diff --git a/README.md b/README.md index b554b0ac6..b6a360ade 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ PCI bus. 86Box is released under the GNU General Public License, version 2. For more information, see the `LICENSE` file. +The project maintainer is OBattler. + Community --------- We operate an IRC channel and a Discord server for discussing anything related diff --git a/src/86box.h b/src/86box.h index 28a46cc0b..eaac682d3 100644 --- a/src/86box.h +++ b/src/86box.h @@ -8,7 +8,7 @@ * * Main include file for the application. * - * Version: @(#)86box.h 1.0.21 2018/03/19 + * Version: @(#)86box.h 1.0.23 2018/05/25 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -90,8 +90,7 @@ extern int vid_cga_contrast, /* (C) video */ video_fullscreen_scale, /* (C) video */ enable_overscan, /* (C) video */ force_43, /* (C) video */ - gfxcard, /* (C) graphics/video card */ - video_speed; /* (C) video */ + gfxcard; /* (C) graphics/video card */ extern int serial_enabled[], /* (C) enable serial ports */ lpt_enabled, /* (C) enable LPT ports */ bugger_enabled; /* (C) enable ISAbugger */ @@ -100,7 +99,7 @@ extern int sound_is_float, /* (C) sound uses FP values */ GUS, /* (C) sound option */ SSI2001, /* (C) sound option */ voodoo_enabled; /* (C) video option */ -extern int mem_size; /* (C) memory size */ +extern uint32_t mem_size; /* (C) memory size */ extern int cpu_manufacturer, /* (C) cpu manufacturer */ cpu, /* (C) cpu type */ cpu_use_dynarec, /* (C) cpu uses/needs Dyna */ @@ -127,6 +126,7 @@ extern wchar_t cfg_path[1024]; /* full path of config file */ extern FILE *stdlog; /* file to log output to */ extern int scrnsz_x, /* current screen size, X */ scrnsz_y; /* current screen size, Y */ +extern int efscrnsz_y; extern int config_changed; /* config has changed */ @@ -139,7 +139,9 @@ extern void pclog(const char *fmt, ...); extern void fatal(const char *fmt, ...); extern void set_screen_size(int x, int y); extern void set_screen_size_natural(void); +#if 0 extern void pc_reload(wchar_t *fn); +#endif extern int pc_init_modules(void); extern int pc_init(int argc, wchar_t *argv[]); extern void pc_close(void *threadid); diff --git a/src/Makefile.local b/src/Makefile.local index 9b9b7f2a7..a93152007 100644 --- a/src/Makefile.local +++ b/src/Makefile.local @@ -10,7 +10,7 @@ # settings, so we can avoid changing the main one for all of # our local setups. # -# Version: @(#)Makefile.local 1.0.10 2018/03/20 +# Version: @(#)Makefile.local 1.0.14 2018/05/26 # # Author: Fred N. van Kempen, # @@ -34,31 +34,103 @@ STUFF := # -DANSI_CFG forces the config file to ANSI encoding. # -DENABLE_VRAM_DUMP enables Video Ram dumping. # -DENABLE_LOG_BREAKPOINT enables extra logging. +# Root logging: +# -DENABLE_BUGGER_LOG=N sets logging level at N. +# -DENABLE_CONFIG_LOG=N sets logging level at N. +# -DENABLE_DEVICE_LOG=N sets logging level at N. # -DENABLE_KEYBOARD_AMSTRAD_LOG=N sets logging level at N. # -DENABLE_KEYBOARD_AT_LOG=N sets logging level at N. # -DENABLE_KEYBOARD_LOG=N sets logging level at N. +# -DENABLE_IO_LOG=N sets logging level at N. +# -DENABLE_MEM_LOG=N sets logging level at N. +# -DENABLE_MOUSE_LOG=N sets logging level at N. +# -DENABLE_MOUSE_BUS_LOG=N sets logging level at N. +# -DENABLE_MOUSE_PS2_LOG=N sets logging level at N. +# -DENABLE_MOUSE_SERIAL_LOG=N sets logging level at N. +# -DENABLE_NVR_LOG=N sets logging level at N. +# -DENABLE_PC_LOG=N sets logging level at N. # -DENABLE_PCI_LOG=N sets logging level at N. +# -DENABLE_PIC_LOG=N sets logging level at N. +# -DENABLE_PIIX_LOG=N sets logging level at N. +# -DENABLE_ROM_LOG=N sets logging level at N. +# -DENABLE_SERIAL_LOG=N sets logging level at N. +# -DENABLE_VNC_LOG=N sets logging level at N. +# cdrom/ logging: # -DENABLE_CDROM_LOG=N sets logging level at N. # -DENABLE_CDROM_IMAGE_LOG=N sets logging level at N. -# -DENABLE_CDROM_IOCTL_LOG=N sets logging level at N. -# -DENABLE_HDD_LOG=N sets logging level at N. +# cpu/ logging: +# -DENABLE_386_LOG=N sets logging level at N. +# -DENABLE_386_DYNAREC_LOG=N sets logging level at N. +# -DENABLE_808X_LOG=N sets logging level at N. +# -DENABLE_X86SEG_LOG=N sets logging level at N. +# disk/ logging: +# -DENABLE_ESDI_AT_LOG=N sets logging level at N. +# -DENABLE_ESDI_MCA_LOG=N sets logging level at N. +# -DENABLE_HDC_LOG=N sets logging level at N. +# -DENABLE_HDD_IMAGE_LOG=N sets logging level at N. # -DENABLE_IDE_LOG=N sets logging level at N. -# -DENABLE_FDC_LOG=N sets logging level at N. +# -DENABLE_MFM_AT_LOG=N sets logging level at N. +# -DENABLE_MFM_XT_LOG=N sets logging level at N. +# -DENABLE_XTA_LOG=N sets logging level at N. +# -DENABLE_ZIP_LOG=N sets logging level at N. +# floppy/ logging: # -DENABLE_D86F_LOG=N sets logging level at N. +# -DENABLE_FDC_LOG=N sets logging level at N. +# -DENABLE_FDD_LOG=N sets logging level at N. +# -DENABLE_FDI_LOG=N sets logging level at N. +# -DENABLE_FDI2RAW_LOG=N sets logging level at N. +# -DENABLE_IMD_LOG=N sets logging level at N. +# -DENABLE_IMG_LOG=N sets logging level at N. +# -DENABLE_JSON_LOG=N sets logging level at N. +# -DENABLE_TD0_LOG=N sets logging level at N. +# machine/ logging: +# -DENABLE_AMSTRAD_LOG=N sets logging level at N. +# -DENABLE_EUROPC_LOG=N sets logging level at N. +# -DENABLE_MACHINE_LOG=N sets logging level at N. +# -DENABLE_PS1_HDC_LOG=N sets logging level at N. +# -DENABLE_PS2_MCA_LOG=N sets logging level at N. +# -DENABLE_T1000_LOG=N sets logging level at N. +# -DENABLE_T3100E_LOG=N sets logging level at N. +# -DENABLE_TANDY_LOG=N sets logging level at N. +# network/ logging: +# -DENABLE_NETWORK_LOG=N sets logging level at N. # -DENABLE_NIC_LOG=N sets logging level at N. -# -DENABLE_SCAT_LOG=N sets logging level at N. -# -DENABLE_SCSI_BUS_LOG=N sets logging level at N. -# -DENABLE_SCSI_DISK_LOG=N sets logging level at N. -# -DENABLE_X54X_LOG=N sets logging level at N. +# -DENABLE_PCAP_LOG=N sets logging level at N. +# -DENABLE_SLIRP_LOG=N sets logging level at N. +# scsi/ logging: # -DENABLE_AHA154X_LOG=N sets logging level at N. # -DENABLE_BUSLOGIC_LOG=N sets logging level at N. # -DENABLE_NCR5380_LOG=N sets logging level at N. # -DENABLE_NCR53C810_LOG=N sets logging level at N. +# -DENABLE_SCSI_LOG=N sets logging level at N. +# -DENABLE_SCSI_BUS_LOG=N sets logging level at N. +# -DENABLE_SCSI_DISK_LOG=N sets logging level at N. +# -DENABLE_X54X_LOG=N sets logging level at N. +# sound/ logging: +# -DENABLE_ADLIB_LOG=N sets logging level at N. # -DENABLE_AUDIOPCI_LOG=N sets logging level at N. # -DENABLE_EMU8K_LOG=N sets logging level at N. +# -DENABLE_MPU401_LOG=N sets logging level at N. +# -DENABLE_PAS16_LOG=N sets logging level at N. +# -DENABLE_SB_LOG=N sets logging level at N. +# -DENABLE_SB_DSP_LOG=N sets logging level at N. +# -DENABLE_SOUND_LOG=N sets logging level at N. +# video/ logging: +# -DENABLE_ATI28800_LOG=N sets logging level at N. +# -DENABLE_MACH64_LOG=N sets logging level at N. +# -DENABLE_ET4000W32_LOG=N sets logging level at N. +# -DENABLE_NV_RIVA_LOG=N sets logging level at N. +# -DENABLE_NVIDIA_LOG=N sets logging level at N. +# -DENABLE_S3_VIRGE_LOG=N sets logging level at N. +# -DENABLE_VID_TABLE_LOG=N sets logging level at N. # -DENABLE_VOODOO_LOG=N sets logging level at N. # -DENABLE_VRAM_DUMP=N sets logging level at N. -# -DENABLE_SERIAL_LOG=N sets logging level at N. +# win/ logging: +# -DENABLE_DDRAW_LOG=N sets logging level at N. +# -DENABLE_DYNLD_LOG=N sets logging level at N. +# -DENABLE_JOYSTICK_LOG=N sets logging level at N. +# -DENABLE_SDL_LOG=N sets logging level at N. +# -DENABLE_WIN_LOG=N sets logging level at N. EXTRAS := diff --git a/src/bugger.c b/src/bugger.c index f70a25c6e..0619a0bb0 100644 --- a/src/bugger.c +++ b/src/bugger.c @@ -44,15 +44,17 @@ * configuration register (CTRL_SPCFG bit set) but have to * remember that stuff first... * - * Version: @(#)bugger.c 1.0.10 2018/03/18 + * Version: @(#)bugger.c 1.0.12 2018/04/29 * * Author: Fred N. van Kempen, * Copyright 1989-2018 Fred N. van Kempen. */ +#include #include #include #include #include +#define HAVE_STDARG_H #include "86box.h" #include "io.h" #include "device.h" @@ -89,6 +91,26 @@ static char bug_str[UISTR_LEN]; /* UI output string */ extern void ui_sb_bugui(char *__str); +#ifdef ENABLE_BUGGER_LOG +int bugger_do_log = ENABLE_BUGGER_LOG; +#endif + + +static void +bugger_log(const char *format, ...) +{ +#ifdef ENABLE_BUGGER_LOG + va_list ap; + + if (bugger_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + /* Update the system's UI with the actual Bugger status. */ static void bug_setui(void) @@ -115,7 +137,7 @@ static void bug_spflsh(void) { *bug_bptr = '\0'; - pclog("BUGGER- serial port [%s]\n", bug_buff); + bugger_log("BUGGER- serial port [%s]\n", bug_buff); bug_bptr = bug_buff; } @@ -141,7 +163,7 @@ bug_wsport(uint8_t val) /* Restore the SPORT bit. */ bug_ctrl |= (old & CTRL_SPORT); - pclog("BUGGER- sport %02x\n", val); + bugger_log("BUGGER- sport %02x\n", val); } @@ -151,7 +173,7 @@ bug_wspcfg(uint8_t val) { bug_spcfg = val; - pclog("BUGGER- spcfg %02x\n", bug_spcfg); + bugger_log("BUGGER- spcfg %02x\n", bug_spcfg); } @@ -201,7 +223,7 @@ bug_wctrl(uint8_t val) } /* Update the UI with active settings. */ - pclog("BUGGER- ctrl %02x\n", bug_ctrl); + bugger_log("BUGGER- ctrl %02x\n", bug_ctrl); bug_setui(); } @@ -226,7 +248,7 @@ bug_wdata(uint8_t val) else bug_ledr = val; - pclog("BUGGER- data %02x\n", bug_data); + bugger_log("BUGGER- data %02x\n", bug_data); } /* Update the UI with active settings. */ @@ -311,7 +333,7 @@ bug_read(uint16_t port, void *priv) static void * bug_init(const device_t *info) { - pclog("%s, I/O=%04x\n", info->name, BUGGER_ADDR); + bugger_log("%s, I/O=%04x\n", info->name, BUGGER_ADDR); /* Initialize local registers. */ bug_reset(); @@ -338,6 +360,6 @@ const device_t bugger_device = { DEVICE_ISA | DEVICE_AT, 0, bug_init, bug_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index e88a9606e..4ab96d37a 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -9,18 +9,18 @@ * Implementation of the CD-ROM drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)cdrom.c 1.0.45 2018/03/21 + * Version: @(#)cdrom.c 1.0.48 2018/05/28 * * Author: Miran Grca, * * Copyright 2016-2018 Miran Grca. */ #include -#include +#include #include +#include #include #include -#include #include #define HAVE_STDARG_H #include "../86box.h" @@ -33,6 +33,7 @@ #include "../disk/hdc.h" #include "../disk/hdc_ide.h" #include "../plat.h" +#include "../sound/sound.h" #include "../ui.h" #include "cdrom.h" #include "cdrom_image.h" @@ -42,8 +43,8 @@ /* Bits of 'status' */ #define ERR_STAT 0x01 #define DRQ_STAT 0x08 /* Data request */ -#define DSC_STAT 0x10 -#define SERVICE_STAT 0x10 +#define DSC_STAT 0x10 +#define SERVICE_STAT 0x10 #define READY_STAT 0x40 #define BUSY_STAT 0x80 @@ -51,27 +52,18 @@ #define ABRT_ERR 0x04 /* Command aborted */ #define MCR_ERR 0x08 /* Media change request */ +#define MIN_SEEK 2000 +#define MAX_SEEK 333333 + +#define cdbufferb dev->buffer + + cdrom_t *cdrom[CDROM_NUM]; cdrom_image_t cdrom_image[CDROM_NUM]; -cdrom_ioctl_t cdrom_ioctl[CDROM_NUM]; cdrom_drive_t cdrom_drives[CDROM_NUM]; uint8_t atapi_cdrom_drives[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -uint8_t scsi_cdrom_drives[16][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } }; +uint8_t scsi_cdrom_drives[16] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; #pragma pack(push,1) @@ -100,237 +92,249 @@ static struct /* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ const uint8_t cdrom_command_flags[0x100] = { - IMPLEMENTED | CHECK_READY | NONDATA, - IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, - 0, - IMPLEMENTED | ALLOW_UA, - 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, - 0, 0, - IMPLEMENTED | CHECK_READY | NONDATA, - 0, 0, 0, 0, 0, 0, - IMPLEMENTED | ALLOW_UA, - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, - 0, - IMPLEMENTED, - 0, 0, 0, 0, - IMPLEMENTED, - IMPLEMENTED | CHECK_READY, - 0, 0, - IMPLEMENTED | CHECK_READY, - 0, 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, - 0, 0, - IMPLEMENTED | CHECK_READY, - 0, 0, - IMPLEMENTED | CHECK_READY | NONDATA, - 0, 0, 0, - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - IMPLEMENTED | CHECK_READY, - IMPLEMENTED | CHECK_READY, /* Read TOC - can get through UNIT_ATTENTION, per VIDE-CDD.SYS - NOTE: The ATAPI reference says otherwise, but I think this is a question of - interpreting things right - the UNIT ATTENTION condition we have here - is a tradition from not ready to ready, by definition the drive - eventually becomes ready, make the condition go away. */ - IMPLEMENTED | CHECK_READY, - IMPLEMENTED | CHECK_READY, - IMPLEMENTED | ALLOW_UA, - IMPLEMENTED | CHECK_READY, - IMPLEMENTED | CHECK_READY, - 0, - IMPLEMENTED | ALLOW_UA, - IMPLEMENTED | CHECK_READY, - 0, 0, - IMPLEMENTED | CHECK_READY, - 0, 0, - IMPLEMENTED | CHECK_READY, - IMPLEMENTED | CHECK_READY, - 0, 0, - IMPLEMENTED, - 0, 0, 0, 0, - IMPLEMENTED, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, - 0, 0, - IMPLEMENTED | CHECK_READY, - 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, - 0, - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, - 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY | ATAPI_ONLY, - 0, 0, 0, - IMPLEMENTED | CHECK_READY | ATAPI_ONLY, - IMPLEMENTED | CHECK_READY, - IMPLEMENTED | CHECK_READY, - IMPLEMENTED, - IMPLEMENTED | CHECK_READY, - IMPLEMENTED, - IMPLEMENTED | CHECK_READY, - IMPLEMENTED | CHECK_READY, - 0, 0, - IMPLEMENTED | CHECK_READY | SCSI_ONLY, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY | SCSI_ONLY, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED | SCSI_ONLY, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ + IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ + 0, /* 0x02 */ + IMPLEMENTED | ALLOW_UA, /* 0x03 */ + 0, 0, 0, 0, /* 0x04-0x07 */ + IMPLEMENTED | CHECK_READY, /* 0x08 */ + 0, 0, /* 0x09-0x0A */ + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ + 0, 0, 0, 0, 0, 0, /* 0x0C-0x11 */ + IMPLEMENTED | ALLOW_UA, /* 0x12 */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ + 0, /* 0x14 */ + IMPLEMENTED, /* 0x15 */ + 0, 0, 0, 0, /* 0x16-0x19 */ + IMPLEMENTED, /* 0x1A */ + IMPLEMENTED | CHECK_READY, /* 0x1B */ + 0, 0, /* 0x1C-0x1D */ + IMPLEMENTED | CHECK_READY, /* 0x1E */ + 0, 0, 0, 0, 0, 0, /* 0x1F-0x24 */ + IMPLEMENTED | CHECK_READY, /* 0x25 */ + 0, 0, /* 0x26-0x27 */ + IMPLEMENTED | CHECK_READY, /* 0x28 */ + 0, 0, /* 0x29-0x2A */ + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ + 0, 0, 0, /* 0x2C-0x2E */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F */ + 0, 0, /* 0x40-0x41 */ + IMPLEMENTED | CHECK_READY, /* 0x42 */ + IMPLEMENTED | CHECK_READY, /* 0x43 - Read TOC - can get through UNIT_ATTENTION, per VIDE-CDD.SYS + NOTE: The ATAPI reference says otherwise, but I think this is a question of + interpreting things right - the UNIT ATTENTION condition we have here + is a tradition from not ready to ready, by definition the drive + eventually becomes ready, make the condition go away. */ + IMPLEMENTED | CHECK_READY, /* 0x44 */ + IMPLEMENTED | CHECK_READY, /* 0x45 */ + IMPLEMENTED | ALLOW_UA, /* 0x46 */ + IMPLEMENTED | CHECK_READY, /* 0x47 */ + IMPLEMENTED | CHECK_READY, /* 0x48 */ + 0, /* 0x49 */ + IMPLEMENTED | ALLOW_UA, /* 0x4A */ + IMPLEMENTED | CHECK_READY, /* 0x4B */ + 0, 0, /* 0x4C-0x4D */ + IMPLEMENTED | CHECK_READY, /* 0x4E */ + 0, 0, /* 0x4F-0x50 */ + IMPLEMENTED | CHECK_READY, /* 0x51 */ + IMPLEMENTED | CHECK_READY, /* 0x52 */ + 0, 0, /* 0x53-0x54 */ + IMPLEMENTED, /* 0x55 */ + 0, 0, 0, 0, /* 0x56-0x59 */ + IMPLEMENTED, /* 0x5A */ + 0, 0, 0, 0, 0, /* 0x5B-0x5F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x6F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x7F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */ + 0, 0, 0, 0, 0, /* 0xA0-0xA4 */ + IMPLEMENTED | CHECK_READY, /* 0xA5 */ + 0, 0, /* 0xA6-0xA7 */ + IMPLEMENTED | CHECK_READY, /* 0xA8 */ + 0, 0, 0, 0, /* 0xA9-0xAC */ + IMPLEMENTED | CHECK_READY, /* 0xAD */ + 0, /* 0xAE */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0xAF */ + 0, 0, 0, 0, /* 0xB0-0xB3 */ + IMPLEMENTED | CHECK_READY | ATAPI_ONLY, /* 0xB4 */ + 0, 0, 0, /* 0xB5-0xB7 */ + IMPLEMENTED | CHECK_READY | ATAPI_ONLY, /* 0xB8 */ + IMPLEMENTED | CHECK_READY, /* 0xB9 */ + IMPLEMENTED | CHECK_READY, /* 0xBA */ + IMPLEMENTED, /* 0xBB */ + IMPLEMENTED | CHECK_READY, /* 0xBC */ + IMPLEMENTED, /* 0xBD */ + IMPLEMENTED | CHECK_READY, /* 0xBE */ + IMPLEMENTED | CHECK_READY, /* 0xBF */ + 0, 0, /* 0xC0-0xC1 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC2 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC3-0xCC */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xCD */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xCE-0xD9 */ + IMPLEMENTED | SCSI_ONLY, /* 0xDA */ + 0, 0, 0, 0, 0, /* 0xDB-0xDF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xF0-0xFF */ }; -uint64_t cdrom_mode_sense_page_flags = (1LL << GPMODE_R_W_ERROR_PAGE) | (1LL << GPMODE_CDROM_PAGE) | (1LL << GPMODE_CDROM_AUDIO_PAGE) | (1LL << GPMODE_CAPABILITIES_PAGE) | (1LL << GPMODE_ALL_PAGES); +static uint64_t cdrom_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | + GPMODEP_CDROM_PAGE | + GPMODEP_CDROM_AUDIO_PAGE | + GPMODEP_CAPABILITIES_PAGE | + GPMODEP_ALL_PAGES); static const mode_sense_pages_t cdrom_mode_sense_pages_default = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, - { 0x8E, 0xE, 4, 0, 0, 0, 0, 75, 1, 0xFF, 2, 0xFF, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 0x02, 0xC2, 1, 0, 0, 0, 0x02, 0xC2, 0, 0, 0, 0 } -} }; +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + { 0x8E, 0xE, 4, 0, 0, 0, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 } +} }; static const mode_sense_pages_t cdrom_mode_sense_pages_default_scsi = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, - { 0x8E, 0xE, 5, 4, 0,0x80,0, 75, 1, 0xFF, 2, 0xFF, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 0x02, 0xC2, 1, 0, 0, 0, 0x02, 0xC2, 0, 0, 0, 0 } -} }; +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + { 0x8E, 0xE, 5, 4, 0,128, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 } +} }; static const mode_sense_pages_t cdrom_mode_sense_pages_changeable = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, - { 0x8E, 0xE, 5, 4, 0,0x80,0, 75, 1, 0xFF, 2, 0xFF, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 0x02, 0xC2, 1, 0, 0, 0, 0x02, 0xC2, 0, 0, 0, 0 } -} }; +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + { 0x8E, 0xE, 5, 4, 0,128, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 } +} }; -static mode_sense_pages_t cdrom_mode_sense_pages_saved[CDROM_NUM]; +uint8_t cdrom_read_capacity_cdb[12] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + +static void cdrom_command_complete(cdrom_t *dev); + +static void cdrom_mode_sense_load(cdrom_t *dev); + +static void cdrom_init(cdrom_t *dev); +void cdrom_phase_callback(cdrom_t *dev); #ifdef ENABLE_CDROM_LOG @@ -342,2997 +346,2840 @@ static void cdrom_log(const char *format, ...) { #ifdef ENABLE_CDROM_LOG - va_list ap; + va_list ap; - if (cdrom_do_log) - { - va_start(ap, format); - pclog_ex(format, ap); - va_end(ap); - } + if (cdrom_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } #endif } -int find_cdrom_for_channel(uint8_t channel) +int +find_cdrom_for_channel(uint8_t channel) { - uint8_t i = 0; + uint8_t i = 0; - for (i = 0; i < CDROM_NUM; i++) { - if (((cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) || (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA)) && (cdrom_drives[i].ide_channel == channel)) - return i; - } - return 0xff; + for (i = 0; i < CDROM_NUM; i++) { + if ((cdrom_drives[i].bus_type == CDROM_BUS_ATAPI) && (cdrom_drives[i].ide_channel == channel)) + return i; + } + return 0xff; } -void cdrom_init(int id, int cdb_len_setting); -void build_atapi_cdrom_map() +void +build_atapi_cdrom_map() { - uint8_t i = 0; + uint8_t i = 0; - memset(atapi_cdrom_drives, 0xff, 8); + memset(atapi_cdrom_drives, 0xff, 8); - for (i = 0; i < 8; i++) { - atapi_cdrom_drives[i] = find_cdrom_for_channel(i); - if (atapi_cdrom_drives[i] != 0xff) - cdrom_init(atapi_cdrom_drives[i], 12); - } + for (i = 0; i < 8; i++) + atapi_cdrom_drives[i] = find_cdrom_for_channel(i); } -int find_cdrom_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun) -{ - uint8_t i = 0; - for (i = 0; i < CDROM_NUM; i++) { - if ((cdrom_drives[i].bus_type == CDROM_BUS_SCSI) && (cdrom_drives[i].scsi_device_id == scsi_id) && (cdrom_drives[i].scsi_device_lun == scsi_lun)) - return i; - } - return 0xff; +int +find_cdrom_for_scsi_id(uint8_t scsi_id) +{ + uint8_t i = 0; + + for (i = 0; i < CDROM_NUM; i++) { + if ((cdrom_drives[i].bus_type == CDROM_BUS_SCSI) && (cdrom_drives[i].scsi_device_id == scsi_id)) + return i; + } + return 0xff; } -void build_scsi_cdrom_map() + +void +build_scsi_cdrom_map() { - uint8_t i = 0; - uint8_t j = 0; + uint8_t i = 0; - for (i = 0; i < 16; i++) - memset(scsi_cdrom_drives[i], 0xff, 8); + memset(scsi_cdrom_drives, 0xff, 16); - for (i = 0; i < 16; i++) { - for (j = 0; j < 8; j++) { - scsi_cdrom_drives[i][j] = find_cdrom_for_scsi_id(i, j); - if (scsi_cdrom_drives[i][j] != 0xff) - cdrom_init(scsi_cdrom_drives[i][j], 12); - } - } + for (i = 0; i < 16; i++) + scsi_cdrom_drives[i] = find_cdrom_for_scsi_id(i); } -void cdrom_set_callback(uint8_t id) + +static void +cdrom_set_callback(cdrom_t *dev) { - if (cdrom_drives[id].bus_type != CDROM_BUS_SCSI) - ide_set_callback(cdrom_drives[id].ide_channel, cdrom[id]->callback); + if (dev && dev->drv && (dev->drv->bus_type != CDROM_BUS_SCSI)) + ide_set_callback(dev->drv->ide_channel >> 1, dev->callback); } -void cdrom_set_cdb_len(int id, int cdb_len) + +void +cdrom_set_signature(cdrom_t *dev) { - cdrom[id]->cdb_len = cdb_len; + if (!dev) + return; + dev->phase = 1; + dev->request_length = 0xEB14; } -void cdrom_reset_cdb_len(int id) + +static void +cdrom_init(cdrom_t *dev) { - cdrom[id]->cdb_len = cdrom[id]->cdb_len_setting ? 16 : 12; + if (!dev) + return; + + /* Tell the cdrom_t struct what cdrom_drives element corresponds to it. */ + dev->drv = &(cdrom_drives[dev->id]); + + /* Do a reset (which will also rezero it). */ + cdrom_reset(dev); + + /* Configure the drive. */ + dev->requested_blocks = 1; + + dev->drv->bus_mode = 0; + if (dev->drv->bus_type >= CDROM_BUS_ATAPI) + dev->drv->bus_mode |= 2; + if (dev->drv->bus_type < CDROM_BUS_SCSI) + dev->drv->bus_mode |= 1; + cdrom_log("CD-ROM %i: Bus type %i, bus mode %i\n", dev->id, dev->drv->bus_type, dev->drv->bus_mode); + dev->cdb_len = 12; + + dev->sense[0] = 0xf0; + dev->sense[7] = 10; + dev->status = READY_STAT | DSC_STAT; + dev->pos = 0; + dev->packet_status = 0xff; + cdrom_sense_key = cdrom_asc = cdrom_ascq = dev->unit_attention = 0; + dev->cur_speed = dev->drv->speed; + cdrom_mode_sense_load(dev); } -void cdrom_set_signature(int id) -{ - cdrom_t *dev = cdrom[id]; - if (id >= CDROM_NUM) - return; - dev->phase = 1; - dev->request_length = 0xEB14; +static int +cdrom_supports_pio(cdrom_t *dev) +{ + return (dev->drv->bus_mode & 1); } -void cdrom_destroy_drives(void) -{ - int i; - for (i = 0; i < CDROM_NUM; i++) { - if (cdrom[i]) { - free(cdrom[i]); - cdrom[i] = NULL; - } - } +static int +cdrom_supports_dma(cdrom_t *dev) +{ + return (dev->drv->bus_mode & 2); } -void cdrom_init(int id, int cdb_len_setting) -{ - cdrom_t *dev; - - uint8_t *trcbuf; - uint32_t tcap; - - if (id >= CDROM_NUM) - return; - dev = cdrom[id]; - tcap = dev->cdrom_capacity; - trcbuf = (uint8_t *) malloc(16); - memcpy(trcbuf, dev->rcbuf, 16); - memset(dev, 0, sizeof(cdrom_t)); - memcpy(dev->rcbuf, trcbuf, 16); - free(trcbuf); - dev->cdrom_capacity = tcap; - dev->requested_blocks = 1; - if (cdb_len_setting <= 1) - dev->cdb_len_setting = cdb_len_setting; - cdrom_reset_cdb_len(id); - dev->cd_status = CD_STATUS_EMPTY; - dev->sense[0] = 0xf0; - dev->sense[7] = 10; - cdrom_drives[id].bus_mode = 0; - if (cdrom_drives[id].bus_type >= CDROM_BUS_ATAPI_PIO_AND_DMA) - cdrom_drives[id].bus_mode |= 2; - if (cdrom_drives[id].bus_type < CDROM_BUS_SCSI) - cdrom_drives[id].bus_mode |= 1; - cdrom_log("CD-ROM %i: Bus type %i, bus mode %i\n", id, cdrom_drives[id].bus_type, cdrom_drives[id].bus_mode); - if (cdrom_drives[id].bus_type < CDROM_BUS_SCSI) - cdrom_set_signature(id); - dev->status = READY_STAT | DSC_STAT; - dev->pos = 0; - dev->packet_status = 0xff; - cdrom_sense_key = cdrom_asc = cdrom_ascq = dev->unit_attention = 0; - dev->cdb_len_setting = 0; - dev->cdb_len = 12; - dev->cur_speed = cdrom_drives[id].speed; -} - -int cdrom_supports_pio(int id) -{ - return (cdrom_drives[id].bus_mode & 1); -} - -int cdrom_supports_dma(int id) -{ - return (cdrom_drives[id].bus_mode & 2); -} /* Returns: 0 for none, 1 for PIO, 2 for DMA. */ -int cdrom_current_mode(int id) +static int +cdrom_current_mode(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - - if (!cdrom_supports_pio(id) && !cdrom_supports_dma(id)) - return 0; - if (cdrom_supports_pio(id) && !cdrom_supports_dma(id)) { - cdrom_log("CD-ROM %i: Drive does not support DMA, setting to PIO\n", id); - return 1; - } - if (!cdrom_supports_pio(id) && cdrom_supports_dma(id)) - return 2; - if (cdrom_supports_pio(id) && cdrom_supports_dma(id)) { - cdrom_log("CD-ROM %i: Drive supports both, setting to %s\n", id, (dev->features & 1) ? "DMA" : "PIO", id); - return (dev->features & 1) ? 2 : 1; - } - + if (!cdrom_supports_pio(dev) && !cdrom_supports_dma(dev)) return 0; + if (cdrom_supports_pio(dev) && !cdrom_supports_dma(dev)) { + cdrom_log("CD-ROM %i: Drive does not support DMA, setting to PIO\n", dev->id); + return 1; + } + if (!cdrom_supports_pio(dev) && cdrom_supports_dma(dev)) + return 2; + if (cdrom_supports_pio(dev) && cdrom_supports_dma(dev)) { + cdrom_log("CD-ROM %i: Drive supports both, setting to %s\n", dev->id, + (dev->features & 1) ? "DMA" : "PIO", + dev->id); + return (dev->features & 1) ? 2 : 1; + } + + return 0; } + /* Translates ATAPI status (ERR_STAT flag) to SCSI status. */ -int cdrom_CDROM_PHASE_to_scsi(uint8_t id) +int +cdrom_CDROM_PHASE_to_scsi(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - - if (dev->status & ERR_STAT) - return SCSI_STATUS_CHECK_CONDITION; - else - return SCSI_STATUS_OK; + if (dev->status & ERR_STAT) + return SCSI_STATUS_CHECK_CONDITION; + else + return SCSI_STATUS_OK; } + /* Translates ATAPI phase (DRQ, I/O, C/D) to SCSI phase (MSG, C/D, I/O). */ -int cdrom_atapi_phase_to_scsi(uint8_t id) +int +cdrom_atapi_phase_to_scsi(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - - if (dev->status & 8) { - switch (dev->phase & 3) { - case 0: - return 0; - case 1: - return 2; - case 2: - return 1; - case 3: - return 7; - } - } else { - if ((dev->phase & 3) == 3) - return 3; - else - return 4; - } - - return 0; -} - -int cdrom_lba_to_msf_accurate(int lba) -{ - int temp_pos; - int m, s, f; - - temp_pos = lba + 150; - f = temp_pos % 75; - temp_pos -= f; - temp_pos /= 75; - s = temp_pos % 60; - temp_pos -= s; - temp_pos /= 60; - m = temp_pos; - - return ((m << 16) | (s << 8) | f); -} - -uint32_t cdrom_mode_sense_get_channel(uint8_t id, int channel) -{ - return cdrom_mode_sense_pages_saved[id].pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 10 : 8]; -} - -uint32_t cdrom_mode_sense_get_volume(uint8_t id, int channel) -{ - return cdrom_mode_sense_pages_saved[id].pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 11 : 9]; -} - -void cdrom_mode_sense_load(uint8_t id) -{ - FILE *f; - wchar_t file_name[512]; - int i; - memset(&cdrom_mode_sense_pages_saved[id], 0, sizeof(mode_sense_pages_t)); - for (i = 0; i < 0x3f; i++) { - if (cdrom_mode_sense_pages_default.pages[i][1] != 0) { - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - memcpy(cdrom_mode_sense_pages_saved[id].pages[i], cdrom_mode_sense_pages_default_scsi.pages[i], cdrom_mode_sense_pages_default_scsi.pages[i][1] + 2); - else - memcpy(cdrom_mode_sense_pages_saved[id].pages[i], cdrom_mode_sense_pages_default.pages[i], cdrom_mode_sense_pages_default.pages[i][1] + 2); - } - } - memset(file_name, 0, 512 * sizeof(wchar_t)); - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - swprintf(file_name, 512, L"scsi_cdrom_%02i_mode_sense_bin", id); - else - swprintf(file_name, 512, L"cdrom_%02i_mode_sense_bin", id); - f = plat_fopen(nvr_path(file_name), L"rb"); - if (f) { - fread(cdrom_mode_sense_pages_saved[id].pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f); - fclose(f); - } -} - -void cdrom_mode_sense_save(uint8_t id) -{ - FILE *f; - wchar_t file_name[512]; - memset(file_name, 0, 512 * sizeof(wchar_t)); - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - swprintf(file_name, 512, L"scsi_cdrom_%02i_mode_sense_bin", id); - else - swprintf(file_name, 512, L"cdrom_%02i_mode_sense_bin", id); - f = plat_fopen(nvr_path(file_name), L"wb"); - if (f) { - fwrite(cdrom_mode_sense_pages_saved[id].pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f); - fclose(f); - } -} - -static void cdrom_command_complete(uint8_t id); - -uint8_t cdrom_read_capacity_cdb[12] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -static int cdrom_pass_through(uint8_t id, uint32_t *len, uint8_t *cdb, uint8_t *buffer); - -int cdrom_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len) -{ - int ret = 0; - int size = 0; - - if (cdrom_drives[id].handler->pass_through) { - ret = cdrom_pass_through(id, len, cdb, buffer); - if (!ret) + if (dev->status & 8) { + switch (dev->phase & 3) { + case 0: return 0; - if (*len == 65534) - *len = 8; - } else { - size = cdrom_drives[id].handler->size(id) - 1; /* IMPORTANT: What's returned is the last LBA block. */ - memset(buffer, 0, 8); - buffer[0] = (size >> 24) & 0xff; - buffer[1] = (size >> 16) & 0xff; - buffer[2] = (size >> 8) & 0xff; - buffer[3] = size & 0xff; - buffer[6] = 8; /* 2048 = 0x0800 */ - *len = 8; + case 1: + return 2; + case 2: + return 1; + case 3: + return 7; } - return 1; + } else { + if ((dev->phase & 3) == 3) + return 3; + else + return 4; + } + + return 0; } + +int +cdrom_lba_to_msf_accurate(int lba) +{ + int temp_pos; + int m, s, f; + + temp_pos = lba + 150; + f = temp_pos % 75; + temp_pos -= f; + temp_pos /= 75; + s = temp_pos % 60; + temp_pos -= s; + temp_pos /= 60; + m = temp_pos; + + return ((m << 16) | (s << 8) | f); +} + + +uint32_t +cdrom_mode_sense_get_channel(cdrom_t *dev, int channel) +{ + return dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 10 : 8]; +} + + +uint32_t +cdrom_mode_sense_get_volume(cdrom_t *dev, int channel) +{ + return dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 11 : 9]; +} + + +static void +cdrom_mode_sense_load(cdrom_t *dev) +{ + FILE *f; + wchar_t file_name[512]; + int i; + + memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); + for (i = 0; i < 0x3f; i++) { + if (cdrom_mode_sense_pages_default.pages[i][1] != 0) { + if (dev->drv->bus_type == CDROM_BUS_SCSI) + memcpy(dev->ms_pages_saved.pages[i], + cdrom_mode_sense_pages_default_scsi.pages[i], + cdrom_mode_sense_pages_default_scsi.pages[i][1] + 2); + else + memcpy(dev->ms_pages_saved.pages[i], + cdrom_mode_sense_pages_default.pages[i], + cdrom_mode_sense_pages_default.pages[i][1] + 2); + } + } + memset(file_name, 0, 512 * sizeof(wchar_t)); + if (dev->drv->bus_type == CDROM_BUS_SCSI) + swprintf(file_name, 512, L"scsi_cdrom_%02i_mode_sense_bin", dev->id); + else + swprintf(file_name, 512, L"cdrom_%02i_mode_sense_bin", dev->id); + f = plat_fopen(nvr_path(file_name), L"rb"); + if (f) { + fread(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f); + fclose(f); + } +} + + +static void +cdrom_mode_sense_save(cdrom_t *dev) +{ + FILE *f; + wchar_t file_name[512]; + + memset(file_name, 0, 512 * sizeof(wchar_t)); + if (dev->drv->bus_type == CDROM_BUS_SCSI) + swprintf(file_name, 512, L"scsi_cdrom_%02i_mode_sense_bin", dev->id); + else + swprintf(file_name, 512, L"cdrom_%02i_mode_sense_bin", dev->id); + f = plat_fopen(nvr_path(file_name), L"wb"); + if (f) { + fwrite(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f); + fclose(f); + } +} + + +int +cdrom_read_capacity(cdrom_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len) +{ + int size = 0; + + size = dev->handler->size(dev->id) - 1; /* IMPORTANT: What's returned is the last LBA block. */ + memset(buffer, 0, 8); + buffer[0] = (size >> 24) & 0xff; + buffer[1] = (size >> 16) & 0xff; + buffer[2] = (size >> 8) & 0xff; + buffer[3] = size & 0xff; + buffer[6] = 8; /* 2048 = 0x0800 */ + *len = 8; + + return 1; +} + + /*SCSI Mode Sense 6/10*/ -uint8_t cdrom_mode_sense_read(uint8_t id, uint8_t page_control, uint8_t page, uint8_t pos) +static uint8_t +cdrom_mode_sense_read(cdrom_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) { - switch (page_control) { - case 0: - case 3: - return cdrom_mode_sense_pages_saved[id].pages[page][pos]; - break; - case 1: - return cdrom_mode_sense_pages_changeable.pages[page][pos]; - break; - case 2: - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - return cdrom_mode_sense_pages_default_scsi.pages[page][pos]; - else - return cdrom_mode_sense_pages_default.pages[page][pos]; - break; - } + switch (page_control) { + case 0: + case 3: + return dev->ms_pages_saved.pages[page][pos]; + break; + case 1: + return cdrom_mode_sense_pages_changeable.pages[page][pos]; + break; + case 2: + if (dev->drv->bus_type == CDROM_BUS_SCSI) + return cdrom_mode_sense_pages_default_scsi.pages[page][pos]; + else + return cdrom_mode_sense_pages_default.pages[page][pos]; + break; + } - return 0; + return 0; } -uint32_t cdrom_mode_sense(uint8_t id, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len) + +static uint32_t +cdrom_mode_sense(cdrom_t *dev, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len) { - cdrom_t *dev = cdrom[id]; + uint8_t page_control = (type >> 6) & 3; + int i = 0, j = 0; - uint8_t page_control = (type >> 6) & 3; + uint8_t msplen; - int i = 0; - int j = 0; + type &= 0x3f; - uint8_t msplen; + if (block_descriptor_len) { + buf[pos++] = 1; /* Density code. */ + buf[pos++] = 0; /* Number of blocks (0 = all). */ + buf[pos++] = 0; + buf[pos++] = 0; + buf[pos++] = 0; /* Reserved. */ + buf[pos++] = 0; /* Block length (0x800 = 2048 bytes). */ + buf[pos++] = 8; + buf[pos++] = 0; + } - type &= 0x3f; - - if (block_descriptor_len) { - buf[pos++] = 1; /* Density code. */ - buf[pos++] = 0; /* Number of blocks (0 = all). */ - buf[pos++] = 0; - buf[pos++] = 0; - buf[pos++] = 0; /* Reserved. */ - buf[pos++] = 0; /* Block length (0x800 = 2048 bytes). */ - buf[pos++] = 8; - buf[pos++] = 0; - } - - for (i = 0; i < 0x40; i++) { - if ((type == GPMODE_ALL_PAGES) || (type == i)) { - if (cdrom_mode_sense_page_flags & (1LL << dev->current_page_code)) { - buf[pos++] = cdrom_mode_sense_read(id, page_control, i, 0); - msplen = cdrom_mode_sense_read(id, page_control, i, 1); - buf[pos++] = msplen; - cdrom_log("CD-ROM %i: MODE SENSE: Page [%02X] length %i\n", id, i, msplen); - for (j = 0; j < msplen; j++) { - if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 6) && (j <= 7)) { - if (j & 1) - buf[pos++] = ((cdrom_drives[id].speed * 176) & 0xff); - else - buf[pos++] = ((cdrom_drives[id].speed * 176) >> 8); - } else if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 12) && (j <= 13)) { - if (j & 1) - buf[pos++] = ((dev->cur_speed * 176) & 0xff); - else - buf[pos++] = ((dev->cur_speed * 176) >> 8); - } else - buf[pos++] = cdrom_mode_sense_read(id, page_control, i, 2 + j); - } + for (i = 0; i < 0x40; i++) { + if ((type == GPMODE_ALL_PAGES) || (type == i)) { + if (cdrom_mode_sense_page_flags & (1LL << dev->current_page_code)) { + buf[pos++] = cdrom_mode_sense_read(dev, page_control, i, 0); + msplen = cdrom_mode_sense_read(dev, page_control, i, 1); + buf[pos++] = msplen; + cdrom_log("CD-ROM %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); + for (j = 0; j < msplen; j++) { + if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 6) && (j <= 7)) { + if (j & 1) + buf[pos++] = ((dev->drv->speed * 176) & 0xff); + else + buf[pos++] = ((dev->drv->speed * 176) >> 8); + } else if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 12) && (j <= 13)) { + if (j & 1) + buf[pos++] = ((dev->cur_speed * 176) & 0xff); + else + buf[pos++] = ((dev->cur_speed * 176) >> 8); + } else + buf[pos++] = cdrom_mode_sense_read(dev, page_control, i, 2 + j); } } } + } - return pos; + return pos; } -void cdrom_update_request_length(uint8_t id, int len, int block_len) + +static void +cdrom_update_request_length(cdrom_t *dev, int len, int block_len) { - cdrom_t *dev = cdrom[id]; - uint32_t bt; + int32_t bt, min_len = 0; - uint32_t min_len = 0; + dev->max_transfer_len = dev->request_length; - dev->max_transfer_len = dev->request_length; + /* For media access commands, make sure the requested DRQ length matches the block length. */ + switch (dev->current_cdb[0]) { + case 0x08: + case 0x28: + case 0xa8: + case 0xb9: + case 0xbe: + /* Make sure total length is not bigger than sum of the lengths of + all the requested blocks. */ + bt = (dev->requested_blocks * block_len); + if (len > bt) + len = bt; - /* For media access commands, make sure the requested DRQ length matches the block length. */ - switch (dev->current_cdb[0]) { + min_len = block_len; + + if (len <= block_len) { + /* Total length is less or equal to block length. */ + if (dev->max_transfer_len < block_len) { + /* Transfer a minimum of (block size) bytes. */ + dev->max_transfer_len = block_len; + dev->packet_len = block_len; + break; + } + } + default: + dev->packet_len = len; + break; + } + /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ + if ((dev->max_transfer_len & 1) && (dev->max_transfer_len < len)) + dev->max_transfer_len &= 0xfffe; + /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ + if (!dev->max_transfer_len) + dev->max_transfer_len = 65534; + + if ((len <= dev->max_transfer_len) && (len >= min_len)) + dev->request_length = dev->max_transfer_len = len; + else if (len > dev->max_transfer_len) + dev->request_length = dev->max_transfer_len; + + return; +} + + +static double +cdrom_get_short_seek(cdrom_t *dev) +{ + switch(dev->cur_speed) { + case 0: + fatal("CD-ROM %i: 0x speed\n", dev->id); + return 0.0; + case 1: + return 240.0; + case 2: + return 160.0; + case 3: + return 150.0; + case 4: case 5: case 6: case 7: case 8: + case 9: case 10: case 11: + return 112.0; + case 12: case 13: case 14: case 15: + return 75.0; + case 16: case 17: case 18: case 19: + return 58.0; + case 20: case 21: case 22: case 23: + case 40: case 41: case 42: case 43: + case 44: case 45: case 46: case 47: + case 48: + return 50.0; + default: + /* 24-32, 52+ */ + return 45.0; + } +} + + +static double +cdrom_get_long_seek(cdrom_t *dev) +{ + switch(dev->cur_speed) { + case 0: + fatal("CD-ROM %i: 0x speed\n", dev->id); + return 0.0; + case 1: + return 1446.0; + case 2: + return 1000.0; + case 3: + return 900.0; + case 4: case 5: case 6: case 7: case 8: + case 9: case 10: case 11: + return 675.0; + case 12: case 13: case 14: case 15: + return 400.0; + case 16: case 17: case 18: case 19: + return 350.0; + case 20: case 21: case 22: case 23: + case 40: case 41: case 42: case 43: + case 44: case 45: case 46: case 47: + case 48: + return 300.0; + default: + /* 24-32, 52+ */ + return 270.0; + } +} + + +static double +cdrom_seek_time(cdrom_t *dev) +{ + uint32_t diff = dev->seek_diff; + double sd = (double) (MAX_SEEK - MIN_SEEK); + + if (diff < MIN_SEEK) + return 0.0; + if (diff > MAX_SEEK) + diff = MAX_SEEK; + + diff -= MIN_SEEK; + + return cdrom_get_short_seek(dev) + ((cdrom_get_long_seek(dev) * ((double) diff)) / sd); +} + + +static double +cdrom_bus_speed(cdrom_t *dev) +{ + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + dev->callback = -1LL; /* Speed depends on SCSI controller */ + return 0.0; + } else { + if (cdrom_current_mode(dev) == 2) + return 66666666.666666666666666; /* 66 MB/s MDMA-2 speed */ + else + return 8333333.333333333333333; /* 8.3 MB/s PIO-2 speed */ + } +} + + +static void +cdrom_command_bus(cdrom_t *dev) +{ + dev->status = BUSY_STAT; + dev->phase = 1; + dev->pos = 0; + dev->callback = 1LL * CDROM_TIME; + cdrom_set_callback(dev); +} + + +static void +cdrom_command_common(cdrom_t *dev) +{ + double bytes_per_second, period; + double dusec; + + dev->status = BUSY_STAT; + dev->phase = 1; + dev->pos = 0; + dev->callback = 0LL; + + cdrom_log("CD-ROM %i: Current speed: %ix\n", dev->id, dev->cur_speed); + + if (dev->packet_status == CDROM_PHASE_COMPLETE) { + cdrom_phase_callback(dev); + dev->callback = 0LL; + } else { + switch(dev->current_cdb[0]) { + case GPCMD_REZERO_UNIT: + case 0x0b: + case 0x2b: + /* Seek time is in us. */ + period = cdrom_seek_time(dev); + cdrom_log("CD-ROM %i: Seek period: %" PRIu64 " us\n", + dev->id, (int64_t) period); + period = period * ((double) TIMER_USEC); + dev->callback += ((int64_t) period); + cdrom_set_callback(dev); + return; case 0x08: case 0x28: case 0xa8: + /* Seek time is in us. */ + period = cdrom_seek_time(dev); + cdrom_log("CD-ROM %i: Seek period: %" PRIu64 " us\n", + dev->id, (int64_t) period); + period = period * ((double) TIMER_USEC); + dev->callback += ((int64_t) period); + case 0x25: + case 0x42: + case 0x43: + case 0x44: + case 0x51: + case 0x52: + case 0xad: + case 0xb8: case 0xb9: case 0xbe: - /* Make sure total length is not bigger than sum of the lengths of - all the requested blocks. */ - bt = (dev->requested_blocks * block_len); - if (len > bt) - len = bt; - - min_len = block_len; - - if (len <= block_len) { - /* Total length is less or equal to block length. */ - if (dev->max_transfer_len < block_len) { - /* Transfer a minimum of (block size) bytes. */ - dev->max_transfer_len = block_len; - dev->packet_len = block_len; - break; - } - } + if (dev->current_cdb[0] == 0x42) + dev->callback += 200LL * CDROM_TIME; + /* Account for seek time. */ + bytes_per_second = 176.0 * 1024.0; + bytes_per_second *= (double) dev->cur_speed; + break; default: - dev->packet_len = len; + bytes_per_second = cdrom_bus_speed(dev); + if (bytes_per_second == 0.0) { + dev->callback = -1LL; /* Speed depends on SCSI controller */ + return; + } break; } - /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ - if ((dev->max_transfer_len & 1) && (dev->max_transfer_len < len)) - dev->max_transfer_len &= 0xfffe; - /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ - if (!dev->max_transfer_len) - dev->max_transfer_len = 65534; - if ((len <= dev->max_transfer_len) && (len >= min_len)) { - dev->request_length = dev->max_transfer_len = len; - } - return; + period = 1000000.0 / bytes_per_second; + cdrom_log("CD-ROM %i: Byte transfer period: %" PRIu64 " us\n", dev->id, (int64_t) period); + period = period * (double) (dev->packet_len); + cdrom_log("CD-ROM %i: Sector transfer period: %" PRIu64 " us\n", dev->id, (int64_t) period); + dusec = period * ((double) TIMER_USEC); + dev->callback += ((int64_t) dusec); + } + cdrom_set_callback(dev); } -static double cdrom_get_short_seek(uint8_t id) + +static void +cdrom_command_complete(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - - switch(dev->cur_speed) { - case 0: - fatal("CD-ROM %i: 0x speed\n", id); - return 0.0; - case 1: - return 240.0; - case 2: - return 160.0; - case 3: - return 150.0; - case 4: case 5: case 6: case 7: case 8: - case 9: case 10: case 11: - return 112.0; - case 12: case 13: case 14: case 15: - return 75.0; - case 16: case 17: case 18: case 19: - return 58.0; - case 20: case 21: case 22: case 23: - case 40: case 41: case 42: case 43: - case 44: case 45: case 46: case 47: - case 48: - return 50.0; - default: - /* 24-32, 52+ */ - return 45.0; - } + dev->packet_status = CDROM_PHASE_COMPLETE; + cdrom_command_common(dev); } -static double cdrom_get_long_seek(uint8_t id) + +static void +cdrom_command_read(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - - switch(dev->cur_speed) { - case 0: - fatal("CD-ROM %i: 0x speed\n", id); - return 0.0; - case 1: - return 1446.0; - case 2: - return 1000.0; - case 3: - return 900.0; - case 4: case 5: case 6: case 7: case 8: - case 9: case 10: case 11: - return 675.0; - case 12: case 13: case 14: case 15: - return 400.0; - case 16: case 17: case 18: case 19: - return 350.0; - case 20: case 21: case 22: case 23: - case 40: case 41: case 42: case 43: - case 44: case 45: case 46: case 47: - case 48: - return 300.0; - default: - /* 24-32, 52+ */ - return 270.0; - } + dev->packet_status = CDROM_PHASE_DATA_IN; + cdrom_command_common(dev); + dev->total_read = 0; } -#define MIN_SEEK 2000 -#define MAX_SEEK 333333 -static double cdrom_seek_time(uint8_t id) +static void +cdrom_command_read_dma(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - - uint32_t diff = dev->seek_diff; - double sd = (double) (MAX_SEEK - MIN_SEEK); - - if (diff < MIN_SEEK) - return 0.0; - if (diff > MAX_SEEK) - diff = MAX_SEEK; - - diff -= MIN_SEEK; - - return cdrom_get_short_seek(id) + ((cdrom_get_long_seek(id) * ((double) diff)) / sd); + dev->packet_status = CDROM_PHASE_DATA_IN_DMA; + cdrom_command_common(dev); + dev->total_read = 0; } -static double cdrom_bus_speed(uint8_t id) + +static void +cdrom_command_write(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { - dev->callback = -1LL; /* Speed depends on SCSI controller */ - return 0.0; - } else if (cdrom_drives[id].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA) { - if (cdrom_current_mode(id) == 2) - return 66666666.666666666666666; /* 66 MB/s MDMA-2 speed */ - else - return 8333333.333333333333333; /* 8.3 MB/s PIO-2 speed */ - } else - return 3333333.333333333333333; /* 3.3 MB/s PIO-0 speed */ + dev->packet_status = CDROM_PHASE_DATA_OUT; + cdrom_command_common(dev); } -static void cdrom_command_bus(uint8_t id) + +static void cdrom_command_write_dma(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - - dev->status = BUSY_STAT; - dev->phase = 1; - dev->pos = 0; - dev->callback = 1LL * CDROM_TIME; - cdrom_set_callback(id); + dev->packet_status = CDROM_PHASE_DATA_OUT_DMA; + cdrom_command_common(dev); } -static void cdrom_command_common(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - double bytes_per_second, period; - double dusec; - - dev->status = BUSY_STAT; - dev->phase = 1; - dev->pos = 0; - dev->callback = 0LL; - - cdrom_log("CD-ROM %i: Current speed: %ix\n", id, dev->cur_speed); - - if (dev->packet_status == CDROM_PHASE_COMPLETE) { - cdrom_phase_callback(id); - dev->callback = 0LL; - } else { - switch(dev->current_cdb[0]) { - case GPCMD_REZERO_UNIT: - case 0x0b: - case 0x2b: - /* Seek time is in us. */ - period = cdrom_seek_time(id) * ((double) TIMER_USEC); - dev->callback += ((int64_t) period); - cdrom_set_callback(id); - cdrom_log("CD-ROM %i: Seek period: %" PRIu64 " us\n", id, (int64_t) cdrom_seek_time(id)); - return; - case 0x08: - case 0x28: - case 0xa8: - /* Seek time is in us. */ - period = cdrom_seek_time(id) * ((double) TIMER_USEC); - dev->callback += ((int64_t) period); - cdrom_log("CD-ROM %i: Seek period: %" PRIu64 " us\n", id, (int64_t) cdrom_seek_time(id)); - case 0x25: - case 0x42: - case 0x43: - case 0x44: - case 0x51: - case 0x52: - case 0xad: - case 0xb8: - case 0xb9: - case 0xbe: - /* bytes_per_second = 150.0 * 1024.0; */ - /* bytes_per_second = (1000000.0 / 12000.0) * 2048.0; */ /* Account for seek time. */ - bytes_per_second = 176.0 * 1024.0; - bytes_per_second *= (double) dev->cur_speed; - break; - default: - bytes_per_second = cdrom_bus_speed(id); - if (bytes_per_second == 0.0) { - dev->callback = -1LL; /* Speed depends on SCSI controller */ - return; - } - break; - } - - period = 1000000.0 / bytes_per_second; - cdrom_log("CD-ROM %i: Byte transfer period: %" PRIu64 " us\n", id, (int64_t) period); - period = period * (double) (dev->packet_len); - cdrom_log("CD-ROM %i: Sector transfer period: %" PRIu64 " us\n", id, (int64_t) period); - dusec = period * ((double) TIMER_USEC); - dev->callback += ((int64_t) dusec); - } - cdrom_set_callback(id); -} - -static void cdrom_command_complete(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - dev->packet_status = CDROM_PHASE_COMPLETE; - cdrom_command_common(id); -} - -static void cdrom_command_read(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - dev->packet_status = CDROM_PHASE_DATA_IN; - cdrom_command_common(id); - dev->total_read = 0; -} - -static void cdrom_command_read_dma(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - dev->packet_status = CDROM_PHASE_DATA_IN_DMA; - cdrom_command_common(id); - dev->total_read = 0; -} - -static void cdrom_command_write(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - dev->packet_status = CDROM_PHASE_DATA_OUT; - cdrom_command_common(id); -} - -static void cdrom_command_write_dma(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - dev->packet_status = CDROM_PHASE_DATA_OUT_DMA; - cdrom_command_common(id); -} /* id = Current CD-ROM device ID; len = Total transfer length; block_len = Length of a single block (why does it matter?!); alloc_len = Allocated transfer length; direction = Transfer direction (0 = read from host, 1 = write to host). */ -static void cdrom_data_command_finish(uint8_t id, int len, int block_len, int alloc_len, int direction) +static void cdrom_data_command_finish(cdrom_t *dev, int len, int block_len, int alloc_len, int direction) { - cdrom_t *dev = cdrom[id]; + cdrom_log("CD-ROM %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", + dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length); + dev->pos = 0; + if (alloc_len >= 0) { + if (alloc_len < len) + len = alloc_len; + } + if ((len == 0) || (cdrom_current_mode(dev) == 0)) { + if (dev->drv->bus_type != CDROM_BUS_SCSI) + dev->packet_len = 0; - cdrom_log("CD-ROM %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length); - dev->pos=0; - if (alloc_len >= 0) { - if (alloc_len < len) { - len = alloc_len; - } + cdrom_command_complete(dev); + } else { + if (cdrom_current_mode(dev) == 2) { + if (dev->drv->bus_type != CDROM_BUS_SCSI) + dev->packet_len = alloc_len; + + if (direction == 0) + cdrom_command_read_dma(dev); + else + cdrom_command_write_dma(dev); + } else { + cdrom_update_request_length(dev, len, block_len); + if (direction == 0) + cdrom_command_read(dev); + else + cdrom_command_write(dev); } - if ((len == 0) || (cdrom_current_mode(id) == 0)) { - if (cdrom_drives[id].bus_type != CDROM_BUS_SCSI) { - dev->packet_len = 0; - } - cdrom_command_complete(id); - } - else { - if (cdrom_current_mode(id) == 2) { - if (cdrom_drives[id].bus_type != CDROM_BUS_SCSI) { - dev->packet_len = alloc_len; - } + } - if (direction == 0) - cdrom_command_read_dma(id); - else - cdrom_command_write_dma(id); - } - else { - cdrom_update_request_length(id, len, block_len); - if (direction == 0) - cdrom_command_read(id); - else - cdrom_command_write(id); - } - } - - cdrom_log("CD-ROM %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", id, dev->packet_status, dev->request_length, dev->packet_len, dev->pos, dev->phase); + cdrom_log("CD-ROM %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", + dev->id, dev->packet_status, dev->request_length, dev->packet_len, dev->pos, dev->phase); } -static void cdrom_sense_clear(int id, int command) -{ - cdrom_t *dev = cdrom[id]; - dev->previous_command = command; - cdrom_sense_key = cdrom_asc = cdrom_ascq = 0; +static void +cdrom_sense_clear(cdrom_t *dev, int command) +{ + dev->previous_command = command; + cdrom_sense_key = cdrom_asc = cdrom_ascq = 0; } -static void cdrom_set_phase(uint8_t id, uint8_t phase) + +static void +cdrom_set_phase(cdrom_t *dev, uint8_t phase) { - uint8_t scsi_id = cdrom_drives[id].scsi_device_id; - uint8_t scsi_lun = cdrom_drives[id].scsi_device_lun; + uint8_t scsi_id = dev->drv->scsi_device_id; - if (cdrom_drives[id].bus_type != CDROM_BUS_SCSI) - return; + if (dev->drv->bus_type != CDROM_BUS_SCSI) + return; - SCSIDevices[scsi_id][scsi_lun].Phase = phase; + SCSIDevices[scsi_id].Phase = phase; } -static void cdrom_cmd_error(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - cdrom_set_phase(id, SCSI_PHASE_STATUS); - dev->error = ((cdrom_sense_key & 0xf) << 4) | ABRT_ERR; - if (dev->unit_attention) - dev->error |= MCR_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - dev->pos = 0; - dev->packet_status = 0x80; - dev->callback = 50LL * CDROM_TIME; - cdrom_set_callback(id); - cdrom_log("CD-ROM %i: ERROR: %02X/%02X/%02X\n", id, cdrom_sense_key, cdrom_asc, cdrom_ascq); +static void +cdrom_cmd_error(cdrom_t *dev) +{ + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->error = ((cdrom_sense_key & 0xf) << 4) | ABRT_ERR; + if (dev->unit_attention) + dev->error |= MCR_ERR; + dev->status = READY_STAT | ERR_STAT; + dev->phase = 3; + dev->pos = 0; + dev->packet_status = 0x80; + dev->callback = 50LL * CDROM_TIME; + cdrom_set_callback(dev); + cdrom_log("CD-ROM %i: ERROR: %02X/%02X/%02X\n", dev->id, cdrom_sense_key, cdrom_asc, cdrom_ascq); } -static void cdrom_unit_attention(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - cdrom_set_phase(id, SCSI_PHASE_STATUS); - dev->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; - if (dev->unit_attention) - dev->error |= MCR_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - dev->pos = 0; - dev->packet_status = 0x80; - dev->callback = 50LL * CDROM_TIME; - cdrom_set_callback(id); - cdrom_log("CD-ROM %i: UNIT ATTENTION\n", id); +static void +cdrom_unit_attention(cdrom_t *dev) +{ + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; + if (dev->unit_attention) + dev->error |= MCR_ERR; + dev->status = READY_STAT | ERR_STAT; + dev->phase = 3; + dev->pos = 0; + dev->packet_status = 0x80; + dev->callback = 50LL * CDROM_TIME; + cdrom_set_callback(dev); + cdrom_log("CD-ROM %i: UNIT ATTENTION\n", dev->id); } -static void cdrom_not_ready(uint8_t id) + +static void +cdrom_bus_master_error(cdrom_t *dev) { - cdrom_sense_key = SENSE_NOT_READY; - cdrom_asc = ASC_MEDIUM_NOT_PRESENT; - cdrom_ascq = 0; - cdrom_cmd_error(id); + cdrom_sense_key = cdrom_asc = cdrom_ascq = 0; + cdrom_cmd_error(dev); } -static void cdrom_invalid_lun(uint8_t id) + +static void +cdrom_not_ready(cdrom_t *dev) { - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_INV_LUN; - cdrom_ascq = 0; - cdrom_cmd_error(id); + cdrom_sense_key = SENSE_NOT_READY; + cdrom_asc = ASC_MEDIUM_NOT_PRESENT; + cdrom_ascq = 0; + cdrom_cmd_error(dev); } -static void cdrom_illegal_opcode(uint8_t id) + +static void +cdrom_invalid_lun(cdrom_t *dev) { - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_ILLEGAL_OPCODE; - cdrom_ascq = 0; - cdrom_cmd_error(id); + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_INV_LUN; + cdrom_ascq = 0; + cdrom_cmd_error(dev); } -static void cdrom_lba_out_of_range(uint8_t id) + +static void +cdrom_illegal_opcode(cdrom_t *dev) { - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_LBA_OUT_OF_RANGE; - cdrom_ascq = 0; - cdrom_cmd_error(id); + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_ILLEGAL_OPCODE; + cdrom_ascq = 0; + cdrom_cmd_error(dev); } -static void cdrom_invalid_field(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_INV_FIELD_IN_CMD_PACKET; - cdrom_ascq = 0; - cdrom_cmd_error(id); - dev->status = 0x53; +static void +cdrom_lba_out_of_range(cdrom_t *dev) +{ + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_LBA_OUT_OF_RANGE; + cdrom_ascq = 0; + cdrom_cmd_error(dev); } -static void cdrom_invalid_field_pl(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; - cdrom_ascq = 0; - cdrom_cmd_error(id); - dev->status = 0x53; +static void +cdrom_invalid_field(cdrom_t *dev) +{ + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_INV_FIELD_IN_CMD_PACKET; + cdrom_ascq = 0; + cdrom_cmd_error(dev); + dev->status = 0x53; } -static void cdrom_illegal_mode(uint8_t id) + +static void +cdrom_invalid_field_pl(cdrom_t *dev) { - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_ILLEGAL_MODE_FOR_THIS_TRACK; - cdrom_ascq = 0; - cdrom_cmd_error(id); + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; + cdrom_ascq = 0; + cdrom_cmd_error(dev); + dev->status = 0x53; } -static void cdrom_incompatible_format(uint8_t id) + +static void +cdrom_illegal_mode(cdrom_t *dev) { - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_INCOMPATIBLE_FORMAT; - cdrom_ascq = 2; - cdrom_cmd_error(id); + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_ILLEGAL_MODE_FOR_THIS_TRACK; + cdrom_ascq = 0; + cdrom_cmd_error(dev); } -static void cdrom_data_phase_error(uint8_t id) + +static void +cdrom_incompatible_format(cdrom_t *dev) { - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_DATA_PHASE_ERROR; - cdrom_ascq = 0; - cdrom_cmd_error(id); + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_INCOMPATIBLE_FORMAT; + cdrom_ascq = 2; + cdrom_cmd_error(dev); } -static int cdrom_pass_through(uint8_t id, uint32_t *len, uint8_t *cdb, uint8_t *buffer) + +static void +cdrom_data_phase_error(cdrom_t *dev) { - int ret = 0; - uint8_t temp_cdb[16]; + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_DATA_PHASE_ERROR; + cdrom_ascq = 0; + cdrom_cmd_error(dev); +} - memset(temp_cdb, 0, 16); - if (cdb[0] == 8) { - temp_cdb[0] = 0x28; - temp_cdb[8] = cdb[4]; - temp_cdb[3] = cdb[1]; - temp_cdb[4] = cdb[2]; - temp_cdb[5] = cdb[3]; - } else - memcpy(temp_cdb, cdb, 16); +void +cdrom_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks) +{ + int temp = 0; - ret = cdrom_drives[id].handler->pass_through(id, temp_cdb, buffer, len); - cdrom_log("CD-ROM %i: Data from pass through: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]); - cdrom_log("CD-ROM %i: Returned value: %i\n", id, ret); + switch(cdb[0]) { + case GPCMD_READ_6: + cdb[1] = (lba_pos >> 16) & 0xff; + cdb[2] = (lba_pos >> 8) & 0xff; + cdb[3] = lba_pos & 0xff; + break; + + case GPCMD_READ_10: + cdb[2] = (lba_pos >> 24) & 0xff; + cdb[3] = (lba_pos >> 16) & 0xff; + cdb[4] = (lba_pos >> 8) & 0xff; + cdb[5] = lba_pos & 0xff; + cdb[7] = (number_of_blocks >> 8) & 0xff; + cdb[8] = number_of_blocks & 0xff; + break; + + case GPCMD_READ_12: + cdb[2] = (lba_pos >> 24) & 0xff; + cdb[3] = (lba_pos >> 16) & 0xff; + cdb[4] = (lba_pos >> 8) & 0xff; + cdb[5] = lba_pos & 0xff; + cdb[6] = (number_of_blocks >> 24) & 0xff; + cdb[7] = (number_of_blocks >> 16) & 0xff; + cdb[8] = (number_of_blocks >> 8) & 0xff; + cdb[9] = number_of_blocks & 0xff; + break; + + case GPCMD_READ_CD_MSF: + temp = cdrom_lba_to_msf_accurate(lba_pos); + cdb[3] = (temp >> 16) & 0xff; + cdb[4] = (temp >> 8) & 0xff; + cdb[5] = temp & 0xff; + + temp = cdrom_lba_to_msf_accurate(lba_pos + number_of_blocks - 1); + cdb[6] = (temp >> 16) & 0xff; + cdb[7] = (temp >> 8) & 0xff; + cdb[8] = temp & 0xff; + break; + + case GPCMD_READ_CD: + cdb[2] = (lba_pos >> 24) & 0xff; + cdb[3] = (lba_pos >> 16) & 0xff; + cdb[4] = (lba_pos >> 8) & 0xff; + cdb[5] = lba_pos & 0xff; + cdb[6] = (number_of_blocks >> 16) & 0xff; + cdb[7] = (number_of_blocks >> 8) & 0xff; + cdb[8] = number_of_blocks & 0xff; + break; + } +} + + +static int +cdrom_read_data(cdrom_t *dev, int msf, int type, int flags, int32_t *len) +{ + int ret = 0; + uint32_t cdsize = 0; + + int i = 0; + int temp_len = 0; + + cdsize = dev->handler->size(dev->id); + + if (dev->sector_pos >= cdsize) { + cdrom_log("CD-ROM %i: Trying to read from beyond the end of disc (%i >= %i)\n", dev->id, + dev->sector_pos, cdsize); + cdrom_lba_out_of_range(dev); + return 0; + } + + if ((dev->sector_pos + dev->sector_len - 1) >= cdsize) { + cdrom_log("CD-ROM %i: Trying to read to beyond the end of disc (%i >= %i)\n", dev->id, + (dev->sector_pos + dev->sector_len - 1), cdsize); + cdrom_lba_out_of_range(dev); + return 0; + } + + dev->old_len = 0; + *len = 0; + + for (i = 0; i < dev->requested_blocks; i++) { + ret = dev->handler->readsector_raw(dev->id, cdbufferb + dev->data_pos, dev->sector_pos + i, + msf, type, flags, &temp_len); + + dev->data_pos += temp_len; + dev->old_len += temp_len; + + *len += temp_len; if (!ret) { - /* Command failed with OS error code, return illegal opcode. */ - cdrom_log("CD-ROM %i: Command failed with OS error code, return illegal opcode.\n", id); - cdrom_illegal_opcode(id); + cdrom_illegal_mode(dev); return 0; - } else { - if ((cdrom_sense_key != 0) || (cdrom_asc != 0) || (cdrom_ascq != 0)) { - /* Command failed with sense, error with that sense. */ - cdrom_log("CD-ROM %i: Command failed with sense, error with that sense (%02X/%02X/%02X).\n", id, cdrom_sense_key, cdrom_asc, cdrom_ascq); - cdrom_cmd_error(id); - return 0; - } else { - /* Command was performed successfully. */ - cdrom_log("CD-ROM %i: Command was performed successfully.\n", id); - return 1; - } } + } + + return 1; } -void cdrom_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks) + +static int +cdrom_read_blocks(cdrom_t *dev, int32_t *len, int first_batch) { - int temp = 0; + int ret = 0, msf = 0; + int type = 0, flags = 0; - switch(cdb[0]) { - case GPCMD_READ_6: - cdb[1] = (lba_pos >> 16) & 0xff; - cdb[2] = (lba_pos >> 8) & 0xff; - cdb[3] = lba_pos & 0xff; - break; + if (dev->current_cdb[0] == 0xb9) + msf = 1; - case GPCMD_READ_10: - cdb[2] = (lba_pos >> 24) & 0xff; - cdb[3] = (lba_pos >> 16) & 0xff; - cdb[4] = (lba_pos >> 8) & 0xff; - cdb[5] = lba_pos & 0xff; - cdb[7] = (number_of_blocks >> 8) & 0xff; - cdb[8] = number_of_blocks & 0xff; - break; + if ((dev->current_cdb[0] == 0xb9) || (dev->current_cdb[0] == 0xbe)) { + type = (dev->current_cdb[1] >> 2) & 7; + flags = dev->current_cdb[9] | (((uint32_t) dev->current_cdb[10]) << 8); + } else { + type = 8; + flags = 0x10; + } - case GPCMD_READ_12: - cdb[2] = (lba_pos >> 24) & 0xff; - cdb[3] = (lba_pos >> 16) & 0xff; - cdb[4] = (lba_pos >> 8) & 0xff; - cdb[5] = lba_pos & 0xff; - cdb[6] = (number_of_blocks >> 24) & 0xff; - cdb[7] = (number_of_blocks >> 16) & 0xff; - cdb[8] = (number_of_blocks >> 8) & 0xff; - cdb[9] = number_of_blocks & 0xff; - break; + dev->data_pos = 0; - case GPCMD_READ_CD_MSF: - temp = cdrom_lba_to_msf_accurate(lba_pos); - cdb[3] = (temp >> 16) & 0xff; - cdb[4] = (temp >> 8) & 0xff; - cdb[5] = temp & 0xff; + if (!dev->sector_len) { + cdrom_command_complete(dev); + return -1; + } - temp = cdrom_lba_to_msf_accurate(lba_pos + number_of_blocks - 1); - cdb[6] = (temp >> 16) & 0xff; - cdb[7] = (temp >> 8) & 0xff; - cdb[8] = temp & 0xff; - break; + cdrom_log("Reading %i blocks starting from %i...\n", dev->requested_blocks, dev->sector_pos); - case GPCMD_READ_CD: - cdb[2] = (lba_pos >> 24) & 0xff; - cdb[3] = (lba_pos >> 16) & 0xff; - cdb[4] = (lba_pos >> 8) & 0xff; - cdb[5] = lba_pos & 0xff; - cdb[6] = (number_of_blocks >> 16) & 0xff; - cdb[7] = (number_of_blocks >> 8) & 0xff; - cdb[8] = number_of_blocks & 0xff; - break; - } + cdrom_update_cdb(dev->current_cdb, dev->sector_pos, dev->requested_blocks); + + ret = cdrom_read_data(dev, msf, type, flags, len); + + cdrom_log("Read %i bytes of blocks...\n", *len); + + if (!ret || ((dev->old_len != *len) && !first_batch)) { + if ((dev->old_len != *len) && !first_batch) + cdrom_illegal_mode(dev); + + return 0; + } + + dev->sector_pos += dev->requested_blocks; + dev->sector_len -= dev->requested_blocks; + + return 1; } -#define cdbufferb dev->buffer -int cdrom_read_data(uint8_t id, int msf, int type, int flags, uint32_t *len) -{ - cdrom_t *dev = cdrom[id]; - - int ret = 0; - int cdsize = 0; - - int i = 0; - int temp_len = 0; - - int last_valid_data_pos = 0; - - cdsize = cdrom_drives[id].handler->size(id); - - if (dev->sector_pos >= cdsize) { - cdrom_log("CD-ROM %i: Trying to read from beyond the end of disc (%i >= %i)\n", id, dev->sector_pos, cdsize); - cdrom_lba_out_of_range(id); - return 0; - } - - if ((dev->sector_pos + dev->sector_len - 1) >= cdsize) { - cdrom_log("CD-ROM %i: Trying to read to beyond the end of disc (%i >= %i)\n", id, (dev->sector_pos + dev->sector_len - 1), cdsize); - cdrom_lba_out_of_range(id); - return 0; - } - - if (cdrom_drives[id].handler->pass_through) { - ret = cdrom_pass_through(id, len, dev->current_cdb, cdbufferb + dev->data_pos); - dev->data_pos += *len; - - if (!ret) - return 0; - - dev->old_len = *len; - } else { - dev->old_len = 0; - *len = 0; - - for (i = 0; i < dev->requested_blocks; i++) { - ret = cdrom_drives[id].handler->readsector_raw(id, cdbufferb + dev->data_pos, dev->sector_pos + i, msf, type, flags, &temp_len); - - last_valid_data_pos = dev->data_pos; - - dev->data_pos += temp_len; - dev->old_len += temp_len; - - *len += temp_len; - - if (!ret) { - cdrom_illegal_mode(id); - return 0; - } - } - - cdrom_log("CD-ROM %i: Data from raw sector read: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, cdbufferb[last_valid_data_pos + 0], cdbufferb[last_valid_data_pos + 1], cdbufferb[last_valid_data_pos + 2], cdbufferb[last_valid_data_pos + 3], cdbufferb[last_valid_data_pos + 4], cdbufferb[last_valid_data_pos + 5], cdbufferb[last_valid_data_pos + 6], cdbufferb[last_valid_data_pos + 7]); - } - - return 1; -} - -int cdrom_read_blocks(uint8_t id, uint32_t *len, int first_batch) -{ - cdrom_t *dev = cdrom[id]; - - int ret = 0; - - int msf = 0; - - int type = 0; - int flags = 0; - - if (dev->current_cdb[0] == 0xb9) - msf = 1; - - if ((dev->current_cdb[0] == 0xb9) || (dev->current_cdb[0] == 0xbe)) { - type = (dev->current_cdb[1] >> 2) & 7; - flags = dev->current_cdb[9] | (((uint32_t) dev->current_cdb[10]) << 8); - } else { - type = 8; - flags = 0x10; - } - - dev->data_pos = 0; - - if (!dev->sector_len) { - cdrom_command_complete(id); - return -1; - } - - cdrom_log("Reading %i blocks starting from %i...\n", dev->requested_blocks, dev->sector_pos); - - cdrom_update_cdb(dev->current_cdb, dev->sector_pos, dev->requested_blocks); - - ret = cdrom_read_data(id, msf, type, flags, len); - - cdrom_log("Read %i bytes of blocks...\n", *len); - - if (!ret || ((dev->old_len != *len) && !first_batch)) { - if ((dev->old_len != *len) && !first_batch) - cdrom_illegal_mode(id); - - return 0; - } - - dev->sector_pos += dev->requested_blocks; - dev->sector_len -= dev->requested_blocks; - - return 1; -} - -/*SCSI Get Configuration*/ /*SCSI Read DVD Structure*/ -static int cdrom_read_dvd_structure(uint8_t id, int format, const uint8_t *packet, uint8_t *buf) +static int +cdrom_read_dvd_structure(cdrom_t *dev, int format, const uint8_t *packet, uint8_t *buf) { - int layer = packet[6]; - uint64_t total_sectors; + int layer = packet[6]; + uint64_t total_sectors; - switch (format) { - case 0x00: /* Physical format information */ - total_sectors = (uint64_t) cdrom_drives[id].handler->size(id); + switch (format) { + case 0x00: /* Physical format information */ + total_sectors = (uint64_t) dev->handler->size(dev->id); - if (layer != 0) { - cdrom_invalid_field(id); - return 0; - } - - total_sectors >>= 2; - if (total_sectors == 0) { - /* return -ASC_MEDIUM_NOT_PRESENT; */ - cdrom_not_ready(id); - return 0; - } - - buf[4] = 1; /* DVD-ROM, part version 1 */ - buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */ - buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */ - buf[7] = 0; /* default densities */ - - /* FIXME: 0x30000 per spec? */ - buf[8] = buf[9] = buf[10] = buf[11] = 0; /* start sector */ - buf[12] = (total_sectors >> 24) & 0xff; /* end sector */ - buf[13] = (total_sectors >> 16) & 0xff; - buf[14] = (total_sectors >> 8) & 0xff; - buf[15] = total_sectors & 0xff; - - buf[16] = (total_sectors >> 24) & 0xff; /* l0 end sector */ - buf[17] = (total_sectors >> 16) & 0xff; - buf[18] = (total_sectors >> 8) & 0xff; - buf[19] = total_sectors & 0xff; - - /* Size of buffer, not including 2 byte size field */ - buf[0] = ((2048 +2 ) >> 8) & 0xff; - buf[1] = (2048 + 2) & 0xff; - - /* 2k data + 4 byte header */ - return (2048 + 4); - - case 0x01: /* DVD copyright information */ - buf[4] = 0; /* no copyright data */ - buf[5] = 0; /* no region restrictions */ - - /* Size of buffer, not including 2 byte size field */ - buf[0] = ((4 + 2) >> 8) & 0xff; - buf[1] = (4 + 2) & 0xff; - - /* 4 byte header + 4 byte data */ - return (4 + 4); - - case 0x03: /* BCA information - invalid field for no BCA info */ - cdrom_invalid_field(id); + if (layer != 0) { + cdrom_invalid_field(dev); return 0; + } - case 0x04: /* DVD disc manufacturing information */ - /* Size of buffer, not including 2 byte size field */ - buf[0] = ((2048 + 2) >> 8) & 0xff; - buf[1] = (2048 + 2) & 0xff; - - /* 2k data + 4 byte header */ - return (2048 + 4); - - case 0xff: - /* - * This lists all the command capabilities above. Add new ones - * in order and update the length and buffer return values. - */ - - buf[4] = 0x00; /* Physical format */ - buf[5] = 0x40; /* Not writable, is readable */ - buf[6] = ((2048 + 4) >> 8) & 0xff; - buf[7] = (2048 + 4) & 0xff; - - buf[8] = 0x01; /* Copyright info */ - buf[9] = 0x40; /* Not writable, is readable */ - buf[10] = ((4 + 4) >> 8) & 0xff; - buf[11] = (4 + 4) & 0xff; - - buf[12] = 0x03; /* BCA info */ - buf[13] = 0x40; /* Not writable, is readable */ - buf[14] = ((188 + 4) >> 8) & 0xff; - buf[15] = (188 + 4) & 0xff; - - buf[16] = 0x04; /* Manufacturing info */ - buf[17] = 0x40; /* Not writable, is readable */ - buf[18] = ((2048 + 4) >> 8) & 0xff; - buf[19] = (2048 + 4) & 0xff; - - /* Size of buffer, not including 2 byte size field */ - buf[6] = ((16 + 2) >> 8) & 0xff; - buf[7] = (16 + 2) & 0xff; - - /* data written + 4 byte header */ - return (16 + 4); - - default: /* TODO: formats beyond DVD-ROM requires */ - cdrom_invalid_field(id); + total_sectors >>= 2; + if (total_sectors == 0) { + /* return -ASC_MEDIUM_NOT_PRESENT; */ + cdrom_not_ready(dev); return 0; - } + } + + buf[4] = 1; /* DVD-ROM, part version 1 */ + buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */ + buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */ + buf[7] = 0; /* default densities */ + + /* FIXME: 0x30000 per spec? */ + buf[8] = buf[9] = buf[10] = buf[11] = 0; /* start sector */ + buf[12] = (total_sectors >> 24) & 0xff; /* end sector */ + buf[13] = (total_sectors >> 16) & 0xff; + buf[14] = (total_sectors >> 8) & 0xff; + buf[15] = total_sectors & 0xff; + + buf[16] = (total_sectors >> 24) & 0xff; /* l0 end sector */ + buf[17] = (total_sectors >> 16) & 0xff; + buf[18] = (total_sectors >> 8) & 0xff; + buf[19] = total_sectors & 0xff; + + /* Size of buffer, not including 2 byte size field */ + buf[0] = ((2048 +2 ) >> 8) & 0xff; + buf[1] = (2048 + 2) & 0xff; + + /* 2k data + 4 byte header */ + return (2048 + 4); + + case 0x01: /* DVD copyright information */ + buf[4] = 0; /* no copyright data */ + buf[5] = 0; /* no region restrictions */ + + /* Size of buffer, not including 2 byte size field */ + buf[0] = ((4 + 2) >> 8) & 0xff; + buf[1] = (4 + 2) & 0xff; + + /* 4 byte header + 4 byte data */ + return (4 + 4); + + case 0x03: /* BCA information - invalid field for no BCA info */ + cdrom_invalid_field(dev); + return 0; + + case 0x04: /* DVD disc manufacturing information */ + /* Size of buffer, not including 2 byte size field */ + buf[0] = ((2048 + 2) >> 8) & 0xff; + buf[1] = (2048 + 2) & 0xff; + + /* 2k data + 4 byte header */ + return (2048 + 4); + + case 0xff: + /* + * This lists all the command capabilities above. Add new ones + * in order and update the length and buffer return values. + */ + + buf[4] = 0x00; /* Physical format */ + buf[5] = 0x40; /* Not writable, is readable */ + buf[6] = ((2048 + 4) >> 8) & 0xff; + buf[7] = (2048 + 4) & 0xff; + + buf[8] = 0x01; /* Copyright info */ + buf[9] = 0x40; /* Not writable, is readable */ + buf[10] = ((4 + 4) >> 8) & 0xff; + buf[11] = (4 + 4) & 0xff; + + buf[12] = 0x03; /* BCA info */ + buf[13] = 0x40; /* Not writable, is readable */ + buf[14] = ((188 + 4) >> 8) & 0xff; + buf[15] = (188 + 4) & 0xff; + + buf[16] = 0x04; /* Manufacturing info */ + buf[17] = 0x40; /* Not writable, is readable */ + buf[18] = ((2048 + 4) >> 8) & 0xff; + buf[19] = (2048 + 4) & 0xff; + + /* Size of buffer, not including 2 byte size field */ + buf[6] = ((16 + 2) >> 8) & 0xff; + buf[7] = (16 + 2) & 0xff; + + /* data written + 4 byte header */ + return (16 + 4); + + default: /* TODO: formats beyond DVD-ROM requires */ + cdrom_invalid_field(dev); + return 0; + } } -void cdrom_insert(uint8_t id) + +void +cdrom_insert(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - - dev->unit_attention = 1; - - cdrom_log("CD-ROM %i: Media insert\n", id); + dev->unit_attention = 1; + cdrom_log("CD-ROM %i: Media insert\n", dev->id); } + /*SCSI Sense Initialization*/ -void cdrom_sense_code_ok(uint8_t id) +void +cdrom_sense_code_ok(uint8_t id) { - cdrom_sense_key = SENSE_NONE; - cdrom_asc = 0; - cdrom_ascq = 0; + cdrom_t *dev = cdrom[id]; + + cdrom_sense_key = SENSE_NONE; + cdrom_asc = 0; + cdrom_ascq = 0; } -int cdrom_pre_execution_check(uint8_t id, uint8_t *cdb) + +static int +cdrom_pre_execution_check(cdrom_t *dev, uint8_t *cdb) { - cdrom_t *dev = cdrom[id]; + int ready = 0, status = 0; - int ready = 0; - - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { - if (((dev->request_length >> 5) & 7) != cdrom_drives[id].scsi_device_lun) { - cdrom_log("CD-ROM %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", id, ((dev->request_length >> 5) & 7)); - cdrom_invalid_lun(id); - return 0; - } - } - - if (!(cdrom_command_flags[cdb[0]] & IMPLEMENTED)) { - cdrom_log("CD-ROM %i: Attempting to execute unknown command %02X over %s\n", id, cdb[0], (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) ? "SCSI" : ((cdrom_drives[id].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA) ? "ATAPI PIO/DMA" : "ATAPI PIO")); - - cdrom_illegal_opcode(id); + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + if ((cdb[0] != GPCMD_REQUEST_SENSE) && (cdb[1] & 0xe0)) { + cdrom_log("CD-ROM %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", + dev->id, ((dev->request_length >> 5) & 7)); + cdrom_invalid_lun(dev); return 0; } + } - if ((cdrom_drives[id].bus_type < CDROM_BUS_SCSI) && (cdrom_command_flags[cdb[0]] & SCSI_ONLY)) { - cdrom_log("CD-ROM %i: Attempting to execute SCSI-only command %02X over ATAPI\n", id, cdb[0]); - cdrom_illegal_opcode(id); - return 0; - } + if (!(cdrom_command_flags[cdb[0]] & IMPLEMENTED)) { + cdrom_log("CD-ROM %i: Attempting to execute unknown command %02X over %s\n", dev->id, cdb[0], + (dev->drv->bus_type == CDROM_BUS_SCSI) ? "SCSI" : "ATAPI"); - if ((cdrom_drives[id].bus_type == CDROM_BUS_SCSI) && (cdrom_command_flags[cdb[0]] & ATAPI_ONLY)) { - cdrom_log("CD-ROM %i: Attempting to execute ATAPI-only command %02X over SCSI\n", id, cdb[0]); - cdrom_illegal_opcode(id); - return 0; - } + cdrom_illegal_opcode(dev); + return 0; + } - if ((cdrom_drives[id].handler->status(id) == CD_STATUS_PLAYING) || (cdrom_drives[id].handler->status(id) == CD_STATUS_PAUSED)) { - ready = 1; - goto skip_ready_check; - } + if ((dev->drv->bus_type < CDROM_BUS_SCSI) && (cdrom_command_flags[cdb[0]] & SCSI_ONLY)) { + cdrom_log("CD-ROM %i: Attempting to execute SCSI-only command %02X over ATAPI\n", dev->id, cdb[0]); + cdrom_illegal_opcode(dev); + return 0; + } - if (cdrom_drives[id].handler->medium_changed(id)) - cdrom_insert(id); + if ((dev->drv->bus_type == CDROM_BUS_SCSI) && (cdrom_command_flags[cdb[0]] & ATAPI_ONLY)) { + cdrom_log("CD-ROM %i: Attempting to execute ATAPI-only command %02X over SCSI\n", dev->id, cdb[0]); + cdrom_illegal_opcode(dev); + return 0; + } - ready = cdrom_drives[id].handler->ready(id); + status = dev->handler->status(dev->id); + + if ((status == CD_STATUS_PLAYING) || (status == CD_STATUS_PAUSED)) { + ready = 1; + goto skip_ready_check; + } + + if (dev->handler->medium_changed(dev->id)) + cdrom_insert(dev); + + ready = dev->handler->ready(dev->id); skip_ready_check: - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - if (!ready && dev->unit_attention) - dev->unit_attention = 0; - - /* If the UNIT ATTENTION condition is set and the command does not allow - execution under it, error out and report the condition. */ - if (dev->unit_attention == 1) { - /* Only increment the unit attention phase if the command can not pass through it. */ - if (!(cdrom_command_flags[cdb[0]] & ALLOW_UA)) { - /* cdrom_log("CD-ROM %i: Unit attention now 2\n", id); */ - dev->unit_attention++; - cdrom_log("CD-ROM %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", id, cdb[0]); - cdrom_unit_attention(id); - return 0; - } - } - else if (dev->unit_attention == 2) { - if (cdb[0] != GPCMD_REQUEST_SENSE) { - /* cdrom_log("CD-ROM %i: Unit attention now 0\n", id); */ - dev->unit_attention = 0; - } - } - - /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* - the UNIT ATTENTION condition if it's set. */ - if (cdb[0] != GPCMD_REQUEST_SENSE) - cdrom_sense_clear(id, cdb[0]); - - /* Next it's time for NOT READY. */ - if (!ready) - dev->media_status = MEC_MEDIA_REMOVAL; - else - dev->media_status = (dev->unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE; - - if ((cdrom_command_flags[cdb[0]] & CHECK_READY) && !ready) { - cdrom_log("CD-ROM %i: Not ready (%02X)\n", id, cdb[0]); - cdrom_not_ready(id); - return 0; - } - - cdrom_log("CD-ROM %i: Continuing with command %02X\n", id, cdb[0]); - - return 1; -} - -void cdrom_clear_callback(uint8_t channel) -{ - cdrom_t *dev; - - uint8_t id = atapi_cdrom_drives[channel]; - - dev = cdrom[id]; - - if (id < CDROM_NUM) - { - dev->callback = 0LL; - cdrom_set_callback(id); - } -} - -static void cdrom_seek(uint8_t id, uint32_t pos) -{ - cdrom_t *dev = cdrom[id]; - - /* cdrom_log("CD-ROM %i: Seek %08X\n", id, pos); */ - dev->seek_pos = pos; - if (cdrom_drives[id].handler->stop) - cdrom_drives[id].handler->stop(id); -} - -static void cdrom_rezero(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - if (cdrom_drives[id].handler->stop) - cdrom_drives[id].handler->stop(id); - dev->sector_pos = dev->sector_len = 0; - cdrom_seek(id, 0); -} - -void cdrom_reset(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - if (!dev) - return; - - cdrom_rezero(id); - dev->status = 0; - dev->callback = 0LL; - cdrom_set_callback(id); - dev->packet_status = 0xff; + /* If the drive is not ready, there is no reason to keep the + UNIT ATTENTION condition present, as we only use it to mark + disc changes. */ + if (!ready && dev->unit_attention) dev->unit_attention = 0; -} -int cdrom_playing_completed(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - dev->prev_status = dev->cd_status; - dev->cd_status = cdrom_drives[id].handler->status(id); - if (((dev->prev_status == CD_STATUS_PLAYING) || (dev->prev_status == CD_STATUS_PAUSED)) && ((dev->cd_status != CD_STATUS_PLAYING) && (dev->cd_status != CD_STATUS_PAUSED))) - return 1; - else + /* If the UNIT ATTENTION condition is set and the command does not allow + execution under it, error out and report the condition. */ + if (dev->unit_attention == 1) { + /* Only increment the unit attention phase if the command can not pass through it. */ + if (!(cdrom_command_flags[cdb[0]] & ALLOW_UA)) { + /* cdrom_log("CD-ROM %i: Unit attention now 2\n", dev->id); */ + dev->unit_attention++; + cdrom_log("CD-ROM %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", + dev->id, cdb[0]); + cdrom_unit_attention(dev); return 0; -} - -void cdrom_request_sense(uint8_t id, uint8_t *buffer, uint8_t alloc_length) -{ - cdrom_t *dev = cdrom[id]; - - /*Will return 18 bytes of 0*/ - if (alloc_length != 0) { - memset(buffer, 0, alloc_length); - memcpy(buffer, dev->sense, alloc_length); } - - buffer[0] = 0x70; - - if ((cdrom_sense_key > 0) && ((dev->cd_status < CD_STATUS_PLAYING) || (dev->cd_status == CD_STATUS_STOPPED)) && cdrom_playing_completed(id)) { - buffer[2]=SENSE_ILLEGAL_REQUEST; - buffer[12]=ASC_AUDIO_PLAY_OPERATION; - buffer[13]=ASCQ_AUDIO_PLAY_OPERATION_COMPLETED; - } - else if ((cdrom_sense_key == 0) && (dev->cd_status >= CD_STATUS_PLAYING) && (dev->cd_status != CD_STATUS_STOPPED)) { - buffer[2]=SENSE_ILLEGAL_REQUEST; - buffer[12]=ASC_AUDIO_PLAY_OPERATION; - buffer[13]=(dev->cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; - } - else { - if (dev->unit_attention && (cdrom_sense_key == 0)) { - buffer[2]=SENSE_UNIT_ATTENTION; - buffer[12]=ASC_MEDIUM_MAY_HAVE_CHANGED; - buffer[13]=0; - } - } - - cdrom_log("CD-ROM %i: Reporting sense: %02X %02X %02X\n", id, buffer[2], buffer[12], buffer[13]); - - if (buffer[2] == SENSE_UNIT_ATTENTION) { - /* If the last remaining sense is unit attention, clear - that condition. */ + } else if (dev->unit_attention == 2) { + if (cdb[0] != GPCMD_REQUEST_SENSE) { + /* cdrom_log("CD-ROM %i: Unit attention now 0\n", dev->id); */ dev->unit_attention = 0; } + } - /* Clear the sense stuff as per the spec. */ - cdrom_sense_clear(id, GPCMD_REQUEST_SENSE); + /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* + the UNIT ATTENTION condition if it's set. */ + if (cdb[0] != GPCMD_REQUEST_SENSE) + cdrom_sense_clear(dev, cdb[0]); + + /* Next it's time for NOT READY. */ + if (!ready) + dev->media_status = MEC_MEDIA_REMOVAL; + else + dev->media_status = (dev->unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE; + + if ((cdrom_command_flags[cdb[0]] & CHECK_READY) && !ready) { + cdrom_log("CD-ROM %i: Not ready (%02X)\n", dev->id, cdb[0]); + cdrom_not_ready(dev); + return 0; + } + + cdrom_log("CD-ROM %i: Continuing with command %02X\n", dev->id, cdb[0]); + + return 1; } -void cdrom_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length) + +static void +cdrom_seek(cdrom_t *dev, uint32_t pos) { - cdrom_t *dev = cdrom[id]; - - int ready = 0; - - if (cdrom_drives[id].handler->medium_changed(id)) - cdrom_insert(id); - - ready = cdrom_drives[id].handler->ready(id); - - if (!ready && dev->unit_attention) { - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - dev->unit_attention = 0; - } - - /* Do *NOT* advance the unit attention phase. */ - - cdrom_request_sense(id, buffer, alloc_length); + /* cdrom_log("CD-ROM %i: Seek %08X\n", dev->id, pos); */ + dev->seek_pos = pos; + if (dev->handler && dev->handler->stop) + dev->handler->stop(dev->id); } -void cdrom_set_buf_len(uint8_t id, int32_t *BufLen, uint32_t *src_len) + +static void +cdrom_rezero(cdrom_t *dev) { - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { - if (*BufLen == -1) - *BufLen = *src_len; - else { - *BufLen = MIN(*src_len, *BufLen); - *src_len = *BufLen; - } - cdrom_log("CD-ROM %i: Actual transfer length: %i\n", id, *BufLen); - } + if (dev->handler && dev->handler->stop) + dev->handler->stop(dev->id); + dev->sector_pos = dev->sector_len = 0; + cdrom_seek(dev, 0); } -void cdrom_buf_alloc(uint8_t id, uint32_t len) -{ - cdrom_t *dev = cdrom[id]; - cdrom_log("CD-ROM %i: Allocated buffer length: %i\n", id, len); - cdbufferb = (uint8_t *) malloc(len); +void +cdrom_reset(cdrom_t *dev) +{ + if (!dev) + return; + + cdrom_rezero(dev); + dev->status = 0; + dev->callback = 0LL; + cdrom_set_callback(dev); + dev->packet_status = 0xff; + dev->unit_attention = 0xff; } -void cdrom_buf_free(uint8_t id) + +static int +cdrom_playing_completed(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - - if (cdbufferb) { - cdrom_log("CD-ROM %i: Freeing buffer...\n", id); - free(cdbufferb); - cdbufferb = NULL; - } -} - -void cdrom_command(uint8_t id, uint8_t *cdb) -{ - uint32_t len; - int msf; - int pos=0; - uint32_t max_len; - uint32_t feature; - uint32_t used_len; - unsigned idx = 0; - unsigned size_idx; - unsigned preamble_len; - int toc_format; - uint32_t alloc_length; - int block_desc = 0; - int format = 0; - int ret; - int real_pos; - int track = 0; - char device_identify[9] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', 0 }; - char device_identify_ex[15] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; - int32_t blen = 0; - int32_t *BufLen; - uint8_t *b; - uint32_t profiles[2] = { MMC_PROFILE_CD_ROM, MMC_PROFILE_DVD_ROM }; - uint32_t i = 0; - - cdrom_t *dev = cdrom[id]; - - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { - BufLen = &SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].BufferLength; - dev->status &= ~ERR_STAT; - } else { - BufLen = &blen; - dev->error = 0; - } - - dev->packet_len = 0; - dev->request_pos = 0; - - device_identify[7] = id + 0x30; - - device_identify_ex[7] = id + 0x30; - device_identify_ex[10] = EMU_VERSION[0]; - device_identify_ex[12] = EMU_VERSION[2]; - device_identify_ex[13] = EMU_VERSION[3]; - - dev->data_pos = 0; - - memcpy(dev->current_cdb, cdb, dev->cdb_len); - - dev->cd_status = cdrom_drives[id].handler->status(id); - - if (cdb[0] != 0) { - cdrom_log("CD-ROM %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", id, cdb[0], cdrom_sense_key, cdrom_asc, cdrom_ascq, dev->unit_attention); - cdrom_log("CD-ROM %i: Request length: %04X\n", id, dev->request_length); - - cdrom_log("CD-ROM %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", id, - cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], - cdb[8], cdb[9], cdb[10], cdb[11]); - } - - msf = cdb[1] & 2; - dev->sector_len = 0; - - cdrom_set_phase(id, SCSI_PHASE_STATUS); - - /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ - if (cdrom_pre_execution_check(id, cdb) == 0) - return; - - switch (cdb[0]) { - case GPCMD_TEST_UNIT_READY: - cdrom_set_phase(id, SCSI_PHASE_STATUS); - cdrom_command_complete(id); - break; - - case GPCMD_REZERO_UNIT: - if (cdrom_drives[id].handler->stop) - cdrom_drives[id].handler->stop(id); - dev->sector_pos = dev->sector_len = 0; - dev->seek_diff = dev->seek_pos; - cdrom_seek(id, 0); - cdrom_set_phase(id, SCSI_PHASE_STATUS); - break; - - case GPCMD_REQUEST_SENSE: - /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE - should forget about the not ready, and report unit attention straight away. */ - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - max_len = cdb[4]; - cdrom_buf_alloc(id, 256); - cdrom_set_buf_len(id, BufLen, &max_len); - cdrom_request_sense(id, cdbufferb, max_len); - cdrom_data_command_finish(id, 18, 18, cdb[4], 0); - break; - - case GPCMD_SET_SPEED: - case GPCMD_SET_SPEED_ALT: - dev->cur_speed = (cdb[3] | (cdb[2] << 8)) / 176; - if (dev->cur_speed < 1) - dev->cur_speed = 1; - else if (dev->cur_speed > cdrom_drives[id].speed) - dev->cur_speed = cdrom_drives[id].speed; - cdrom_set_phase(id, SCSI_PHASE_STATUS); - cdrom_command_complete(id); - break; - - case GPCMD_MECHANISM_STATUS: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - - cdrom_buf_alloc(id, 8); - - cdrom_set_buf_len(id, BufLen, &len); - - memset(cdbufferb, 0, 8); - cdbufferb[5] = 1; - - cdrom_data_command_finish(id, 8, 8, len, 0); - break; - - case GPCMD_READ_TOC_PMA_ATIP: - dev->toctimes++; - - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - max_len = cdb[7]; - max_len <<= 8; - max_len |= cdb[8]; - - cdrom_buf_alloc(id, 65536); - - if (cdrom_drives[id].handler->pass_through) { - ret = cdrom_pass_through(id, &len, dev->current_cdb, cdbufferb); - if (!ret) { - cdrom_sense_key = cdrom_asc = cdrom_ascq = 0; - goto cdrom_readtoc_fallback; - } - alloc_length = cdbufferb[0]; - alloc_length <<= 8; - alloc_length |= cdbufferb[1]; - alloc_length += 2; - len = MIN(alloc_length, len); - - cdrom_set_buf_len(id, BufLen, &len); - } else { -cdrom_readtoc_fallback: - toc_format = cdb[2] & 0xf; - - if (toc_format == 0) - toc_format = (cdb[9] >> 6) & 3; - - switch (toc_format) { - case 0: /*Normal*/ - len = cdrom_drives[id].handler->readtoc(id, cdbufferb, cdb[6], msf, max_len, 0); - break; - case 1: /*Multi session*/ - len = cdrom_drives[id].handler->readtoc_session(id, cdbufferb, msf, max_len); - cdbufferb[0] = 0; cdbufferb[1] = 0xA; - break; - case 2: /*Raw*/ - len = cdrom_drives[id].handler->readtoc_raw(id, cdbufferb, max_len); - break; - default: - cdrom_invalid_field(id); - cdrom_buf_free(id); - return; - } - } - - if (len > max_len) { - len = max_len; - - cdbufferb[0] = ((len - 2) >> 8) & 0xff; - cdbufferb[1] = (len - 2) & 0xff; - } - - cdrom_set_buf_len(id, BufLen, &len); - - if (len >= 8) { - cdrom_log("CD-ROM %i: TOC: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, - cdbufferb[0], cdbufferb[1], cdbufferb[2], cdbufferb[3], - cdbufferb[4], cdbufferb[5], cdbufferb[6], cdbufferb[7]); - } - - if (len >= 16) { - cdrom_log(" %02X %02X %02X %02X %02X %02X %02X %02X\n", - cdbufferb[8], cdbufferb[9], cdbufferb[10], cdbufferb[11], - cdbufferb[12], cdbufferb[13], cdbufferb[14], cdbufferb[15]); - } - - if (len >= 24) { - cdrom_log(" %02X %02X %02X %02X %02X %02X %02X %02X\n", - cdbufferb[16], cdbufferb[17], cdbufferb[18], cdbufferb[19], - cdbufferb[20], cdbufferb[21], cdbufferb[22], cdbufferb[23]); - } - - if (len >= 32) { - cdrom_log(" %02X %02X %02X %02X %02X %02X %02X %02X\n", - cdbufferb[24], cdbufferb[25], cdbufferb[26], cdbufferb[27], - cdbufferb[28], cdbufferb[29], cdbufferb[30], cdbufferb[31]); - } - - if (len >= 36) { - cdrom_log(" %02X %02X %02X %02X\n", - cdbufferb[32], cdbufferb[33], cdbufferb[34], cdbufferb[35]); - } - - cdrom_data_command_finish(id, len, len, len, 0); - /* cdrom_log("CD-ROM %i: READ_TOC_PMA_ATIP format %02X, length %i (%i)\n", id, toc_format, ide->cylinder, cdbufferb[1]); */ - return; - - case GPCMD_READ_CD_OLD: - dev->current_cdb[0] = 0xbe; /* IMPORTANT: Convert the command to new read CD for pass through purposes. */ - case GPCMD_READ_6: - case GPCMD_READ_10: - case GPCMD_READ_12: - case GPCMD_READ_CD: - case GPCMD_READ_CD_MSF: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - alloc_length = 2048; - - switch(cdb[0]) { - case GPCMD_READ_6: - dev->sector_len = cdb[4]; - dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - msf = 0; - break; - case GPCMD_READ_10: - dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - cdrom_log("CD-ROM %i: Length: %i, LBA: %i\n", id, dev->sector_len, dev->sector_pos); - msf = 0; - break; - case GPCMD_READ_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - cdrom_log("CD-ROM %i: Length: %i, LBA: %i\n", id, dev->sector_len, dev->sector_pos); - msf = 0; - break; - case GPCMD_READ_CD_MSF: - /* cdrom_log("CD-ROM %i: Read CD MSF: Start MSF %02X%02X%02X End MSF %02X%02X%02X Flags %02X\n", id, cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9]); */ - alloc_length = 2856; - dev->sector_len = MSFtoLBA(cdb[6], cdb[7], cdb[8]); - dev->sector_pos = MSFtoLBA(cdb[3], cdb[4], cdb[5]); - - dev->sector_len -= dev->sector_pos; - dev->sector_len++; - msf = 1; - break; - case GPCMD_READ_CD_OLD: - case GPCMD_READ_CD: - /* cdrom_log("CD-ROM %i: Read CD: Start LBA %02X%02X%02X%02X Length %02X%02X%02X Flags %02X\n", id, cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9]); */ - alloc_length = 2856; - dev->sector_len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - - msf = 0; - break; - } - - dev->seek_diff = ABS((int) (pos - dev->seek_pos)); - dev->seek_pos = dev->sector_pos; - - if (!dev->sector_len) { - cdrom_set_phase(id, SCSI_PHASE_STATUS); - /* cdrom_log("CD-ROM %i: All done - callback set\n", id); */ - dev->packet_status = CDROM_PHASE_COMPLETE; - dev->callback = 20LL * CDROM_TIME; - cdrom_set_callback(id); - break; - } - - max_len = dev->sector_len; - dev->requested_blocks = max_len; /* If we're reading all blocks in one go for DMA, why not also for PIO, it should NOT - matter anyway, this step should be identical and only the way the read dat is - transferred to the host should be different. */ - - dev->packet_len = max_len * alloc_length; - cdrom_buf_alloc(id, dev->packet_len); - - ret = cdrom_read_blocks(id, &alloc_length, 1); - if (ret <= 0) { - cdrom_buf_free(id); - return; - } - - dev->requested_blocks = max_len; - dev->packet_len = alloc_length; - - cdrom_set_buf_len(id, BufLen, &dev->packet_len); - - cdrom_data_command_finish(id, alloc_length, alloc_length / dev->requested_blocks, alloc_length, 0); - - dev->all_blocks_total = dev->block_total; - if (dev->packet_status != CDROM_PHASE_COMPLETE) - ui_sb_update_icon(SB_CDROM | id, 1); - else - ui_sb_update_icon(SB_CDROM | id, 0); - return; - - case GPCMD_READ_HEADER: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - alloc_length = ((cdb[7] << 8) | cdb[8]); - cdrom_buf_alloc(id, 8); - - if (cdrom_drives[id].handler->pass_through) { - ret = cdrom_pass_through(id, &len, dev->current_cdb, cdbufferb); - if (!ret) { - cdrom_buf_free(id); - return; - } - } else { - dev->sector_len = 1; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4]<<8) | cdb[5]; - if (msf) - real_pos = cdrom_lba_to_msf_accurate(dev->sector_pos); - else - real_pos = dev->sector_pos; - cdbufferb[0] = 1; /*2048 bytes user data*/ - cdbufferb[1] = cdbufferb[2] = cdbufferb[3] = 0; - cdbufferb[4] = (real_pos >> 24); - cdbufferb[5] = ((real_pos >> 16) & 0xff); - cdbufferb[6] = ((real_pos >> 8) & 0xff); - cdbufferb[7] = real_pos & 0xff; - - len = 8; - } - - len = MIN(len, alloc_length); - - cdrom_set_buf_len(id, BufLen, &len); - - cdrom_data_command_finish(id, len, len, len, 0); - return; - - case GPCMD_MODE_SENSE_6: - case GPCMD_MODE_SENSE_10: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; - else - block_desc = 0; - - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = cdb[4]; - cdrom_buf_alloc(id, 256); - } else { - len = (cdb[8] | (cdb[7] << 8)); - cdrom_buf_alloc(id, 65536); - } - - dev->current_page_code = cdb[2] & 0x3F; - - if (!(cdrom_mode_sense_page_flags & (1LL << dev->current_page_code))) { - cdrom_invalid_field(id); - cdrom_buf_free(id); - return; - } - - memset(cdbufferb, 0, len); - alloc_length = len; - - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = cdrom_mode_sense(id, cdbufferb, 4, cdb[2], block_desc); - len = MIN(len, alloc_length); - cdbufferb[0] = len - 1; - cdbufferb[1] = cdrom_drives[id].handler->media_type_id(id); - if (block_desc) - cdbufferb[3] = 8; - } else { - len = cdrom_mode_sense(id, cdbufferb, 8, cdb[2], block_desc); - len = MIN(len, alloc_length); - cdbufferb[0]=(len - 2) >> 8; - cdbufferb[1]=(len - 2) & 255; - cdbufferb[2] = cdrom_drives[id].handler->media_type_id(id); - if (block_desc) { - cdbufferb[6] = 0; - cdbufferb[7] = 8; - } - } - - cdrom_set_buf_len(id, BufLen, &len); - - cdrom_log("CD-ROM %i: Reading mode page: %02X...\n", id, cdb[2]); - - cdrom_data_command_finish(id, len, len, alloc_length, 0); - return; - - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - cdrom_set_phase(id, SCSI_PHASE_DATA_OUT); - - if (cdb[0] == GPCMD_MODE_SELECT_6) { - len = cdb[4]; - cdrom_buf_alloc(id, 256); - } else { - len = (cdb[7] << 8) | cdb[8]; - cdrom_buf_alloc(id, 65536); - } - - cdrom_set_buf_len(id, BufLen, &len); - - dev->total_length = len; - dev->do_page_save = cdb[1] & 1; - - dev->current_page_pos = 0; - - cdrom_data_command_finish(id, len, len, len, 1); - return; - - case GPCMD_GET_CONFIGURATION: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - /* XXX: could result in alignment problems in some architectures */ - feature = (cdb[2] << 8) | cdb[3]; - max_len = (cdb[7] << 8) | cdb[8]; - - /* only feature 0 is supported */ - if ((cdb[2] != 0) || (cdb[3] > 2)) { - cdrom_invalid_field(id); - cdrom_buf_free(id); - return; - } - - cdrom_buf_alloc(id, 65536); - memset(cdbufferb, 0, max_len); - - alloc_length = 0; - b = cdbufferb; - - /* - * the number of sectors from the media tells us which profile - * to use as current. 0 means there is no media - */ - if (cdrom_drives[id].handler->ready(id)) { - len = cdrom_drives[id].handler->size(id); - if (len > CD_MAX_SECTORS) { - b[6] = (MMC_PROFILE_DVD_ROM >> 8) & 0xff; - b[7] = MMC_PROFILE_DVD_ROM & 0xff; - ret = 1; - } else { - b[6] = (MMC_PROFILE_CD_ROM >> 8) & 0xff; - b[7] = MMC_PROFILE_CD_ROM & 0xff; - ret = 0; - } - } else - ret = 2; - - alloc_length = 8; - b += 8; - - if ((feature == 0) || ((cdb[1] & 3) < 2)) { - b[2] = (0 << 2) | 0x02 | 0x01; /* persistent and current */ - b[3] = 8; - - alloc_length += 4; - b += 4; - - for (i = 0; i < 2; i++) { - b[0] = (profiles[i] >> 8) & 0xff; - b[1] = profiles[i] & 0xff; - - if (ret == i) - b[2] |= 1; - - alloc_length += 4; - b += 4; - } - } - if ((feature == 1) || ((cdb[1] & 3) < 2)) { - b[1] = 1; - b[2] = (2 << 2) | 0x02 | 0x01; /* persistent and current */ - b[3] = 8; - - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - b[7] = 1; - else - b[7] = 2; - b[8] = 1; - - alloc_length += 12; - b += 12; - } - if ((feature == 2) || ((cdb[1] & 3) < 2)) { - b[1] = 2; - b[2] = (1 << 2) | 0x02 | 0x01; /* persistent and current */ - b[3] = 4; - - b[4] = 2; - - alloc_length += 8; - b += 8; - } - - cdbufferb[0] = ((alloc_length - 4) >> 24) & 0xff; - cdbufferb[1] = ((alloc_length - 4) >> 16) & 0xff; - cdbufferb[2] = ((alloc_length - 4) >> 8) & 0xff; - cdbufferb[3] = (alloc_length - 4) & 0xff; - - alloc_length = MIN(alloc_length, max_len); - - cdrom_set_buf_len(id, BufLen, &alloc_length); - - cdrom_data_command_finish(id, alloc_length, alloc_length, alloc_length, 0); - break; - - case GPCMD_GET_EVENT_STATUS_NOTIFICATION: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - cdrom_buf_alloc(id, 8 + sizeof(gesn_event_header)); - - gesn_cdb = (void *) cdb; - gesn_event_header = (void *) cdbufferb; - - /* It is fine by the MMC spec to not support async mode operations. */ - if (!(gesn_cdb->polled & 0x01)) { - /* asynchronous mode */ - /* Only polling is supported, asynchronous mode is not. */ - cdrom_invalid_field(id); - cdrom_buf_free(id); - return; - } - - /* polling mode operation */ - - /* - * These are the supported events. - * - * We currently only support requests of the 'media' type. - * Notification class requests and supported event classes are bitmasks, - * but they are built from the same values as the "notification class" - * field. - */ - gesn_event_header->supported_events = 1 << GESN_MEDIA; - - /* - * We use |= below to set the class field; other bits in this byte - * are reserved now but this is useful to do if we have to use the - * reserved fields later. - */ - gesn_event_header->notification_class = 0; - - /* - * Responses to requests are to be based on request priority. The - * notification_class_request_type enum above specifies the - * priority: upper elements are higher prio than lower ones. - */ - if (gesn_cdb->class & (1 << GESN_MEDIA)) { - gesn_event_header->notification_class |= GESN_MEDIA; - - cdbufferb[4] = dev->media_status; /* Bits 7-4 = Reserved, Bits 4-1 = Media Status */ - cdbufferb[5] = 1; /* Power Status (1 = Active) */ - cdbufferb[6] = 0; - cdbufferb[7] = 0; - used_len = 8; - } else { - gesn_event_header->notification_class = 0x80; /* No event available */ - used_len = sizeof(*gesn_event_header); - } - gesn_event_header->len = used_len - sizeof(*gesn_event_header); - - memcpy(cdbufferb, gesn_event_header, 4); - - cdrom_set_buf_len(id, BufLen, &used_len); - - cdrom_data_command_finish(id, used_len, used_len, used_len, 0); - break; - - case GPCMD_READ_DISC_INFORMATION: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - max_len = cdb[7]; - max_len <<= 8; - max_len |= cdb[8]; - - cdrom_buf_alloc(id, 65536); - - if (cdrom_drives[id].handler->pass_through) { - ret = cdrom_pass_through(id, &len, dev->current_cdb, cdbufferb); - if (!ret) { - cdrom_buf_free(id); - return; - } - alloc_length = cdbufferb[0]; - alloc_length <<= 8; - alloc_length |= cdbufferb[1]; - alloc_length += 2; - len = alloc_length; - } else { - memset(cdbufferb, 0, 34); - memset(cdbufferb, 1, 9); - cdbufferb[0] = 0; - cdbufferb[1] = 32; - cdbufferb[2] = 0xe; /* last session complete, disc finalized */ - cdbufferb[7] = 0x20; /* unrestricted use */ - cdbufferb[8] = 0x00; /* CD-ROM */ - len=34; - } - - len = MIN(len, max_len); - - cdrom_set_buf_len(id, BufLen, &len); - - cdrom_data_command_finish(id, len, len, len, 0); - break; - - case GPCMD_READ_TRACK_INFORMATION: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - max_len = cdb[7]; - max_len <<= 8; - max_len |= cdb[8]; - - cdrom_buf_alloc(id, 65536); - - track = ((uint32_t) cdb[2]) << 24; - track |= ((uint32_t) cdb[3]) << 16; - track |= ((uint32_t) cdb[4]) << 8; - track |= (uint32_t) cdb[5]; - - if (cdrom_drives[id].handler->pass_through) { - ret = cdrom_pass_through(id, &len, dev->current_cdb, cdbufferb); - if (!ret) { - cdrom_buf_free(id); - return; - } - alloc_length = cdbufferb[0]; - alloc_length <<= 8; - alloc_length |= cdbufferb[1]; - alloc_length += 2; - len = MIN(len, alloc_length); - } else { - if (((cdb[1] & 0x03) != 1) || (track != 1)) { - cdrom_invalid_field(id); - cdrom_buf_free(id); - return; - } - - len = 36; - - memset(cdbufferb, 0, 36); - cdbufferb[0] = 0; - cdbufferb[1] = 34; - cdbufferb[2] = 1; /* track number (LSB) */ - cdbufferb[3] = 1; /* session number (LSB) */ - cdbufferb[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */ - cdbufferb[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | (1 << 0); /* not reserved track, not blank, not packet writing, not fixed packet, data mode 1 */ - cdbufferb[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */ - cdbufferb[24] = (cdrom_drives[id].handler->size(id) >> 24) & 0xff; /* track size */ - cdbufferb[25] = (cdrom_drives[id].handler->size(id) >> 16) & 0xff; /* track size */ - cdbufferb[26] = (cdrom_drives[id].handler->size(id) >> 8) & 0xff; /* track size */ - cdbufferb[27] = cdrom_drives[id].handler->size(id) & 0xff; /* track size */ - - if (len > max_len) { - len = max_len; - cdbufferb[0] = ((max_len - 2) >> 8) & 0xff; - cdbufferb[1] = (max_len - 2) & 0xff; - } - } - - cdrom_set_buf_len(id, BufLen, &len); - - cdrom_data_command_finish(id, len, len, max_len, 0); - break; - - case GPCMD_PLAY_AUDIO_10: - case GPCMD_PLAY_AUDIO_12: - case GPCMD_PLAY_AUDIO_MSF: - case GPCMD_PLAY_AUDIO_TRACK_INDEX: - cdrom_set_phase(id, SCSI_PHASE_STATUS); - - switch(cdb[0]) { - case GPCMD_PLAY_AUDIO_10: - msf = 0; - pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - len = (cdb[7] << 8) | cdb[8]; - break; - case GPCMD_PLAY_AUDIO_12: - msf = 0; - pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - len = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - break; - case GPCMD_PLAY_AUDIO_MSF: - /* This is apparently deprecated in the ATAPI spec, and apparently - has been since 1995 (!). Hence I'm having to guess most of it. */ - msf = 1; - pos = (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; - break; - case GPCMD_PLAY_AUDIO_TRACK_INDEX: - msf = 2; - pos = (cdb[4] << 8) | cdb[5]; - len = (cdb[7] << 8) | cdb[8]; - break; - } - - if (!cdrom_drives[id].handler->is_track_audio) - break; - - if ((cdrom_drives[id].host_drive < 1) || (dev->cd_status <= CD_STATUS_DATA_ONLY) || !cdrom_drives[id].handler->is_track_audio(id, pos, msf)) { - cdrom_illegal_mode(id); - break; - } - - if (cdrom_drives[id].handler->playaudio) - cdrom_drives[id].handler->playaudio(id, pos, len, msf); - else { - cdrom_illegal_mode(id); - break; - } - - cdrom_command_complete(id); - break; - - case GPCMD_READ_SUBCHANNEL: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - max_len = cdb[7]; - max_len <<= 8; - max_len |= cdb[8]; - msf = (cdb[1] >> 1) & 1; - - cdrom_buf_alloc(id, 32); - - cdrom_log("CD-ROM %i: Getting page %i (%s)\n", id, cdb[3], msf ? "MSF" : "LBA"); - if ((cdrom_drives[id].handler->pass_through) && (cdb[3] != 1)) { - ret = cdrom_pass_through(id, &len, dev->current_cdb, cdbufferb); - if (!ret) { - cdrom_buf_free(id); - return; - } - switch(dev->cd_status) { - case CD_STATUS_PLAYING: - cdbufferb[1] = 0x11; - break; - case CD_STATUS_PAUSED: - cdbufferb[1] = 0x12; - break; - case CD_STATUS_DATA_ONLY: - cdbufferb[1] = 0x15; - break; - default: - cdbufferb[1] = 0x13; - break; - } - switch(cdb[3]) { - case 0: - alloc_length = 4; - break; - case 1: - alloc_length = 16; - break; - default: - alloc_length = 24; - break; - } - if (!(cdb[2] & 0x40) || (cdb[3] == 0)) - len = 4; - else - len = alloc_length; - } else { - if (cdb[3] > 3) { - /* cdrom_log("CD-ROM %i: Read subchannel check condition %02X\n", id, cdb[3]); */ - cdrom_invalid_field(id); - cdrom_buf_free(id); - return; - } - - switch(cdb[3]) { - case 0: - alloc_length = 4; - break; - case 1: - alloc_length = 16; - break; - default: - alloc_length = 24; - break; - } - - memset(cdbufferb, 0, 24); - pos = 0; - cdbufferb[pos++] = 0; - cdbufferb[pos++] = 0; /*Audio status*/ - cdbufferb[pos++] = 0; cdbufferb[pos++] = 0; /*Subchannel length*/ - cdbufferb[pos++] = cdb[3] & 3; /*Format code*/ - if (cdb[3] == 1) { - cdbufferb[1] = cdrom_drives[id].handler->getcurrentsubchannel(id, &cdbufferb[5], msf); - switch(dev->cd_status) { - case CD_STATUS_PLAYING: - cdbufferb[1] = 0x11; - break; - case CD_STATUS_PAUSED: - cdbufferb[1] = 0x12; - break; - case CD_STATUS_DATA_ONLY: - cdbufferb[1] = 0x15; - break; - default: - cdbufferb[1] = 0x13; - break; - } - } - if (!(cdb[2] & 0x40) || (cdb[3] == 0)) - len = 4; - else - len = alloc_length; - } - - len = MIN(len, max_len); - cdrom_set_buf_len(id, BufLen, &len); - - cdrom_log("CD-ROM %i: Read subchannel:", id); - for (i = 0; i < 32; i += 8) { - cdrom_log("[%02X] %02X %02X %02X %02X %02X %02X %02X %02X\n", i, - cdbufferb[i], cdbufferb[i + 1], cdbufferb[i + 2], cdbufferb[i + 3], - cdbufferb[i + 4], cdbufferb[i + 5], cdbufferb[i + 6], cdbufferb[i + 7]); - } - - cdrom_data_command_finish(id, len, len, len, 0); - break; - - case GPCMD_READ_DVD_STRUCTURE: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - alloc_length = (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - - cdrom_buf_alloc(id, alloc_length); - - if (cdrom_drives[id].handler->pass_through) { - ret = cdrom_pass_through(id, &len, dev->current_cdb, cdbufferb); - if (!ret) { - cdrom_buf_free(id); - return; - } else { - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { - if (*BufLen == -1) - *BufLen = len; - else { - *BufLen = MIN(len, *BufLen); - len = *BufLen; - } - } - } - } else { - len = cdrom_drives[id].handler->size(id); - - if (cdb[7] < 0xc0) { - if (len <= CD_MAX_SECTORS) { - cdrom_incompatible_format(id); - cdrom_buf_free(id); - return; - } - } - - memset(cdbufferb, 0, alloc_length); - - if (((cdb[7] >= 0x00) && (cdb[7] <= 0x7f)) || (cdb[7] == 0xff)) { - if (cdb[1] == 0) { - ret = cdrom_read_dvd_structure(id, format, cdb, cdbufferb); - - if (ret) { - cdrom_set_buf_len(id, BufLen, &alloc_length); - cdrom_data_command_finish(id, alloc_length, alloc_length, len, 0); - } else - cdrom_buf_free(id); - return; - } - } else { - cdrom_invalid_field(id); - cdrom_buf_free(id); - return; - } - } - break; - - case GPCMD_START_STOP_UNIT: - cdrom_set_phase(id, SCSI_PHASE_STATUS); - - switch(cdb[4] & 3) { - case 0: /* Stop the disc. */ - if (cdrom_drives[id].handler->stop) - cdrom_drives[id].handler->stop(id); - break; - case 1: /* Start the disc and read the TOC. */ - cdrom_drives[id].handler->medium_changed(id); /* This causes a TOC reload. */ - break; - case 2: /* Eject the disc if possible. */ - if (cdrom_drives[id].handler->stop) - cdrom_drives[id].handler->stop(id); - cdrom_eject(id); - break; - case 3: /* Load the disc (close tray). */ - cdrom_reload(id); - break; - } - - cdrom_command_complete(id); - break; - - case GPCMD_INQUIRY: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - max_len = cdb[3]; - max_len <<= 8; - max_len |= cdb[4]; - - cdrom_buf_alloc(id, 65536); - - if (cdb[1] & 1) { - preamble_len = 4; - size_idx = 3; - - cdbufferb[idx++] = 05; - cdbufferb[idx++] = cdb[2]; - cdbufferb[idx++] = 0; - - idx++; - - switch (cdb[2]) { - case 0x00: - cdbufferb[idx++] = 0x00; - cdbufferb[idx++] = 0x83; - break; - case 0x83: - if (idx + 24 > max_len) { - cdrom_data_phase_error(id); - cdrom_buf_free(id); - return; - } - - cdbufferb[idx++] = 0x02; - cdbufferb[idx++] = 0x00; - cdbufferb[idx++] = 0x00; - cdbufferb[idx++] = 20; - ide_padstr8(cdbufferb + idx, 20, "53R141"); /* Serial */ - idx += 20; - - if (idx + 72 > cdb[4]) - goto atapi_out; - cdbufferb[idx++] = 0x02; - cdbufferb[idx++] = 0x01; - cdbufferb[idx++] = 0x00; - cdbufferb[idx++] = 68; - ide_padstr8(cdbufferb + idx, 8, EMU_NAME); /* Vendor */ - idx += 8; - ide_padstr8(cdbufferb + idx, 40, device_identify_ex); /* Product */ - idx += 40; - ide_padstr8(cdbufferb + idx, 20, "53R141"); /* Product */ - idx += 20; - break; - default: - cdrom_log("INQUIRY: Invalid page: %02X\n", cdb[2]); - cdrom_invalid_field(id); - cdrom_buf_free(id); - return; - } - } else { - preamble_len = 5; - size_idx = 4; - - memset(cdbufferb, 0, 8); - cdbufferb[0] = 5; /*CD-ROM*/ - cdbufferb[1] = 0x80; /*Removable*/ - cdbufferb[2] = (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ - cdbufferb[3] = (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) ? 0x12 : 0x21; - cdbufferb[4] = 31; - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { - cdbufferb[6] = 1; /* 16-bit transfers supported */ - cdbufferb[7] = 0x20; /* Wide bus supported */ - } - - ide_padstr8(cdbufferb + 8, 8, EMU_NAME); /* Vendor */ - ide_padstr8(cdbufferb + 16, 16, device_identify); /* Product */ - ide_padstr8(cdbufferb + 32, 4, EMU_VERSION); /* Revision */ - idx = 36; - - if (max_len == 96) { - cdbufferb[4] = 91; - idx = 96; - } - } - -atapi_out: - cdbufferb[size_idx] = idx - preamble_len; - len=idx; - - len = MIN(len, max_len); - cdrom_set_buf_len(id, BufLen, &len); - - cdrom_data_command_finish(id, len, len, max_len, 0); - break; - - case GPCMD_PREVENT_REMOVAL: - cdrom_set_phase(id, SCSI_PHASE_STATUS); - cdrom_command_complete(id); - break; - - case GPCMD_PAUSE_RESUME_ALT: - case GPCMD_PAUSE_RESUME: - cdrom_set_phase(id, SCSI_PHASE_STATUS); - - if (cdb[8] & 1) { - if (cdrom_drives[id].handler->resume) - cdrom_drives[id].handler->resume(id); - else { - cdrom_illegal_mode(id); - break; - } - } else { - if (cdrom_drives[id].handler->pause) - cdrom_drives[id].handler->pause(id); - else { - cdrom_illegal_mode(id); - break; - } - } - cdrom_command_complete(id); - break; - - case GPCMD_SEEK_6: - case GPCMD_SEEK_10: - cdrom_set_phase(id, SCSI_PHASE_STATUS); - - switch(cdb[0]) { - case GPCMD_SEEK_6: - pos = (cdb[2] << 8) | cdb[3]; - break; - case GPCMD_SEEK_10: - pos = (cdb[2] << 24) | (cdb[3]<<16) | (cdb[4]<<8) | cdb[5]; - break; - } - dev->seek_diff = ABS((int) (pos - dev->seek_pos)); - cdrom_seek(id, pos); - cdrom_command_complete(id); - break; - - case GPCMD_READ_CDROM_CAPACITY: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - cdrom_buf_alloc(id, 8); - - if (cdrom_read_capacity(id, dev->current_cdb, cdbufferb, &len) == 0) { - cdrom_buf_free(id); - return; - } - - cdrom_set_buf_len(id, BufLen, &len); - - cdrom_data_command_finish(id, len, len, len, 0); - break; - - case GPCMD_STOP_PLAY_SCAN: - cdrom_set_phase(id, SCSI_PHASE_STATUS); - - if (cdrom_drives[id].handler->stop) - cdrom_drives[id].handler->stop(id); - else { - cdrom_illegal_mode(id); - break; - } - cdrom_command_complete(id); - break; - - default: - cdrom_illegal_opcode(id); - break; - } - - /* cdrom_log("CD-ROM %i: Phase: %02X, request length: %i\n", dev->phase, dev->request_length); */ - - if (cdrom_atapi_phase_to_scsi(id) == SCSI_PHASE_STATUS) - cdrom_buf_free(id); -} - -/* The command second phase function, needed for Mode Select. */ -uint8_t cdrom_phase_data_out(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - uint16_t block_desc_len; - uint16_t pos; - - uint8_t error = 0; - uint8_t page, page_len; - - uint16_t i = 0; - - uint8_t hdr_len, val, old_val, ch; - - FILE *f; - - switch(dev->current_cdb[0]) { - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - f = nvr_fopen(L"modeselect.bin", L"wb"); - fwrite(cdbufferb, 1, dev->total_length, f); - fclose(f); - - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) - hdr_len = 8; - else - hdr_len = 4; - - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { - block_desc_len = cdbufferb[2]; - block_desc_len <<= 8; - block_desc_len |= cdbufferb[3]; - } else { - block_desc_len = cdbufferb[6]; - block_desc_len <<= 8; - block_desc_len |= cdbufferb[7]; - } - } else - block_desc_len = 0; - - pos = hdr_len + block_desc_len; - - while(1) { - page = cdbufferb[pos] & 0x3F; - page_len = cdbufferb[pos + 1]; - - pos += 2; - - if (!(cdrom_mode_sense_page_flags & (1LL << ((uint64_t) page)))) { - cdrom_log("Unimplemented page %02X\n", page); - error |= 1; - } else { - for (i = 0; i < page_len; i++) { - ch = cdrom_mode_sense_pages_changeable.pages[page][i + 2]; - val = cdbufferb[pos + i]; - old_val = cdrom_mode_sense_pages_saved[id].pages[page][i + 2]; - if (val != old_val) { - if (ch) - cdrom_mode_sense_pages_saved[id].pages[page][i + 2] = val; - else { - cdrom_log("Unchangeable value on position %02X on page %02X\n", i + 2, page); - error |= 1; - } - } - } - } - - pos += page_len; - - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - val = cdrom_mode_sense_pages_default_scsi.pages[page][0] & 0x80; - else - val = cdrom_mode_sense_pages_default.pages[page][0] & 0x80; - if (dev->do_page_save && val) - cdrom_mode_sense_save(id); - - if (pos >= dev->total_length) - break; - } - - if (error) { - cdrom_invalid_field_pl(id); - return 0; - } - break; - } - + dev->prev_status = dev->cd_status; + dev->cd_status = dev->handler->status(dev->id); + if (((dev->prev_status == CD_STATUS_PLAYING) || (dev->prev_status == CD_STATUS_PAUSED)) && ((dev->cd_status != CD_STATUS_PLAYING) && (dev->cd_status != CD_STATUS_PAUSED))) return 1; -} - -/* This is the general ATAPI PIO request function. */ -void cdrom_pio_request(uint8_t id, uint8_t out) -{ - cdrom_t *dev = cdrom[id]; - - int old_pos = 0; - int ret = 0; - - if (cdrom_drives[id].bus_type < CDROM_BUS_SCSI) { - cdrom_log("CD-ROM %i: Lowering IDE IRQ\n", id); - ide_irq_lower(&(ide_drives[cdrom_drives[id].ide_channel])); - } - - dev->status = BUSY_STAT; - - if (dev->pos >= dev->packet_len) { - cdrom_log("CD-ROM %i: %i bytes %s, command done\n", id, dev->pos, out ? "written" : "read"); - - dev->pos = dev->request_pos = 0; - if (out) { - ret = cdrom_phase_data_out(id); - /* If ret = 0 (phase 1 error), then we do not do anything else other than - free the buffer, as the phase and callback have already been set by the - error function. */ - if (ret) - cdrom_command_complete(id); - } else - cdrom_command_complete(id); - cdrom_buf_free(id); - } else { - cdrom_log("CD-ROM %i: %i bytes %s, %i bytes are still left\n", id, dev->pos, out ? "written" : "read", dev->packet_len - dev->pos); - - /* Make sure to keep pos, and reset request_pos to 0. */ - /* Also make sure to not reset total_read. */ - - /* If less than (packet length) bytes are remaining, update packet length - accordingly. */ - if ((dev->packet_len - dev->pos) < (dev->max_transfer_len)) - dev->max_transfer_len = dev->packet_len - dev->pos; - cdrom_log("CD-ROM %i: Packet length %i, request length %i\n", id, dev->packet_len, dev->max_transfer_len); - - old_pos = dev->pos; - dev->packet_status = out ? CDROM_PHASE_DATA_OUT : CDROM_PHASE_DATA_IN; - cdrom_command_common(id); - dev->pos = old_pos; - - dev->request_pos = 0; - } -} - -void cdrom_phase_callback(uint8_t id); - -int cdrom_read_from_ide_dma(uint8_t channel) -{ - cdrom_t *dev; - - uint8_t id = atapi_cdrom_drives[channel]; - - if (id > CDROM_NUM) - return 0; - - dev = cdrom[id]; - - if (ide_bus_master_write) { - if (ide_bus_master_write(channel >> 1, cdbufferb, dev->packet_len)) - return 0; - else - return 1; - } else - return 0; - + else return 0; } -int cdrom_read_from_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) + +static void +cdrom_request_sense(cdrom_t *dev, uint8_t *buffer, uint8_t alloc_length) { - cdrom_t *dev; + /*Will return 18 bytes of 0*/ + if (alloc_length != 0) { + memset(buffer, 0, alloc_length); + memcpy(buffer, dev->sense, alloc_length); + } - uint8_t id = scsi_cdrom_drives[scsi_id][scsi_lun]; - int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; + buffer[0] = 0x70; - if (id > CDROM_NUM) - return 0; + if ((cdrom_sense_key > 0) && ((dev->cd_status < CD_STATUS_PLAYING) || + (dev->cd_status == CD_STATUS_STOPPED)) && cdrom_playing_completed(dev)) { + buffer[2]=SENSE_ILLEGAL_REQUEST; + buffer[12]=ASC_AUDIO_PLAY_OPERATION; + buffer[13]=ASCQ_AUDIO_PLAY_OPERATION_COMPLETED; + } else if ((cdrom_sense_key == 0) && (dev->cd_status >= CD_STATUS_PLAYING) && + (dev->cd_status != CD_STATUS_STOPPED)) { + buffer[2]=SENSE_ILLEGAL_REQUEST; + buffer[12]=ASC_AUDIO_PLAY_OPERATION; + buffer[13]=(dev->cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; + } else { + if (dev->unit_attention && (cdrom_sense_key == 0)) { + buffer[2]=SENSE_UNIT_ATTENTION; + buffer[12]=ASC_MEDIUM_MAY_HAVE_CHANGED; + buffer[13]=0; + } + } - dev = cdrom[id]; + cdrom_log("CD-ROM %i: Reporting sense: %02X %02X %02X\n", dev->id, buffer[2], buffer[12], buffer[13]); - cdrom_log("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); - memcpy(cdbufferb, SCSIDevices[scsi_id][scsi_lun].CmdBuffer, *BufLen); - return 1; + if (buffer[2] == SENSE_UNIT_ATTENTION) { + /* If the last remaining sense is unit attention, clear + that condition. */ + dev->unit_attention = 0; + } + + /* Clear the sense stuff as per the spec. */ + cdrom_sense_clear(dev, GPCMD_REQUEST_SENSE); } -void cdrom_irq_raise(uint8_t id) + +void +cdrom_request_sense_for_scsi(cdrom_t *dev, uint8_t *buffer, uint8_t alloc_length) { - if (cdrom_drives[id].bus_type < CDROM_BUS_SCSI) - ide_irq_raise(&(ide_drives[cdrom_drives[id].ide_channel])); + int ready = 0; + + if (dev->handler->medium_changed(dev->id)) + cdrom_insert(dev); + + ready = dev->handler->ready(dev->id); + + if (!ready && dev->unit_attention) { + /* If the drive is not ready, there is no reason to keep the + UNIT ATTENTION condition present, as we only use it to mark + disc changes. */ + dev->unit_attention = 0; + } + + /* Do *NOT* advance the unit attention phase. */ + cdrom_request_sense(dev, buffer, alloc_length); } -int cdrom_read_from_dma(uint8_t id) + +static void +cdrom_set_buf_len(cdrom_t *dev, int32_t *BufLen, int32_t *src_len) { - cdrom_t *dev = cdrom[id]; - - int32_t *BufLen = &SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].BufferLength; - int ret = 0; - - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - ret = cdrom_read_from_scsi_dma(cdrom_drives[id].scsi_device_id, cdrom_drives[id].scsi_device_lun); - else - ret = cdrom_read_from_ide_dma(cdrom_drives[id].ide_channel); - - if (!ret) - return 0; - - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - cdrom_log("CD-ROM %i: SCSI Input data length: %i\n", id, *BufLen); - else - cdrom_log("CD-ROM %i: ATAPI Input data length: %i\n", id, dev->packet_len); - - ret = cdrom_phase_data_out(id); - - if (ret) - return 1; - else - return 0; + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + if (*BufLen == -1) + *BufLen = *src_len; + else { + *BufLen = MIN(*src_len, *BufLen); + *src_len = *BufLen; + } + cdrom_log("CD-ROM %i: Actual transfer length: %i\n", dev->id, *BufLen); + } } -int cdrom_write_to_ide_dma(uint8_t channel) + +static void +cdrom_buf_alloc(cdrom_t *dev, uint32_t len) { - cdrom_t *dev; + cdrom_log("CD-ROM %i: Allocated buffer length: %i\n", dev->id, len); + cdbufferb = (uint8_t *) malloc(len); +} - uint8_t id = atapi_cdrom_drives[channel]; - if (id > CDROM_NUM) - return 0; +static void +cdrom_buf_free(cdrom_t *dev) +{ + if (cdbufferb) { + cdrom_log("CD-ROM %i: Freeing buffer...\n", dev->id); + free(cdbufferb); + cdbufferb = NULL; + } +} - dev = cdrom[id]; - if (ide_bus_master_read) { - if (ide_bus_master_read(channel >> 1, cdbufferb, dev->packet_len)) - return 0; +void +cdrom_command(cdrom_t *dev, uint8_t *cdb) +{ + int len, max_len, used_len, alloc_length, msf; + int pos = 0, i= 0, size_idx, idx = 0; + uint32_t feature; + unsigned preamble_len; + int toc_format, block_desc = 0; + int ret, format = 0; + int real_pos, track = 0; + char device_identify[9] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', 0 }; + char device_identify_ex[15] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; + int32_t blen = 0, *BufLen; + uint8_t *b; + uint32_t profiles[2] = { MMC_PROFILE_CD_ROM, MMC_PROFILE_DVD_ROM }; + + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + BufLen = &SCSIDevices[dev->drv->scsi_device_id].BufferLength; + dev->status &= ~ERR_STAT; + } else { + BufLen = &blen; + dev->error = 0; + } + + dev->packet_len = 0; + dev->request_pos = 0; + + device_identify[7] = dev->id + 0x30; + + device_identify_ex[7] = dev->id + 0x30; + device_identify_ex[10] = EMU_VERSION[0]; + device_identify_ex[12] = EMU_VERSION[2]; + device_identify_ex[13] = EMU_VERSION[3]; + + dev->data_pos = 0; + + memcpy(dev->current_cdb, cdb, dev->cdb_len); + + dev->cd_status = dev->handler->status(dev->id); + + if (cdb[0] != 0) { + cdrom_log("CD-ROM %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", + dev->id, cdb[0], cdrom_sense_key, cdrom_asc, cdrom_ascq, dev->unit_attention); + cdrom_log("CD-ROM %i: Request length: %04X\n", dev->id, dev->request_length); + + cdrom_log("CD-ROM %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, + cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], + cdb[8], cdb[9], cdb[10], cdb[11]); + } + + msf = cdb[1] & 2; + dev->sector_len = 0; + + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ + if (cdrom_pre_execution_check(dev, cdb) == 0) + return; + + switch (cdb[0]) { + case GPCMD_TEST_UNIT_READY: + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + cdrom_command_complete(dev); + break; + + case GPCMD_REZERO_UNIT: + if (dev->handler->stop) + dev->handler->stop(dev->id); + dev->sector_pos = dev->sector_len = 0; + dev->seek_diff = dev->seek_pos; + cdrom_seek(dev, 0); + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + break; + + case GPCMD_REQUEST_SENSE: + /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE + should forget about the not ready, and report unit attention straight away. */ + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + max_len = cdb[4]; + cdrom_buf_alloc(dev, 256); + cdrom_set_buf_len(dev, BufLen, &max_len); + cdrom_request_sense(dev, cdbufferb, max_len); + cdrom_data_command_finish(dev, 18, 18, cdb[4], 0); + break; + + case GPCMD_SET_SPEED: + case GPCMD_SET_SPEED_ALT: + dev->cur_speed = (cdb[3] | (cdb[2] << 8)) / 176; + if (dev->cur_speed < 1) + dev->cur_speed = 1; + else if (dev->cur_speed > dev->drv->speed) + dev->cur_speed = dev->drv->speed; + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + cdrom_command_complete(dev); + break; + + case GPCMD_MECHANISM_STATUS: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; + + cdrom_buf_alloc(dev, 8); + + cdrom_set_buf_len(dev, BufLen, &len); + + memset(cdbufferb, 0, 8); + cdbufferb[5] = 1; + + cdrom_data_command_finish(dev, 8, 8, len, 0); + break; + + case GPCMD_READ_TOC_PMA_ATIP: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + + cdrom_buf_alloc(dev, 65536); + + toc_format = cdb[2] & 0xf; + + if (toc_format == 0) + toc_format = (cdb[9] >> 6) & 3; + + switch (toc_format) { + case 0: /*Normal*/ + len = dev->handler->readtoc(dev->id, cdbufferb, cdb[6], msf, max_len, + 0); + break; + case 1: /*Multi session*/ + len = dev->handler->readtoc_session(dev->id, cdbufferb, msf, max_len); + cdbufferb[0] = 0; cdbufferb[1] = 0xA; + break; + case 2: /*Raw*/ + len = dev->handler->readtoc_raw(dev->id, cdbufferb, max_len); + break; + default: + cdrom_invalid_field(dev); + cdrom_buf_free(dev); + return; + } + + if (len > max_len) { + len = max_len; + + cdbufferb[0] = ((len - 2) >> 8) & 0xff; + cdbufferb[1] = (len - 2) & 0xff; + } + + cdrom_set_buf_len(dev, BufLen, &len); + + if (len >= 8) { + cdrom_log("CD-ROM %i: TOC: %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, + cdbufferb[0], cdbufferb[1], cdbufferb[2], cdbufferb[3], + cdbufferb[4], cdbufferb[5], cdbufferb[6], cdbufferb[7]); + } + + if (len >= 16) { + cdrom_log(" %02X %02X %02X %02X %02X %02X %02X %02X\n", + cdbufferb[8], cdbufferb[9], cdbufferb[10], cdbufferb[11], + cdbufferb[12], cdbufferb[13], cdbufferb[14], cdbufferb[15]); + } + + if (len >= 24) { + cdrom_log(" %02X %02X %02X %02X %02X %02X %02X %02X\n", + cdbufferb[16], cdbufferb[17], cdbufferb[18], cdbufferb[19], + cdbufferb[20], cdbufferb[21], cdbufferb[22], cdbufferb[23]); + } + + if (len >= 32) { + cdrom_log(" %02X %02X %02X %02X %02X %02X %02X %02X\n", + cdbufferb[24], cdbufferb[25], cdbufferb[26], cdbufferb[27], + cdbufferb[28], cdbufferb[29], cdbufferb[30], cdbufferb[31]); + } + + if (len >= 36) { + cdrom_log(" %02X %02X %02X %02X\n", + cdbufferb[32], cdbufferb[33], cdbufferb[34], cdbufferb[35]); + } + + cdrom_data_command_finish(dev, len, len, len, 0); + /* cdrom_log("CD-ROM %i: READ_TOC_PMA_ATIP format %02X, length %i (%i)\n", dev->id, + toc_format, ide->cylinder, cdbufferb[1]); */ + return; + + case GPCMD_READ_CD_OLD: + /* IMPORTANT: Convert the command to new read CD + for pass through purposes. */ + dev->current_cdb[0] = 0xbe; + case GPCMD_READ_6: + case GPCMD_READ_10: + case GPCMD_READ_12: + case GPCMD_READ_CD: + case GPCMD_READ_CD_MSF: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + alloc_length = 2048; + + switch(cdb[0]) { + case GPCMD_READ_6: + dev->sector_len = cdb[4]; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + msf = 0; + break; + case GPCMD_READ_10: + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + cdrom_log("CD-ROM %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, + dev->sector_pos); + msf = 0; + break; + case GPCMD_READ_12: + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + cdrom_log("CD-ROM %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, + dev->sector_pos); + msf = 0; + break; + case GPCMD_READ_CD_MSF: + alloc_length = 2856; + dev->sector_len = MSFtoLBA(cdb[6], cdb[7], cdb[8]); + dev->sector_pos = MSFtoLBA(cdb[3], cdb[4], cdb[5]); + + dev->sector_len -= dev->sector_pos; + dev->sector_len++; + msf = 1; + break; + case GPCMD_READ_CD_OLD: + case GPCMD_READ_CD: + alloc_length = 2856; + dev->sector_len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + + msf = 0; + break; + } + + dev->seek_diff = ABS((int) (pos - dev->seek_pos)); + dev->seek_pos = dev->sector_pos; + + if (!dev->sector_len) { + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + /* cdrom_log("CD-ROM %i: All done - callback set\n", dev->id); */ + dev->packet_status = CDROM_PHASE_COMPLETE; + dev->callback = 20LL * CDROM_TIME; + cdrom_set_callback(dev); + break; + } + + max_len = dev->sector_len; + dev->requested_blocks = max_len; /* If we're reading all blocks in one go for DMA, why not also for PIO, it should NOT + matter anyway, this step should be identical and only the way the read dat is + transferred to the host should be different. */ + + dev->packet_len = max_len * alloc_length; + cdrom_buf_alloc(dev, dev->packet_len); + + ret = cdrom_read_blocks(dev, &alloc_length, 1); + if (ret <= 0) { + cdrom_buf_free(dev); + return; + } + + dev->requested_blocks = max_len; + dev->packet_len = alloc_length; + + cdrom_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); + + cdrom_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, + alloc_length, 0); + + dev->all_blocks_total = dev->block_total; + if (dev->packet_status != CDROM_PHASE_COMPLETE) + ui_sb_update_icon(SB_CDROM | dev->id, 1); else - return 1; - } else - return 0; -} + ui_sb_update_icon(SB_CDROM | dev->id, 0); + return; -int cdrom_write_to_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) -{ - cdrom_t *dev; + case GPCMD_READ_HEADER: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - uint8_t id = scsi_cdrom_drives[scsi_id][scsi_lun]; - int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; + alloc_length = ((cdb[7] << 8) | cdb[8]); + cdrom_buf_alloc(dev, 8); - if (id > CDROM_NUM) - return 0; + dev->sector_len = 1; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4]<<8) | cdb[5]; + if (msf) + real_pos = cdrom_lba_to_msf_accurate(dev->sector_pos); + else + real_pos = dev->sector_pos; + cdbufferb[0] = 1; /*2048 bytes user data*/ + cdbufferb[1] = cdbufferb[2] = cdbufferb[3] = 0; + cdbufferb[4] = (real_pos >> 24); + cdbufferb[5] = ((real_pos >> 16) & 0xff); + cdbufferb[6] = ((real_pos >> 8) & 0xff); + cdbufferb[7] = real_pos & 0xff; - dev = cdrom[id]; + len = 8; + len = MIN(len, alloc_length); - cdrom_log("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); - memcpy(SCSIDevices[scsi_id][scsi_lun].CmdBuffer, cdbufferb, *BufLen); - cdrom_log("CD-ROM %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, cdbufferb[0], cdbufferb[1], cdbufferb[2], cdbufferb[3], cdbufferb[4], cdbufferb[5], cdbufferb[6], cdbufferb[7]); - cdrom_log("CD-ROM %i: Data from SCSI DMA : %02X %02X %02X %02X %02X %02X %02X %02X\n", id, SCSIDevices[scsi_id][scsi_lun].CmdBuffer[0], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[1], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[2], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[3], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[4], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[5], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[6], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[7]); - return 1; -} + cdrom_set_buf_len(dev, BufLen, &len); -int cdrom_write_to_dma(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; + cdrom_data_command_finish(dev, len, len, len, 0); + return; - int32_t *BufLen = &SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].BufferLength; - int ret = 0; + case GPCMD_MODE_SENSE_6: + case GPCMD_MODE_SENSE_10: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { - cdrom_log("Write to SCSI DMA: (%02X:%02X)\n", cdrom_drives[id].scsi_device_id, cdrom_drives[id].scsi_device_lun); - ret = cdrom_write_to_scsi_dma(cdrom_drives[id].scsi_device_id, cdrom_drives[id].scsi_device_lun); - } else - ret = cdrom_write_to_ide_dma(cdrom_drives[id].ide_channel); + if (dev->drv->bus_type == CDROM_BUS_SCSI) + block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; + else + block_desc = 0; - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - cdrom_log("CD-ROM %i: SCSI Output data length: %i\n", id, *BufLen); - else - cdrom_log("CD-ROM %i: ATAPI Output data length: %i\n", id, dev->packet_len); + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = cdb[4]; + cdrom_buf_alloc(dev, 256); + } else { + len = (cdb[8] | (cdb[7] << 8)); + cdrom_buf_alloc(dev, 65536); + } - if (ret) - return 1; - else - return 0; -} + dev->current_page_code = cdb[2] & 0x3F; -/* If the result is 1, issue an IRQ, otherwise not. */ -void cdrom_phase_callback(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - int ret; - - switch(dev->packet_status) { - case CDROM_PHASE_IDLE: - cdrom_log("CD-ROM %i: CDROM_PHASE_IDLE\n", id); - dev->pos=0; - dev->phase = 1; - dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); + if (!(cdrom_mode_sense_page_flags & (1LL << dev->current_page_code))) { + cdrom_invalid_field(dev); + cdrom_buf_free(dev); return; - case CDROM_PHASE_COMMAND: - cdrom_log("CD-ROM %i: CDROM_PHASE_COMMAND\n", id); - dev->status = BUSY_STAT | (dev->status &ERR_STAT); - memcpy(dev->atapi_cdb, cdbufferb, dev->cdb_len); - cdrom_command(id, dev->atapi_cdb); - return; - case CDROM_PHASE_COMPLETE: - cdrom_log("CD-ROM %i: CDROM_PHASE_COMPLETE\n", id); - dev->status = READY_STAT; - dev->phase = 3; - dev->packet_status = 0xFF; - ui_sb_update_icon(SB_CDROM | id, 0); - cdrom_irq_raise(id); - return; - case CDROM_PHASE_DATA_OUT: - cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_OUT\n", id); - dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); - dev->phase = 0; - cdrom_irq_raise(id); - return; - case CDROM_PHASE_DATA_OUT_DMA: - cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_OUT_DMA\n", id); - ret = cdrom_read_from_dma(id); - cdrom_command_complete(id); + } - if (ret || (cdrom_drives[id].bus_type == CDROM_BUS_SCSI)) { - cdrom_log("CD-ROM %i: DMA data out phase done\n"); - cdrom_buf_free(id); - cdrom_command_complete(id); - } else { - cdrom_log("CD-ROM %i: DMA data out phase failure\n"); - cdrom_command_bus(id); + memset(cdbufferb, 0, len); + alloc_length = len; + + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = cdrom_mode_sense(dev, cdbufferb, 4, cdb[2], block_desc); + len = MIN(len, alloc_length); + cdbufferb[0] = len - 1; + cdbufferb[1] = dev->handler->media_type_id(dev->id); + if (block_desc) + cdbufferb[3] = 8; + } else { + len = cdrom_mode_sense(dev, cdbufferb, 8, cdb[2], block_desc); + len = MIN(len, alloc_length); + cdbufferb[0]=(len - 2) >> 8; + cdbufferb[1]=(len - 2) & 255; + cdbufferb[2] = dev->handler->media_type_id(dev->id); + if (block_desc) { + cdbufferb[6] = 0; + cdbufferb[7] = 8; } - return; - case CDROM_PHASE_DATA_IN: - cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_IN\n", id); - dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); - dev->phase = 2; - cdrom_irq_raise(id); - return; - case CDROM_PHASE_DATA_IN_DMA: - cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_IN_DMA\n", id); - ret = cdrom_write_to_dma(id); + } - if (ret || (cdrom_drives[id].bus_type == CDROM_BUS_SCSI)) { - cdrom_log("CD-ROM %i: DMA data in phase done\n"); - cdrom_buf_free(id); - cdrom_command_complete(id); + cdrom_set_buf_len(dev, BufLen, &len); + + cdrom_log("CD-ROM %i: Reading mode page: %02X...\n", dev->id, cdb[2]); + + cdrom_data_command_finish(dev, len, len, alloc_length, 0); + return; + + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + cdrom_set_phase(dev, SCSI_PHASE_DATA_OUT); + + if (cdb[0] == GPCMD_MODE_SELECT_6) { + len = cdb[4]; + cdrom_buf_alloc(dev, 256); + } else { + len = (cdb[7] << 8) | cdb[8]; + cdrom_buf_alloc(dev, 65536); + } + + cdrom_set_buf_len(dev, BufLen, &len); + + dev->total_length = len; + dev->do_page_save = cdb[1] & 1; + + dev->current_page_pos = 0; + + cdrom_data_command_finish(dev, len, len, len, 1); + return; + + case GPCMD_GET_CONFIGURATION: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + /* XXX: could result in alignment problems in some architectures */ + feature = (cdb[2] << 8) | cdb[3]; + max_len = (cdb[7] << 8) | cdb[8]; + + /* only feature 0 is supported */ + if ((cdb[2] != 0) || (cdb[3] > 2)) { + cdrom_invalid_field(dev); + cdrom_buf_free(dev); + return; + } + + cdrom_buf_alloc(dev, 65536); + memset(cdbufferb, 0, max_len); + + alloc_length = 0; + b = cdbufferb; + + /* + * the number of sectors from the media tells us which profile + * to use as current. 0 means there is no media + */ + if (dev->handler->ready(dev->id)) { + len = dev->handler->size(dev->id); + if (len > CD_MAX_SECTORS) { + b[6] = (MMC_PROFILE_DVD_ROM >> 8) & 0xff; + b[7] = MMC_PROFILE_DVD_ROM & 0xff; + ret = 1; } else { - cdrom_log("CD-ROM %i: DMA data in phase failure\n"); - cdrom_command_bus(id); + b[6] = (MMC_PROFILE_CD_ROM >> 8) & 0xff; + b[7] = MMC_PROFILE_CD_ROM & 0xff; + ret = 0; } + } else + ret = 2; + + alloc_length = 8; + b += 8; + + if ((feature == 0) || ((cdb[1] & 3) < 2)) { + b[2] = (0 << 2) | 0x02 | 0x01; /* persistent and current */ + b[3] = 8; + + alloc_length += 4; + b += 4; + + for (i = 0; i < 2; i++) { + b[0] = (profiles[i] >> 8) & 0xff; + b[1] = profiles[i] & 0xff; + + if (ret == i) + b[2] |= 1; + + alloc_length += 4; + b += 4; + } + } + if ((feature == 1) || ((cdb[1] & 3) < 2)) { + b[1] = 1; + b[2] = (2 << 2) | 0x02 | 0x01; /* persistent and current */ + b[3] = 8; + + if (dev->drv->bus_type == CDROM_BUS_SCSI) + b[7] = 1; + else + b[7] = 2; + b[8] = 1; + + alloc_length += 12; + b += 12; + } + if ((feature == 2) || ((cdb[1] & 3) < 2)) { + b[1] = 2; + b[2] = (1 << 2) | 0x02 | 0x01; /* persistent and current */ + b[3] = 4; + + b[4] = 2; + + alloc_length += 8; + b += 8; + } + + cdbufferb[0] = ((alloc_length - 4) >> 24) & 0xff; + cdbufferb[1] = ((alloc_length - 4) >> 16) & 0xff; + cdbufferb[2] = ((alloc_length - 4) >> 8) & 0xff; + cdbufferb[3] = (alloc_length - 4) & 0xff; + + alloc_length = MIN(alloc_length, max_len); + + cdrom_set_buf_len(dev, BufLen, &alloc_length); + + cdrom_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 0); + break; + + case GPCMD_GET_EVENT_STATUS_NOTIFICATION: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + cdrom_buf_alloc(dev, 8 + sizeof(gesn_event_header)); + + gesn_cdb = (void *) cdb; + gesn_event_header = (void *) cdbufferb; + + /* It is fine by the MMC spec to not support async mode operations. */ + if (!(gesn_cdb->polled & 0x01)) { + /* asynchronous mode */ + /* Only polling is supported, asynchronous mode is not. */ + cdrom_invalid_field(dev); + cdrom_buf_free(dev); return; - case CDROM_PHASE_ERROR: - cdrom_log("CD-ROM %i: CDROM_PHASE_ERROR\n", id); - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - cdrom_irq_raise(id); - ui_sb_update_icon(SB_CDROM | id, 0); + } + + /* + * These are the supported events. + * + * We currently only support requests of the 'media' type. + * Notification class requests and supported event classes are bitmasks, + * but they are built from the same values as the "notification class" + * field. + */ + gesn_event_header->supported_events = 1 << GESN_MEDIA; + + /* + * We use |= below to set the class field; other bits in this byte + * are reserved now but this is useful to do if we have to use the + * reserved fields later. + */ + gesn_event_header->notification_class = 0; + + /* + * Responses to requests are to be based on request priority. The + * notification_class_request_type enum above specifies the + * priority: upper elements are higher prio than lower ones. + */ + if (gesn_cdb->class & (1 << GESN_MEDIA)) { + gesn_event_header->notification_class |= GESN_MEDIA; + + cdbufferb[4] = dev->media_status; /* Bits 7-4 = Reserved, Bits 4-1 = Media Status */ + cdbufferb[5] = 1; /* Power Status (1 = Active) */ + cdbufferb[6] = 0; + cdbufferb[7] = 0; + used_len = 8; + } else { + gesn_event_header->notification_class = 0x80; /* No event available */ + used_len = sizeof(*gesn_event_header); + } + gesn_event_header->len = used_len - sizeof(*gesn_event_header); + + memcpy(cdbufferb, gesn_event_header, 4); + + cdrom_set_buf_len(dev, BufLen, &used_len); + + cdrom_data_command_finish(dev, used_len, used_len, used_len, 0); + break; + + case GPCMD_READ_DISC_INFORMATION: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + + cdrom_buf_alloc(dev, 65536); + + memset(cdbufferb, 0, 34); + memset(cdbufferb, 1, 9); + cdbufferb[0] = 0; + cdbufferb[1] = 32; + cdbufferb[2] = 0xe; /* last session complete, disc finalized */ + cdbufferb[7] = 0x20; /* unrestricted use */ + cdbufferb[8] = 0x00; /* CD-ROM */ + + len=34; + len = MIN(len, max_len); + + cdrom_set_buf_len(dev, BufLen, &len); + + cdrom_data_command_finish(dev, len, len, len, 0); + break; + + case GPCMD_READ_TRACK_INFORMATION: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + + cdrom_buf_alloc(dev, 65536); + + track = ((uint32_t) cdb[2]) << 24; + track |= ((uint32_t) cdb[3]) << 16; + track |= ((uint32_t) cdb[4]) << 8; + track |= (uint32_t) cdb[5]; + + if (((cdb[1] & 0x03) != 1) || (track != 1)) { + cdrom_invalid_field(dev); + cdrom_buf_free(dev); return; - } + } + + len = 36; + + memset(cdbufferb, 0, 36); + cdbufferb[0] = 0; + cdbufferb[1] = 34; + cdbufferb[2] = 1; /* track number (LSB) */ + cdbufferb[3] = 1; /* session number (LSB) */ + cdbufferb[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */ + cdbufferb[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | (1 << 0); /* not reserved track, not blank, not packet writing, not fixed packet, data mode 1 */ + cdbufferb[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */ + cdbufferb[24] = (dev->handler->size(dev->id) >> 24) & 0xff; /* track size */ + cdbufferb[25] = (dev->handler->size(dev->id) >> 16) & 0xff; /* track size */ + cdbufferb[26] = (dev->handler->size(dev->id) >> 8) & 0xff; /* track size */ + cdbufferb[27] = dev->handler->size(dev->id) & 0xff; /* track size */ + + if (len > max_len) { + len = max_len; + cdbufferb[0] = ((max_len - 2) >> 8) & 0xff; + cdbufferb[1] = (max_len - 2) & 0xff; + } + + cdrom_set_buf_len(dev, BufLen, &len); + + cdrom_data_command_finish(dev, len, len, max_len, 0); + break; + + case GPCMD_PLAY_AUDIO_10: + case GPCMD_PLAY_AUDIO_12: + case GPCMD_PLAY_AUDIO_MSF: + case GPCMD_PLAY_AUDIO_TRACK_INDEX: + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + switch(cdb[0]) { + case GPCMD_PLAY_AUDIO_10: + msf = 0; + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + len = (cdb[7] << 8) | cdb[8]; + break; + case GPCMD_PLAY_AUDIO_12: + msf = 0; + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + len = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; + break; + case GPCMD_PLAY_AUDIO_MSF: + /* This is apparently deprecated in the ATAPI spec, and apparently + has been since 1995 (!). Hence I'm having to guess most of it. */ + msf = 1; + pos = (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; + break; + case GPCMD_PLAY_AUDIO_TRACK_INDEX: + msf = 2; + pos = (cdb[4] << 8) | cdb[5]; + len = (cdb[7] << 8) | cdb[8]; + break; + } + + if ((dev->drv->host_drive < 1) || (dev->cd_status <= CD_STATUS_DATA_ONLY)) { + cdrom_illegal_mode(dev); + break; + } + + if (dev->handler->playaudio) + ret = dev->handler->playaudio(dev->id, pos, len, msf); + else + ret = 0; + + if (ret) + cdrom_command_complete(dev); + else + cdrom_illegal_mode(dev); + break; + + case GPCMD_READ_SUBCHANNEL: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + msf = (cdb[1] >> 1) & 1; + + cdrom_buf_alloc(dev, 32); + + cdrom_log("CD-ROM %i: Getting page %i (%s)\n", dev->id, cdb[3], msf ? "MSF" : "LBA"); + + if (cdb[3] > 3) { + /* cdrom_log("CD-ROM %i: Read subchannel check condition %02X\n", dev->id, + cdb[3]); */ + cdrom_invalid_field(dev); + cdrom_buf_free(dev); + return; + } + + switch(cdb[3]) { + case 0: + alloc_length = 4; + break; + case 1: + alloc_length = 16; + break; + default: + alloc_length = 24; + break; + } + + memset(cdbufferb, 0, 24); + pos = 0; + cdbufferb[pos++] = 0; + cdbufferb[pos++] = 0; /*Audio status*/ + cdbufferb[pos++] = 0; cdbufferb[pos++] = 0; /*Subchannel length*/ + cdbufferb[pos++] = cdb[3] & 3; /*Format code*/ + if (cdb[3] == 1) { + cdbufferb[1] = dev->handler->getcurrentsubchannel(dev->id, &cdbufferb[5], msf); + switch(dev->cd_status) { + case CD_STATUS_PLAYING: + cdbufferb[1] = 0x11; + break; + case CD_STATUS_PAUSED: + cdbufferb[1] = 0x12; + break; + case CD_STATUS_DATA_ONLY: + cdbufferb[1] = 0x15; + break; + default: + cdbufferb[1] = 0x13; + break; + } + } + + if (!(cdb[2] & 0x40) || (cdb[3] == 0)) + len = 4; + else + len = alloc_length; + + len = MIN(len, max_len); + cdrom_set_buf_len(dev, BufLen, &len); + + cdrom_log("CD-ROM %i: Read subchannel:", dev->id); + for (i = 0; i < 32; i += 8) { + cdrom_log("[%02X] %02X %02X %02X %02X %02X %02X %02X %02X\n", i, + cdbufferb[i], cdbufferb[i + 1], cdbufferb[i + 2], cdbufferb[i + 3], + cdbufferb[i + 4], cdbufferb[i + 5], cdbufferb[i + 6], cdbufferb[i + 7]); + } + + cdrom_data_command_finish(dev, len, len, len, 0); + break; + + case GPCMD_READ_DVD_STRUCTURE: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + alloc_length = (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + + cdrom_buf_alloc(dev, alloc_length); + + len = dev->handler->size(dev->id); + + if ((cdb[7] < 0xc0) && (len <= CD_MAX_SECTORS)) { + cdrom_incompatible_format(dev); + cdrom_buf_free(dev); + return; + } + + memset(cdbufferb, 0, alloc_length); + + if ((cdb[7] <= 0x7f) || (cdb[7] == 0xff)) { + if (cdb[1] == 0) { + ret = cdrom_read_dvd_structure(dev, format, cdb, cdbufferb); + if (ret) { + cdrom_set_buf_len(dev, BufLen, &alloc_length); + cdrom_data_command_finish(dev, alloc_length, alloc_length, + len, 0); + } else + cdrom_buf_free(dev); + return; + } + } else { + cdrom_invalid_field(dev); + cdrom_buf_free(dev); + return; + } + break; + + case GPCMD_START_STOP_UNIT: + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + switch(cdb[4] & 3) { + case 0: /* Stop the disc. */ + if (dev->handler->stop) + dev->handler->stop(dev->id); + break; + case 1: /* Start the disc and read the TOC. */ + dev->handler->medium_changed(dev->id); /* This causes a TOC reload. */ + break; + case 2: /* Eject the disc if possible. */ + if (dev->handler->stop) + dev->handler->stop(dev->id); + cdrom_eject(dev->id); + break; + case 3: /* Load the disc (close tray). */ + cdrom_reload(dev->id); + break; + } + + cdrom_command_complete(dev); + break; + + case GPCMD_INQUIRY: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[3]; + max_len <<= 8; + max_len |= cdb[4]; + + cdrom_buf_alloc(dev, 65536); + + if (cdb[1] & 1) { + preamble_len = 4; + size_idx = 3; + + cdbufferb[idx++] = 05; + cdbufferb[idx++] = cdb[2]; + cdbufferb[idx++] = 0; + + idx++; + + switch (cdb[2]) { + case 0x00: + cdbufferb[idx++] = 0x00; + cdbufferb[idx++] = 0x83; + break; + case 0x83: + if (idx + 24 > max_len) { + cdrom_data_phase_error(dev); + cdrom_buf_free(dev); + return; + } + + cdbufferb[idx++] = 0x02; + cdbufferb[idx++] = 0x00; + cdbufferb[idx++] = 0x00; + cdbufferb[idx++] = 20; + ide_padstr8(cdbufferb + idx, 20, "53R141"); /* Serial */ + idx += 20; + + if (idx + 72 > cdb[4]) + goto atapi_out; + cdbufferb[idx++] = 0x02; + cdbufferb[idx++] = 0x01; + cdbufferb[idx++] = 0x00; + cdbufferb[idx++] = 68; + ide_padstr8(cdbufferb + idx, 8, EMU_NAME); /* Vendor */ + idx += 8; + ide_padstr8(cdbufferb + idx, 40, device_identify_ex); /* Product */ + idx += 40; + ide_padstr8(cdbufferb + idx, 20, "53R141"); /* Product */ + idx += 20; + break; + default: + cdrom_log("INQUIRY: Invalid page: %02X\n", cdb[2]); + cdrom_invalid_field(dev); + cdrom_buf_free(dev); + return; + } + } else { + preamble_len = 5; + size_idx = 4; + + memset(cdbufferb, 0, 8); + cdbufferb[0] = 5; /*CD-ROM*/ + cdbufferb[1] = 0x80; /*Removable*/ + cdbufferb[2] = (dev->drv->bus_type == CDROM_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ + cdbufferb[3] = (dev->drv->bus_type == CDROM_BUS_SCSI) ? 0x12 : 0x21; + cdbufferb[4] = 31; + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + cdbufferb[6] = 1; /* 16-bit transfers supported */ + cdbufferb[7] = 0x20; /* Wide bus supported */ + } + + ide_padstr8(cdbufferb + 8, 8, EMU_NAME); /* Vendor */ + ide_padstr8(cdbufferb + 16, 16, device_identify); /* Product */ + ide_padstr8(cdbufferb + 32, 4, EMU_VERSION); /* Revision */ + idx = 36; + + if (max_len == 96) { + cdbufferb[4] = 91; + idx = 96; + } + } + +atapi_out: + cdbufferb[size_idx] = idx - preamble_len; + len=idx; + + len = MIN(len, max_len); + cdrom_set_buf_len(dev, BufLen, &len); + + cdrom_data_command_finish(dev, len, len, max_len, 0); + break; + + case GPCMD_PREVENT_REMOVAL: + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + cdrom_command_complete(dev); + break; + + case GPCMD_PAUSE_RESUME_ALT: + case GPCMD_PAUSE_RESUME: + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + if (cdb[8] & 1) { + if (dev->handler->resume) + dev->handler->resume(dev->id); + else { + cdrom_illegal_mode(dev); + break; + } + } else { + if (dev->handler->pause) + dev->handler->pause(dev->id); + else { + cdrom_illegal_mode(dev); + break; + } + } + cdrom_command_complete(dev); + break; + + case GPCMD_SEEK_6: + case GPCMD_SEEK_10: + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + switch(cdb[0]) { + case GPCMD_SEEK_6: + pos = (cdb[2] << 8) | cdb[3]; + break; + case GPCMD_SEEK_10: + pos = (cdb[2] << 24) | (cdb[3]<<16) | (cdb[4]<<8) | cdb[5]; + break; + } + dev->seek_diff = ABS((int) (pos - dev->seek_pos)); + cdrom_seek(dev, pos); + cdrom_command_complete(dev); + break; + + case GPCMD_READ_CDROM_CAPACITY: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + cdrom_buf_alloc(dev, 8); + + if (cdrom_read_capacity(dev, dev->current_cdb, cdbufferb, (uint32_t *) &len) == 0) { + cdrom_buf_free(dev); + return; + } + + cdrom_set_buf_len(dev, BufLen, &len); + + cdrom_data_command_finish(dev, len, len, len, 0); + break; + + case GPCMD_STOP_PLAY_SCAN: + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + if (dev->handler->stop) + dev->handler->stop(dev->id); + else { + cdrom_illegal_mode(dev); + break; + } + cdrom_command_complete(dev); + break; + + default: + cdrom_illegal_opcode(dev); + break; + } + + /* cdrom_log("CD-ROM %i: Phase: %02X, request length: %i\n", dev->phase, dev->request_length); */ + + if (cdrom_atapi_phase_to_scsi(dev) == SCSI_PHASE_STATUS) + cdrom_buf_free(dev); } -/* Reimplement as 8-bit due to reimplementation of IDE data read and write. */ -uint32_t cdrom_read(uint8_t channel, int length) + +/* The command second phase function, needed for Mode Select. */ +static uint8_t +cdrom_phase_data_out(cdrom_t *dev) { - cdrom_t *dev; + uint16_t block_desc_len, pos; + uint16_t i = 0; - uint16_t *cdbufferw; - uint32_t *cdbufferl; + uint8_t error = 0; + uint8_t page, page_len, hdr_len, val, old_val, ch; - uint8_t id = atapi_cdrom_drives[channel]; + FILE *f; - uint32_t temp = 0; + switch(dev->current_cdb[0]) { + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + f = nvr_fopen(L"modeselect.bin", L"wb"); + fwrite(cdbufferb, 1, dev->total_length, f); + fclose(f); - if (id > CDROM_NUM) - return 0; + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) + hdr_len = 8; + else + hdr_len = 4; - dev = cdrom[id]; + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { + block_desc_len = cdbufferb[2]; + block_desc_len <<= 8; + block_desc_len |= cdbufferb[3]; + } else { + block_desc_len = cdbufferb[6]; + block_desc_len <<= 8; + block_desc_len |= cdbufferb[7]; + } + } else + block_desc_len = 0; - cdbufferw = (uint16_t *) cdbufferb; - cdbufferl = (uint32_t *) cdbufferb; + pos = hdr_len + block_desc_len; - if (!cdbufferb) - return 0; + while(1) { + page = cdbufferb[pos] & 0x3F; + page_len = cdbufferb[pos + 1]; - /* Make sure we return a 0 and don't attempt to read from the buffer if we're transferring bytes beyond it, - which can happen when issuing media access commands with an allocated length below minimum request length - (which is 1 sector = 2048 bytes). */ - switch(length) { - case 1: - temp = (dev->pos < dev->packet_len) ? cdbufferb[dev->pos] : 0; - dev->pos++; - dev->request_pos++; - break; - case 2: - temp = (dev->pos < dev->packet_len) ? cdbufferw[dev->pos >> 1] : 0; - dev->pos += 2; - dev->request_pos += 2; - break; - case 4: - temp = (dev->pos < dev->packet_len) ? cdbufferl[dev->pos >> 2] : 0; - dev->pos += 4; - dev->request_pos += 4; - break; - default: + pos += 2; + + if (!(cdrom_mode_sense_page_flags & (1LL << ((uint64_t) page)))) { + cdrom_log("Unimplemented page %02X\n", page); + error |= 1; + } else { + for (i = 0; i < page_len; i++) { + ch = cdrom_mode_sense_pages_changeable.pages[page][i + 2]; + val = cdbufferb[pos + i]; + old_val = dev->ms_pages_saved.pages[page][i + 2]; + if (val != old_val) { + if (ch) + dev->ms_pages_saved.pages[page][i + 2] = val; + else { + cdrom_log("Unchangeable value on position %02X on page %02X\n", i + 2, page); + error |= 1; + } + } + } + } + + pos += page_len; + + if (dev->drv->bus_type == CDROM_BUS_SCSI) + val = cdrom_mode_sense_pages_default_scsi.pages[page][0] & 0x80; + else + val = cdrom_mode_sense_pages_default.pages[page][0] & 0x80; + + if (dev->do_page_save && val) + cdrom_mode_sense_save(dev); + + if (pos >= dev->total_length) + break; + } + + if (error) { + cdrom_invalid_field_pl(dev); return 0; - } - - if (dev->packet_status == CDROM_PHASE_DATA_IN) { - if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { - /* Time for a DRQ. */ - // cdrom_log("CD-ROM %i: Issuing read callback\n", id); - cdrom_pio_request(id, 0); } - // cdrom_log("CD-ROM %i: Returning: %02X (buffer position: %i, request position: %i)\n", id, temp, dev->pos, dev->request_pos); - return temp; - } else { - // cdrom_log("CD-ROM %i: Returning zero (buffer position: %i, request position: %i)\n", id, dev->pos, dev->request_pos); - return 0; - } + break; + } + + return 1; } -/* Reimplement as 8-bit due to reimplementation of IDE data read and write. */ -void cdrom_write(uint8_t channel, uint32_t val, int length) + +/* This is the general ATAPI PIO request function. */ +static void +cdrom_pio_request(cdrom_t *dev, uint8_t out) { - cdrom_t *dev; + int ret = 0; - uint16_t *cdbufferw; - uint32_t *cdbufferl; + if (dev->drv->bus_type < CDROM_BUS_SCSI) { + cdrom_log("CD-ROM %i: Lowering IDE IRQ\n", dev->id); + ide_irq_lower(ide_drives[dev->drv->ide_channel]); + } - uint8_t id = atapi_cdrom_drives[channel]; + dev->status = BUSY_STAT; - if (id > CDROM_NUM) - return; + if (dev->pos >= dev->packet_len) { + cdrom_log("CD-ROM %i: %i bytes %s, command done\n", dev->id, dev->pos, out ? "written" : "read"); - dev = cdrom[id]; + dev->pos = dev->request_pos = 0; + if (out) { + ret = cdrom_phase_data_out(dev); + /* If ret = 0 (phase 1 error), then we do not do anything else other than + free the buffer, as the phase and callback have already been set by the + error function. */ + if (ret) + cdrom_command_complete(dev); + } else + cdrom_command_complete(dev); + cdrom_buf_free(dev); + } else { + cdrom_log("CD-ROM %i: %i bytes %s, %i bytes are still left\n", dev->id, dev->pos, + out ? "written" : "read", dev->packet_len - dev->pos); - if (dev->packet_status == CDROM_PHASE_IDLE) { - if (!cdbufferb) - cdrom_buf_alloc(id, dev->cdb_len); - } + /* If less than (packet length) bytes are remaining, update packet length + accordingly. */ + if ((dev->packet_len - dev->pos) < (dev->max_transfer_len)) + dev->max_transfer_len = dev->packet_len - dev->pos; + cdrom_log("CD-ROM %i: Packet length %i, request length %i\n", dev->id, dev->packet_len, + dev->max_transfer_len); - cdbufferw = (uint16_t *) cdbufferb; - cdbufferl = (uint32_t *) cdbufferb; + dev->packet_status = out ? CDROM_PHASE_DATA_OUT : CDROM_PHASE_DATA_IN; - if (!cdbufferb) - return; + dev->status = BUSY_STAT; + dev->phase = 1; + cdrom_phase_callback(dev); + dev->callback = 0LL; + cdrom_set_callback(dev); - switch(length) { - case 1: - cdbufferb[dev->pos] = val & 0xff; - dev->pos++; - dev->request_pos++; - break; - case 2: - cdbufferw[dev->pos >> 1] = val & 0xffff; - dev->pos += 2; - dev->request_pos += 2; - break; - case 4: - cdbufferl[dev->pos >> 2] = val; - dev->pos += 4; - dev->request_pos += 4; - break; - default: - return; - } - - if (dev->packet_status == CDROM_PHASE_DATA_OUT) { - if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { - /* Time for a DRQ. */ - cdrom_pio_request(id, 1); - } - return; - } else if (dev->packet_status == CDROM_PHASE_IDLE) { - if (dev->pos >= dev->cdb_len) { - dev->pos=0; - dev->status = BUSY_STAT; - dev->packet_status = CDROM_PHASE_COMMAND; - timer_process(); - cdrom_phase_callback(id); - timer_update_outstanding(); - } - return; - } + dev->request_pos = 0; + } } + +static int +cdrom_read_from_ide_dma(uint8_t channel) +{ + cdrom_t *dev; + + uint8_t id = atapi_cdrom_drives[channel]; + int ret; + + if (id > CDROM_NUM) + return 0; + + dev = cdrom[id]; + + if (ide_bus_master_write) { + ret = ide_bus_master_write(channel >> 1, + cdbufferb, dev->packet_len, + ide_bus_master_priv[channel >> 1]); + if (ret == 2) /* DMA not enabled, wait for it to be enabled. */ + return 2; + else if (ret == 1) { /* DMA error. */ + cdrom_bus_master_error(dev); + return 0; + } else + return 1; + } else + return 0; + + return 0; +} + + +static int +cdrom_read_from_scsi_dma(uint8_t scsi_id) +{ + cdrom_t *dev; + + uint8_t id = scsi_cdrom_drives[scsi_id]; + int32_t *BufLen = &SCSIDevices[scsi_id].BufferLength; + + if (id > CDROM_NUM) + return 0; + + dev = cdrom[id]; + + cdrom_log("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); + memcpy(cdbufferb, SCSIDevices[scsi_id].CmdBuffer, *BufLen); + return 1; +} + + +static void +cdrom_irq_raise(cdrom_t *dev) +{ + if (dev->drv->bus_type < CDROM_BUS_SCSI) + ide_irq_raise(ide_drives[dev->drv->ide_channel]); +} + + +static int +cdrom_read_from_dma(cdrom_t *dev) +{ + int32_t *BufLen = &SCSIDevices[dev->drv->scsi_device_id].BufferLength; + int ret = 0; + + if (dev->drv->bus_type == CDROM_BUS_SCSI) + ret = cdrom_read_from_scsi_dma(dev->drv->scsi_device_id); + else + ret = cdrom_read_from_ide_dma(dev->drv->ide_channel); + + if (ret != 1) + return ret; + + if (dev->drv->bus_type == CDROM_BUS_SCSI) + cdrom_log("CD-ROM %i: SCSI Input data length: %i\n", dev->id, *BufLen); + else + cdrom_log("CD-ROM %i: ATAPI Input data length: %i\n", dev->id, dev->packet_len); + + ret = cdrom_phase_data_out(dev); + + if (ret) + return 1; + else + return 0; +} + + +static int +cdrom_write_to_ide_dma(uint8_t channel) +{ + cdrom_t *dev; + + uint8_t id = atapi_cdrom_drives[channel]; + int ret; + + if (id > CDROM_NUM) + return 0; + + dev = cdrom[id]; + + if (ide_bus_master_read) { + ret = ide_bus_master_read(channel >> 1, + cdbufferb, dev->packet_len, + ide_bus_master_priv[channel >> 1]); + if (ret == 2) /* DMA not enabled, wait for it to be enabled. */ + return 2; + else if (ret == 1) { /* DMA error. */ + cdrom_bus_master_error(dev); + return 0; + } else + return 1; + } else + return 0; +} + + +static int +cdrom_write_to_scsi_dma(uint8_t scsi_id) +{ + cdrom_t *dev; + + uint8_t id = scsi_cdrom_drives[scsi_id]; + int32_t *BufLen = &SCSIDevices[scsi_id].BufferLength; + + if (id > CDROM_NUM) + return 0; + + dev = cdrom[id]; + + cdrom_log("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); + memcpy(SCSIDevices[scsi_id].CmdBuffer, cdbufferb, *BufLen); + cdrom_log("CD-ROM %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, + cdbufferb[0], cdbufferb[1], cdbufferb[2], cdbufferb[3], cdbufferb[4], cdbufferb[5], + cdbufferb[6], cdbufferb[7]); + cdrom_log("CD-ROM %i: Data from SCSI DMA : %02X %02X %02X %02X %02X %02X %02X %02X\n", id, + SCSIDevices[scsi_id].CmdBuffer[0], SCSIDevices[scsi_id].CmdBuffer[1], + SCSIDevices[scsi_id].CmdBuffer[2], SCSIDevices[scsi_id].CmdBuffer[3], + SCSIDevices[scsi_id].CmdBuffer[4], SCSIDevices[scsi_id].CmdBuffer[5], + SCSIDevices[scsi_id].CmdBuffer[6], SCSIDevices[scsi_id].CmdBuffer[7]); + return 1; +} + + +static int +cdrom_write_to_dma(cdrom_t *dev) +{ + int32_t *BufLen = &SCSIDevices[dev->drv->scsi_device_id].BufferLength; + int ret = 0; + + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + cdrom_log("Write to SCSI DMA: (ID %02X)\n", dev->drv->scsi_device_id); + ret = cdrom_write_to_scsi_dma(dev->drv->scsi_device_id); + } else + ret = cdrom_write_to_ide_dma(dev->drv->ide_channel); + + if (dev->drv->bus_type == CDROM_BUS_SCSI) + cdrom_log("CD-ROM %i: SCSI Output data length: %i\n", dev->id, *BufLen); + else + cdrom_log("CD-ROM %i: ATAPI Output data length: %i\n", dev->id, dev->packet_len); + + return ret; +} + + +void +cdrom_phase_callback(cdrom_t *dev) +{ + int ret; + + switch(dev->packet_status) { + case CDROM_PHASE_IDLE: + cdrom_log("CD-ROM %i: CDROM_PHASE_IDLE\n", dev->id); + dev->pos = 0; + dev->phase = 1; + dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); + return; + case CDROM_PHASE_COMMAND: + cdrom_log("CD-ROM %i: CDROM_PHASE_COMMAND\n", dev->id); + dev->status = BUSY_STAT | (dev->status & ERR_STAT); + memcpy(dev->atapi_cdb, cdbufferb, dev->cdb_len); + cdrom_command(dev, dev->atapi_cdb); + return; + case CDROM_PHASE_COMPLETE: + cdrom_log("CD-ROM %i: CDROM_PHASE_COMPLETE\n", dev->id); + dev->status = READY_STAT; + dev->phase = 3; + dev->packet_status = 0xFF; + ui_sb_update_icon(SB_CDROM | dev->id, 0); + cdrom_irq_raise(dev); + return; + case CDROM_PHASE_DATA_OUT: + cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_OUT\n", dev->id); + dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); + dev->phase = 0; + cdrom_irq_raise(dev); + return; + case CDROM_PHASE_DATA_OUT_DMA: + cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_OUT_DMA\n", dev->id); + ret = cdrom_read_from_dma(dev); + + if ((ret == 1) || (dev->drv->bus_type == CDROM_BUS_SCSI)) { + cdrom_log("CD-ROM %i: DMA data out phase done\n"); + cdrom_buf_free(dev); + cdrom_command_complete(dev); + } else if (ret == 2) { + cdrom_log("CD-ROM %i: DMA out not enabled, wait\n"); + cdrom_command_bus(dev); + } else { + cdrom_log("CD-ROM %i: DMA data out phase failure\n"); + cdrom_buf_free(dev); + } + return; + case CDROM_PHASE_DATA_IN: + cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_IN\n", dev->id); + dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); + dev->phase = 2; + cdrom_irq_raise(dev); + return; + case CDROM_PHASE_DATA_IN_DMA: + cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_IN_DMA\n", dev->id); + ret = cdrom_write_to_dma(dev); + + if ((ret == 1) || (dev->drv->bus_type == CDROM_BUS_SCSI)) { + cdrom_log("CD-ROM %i: DMA data in phase done\n", dev->id); + cdrom_buf_free(dev); + cdrom_command_complete(dev); + } else if (ret == 2) { + cdrom_log("CD-ROM %i: DMA in not enabled, wait\n", dev->id); + cdrom_command_bus(dev); + } else { + cdrom_log("CD-ROM %i: DMA data in phase failure\n", dev->id); + cdrom_buf_free(dev); + } + return; + case CDROM_PHASE_ERROR: + cdrom_log("CD-ROM %i: CDROM_PHASE_ERROR\n", dev->id); + dev->status = READY_STAT | ERR_STAT; + dev->phase = 3; + cdrom_irq_raise(dev); + ui_sb_update_icon(SB_CDROM | dev->id, 0); + return; + } +} + + +uint32_t +cdrom_read(uint8_t channel, int length) +{ + cdrom_t *dev; + + uint16_t *cdbufferw; + uint32_t *cdbufferl; + + uint8_t id = atapi_cdrom_drives[channel]; + + uint32_t temp = 0; + + if (id > CDROM_NUM) + return 0; + + dev = cdrom[id]; + + cdbufferw = (uint16_t *) cdbufferb; + cdbufferl = (uint32_t *) cdbufferb; + + if (!cdbufferb) + return 0; + + /* Make sure we return a 0 and don't attempt to read from the buffer if we're transferring bytes beyond it, + which can happen when issuing media access commands with an allocated length below minimum request length + (which is 1 sector = 2048 bytes). */ + switch(length) { + case 1: + temp = (dev->pos < dev->packet_len) ? cdbufferb[dev->pos] : 0; + dev->pos++; + dev->request_pos++; + break; + case 2: + temp = (dev->pos < dev->packet_len) ? cdbufferw[dev->pos >> 1] : 0; + dev->pos += 2; + dev->request_pos += 2; + break; + case 4: + temp = (dev->pos < dev->packet_len) ? cdbufferl[dev->pos >> 2] : 0; + dev->pos += 4; + dev->request_pos += 4; + break; + default: + return 0; + } + + if (dev->packet_status == CDROM_PHASE_DATA_IN) { + cdrom_log("CD-ROM %i: Returning: %04X (buffer position: %05i, request position: %05i)\n", + id, temp, (dev->pos - 2) & 0xffff, (dev->request_pos - 2) & 0xffff); + if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { + /* Time for a DRQ. */ + cdrom_log("CD-ROM %i: Issuing read callback\n", id); + cdrom_pio_request(dev, 0); + } + return temp; + } else { + cdrom_log("CD-ROM %i: Returning: 0000 (buffer position: %05i, request position: %05i)\n", + id, (dev->pos - 2) & 0xffff, (dev->request_pos - 2) & 0xffff); + return 0; + } +} + + +void +cdrom_write(uint8_t channel, uint32_t val, int length) +{ + cdrom_t *dev; + + uint16_t *cdbufferw; + uint32_t *cdbufferl; + + uint8_t id = atapi_cdrom_drives[channel]; + + if (id > CDROM_NUM) + return; + + dev = cdrom[id]; + + if ((dev->packet_status == CDROM_PHASE_IDLE) && !cdbufferb) + cdrom_buf_alloc(dev, dev->cdb_len); + + cdbufferw = (uint16_t *) cdbufferb; + cdbufferl = (uint32_t *) cdbufferb; + + if (!cdbufferb) + return; + + switch(length) { + case 1: + cdbufferb[dev->pos] = val & 0xff; + dev->pos++; + dev->request_pos++; + break; + case 2: + cdbufferw[dev->pos >> 1] = val & 0xffff; + dev->pos += 2; + dev->request_pos += 2; + break; + case 4: + cdbufferl[dev->pos >> 2] = val; + dev->pos += 4; + dev->request_pos += 4; + break; + default: + return; + } + + if (dev->packet_status == CDROM_PHASE_DATA_OUT) { + if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { + /* Time for a DRQ. */ + cdrom_pio_request(dev, 1); + } + return; + } else if (dev->packet_status == CDROM_PHASE_IDLE) { + if (dev->pos >= dev->cdb_len) { + dev->pos = 0; + dev->status = BUSY_STAT; + dev->packet_status = CDROM_PHASE_COMMAND; + timer_process(); + cdrom_phase_callback(dev); + timer_update_outstanding(); + } + return; + } +} + + /* Peform a master init on the entire module. */ void cdrom_global_init(void) { - int c; - /* Clear the global data. */ memset(cdrom, 0x00, sizeof(cdrom)); memset(cdrom_drives, 0x00, sizeof(cdrom_drives)); - - /* Initialize the host devices, if any. */ - cdrom_init_host_drives(); - - /* Set all drives to NULL mode. */ - for (c=0; chandler and logging. */ + dev->id = c; + + cdrom_init(dev); + + if (dev->drv->host_drive == 200) { image_open(c, cdrom_image[c].image_path); image_reset(c); - } else if ((cdrom_drives[c].host_drive>='A') && (cdrom_drives[c].host_drive <= 'Z')) { - ioctl_open(c, cdrom_drives[c].host_drive); - ioctl_reset(c); } else - cdrom_null_open(c, cdrom_drives[c].host_drive); + cdrom_null_open(c); } + } - cdrom_mode_sense_load(c); + build_atapi_cdrom_map(); + + sound_cd_thread_reset(); +} + + +void +cdrom_close_handler(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + switch (dev->drv->host_drive) { + case 200: + image_close(id); + break; + default: + null_close(id); + break; } } void -cdrom_close(uint8_t id) +cdrom_close(void) { - switch (cdrom_drives[id].host_drive) { - case 0: - null_close(id); - break; - case 200: - image_close(id); - break; - default: - ioctl_close(id); - break; + cdrom_t *dev; + int c; + + for (c = 0; c < CDROM_NUM; c++) { + dev = cdrom[c]; + + if (dev) { + if (dev->drv && dev->handler) + cdrom_close_handler(c); + + free(cdrom[c]); + cdrom[c] = NULL; + } } } diff --git a/src/cdrom/cdrom.h b/src/cdrom/cdrom.h index 1a2607507..9f6f4d476 100644 --- a/src/cdrom/cdrom.h +++ b/src/cdrom/cdrom.h @@ -9,7 +9,7 @@ * Implementation of the CD-ROM drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)cdrom.h 1.0.10 2018/03/20 + * Version: @(#)cdrom.h 1.0.13 2018/06/18 * * Author: Miran Grca, * @@ -19,204 +19,131 @@ #define EMU_CDROM_H -#define CDROM_NUM 4 +#define CDROM_NUM 4 -#define CD_STATUS_EMPTY 0 -#define CD_STATUS_DATA_ONLY 1 -#define CD_STATUS_PLAYING 2 -#define CD_STATUS_PAUSED 3 -#define CD_STATUS_STOPPED 4 +#define CD_STATUS_EMPTY 0 +#define CD_STATUS_DATA_ONLY 1 +#define CD_STATUS_PLAYING 2 +#define CD_STATUS_PAUSED 3 +#define CD_STATUS_STOPPED 4 -#define CDROM_PHASE_IDLE 0 -#define CDROM_PHASE_COMMAND 1 -#define CDROM_PHASE_COMPLETE 2 -#define CDROM_PHASE_DATA_IN 3 -#define CDROM_PHASE_DATA_IN_DMA 4 -#define CDROM_PHASE_DATA_OUT 5 -#define CDROM_PHASE_DATA_OUT_DMA 6 -#define CDROM_PHASE_ERROR 0x80 +#define CDROM_PHASE_IDLE 0x00 +#define CDROM_PHASE_COMMAND 0x01 +#define CDROM_PHASE_COMPLETE 0x02 +#define CDROM_PHASE_DATA_IN 0x03 +#define CDROM_PHASE_DATA_IN_DMA 0x04 +#define CDROM_PHASE_DATA_OUT 0x05 +#define CDROM_PHASE_DATA_OUT_DMA 0x06 +#define CDROM_PHASE_ERROR 0x80 #define BUF_SIZE 32768 #define CDROM_IMAGE 200 -#define IDE_TIME (5LL * 100LL * (1LL << TIMER_SHIFT)) #define CDROM_TIME (5LL * 100LL * (1LL << TIMER_SHIFT)) enum { CDROM_BUS_DISABLED = 0, - CDROM_BUS_ATAPI_PIO_ONLY = 4, - CDROM_BUS_ATAPI_PIO_AND_DMA, + CDROM_BUS_ATAPI = 4, CDROM_BUS_SCSI, - CDROM_BUS_USB = 8 + CDROM_BUS_USB }; typedef struct { - int (*ready)(uint8_t id); - int (*medium_changed)(uint8_t id); - int (*media_type_id)(uint8_t id); + int (*ready)(uint8_t id); + int (*medium_changed)(uint8_t id); + int (*media_type_id)(uint8_t id); - void (*audio_callback)(uint8_t id, int16_t *output, int len); - void (*audio_stop)(uint8_t id); - int (*readtoc)(uint8_t id, uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single); - int (*readtoc_session)(uint8_t id, uint8_t *b, int msf, int maxlen); - int (*readtoc_raw)(uint8_t id, uint8_t *b, int maxlen); - uint8_t (*getcurrentsubchannel)(uint8_t id, uint8_t *b, int msf); - int (*pass_through)(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t *len); - int (*readsector_raw)(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len); - void (*playaudio)(uint8_t id, uint32_t pos, uint32_t len, int ismsf); - void (*load)(uint8_t id); - void (*eject)(uint8_t id); - void (*pause)(uint8_t id); - void (*resume)(uint8_t id); - uint32_t (*size)(uint8_t id); - int (*status)(uint8_t id); - int (*is_track_audio)(uint8_t id, uint32_t pos, int ismsf); - void (*stop)(uint8_t id); - void (*exit)(uint8_t id); + int (*audio_callback)(uint8_t id, int16_t *output, int len); + void (*audio_stop)(uint8_t id); + int (*readtoc)(uint8_t id, uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single); + int (*readtoc_session)(uint8_t id, uint8_t *b, int msf, int maxlen); + int (*readtoc_raw)(uint8_t id, uint8_t *b, int maxlen); + uint8_t (*getcurrentsubchannel)(uint8_t id, uint8_t *b, int msf); + int (*readsector_raw)(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len); + uint8_t (*playaudio)(uint8_t id, uint32_t pos, uint32_t len, int ismsf); + void (*pause)(uint8_t id); + void (*resume)(uint8_t id); + uint32_t (*size)(uint8_t id); + int (*status)(uint8_t id); + void (*stop)(uint8_t id); + void (*exit)(uint8_t id); } CDROM; typedef struct { - uint8_t previous_command; + int host_drive; + int prev_host_drive; - int toctimes; - int media_status; + unsigned int bus_type; /* 0 = ATAPI, 1 = SCSI */ - int is_dma; + uint8_t speed, ide_channel, + bus_mode; /* Bit 0 = PIO suported; + Bit 1 = DMA supportd. */ - int requested_blocks; /* This will be set to something other than 1 when block reads are implemented. */ - - uint64_t current_page_code; - int current_page_len; - - int current_page_pos; - - int mode_select_phase; - - int total_length; - int written_length; - - int do_page_save; - - uint8_t error; - uint8_t features; - uint16_t request_length; - uint16_t max_transfer_len; - uint8_t status; - uint8_t phase; - - uint32_t sector_pos; - uint32_t sector_len; - - uint32_t packet_len; - int packet_status; - - uint8_t atapi_cdb[16]; - uint8_t current_cdb[16]; - - uint32_t pos; - - int callback; - - int data_pos; - uint32_t seek_diff; - - int cdb_len_setting; - int cdb_len; - - int cd_status; - int prev_status; - - int unit_attention; - uint8_t sense[256]; - - int request_pos; - - uint8_t *buffer; - - int times; - - uint32_t seek_pos; - - int total_read; - - int block_total; - int all_blocks_total; - - int old_len; - int block_descriptor_len; - - int init_length; - - int16_t cd_buffer[BUF_SIZE]; - - uint8_t rcbuf[16]; - uint8_t sub_q_data_format[16]; - uint8_t sub_q_channel_data[256]; - int last_subchannel_pos; - - uint32_t cd_end; - uint32_t cdrom_capacity; - - int cd_buflen; - int cd_state; - - int handler_inited; - int disc_changed; - - int cur_speed; -} cdrom_t; - -typedef struct { - CDROM *handler; - - int host_drive; - int prev_host_drive; - - unsigned int bus_type; /* 0 = ATAPI, 1 = SCSI */ - uint8_t bus_mode; /* Bit 0 = PIO suported; - Bit 1 = DMA supportd. */ - - uint8_t ide_channel; - - unsigned int scsi_device_id; - unsigned int scsi_device_lun; - - unsigned int sound_on; - unsigned int atapi_dma; - - uint8_t speed; + unsigned int scsi_device_id, sound_on; } cdrom_drive_t; typedef struct { - int image_is_iso; - wchar_t image_path[1024]; - wchar_t *prev_image_path; - FILE* image; -} cdrom_image_t; + mode_sense_pages_t ms_pages_saved; + + CDROM *handler; + cdrom_drive_t *drv; + + uint8_t previous_command, + error, features, + status, phase, + id, *buffer, + atapi_cdb[16], + current_cdb[16], + sense[256]; + + uint16_t request_length, max_transfer_len; + int16_t cd_buffer[BUF_SIZE]; + + int media_status, is_dma, + packet_status, requested_blocks, + current_page_len, current_page_pos, + mode_select_phase, do_page_save, + total_length, written_length, + callback, data_pos, + cd_status, prev_status, + unit_attention, request_pos, + total_read, cur_speed, + block_total, all_blocks_total, + old_len, block_descriptor_len, + init_length, last_subchannel_pos, + cd_buflen, cd_state, + handler_inited, disc_changed; + + uint32_t sector_pos, sector_len, + seek_pos, seek_diff, + pos, packet_len, + cdb_len, cd_end, + cdrom_capacity; + + uint64_t current_page_code; +} cdrom_t; typedef struct { - char ioctl_path[8]; - int actual_requested_blocks; - int last_track_pos; - int last_track_nr; - int capacity_read; -} cdrom_ioctl_t; + int image_is_iso; + wchar_t image_path[1024], + *prev_image_path; + FILE* image; +} cdrom_image_t; extern cdrom_t *cdrom[CDROM_NUM]; extern cdrom_drive_t cdrom_drives[CDROM_NUM]; extern cdrom_image_t cdrom_image[CDROM_NUM]; -extern cdrom_ioctl_t cdrom_ioctl[CDROM_NUM]; extern uint8_t atapi_cdrom_drives[8]; -extern uint8_t scsi_cdrom_drives[16][8]; +extern uint8_t scsi_cdrom_drives[16]; -#define cdrom_sense_error cdrom[id]->sense[0] -#define cdrom_sense_key cdrom[id]->sense[2] -#define cdrom_asc cdrom[id]->sense[12] -#define cdrom_ascq cdrom[id]->sense[13] +#define cdrom_sense_error dev->sense[0] +#define cdrom_sense_key dev->sense[2] +#define cdrom_asc dev->sense[12] +#define cdrom_ascq dev->sense[13] #define cdrom_drive cdrom_drives[id].host_drive @@ -224,35 +151,34 @@ extern uint8_t scsi_cdrom_drives[16][8]; extern "C" { #endif -extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length); -extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length); -extern void (*ide_bus_master_set_irq)(int channel); -extern void ioctl_close(uint8_t id); +extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length, void *priv); +extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length, void *priv); +extern void (*ide_bus_master_set_irq)(int channel, void *priv); +extern void *ide_bus_master_priv[2]; -extern uint32_t cdrom_mode_sense_get_channel(uint8_t id, int channel); -extern uint32_t cdrom_mode_sense_get_volume(uint8_t id, int channel); +extern uint32_t cdrom_mode_sense_get_channel(cdrom_t *dev, int channel); +extern uint32_t cdrom_mode_sense_get_volume(cdrom_t *dev, int channel); extern void build_atapi_cdrom_map(void); extern void build_scsi_cdrom_map(void); -extern int cdrom_CDROM_PHASE_to_scsi(uint8_t id); -extern int cdrom_atapi_phase_to_scsi(uint8_t id); -extern void cdrom_command(uint8_t id, uint8_t *cdb); -extern void cdrom_phase_callback(uint8_t id); +extern int cdrom_CDROM_PHASE_to_scsi(cdrom_t *dev); +extern int cdrom_atapi_phase_to_scsi(cdrom_t *dev); +extern void cdrom_command(cdrom_t *dev, uint8_t *cdb); +extern void cdrom_phase_callback(cdrom_t *dev); extern uint32_t cdrom_read(uint8_t channel, int length); extern void cdrom_write(uint8_t channel, uint32_t val, int length); extern int cdrom_lba_to_msf_accurate(int lba); -extern void cdrom_destroy_drives(void); -extern void cdrom_close(uint8_t id); -extern void cdrom_reset(uint8_t id); -extern void cdrom_set_signature(int id); -extern void cdrom_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length); +extern void cdrom_close_handler(uint8_t id); +extern void cdrom_close(void); +extern void cdrom_reset(cdrom_t *dev); +extern void cdrom_set_signature(cdrom_t *dev); +extern void cdrom_request_sense_for_scsi(cdrom_t *dev, uint8_t *buffer, uint8_t alloc_length); extern void cdrom_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks); -extern void cdrom_insert(uint8_t id); -extern void cdrom_new_image(uint8_t id); +extern void cdrom_insert(cdrom_t *dev); -extern int find_cdrom_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun); -extern int cdrom_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len); +extern int find_cdrom_for_scsi_id(uint8_t scsi_id); +extern int cdrom_read_capacity(cdrom_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len); extern void cdrom_global_init(void); extern void cdrom_global_reset(void); diff --git a/src/cdrom/cdrom_dosbox.cpp b/src/cdrom/cdrom_dosbox.cpp index 7fffa01b9..0408be688 100644 --- a/src/cdrom/cdrom_dosbox.cpp +++ b/src/cdrom/cdrom_dosbox.cpp @@ -87,12 +87,12 @@ uint64_t CDROM_Interface_Image::BinaryFile::getLength() CDROM_Interface_Image::CDROM_Interface_Image() { - printf("CDROM_Interface_Image constructor\n"); + // printf("CDROM_Interface_Image constructor\n"); } CDROM_Interface_Image::~CDROM_Interface_Image() { - printf("CDROM_Interface_Image destructor\n"); + // printf("CDROM_Interface_Image destructor\n"); ClearTracks(); } @@ -263,7 +263,7 @@ bool CDROM_Interface_Image::LoadIsoFile(char* filename) tracks.clear(); // data track - Track track = {0, 0, 0, 0, 0, 0, 0, false, NULL}; + Track track = {0, 0, 0, 0, 0, 0, 0, 0, false, NULL}; bool error; track.file = new BinaryFile(filename, error); if (error) { @@ -343,7 +343,7 @@ static string dirname(char * file) { bool CDROM_Interface_Image::LoadCueSheet(char *cuefile) { - Track track = {0, 0, 0, 0, 0, 0, 0, false, NULL}; + Track track = {0, 0, 0, 0, 0, 0, 0, 0, false, NULL}; tracks.clear(); uint64_t shift = 0; uint64_t currPregap = 0; @@ -357,7 +357,6 @@ bool CDROM_Interface_Image::LoadCueSheet(char *cuefile) ifstream in; in.open(cuefile, ios::in); if (in.fail()) return false; - int last_attr; while(!in.eof()) { // get next line @@ -429,7 +428,6 @@ bool CDROM_Interface_Image::LoadCueSheet(char *cuefile) track.attr = DATA_TRACK; track.mode2 = true; } else success = false; - last_attr = track.attr; canAddTrack = true; } diff --git a/src/cdrom/cdrom_image.cc b/src/cdrom/cdrom_image.cc index 6a7c74e8c..c1a301ba6 100644 --- a/src/cdrom/cdrom_image.cc +++ b/src/cdrom/cdrom_image.cc @@ -1,8 +1,23 @@ -/* Copyright holders: RichardG867, Tenshi, bit - see COPYING for more details -*/ -/*CD-ROM image support*/ - +/* + * 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. + * + * CD-ROM image support. + * + * Version: @(#)cdrom_image.cc 1.0.0 2018/03/29 + * + * Author: RichardG867, + * Miran Grca, + * bit, + * + * Copyright 2015-2018 Richardg867. + * Copyright 2015-2018 Miran Grca. + * Copyright 2017,2018 bit. + */ #define __USE_LARGEFILE64 #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE @@ -14,6 +29,7 @@ #include #include "../config.h" #include "../plat.h" +#include "../scsi/scsi.h" #include "cdrom_dosbox.h" #include "cdrom.h" #include "cdrom_image.h" @@ -28,381 +44,55 @@ /* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong: there is a seeming 2 seconds in which audio plays but counter does not move, while a data track before audio jumps to 2 seconds before the actual start of the audio while audio still plays. With an absolute conversion, the counter is fine. */ -#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) +#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) -extern CDROM image_cdrom; - -enum -{ - CD_STOPPED = 0, - CD_PLAYING, - CD_PAUSED -}; - -#ifdef ENABLE_CDROM_IMAGE_LOG -int cdrom_image_do_log = ENABLE_CDROM_IMAGE_LOG; -#endif - -CDROM_Interface_Image* cdimg[CDROM_NUM] = { NULL, NULL, NULL, NULL }; - - -void cdrom_image_log(const char *format, ...) -{ -#ifdef ENABLE_CDROM_IMAGE_LOG - if (cdrom_image_do_log) - { - va_list ap; - va_start(ap, format); - vprintf(format, ap); - va_end(ap); - fflush(stdout); - } -/* #else - (void)format; */ -#endif -} - -void image_close(uint8_t id); - -void image_audio_callback(uint8_t id, int16_t *output, int len) -{ - cdrom_t *dev = cdrom[id]; - - if (!cdrom_drives[id].sound_on || (dev->cd_state != CD_PLAYING) || cdrom_image[id].image_is_iso) - { - cdrom_image_log("image_audio_callback(i): Not playing\n", id); - if (dev->cd_state == CD_PLAYING) - { - dev->seek_pos += (len >> 11); - } - memset(output, 0, len * 2); - return; - } - while (dev->cd_buflen < len) - { - if (dev->seek_pos < dev->cd_end) - { - if (!cdimg[id]->ReadSector((unsigned char*)&dev->cd_buffer[dev->cd_buflen], true, dev->seek_pos)) - { - memset(&dev->cd_buffer[dev->cd_buflen], 0, (BUF_SIZE - dev->cd_buflen) * 2); - dev->cd_state = CD_STOPPED; - dev->cd_buflen = len; - } - else - { - dev->seek_pos++; - dev->cd_buflen += (RAW_SECTOR_SIZE / 2); - } - } - else - { - memset(&dev->cd_buffer[dev->cd_buflen], 0, (BUF_SIZE - dev->cd_buflen) * 2); - dev->cd_state = CD_STOPPED; - dev->cd_buflen = len; - } - } - memcpy(output, dev->cd_buffer, len * 2); - memmove(dev->cd_buffer, &dev->cd_buffer[len], (BUF_SIZE - len) * 2); - dev->cd_buflen -= len; -} - -void image_audio_stop(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - dev->cd_state = CD_STOPPED; -} - -static void image_playaudio(uint8_t id, uint32_t pos, uint32_t len, int ismsf) -{ - cdrom_t *dev = cdrom[id]; - if (!cdimg[id]) return; - int number; - unsigned char attr; - TMSF tmsf; - int m = 0, s = 0, f = 0; - cdimg[id]->GetAudioTrackInfo(cdimg[id]->GetTrack(pos), number, tmsf, attr); - if (attr == DATA_TRACK) - { - cdrom_image_log("Can't play data track\n"); - dev->seek_pos = 0; - dev->cd_state = CD_STOPPED; - return; - } - cdrom_image_log("Play audio - %08X %08X %i\n", pos, len, ismsf); - if (ismsf == 2) - { - cdimg[id]->GetAudioTrackInfo(pos, number, tmsf, attr); - pos = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; - cdimg[id]->GetAudioTrackInfo(len, number, tmsf, attr); - len = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; - } - else if (ismsf == 1) - { - m = (pos >> 16) & 0xff; - s = (pos >> 8) & 0xff; - f = pos & 0xff; - - if (pos == 0xffffff) - { - cdrom_image_log("Playing from current position (MSF)\n"); - pos = dev->seek_pos; - } - else - { - pos = MSFtoLBA(m, s, f) - 150; - } - - m = (len >> 16) & 0xff; - s = (len >> 8) & 0xff; - f = len & 0xff; - len = MSFtoLBA(m, s, f) - 150; - - cdrom_image_log("MSF - pos = %08X len = %08X\n", pos, len); - } - else if (ismsf == 0) - { - if (pos == 0xffffffff) - { - cdrom_image_log("Playing from current position\n"); - pos = dev->seek_pos; - } - len += pos; - } - dev->seek_pos = pos; - dev->cd_end = len; - dev->cd_state = CD_PLAYING; - dev->cd_buflen = 0; -} - -static void image_pause(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - if (!cdimg[id] || cdrom_image[id].image_is_iso) return; - if (dev->cd_state == CD_PLAYING) - dev->cd_state = CD_PAUSED; -} - -static void image_resume(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - if (!cdimg[id] || cdrom_image[id].image_is_iso) return; - if (dev->cd_state == CD_PAUSED) - dev->cd_state = CD_PLAYING; -} - -static void image_stop(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - if (!cdimg[id] || cdrom_image[id].image_is_iso) return; - dev->cd_state = CD_STOPPED; -} - -static int image_ready(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - if (!cdimg[id]) - return 0; - - if (wcslen(cdrom_image[id].image_path) == 0) - return 0; - - if (cdrom_drives[id].prev_host_drive != cdrom_drives[id].host_drive) - { - return 1; - } - - return 1; -} - -static int image_get_last_block(uint8_t id, UNUSED(uint8_t starttrack), UNUSED(int msf), UNUSED(int maxlen), UNUSED(int single)) -{ - int c; - uint32_t lb=0; - - if (!cdimg[id]) return 0; - - int first_track; - int last_track; - int number; - unsigned char attr; - TMSF tmsf; - cdimg[id]->GetAudioTracks(first_track, last_track, tmsf); - - for (c = 0; c <= last_track; c++) - { - uint32_t address; - cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); - address = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; /* Do the - 150 here as well. */ - if (address > lb) - lb = address; - } - return lb; -} - -static int image_medium_changed(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - if (!cdimg[id]) - return 0; - - if (wcslen(cdrom_image[id].image_path) == 0) - { - return 0; - } - - if (cdrom_drives[id].prev_host_drive != cdrom_drives[id].host_drive) - { - cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; - return 1; - } - - return 0; -} - -static uint8_t image_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf) -{ - cdrom_t *dev = cdrom[id]; - if (!cdimg[id]) return 0; - uint8_t ret; - int pos=0; - - uint32_t cdpos = dev->seek_pos; - TMSF relPos, absPos; - unsigned char attr, track, index; - cdimg[id]->GetAudioSub(cdpos, attr, track, index, relPos, absPos); - - if (cdrom_image[id].image_is_iso) - { - ret = 0x15; - } - else - { - if (dev->cd_state == CD_PLAYING) - ret = 0x11; - else if (dev->cd_state == CD_PAUSED) - ret = 0x12; - else - ret = 0x13; - } - - b[pos++] = attr; - b[pos++] = track; - b[pos++] = index; - - if (msf) - { - b[pos + 3] = (uint8_t) absPos.fr; - b[pos + 2] = (uint8_t) absPos.sec; - b[pos + 1] = (uint8_t) absPos.min; - b[pos] = 0; - pos += 4; - b[pos + 3] = (uint8_t) relPos.fr; - b[pos + 2] = (uint8_t) relPos.sec; - b[pos + 1] = (uint8_t) relPos.min; - b[pos] = 0; - pos += 4; - } - else - { - uint32_t dat = MSFtoLBA(absPos.min, absPos.sec, absPos.fr) - 150; - b[pos++] = (dat >> 24) & 0xff; - b[pos++] = (dat >> 16) & 0xff; - b[pos++] = (dat >> 8) & 0xff; - b[pos++] = dat & 0xff; - dat = MSFtoLBA(relPos.min, relPos.sec, relPos.fr); - b[pos++] = (dat >> 24) & 0xff; - b[pos++] = (dat >> 16) & 0xff; - b[pos++] = (dat >> 8) & 0xff; - b[pos++] = dat & 0xff; - } - - return ret; -} - -static void image_eject(UNUSED(uint8_t id)) -{ - return; -} - -static void image_load(UNUSED(uint8_t id)) -{ - return; -} - -static int image_is_track_audio(uint8_t id, uint32_t pos, int ismsf) -{ - int m, s, f; - unsigned char attr; - TMSF tmsf; - int number; - - if (!cdimg[id] || cdrom_image[id].image_is_iso) return 0; - - if (ismsf) - { - m = (pos >> 16) & 0xff; - s = (pos >> 8) & 0xff; - f = pos & 0xff; - pos = MSFtoLBA(m, s, f) - 150; - } - - /* GetTrack requires LBA. */ - cdimg[id]->GetAudioTrackInfo(cdimg[id]->GetTrack(pos), number, tmsf, attr); - - return attr == AUDIO_TRACK; -} +extern CDROM image_cdrom; typedef struct __attribute__((__packed__)) { - uint8_t user_data[2048]; - uint8_t ecc[288]; + uint8_t user_data[2048], + ecc[288]; } m1_data_t; typedef struct __attribute__((__packed__)) { - uint8_t sub_header[8]; - uint8_t user_data[2328]; + uint8_t sub_header[8], + user_data[2328]; } m2_data_t; typedef union __attribute__((__packed__)) { - m1_data_t m1_data; - m2_data_t m2_data; - uint8_t raw_data[2336]; + m1_data_t m1_data; + m2_data_t m2_data; + uint8_t raw_data[2336]; } sector_data_t; typedef struct __attribute__((__packed__)) { - uint8_t sync[12]; - uint8_t header[4]; - sector_data_t data; + uint8_t sync[12]; + uint8_t header[4]; + sector_data_t data; } sector_raw_data_t; typedef union __attribute__((__packed__)) { - sector_raw_data_t sector_data; - uint8_t raw_data[2352]; + sector_raw_data_t sector_data; + uint8_t raw_data[2352]; } sector_t; typedef struct __attribute__((__packed__)) { - sector_t sector; - uint8_t c2[296]; - uint8_t subchannel_raw[96]; - uint8_t subchannel_q[16]; - uint8_t subchannel_rw[96]; + sector_t sector; + uint8_t c2[296]; + uint8_t subchannel_raw[96]; + uint8_t subchannel_q[16]; + uint8_t subchannel_rw[96]; } cdrom_sector_t; typedef union __attribute__((__packed__)) { - cdrom_sector_t cdrom_sector; - uint8_t buffer[2856]; + cdrom_sector_t cdrom_sector; + uint8_t buffer[2856]; } sector_buffer_t; sector_buffer_t cdrom_sector_buffer; @@ -411,717 +101,1007 @@ int cdrom_sector_size; uint8_t raw_buffer[2448]; uint8_t extra_buffer[296]; -static int is_legal(int id, int cdrom_sector_type, int cdrom_sector_flags, int audio, int mode2, int form) +enum { - if (!(cdrom_sector_flags & 0x70)) { /* 0x00/0x08/0x80/0x88 are illegal modes */ - cdrom_image_log("CD-ROM %i: [Any Mode] 0x00/0x08/0x80/0x88 are illegal modes\n", id); - return 0; - } + CD_STOPPED = 0, + CD_PLAYING, + CD_PAUSED +}; - if ((cdrom_sector_type != 1) && !audio) - { - if (!(cdrom_sector_flags & 0x70)) { /* 0x00/0x08/0x80/0x88 are illegal modes */ - cdrom_image_log("CD-ROM %i: [Any Data Mode] 0x00/0x08/0x80/0x88 are illegal modes\n", id); - return 0; - } - if ((cdrom_sector_flags & 0x06) == 0x06) { - cdrom_image_log("CD-ROM %i: [Any Data Mode] Invalid error flags\n", id); - return 0; - } +#ifdef ENABLE_CDROM_IMAGE_LOG +int cdrom_image_do_log = ENABLE_CDROM_IMAGE_LOG; +#endif - if (((cdrom_sector_flags & 0x700) == 0x300) || ((cdrom_sector_flags & 0x700) > 0x400)) { - cdrom_image_log("CD-ROM %i: [Any Data Mode] Invalid subchannel data flags (%02X)\n", id, cdrom_sector_flags & 0x700); - return 0; - } - if ((cdrom_sector_flags & 0x18) == 0x08) { /* EDC/ECC without user data is an illegal mode */ - cdrom_image_log("CD-ROM %i: [Any Data Mode] EDC/ECC without user data is an illegal mode\n", id); - return 0; - } +static CDROM_Interface_Image* cdimg[CDROM_NUM] = { NULL, NULL, NULL, NULL }; +static char afn[1024]; - if (((cdrom_sector_flags & 0xf0) == 0x90) || ((cdrom_sector_flags & 0xf0) == 0xc0)) { /* 0x90/0x98/0xC0/0xC8 are illegal modes */ - cdrom_image_log("CD-ROM %i: [Any Data Mode] 0x90/0x98/0xC0/0xC8 are illegal modes\n", id); - return 0; - } +void image_close(uint8_t id); - if (((cdrom_sector_type > 3) && (cdrom_sector_type != 8)) || (mode2 && form)) - { - if ((cdrom_sector_flags & 0xf0) == 0x30) { /* 0x30/0x38 are illegal modes */ - cdrom_image_log("CD-ROM %i: [Any XA Mode 2] 0x30/0x38 are illegal modes\n", id); - return 0; - } - if (((cdrom_sector_flags & 0xf0) == 0xb0) || ((cdrom_sector_flags & 0xf0) == 0xd0)) { /* 0xBx and 0xDx are illegal modes */ - cdrom_image_log("CD-ROM %i: [Any XA Mode 2] 0xBx and 0xDx are illegal modes\n", id); - return 0; - } - } - } - return 1; +void +cdrom_image_log(const char *format, ...) +{ +#ifdef ENABLE_CDROM_IMAGE_LOG + if (cdrom_image_do_log) { + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + fflush(stdout); + } +#endif } -static void read_sector_to_buffer(uint8_t id, uint8_t *raw_buffer, uint32_t msf, uint32_t lba, int mode2, int form, int len) + +int +image_audio_callback(uint8_t id, int16_t *output, int len) { - cdimg[id]->ReadSector(raw_buffer + 16, false, lba); + cdrom_t *dev = cdrom[id]; + int ret = 1; - uint8_t *bb = raw_buffer; - - /* sync bytes */ - bb[0] = 0; - memset(bb + 1, 0xff, 10); - bb[11] = 0; - bb += 12; - - bb[0] = (msf >> 16) & 0xff; - bb[1] = (msf >> 8) & 0xff; - bb[2] = msf & 0xff; - - bb[3] = 1; /* mode 1 data */ - bb += mode2 ? 12 : 4; - bb += len; - if (mode2 && (form == 1)) - memset(bb, 0, 280); - else if (!mode2) - memset(bb, 0, 288); -} - -static int image_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len) -{ - uint8_t *b; - uint8_t *temp_b; - uint32_t msf; - uint32_t lba; - int audio; - int mode2; - int m, s, f; - int form; - - if (!cdimg[id]) - return 0; - - if (!cdrom_drives[id].host_drive) - return 0; - - b = temp_b = buffer; - - *len = 0; - - if (ismsf) { - m = (sector >> 16) & 0xff; - s = (sector >> 8) & 0xff; - f = sector & 0xff; - lba = MSFtoLBA(m, s, f) - 150; - msf = sector; - } else { - lba = sector; - msf = cdrom_lba_to_msf_accurate(sector); - } - - if (cdrom_image[id].image_is_iso) { - audio = 0; - mode2 = cdimg[id]->IsMode2(lba) ? 1 : 0; - } else { - audio = image_is_track_audio(id, sector, ismsf); - mode2 = cdimg[id]->IsMode2(lba) ? 1 : 0; - } - form = cdimg[id]->GetMode2Form(lba); - - memset(raw_buffer, 0, 2448); - memset(extra_buffer, 0, 296); - - if (!(cdrom_sector_flags & 0xf0)) { /* 0x00 and 0x08 are illegal modes */ - cdrom_image_log("CD-ROM %i: [Mode 1] 0x00 and 0x08 are illegal modes\n", id); - return 0; - } - - if ((cdrom_sector_type == 3) || ((cdrom_sector_type > 4) && (cdrom_sector_type != 8))) { - if (cdrom_sector_type == 3) - cdrom_image_log("CD-ROM %i: Attempting to read a Yellowbook Mode 2 data sector from an image\n", id); - if (cdrom_sector_type > 4) - cdrom_image_log("CD-ROM %i: Attempting to read a XA Mode 2 Form 2 data sector from an image\n", id); - return 0; - } - else if (cdrom_sector_type == 1) { - if (!audio || cdrom_image[id].image_is_iso) { - cdrom_image_log("CD-ROM %i: [Audio] Attempting to read an audio sector from a data image\n", id); - return 0; - } - -read_audio: - if (!is_legal(id, cdrom_sector_type, cdrom_sector_flags, audio, mode2, form)) - return 0; - - if (cdimg[id]->GetSectorSize(lba) == 2352) - cdimg[id]->ReadSector(raw_buffer, true, lba); - else - cdimg[id]->ReadSectorSub(raw_buffer, lba); - - memcpy(temp_b, raw_buffer, 2352); - cdrom_sector_size = 2352; - } else if (cdrom_sector_type == 2) { - if (audio || mode2) { - cdrom_image_log("CD-ROM %i: [Mode 1] Attempting to read a sector of another type\n", id); - return 0; - } - -read_mode1: - if (!is_legal(id, cdrom_sector_type, cdrom_sector_flags, audio, mode2, form)) - return 0; - - if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2048)) - read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, form, 2048); - else if (cdimg[id]->GetSectorSize(lba) == 2352) - cdimg[id]->ReadSector(raw_buffer, true, lba); - else - cdimg[id]->ReadSectorSub(raw_buffer, lba); - - cdrom_sector_size = 0; - - if (cdrom_sector_flags & 0x80) { /* Sync */ - cdrom_image_log("CD-ROM %i: [Mode 1] Sync\n", id); - memcpy(temp_b, raw_buffer, 12); - cdrom_sector_size += 12; - temp_b += 12; - } - - if (cdrom_sector_flags & 0x20) { /* Header */ - cdrom_image_log("CD-ROM %i: [Mode 1] Header\n", id); - memcpy(temp_b, raw_buffer + 12, 4); - cdrom_sector_size += 4; - temp_b += 4; - } - - if (cdrom_sector_flags & 0x40) { /* Sub-header */ - if (!(cdrom_sector_flags & 0x10)) { /* No user data */ - cdrom_image_log("CD-ROM %i: [Mode 1] Sub-header\n", id); - memcpy(temp_b, raw_buffer + 16, 8); - cdrom_sector_size += 8; - temp_b += 8; - } - } - - if (cdrom_sector_flags & 0x10) { /* User data */ - cdrom_image_log("CD-ROM %i: [Mode 1] User data\n", id); - memcpy(temp_b, raw_buffer + 16, 2048); - cdrom_sector_size += 2048; - temp_b += 2048; - } - - if (cdrom_sector_flags & 0x08) { /* EDC/ECC */ - cdrom_image_log("CD-ROM %i: [Mode 1] EDC/ECC\n", id); - memcpy(temp_b, raw_buffer + 2064, 288); - cdrom_sector_size += 288; - temp_b += 288; - } - } else if (cdrom_sector_type == 3) { - if (audio || !mode2 || form) { - cdrom_image_log("CD-ROM %i: [Mode 2 Formless] Attempting to read a sector of another type\n", id); - return 0; - } - -read_mode2_non_xa: - if (!is_legal(id, cdrom_sector_type, cdrom_sector_flags, audio, mode2, form)) - return 0; - - if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2336)) - read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, form, 2336); - else if (cdimg[id]->GetSectorSize(lba) == 2352) - cdimg[id]->ReadSector(raw_buffer, true, lba); - else - cdimg[id]->ReadSectorSub(raw_buffer, lba); - - cdrom_sector_size = 0; - - if (cdrom_sector_flags & 0x80) { /* Sync */ - cdrom_image_log("CD-ROM %i: [Mode 2 Formless] Sync\n", id); - memcpy(temp_b, raw_buffer, 12); - cdrom_sector_size += 12; - temp_b += 12; - } - - if (cdrom_sector_flags & 0x20) { /* Header */ - cdrom_image_log("CD-ROM %i: [Mode 2 Formless] Header\n", id); - memcpy(temp_b, raw_buffer + 12, 4); - cdrom_sector_size += 4; - temp_b += 4; - } - - /* Mode 1 sector, expected type is 1 type. */ - if (cdrom_sector_flags & 0x40) { /* Sub-header */ - cdrom_image_log("CD-ROM %i: [Mode 2 Formless] Sub-header\n", id); - memcpy(temp_b, raw_buffer + 16, 8); - cdrom_sector_size += 8; - temp_b += 8; - } - - if (cdrom_sector_flags & 0x10) { /* User data */ - cdrom_image_log("CD-ROM %i: [Mode 2 Formless] User data\n", id); - memcpy(temp_b, raw_buffer + 24, 2336); - cdrom_sector_size += 2336; - temp_b += 2336; - } - } else if (cdrom_sector_type == 4) { - if (audio || !mode2 || (form != 1)) { - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] Attempting to read a sector of another type\n", id); - return 0; - } - -read_mode2_xa_form1: - if (!is_legal(id, cdrom_sector_type, cdrom_sector_flags, audio, mode2, form)) - return 0; - - if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2048)) - read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, form, 2048); - else if (cdimg[id]->GetSectorSize(lba) == 2352) - cdimg[id]->ReadSector(raw_buffer, true, lba); - else - cdimg[id]->ReadSectorSub(raw_buffer, lba); - - cdrom_sector_size = 0; - - if (cdrom_sector_flags & 0x80) { /* Sync */ - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] Sync\n", id); - memcpy(temp_b, raw_buffer, 12); - cdrom_sector_size += 12; - temp_b += 12; - } - - if (cdrom_sector_flags & 0x20) { /* Header */ - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] Header\n", id); - memcpy(temp_b, raw_buffer + 12, 4); - cdrom_sector_size += 4; - temp_b += 4; - } - - if (cdrom_sector_flags & 0x40) { /* Sub-header */ - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] Sub-header\n", id); - memcpy(temp_b, raw_buffer + 16, 8); - cdrom_sector_size += 8; - temp_b += 8; - } - - if (cdrom_sector_flags & 0x10) { /* User data */ - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] User data\n", id); - memcpy(temp_b, raw_buffer + 24, 2048); - cdrom_sector_size += 2048; - temp_b += 2048; - } - - if (cdrom_sector_flags & 0x08) { /* EDC/ECC */ - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] EDC/ECC\n", id); - memcpy(temp_b, raw_buffer + 2072, 280); - cdrom_sector_size += 280; - temp_b += 280; - } - } else if (cdrom_sector_type == 5) { - if (audio || !mode2 || (form != 2)) { - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] Attempting to read a sector of another type\n", id); - return 0; - } - -read_mode2_xa_form2: - if (!is_legal(id, cdrom_sector_type, cdrom_sector_flags, audio, mode2, form)) - return 0; - - if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2324)) - read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, form, 2324); - else if (cdimg[id]->GetSectorSize(lba) == 2352) - cdimg[id]->ReadSector(raw_buffer, true, lba); - else - cdimg[id]->ReadSectorSub(raw_buffer, lba); - - cdrom_sector_size = 0; - - if (cdrom_sector_flags & 0x80) { /* Sync */ - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] Sync\n", id); - memcpy(temp_b, raw_buffer, 12); - cdrom_sector_size += 12; - temp_b += 12; - } - - if (cdrom_sector_flags & 0x20) { /* Header */ - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] Header\n", id); - memcpy(temp_b, raw_buffer + 12, 4); - cdrom_sector_size += 4; - temp_b += 4; - } - - if (cdrom_sector_flags & 0x40) { /* Sub-header */ - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] Sub-header\n", id); - memcpy(temp_b, raw_buffer + 16, 8); - cdrom_sector_size += 8; - temp_b += 8; - } - - if (cdrom_sector_flags & 0x10) { /* User data */ - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] User data\n", id); - memcpy(temp_b, raw_buffer + 24, 2328); - cdrom_sector_size += 2328; - temp_b += 2328; - } - } else if (cdrom_sector_type == 8) { - if (audio) { - cdrom_image_log("CD-ROM %i: [Any Data] Attempting to read a data sector from an audio track\n", id); - return 0; - } - - if (mode2 && (form == 1)) - goto read_mode2_xa_form1; - else if (!mode2) - goto read_mode1; - else { - cdrom_image_log("CD-ROM %i: [Any Data] Attempting to read a data sector whose cooked size is not 2048 bytes\n", id); - return 0; + if (!cdrom_drives[id].sound_on || (dev->cd_state != CD_PLAYING) || cdrom_image[id].image_is_iso) { + cdrom_image_log("image_audio_callback(i): Not playing\n", id); + if (dev->cd_state == CD_PLAYING) + dev->seek_pos += (len >> 11); + memset(output, 0, len * 2); + return 0; + } + while (dev->cd_buflen < len) { + if (dev->seek_pos < dev->cd_end) { + if (!cdimg[id]->ReadSector((unsigned char*)&dev->cd_buffer[dev->cd_buflen], true, + dev->seek_pos)) { + memset(&dev->cd_buffer[dev->cd_buflen], 0, (BUF_SIZE - dev->cd_buflen) * 2); + dev->cd_state = CD_STOPPED; + dev->cd_buflen = len; + ret = 0; + } else { + dev->seek_pos++; + dev->cd_buflen += (RAW_SECTOR_SIZE / 2); + ret = 1; } } else { - if (mode2) - if (form == 1) - goto read_mode2_xa_form1; - else if (form == 2) - goto read_mode2_xa_form2; - else - goto read_mode2_non_xa; - else { - if (audio) - goto read_audio; - else - goto read_mode1; - } + memset(&dev->cd_buffer[dev->cd_buflen], 0, (BUF_SIZE - dev->cd_buflen) * 2); + dev->cd_state = CD_STOPPED; + dev->cd_buflen = len; + ret = 0; } + } - if ((cdrom_sector_flags & 0x06) == 0x02) { - /* Add error flags. */ - cdrom_image_log("CD-ROM %i: Error flags\n", id); - memcpy(b + cdrom_sector_size, extra_buffer, 294); - cdrom_sector_size += 294; - } - else if ((cdrom_sector_flags & 0x06) == 0x04) { - /* Add error flags. */ - cdrom_image_log("CD-ROM %i: Full error flags\n", id); - memcpy(b + cdrom_sector_size, extra_buffer, 296); - cdrom_sector_size += 296; - } - - if ((cdrom_sector_flags & 0x700) == 0x100) { - cdrom_image_log("CD-ROM %i: Raw subchannel data\n", id); - memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96); - cdrom_sector_size += 96; - } - else if ((cdrom_sector_flags & 0x700) == 0x200) { - cdrom_image_log("CD-ROM %i: Q subchannel data\n", id); - memcpy(b + cdrom_sector_size, raw_buffer + 2352, 16); - cdrom_sector_size += 16; - } - else if ((cdrom_sector_flags & 0x700) == 0x400) { - cdrom_image_log("CD-ROM %i: R/W subchannel data\n", id); - memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96); - cdrom_sector_size += 96; - } - - *len = cdrom_sector_size; - - return 1; + memcpy(output, dev->cd_buffer, len * 2); + memmove(dev->cd_buffer, &dev->cd_buffer[len], (BUF_SIZE - len) * 2); + dev->cd_buflen -= len; + return ret; } -static uint32_t image_size(uint8_t id) +void +image_audio_stop(uint8_t id) { - cdrom_t *dev = cdrom[id]; + cdrom_t *dev = cdrom[id]; - return dev->cdrom_capacity; + dev->cd_state = CD_STOPPED; } -static int image_readtoc(uint8_t id, unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single) + +static uint8_t +image_playaudio(uint8_t id, uint32_t pos, uint32_t len, int ismsf) { - if (!cdimg[id]) return 0; - int len=4; - int c,d; - uint32_t temp; - - int first_track; - int last_track; - int number; - unsigned char attr; - TMSF tmsf; - - cdimg[id]->GetAudioTracks(first_track, last_track, tmsf); - - b[2] = first_track; - b[3] = last_track; - - d = 0; - for (c = 0; c <= last_track; c++) - { - cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); - if (number >= starttrack) - { - d=c; - break; - } - } - - if (starttrack != 0xAA) - { - cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); - b[2] = number; - } - - for (c = d; c <= last_track; c++) - { - if ((len + 8) > maxlen) - break; - cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); - - b[len++] = 0; /* reserved */ - b[len++] = attr; - b[len++] = number; /* track number */ - b[len++] = 0; /* reserved */ - - if (msf) - { - b[len++] = 0; - b[len++] = tmsf.min; - b[len++] = tmsf.sec; - b[len++] = tmsf.fr; - } - else - { - temp = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; - b[len++] = temp >> 24; - b[len++] = temp >> 16; - b[len++] = temp >> 8; - b[len++] = temp; - } - if (single) - break; - } - b[0] = (uint8_t)(((len-2) >> 8) & 0xff); - b[1] = (uint8_t)((len-2) & 0xff); - return len; -} - -static int image_readtoc_session(uint8_t id, unsigned char *b, int msf, int maxlen) -{ - int len = 4; - - int number; - TMSF tmsf; - unsigned char attr; - - if (!cdimg[id]) return 0; - - cdimg[id]->GetAudioTrackInfo(1, number, tmsf, attr); - - if (number == 0) - { - number = 1; - } - - b[2] = 1; - b[3] = 1; - b[len++] = 0; /* reserved */ - b[len++] = attr; - b[len++] = number; /* track number */ - b[len++] = 0; /* reserved */ - if (msf) - { - b[len++] = 0; - b[len++] = tmsf.min; - b[len++] = tmsf.sec; - b[len++] = tmsf.fr; - } - else - { - uint32_t temp = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; /* Do the - 150. */ - b[len++] = temp >> 24; - b[len++] = temp >> 16; - b[len++] = temp >> 8; - b[len++] = temp; - } - - if (maxlen < len) - { - return maxlen; - } - - return len; -} - -static int image_readtoc_raw(uint8_t id, unsigned char *b, int maxlen) -{ - int track; - int len = 4; - - int first_track; - int last_track; - int number; - unsigned char attr; - TMSF tmsf; - - if (!cdimg[id]) return 0; - - cdimg[id]->GetAudioTracks(first_track, last_track, tmsf); - - b[2] = first_track; - b[3] = last_track; - - for (track = first_track; track <= last_track; track++) - { - if ((len + 11) > maxlen) - { - cdrom_image_log("image_readtocraw: This iteration would fill the buffer beyond the bounds, aborting...\n"); - return len; - } - - cdimg[id]->GetAudioTrackInfo(track, number, tmsf, attr); - - b[len++] = track; - if (len == maxlen) return len; - b[len++]= attr; - if (len == maxlen) return len; - b[len++]=0; - if (len == maxlen) return len; - b[len++]=0; - if (len == maxlen) return len; - b[len++]=0; - if (len == maxlen) return len; - b[len++]=0; - if (len == maxlen) return len; - b[len++]=0; - if (len == maxlen) return len; - b[len++]=0; - if (len == maxlen) return len; - b[len++] = tmsf.min; - if (len == maxlen) return len; - b[len++] = tmsf.sec; - if (len == maxlen) return len; - b[len++] = tmsf.fr; - if (len == maxlen) return len; - } - return len; -} - -static int image_status(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - if (!cdimg[id]) return CD_STATUS_EMPTY; - if (cdrom_image[id].image_is_iso) return CD_STATUS_DATA_ONLY; - if (cdimg[id]->HasAudioTracks()) - { - switch(dev->cd_state) - { - case CD_PLAYING: - return CD_STATUS_PLAYING; - case CD_PAUSED: - return CD_STATUS_PAUSED; - case CD_STOPPED: - default: - return CD_STATUS_STOPPED; - } - } - return CD_STATUS_DATA_ONLY; -} - -void image_reset(UNUSED(uint8_t id)) -{ - return; -} - -void image_close(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - dev->cd_state = CD_STOPPED; - if (cdimg[id]) - { - delete cdimg[id]; - cdimg[id] = NULL; - } - memset(cdrom_image[id].image_path, 0, 2048); -} - -static char afn[1024]; - -int image_open(uint8_t id, wchar_t *fn) -{ - cdrom_t *dev = cdrom[id]; - - wcscpy(cdrom_image[id].image_path, fn); - - if (! wcscasecmp(plat_get_extension(fn), L"ISO")) - { - cdrom_image[id].image_is_iso = 1; - } - else - { - cdrom_image[id].image_is_iso = 0; - } - - cdimg[id] = new CDROM_Interface_Image(); - memset(afn, 0, sizeof(afn)); - wcstombs(afn, fn, sizeof(afn)); - if (!cdimg[id]->SetDevice(afn, false)) - { - image_close(id); - cdrom_set_null_handler(id); - return 1; - } - dev->cd_state = CD_STOPPED; + cdrom_t *dev = cdrom[id]; + if (!cdimg[id]) + return 0; + int number; + unsigned char attr; + TMSF tmsf; + int m = 0, s = 0, f = 0; + cdimg[id]->GetAudioTrackInfo(cdimg[id]->GetTrack(pos), number, tmsf, attr); + if (attr == DATA_TRACK) { + cdrom_image_log("Can't play data track\n"); dev->seek_pos = 0; - dev->cd_buflen = 0; - dev->cdrom_capacity = image_get_last_block(id, 0, 0, 4096, 0) + 1; - cdrom_drives[id].handler = &image_cdrom; + dev->cd_state = CD_STOPPED; + return 0; + } + cdrom_image_log("Play audio - %08X %08X %i\n", pos, len, ismsf); + if (ismsf == 2) { + cdimg[id]->GetAudioTrackInfo(pos, number, tmsf, attr); + pos = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; + cdimg[id]->GetAudioTrackInfo(len, number, tmsf, attr); + len = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; + } else if (ismsf == 1) { + m = (pos >> 16) & 0xff; + s = (pos >> 8) & 0xff; + f = pos & 0xff; - return 0; + if (pos == 0xffffff) { + cdrom_image_log("Playing from current position (MSF)\n"); + pos = dev->seek_pos; + } else + pos = MSFtoLBA(m, s, f) - 150; + + m = (len >> 16) & 0xff; + s = (len >> 8) & 0xff; + f = len & 0xff; + len = MSFtoLBA(m, s, f) - 150; + + cdrom_image_log("MSF - pos = %08X len = %08X\n", pos, len); + } else if (ismsf == 0) { + if (pos == 0xffffffff) { + cdrom_image_log("Playing from current position\n"); + pos = dev->seek_pos; + } + len += pos; + } + + dev->seek_pos = pos; + dev->cd_end = len; + dev->cd_state = CD_PLAYING; + dev->cd_buflen = 0; + + return 1; } -static void image_exit(uint8_t id) + +static void +image_pause(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + if (!cdimg[id] || cdrom_image[id].image_is_iso) return; + if (dev->cd_state == CD_PLAYING) + dev->cd_state = CD_PAUSED; +} + + +static void +image_resume(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + if (!cdimg[id] || cdrom_image[id].image_is_iso) + return; + if (dev->cd_state == CD_PAUSED) + dev->cd_state = CD_PLAYING; +} + + +static void +image_stop(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + if (!cdimg[id] || cdrom_image[id].image_is_iso) + return; + dev->cd_state = CD_STOPPED; +} + + +static int +image_ready(uint8_t id) +{ + if (!cdimg[id] || (wcslen(cdrom_image[id].image_path) == 0)) + return 0; + + return 1; +} + + +static int +image_get_last_block(uint8_t id) +{ + int first_track, last_track; + int number, c; + unsigned char attr; + TMSF tmsf; + uint32_t lb=0; + + if (!cdimg[id]) + return 0; + + cdimg[id]->GetAudioTracks(first_track, last_track, tmsf); + + for (c = 0; c <= last_track; c++) { + uint32_t address; + cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); + address = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; /* Do the - 150 here as well. */ + if (address > lb) + lb = address; + } + return lb; +} + + +static int +image_medium_changed(uint8_t id) +{ + /* There is no way to change the medium within an already mounted image. */ + return 0; +} + + +static uint8_t +image_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf) +{ + cdrom_t *dev = cdrom[id]; + uint8_t ret; + int pos = 0; + uint32_t cdpos; + TMSF relPos, absPos; + unsigned char attr, track, index; + + cdpos = dev->seek_pos; + + if (!cdimg[id]) + return 0; + + cdimg[id]->GetAudioSub(cdpos, attr, track, index, relPos, absPos); + + if (cdrom_image[id].image_is_iso) + ret = 0x15; + else { + if (dev->cd_state == CD_PLAYING) + ret = 0x11; + else if (dev->cd_state == CD_PAUSED) + ret = 0x12; + else + ret = 0x13; + } + + b[pos++] = attr; + b[pos++] = track; + b[pos++] = index; + + if (msf) { + b[pos + 3] = (uint8_t) absPos.fr; + b[pos + 2] = (uint8_t) absPos.sec; + b[pos + 1] = (uint8_t) absPos.min; + b[pos] = 0; + pos += 4; + b[pos + 3] = (uint8_t) relPos.fr; + b[pos + 2] = (uint8_t) relPos.sec; + b[pos + 1] = (uint8_t) relPos.min; + b[pos] = 0; + pos += 4; + } else { + uint32_t dat = MSFtoLBA(absPos.min, absPos.sec, absPos.fr) - 150; + b[pos++] = (dat >> 24) & 0xff; + b[pos++] = (dat >> 16) & 0xff; + b[pos++] = (dat >> 8) & 0xff; + b[pos++] = dat & 0xff; + dat = MSFtoLBA(relPos.min, relPos.sec, relPos.fr); + b[pos++] = (dat >> 24) & 0xff; + b[pos++] = (dat >> 16) & 0xff; + b[pos++] = (dat >> 8) & 0xff; + b[pos++] = dat & 0xff; + } + + return ret; +} + + +static int +image_is_track_audio(uint8_t id, uint32_t pos, int ismsf) +{ + int m, s, f; + unsigned char attr; + TMSF tmsf; + int number; + + if (!cdimg[id] || cdrom_image[id].image_is_iso) + return 0; + + if (ismsf) { + m = (pos >> 16) & 0xff; + s = (pos >> 8) & 0xff; + f = pos & 0xff; + pos = MSFtoLBA(m, s, f) - 150; + } + + /* GetTrack requires LBA. */ + cdimg[id]->GetAudioTrackInfo(cdimg[id]->GetTrack(pos), number, tmsf, attr); + + return attr == AUDIO_TRACK; +} + + +static int +is_legal(int id, int cdrom_sector_type, int cdrom_sector_flags, int audio, int mode2) +{ + if (!(cdrom_sector_flags & 0x70)) { /* 0x00/0x08/0x80/0x88 are illegal modes */ + cdrom_image_log("CD-ROM %i: [Any Mode] 0x00/0x08/0x80/0x88 are illegal modes\n", id); + return 0; + } + + if ((cdrom_sector_type != 1) && !audio) { + if (!(cdrom_sector_flags & 0x70)) { /* 0x00/0x08/0x80/0x88 are illegal modes */ + cdrom_image_log("CD-ROM %i: [Any Data Mode] 0x00/0x08/0x80/0x88 are illegal modes\n", id); + return 0; + } + + if ((cdrom_sector_flags & 0x06) == 0x06) { + cdrom_image_log("CD-ROM %i: [Any Data Mode] Invalid error flags\n", id); + return 0; + } + + if (((cdrom_sector_flags & 0x700) == 0x300) || ((cdrom_sector_flags & 0x700) > 0x400)) { + cdrom_image_log("CD-ROM %i: [Any Data Mode] Invalid subchannel data flags (%02X)\n", id, cdrom_sector_flags & 0x700); + return 0; + } + + if ((cdrom_sector_flags & 0x18) == 0x08) { /* EDC/ECC without user data is an illegal mode */ + cdrom_image_log("CD-ROM %i: [Any Data Mode] EDC/ECC without user data is an illegal mode\n", id); + return 0; + } + + if (((cdrom_sector_flags & 0xf0) == 0x90) || ((cdrom_sector_flags & 0xf0) == 0xc0)) { /* 0x90/0x98/0xC0/0xC8 are illegal modes */ + cdrom_image_log("CD-ROM %i: [Any Data Mode] 0x90/0x98/0xC0/0xC8 are illegal modes\n", id); + return 0; + } + + if (((cdrom_sector_type > 3) && (cdrom_sector_type != 8)) || (mode2 && (mode2 & 0x03))) { + if ((cdrom_sector_flags & 0xf0) == 0x30) { /* 0x30/0x38 are illegal modes */ + cdrom_image_log("CD-ROM %i: [Any XA Mode 2] 0x30/0x38 are illegal modes\n", id); + return 0; + } + if (((cdrom_sector_flags & 0xf0) == 0xb0) || ((cdrom_sector_flags & 0xf0) == 0xd0)) { /* 0xBx and 0xDx are illegal modes */ + cdrom_image_log("CD-ROM %i: [Any XA Mode 2] 0xBx and 0xDx are illegal modes\n", id); + return 0; + } + } + } + + return 1; +} + + +static void +read_sector_to_buffer(uint8_t id, uint8_t *raw_buffer, uint32_t msf, uint32_t lba, int mode2, int len) +{ + uint8_t *bb = raw_buffer; + + cdimg[id]->ReadSector(raw_buffer + 16, false, lba); + + /* Sync bytes */ + bb[0] = 0; + memset(bb + 1, 0xff, 10); + bb[11] = 0; + bb += 12; + + /* Sector header */ + bb[0] = (msf >> 16) & 0xff; + bb[1] = (msf >> 8) & 0xff; + bb[2] = msf & 0xff; + + bb[3] = 1; /* mode 1 data */ + bb += mode2 ? 12 : 4; + bb += len; + if (mode2 && ((mode2 & 0x03) == 1)) + memset(bb, 0, 280); + else if (!mode2) + memset(bb, 0, 288); +} + + +static void +read_audio(int id, uint32_t lba, uint8_t *b) +{ + if (cdimg[id]->GetSectorSize(lba) == 2352) + cdimg[id]->ReadSector(raw_buffer, true, lba); + else + cdimg[id]->ReadSectorSub(raw_buffer, lba); + + memcpy(b, raw_buffer, 2352); + cdrom_sector_size = 2352; +} + + +static void +read_mode1(int id, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) +{ + if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2048)) + read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, 2048); + else if (cdimg[id]->GetSectorSize(lba) == 2352) + cdimg[id]->ReadSector(raw_buffer, true, lba); + else + cdimg[id]->ReadSectorSub(raw_buffer, lba); + + cdrom_sector_size = 0; + + if (cdrom_sector_flags & 0x80) { /* Sync */ + cdrom_image_log("CD-ROM %i: [Mode 1] Sync\n", id); + memcpy(b, raw_buffer, 12); + cdrom_sector_size += 12; + b += 12; + } + + if (cdrom_sector_flags & 0x20) { /* Header */ + cdrom_image_log("CD-ROM %i: [Mode 1] Header\n", id); + memcpy(b, raw_buffer + 12, 4); + cdrom_sector_size += 4; + b += 4; + } + + if (cdrom_sector_flags & 0x40) { /* Sub-header */ + if (!(cdrom_sector_flags & 0x10)) { /* No user data */ + cdrom_image_log("CD-ROM %i: [Mode 1] Sub-header\n", id); + memcpy(b, raw_buffer + 16, 8); + cdrom_sector_size += 8; + b += 8; + } + } + + if (cdrom_sector_flags & 0x10) { /* User data */ + cdrom_image_log("CD-ROM %i: [Mode 1] User data\n", id); + memcpy(b, raw_buffer + 16, 2048); + cdrom_sector_size += 2048; + b += 2048; + } + + if (cdrom_sector_flags & 0x08) { /* EDC/ECC */ + cdrom_image_log("CD-ROM %i: [Mode 1] EDC/ECC\n", id); + memcpy(b, raw_buffer + 2064, 288); + cdrom_sector_size += 288; + b += 288; + } +} + + +static void +read_mode2_non_xa(int id, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) +{ + if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2336)) + read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, 2336); + else if (cdimg[id]->GetSectorSize(lba) == 2352) + cdimg[id]->ReadSector(raw_buffer, true, lba); + else + cdimg[id]->ReadSectorSub(raw_buffer, lba); + + cdrom_sector_size = 0; + + if (cdrom_sector_flags & 0x80) { /* Sync */ + cdrom_image_log("CD-ROM %i: [Mode 2 Formless] Sync\n", id); + memcpy(b, raw_buffer, 12); + cdrom_sector_size += 12; + b += 12; + } + + if (cdrom_sector_flags & 0x20) { /* Header */ + cdrom_image_log("CD-ROM %i: [Mode 2 Formless] Header\n", id); + memcpy(b, raw_buffer + 12, 4); + cdrom_sector_size += 4; + b += 4; + } + + /* Mode 1 sector, expected type is 1 type. */ + if (cdrom_sector_flags & 0x40) { /* Sub-header */ + cdrom_image_log("CD-ROM %i: [Mode 2 Formless] Sub-header\n", id); + memcpy(b, raw_buffer + 16, 8); + cdrom_sector_size += 8; + b += 8; + } + + if (cdrom_sector_flags & 0x10) { /* User data */ + cdrom_image_log("CD-ROM %i: [Mode 2 Formless] User data\n", id); + memcpy(b, raw_buffer + 24, 2336); + cdrom_sector_size += 2336; + b += 2336; + } +} + + +static void +read_mode2_xa_form1(int id, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) +{ + if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2048)) + read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, 2048); + else if (cdimg[id]->GetSectorSize(lba) == 2352) + cdimg[id]->ReadSector(raw_buffer, true, lba); + else + cdimg[id]->ReadSectorSub(raw_buffer, lba); + + cdrom_sector_size = 0; + + if (cdrom_sector_flags & 0x80) { /* Sync */ + cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] Sync\n", id); + memcpy(b, raw_buffer, 12); + cdrom_sector_size += 12; + b += 12; + } + + if (cdrom_sector_flags & 0x20) { /* Header */ + cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] Header\n", id); + memcpy(b, raw_buffer + 12, 4); + cdrom_sector_size += 4; + b += 4; + } + + if (cdrom_sector_flags & 0x40) { /* Sub-header */ + cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] Sub-header\n", id); + memcpy(b, raw_buffer + 16, 8); + cdrom_sector_size += 8; + b += 8; + } + + if (cdrom_sector_flags & 0x10) { /* User data */ + cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] User data\n", id); + memcpy(b, raw_buffer + 24, 2048); + cdrom_sector_size += 2048; + b += 2048; + } + + if (cdrom_sector_flags & 0x08) { /* EDC/ECC */ + cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] EDC/ECC\n", id); + memcpy(b, raw_buffer + 2072, 280); + cdrom_sector_size += 280; + b += 280; + } +} + + +static void +read_mode2_xa_form2(int id, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) +{ + if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2324)) + read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, 2324); + else if (cdimg[id]->GetSectorSize(lba) == 2352) + cdimg[id]->ReadSector(raw_buffer, true, lba); + else + cdimg[id]->ReadSectorSub(raw_buffer, lba); + + cdrom_sector_size = 0; + + if (cdrom_sector_flags & 0x80) { /* Sync */ + cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] Sync\n", id); + memcpy(b, raw_buffer, 12); + cdrom_sector_size += 12; + b += 12; + } + + if (cdrom_sector_flags & 0x20) { /* Header */ + cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] Header\n", id); + memcpy(b, raw_buffer + 12, 4); + cdrom_sector_size += 4; + b += 4; + } + + if (cdrom_sector_flags & 0x40) { /* Sub-header */ + cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] Sub-header\n", id); + memcpy(b, raw_buffer + 16, 8); + cdrom_sector_size += 8; + b += 8; + } + + if (cdrom_sector_flags & 0x10) { /* User data */ + cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] User data\n", id); + memcpy(b, raw_buffer + 24, 2328); + cdrom_sector_size += 2328; + b += 2328; + } +} + + +static int +image_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, + int cdrom_sector_flags, int *len) +{ + uint8_t *b, *temp_b; + uint32_t msf, lba; + int audio, mode2; + int m, s, f; + + if (!cdimg[id]) + return 0; + + if (!cdrom_drives[id].host_drive) + return 0; + + b = temp_b = buffer; + + *len = 0; + + if (ismsf) { + m = (sector >> 16) & 0xff; + s = (sector >> 8) & 0xff; + f = sector & 0xff; + lba = MSFtoLBA(m, s, f) - 150; + msf = sector; + } else { + lba = sector; + msf = cdrom_lba_to_msf_accurate(sector); + } + + if (cdrom_image[id].image_is_iso) { + audio = 0; + mode2 = cdimg[id]->IsMode2(lba) ? 1 : 0; + } else { + audio = image_is_track_audio(id, sector, ismsf); + mode2 = cdimg[id]->IsMode2(lba) ? 1 : 0; + } + mode2 <<= 2; + mode2 |= cdimg[id]->GetMode2Form(lba); + + memset(raw_buffer, 0, 2448); + memset(extra_buffer, 0, 296); + + if (!(cdrom_sector_flags & 0xf0)) { /* 0x00 and 0x08 are illegal modes */ + cdrom_image_log("CD-ROM %i: [Mode 1] 0x00 and 0x08 are illegal modes\n", id); + return 0; + } + + if (!is_legal(id, cdrom_sector_type, cdrom_sector_flags, audio, mode2)) + return 0; + + if ((cdrom_sector_type == 3) || ((cdrom_sector_type > 4) && (cdrom_sector_type != 8))) { + if (cdrom_sector_type == 3) + cdrom_image_log("CD-ROM %i: Attempting to read a Yellowbook Mode 2 data sector from an image\n", id); + if (cdrom_sector_type > 4) + cdrom_image_log("CD-ROM %i: Attempting to read a XA Mode 2 Form 2 data sector from an image\n", id); + return 0; + } else if (cdrom_sector_type == 1) { + if (!audio || cdrom_image[id].image_is_iso) { + cdrom_image_log("CD-ROM %i: [Audio] Attempting to read an audio sector from a data image\n", id); + return 0; + } + + read_audio(id, lba, temp_b); + } else if (cdrom_sector_type == 2) { + if (audio || mode2) { + cdrom_image_log("CD-ROM %i: [Mode 1] Attempting to read a sector of another type\n", id); + return 0; + } + + read_mode1(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + } else if (cdrom_sector_type == 3) { + if (audio || !mode2 || (mode2 & 0x03)) { + cdrom_image_log("CD-ROM %i: [Mode 2 Formless] Attempting to read a sector of another type\n", id); + return 0; + } + + read_mode2_non_xa(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + } else if (cdrom_sector_type == 4) { + if (audio || !mode2 || ((mode2 & 0x03) != 1)) { + cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] Attempting to read a sector of another type\n", id); + return 0; + } + + read_mode2_xa_form1(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + } else if (cdrom_sector_type == 5) { + if (audio || !mode2 || ((mode2 & 0x03) != 2)) { + cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] Attempting to read a sector of another type\n", id); + return 0; + } + + read_mode2_xa_form2(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + } else if (cdrom_sector_type == 8) { + if (audio) { + cdrom_image_log("CD-ROM %i: [Any Data] Attempting to read a data sector from an audio track\n", id); + return 0; + } + + if (mode2 && ((mode2 & 0x03) == 1)) + read_mode2_xa_form1(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + else if (!mode2) + read_mode1(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + else { + cdrom_image_log("CD-ROM %i: [Any Data] Attempting to read a data sector whose cooked size is not 2048 bytes\n", id); + return 0; + } + } else { + if (mode2) { + if ((mode2 & 0x03) == 0x01) + read_mode2_xa_form1(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + else if ((mode2 & 0x03) == 0x02) + read_mode2_xa_form2(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + else + read_mode2_non_xa(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + } else { + if (audio) + read_audio(id, lba, temp_b); + else + read_mode1(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + } + } + + if ((cdrom_sector_flags & 0x06) == 0x02) { + /* Add error flags. */ + cdrom_image_log("CD-ROM %i: Error flags\n", id); + memcpy(b + cdrom_sector_size, extra_buffer, 294); + cdrom_sector_size += 294; + } else if ((cdrom_sector_flags & 0x06) == 0x04) { + /* Add error flags. */ + cdrom_image_log("CD-ROM %i: Full error flags\n", id); + memcpy(b + cdrom_sector_size, extra_buffer, 296); + cdrom_sector_size += 296; + } + + if ((cdrom_sector_flags & 0x700) == 0x100) { + cdrom_image_log("CD-ROM %i: Raw subchannel data\n", id); + memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96); + cdrom_sector_size += 96; + } else if ((cdrom_sector_flags & 0x700) == 0x200) { + cdrom_image_log("CD-ROM %i: Q subchannel data\n", id); + memcpy(b + cdrom_sector_size, raw_buffer + 2352, 16); + cdrom_sector_size += 16; + } else if ((cdrom_sector_flags & 0x700) == 0x400) { + cdrom_image_log("CD-ROM %i: R/W subchannel data\n", id); + memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96); + cdrom_sector_size += 96; + } + + *len = cdrom_sector_size; + + return 1; +} + + +static uint32_t +image_size(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + return dev->cdrom_capacity; +} + + +static int +image_readtoc(uint8_t id, unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single) +{ + int number, len = 4; + int c, d, first_track, last_track; + uint32_t temp; + unsigned char attr; + TMSF tmsf; + + if (!cdimg[id]) + return 0; + + cdimg[id]->GetAudioTracks(first_track, last_track, tmsf); + + b[2] = first_track; + b[3] = last_track; + + d = 0; + for (c = 0; c <= last_track; c++) { + cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); + if (number >= starttrack) { + d=c; + break; + } + } + + if (starttrack != 0xAA) { + cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); + b[2] = number; + } + + for (c = d; c <= last_track; c++) { + cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); + + b[len++] = 0; /* reserved */ + b[len++] = attr; + b[len++] = number; /* track number */ + b[len++] = 0; /* reserved */ + + if (msf) { + b[len++] = 0; + b[len++] = tmsf.min; + b[len++] = tmsf.sec; + b[len++] = tmsf.fr; + } else { + temp = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; + b[len++] = temp >> 24; + b[len++] = temp >> 16; + b[len++] = temp >> 8; + b[len++] = temp; + } + + if (single) + break; + } + + b[0] = (uint8_t)(((len-2) >> 8) & 0xff); + b[1] = (uint8_t)((len-2) & 0xff); + + return len; +} + + +static int +image_readtoc_session(uint8_t id, unsigned char *b, int msf, int maxlen) +{ + int number, len = 4; + TMSF tmsf; + unsigned char attr; + uint32_t temp; + + if (!cdimg[id]) + return 0; + + cdimg[id]->GetAudioTrackInfo(1, number, tmsf, attr); + + if (number == 0) + number = 1; + + b[2] = b[3] = 1; + b[len++] = 0; /* reserved */ + b[len++] = attr; + b[len++] = number; /* track number */ + b[len++] = 0; /* reserved */ + if (msf) { + b[len++] = 0; + b[len++] = tmsf.min; + b[len++] = tmsf.sec; + b[len++] = tmsf.fr; + } else { + temp = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; /* Do the - 150. */ + b[len++] = temp >> 24; + b[len++] = temp >> 16; + b[len++] = temp >> 8; + b[len++] = temp; + } + + if (maxlen < len) + return maxlen; + + return len; +} + + +static int +image_readtoc_raw(uint8_t id, unsigned char *b, int maxlen) +{ + int track, len = 4; + int first_track, last_track; + int number; + unsigned char attr; + TMSF tmsf; + + if (!cdimg[id]) + return 0; + + cdimg[id]->GetAudioTracks(first_track, last_track, tmsf); + + b[2] = first_track; + b[3] = last_track; + + for (track = first_track; track <= last_track; track++) { + cdimg[id]->GetAudioTrackInfo(track, number, tmsf, attr); + + b[len++] = track; + b[len++]= attr; + b[len++]=0; + b[len++]=0; + b[len++]=0; + b[len++]=0; + b[len++]=0; + b[len++]=0; + b[len++] = tmsf.min; + b[len++] = tmsf.sec; + b[len++] = tmsf.fr; + } + + return len; +} + + +static int +image_status(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + if (!cdimg[id]) + return CD_STATUS_EMPTY; + + if (cdrom_image[id].image_is_iso) + return CD_STATUS_DATA_ONLY; + + if (cdimg[id]->HasAudioTracks()) { + switch(dev->cd_state) { + case CD_PLAYING: + return CD_STATUS_PLAYING; + case CD_PAUSED: + return CD_STATUS_PAUSED; + case CD_STOPPED: + default: + return CD_STATUS_STOPPED; + } + } + + return CD_STATUS_DATA_ONLY; +} + + +void +image_reset(UNUSED(uint8_t id)) +{ + return; +} + + +void +image_close(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + dev->cd_state = CD_STOPPED; + if (cdimg[id]) { + delete cdimg[id]; + cdimg[id] = NULL; + } +} + + +int +image_open(uint8_t id, wchar_t *fn) +{ + cdrom_t *dev = cdrom[id]; + + wcscpy(cdrom_image[id].image_path, fn); + + if (! wcscasecmp(plat_get_extension(fn), L"ISO")) + cdrom_image[id].image_is_iso = 1; + else + cdrom_image[id].image_is_iso = 0; + + cdimg[id] = new CDROM_Interface_Image(); + memset(afn, 0, sizeof(afn)); + wcstombs(afn, fn, sizeof(afn)); + if (!cdimg[id]->SetDevice(afn, false)) { + image_close(id); + cdrom_set_null_handler(id); + cdrom_image_log("[f] image_open(): cdrom[%i]->handler = %08X\n", id, cdrom[id]->handler); + return 1; + } + dev->cd_state = CD_STOPPED; + dev->seek_pos = 0; + dev->cd_buflen = 0; + dev->cdrom_capacity = image_get_last_block(id) + 1; + cdrom[id]->handler = &image_cdrom; + + return 0; +} + + +static void +image_exit(uint8_t id) { cdrom_t *dev = cdrom[id]; dev->handler_inited = 0; } + /* TODO: Check for what data type a mixed CD is. */ static int image_media_type_id(uint8_t id) { - if (!cdrom_image[id].image_is_iso) - { - return 3; /* Mixed mode CD. */ - } - - if (image_size(id) <= 405000) - { + if (image_size(id) > 405000) + return 65; /* DVD. */ + else { + if (cdrom_image[id].image_is_iso) return 1; /* Data CD. */ - } else - { - return 65; /* DVD. */ - } + return 3; /* Mixed mode CD. */ + } } + CDROM image_cdrom = { - image_ready, - image_medium_changed, - image_media_type_id, - image_audio_callback, - image_audio_stop, - image_readtoc, - image_readtoc_session, - image_readtoc_raw, - image_getcurrentsubchannel, - NULL, - image_readsector_raw, - image_playaudio, - image_load, - image_eject, - image_pause, - image_resume, - image_size, - image_status, - image_is_track_audio, - image_stop, - image_exit + image_ready, + image_medium_changed, + image_media_type_id, + image_audio_callback, + image_audio_stop, + image_readtoc, + image_readtoc_session, + image_readtoc_raw, + image_getcurrentsubchannel, + image_readsector_raw, + image_playaudio, + image_pause, + image_resume, + image_size, + image_status, + image_stop, + image_exit }; diff --git a/src/cdrom/cdrom_null.c b/src/cdrom/cdrom_null.c index 3c939f7d6..15b2c937f 100644 --- a/src/cdrom/cdrom_null.c +++ b/src/cdrom/cdrom_null.c @@ -9,19 +9,20 @@ * Implementation of the CD-ROM null interface for unmounted * guest CD-ROM drives. * - * Version: @(#)cdrom_null.c 1.0.6 2017/11/04 + * Version: @(#)cdrom_null.c 1.0.7 2018/03/26 * * Authors: Sarah Walker, * Miran Grca, * * Copyright 2008-2016 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #include #include #include #include #include "../86box.h" +#include "../scsi/scsi.h" #include "cdrom.h" @@ -50,17 +51,6 @@ null_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf) } -static void -null_eject(uint8_t id) -{ -} - - -static void -null_load(uint8_t id) -{ -} - static int null_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len) { @@ -114,7 +104,7 @@ cdrom_null_reset(uint8_t id) void cdrom_set_null_handler(uint8_t id); int -cdrom_null_open(uint8_t id, char d) +cdrom_null_open(uint8_t id) { cdrom_set_null_handler(id); @@ -134,20 +124,6 @@ void null_exit(uint8_t id) } -static int -null_is_track_audio(uint8_t id, uint32_t pos, int ismsf) -{ - return(0); -} - - -static int -null_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t *len) -{ - return(0); -} - - static int null_media_type_id(uint8_t id) { @@ -158,7 +134,7 @@ null_media_type_id(uint8_t id) void cdrom_set_null_handler(uint8_t id) { - cdrom_drives[id].handler = &null_cdrom; + cdrom[id]->handler = &null_cdrom; cdrom_drives[id].host_drive = 0; memset(cdrom_image[id].image_path, 0, sizeof(cdrom_image[id].image_path)); } @@ -174,16 +150,12 @@ static CDROM null_cdrom = { null_readtoc_session, null_readtoc_raw, null_getcurrentsubchannel, - null_pass_through, null_readsector_raw, NULL, - null_load, - null_eject, NULL, NULL, null_size, null_status, - null_is_track_audio, NULL, null_exit }; diff --git a/src/cdrom/cdrom_null.h b/src/cdrom/cdrom_null.h index 0fb9ee166..480acb29c 100644 --- a/src/cdrom/cdrom_null.h +++ b/src/cdrom/cdrom_null.h @@ -9,18 +9,18 @@ * Implementation of the CD-ROM null interface for unmounted * guest CD-ROM drives. * - * Version: @(#)cdrom_null.h 1.0.3 2017/09/03 + * Version: @(#)cdrom_null.h 1.0.4 2018/03/31 * * Authors: Sarah Walker, * Miran Grca, - * Copyright 2008-2016 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #ifndef EMU_CDROM_NULL_H #define EMU_CDROM_NULL_H -extern int cdrom_null_open(uint8_t id, char d); +extern int cdrom_null_open(uint8_t id); extern void cdrom_null_reset(uint8_t id); extern void null_close(uint8_t id); diff --git a/src/config.c b/src/config.c index 494600002..f419539da 100644 --- a/src/config.c +++ b/src/config.c @@ -8,7 +8,7 @@ * * Configuration file handler. * - * Version: @(#)config.c 1.0.46 2018/03/18 + * Version: @(#)config.c 1.0.48 2018/05/25 * * Authors: Sarah Walker, * Miran Grca, @@ -23,23 +23,23 @@ * it on Windows XP, and possibly also Vista. Use the * -DANSI_CFG for use on these systems. */ +#include +#include #include #include #include #include #include -#include +#define HAVE_STDARG_H #include "86box.h" #include "cpu/cpu.h" +#include "device.h" #include "nvr.h" #include "config.h" -#include "device.h" #include "lpt.h" -#include "cdrom/cdrom.h" #include "disk/hdd.h" #include "disk/hdc.h" #include "disk/hdc_ide.h" -#include "disk/zip.h" #include "floppy/fdd.h" #include "floppy/fdc.h" #include "game/gameport.h" @@ -47,6 +47,8 @@ #include "mouse.h" #include "network/network.h" #include "scsi/scsi.h" +#include "cdrom/cdrom.h" +#include "disk/zip.h" #include "sound/sound.h" #include "sound/midi.h" #include "sound/snd_dbopl.h" @@ -103,6 +105,26 @@ typedef struct { static list_t config_head; +#ifdef ENABLE_CONFIG_LOG +int config_do_log = ENABLE_CONFIG_LOG; +#endif + + +static void +config_log(const char *format, ...) +{ +#ifdef ENABLE_CONFIG_LOG + va_list ap; + + if (config_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + static section_t * find_section(char *name) { @@ -522,7 +544,6 @@ load_video(void) if (machines[machine].fixed_gfxcard) { config_delete_var(cat, "gfxcard"); - config_delete_var(cat, "voodoo"); gfxcard = GFX_INTERNAL; } else { p = config_get_string(cat, "gfxcard", NULL); @@ -536,11 +557,9 @@ load_video(void) } } gfxcard = video_get_video_from_internal_name(p); - - video_speed = config_get_int(cat, "video_speed", -1); - - voodoo_enabled = !!config_get_int(cat, "voodoo", 0); } + + voodoo_enabled = !!config_get_int(cat, "voodoo", 0); } @@ -612,12 +631,12 @@ load_sound(void) GUS = !!config_get_int(cat, "gus", 0); memset(temp, '\0', sizeof(temp)); - p = config_get_string(cat, "opl3_type", "dbopl"); + p = config_get_string(cat, "opl_type", "dbopl"); strcpy(temp, p); if (!strcmp(temp, "nukedopl") || !strcmp(temp, "1")) - opl3_type = 1; - else - opl3_type = 0; + opl_type = 1; + else + opl_type = 0; memset(temp, '\0', sizeof(temp)); p = config_get_string(cat, "sound_type", "float"); @@ -658,9 +677,9 @@ load_network(void) if (p != NULL) { if ((network_dev_to_id(p) == -1) || (network_ndev == 1)) { if ((network_ndev == 1) && strcmp(network_host, "none")) { - ui_msgbox(MBX_ERROR, (wchar_t *)IDS_2140); + ui_msgbox(MBX_ERROR, (wchar_t *)IDS_2103); } else if (network_dev_to_id(p) == -1) { - ui_msgbox(MBX_ERROR, (wchar_t *)IDS_2141); + ui_msgbox(MBX_ERROR, (wchar_t *)IDS_2104); } strcpy(network_host, "none"); @@ -714,8 +733,7 @@ static void load_other_peripherals(void) { char *cat = "Other peripherals"; - char temp[512], *p; - int c; + char *p; p = config_get_string(cat, "scsicard", NULL); if (p != NULL) @@ -747,34 +765,13 @@ load_other_peripherals(void) } config_set_string(cat, "hdc", hdc_name); - memset(temp, '\0', sizeof(temp)); - for (c=2; c<4; c++) { - sprintf(temp, "ide_%02i", c + 1); - p = config_get_string(cat, temp, NULL); - if (p == NULL) - p = "0, 00"; - sscanf(p, "%i, %02i", &ide_enable[c], &ide_irq[c]); - } + ide_ter_enabled = !!config_get_int(cat, "ide_ter", 0); + ide_qua_enabled = !!config_get_int(cat, "ide_qua", 0); bugger_enabled = !!config_get_int(cat, "bugger_enabled", 0); } -static int -tally_char(char *str, char c) -{ - int tally; - - tally = 0; - if (str != NULL) { - while (*str) - if (*str++ == c) tally++; - } - - return(tally); -} - - /* Load "Hard Disks" section. */ static void load_hard_disks(void) @@ -785,21 +782,17 @@ load_hard_disks(void) int c; char *p; wchar_t *wp; - int max_spt, max_hpc, max_tracks; - int board = 0, dev = 0; + uint32_t max_spt, max_hpc, max_tracks; + uint32_t board = 0, dev = 0; + /* FIXME: Remove in a month. */ + int lun; memset(temp, '\0', sizeof(temp)); for (c=0; c>1, c&1); p = config_get_string(cat, temp, tmp2); - if (! strstr(p, ":")) { - sscanf(p, "%i", (int *)&hdd[c].ide_channel); - hdd[c].ide_channel &= 7; - } else { - sscanf(p, "%01u:%01u", &board, &dev); - - board &= 3; - dev &= 1; - hdd[c].ide_channel = (board<<1) + dev; - } + sscanf(p, "%01u:%01u", &board, &dev); + board &= 3; + dev &= 1; + hdd[c].ide_channel = (board<<1) + dev; if (hdd[c].ide_channel > 7) hdd[c].ide_channel = 7; @@ -888,22 +879,29 @@ load_hard_disks(void) } /* SCSI */ - sprintf(temp, "hdd_%02i_scsi_location", c+1); - if ((hdd[c].bus == HDD_BUS_SCSI) || - (hdd[c].bus == HDD_BUS_SCSI_REMOVABLE)) { - sprintf(tmp2, "%02u:%02u", c, 0); - p = config_get_string(cat, temp, tmp2); - - sscanf(p, "%02u:%02u", - (int *)&hdd[c].scsi_id, (int *)&hdd[c].scsi_lun); + sprintf(temp, "hdd_%02i_scsi_id", c+1); + if (hdd[c].bus == HDD_BUS_SCSI) { + hdd[c].scsi_id = config_get_int(cat, temp, c); if (hdd[c].scsi_id > 15) hdd[c].scsi_id = 15; - if (hdd[c].scsi_lun > 7) - hdd[c].scsi_lun = 7; - } else { + } else config_delete_var(cat, temp); + + /* FIXME: Remove in a month. */ + sprintf(temp, "hdd_%02i_scsi_location", c+1); + if (hdd[c].bus == HDD_BUS_SCSI) { + p = config_get_string(cat, temp, NULL); + + if (p) { + sscanf(p, "%02i:%02i", + (int *)&hdd[c].scsi_id, (int *)&lun); + + if (hdd[c].scsi_id > 15) + hdd[c].scsi_id = 15; + } } + config_delete_var(cat, temp); memset(hdd[c].fn, 0x00, sizeof(hdd[c].fn)); memset(hdd[c].prev_fn, 0x00, sizeof(hdd[c].prev_fn)); @@ -940,6 +938,10 @@ load_hard_disks(void) sprintf(temp, "hdd_%02i_ide_channels", c+1); config_delete_var(cat, temp); + sprintf(temp, "hdd_%02i_scsi_id", c+1); + config_delete_var(cat, temp); + + /* FIXME: Remove in a month. */ sprintf(temp, "hdd_%02i_scsi_location", c+1); config_delete_var(cat, temp); @@ -956,181 +958,6 @@ load_hard_disks(void) } -/* Load old "Removable Devices" section. */ -static void -load_removable_devices(void) -{ - char *cat = "Removable devices"; - char temp[512], tmp2[512], *p; - char s[512]; - unsigned int board = 0, dev = 0; - wchar_t *wp; - int c; - - if (find_section(cat) == NULL) - return; - - for (c=0; c 13) - fdd_set_type(c, 13); - - sprintf(temp, "fdd_%02i_fn", c + 1); - wp = config_get_wstring(cat, temp, L""); - -#if 0 - /* - * NOTE: - * Temporary hack to remove the absolute - * path currently saved in most config - * files. We should remove this before - * finalizing this release! --FvK - */ - if (! wcsnicmp(wp, usr_path, wcslen(usr_path))) { - /* - * Yep, its absolute and prefixed - * with the EXE path. Just strip - * that off for now... - */ - wcsncpy(floppyfns[c], &wp[wcslen(usr_path)], sizeof_w(floppyfns[c])); - } else -#endif - wcsncpy(floppyfns[c], wp, sizeof_w(floppyfns[c])); - - /* if (*wp != L'\0') - pclog("Floppy%d: %ls\n", c, floppyfns[c]); */ - sprintf(temp, "fdd_%02i_writeprot", c+1); - ui_writeprot[c] = !!config_get_int(cat, temp, 0); - sprintf(temp, "fdd_%02i_turbo", c + 1); - fdd_set_turbo(c, !!config_get_int(cat, temp, 0)); - sprintf(temp, "fdd_%02i_check_bpb", c+1); - fdd_set_check_bpb(c, !!config_get_int(cat, temp, 1)); - - /* Check whether each value is default, if yes, delete it so that only non-default values will later be saved. */ - sprintf(temp, "fdd_%02i_type", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "fdd_%02i_fn", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "fdd_%02i_writeprot", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "fdd_%02i_turbo", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "fdd_%02i_check_bpb", c+1); - config_delete_var(cat, temp); - } - - memset(temp, 0x00, sizeof(temp)); - for (c=0; c>1, (c+2)&1); - p = config_get_string(cat, temp, tmp2); - if (! strstr(p, ":")) { - sscanf(p, "%i", (int *)&cdrom_drives[c].ide_channel); - cdrom_drives[c].ide_channel &= 7; - } else { - sscanf(p, "%01u:%01u", &board, &dev); - - board &= 3; - dev &= 1; - cdrom_drives[c].ide_channel = (board<<1)+dev; - } - - if (cdrom_drives[c].ide_channel > 7) - cdrom_drives[c].ide_channel = 7; - } else { - sprintf(temp, "cdrom_%02i_scsi_location", c+1); - if (cdrom_drives[c].bus_type == CDROM_BUS_SCSI) { - sprintf(tmp2, "%02u:%02u", c+2, 0); - p = config_get_string(cat, temp, tmp2); - sscanf(p, "%02u:%02u", - &cdrom_drives[c].scsi_device_id, - &cdrom_drives[c].scsi_device_lun); - - if (cdrom_drives[c].scsi_device_id > 15) - cdrom_drives[c].scsi_device_id = 15; - if (cdrom_drives[c].scsi_device_lun > 7) - cdrom_drives[c].scsi_device_lun = 7; - } else { - config_delete_var(cat, temp); - } - } - - sprintf(temp, "cdrom_%02i_image_path", c+1); - wp = config_get_wstring(cat, temp, L""); - -#if 0 - /* - * NOTE: - * Temporary hack to remove the absolute - * path currently saved in most config - * files. We should remove this before - * finalizing this release! --FvK - */ - if (! wcsnicmp(wp, usr_path, wcslen(usr_path))) { - /* - * Yep, its absolute and prefixed - * with the EXE path. Just strip - * that off for now... - */ - wcsncpy(cdrom_image[c].image_path, &wp[wcslen(usr_path)], sizeof_w(cdrom_image[c].image_path)); - } else -#endif - wcsncpy(cdrom_image[c].image_path, wp, sizeof_w(cdrom_image[c].image_path)); - - if (cdrom_drives[c].host_drive < 'A') - cdrom_drives[c].host_drive = 0; - - if ((cdrom_drives[c].host_drive == 0x200) && - (wcslen(cdrom_image[c].image_path) == 0)) - cdrom_drives[c].host_drive = 0; - - /* If the CD-ROM is disabled, delete all its variables. */ - sprintf(temp, "cdrom_%02i_host_drive", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "cdrom_%02i_parameters", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "cdrom_%02i_ide_channel", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "cdrom_%02i_scsi_location", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "cdrom_%02i_image_path", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "cdrom_%02i_iso_path", c+1); - config_delete_var(cat, temp); - } - - delete_section_if_empty(cat); -} - - /* Load "Floppy Drives" section. */ static void load_floppy_drives(void) @@ -1170,7 +997,7 @@ load_floppy_drives(void) wcsncpy(floppyfns[c], wp, sizeof_w(floppyfns[c])); /* if (*wp != L'\0') - pclog("Floppy%d: %ls\n", c, floppyfns[c]); */ + config_log("Floppy%d: %ls\n", c, floppyfns[c]); */ sprintf(temp, "fdd_%02i_writeprot", c+1); ui_writeprot[c] = !!config_get_int(cat, temp, 0); sprintf(temp, "fdd_%02i_turbo", c + 1); @@ -1213,6 +1040,8 @@ load_other_removable_devices(void) unsigned int board = 0, dev = 0; wchar_t *wp; int c; + /* FIXME: Remove in a month. */ + int lun; memset(temp, 0x00, sizeof(temp)); for (c=0; c>1, (c+2)&1); p = config_get_string(cat, temp, tmp2); - if (! strstr(p, ":")) { - sscanf(p, "%i", (int *)&cdrom_drives[c].ide_channel); - cdrom_drives[c].ide_channel &= 7; - } else { - sscanf(p, "%01u:%01u", &board, &dev); - - board &= 3; - dev &= 1; - cdrom_drives[c].ide_channel = (board<<1)+dev; - } + sscanf(p, "%01u:%01u", &board, &dev); + board &= 3; + dev &= 1; + cdrom_drives[c].ide_channel = (board<<1)+dev; if (cdrom_drives[c].ide_channel > 7) cdrom_drives[c].ide_channel = 7; } else { - sprintf(temp, "cdrom_%02i_scsi_location", c+1); + sprintf(temp, "cdrom_%02i_scsi_id", c+1); if (cdrom_drives[c].bus_type == CDROM_BUS_SCSI) { - sprintf(tmp2, "%02u:%02u", c+2, 0); - p = config_get_string(cat, temp, tmp2); - sscanf(p, "%02u:%02u", - &cdrom_drives[c].scsi_device_id, - &cdrom_drives[c].scsi_device_lun); + cdrom_drives[c].scsi_device_id = config_get_int(cat, temp, c+2); if (cdrom_drives[c].scsi_device_id > 15) cdrom_drives[c].scsi_device_id = 15; - if (cdrom_drives[c].scsi_device_lun > 7) - cdrom_drives[c].scsi_device_lun = 7; - } else { + } else config_delete_var(cat, temp); + + /* FIXME: Remove in a month. */ + sprintf(temp, "cdrom_%02i_scsi_location", c+1); + if (cdrom_drives[c].bus_type == CDROM_BUS_SCSI) { + p = config_get_string(cat, temp, NULL); + if (p) { + sscanf(p, "%02u:%02u", + &cdrom_drives[c].scsi_device_id, &lun); + + if (cdrom_drives[c].scsi_device_id > 15) + cdrom_drives[c].scsi_device_id = 15; + } } + config_delete_var(cat, temp); } sprintf(temp, "cdrom_%02i_image_path", c+1); @@ -1310,6 +1139,10 @@ load_other_removable_devices(void) sprintf(temp, "cdrom_%02i_ide_channel", c+1); config_delete_var(cat, temp); + sprintf(temp, "cdrom_%02i_scsi_id", c+1); + config_delete_var(cat, temp); + + /* FIXME: Remove in a month. */ sprintf(temp, "cdrom_%02i_scsi_location", c+1); config_delete_var(cat, temp); @@ -1335,39 +1168,39 @@ load_other_removable_devices(void) zip_drives[c].ide_channel = zip_drives[c].scsi_device_id = c + 2; sprintf(temp, "zip_%02i_ide_channel", c+1); - if ((zip_drives[c].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || - (zip_drives[c].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA)) { + if (zip_drives[c].bus_type == ZIP_BUS_ATAPI) { sprintf(tmp2, "%01u:%01u", (c+2)>>1, (c+2)&1); p = config_get_string(cat, temp, tmp2); - if (! strstr(p, ":")) { - sscanf(p, "%i", (int *)&zip_drives[c].ide_channel); - zip_drives[c].ide_channel &= 7; - } else { - sscanf(p, "%01u:%01u", &board, &dev); - - board &= 3; - dev &= 1; - zip_drives[c].ide_channel = (board<<1)+dev; - } + sscanf(p, "%01u:%01u", &board, &dev); + board &= 3; + dev &= 1; + zip_drives[c].ide_channel = (board<<1)+dev; if (zip_drives[c].ide_channel > 7) zip_drives[c].ide_channel = 7; } else { - sprintf(temp, "zip_%02i_scsi_location", c+1); + sprintf(temp, "zip_%02i_scsi_id", c+1); if (zip_drives[c].bus_type == CDROM_BUS_SCSI) { - sprintf(tmp2, "%02u:%02u", c+2, 0); - p = config_get_string(cat, temp, tmp2); - sscanf(p, "%02u:%02u", - &zip_drives[c].scsi_device_id, - &zip_drives[c].scsi_device_lun); + zip_drives[c].scsi_device_id = config_get_int(cat, temp, c+2); if (zip_drives[c].scsi_device_id > 15) zip_drives[c].scsi_device_id = 15; - if (zip_drives[c].scsi_device_lun > 7) - zip_drives[c].scsi_device_lun = 7; - } else { + } else config_delete_var(cat, temp); + + /* FIXME: Remove in a month. */ + sprintf(temp, "zip_%02i_scsi_location", c+1); + if (zip_drives[c].bus_type == CDROM_BUS_SCSI) { + p = config_get_string(cat, temp, NULL); + if (p) { + sscanf(p, "%02u:%02u", + &zip_drives[c].scsi_device_id, &lun); + + if (zip_drives[c].scsi_device_id > 15) + zip_drives[c].scsi_device_id = 15; + } } + config_delete_var(cat, temp); } sprintf(temp, "zip_%02i_image_path", c+1); @@ -1403,6 +1236,10 @@ load_other_removable_devices(void) sprintf(temp, "zip_%02i_ide_channel", c+1); config_delete_var(cat, temp); + sprintf(temp, "zip_%02i_scsi_id", c+1); + config_delete_var(cat, temp); + + /* FIXME: Remove in a month. */ sprintf(temp, "zip_%02i_scsi_location", c+1); config_delete_var(cat, temp); @@ -1420,7 +1257,17 @@ load_other_removable_devices(void) void config_load(void) { - pclog("Loading config file '%ls'..\n", cfg_path); + int i; + + config_log("Loading config file '%ls'..\n", cfg_path); + + memset(hdd, 0, sizeof(hard_disk_t)); + memset(cdrom_drives, 0, sizeof(cdrom_drive_t) * CDROM_NUM); + memset(cdrom_image, 0, sizeof(cdrom_image_t) * CDROM_NUM); +#ifdef USE_IOCTL + memset(cdrom_ioctl, 0, sizeof(cdrom_ioctl_t) * CDROM_NUM); +#endif + memset(zip_drives, 0, sizeof(zip_drive_t)); if (! config_read(cfg_path)) { cpu = 0; @@ -1428,8 +1275,9 @@ config_load(void) plat_langid = 0x0409; #endif scale = 1; + machine = machine_get_machine_from_internal_name("ibmpc"); gfxcard = GFX_CGA; - vid_api = plat_vidapi("default");; + vid_api = plat_vidapi("default"); enable_sync = 1; joystick_type = 7; if (hdc_name) { @@ -1438,14 +1286,22 @@ config_load(void) } hdc_name = (char *) malloc((strlen("none")+1) * sizeof(char)); strcpy(hdc_name, "none"); - serial_enabled[0] = 0; - serial_enabled[1] = 0; - lpt_enabled = 0; - fdd_set_type(0, 2); - fdd_set_type(1, 2); - mem_size = 640; + serial_enabled[0] = 1; + serial_enabled[1] = 1; + lpt_enabled = 1; + for (i = 0; i < FDD_NUM; i++) { + if (i < 2) + fdd_set_type(i, 2); + else + fdd_set_type(i, 0); - pclog("Config file not present or invalid!\n"); + fdd_set_turbo(i, 0); + fdd_set_check_bpb(i, 1); + } + mem_size = 640; + opl_type = 0; + + config_log("Config file not present or invalid!\n"); return; } @@ -1460,12 +1316,11 @@ config_load(void) load_hard_disks(); /* Hard disks */ load_floppy_drives(); /* Floppy drives */ load_other_removable_devices(); /* Other removable devices */ - load_removable_devices(); /* Removable devices (legacy) */ /* Mark the configuration as changed. */ config_changed = 1; - pclog("Config loaded.\n\n"); + config_log("Config loaded.\n\n"); } @@ -1618,11 +1473,6 @@ save_video(void) config_set_string(cat, "gfxcard", video_get_internal_name(video_old_to_new(gfxcard))); - if (video_speed == 3) - config_delete_var(cat, "video_speed"); - else - config_set_int(cat, "video_speed", video_speed); - if (voodoo_enabled == 0) config_delete_var(cat, "voodoo"); else @@ -1730,10 +1580,10 @@ save_sound(void) else config_set_int(cat, "gus", GUS); - if (opl3_type == 0) - config_delete_var(cat, "opl3_type"); + if (opl_type == 0) + config_delete_var(cat, "opl_type"); else - config_set_string(cat, "opl3_type", (opl3_type == 1) ? "nukedopl" : "dbopl"); + config_set_string(cat, "opl_type", (opl_type == 1) ? "nukedopl" : "dbopl"); if (sound_is_float == 1) config_delete_var(cat, "sound_type"); @@ -1821,8 +1671,6 @@ static void save_other_peripherals(void) { char *cat = "Other peripherals"; - char temp[512], tmp2[512]; - int c; if (scsi_card_current == 0) config_delete_var(cat, "scsicard"); @@ -1832,15 +1680,15 @@ save_other_peripherals(void) config_set_string(cat, "hdc", hdc_name); - memset(temp, '\0', sizeof(temp)); - for (c=2; c<4; c++) { - sprintf(temp, "ide_%02i", c + 1); - sprintf(tmp2, "%i, %02i", !!ide_enable[c], ide_irq[c]); - if (ide_enable[c] == 0) - config_delete_var(cat, temp); - else - config_set_string(cat, temp, tmp2); - } + if (ide_ter_enabled == 0) + config_delete_var(cat, "ide_ter"); + else + config_set_int(cat, "ide_ter", ide_ter_enabled); + + if (ide_qua_enabled == 0) + config_delete_var(cat, "ide_qua"); + else + config_set_int(cat, "ide_qua", ide_qua_enabled); if (bugger_enabled == 0) config_delete_var(cat, "bugger_enabled"); @@ -1865,7 +1713,7 @@ save_hard_disks(void) sprintf(temp, "hdd_%02i_parameters", c+1); if (hdd_is_valid(c)) { p = hdd_bus_to_string(hdd[c].bus, 0); - sprintf(tmp2, "%" PRIu64 ", %" PRIu64", %" PRIu64 ", %i, %s", + sprintf(tmp2, "%u, %u, %u, %i, %s", hdd[c].spt, hdd[c].hpc, hdd[c].tracks, hdd[c].wp, p); config_set_string(cat, temp, tmp2); } else { @@ -1878,38 +1726,36 @@ save_hard_disks(void) else config_delete_var(cat, temp); - sprintf(temp, "hdd_%02i_xtide_channel", c+1); - if (hdd_is_valid(c) && (hdd[c].bus == HDD_BUS_XTIDE)) - config_set_int(cat, temp, hdd[c].xtide_channel); + sprintf(temp, "hdd_%02i_xta_channel", c+1); + if (hdd_is_valid(c) && (hdd[c].bus == HDD_BUS_XTA)) + config_set_int(cat, temp, hdd[c].xta_channel); else config_delete_var(cat, temp); sprintf(temp, "hdd_%02i_esdi_channel", c+1); if (hdd_is_valid(c) && (hdd[c].bus == HDD_BUS_ESDI)) config_set_int(cat, temp, hdd[c].esdi_channel); - else + else config_delete_var(cat, temp); sprintf(temp, "hdd_%02i_ide_channel", c+1); - if (! hdd_is_valid(c) || ((hdd[c].bus != HDD_BUS_IDE_PIO_ONLY) && (hdd[c].bus != HDD_BUS_IDE_PIO_AND_DMA))) { + if (! hdd_is_valid(c) || (hdd[c].bus != HDD_BUS_IDE)) { config_delete_var(cat, temp); } else { sprintf(tmp2, "%01u:%01u", hdd[c].ide_channel >> 1, hdd[c].ide_channel & 1); config_set_string(cat, temp, tmp2); } - sprintf(temp, "hdd_%02i_scsi_location", c+1); - if (! hdd_is_valid(c) || ((hdd[c].bus != HDD_BUS_SCSI) && (hdd[c].bus != HDD_BUS_SCSI_REMOVABLE))) { + sprintf(temp, "hdd_%02i_scsi_id", c+1); + if (hdd_is_valid(c) && (hdd[c].bus == HDD_BUS_SCSI)) + config_set_int(cat, temp, hdd[c].scsi_id); + else config_delete_var(cat, temp); - } else { - sprintf(tmp2, "%02u:%02u", hdd[c].scsi_id, hdd[c].scsi_lun); - config_set_string(cat, temp, tmp2); - } sprintf(temp, "hdd_%02i_fn", c+1); if (hdd_is_valid(c) && (wcslen(hdd[c].fn) != 0)) config_set_wstring(cat, temp, hdd[c].fn); - else + else config_delete_var(cat, temp); } @@ -2002,22 +1848,19 @@ save_other_removable_devices(void) } sprintf(temp, "cdrom_%02i_ide_channel", c+1); - if ((cdrom_drives[c].bus_type != CDROM_BUS_ATAPI_PIO_ONLY) && - (cdrom_drives[c].bus_type != CDROM_BUS_ATAPI_PIO_AND_DMA)) { + if (cdrom_drives[c].bus_type != CDROM_BUS_ATAPI) config_delete_var(cat, temp); - } else { + else { sprintf(tmp2, "%01u:%01u", cdrom_drives[c].ide_channel>>1, cdrom_drives[c].ide_channel & 1); config_set_string(cat, temp, tmp2); } - sprintf(temp, "cdrom_%02i_scsi_location", c + 1); + sprintf(temp, "cdrom_%02i_scsi_id", c + 1); if (cdrom_drives[c].bus_type != CDROM_BUS_SCSI) { config_delete_var(cat, temp); } else { - sprintf(tmp2, "%02u:%02u", cdrom_drives[c].scsi_device_id, - cdrom_drives[c].scsi_device_lun); - config_set_string(cat, temp, tmp2); + config_set_int(cat, temp, cdrom_drives[c].scsi_device_id); } sprintf(temp, "cdrom_%02i_image_path", c + 1); @@ -2040,22 +1883,19 @@ save_other_removable_devices(void) } sprintf(temp, "zip_%02i_ide_channel", c+1); - if ((zip_drives[c].bus_type != ZIP_BUS_ATAPI_PIO_ONLY) && - (zip_drives[c].bus_type != ZIP_BUS_ATAPI_PIO_AND_DMA)) { + if (zip_drives[c].bus_type != ZIP_BUS_ATAPI) config_delete_var(cat, temp); - } else { + else { sprintf(tmp2, "%01u:%01u", zip_drives[c].ide_channel>>1, zip_drives[c].ide_channel & 1); config_set_string(cat, temp, tmp2); } - sprintf(temp, "zip_%02i_scsi_location", c + 1); + sprintf(temp, "zip_%02i_scsi_id", c + 1); if (zip_drives[c].bus_type != ZIP_BUS_SCSI) { config_delete_var(cat, temp); } else { - sprintf(tmp2, "%02u:%02u", zip_drives[c].scsi_device_id, - zip_drives[c].scsi_device_lun); - config_set_string(cat, temp, tmp2); + config_set_int(cat, temp, zip_drives[c].scsi_device_id); } sprintf(temp, "zip_%02i_image_path", c + 1); @@ -2100,11 +1940,11 @@ config_dump(void) entry_t *ent; if (sec->name && sec->name[0]) - pclog("[%s]\n", sec->name); + config_log("[%s]\n", sec->name); ent = (entry_t *)sec->entry_head.next; while (ent != NULL) { - pclog("%s = %ls\n", ent->name, ent->wdata); + config_log("%s = %ls\n", ent->name, ent->wdata); ent = (entry_t *)ent->list.next; } @@ -2157,7 +1997,7 @@ config_get_hex16(char *head, char *name, int def) { section_t *section; entry_t *entry; - int value; + unsigned int value; section = find_section(head); if (section == NULL) @@ -2178,7 +2018,7 @@ config_get_hex20(char *head, char *name, int def) { section_t *section; entry_t *entry; - int value; + unsigned int value; section = find_section(head); if (section == NULL) @@ -2199,7 +2039,7 @@ config_get_mac(char *head, char *name, int def) { section_t *section; entry_t *entry; - int val0 = 0, val1 = 0, val2 = 0; + unsigned int val0 = 0, val1 = 0, val2 = 0; section = find_section(head); if (section == NULL) diff --git a/src/cpu/386.c b/src/cpu/386.c index 72ba7c008..60012df57 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -1,5 +1,6 @@ -#include +#include #include +#include #include #include #include @@ -7,6 +8,7 @@ #ifndef INFINITY # define INFINITY (__builtin_inff()) #endif +#define HAVE_STDARG_H #include "../86box.h" #include "cpu.h" #include "x86.h" @@ -68,122 +70,6 @@ uint32_t *eal_r, *eal_w; uint16_t *mod1add[2][8]; uint32_t *mod1seg[8]; -#if 0 -static __inline void fetch_ea_32_long(uint32_t rmdat) -{ - eal_r = eal_w = NULL; - easeg = cpu_state.ea_seg->base; - ea_rseg = cpu_state.ea_seg->seg; - if (cpu_rm == 4) - { - uint8_t sib = rmdat >> 8; - - switch (cpu_mod) - { - case 0: - cpu_state.eaaddr = cpu_state.regs[sib & 7].l; - cpu_state.pc++; - break; - case 1: - cpu_state.pc++; - cpu_state.eaaddr = ((uint32_t)(int8_t)getbyte()) + cpu_state.regs[sib & 7].l; - /* pc++; */ - break; - case 2: - cpu_state.eaaddr = (fastreadl(cs + cpu_state.pc + 1)) + cpu_state.regs[sib & 7].l; - cpu_state.pc += 5; - break; - } - /*SIB byte present*/ - if ((sib & 7) == 5 && !cpu_mod) - cpu_state.eaaddr = getlong(); - else if ((sib & 6) == 4 && !cpu_state.ssegs) - { - easeg = ss; - ea_rseg = SS; - cpu_state.ea_seg = &_ss; - } - if (((sib >> 3) & 7) != 4) - cpu_state.eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6); - } - else - { - cpu_state.eaaddr = cpu_state.regs[cpu_rm].l; - if (cpu_mod) - { - if (cpu_rm == 5 && !cpu_state.ssegs) - { - easeg = ss; - ea_rseg = SS; - cpu_state.ea_seg = &_ss; - } - if (cpu_mod == 1) - { - cpu_state.eaaddr += ((uint32_t)(int8_t)(rmdat >> 8)); - cpu_state.pc++; - } - else - { - cpu_state.eaaddr += getlong(); - } - } - else if (cpu_rm == 5) - { - cpu_state.eaaddr = getlong(); - } - } - if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) - { - uint32_t addr = easeg + cpu_state.eaaddr; - if ( readlookup2[addr >> 12] != -1) - eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr); - if (writelookup2[addr >> 12] != -1) - eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); - } -} - -static __inline void fetch_ea_16_long(uint32_t rmdat) -{ - eal_r = eal_w = NULL; - easeg = cpu_state.ea_seg->base; - ea_rseg = cpu_state.ea_seg->seg; - if (!cpu_mod && cpu_rm == 6) - { - cpu_state.eaaddr = getword(); - } - else - { - switch (cpu_mod) - { - case 0: - cpu_state.eaaddr = 0; - break; - case 1: - cpu_state.eaaddr = (uint16_t)(int8_t)(rmdat >> 8); cpu_state.pc++; - break; - case 2: - cpu_state.eaaddr = getword(); - break; - } - cpu_state.eaaddr += (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]); - if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs) - { - easeg = ss; - ea_rseg = SS; - cpu_state.ea_seg = &_ss; - } - cpu_state.eaaddr &= 0xFFFF; - } - if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) - { - uint32_t addr = easeg + cpu_state.eaaddr; - if ( readlookup2[addr >> 12] != -1) - eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr); - if (writelookup2[addr >> 12] != -1) - eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); - } -} -#endif #define fetch_ea_16(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_16_long(rmdat); if (cpu_state.abrt) return 0; } #define fetch_ea_32(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_32_long(rmdat); } if (cpu_state.abrt) return 0 @@ -222,6 +108,27 @@ extern int dontprint; break; \ } + +#ifdef ENABLE_386_LOG +int x386_do_log = ENABLE_386_LOG; +#endif + + +static void +x386_log(const char *fmt, ...) +{ +#ifdef ENABLE_386_LOG + va_list ap; + + if (x386_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + void exec386(int cycs) { uint8_t temp; @@ -240,7 +147,6 @@ void exec386(int cycs) cycdiff=0; oldcyc=cycles; timer_start_period(cycles << TIMER_SHIFT); - /* pclog("%i %02X\n", ins, ram[8]); */ while (cycdiff < cycle_period) { /* testr[0]=EAX; testr[1]=EBX; testr[2]=ECX; testr[3]=EDX; @@ -268,10 +174,6 @@ dontprint=0; opcode = fetchdat & 0xFF; fetchdat >>= 8; - if (output == 3) - { - pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %f %02X%02X %02X%02X %02X%02X %02X\n",CS,cs,cpu_state.pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, pit.c[0], ram[0xB270+0x3F5], ram[0xB270+0x3F4], ram[0xB270+0x3F7], ram[0xB270+0x3F6], ram[0xB270+0x3F9], ram[0xB270+0x3F8], ram[0x4430+0x0D49]); - } cpu_state.pc++; x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); if (x86_was_reset) @@ -284,17 +186,6 @@ dontprint=0; if (cpu_state.abrt) { flags_rebuild(); - /* pclog("Abort\n"); */ - /* if (CS == 0x228) pclog("Abort at %04X:%04X - %i %i %i\n",CS,pc,notpresent,nullseg,cpu_state.abrt); */ -/* if (testr[0]!=EAX) pclog("EAX corrupted %08X\n",pc); - if (testr[1]!=EBX) pclog("EBX corrupted %08X\n",pc); - if (testr[2]!=ECX) pclog("ECX corrupted %08X\n",pc); - if (testr[3]!=EDX) pclog("EDX corrupted %08X\n",pc); - if (testr[4]!=ESI) pclog("ESI corrupted %08X\n",pc); - if (testr[5]!=EDI) pclog("EDI corrupted %08X\n",pc); - if (testr[6]!=EBP) pclog("EBP corrupted %08X\n",pc); - if (testr[7]!=ESP) pclog("ESP corrupted %08X\n",pc);*/ -/* if (testr[8]!=flags) pclog("FLAGS corrupted %08X\n",pc);*/ tempi = cpu_state.abrt; cpu_state.abrt = 0; x86_doabrt(tempi); @@ -303,14 +194,14 @@ dontprint=0; cpu_state.abrt = 0; CS = oldcs; cpu_state.pc = cpu_state.oldpc; - pclog("Double fault %i\n", ins); + x386_log("Double fault %i\n", ins); pmodeint(8, 0); if (cpu_state.abrt) { cpu_state.abrt = 0; softresetx86(); cpu_set_edx(); - pclog("Triple fault - reset\n"); + x386_log("Triple fault - reset\n"); } } } @@ -342,7 +233,6 @@ dontprint=0; { cpu_state.oldpc = cpu_state.pc; oldcs = CS; - /* pclog("NMI\n"); */ x86_int(2); nmi_enable = 0; if (nmi_auto_clear) @@ -356,10 +246,6 @@ dontprint=0; temp=picinterrupt(); if (temp!=0xFF) { - /* if (temp == 0x54) pclog("Take int 54\n"); */ - /* if (output) output=3; */ - /* if (temp == 0xd) pclog("Hardware int %02X %i %04X(%08X):%08X\n",temp,ins, CS,cs,pc); */ - /* if (temp==0x54) output=3; */ flags_rebuild(); if (msw&1) { @@ -377,14 +263,11 @@ dontprint=0; oxpc=cpu_state.pc; cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); - /* if (temp==0x76) pclog("INT to %04X:%04X\n",CS,pc); */ } - /* pclog("Now at %04X(%08X):%08X\n", CS, cs, pc); */ } } ins++; - insc++; if (timetolive) { diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index 4aca453e5..a3ff0c0ee 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -1,5 +1,6 @@ -#include +#include #include +#include #include #include #include @@ -7,6 +8,7 @@ #ifndef INFINITY # define INFINITY (__builtin_inff()) #endif +#define HAVE_STDARG_H #include "../86box.h" #include "cpu.h" #include "x86.h" @@ -69,6 +71,27 @@ uint32_t *eal_r, *eal_w; uint16_t *mod1add[2][8]; uint32_t *mod1seg[8]; + +#ifdef ENABLE_386_DYNAREC_LOG +int x386_dynarec_do_log = ENABLE_386_DYNAREC_LOG; +#endif + + +static void +x386_dynarec_log(const char *fmt, ...) +{ +#ifdef ENABLE_386_DYNAREC_LOG + va_list ap; + + if (x386_dynarec_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + static __inline void fetch_ea_32_long(uint32_t rmdat) { eal_r = eal_w = NULL; @@ -210,7 +233,7 @@ void x86_int(int num) cpu_state.abrt = 0; softresetx86(); cpu_set_edx(); - pclog("Triple fault in real mode - reset\n"); + x386_dynarec_log("Triple fault in real mode - reset\n"); } else x86_int(8); @@ -303,9 +326,9 @@ int x86_int_sw_rm(int num) if (cpu_state.abrt) return 1; - writememw(ss,((SP-2)&0xFFFF),flags); if (cpu_state.abrt) {pclog("abrt5\n"); return 1; } + writememw(ss,((SP-2)&0xFFFF),flags); if (cpu_state.abrt) {x386_dynarec_log("abrt5\n"); return 1; } writememw(ss,((SP-4)&0xFFFF),CS); - writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); if (cpu_state.abrt) {pclog("abrt6\n"); return 1; } + writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); if (cpu_state.abrt) {x386_dynarec_log("abrt6\n"); return 1; } SP-=6; eflags &= ~VIF_FLAG; @@ -428,13 +451,6 @@ int checkio(int port) int xout=0; -#if 0 -#define divexcp() { \ - pclog("Divide exception at %04X(%06X):%04X\n",CS,cs,cpu_state.pc); \ - x86_int(0); \ -} -#endif - #define divexcp() { \ x86_int(0); \ } @@ -592,7 +608,6 @@ void exec386_dynarec(int cycs) CPU_BLOCK_END(); ins++; - insc++; /* if ((cs + pc) == 4) fatal("4\n");*/ @@ -686,9 +701,6 @@ inrecomp=1; inrecomp=0; if (!use32) cpu_state.pc &= 0xffff; cpu_recomp_blocks++; -/* ins += codeblock_ins[index]; - insc += codeblock_ins[index];*/ -/* pclog("Exit block now %04X:%04X\n", CS, pc);*/ } else if (valid_block && !cpu_state.abrt) { @@ -752,7 +764,6 @@ inrecomp=0; } ins++; - insc++; } if (!cpu_state.abrt && !x86_was_reset) @@ -823,7 +834,6 @@ inrecomp=0; } ins++; - insc++; } if (!cpu_state.abrt && !x86_was_reset) @@ -848,14 +858,14 @@ inrecomp=0; cpu_state.abrt = 0; CS = oldcs; cpu_state.pc = cpu_state.oldpc; - pclog("Double fault %i\n", ins); + x386_dynarec_log("Double fault %i\n", ins); pmodeint(8, 0); if (cpu_state.abrt) { cpu_state.abrt = 0; softresetx86(); cpu_set_edx(); - pclog("Triple fault - reset\n"); + x386_dynarec_log("Triple fault - reset\n"); } } } @@ -885,7 +895,6 @@ inrecomp=0; { cpu_state.oldpc = cpu_state.pc; oldcs = CS; - pclog("NMI\n"); x86_int(2); nmi_enable = 0; if (nmi_auto_clear) @@ -903,18 +912,10 @@ inrecomp=0; flags_rebuild(); if (msw&1) { - /* if (temp == 0x0E) - { - pclog("Servicing FDC interupt (p)!\n"); - } */ pmodeint(temp,0); } else { - /* if (temp == 0x0E) - { - pclog("Servicing FDC interupt (r)!\n"); - } */ writememw(ss,(SP-2)&0xFFFF,flags); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); @@ -927,10 +928,6 @@ inrecomp=0; loadcs(readmemw(0,addr+2)); } } - /* else - { - pclog("Servicing pending interrupt 0xFF (!)!\n"); - } */ } } timer_end_period(cycles << TIMER_SHIFT); diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index 299a95d9c..d961bd4ac 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -1,23 +1,43 @@ /* - * 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. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * 286/386+ instruction handlers list. * - * Version: @(#)386_ops.h 1.0.2 2018/02/18 + * Version: @(#)386_ops.h 1.0.3 2018/05/21 * - * Author: Sarah Walker, + * Authors: Fred N. van Kempen, + * Sarah Walker, * leilei, * Miran Grca, + * + * Copyright 2018 Fred N. van Kempen. * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 leilei. * Copyright 2016-2018 Miran Grca. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ - #include "x86_ops.h" @@ -147,11 +167,18 @@ static int ILLEGAL(uint32_t fetchdat) return 0; } -#include "x86seg.h" -#ifdef DEV_BRANCH -#ifdef USE_AMD_K -#include "x86_ops_amd.h" +#if defined(DEV_BRANCH) && (defined(USE_AMD_K) || defined(USE_I686)) +static int internal_illegal(char *s) +{ + cpu_state.pc = cpu_state.oldpc; + x86gpf(s, 0); + return cpu_state.abrt; +} #endif + +#include "x86seg.h" +#if defined(DEV_BRANCH) && defined(USE_AMD_K) +# include "x86_ops_amd.h" #endif #include "x86_ops_arith.h" #include "x86_ops_atomic.h" @@ -167,10 +194,8 @@ static int ILLEGAL(uint32_t fetchdat) #include "x86_ops_jump.h" #include "x86_ops_misc.h" #include "x87_ops.h" -#ifdef DEV_BRANCH -#ifdef USE_I686 -#include "x86_ops_i686.h" -#endif +#if defined(DEV_BRANCH) && defined(USE_I686) +# include "x86_ops_i686.h" #endif #include "x86_ops_mmx.h" #include "x86_ops_mmx_arith.h" @@ -195,6 +220,7 @@ static int ILLEGAL(uint32_t fetchdat) #include "x86_ops_string.h" #include "x86_ops_xchg.h" + static int op0F_w_a16(uint32_t fetchdat) { int opcode = fetchdat & 0xff; @@ -236,7 +262,8 @@ static int op0F_l_a32(uint32_t fetchdat) return x86_opcodes_0f[opcode | 0x300](fetchdat >> 8); } -OpFn OP_TABLE(286_0f)[1024] = + +const OpFn OP_TABLE(286_0f)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -327,7 +354,7 @@ OpFn OP_TABLE(286_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, }; -OpFn OP_TABLE(386_0f)[1024] = +const OpFn OP_TABLE(386_0f)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -418,7 +445,7 @@ OpFn OP_TABLE(386_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, }; -OpFn OP_TABLE(486_0f)[1024] = +const OpFn OP_TABLE(486_0f)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -509,7 +536,7 @@ OpFn OP_TABLE(486_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, }; -OpFn OP_TABLE(winchip_0f)[1024] = +const OpFn OP_TABLE(winchip_0f)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -600,7 +627,7 @@ OpFn OP_TABLE(winchip_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, }; -OpFn OP_TABLE(pentium_0f)[1024] = +const OpFn OP_TABLE(pentium_0f)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -691,7 +718,7 @@ OpFn OP_TABLE(pentium_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, }; -OpFn OP_TABLE(pentiummmx_0f)[1024] = +const OpFn OP_TABLE(pentiummmx_0f)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -782,9 +809,8 @@ OpFn OP_TABLE(pentiummmx_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, }; -#ifdef DEV_BRANCH -#ifdef USE_AMD_K -OpFn OP_TABLE(k6_0f)[1024] = +#if defined(DEV_BRANCH) && defined(USE_AMD_K) +const OpFn OP_TABLE(k6_0f)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -875,9 +901,8 @@ OpFn OP_TABLE(k6_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, }; #endif -#endif -OpFn OP_TABLE(c6x86mx_0f)[1024] = +const OpFn OP_TABLE(c6x86mx_0f)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -970,7 +995,7 @@ OpFn OP_TABLE(c6x86mx_0f)[1024] = #ifdef DEV_BRANCH #ifdef USE_I686 -OpFn OP_TABLE(pentiumpro_0f)[1024] = +const OpFn OP_TABLE(pentiumpro_0f)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -1062,7 +1087,7 @@ OpFn OP_TABLE(pentiumpro_0f)[1024] = }; #if 0 -OpFn OP_TABLE(pentium2_0f)[1024] = +const OpFn OP_TABLE(pentium2_0f)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -1154,7 +1179,7 @@ OpFn OP_TABLE(pentium2_0f)[1024] = }; #endif -OpFn OP_TABLE(pentium2d_0f)[1024] = +const OpFn OP_TABLE(pentium2d_0f)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -1247,7 +1272,7 @@ OpFn OP_TABLE(pentium2d_0f)[1024] = #endif #endif -OpFn OP_TABLE(286)[1024] = +const OpFn OP_TABLE(286)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -1338,7 +1363,7 @@ OpFn OP_TABLE(286)[1024] = /*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, }; -OpFn OP_TABLE(386)[1024] = +const OpFn OP_TABLE(386)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -1429,7 +1454,7 @@ OpFn OP_TABLE(386)[1024] = /*f0*/ opLOCK, opINT1, opREPNE, opREPE, opHLT, opCMC, opF6_a32, opF7_l_a32, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a32, opFF_l_a32, }; -OpFn OP_TABLE(REPE)[1024] = +const OpFn OP_TABLE(REPE)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -1520,7 +1545,7 @@ OpFn OP_TABLE(REPE)[1024] = /*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; -OpFn OP_TABLE(REPNE)[1024] = +const OpFn OP_TABLE(REPNE)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ diff --git a/src/cpu/808x.c b/src/cpu/808x.c index e95cf1c79..53e2403cc 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -18,7 +18,7 @@ * 2 clocks - fetch opcode 1 2 clocks - execute * 2 clocks - fetch opcode 2 etc * - * Version: @(#)808x.c 1.0.2 2018/03/09 + * Version: @(#)808x.c 1.0.5 2018/04/29 * * Authors: Sarah Walker, * Miran Grca, @@ -44,10 +44,12 @@ * Boston, MA 02111-1307 * USA. */ -#include +#include #include +#include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "cpu.h" #include "x86.h" @@ -58,9 +60,6 @@ #include "../nmi.h" #include "../pic.h" #include "../timer.h" -#include "../device.h" /* for scsi.h */ -#include "../keyboard.h" /* its WRONG to have this in here!! --FvK */ -#include "../scsi/scsi.h" /* its WRONG to have this in here!! --FvK */ #include "../plat.h" @@ -84,6 +83,27 @@ void writememwl(uint32_t seg, uint32_t addr, uint16_t val); uint32_t readmemll(uint32_t seg, uint32_t addr); void writememll(uint32_t seg, uint32_t addr, uint32_t val); + +#ifdef ENABLE_808X_LOG +int x808x_do_log = ENABLE_808X_LOG; +#endif + + +static void +x808x_log(const char *fmt, ...) +{ +#ifdef ENABLE_808X_LOG + va_list ap; + + if (x808x_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + #undef readmemb #undef readmemw uint8_t readmemb(uint32_t a) @@ -109,7 +129,7 @@ uint16_t readmemw(uint32_t s, uint16_t a) else return *(uint16_t *)(readlookup2[(s + a) >> 12] + s + a); } -void refreshread() { /*pclog("Refreshread\n"); */FETCHCOMPLETE(); memcycs+=4; } +void refreshread() { FETCHCOMPLETE(); memcycs+=4; } #undef fetchea #define fetchea() { rmdat=FETCH(); \ @@ -488,7 +508,7 @@ void makeznptable() { znptable8[c]=P_FLAG; } - if (c == 0xb1) pclog("znp8 b1 = %i %02X\n", d, znptable8[c]); + if (c == 0xb1) x808x_log("znp8 b1 = %i %02X\n", d, znptable8[c]); if (!c) znptable8[c]|=Z_FLAG; if (c&0x80) znptable8[c]|=N_FLAG; } @@ -507,8 +527,8 @@ void makeznptable() znptable16[c]=0; else znptable16[c]=P_FLAG; - if (c == 0xb1) pclog("znp16 b1 = %i %02X\n", d, znptable16[c]); - if (c == 0x65b1) pclog("znp16 65b1 = %i %02X\n", d, znptable16[c]); + if (c == 0xb1) x808x_log("znp16 b1 = %i %02X\n", d, znptable16[c]); + if (c == 0x65b1) x808x_log("znp16 65b1 = %i %02X\n", d, znptable16[c]); if (!c) znptable16[c]|=Z_FLAG; if (c&0x8000) znptable16[c]|=N_FLAG; } @@ -541,11 +561,11 @@ void dumpregs(int force) f=fopen("ram.dmp","wb"); fwrite(ram,mem_size*1024,1,f); fclose(f); - pclog("Dumping rram.dmp\n"); + x808x_log("Dumping rram.dmp\n"); f=fopen("rram.dmp","wb"); for (c=0;c<0x1000000;c++) putc(readmemb(c),f); fclose(f); - pclog("Dumping rram4.dmp\n"); + x808x_log("Dumping rram4.dmp\n"); f=fopen("rram4.dmp","wb"); for (c=0;c<0x0050000;c++) { @@ -553,44 +573,44 @@ void dumpregs(int force) putc(readmemb386l(0,c+0x80000000),f); } fclose(f); - pclog("Dumping done\n"); + x808x_log("Dumping done\n"); #endif if (is386) - pclog("EAX=%08X EBX=%08X ECX=%08X EDX=%08X\nEDI=%08X ESI=%08X EBP=%08X ESP=%08X\n",EAX,EBX,ECX,EDX,EDI,ESI,EBP,ESP); + x808x_log("EAX=%08X EBX=%08X ECX=%08X EDX=%08X\nEDI=%08X ESI=%08X EBP=%08X ESP=%08X\n",EAX,EBX,ECX,EDX,EDI,ESI,EBP,ESP); else - pclog("AX=%04X BX=%04X CX=%04X DX=%04X DI=%04X SI=%04X BP=%04X SP=%04X\n",AX,BX,CX,DX,DI,SI,BP,SP); - pclog("PC=%04X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n",cpu_state.pc,CS,DS,ES,SS,flags); - pclog("%04X:%04X %04X:%04X\n",oldcs,cpu_state.oldpc, oldcs2, oldpc2); - pclog("%i ins\n",ins); + x808x_log("AX=%04X BX=%04X CX=%04X DX=%04X DI=%04X SI=%04X BP=%04X SP=%04X\n",AX,BX,CX,DX,DI,SI,BP,SP); + x808x_log("PC=%04X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n",cpu_state.pc,CS,DS,ES,SS,flags); + x808x_log("%04X:%04X %04X:%04X\n",oldcs,cpu_state.oldpc, oldcs2, oldpc2); + x808x_log("%i ins\n",ins); if (is386) - pclog("In %s mode\n",(msw&1)?((eflags&VM_FLAG)?"V86":"protected"):"real"); + x808x_log("In %s mode\n",(msw&1)?((eflags&VM_FLAG)?"V86":"protected"):"real"); else - pclog("In %s mode\n",(msw&1)?"protected":"real"); - pclog("CS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",cs,_cs.limit,_cs.access, _cs.limit_low, _cs.limit_high); - pclog("DS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ds,_ds.limit,_ds.access, _ds.limit_low, _ds.limit_high); - pclog("ES : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",es,_es.limit,_es.access, _es.limit_low, _es.limit_high); + x808x_log("In %s mode\n",(msw&1)?"protected":"real"); + x808x_log("CS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",cs,_cs.limit,_cs.access, _cs.limit_low, _cs.limit_high); + x808x_log("DS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ds,_ds.limit,_ds.access, _ds.limit_low, _ds.limit_high); + x808x_log("ES : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",es,_es.limit,_es.access, _es.limit_low, _es.limit_high); if (is386) { - pclog("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",seg_fs,_fs.limit,_fs.access, _fs.limit_low, _fs.limit_high); - pclog("GS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",gs,_gs.limit,_gs.access, _gs.limit_low, _gs.limit_high); + x808x_log("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",seg_fs,_fs.limit,_fs.access, _fs.limit_low, _fs.limit_high); + x808x_log("GS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",gs,_gs.limit,_gs.access, _gs.limit_low, _gs.limit_high); } - pclog("SS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ss,_ss.limit,_ss.access, _ss.limit_low, _ss.limit_high); - pclog("GDT : base=%06X limit=%04X\n",gdt.base,gdt.limit); - pclog("LDT : base=%06X limit=%04X\n",ldt.base,ldt.limit); - pclog("IDT : base=%06X limit=%04X\n",idt.base,idt.limit); - pclog("TR : base=%06X limit=%04X\n", tr.base, tr.limit); + x808x_log("SS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ss,_ss.limit,_ss.access, _ss.limit_low, _ss.limit_high); + x808x_log("GDT : base=%06X limit=%04X\n",gdt.base,gdt.limit); + x808x_log("LDT : base=%06X limit=%04X\n",ldt.base,ldt.limit); + x808x_log("IDT : base=%06X limit=%04X\n",idt.base,idt.limit); + x808x_log("TR : base=%06X limit=%04X\n", tr.base, tr.limit); if (is386) { - pclog("386 in %s mode stack in %s mode\n",(use32)?"32-bit":"16-bit",(stack32)?"32-bit":"16-bit"); - pclog("CR0=%08X CR2=%08X CR3=%08X CR4=%08x\n",cr0,cr2,cr3, cr4); + x808x_log("386 in %s mode stack in %s mode\n",(use32)?"32-bit":"16-bit",(stack32)?"32-bit":"16-bit"); + x808x_log("CR0=%08X CR2=%08X CR3=%08X CR4=%08x\n",cr0,cr2,cr3, cr4); } - pclog("Entries in readlookup : %i writelookup : %i\n",readlnum,writelnum); + x808x_log("Entries in readlookup : %i writelookup : %i\n",readlnum,writelnum); for (c=0;c<1024*1024;c++) { if (readlookup2[c]!=0xFFFFFFFF) d++; if (writelookup2[c]!=0xFFFFFFFF) e++; } - pclog("Entries in readlookup : %i writelookup : %i\n",d,e); + x808x_log("Entries in readlookup : %i writelookup : %i\n",d,e); x87_dumpregs(); indump = 0; } @@ -599,7 +619,7 @@ int resets = 0; int x86_was_reset = 0; void resetx86() { - pclog("x86 reset\n"); + x808x_log("x86 reset\n"); resets++; ins = 0; use32=0; @@ -648,7 +668,6 @@ void resetx86() #endif x86_was_reset = 1; port_92_clear_reset(); - scsi_card_reset(); } void softresetx86() @@ -658,7 +677,12 @@ void softresetx86() cpu_cur_status = 0; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); msw=0; - cr0=0; + if (is486) + cr0 = 1 << 30; + else + cr0 = 0; + cpu_cache_int_enabled = 0; + cpu_update_waitstates(); cr4 = 0; eflags=0; cgate32=0; @@ -680,7 +704,6 @@ void softresetx86() x86seg_reset(); x86_was_reset = 1; port_92_clear_reset(); - scsi_card_reset(); } static void setznp8(uint8_t val) @@ -1065,7 +1088,7 @@ void execx86(int cycs) cpu_state.pc--; if (output) { - if (!skipnextprint) pclog("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i %p %02X\n",cs,cpu_state.pc,AX,BX,CX,DX,CS,DS,ES,SS,DI,SI,BP,SP,opcode,flags, ins, ram, ram[0x1a925]); + if (!skipnextprint) x808x_log("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i %p %02X\n",cs,cpu_state.pc,AX,BX,CX,DX,CS,DS,ES,SS,DI,SI,BP,SP,opcode,flags, ins, ram, ram[0x1a925]); skipnextprint=0; } cpu_state.pc++; @@ -2974,7 +2997,7 @@ void execx86(int cycs) } else { - pclog("DIVb BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); + x808x_log("DIVb BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); writememw(ss,(SP-2)&0xFFFF,flags|0xF000); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); @@ -2998,7 +3021,7 @@ void execx86(int cycs) } else { - pclog("IDIVb BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); + x808x_log("IDIVb BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); writememw(ss,(SP-2)&0xFFFF,flags|0xF000); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); @@ -3070,7 +3093,7 @@ void execx86(int cycs) } else { - pclog("DIVw BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); + x808x_log("DIVw BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); writememw(ss,(SP-2)&0xFFFF,flags|0xF000); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); @@ -3094,7 +3117,7 @@ void execx86(int cycs) } else { - pclog("IDIVw BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); + x808x_log("IDIVw BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); writememw(ss,(SP-2)&0xFFFF,flags|0xF000); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); @@ -3245,7 +3268,6 @@ void execx86(int cycs) } memcycs=0; - insc++; clockhardware(); if (trap && (flags&T_FLAG) && !noint) diff --git a/src/cpu/codegen_ops_fpu.h b/src/cpu/codegen_ops_fpu.h index b2519e5ea..481eadb8c 100644 --- a/src/cpu/codegen_ops_fpu.h +++ b/src/cpu/codegen_ops_fpu.h @@ -634,5 +634,12 @@ opFLDimm(L2T, 3.3219280948873623) opFLDimm(L2E, 1.4426950408889634); opFLDimm(PI, 3.141592653589793); opFLDimm(EG2, 0.3010299956639812); -opFLDimm(LN2, 0.693147180559945); opFLDimm(Z, 0.0) + +static uint32_t ropFLDLN2(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + FP_ENTER(); + FP_LOAD_IMM_Q(0x3fe62e42fefa39f0ull); + + return op_pc; +} diff --git a/src/cpu/codegen_timing_686.c b/src/cpu/codegen_timing_686.c index 412840e89..fc818d7f1 100644 --- a/src/cpu/codegen_timing_686.c +++ b/src/cpu/codegen_timing_686.c @@ -59,6 +59,7 @@ static uint32_t prev_regmask; static uint64_t *prev_deps; static uint32_t prev_fetchdat; +static uint32_t last_regmask_modified; static uint32_t regmask_modified; static uint32_t opcode_timings[256] = @@ -776,7 +777,7 @@ static inline int COUNT(uint32_t c, int op_32) void codegen_timing_686_block_start() { prev_full = decode_delay = 0; - regmask_modified = 0; + regmask_modified = last_regmask_modified = 0; } void codegen_timing_686_start() @@ -787,6 +788,18 @@ void codegen_timing_686_start() void codegen_timing_686_prefix(uint8_t prefix, uint32_t fetchdat) { + if ((prefix & 0xf8) == 0xd8) + { + last_prefix = prefix; + return; + } + if (prefix == 0x0f && (fetchdat & 0xf0) == 0x80) + { + /*0fh prefix is 'free' when used on conditional jumps*/ + last_prefix = prefix; + return; + } + /*6x86 can decode 1 prefix per instruction per clock with no penalty. If either instruction has more than one prefix then decode is delayed by one cycle for each additional prefix*/ @@ -801,7 +814,16 @@ static int check_agi(uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int op_3 if (addr_regmask & IMPL_ESP) addr_regmask |= (1 << REG_ESP); - return regmask_modified & addr_regmask; + if (regmask_modified & addr_regmask) + { + regmask_modified = 0; + return 2; + } + + if (last_regmask_modified & addr_regmask) + return 1; + + return 0; } void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) @@ -914,6 +936,8 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) } } + /*One prefix per instruction is free*/ + decode_delay--; if (decode_delay < 0) decode_delay = 0; @@ -925,8 +949,7 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) if (regmask & IMPL_ESP) regmask |= SRCDEP_ESP | DSTDEP_ESP; - if (check_agi(prev_deps, prev_opcode, prev_fetchdat, prev_op_32)) - agi_stall = 2; + agi_stall = check_agi(prev_deps, prev_opcode, prev_fetchdat, prev_op_32); /*Second instruction in the pair*/ if ((timings[opcode] & PAIR_MASK) == PAIR_NP) @@ -936,6 +959,7 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay + agi_stall; decode_delay = (-COUNT(prev_timings[prev_opcode], prev_op_32)) + 1 + agi_stall; prev_full = 0; + last_regmask_modified = regmask_modified; regmask_modified = prev_regmask; } else if (((timings[opcode] & PAIR_MASK) == PAIR_X || (timings[opcode] & PAIR_MASK) == PAIR_X_BRANCH) @@ -946,6 +970,7 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay + agi_stall; decode_delay = (-COUNT(prev_timings[prev_opcode], prev_op_32)) + 1 + agi_stall; prev_full = 0; + last_regmask_modified = regmask_modified; regmask_modified = prev_regmask; } else if (prev_regmask & regmask) @@ -955,6 +980,7 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay + agi_stall; decode_delay = (-COUNT(prev_timings[prev_opcode], prev_op_32)) + 1 + agi_stall; prev_full = 0; + last_regmask_modified = regmask_modified; regmask_modified = prev_regmask; } else @@ -966,12 +992,12 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) if (!t_pair) fatal("Pairable 0 cycles! %02x %02x\n", opcode, prev_opcode); - if (check_agi(deps, opcode, fetchdat, op_32)) - agi_stall = 2; + agi_stall = check_agi(deps, opcode, fetchdat, op_32); codegen_block_cycles += t_pair + agi_stall; decode_delay = (-t_pair) + 1 + agi_stall; + last_regmask_modified = regmask_modified; regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8) | prev_regmask; prev_full = 0; return; @@ -985,12 +1011,12 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) { /*Instruction not pairable*/ int agi_stall = 0; - - if (check_agi(deps, opcode, fetchdat, op_32)) - agi_stall = 2; + + agi_stall = check_agi(deps, opcode, fetchdat, op_32); codegen_block_cycles += COUNT(timings[opcode], op_32) + decode_delay + agi_stall; decode_delay = (-COUNT(timings[opcode], op_32)) + 1 + agi_stall; + last_regmask_modified = regmask_modified; regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8); } else diff --git a/src/cpu/codegen_timing_pentium.c b/src/cpu/codegen_timing_pentium.c index 8ec6b2c78..60a6fbea0 100644 --- a/src/cpu/codegen_timing_pentium.c +++ b/src/cpu/codegen_timing_pentium.c @@ -963,7 +963,7 @@ void codegen_timing_pentium_prefix(uint8_t prefix, uint32_t fetchdat) last_prefix = prefix; return; } - if (prefix == 0x0f && (opcode & 0xf0) == 0x80) + if (prefix == 0x0f && (fetchdat & 0xf0) == 0x80) { /*On Pentium 0fh prefix is 'free' when used on conditional jumps*/ last_prefix = prefix; diff --git a/src/cpu/codegen_x86-64.c b/src/cpu/codegen_x86-64.c index 72e115331..7f373c163 100644 --- a/src/cpu/codegen_x86-64.c +++ b/src/cpu/codegen_x86-64.c @@ -1,8 +1,10 @@ #ifdef __amd64__ -#include +#include #include +#include #include +#define HAVE_STDARG_H #include "../86box.h" #include "cpu.h" #include "x86.h" @@ -94,7 +96,6 @@ void codegen_init() exit(-1); } #endif -// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); } void codegen_reset() @@ -111,20 +112,6 @@ void codegen_reset() void dump_block() { -/* codeblock_t *block = pages[0x119000 >> 12].block; - - pclog("dump_block:\n"); - while (block) - { - uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff); - uint32_t end_pc = (block->endpc & 0xffc) | (block->phys & ~0xfff); - pclog(" %p : %08x-%08x %08x-%08x %p %p\n", (void *)block, start_pc, end_pc, block->pc, block->endpc, (void *)block->prev, (void *)block->next); - if (!block->pc) - fatal("Dead PC=0\n"); - - block = block->next; - } - pclog("dump_block done\n");*/ } static void add_to_block_list(codeblock_t *block) @@ -204,7 +191,6 @@ static void remove_from_block_list(codeblock_t *block, uint32_t pc) } else { -// pclog(" pages.block_2=%p 3 %p %p\n", (void *)block->next_2, (void *)block, (void *)pages[block->phys_2 >> 12].block_2); pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block->next_2; if (block->next_2) block->next_2->prev_2 = NULL; @@ -270,11 +256,8 @@ void codegen_block_init(uint32_t phys_addr) block_current = (block_current + 1) & BLOCK_MASK; block = &codeblock[block_current]; -// if (block->pc == 0xb00b4ff5) -// pclog("Init target block\n"); if (block->valid != 0) { -// pclog("Reuse block : was %08x now %08x\n", block->pc, cs+pc); delete_block(block); cpu_recomp_reuse++; } @@ -374,8 +357,6 @@ void codegen_block_start_recompile(codeblock_t *block) addbyte(0xBD); addquad(((uintptr_t)&cpu_state) + 128); -// pclog("New block %i for %08X %03x\n", block_current, cs+pc, block_num); - last_op32 = -1; last_ea_seg = NULL; last_ssegs = -1; @@ -434,14 +415,10 @@ void codegen_block_generate_end_mask() end_pc = 0x3ff; start_pc >>= PAGE_MASK_SHIFT; end_pc >>= PAGE_MASK_SHIFT; - -// pclog("block_end: %08x %08x\n", start_pc, end_pc); + for (; start_pc <= end_pc; start_pc++) - { block->page_mask |= ((uint64_t)1 << start_pc); -// pclog(" %08x %llx\n", start_pc, block->page_mask); - } - + pages[block->phys >> 12].code_present_mask[(block->phys >> 10) & 3] |= block->page_mask; block->phys_2 = -1; @@ -467,7 +444,6 @@ void codegen_block_generate_end_mask() fatal("!page_mask2\n"); if (block->next_2) { -// pclog(" next_2->pc=%08x\n", block->next_2->pc); if (block->next_2->valid == 0) fatal("block->next_2->valid=0 %p\n", (void *)block->next_2); } @@ -476,7 +452,6 @@ void codegen_block_generate_end_mask() } } -// pclog("block_end: %08x %08x %016llx\n", block->pc, block->endpc, block->page_mask); recomp_page = -1; } @@ -542,7 +517,6 @@ void codegen_block_end_recompile(codeblock_t *block) block->next_2 = block->prev_2 = NULL; codegen_block_generate_end_mask(); add_to_block_list(block); -// pclog("End block %i\n", block_num); } void codegen_flush() @@ -597,10 +571,6 @@ int opcode_0f_modrm[256] = void codegen_debug() { - if (output) - { - pclog("At %04x(%08x):%04x %04x(%08x):%04x es=%08x EAX=%08x BX=%04x ECX=%08x BP=%04x EDX=%08x EDI=%08x\n", CS, cs, cpu_state.pc, SS, ss, ESP, es,EAX, BX,ECX,BP, EDX,EDI); - } } static x86seg *codegen_generate_ea_16_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) @@ -1122,17 +1092,6 @@ generate_call: addlong(codegen_block_ins); codegen_block_ins = 0; } -#if 0 - if (codegen_block_full_ins) - { - addbyte(0x81); /*ADD $codegen_block_ins,ins*/ - addbyte(0x04); - addbyte(0x25); - addlong((uint32_t)&cpu_recomp_full_ins); - addlong(codegen_block_full_ins); - codegen_block_full_ins = 0; - } -#endif } if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) @@ -1159,8 +1118,6 @@ generate_call: } op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; -// if (output) -// pclog("Generate call at %08X %02X %08X %02X %08X %08X %08X %08X %08X %02X %02X %02X %02X\n", &codeblock[block_current][block_pos], opcode, new_pc, ram[old_pc], EAX, EBX, ECX, EDX, ESI, ram[0x7bd2+6],ram[0x7bd2+7],ram[0x7bd2+8],ram[0x7bd2+9]); if (op_ssegs != last_ssegs) { last_ssegs = op_ssegs; @@ -1169,7 +1126,6 @@ generate_call: addbyte((uint8_t)cpu_state_offset(ssegs)); addbyte(op_ssegs); } -//#if 0 if ((!test_modrm || (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode]))/* && !(op_32 & 0x200)*/) @@ -1195,10 +1151,8 @@ generate_call: op_ea_seg = codegen_generate_ea_32_long(op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); op_pc -= pc_off; } -//#endif if (op_ea_seg != last_ea_seg) { -// last_ea_seg = op_ea_seg; addbyte(0xC7); /*MOVL $&_ds,(ea_seg)*/ addbyte(0x45); addbyte((uint8_t)cpu_state_offset(ea_seg)); @@ -1235,8 +1189,6 @@ generate_call: addbyte(0x0F); addbyte(0x85); /*JNZ 0*/ addlong((uint32_t)(uintptr_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(uintptr_t)(&block->data[block_pos + 4])); -// call(block, codegen_debug); - codegen_endpc = (cs + cpu_state.pc) + 8; } diff --git a/src/cpu/codegen_x86.c b/src/cpu/codegen_x86.c index 5fdf8b532..e7d53ea9f 100644 --- a/src/cpu/codegen_x86.c +++ b/src/cpu/codegen_x86.c @@ -1,3 +1,41 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Dynamic Recompiler for Intel 32-bit systems. + * + * Version: @(#)codegen_x86.c 1.0.3 2018/05/05 + * + * Authors: Fred N. van Kempen, + * Sarah Walker, + * Miran Grca, + * + * Copyright 2018 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _WIN32 #include @@ -956,11 +994,6 @@ static uint32_t gen_MEM_CHECK_WRITE() return addr; } -/*static void checkdebug(uint32_t a) -{ - pclog("checkdebug %08x\n", a); -}*/ - static uint32_t gen_MEM_CHECK_WRITE_W() { uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; @@ -1200,10 +1233,17 @@ void codegen_init() block_pos = (block_pos + 15) & ~15; mem_check_write_l = (uint32_t)gen_MEM_CHECK_WRITE_L(); +#ifndef _MSC_VER asm( "fstcw %0\n" : "=m" (cpu_state.old_npxc) ); +#else + __asm + { + fstcw cpu_state.old_npxc + } +#endif } void codegen_reset() @@ -1215,20 +1255,6 @@ void codegen_reset() void dump_block() { -/* codeblock_t *block = pages[0x119000 >> 12].block; - - pclog("dump_block:\n"); - while (block) - { - uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff); - uint32_t end_pc = (block->endpc & 0xffc) | (block->phys & ~0xfff); - pclog(" %p : %08x-%08x %08x-%08x %p %p\n", (void *)block, start_pc, end_pc, block->pc, block->endpc, (void *)block->prev, (void *)block->next); - if (!block->pc) - fatal("Dead PC=0\n"); - - block = block->next; - } - pclog("dump_block done\n");*/ } static void add_to_block_list(codeblock_t *block) @@ -1657,10 +1683,6 @@ int opcode_0f_modrm[256] = void codegen_debug() { - if (output) - { - pclog("At %04x(%08x):%04x %04x(%08x):%04x es=%08x EAX=%08x BX=%04x ECX=%08x BP=%04x EDX=%08x EDI=%08x\n", CS, cs, cpu_state.pc, SS, ss, ESP, es,EAX, BX,ECX,BP, EDX,EDI); - } } static x86seg *codegen_generate_ea_16_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) @@ -1844,7 +1866,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t codeblock_t *block = &codeblock[block_current]; uint32_t op_32 = use32; uint32_t op_pc = new_pc; - OpFn *op_table = x86_dynarec_opcodes; + const OpFn *op_table = x86_dynarec_opcodes; RecompOpFn *recomp_op_table = recomp_opcodes; int opcode_shift = 0; int opcode_mask = 0x3ff; diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 626b48f02..cd5804b71 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -1,22 +1,42 @@ /* - * 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. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * CPU type handler. * - * Version: @(#)cpu.c 1.0.14 2018/03/11 + * Version: @(#)cpu.c 1.0.6 2018/05/05 * - * Authors: Sarah Walker, + * Authors: Fred N. van Kempen, + * Sarah Walker, * leilei, * Miran Grca, * + * Copyright 2018 Fred N. van Kempen. * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 leilei. * Copyright 2016-2018 Miran Grca. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #include #include @@ -31,58 +51,11 @@ #include "../mem.h" #include "../pci.h" #ifdef USE_DYNAREC -#include "codegen.h" +# include "codegen.h" #endif -int isa_cycles; -static uint8_t ccr0, ccr1, ccr2, ccr3, ccr4, ccr5, ccr6; -#ifdef USE_DYNAREC -OpFn *x86_dynarec_opcodes; -OpFn *x86_dynarec_opcodes_0f; -OpFn *x86_dynarec_opcodes_d8_a16; -OpFn *x86_dynarec_opcodes_d8_a32; -OpFn *x86_dynarec_opcodes_d9_a16; -OpFn *x86_dynarec_opcodes_d9_a32; -OpFn *x86_dynarec_opcodes_da_a16; -OpFn *x86_dynarec_opcodes_da_a32; -OpFn *x86_dynarec_opcodes_db_a16; -OpFn *x86_dynarec_opcodes_db_a32; -OpFn *x86_dynarec_opcodes_dc_a16; -OpFn *x86_dynarec_opcodes_dc_a32; -OpFn *x86_dynarec_opcodes_dd_a16; -OpFn *x86_dynarec_opcodes_dd_a32; -OpFn *x86_dynarec_opcodes_de_a16; -OpFn *x86_dynarec_opcodes_de_a32; -OpFn *x86_dynarec_opcodes_df_a16; -OpFn *x86_dynarec_opcodes_df_a32; -OpFn *x86_dynarec_opcodes_REPE; -OpFn *x86_dynarec_opcodes_REPNE; -#endif - -OpFn *x86_opcodes; -OpFn *x86_opcodes_0f; -OpFn *x86_opcodes_d8_a16; -OpFn *x86_opcodes_d8_a32; -OpFn *x86_opcodes_d9_a16; -OpFn *x86_opcodes_d9_a32; -OpFn *x86_opcodes_da_a16; -OpFn *x86_opcodes_da_a32; -OpFn *x86_opcodes_db_a16; -OpFn *x86_opcodes_db_a32; -OpFn *x86_opcodes_dc_a16; -OpFn *x86_opcodes_dc_a32; -OpFn *x86_opcodes_dd_a16; -OpFn *x86_opcodes_dd_a32; -OpFn *x86_opcodes_de_a16; -OpFn *x86_opcodes_de_a32; -OpFn *x86_opcodes_df_a16; -OpFn *x86_opcodes_df_a32; -OpFn *x86_opcodes_REPE; -OpFn *x86_opcodes_REPNE; - -enum -{ +enum { CPUID_FPU = (1 << 0), CPUID_VME = (1 << 1), CPUID_PSE = (1 << 3), @@ -96,93 +69,145 @@ enum CPUID_FXSR = (1 << 24) }; -CPU *cpu_s; -int cpu_effective; -int cpu_multi; -int cpu_iscyrix; -int cpu_16bitbus; -int cpu_busspeed; -int cpu_hasrdtsc; -int cpu_hasMMX, cpu_hasMSR; -int cpu_hasCR4; -int cpu_hasVME; -int cpu_cyrix_alignment; -int hasfpu; -int cpuspeed; -uint64_t cpu_CR4_mask; - -int cpu_cycles_read, cpu_cycles_read_l, cpu_cycles_write, cpu_cycles_write_l; -int cpu_prefetch_cycles, cpu_prefetch_width, cpu_mem_prefetch_cycles, cpu_rom_prefetch_cycles; -int cpu_waitstates; -int cpu_cache_int_enabled, cpu_cache_ext_enabled; -int cpu_pci_speed; - -int is286, is386, is486; -int israpidcad, is_pentium; - -uint64_t tsc = 0; - -cr0_t CR0; -uint64_t pmc[2] = {0, 0}; - -uint16_t temp_seg_data[4] = {0, 0, 0, 0}; - -#ifdef DEV_BRANCH -#ifdef USE_I686 -uint16_t cs_msr = 0; -uint32_t esp_msr = 0; -uint32_t eip_msr = 0; -uint64_t apic_base_msr = 0; -uint64_t mtrr_cap_msr = 0; -uint64_t mtrr_physbase_msr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; -uint64_t mtrr_physmask_msr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; -uint64_t mtrr_fix64k_8000_msr = 0; -uint64_t mtrr_fix16k_8000_msr = 0; -uint64_t mtrr_fix16k_a000_msr = 0; -uint64_t mtrr_fix4k_msr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; -uint64_t pat_msr = 0; -uint64_t mtrr_deftype_msr = 0; -uint64_t msr_ia32_pmc[8] = {0, 0, 0, 0, 0, 0, 0, 0}; -uint64_t ecx17_msr = 0; -uint64_t ecx79_msr = 0; -uint64_t ecx8x_msr[4] = {0, 0, 0, 0}; -uint64_t ecx116_msr = 0; -uint64_t ecx11x_msr[4] = {0, 0, 0, 0}; -uint64_t ecx11e_msr = 0; -uint64_t ecx186_msr = 0; -uint64_t ecx187_msr = 0; -uint64_t ecx1e0_msr = 0; -uint64_t ecx570_msr = 0; -#endif +#ifdef USE_DYNAREC +const OpFn *x86_dynarec_opcodes; +const OpFn *x86_dynarec_opcodes_0f; +const OpFn *x86_dynarec_opcodes_d8_a16; +const OpFn *x86_dynarec_opcodes_d8_a32; +const OpFn *x86_dynarec_opcodes_d9_a16; +const OpFn *x86_dynarec_opcodes_d9_a32; +const OpFn *x86_dynarec_opcodes_da_a16; +const OpFn *x86_dynarec_opcodes_da_a32; +const OpFn *x86_dynarec_opcodes_db_a16; +const OpFn *x86_dynarec_opcodes_db_a32; +const OpFn *x86_dynarec_opcodes_dc_a16; +const OpFn *x86_dynarec_opcodes_dc_a32; +const OpFn *x86_dynarec_opcodes_dd_a16; +const OpFn *x86_dynarec_opcodes_dd_a32; +const OpFn *x86_dynarec_opcodes_de_a16; +const OpFn *x86_dynarec_opcodes_de_a32; +const OpFn *x86_dynarec_opcodes_df_a16; +const OpFn *x86_dynarec_opcodes_df_a32; +const OpFn *x86_dynarec_opcodes_REPE; +const OpFn *x86_dynarec_opcodes_REPNE; #endif -#ifdef DEV_BRANCH -#ifdef USE_AMD_K -/* AMD K5 and K6 MSR's. */ -uint64_t ecx83_msr = 0; -/* These are K6-only. */ -uint64_t star = 0; -uint64_t sfmask = 0; -#endif +const OpFn *x86_opcodes; +const OpFn *x86_opcodes_0f; +const OpFn *x86_opcodes_d8_a16; +const OpFn *x86_opcodes_d8_a32; +const OpFn *x86_opcodes_d9_a16; +const OpFn *x86_opcodes_d9_a32; +const OpFn *x86_opcodes_da_a16; +const OpFn *x86_opcodes_da_a32; +const OpFn *x86_opcodes_db_a16; +const OpFn *x86_opcodes_db_a32; +const OpFn *x86_opcodes_dc_a16; +const OpFn *x86_opcodes_dc_a32; +const OpFn *x86_opcodes_dd_a16; +const OpFn *x86_opcodes_dd_a32; +const OpFn *x86_opcodes_de_a16; +const OpFn *x86_opcodes_de_a32; +const OpFn *x86_opcodes_df_a16; +const OpFn *x86_opcodes_df_a32; +const OpFn *x86_opcodes_REPE; +const OpFn *x86_opcodes_REPNE; + +CPU *cpu_s; +int cpu_effective; +int cpu_multi; +int cpu_16bitbus; +int cpu_busspeed; +int cpu_cyrix_alignment; +int cpuspeed; +int CPUID; +uint64_t cpu_CR4_mask; +int isa_cycles; +int cpu_cycles_read, cpu_cycles_read_l, + cpu_cycles_write, cpu_cycles_write_l; +int cpu_prefetch_cycles, cpu_prefetch_width, + cpu_mem_prefetch_cycles, cpu_rom_prefetch_cycles; +int cpu_waitstates; +int cpu_cache_int_enabled, cpu_cache_ext_enabled; +int cpu_pci_speed; + +int is286, + is386, + is486, + cpu_iscyrix, + israpidcad, + is_pentium; + +int hasfpu, + cpu_hasrdtsc, + cpu_hasMMX, + cpu_hasMSR, + cpu_hasCR4, + cpu_hasVME; + + +uint64_t tsc = 0; +msr_t msr; +cr0_t CR0; +uint64_t pmc[2] = {0, 0}; + +uint16_t temp_seg_data[4] = {0, 0, 0, 0}; + +#if defined(DEV_BRANCH) && defined(USE_I686) +uint16_t cs_msr = 0; +uint32_t esp_msr = 0; +uint32_t eip_msr = 0; +uint64_t apic_base_msr = 0; +uint64_t mtrr_cap_msr = 0; +uint64_t mtrr_physbase_msr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +uint64_t mtrr_physmask_msr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +uint64_t mtrr_fix64k_8000_msr = 0; +uint64_t mtrr_fix16k_8000_msr = 0; +uint64_t mtrr_fix16k_a000_msr = 0; +uint64_t mtrr_fix4k_msr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +uint64_t pat_msr = 0; +uint64_t mtrr_deftype_msr = 0; +uint64_t msr_ia32_pmc[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +uint64_t ecx17_msr = 0; +uint64_t ecx79_msr = 0; +uint64_t ecx8x_msr[4] = {0, 0, 0, 0}; +uint64_t ecx116_msr = 0; +uint64_t ecx11x_msr[4] = {0, 0, 0, 0}; +uint64_t ecx11e_msr = 0; +uint64_t ecx186_msr = 0; +uint64_t ecx187_msr = 0; +uint64_t ecx1e0_msr = 0; +uint64_t ecx570_msr = 0; #endif -int timing_rr; -int timing_mr, timing_mrl; -int timing_rm, timing_rml; -int timing_mm, timing_mml; -int timing_bt, timing_bnt; -int timing_int, timing_int_rm, timing_int_v86, timing_int_pm, timing_int_pm_outer; -int timing_iret_rm, timing_iret_v86, timing_iret_pm, timing_iret_pm_outer; -int timing_call_rm, timing_call_pm, timing_call_pm_gate, timing_call_pm_gate_inner; -int timing_retf_rm, timing_retf_pm, timing_retf_pm_outer; -int timing_jmp_rm, timing_jmp_pm, timing_jmp_pm_gate; -int timing_misaligned; +#if defined(DEV_BRANCH) && defined(USE_AMD_K) +uint64_t ecx83_msr = 0; /* AMD K5 and K6 MSR's. */ +uint64_t star = 0; /* These are K6-only. */ +uint64_t sfmask = 0; +#endif -msr_t msr; +int timing_rr; +int timing_mr, timing_mrl; +int timing_rm, timing_rml; +int timing_mm, timing_mml; +int timing_bt, timing_bnt; +int timing_int, timing_int_rm, timing_int_v86, timing_int_pm, + timing_int_pm_outer; +int timing_iret_rm, timing_iret_v86, timing_iret_pm, + timing_iret_pm_outer; +int timing_call_rm, timing_call_pm, timing_call_pm_gate, + timing_call_pm_gate_inner; +int timing_retf_rm, timing_retf_pm, timing_retf_pm_outer; +int timing_jmp_rm, timing_jmp_pm, timing_jmp_pm_gate; +int timing_misaligned; -void cpu_dynamic_switch(int new_cpu) +static uint8_t ccr0, ccr1, ccr2, ccr3, ccr4, ccr5, ccr6; + + +void +cpu_dynamic_switch(int new_cpu) { if (cpu_effective == new_cpu) return; @@ -194,16 +219,17 @@ void cpu_dynamic_switch(int new_cpu) cpu = c; } -void cpu_set_edx() + +void +cpu_set_edx(void) { EDX = machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].edx_reset; } -void cpu_set() +void +cpu_set(void) { - CPU *cpu_s; - if (!machines[machine].cpu[cpu_manufacturer].cpus) { /*CPU is invalid, set to default*/ @@ -250,7 +276,7 @@ void cpu_set() cpu_rom_prefetch_cycles = cpu_mem_prefetch_cycles; else cpu_rom_prefetch_cycles = cpu_s->rspeed / 1000000; - + if (cpu_s->pci_speed) { pci_nonburst_time = 4*cpu_s->rspeed / cpu_s->pci_speed; @@ -261,16 +287,12 @@ void cpu_set() pci_nonburst_time = 4; pci_burst_time = 1; } - pclog("PCI burst=%i nonburst=%i\n", pci_burst_time, pci_nonburst_time); if (cpu_iscyrix) io_sethandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL, NULL); else io_removehandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL, NULL); - pclog("hasfpu - %i\n",hasfpu); - pclog("is486 - %i %i\n",is486,cpu_s->cpu_type); - #ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_386_0f, dynarec_ops_386, dynarec_ops_386_0f); #else @@ -1091,8 +1113,7 @@ void cpu_set() ccr4 = 0x80; break; -#ifdef DEV_BRANCH -#ifdef USE_AMD_K +#if defined(DEV_BRANCH) && defined(USE_AMD_K) case CPU_K5: case CPU_5K86: #ifdef USE_DYNAREC @@ -1146,10 +1167,8 @@ void cpu_set() #endif break; #endif -#endif -#ifdef DEV_BRANCH -#ifdef USE_I686 +#if defined(DEV_BRANCH) && defined(USE_I686) case CPU_PENTIUMPRO: #ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_pentiumpro_0f, dynarec_ops_386, dynarec_ops_pentiumpro_0f); @@ -1271,7 +1290,6 @@ void cpu_set() codegen_timing_set(&codegen_timing_686); #endif break; -#endif #endif default: @@ -1294,7 +1312,8 @@ cpu_current_pc(char *bufp) } -void cpu_CPUID() +void +cpu_CPUID(void) { switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type) { @@ -1313,7 +1332,7 @@ void cpu_CPUID() EDX = CPUID_FPU; /*FPU*/ } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; case CPU_iDX4: @@ -1331,7 +1350,7 @@ void cpu_CPUID() EDX = CPUID_FPU | CPUID_VME; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; case CPU_Am486SX: @@ -1348,7 +1367,7 @@ void cpu_CPUID() EBX = ECX = EDX = 0; /*No FPU*/ } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; case CPU_Am486DX: @@ -1366,7 +1385,7 @@ void cpu_CPUID() EDX = CPUID_FPU; /*FPU*/ } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; case CPU_WINCHIP: @@ -1397,7 +1416,7 @@ void cpu_CPUID() EDX |= CPUID_MMX; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; case CPU_PENTIUM: @@ -1415,11 +1434,10 @@ void cpu_CPUID() EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; -#ifdef DEV_BRANCH -#ifdef USE_AMD_K +#if defined(DEV_BRANCH) && defined(USE_AMD_K) case CPU_K5: if (!EAX) { @@ -1435,7 +1453,7 @@ void cpu_CPUID() EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; case CPU_5K86: @@ -1487,7 +1505,7 @@ void cpu_CPUID() EDX = 0x10040120; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; case CPU_K6: @@ -1549,9 +1567,8 @@ void cpu_CPUID() EDX = 0x444D416E; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; -#endif #endif case CPU_PENTIUMMMX: @@ -1569,7 +1586,7 @@ void cpu_CPUID() EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; @@ -1588,7 +1605,7 @@ void cpu_CPUID() EDX = CPUID_FPU; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; @@ -1607,7 +1624,7 @@ void cpu_CPUID() EDX = CPUID_FPU | CPUID_CMPXCHG8B; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; @@ -1626,7 +1643,7 @@ void cpu_CPUID() EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; @@ -1646,7 +1663,7 @@ void cpu_CPUID() EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_CMOV | CPUID_MMX; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; #ifdef DEV_BRANCH @@ -1669,7 +1686,7 @@ void cpu_CPUID() { } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; /* case CPU_PENTIUM2: @@ -1693,7 +1710,7 @@ void cpu_CPUID() EDX = 0x0C040843; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; */ case CPU_PENTIUM2D: @@ -1717,7 +1734,7 @@ void cpu_CPUID() EDX = 0x0C040844; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; #endif #endif @@ -1759,8 +1776,7 @@ void cpu_RDMSR() } break; -#ifdef DEV_BRANCH -#ifdef USE_AMD_K +#if defined(DEV_BRANCH) && defined(USE_AMD_K) case CPU_K5: case CPU_5K86: case CPU_K6: @@ -1787,14 +1803,10 @@ void cpu_RDMSR() EDX = sfmask >> 32; break; default: -#ifndef RELEASE_BUILD - pclog("Invalid MSR: %08X\n", ECX); -#endif x86gpf(NULL, 0); break; } break; -#endif #endif case CPU_PENTIUM: @@ -1941,9 +1953,6 @@ void cpu_RDMSR() break; default: i686_invalid_rdmsr: -#ifndef RELEASE_BUILD - pclog("Invalid MSR: %08X\n", ECX); -#endif x86gpf(NULL, 0); break; } @@ -1988,8 +1997,8 @@ void cpu_WRMSR() break; } break; -#ifdef DEV_BRANCH -#ifdef USE_AMD_K + +#if defined(DEV_BRANCH) && defined(USE_AMD_K) case CPU_K5: case CPU_5K86: case CPU_K6: @@ -2012,7 +2021,6 @@ void cpu_WRMSR() break; } break; -#endif #endif case CPU_PENTIUM: @@ -2124,9 +2132,6 @@ void cpu_WRMSR() break; default: i686_invalid_wrmsr: -#ifndef RELEASE_BUILD - pclog("Invalid MSR: %08X\n", ECX); -#endif x86gpf(NULL, 0); break; } @@ -2202,8 +2207,11 @@ uint8_t cyrix_read(uint16_t addr, void *priv) return 0xff; } + +void #ifdef USE_DYNAREC -void x86_setopcodes(OpFn *opcodes, OpFn *opcodes_0f, OpFn *dynarec_opcodes, OpFn *dynarec_opcodes_0f) +x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f, + const OpFn *dynarec_opcodes, const OpFn *dynarec_opcodes_0f) { x86_opcodes = opcodes; x86_opcodes_0f = opcodes_0f; @@ -2211,22 +2219,24 @@ void x86_setopcodes(OpFn *opcodes, OpFn *opcodes_0f, OpFn *dynarec_opcodes, OpFn x86_dynarec_opcodes_0f = dynarec_opcodes_0f; } #else -void x86_setopcodes(OpFn *opcodes, OpFn *opcodes_0f) +x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f) { x86_opcodes = opcodes; x86_opcodes_0f = opcodes_0f; } #endif -void cpu_update_waitstates() + +void +cpu_update_waitstates(void) { cpu_s = &machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective]; - + if (is486) cpu_prefetch_width = 16; else cpu_prefetch_width = cpu_16bitbus ? 2 : 4; - + if (cpu_cache_int_enabled) { /* Disable prefetch emulation */ @@ -2260,7 +2270,7 @@ void cpu_update_waitstates() cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * cpu_s->mem_write_cycles; } if (is486) - cpu_prefetch_cycles *= 4; + cpu_prefetch_cycles = (cpu_prefetch_cycles * 11) / 16; cpu_mem_prefetch_cycles = cpu_prefetch_cycles; if (cpu_s->rspeed <= 8000000) cpu_rom_prefetch_cycles = cpu_mem_prefetch_cycles; diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index f01b49438..b4efb8a3c 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -8,7 +8,7 @@ * * CPU type handler. * - * Version: @(#)cpu.h 1.0.10 2018/03/11 + * Version: @(#)cpu.h 1.0.11 2018/03/28 * * Authors: Sarah Walker, * leilei, @@ -258,7 +258,11 @@ struct _cpustate_ { #ifdef __MSC__ # define COMPILE_TIME_ASSERT(expr) /*nada*/ #else -# define COMPILE_TIME_ASSERT(expr) typedef char COMP_TIME_ASSERT[(expr) ? 1 : 0]; +# ifdef EXTREME_DEBUG +# define COMPILE_TIME_ASSERT(expr) typedef char COMP_TIME_ASSERT[(expr) ? 1 : 0]; +# else +# define COMPILE_TIME_ASSERT(expr) /*nada*/ +# endif #endif COMPILE_TIME_ASSERT(sizeof(cpu_state) <= 128) diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 92fdd93f4..bf978c9fc 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -29,7 +29,7 @@ * 16 = 180 MHz * 17 = 200 MHz * - * Version: @(#)cpu_table.c 1.0.4 2018/02/18 + * Version: @(#)cpu_table.c 1.0.5 2018/07/17 * * Authors: Sarah Walker, * leilei, diff --git a/src/cpu/x86_ops.h b/src/cpu/x86_ops.h index c0ff64ade..5b30c0747 100644 --- a/src/cpu/x86_ops.h +++ b/src/cpu/x86_ops.h @@ -1,6 +1,41 @@ -/* Copyright holders: Sarah Walker, leilei - see COPYING for more details -*/ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Miscellaneous x86 CPU Instructions. + * + * Version: @(#)x86_ops.h 1.0.2 2018/05/05 + * + * Authors: Fred N. van Kempen, + * Sarah Walker, + * Miran Grca, + * + * Copyright 2018 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ #ifndef _X86_OPS_H #define _X86_OPS_H @@ -11,194 +46,188 @@ typedef int (*OpFn)(uint32_t fetchdat); #ifdef USE_DYNAREC -void x86_setopcodes(OpFn *opcodes, OpFn *opcodes_0f, OpFn *dynarec_opcodes, OpFn *dynarec_opcodes_0f); +void x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f, + const OpFn *dynarec_opcodes, + const OpFn *dynarec_opcodes_0f); -extern OpFn *x86_dynarec_opcodes; -extern OpFn *x86_dynarec_opcodes_0f; -extern OpFn *x86_dynarec_opcodes_d8_a16; -extern OpFn *x86_dynarec_opcodes_d8_a32; -extern OpFn *x86_dynarec_opcodes_d9_a16; -extern OpFn *x86_dynarec_opcodes_d9_a32; -extern OpFn *x86_dynarec_opcodes_da_a16; -extern OpFn *x86_dynarec_opcodes_da_a32; -extern OpFn *x86_dynarec_opcodes_db_a16; -extern OpFn *x86_dynarec_opcodes_db_a32; -extern OpFn *x86_dynarec_opcodes_dc_a16; -extern OpFn *x86_dynarec_opcodes_dc_a32; -extern OpFn *x86_dynarec_opcodes_dd_a16; -extern OpFn *x86_dynarec_opcodes_dd_a32; -extern OpFn *x86_dynarec_opcodes_de_a16; -extern OpFn *x86_dynarec_opcodes_de_a32; -extern OpFn *x86_dynarec_opcodes_df_a16; -extern OpFn *x86_dynarec_opcodes_df_a32; -extern OpFn *x86_dynarec_opcodes_REPE; -extern OpFn *x86_dynarec_opcodes_REPNE; +extern const OpFn *x86_dynarec_opcodes; +extern const OpFn *x86_dynarec_opcodes_0f; +extern const OpFn *x86_dynarec_opcodes_d8_a16; +extern const OpFn *x86_dynarec_opcodes_d8_a32; +extern const OpFn *x86_dynarec_opcodes_d9_a16; +extern const OpFn *x86_dynarec_opcodes_d9_a32; +extern const OpFn *x86_dynarec_opcodes_da_a16; +extern const OpFn *x86_dynarec_opcodes_da_a32; +extern const OpFn *x86_dynarec_opcodes_db_a16; +extern const OpFn *x86_dynarec_opcodes_db_a32; +extern const OpFn *x86_dynarec_opcodes_dc_a16; +extern const OpFn *x86_dynarec_opcodes_dc_a32; +extern const OpFn *x86_dynarec_opcodes_dd_a16; +extern const OpFn *x86_dynarec_opcodes_dd_a32; +extern const OpFn *x86_dynarec_opcodes_de_a16; +extern const OpFn *x86_dynarec_opcodes_de_a32; +extern const OpFn *x86_dynarec_opcodes_df_a16; +extern const OpFn *x86_dynarec_opcodes_df_a32; +extern const OpFn *x86_dynarec_opcodes_REPE; +extern const OpFn *x86_dynarec_opcodes_REPNE; -extern OpFn dynarec_ops_286[1024]; -extern OpFn dynarec_ops_286_0f[1024]; +extern const OpFn dynarec_ops_286[1024]; +extern const OpFn dynarec_ops_286_0f[1024]; -extern OpFn dynarec_ops_386[1024]; -extern OpFn dynarec_ops_386_0f[1024]; +extern const OpFn dynarec_ops_386[1024]; +extern const OpFn dynarec_ops_386_0f[1024]; -extern OpFn dynarec_ops_486_0f[1024]; +extern const OpFn dynarec_ops_486_0f[1024]; -extern OpFn dynarec_ops_winchip_0f[1024]; +extern const OpFn dynarec_ops_winchip_0f[1024]; -extern OpFn dynarec_ops_pentium_0f[1024]; -extern OpFn dynarec_ops_pentiummmx_0f[1024]; -extern OpFn dynarec_ops_c6x86mx_0f[1024]; +extern const OpFn dynarec_ops_pentium_0f[1024]; +extern const OpFn dynarec_ops_pentiummmx_0f[1024]; +extern const OpFn dynarec_ops_c6x86mx_0f[1024]; -#ifdef DEV_BRANCH -#ifdef USE_AMD_K -extern OpFn dynarec_ops_k6_0f[1024]; -#endif +#if defined(DEV_BRANCH) && defined(USE_AMD_K) +extern const OpFn dynarec_ops_k6_0f[1024]; #endif -#ifdef DEV_BRANCH -#ifdef USE_I686 -extern OpFn dynarec_ops_pentiumpro_0f[1024]; -extern OpFn dynarec_ops_pentium2d_0f[1024]; -#endif +#if defined(DEV_BRANCH) && defined(USE_I686) +extern const OpFn dynarec_ops_pentiumpro_0f[1024]; +extern const OpFn dynarec_ops_pentium2d_0f[1024]; #endif -extern OpFn dynarec_ops_fpu_287_d9_a16[256]; -extern OpFn dynarec_ops_fpu_287_d9_a32[256]; -extern OpFn dynarec_ops_fpu_287_da_a16[256]; -extern OpFn dynarec_ops_fpu_287_da_a32[256]; -extern OpFn dynarec_ops_fpu_287_db_a16[256]; -extern OpFn dynarec_ops_fpu_287_db_a32[256]; -extern OpFn dynarec_ops_fpu_287_dc_a16[32]; -extern OpFn dynarec_ops_fpu_287_dc_a32[32]; -extern OpFn dynarec_ops_fpu_287_dd_a16[256]; -extern OpFn dynarec_ops_fpu_287_dd_a32[256]; -extern OpFn dynarec_ops_fpu_287_de_a16[256]; -extern OpFn dynarec_ops_fpu_287_de_a32[256]; -extern OpFn dynarec_ops_fpu_287_df_a16[256]; -extern OpFn dynarec_ops_fpu_287_df_a32[256]; +extern const OpFn dynarec_ops_fpu_287_d9_a16[256]; +extern const OpFn dynarec_ops_fpu_287_d9_a32[256]; +extern const OpFn dynarec_ops_fpu_287_da_a16[256]; +extern const OpFn dynarec_ops_fpu_287_da_a32[256]; +extern const OpFn dynarec_ops_fpu_287_db_a16[256]; +extern const OpFn dynarec_ops_fpu_287_db_a32[256]; +extern const OpFn dynarec_ops_fpu_287_dc_a16[32]; +extern const OpFn dynarec_ops_fpu_287_dc_a32[32]; +extern const OpFn dynarec_ops_fpu_287_dd_a16[256]; +extern const OpFn dynarec_ops_fpu_287_dd_a32[256]; +extern const OpFn dynarec_ops_fpu_287_de_a16[256]; +extern const OpFn dynarec_ops_fpu_287_de_a32[256]; +extern const OpFn dynarec_ops_fpu_287_df_a16[256]; +extern const OpFn dynarec_ops_fpu_287_df_a32[256]; -extern OpFn dynarec_ops_fpu_d8_a16[32]; -extern OpFn dynarec_ops_fpu_d8_a32[32]; -extern OpFn dynarec_ops_fpu_d9_a16[256]; -extern OpFn dynarec_ops_fpu_d9_a32[256]; -extern OpFn dynarec_ops_fpu_da_a16[256]; -extern OpFn dynarec_ops_fpu_da_a32[256]; -extern OpFn dynarec_ops_fpu_db_a16[256]; -extern OpFn dynarec_ops_fpu_db_a32[256]; -extern OpFn dynarec_ops_fpu_dc_a16[32]; -extern OpFn dynarec_ops_fpu_dc_a32[32]; -extern OpFn dynarec_ops_fpu_dd_a16[256]; -extern OpFn dynarec_ops_fpu_dd_a32[256]; -extern OpFn dynarec_ops_fpu_de_a16[256]; -extern OpFn dynarec_ops_fpu_de_a32[256]; -extern OpFn dynarec_ops_fpu_df_a16[256]; -extern OpFn dynarec_ops_fpu_df_a32[256]; -extern OpFn dynarec_ops_nofpu_a16[256]; -extern OpFn dynarec_ops_nofpu_a32[256]; +extern const OpFn dynarec_ops_fpu_d8_a16[32]; +extern const OpFn dynarec_ops_fpu_d8_a32[32]; +extern const OpFn dynarec_ops_fpu_d9_a16[256]; +extern const OpFn dynarec_ops_fpu_d9_a32[256]; +extern const OpFn dynarec_ops_fpu_da_a16[256]; +extern const OpFn dynarec_ops_fpu_da_a32[256]; +extern const OpFn dynarec_ops_fpu_db_a16[256]; +extern const OpFn dynarec_ops_fpu_db_a32[256]; +extern const OpFn dynarec_ops_fpu_dc_a16[32]; +extern const OpFn dynarec_ops_fpu_dc_a32[32]; +extern const OpFn dynarec_ops_fpu_dd_a16[256]; +extern const OpFn dynarec_ops_fpu_dd_a32[256]; +extern const OpFn dynarec_ops_fpu_de_a16[256]; +extern const OpFn dynarec_ops_fpu_de_a32[256]; +extern const OpFn dynarec_ops_fpu_df_a16[256]; +extern const OpFn dynarec_ops_fpu_df_a32[256]; +extern const OpFn dynarec_ops_nofpu_a16[256]; +extern const OpFn dynarec_ops_nofpu_a32[256]; -extern OpFn dynarec_ops_fpu_686_da_a16[256]; -extern OpFn dynarec_ops_fpu_686_da_a32[256]; -extern OpFn dynarec_ops_fpu_686_db_a16[256]; -extern OpFn dynarec_ops_fpu_686_db_a32[256]; -extern OpFn dynarec_ops_fpu_686_df_a16[256]; -extern OpFn dynarec_ops_fpu_686_df_a32[256]; +extern const OpFn dynarec_ops_fpu_686_da_a16[256]; +extern const OpFn dynarec_ops_fpu_686_da_a32[256]; +extern const OpFn dynarec_ops_fpu_686_db_a16[256]; +extern const OpFn dynarec_ops_fpu_686_db_a32[256]; +extern const OpFn dynarec_ops_fpu_686_df_a16[256]; +extern const OpFn dynarec_ops_fpu_686_df_a32[256]; -extern OpFn dynarec_ops_REPE[1024]; -extern OpFn dynarec_ops_REPNE[1024]; +extern const OpFn dynarec_ops_REPE[1024]; +extern const OpFn dynarec_ops_REPNE[1024]; #else -void x86_setopcodes(OpFn *opcodes, OpFn *opcodes_0f); +void x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f); #endif -extern OpFn *x86_opcodes; -extern OpFn *x86_opcodes_0f; -extern OpFn *x86_opcodes_d8_a16; -extern OpFn *x86_opcodes_d8_a32; -extern OpFn *x86_opcodes_d9_a16; -extern OpFn *x86_opcodes_d9_a32; -extern OpFn *x86_opcodes_da_a16; -extern OpFn *x86_opcodes_da_a32; -extern OpFn *x86_opcodes_db_a16; -extern OpFn *x86_opcodes_db_a32; -extern OpFn *x86_opcodes_dc_a16; -extern OpFn *x86_opcodes_dc_a32; -extern OpFn *x86_opcodes_dd_a16; -extern OpFn *x86_opcodes_dd_a32; -extern OpFn *x86_opcodes_de_a16; -extern OpFn *x86_opcodes_de_a32; -extern OpFn *x86_opcodes_df_a16; -extern OpFn *x86_opcodes_df_a32; -extern OpFn *x86_opcodes_REPE; -extern OpFn *x86_opcodes_REPNE; +extern const OpFn *x86_opcodes; +extern const OpFn *x86_opcodes_0f; +extern const OpFn *x86_opcodes_d8_a16; +extern const OpFn *x86_opcodes_d8_a32; +extern const OpFn *x86_opcodes_d9_a16; +extern const OpFn *x86_opcodes_d9_a32; +extern const OpFn *x86_opcodes_da_a16; +extern const OpFn *x86_opcodes_da_a32; +extern const OpFn *x86_opcodes_db_a16; +extern const OpFn *x86_opcodes_db_a32; +extern const OpFn *x86_opcodes_dc_a16; +extern const OpFn *x86_opcodes_dc_a32; +extern const OpFn *x86_opcodes_dd_a16; +extern const OpFn *x86_opcodes_dd_a32; +extern const OpFn *x86_opcodes_de_a16; +extern const OpFn *x86_opcodes_de_a32; +extern const OpFn *x86_opcodes_df_a16; +extern const OpFn *x86_opcodes_df_a32; +extern const OpFn *x86_opcodes_REPE; +extern const OpFn *x86_opcodes_REPNE; -extern OpFn ops_286[1024]; -extern OpFn ops_286_0f[1024]; +extern const OpFn ops_286[1024]; +extern const OpFn ops_286_0f[1024]; -extern OpFn ops_386[1024]; -extern OpFn ops_386_0f[1024]; +extern const OpFn ops_386[1024]; +extern const OpFn ops_386_0f[1024]; -extern OpFn ops_486_0f[1024]; +extern const OpFn ops_486_0f[1024]; -extern OpFn ops_winchip_0f[1024]; +extern const OpFn ops_winchip_0f[1024]; -extern OpFn ops_pentium_0f[1024]; -extern OpFn ops_pentiummmx_0f[1024]; +extern const OpFn ops_pentium_0f[1024]; +extern const OpFn ops_pentiummmx_0f[1024]; -extern OpFn ops_c6x86mx_0f[1024]; +extern const OpFn ops_c6x86mx_0f[1024]; -#ifdef DEV_BRANCH -#ifdef USE_AMD_K -extern OpFn ops_k6_0f[1024]; -#endif +#if defined(DEV_BRANCH) && defined(USE_AMD_K) +extern const OpFn ops_k6_0f[1024]; #endif -#ifdef DEV_BRANCH -#ifdef USE_I686 -extern OpFn ops_pentiumpro_0f[1024]; -extern OpFn ops_pentium2d_0f[1024]; -#endif +#if defined(DEV_BRANCH) && defined(USE_I686) +extern const OpFn ops_pentiumpro_0f[1024]; +extern const OpFn ops_pentium2d_0f[1024]; #endif -extern OpFn ops_fpu_287_d9_a16[256]; -extern OpFn ops_fpu_287_d9_a32[256]; -extern OpFn ops_fpu_287_da_a16[256]; -extern OpFn ops_fpu_287_da_a32[256]; -extern OpFn ops_fpu_287_db_a16[256]; -extern OpFn ops_fpu_287_db_a32[256]; -extern OpFn ops_fpu_287_dc_a16[32]; -extern OpFn ops_fpu_287_dc_a32[32]; -extern OpFn ops_fpu_287_dd_a16[256]; -extern OpFn ops_fpu_287_dd_a32[256]; -extern OpFn ops_fpu_287_de_a16[256]; -extern OpFn ops_fpu_287_de_a32[256]; -extern OpFn ops_fpu_287_df_a16[256]; -extern OpFn ops_fpu_287_df_a32[256]; +extern const OpFn ops_fpu_287_d9_a16[256]; +extern const OpFn ops_fpu_287_d9_a32[256]; +extern const OpFn ops_fpu_287_da_a16[256]; +extern const OpFn ops_fpu_287_da_a32[256]; +extern const OpFn ops_fpu_287_db_a16[256]; +extern const OpFn ops_fpu_287_db_a32[256]; +extern const OpFn ops_fpu_287_dc_a16[32]; +extern const OpFn ops_fpu_287_dc_a32[32]; +extern const OpFn ops_fpu_287_dd_a16[256]; +extern const OpFn ops_fpu_287_dd_a32[256]; +extern const OpFn ops_fpu_287_de_a16[256]; +extern const OpFn ops_fpu_287_de_a32[256]; +extern const OpFn ops_fpu_287_df_a16[256]; +extern const OpFn ops_fpu_287_df_a32[256]; -extern OpFn ops_fpu_d8_a16[32]; -extern OpFn ops_fpu_d8_a32[32]; -extern OpFn ops_fpu_d9_a16[256]; -extern OpFn ops_fpu_d9_a32[256]; -extern OpFn ops_fpu_da_a16[256]; -extern OpFn ops_fpu_da_a32[256]; -extern OpFn ops_fpu_db_a16[256]; -extern OpFn ops_fpu_db_a32[256]; -extern OpFn ops_fpu_dc_a16[32]; -extern OpFn ops_fpu_dc_a32[32]; -extern OpFn ops_fpu_dd_a16[256]; -extern OpFn ops_fpu_dd_a32[256]; -extern OpFn ops_fpu_de_a16[256]; -extern OpFn ops_fpu_de_a32[256]; -extern OpFn ops_fpu_df_a16[256]; -extern OpFn ops_fpu_df_a32[256]; -extern OpFn ops_nofpu_a16[256]; -extern OpFn ops_nofpu_a32[256]; +extern const OpFn ops_fpu_d8_a16[32]; +extern const OpFn ops_fpu_d8_a32[32]; +extern const OpFn ops_fpu_d9_a16[256]; +extern const OpFn ops_fpu_d9_a32[256]; +extern const OpFn ops_fpu_da_a16[256]; +extern const OpFn ops_fpu_da_a32[256]; +extern const OpFn ops_fpu_db_a16[256]; +extern const OpFn ops_fpu_db_a32[256]; +extern const OpFn ops_fpu_dc_a16[32]; +extern const OpFn ops_fpu_dc_a32[32]; +extern const OpFn ops_fpu_dd_a16[256]; +extern const OpFn ops_fpu_dd_a32[256]; +extern const OpFn ops_fpu_de_a16[256]; +extern const OpFn ops_fpu_de_a32[256]; +extern const OpFn ops_fpu_df_a16[256]; +extern const OpFn ops_fpu_df_a32[256]; +extern const OpFn ops_nofpu_a16[256]; +extern const OpFn ops_nofpu_a32[256]; -extern OpFn ops_fpu_686_da_a16[256]; -extern OpFn ops_fpu_686_da_a32[256]; -extern OpFn ops_fpu_686_db_a16[256]; -extern OpFn ops_fpu_686_db_a32[256]; -extern OpFn ops_fpu_686_df_a16[256]; -extern OpFn ops_fpu_686_df_a32[256]; +extern const OpFn ops_fpu_686_da_a16[256]; +extern const OpFn ops_fpu_686_da_a32[256]; +extern const OpFn ops_fpu_686_db_a16[256]; +extern const OpFn ops_fpu_686_db_a32[256]; +extern const OpFn ops_fpu_686_df_a16[256]; +extern const OpFn ops_fpu_686_df_a32[256]; -extern OpFn ops_REPE[1024]; -extern OpFn ops_REPNE[1024]; +extern const OpFn ops_REPE[1024]; +extern const OpFn ops_REPNE[1024]; #endif /*_X86_OPS_H*/ diff --git a/src/cpu/x86_ops_amd.h b/src/cpu/x86_ops_amd.h index 0b8a1e094..acd7790ff 100644 --- a/src/cpu/x86_ops_amd.h +++ b/src/cpu/x86_ops_amd.h @@ -8,19 +8,12 @@ * * AMD SYSCALL and SYSRET CPU Instructions. * - * Version: @(#)x86_ops_amd.h 1.0.1 2018/01/01 + * Version: @(#)x86_ops_amd.h 1.0.3 2018/04/25 * * Author: Miran Grca, * Copyright 2016-2018 Miran Grca. */ -static int internal_illegal(char *s) -{ - cpu_state.pc = cpu_state.oldpc; - x86gpf(s, 0); - return cpu_state.abrt; -} - /* 0 = Limit 0-15 1 = Base 0-15 2 = Base 16-23 (bits 0-7), Access rights diff --git a/src/cpu/x86_ops_i686.h b/src/cpu/x86_ops_i686.h index 1ef3693b9..d4418bfb4 100644 --- a/src/cpu/x86_ops_i686.h +++ b/src/cpu/x86_ops_i686.h @@ -8,7 +8,7 @@ * * x86 i686 (Pentium Pro/Pentium II) CPU Instructions. * - * Version: @(#)x86_ops_i686.h 1.0.2 2018/01/01 + * Version: @(#)x86_ops_i686.h 1.0.4 2018/04/25 * * Author: Miran Grca, * Copyright 2016-2018 Miran Grca. diff --git a/src/cpu/x86_ops_misc.h b/src/cpu/x86_ops_misc.h index 7448007fb..9fa219919 100644 --- a/src/cpu/x86_ops_misc.h +++ b/src/cpu/x86_ops_misc.h @@ -8,12 +8,12 @@ * * Miscellaneous x86 CPU Instructions. * - * Version: @(#)x86_ops_misc.h 1.0.0 2017/05/30 + * Version: @(#)x86_ops_misc.h 1.0.1 2018/04/12 * * Author: Sarah Walker, * Miran Grca, - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ static int opCBW(uint32_t fetchdat) @@ -70,6 +70,10 @@ static int opF6_a16(uint32_t fetchdat) int8_t temps; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + { + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); + } dst = geteab(); if (cpu_state.abrt) return 1; switch (rmdat & 0x38) { @@ -120,6 +124,7 @@ static int opF6_a16(uint32_t fetchdat) { flags_rebuild(); flags |= 0x8D5; /*Not a Cyrix*/ + flags &= ~1; } } else @@ -127,8 +132,8 @@ static int opF6_a16(uint32_t fetchdat) x86_int(0); return 1; } - CLOCK_CYCLES(is486 ? 16 : 14); - PREFETCH_RUN(is486 ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); + CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 16 : 14); + PREFETCH_RUN((is486 && !cpu_iscyrix) ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); break; case 0x38: /*IDIV AL,b*/ tempws = (int)(int16_t)AX; @@ -142,6 +147,7 @@ static int opF6_a16(uint32_t fetchdat) { flags_rebuild(); flags|=0x8D5; /*Not a Cyrix*/ + flags &= ~1; } } else @@ -217,6 +223,7 @@ static int opF6_a32(uint32_t fetchdat) { flags_rebuild(); flags |= 0x8D5; /*Not a Cyrix*/ + flags &= ~1; } } else @@ -224,8 +231,8 @@ static int opF6_a32(uint32_t fetchdat) x86_int(0); return 1; } - CLOCK_CYCLES(is486 ? 16 : 14); - PREFETCH_RUN(is486 ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); + CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 16 : 14); + PREFETCH_RUN((is486 && !cpu_iscyrix) ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); break; case 0x38: /*IDIV AL,b*/ tempws = (int)(int16_t)AX; @@ -239,6 +246,7 @@ static int opF6_a32(uint32_t fetchdat) { flags_rebuild(); flags|=0x8D5; /*Not a Cyrix*/ + flags &= ~1; } } else @@ -323,8 +331,8 @@ static int opF7_w_a16(uint32_t fetchdat) x86_int(0); return 1; } - CLOCK_CYCLES(is486 ? 24 : 22); - PREFETCH_RUN(is486 ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); + CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 24 : 22); + PREFETCH_RUN((is486 && !cpu_iscyrix) ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); break; case 0x38: /*IDIV AX,w*/ tempws = (int)((DX << 16)|AX); @@ -415,8 +423,8 @@ static int opF7_w_a32(uint32_t fetchdat) x86_int(0); return 1; } - CLOCK_CYCLES(is486 ? 24 : 22); - PREFETCH_RUN(is486 ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); + CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 24 : 22); + PREFETCH_RUN((is486 && !cpu_iscyrix) ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); break; case 0x38: /*IDIV AX,w*/ tempws = (int)((DX << 16)|AX); diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index eca24046d..3447a2628 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -8,22 +8,25 @@ * * x86 CPU segment emulation. * - * Version: @(#)x86seg.c 1.0.6 2017/11/24 + * Version: @(#)x86seg.c 1.0.7 2018/04/29 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ -#include +#include #include +#include #include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "cpu.h" +#include "../device.h" #include "../machine/machine.h" #include "../mem.h" #include "../nvr.h" @@ -57,7 +60,27 @@ void pmodeint(int num, int soft); /*NOT PRESENT is INT 0B GPF is INT 0D*/ -FILE *pclogf; + +#ifdef ENABLE_X86SEG_LOG +int x86seg_do_log = ENABLE_X86SEG_LOG; +#endif + + +static void +x86seg_log(const char *fmt, ...) +{ +#ifdef ENABLE_X86SEG_LOG + va_list ap; + + if (x86seg_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + void x86abort(const char *format, ...) { va_list ap; @@ -377,8 +400,8 @@ void loadseg(uint16_t seg, x86seg *s) } else if (s!=&_cs) { - if (output) pclog("Seg data %04X %04X %04X %04X\n", segdat[0], segdat[1], segdat[2], segdat[3]); - if (output) pclog("Seg type %03X\n",segdat[2]&0x1F00); + x86seg_log("Seg data %04X %04X %04X %04X\n", segdat[0], segdat[1], segdat[2], segdat[3]); + x86seg_log("Seg type %03X\n",segdat[2]&0x1F00); switch ((segdat[2]>>8)&0x1F) { case 0x10: case 0x11: case 0x12: case 0x13: /*Data segments*/ @@ -466,7 +489,7 @@ void loadcs(uint16_t seg) { uint16_t segdat[4]; uint32_t addr; - if (output) pclog("Load CS %04X\n",seg); + x86seg_log("Load CS %04X\n",seg); if (msw&1 && !(eflags&VM_FLAG)) { if (!(seg&~3)) @@ -600,7 +623,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) segdat[1]=readmemw(0,addr+2); segdat[2]=readmemw(0,addr+4); segdat[3]=readmemw(0,addr+6); cpl_override=0; if (cpu_state.abrt) return; - if (output) pclog("%04X %04X %04X %04X\n",segdat[0],segdat[1],segdat[2],segdat[3]); + x86seg_log("%04X %04X %04X %04X\n",segdat[0],segdat[1],segdat[2],segdat[3]); if (segdat[2]&0x1000) /*Normal code segment*/ { if (!(segdat[2]&0x400)) /*Not conforming*/ @@ -863,7 +886,7 @@ void loadcscall(uint16_t seg) if (msw&1 && !(eflags&VM_FLAG)) { - if (csout) pclog("Protected mode CS load! %04X\n",seg); + if (csout) x86seg_log("Protected mode CS load! %04X\n",seg); if (!(seg&~3)) { x86gpf(NULL,0); @@ -897,7 +920,7 @@ void loadcscall(uint16_t seg) newpc=segdat[0]; if (type&0x800) newpc|=segdat[3]<<16; - if (csout) pclog("Code seg call - %04X - %04X %04X %04X\n",seg,segdat[0],segdat[1],segdat[2]); + if (csout) x86seg_log("Code seg call - %04X - %04X %04X %04X\n",seg,segdat[0],segdat[1],segdat[2]); if (segdat[2]&0x1000) { if (!(segdat[2]&0x400)) /*Not conforming*/ @@ -942,18 +965,18 @@ void loadcscall(uint16_t seg) CS=seg; do_seg_load(&_cs, segdat); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); - if (csout) pclog("Complete\n"); + if (csout) x86seg_log("Complete\n"); cycles -= timing_call_pm; } else { type=segdat[2]&0xF00; - if (csout) pclog("Type %03X\n",type); + if (csout) x86seg_log("Type %03X\n",type); switch (type) { case 0x400: /*Call gate*/ case 0xC00: /*386 Call gate*/ - if (output) pclog("Callgate %08X\n", cpu_state.pc); + x86seg_log("Callgate %08X\n", cpu_state.pc); cgate32=(type&0x800); cgate16=!cgate32; oldcs=CS; @@ -970,13 +993,13 @@ void loadcscall(uint16_t seg) } if (!(segdat[2]&0x8000)) { - if (output) pclog("Call gate not present %04X\n",seg); + x86seg_log("Call gate not present %04X\n",seg); x86np("Call gate not present\n", seg & 0xfffc); return; } seg2=segdat[1]; - if (output) pclog("New address : %04X:%08X\n", seg2, newpc); + x86seg_log("New address : %04X:%08X\n", seg2, newpc); if (!(seg2&~3)) { @@ -1008,7 +1031,7 @@ void loadcscall(uint16_t seg) segdat[2]=readmemw(0,addr+4); segdat[3]=readmemw(0,addr+6); cpl_override=0; if (cpu_state.abrt) return; - if (output) pclog("Code seg2 call - %04X - %04X %04X %04X\n",seg2,segdat[0],segdat[1],segdat[2]); + x86seg_log("Code seg2 call - %04X - %04X %04X %04X\n",seg2,segdat[0],segdat[1],segdat[2]); if (DPL > CPL) { @@ -1017,7 +1040,7 @@ void loadcscall(uint16_t seg) } if (!(segdat[2]&0x8000)) { - if (output) pclog("Call gate CS not present %04X\n",seg2); + x86seg_log("Call gate CS not present %04X\n",seg2); x86np("Call gate CS not present", seg2 & 0xfffc); return; } @@ -1047,7 +1070,7 @@ void loadcscall(uint16_t seg) } cpl_override=0; if (cpu_state.abrt) return; - if (output) pclog("New stack %04X:%08X\n",newss,newsp); + x86seg_log("New stack %04X:%08X\n",newss,newsp); if (!(newss&~3)) { x86ts(NULL,newss&~3); @@ -1075,12 +1098,12 @@ void loadcscall(uint16_t seg) addr+=gdt.base; } cpl_override=1; - if (output) pclog("Read stack seg\n"); + x86seg_log("Read stack seg\n"); segdat2[0]=readmemw(0,addr); segdat2[1]=readmemw(0,addr+2); segdat2[2]=readmemw(0,addr+4); segdat2[3]=readmemw(0,addr+6); cpl_override=0; if (cpu_state.abrt) return; - if (output) pclog("Read stack seg done!\n"); + x86seg_log("Read stack seg done!\n"); if (((newss & 3) != DPL) || (DPL2 != DPL)) { x86ts(NULL,newss&~3); @@ -1104,7 +1127,7 @@ void loadcscall(uint16_t seg) do_seg_load(&_ss, segdat2); - if (output) pclog("Set access 1\n"); + x86seg_log("Set access 1\n"); #ifdef SEL_ACCESSED cpl_override = 1; @@ -1118,7 +1141,7 @@ void loadcscall(uint16_t seg) set_use32(segdat[3]&0x40); cpu_state.pc=newpc; - if (output) pclog("Set access 2\n"); + x86seg_log("Set access 2\n"); #ifdef CS_ACCESSED cpl_override = 1; @@ -1126,7 +1149,7 @@ void loadcscall(uint16_t seg) cpl_override = 0; #endif - if (output) pclog("Type %04X\n",type); + x86seg_log("Type %04X\n",type); if (type==0xC00) { PUSHL(oldss); @@ -1154,9 +1177,9 @@ void loadcscall(uint16_t seg) } else { - if (output) pclog("Stack %04X\n",SP); + x86seg_log("Stack %04X\n",SP); PUSHW(oldss); - if (output) pclog("Write SS to %04X:%04X\n",SS,SP); + x86seg_log("Write SS to %04X:%04X\n",SS,SP); PUSHW(oldsp2); if (cpu_state.abrt) { @@ -1164,14 +1187,14 @@ void loadcscall(uint16_t seg) ESP = oldsp2; return; } - if (output) pclog("Write SP to %04X:%04X\n",SS,SP); + x86seg_log("Write SP to %04X:%04X\n",SS,SP); if (count) { while (count) { count--; tempw=readmemw(oldssbase,(oldsp&0xFFFF)+(count*2)); - if (output) pclog("PUSH %04X\n",tempw); + x86seg_log("PUSH %04X\n",tempw); PUSHW(tempw); if (cpu_state.abrt) { @@ -1245,7 +1268,7 @@ void pmoderetf(int is32, uint16_t off) uint32_t addr, oaddr; uint16_t segdat[4],segdat2[4],seg,newss; uint32_t oldsp=ESP; - if (output) pclog("RETF %i %04X:%04X %08X %04X\n",is32,CS,cpu_state.pc,cr0,eflags); + x86seg_log("RETF %i %04X:%04X %08X %04X\n",is32,CS,cpu_state.pc,cr0,eflags); if (is32) { newpc=POPL(); @@ -1253,12 +1276,12 @@ void pmoderetf(int is32, uint16_t off) } else { - if (output) pclog("PC read from %04X:%04X\n",SS,SP); + x86seg_log("PC read from %04X:%04X\n",SS,SP); newpc=POPW(); - if (output) pclog("CS read from %04X:%04X\n",SS,SP); + x86seg_log("CS read from %04X:%04X\n",SS,SP); seg=POPW(); if (cpu_state.abrt) return; } - if (output) pclog("Return to %04X:%08X\n",seg,newpc); + x86seg_log("Return to %04X:%08X\n",seg,newpc); if ((seg&3)= IDT.limit\n"); + x86seg_log("addr >= IDT.limit\n"); return; } addr+=idt.base; @@ -1536,10 +1559,10 @@ void pmodeint(int num, int soft) segdat[0]=readmemw(0,addr); segdat[1]=readmemw(2,addr); segdat[2]=readmemw(4,addr); - segdat[3]=readmemw(6,addr); cpl_override=0; if (cpu_state.abrt) { /* pclog("Abrt reading from %08X\n",addr); */ return; } + segdat[3]=readmemw(6,addr); cpl_override=0; if (cpu_state.abrt) { /* x86seg_log("Abrt reading from %08X\n",addr); */ return; } oaddr = addr; - if (output) pclog("Addr %08X seg %04X %04X %04X %04X\n",addr,segdat[0],segdat[1],segdat[2],segdat[3]); + x86seg_log("Addr %08X seg %04X %04X %04X %04X\n",addr,segdat[0],segdat[1],segdat[2],segdat[3]); if (!(segdat[2]&0x1F00)) { x86gpf(NULL,(num*8)+2); @@ -1682,7 +1705,7 @@ void pmodeint(int num, int soft) cpl_override = 0; #endif - if (output) pclog("New stack %04X:%08X\n",SS,ESP); + x86seg_log("New stack %04X:%08X\n",SS,ESP); cpl_override=1; if (type>=0x800) { @@ -1867,7 +1890,7 @@ void pmodeiret(int is32) addr=seg&~7; if (seg&4) { - pclog("TS LDT %04X %04X IRET\n",seg,gdt.limit); + x86seg_log("TS LDT %04X %04X IRET\n",seg,gdt.limit); x86ts(NULL,seg&~3); return; } @@ -2031,7 +2054,7 @@ void pmodeiret(int is32) else /*Return to outer level*/ { oaddr = addr; - if (output) pclog("Outer level\n"); + x86seg_log("Outer level\n"); if (is32) { newsp=POPL(); @@ -2043,7 +2066,7 @@ void pmodeiret(int is32) newss=POPW(); if (cpu_state.abrt) { ESP = oldsp; return; } } - if (output) pclog("IRET load stack %04X:%04X\n",newss,newsp); + x86seg_log("IRET load stack %04X:%04X\n",newss,newsp); if (!(newss&~3)) { diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index 08c0b44bc..d1fd0b464 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -1,25 +1,48 @@ /* - * 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. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * x87 FPU instructions core. * - * Version: @(#)x87_ops.h 1.0.1 2017/10/28 + * Version: @(#)x87_ops.h 1.0.5 2018/05/05 * - * Author: Sarah Walker, + * Authors: Fred N. van Kempen, + * Sarah Walker, * leilei, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 leilei. - * Copyright 2016,2017 Miran Grca. + * Copyright 2018 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 leilei. + * Copyright 2016-2018 Miran Grca. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #include #include +#ifdef _MSC_VER +# include +#endif #define fplog 0 @@ -80,6 +103,21 @@ static __inline void x87_push(double i) cpu_state.tag[cpu_state.TOP&7] = (i == 0.0) ? 1 : 0; } +static inline void x87_push_u64(uint64_t i) +{ + union + { + double d; + uint64_t ll; + } td; + + td.ll = i; + + cpu_state.TOP=(cpu_state.TOP-1)&7; + cpu_state.ST[cpu_state.TOP] = td.d; + cpu_state.tag[cpu_state.TOP&7] = (td.d == 0.0) ? 1 : 0; +} + static __inline double x87_pop() { double t = cpu_state.ST[cpu_state.TOP]; @@ -193,7 +231,7 @@ static __inline void x87_st80(double d) test.begin = (((int16_t)sign80)<<15)| (int16_t)exp80final; test.eind.ll = mant80final; - writememl(easeg,cpu_state.eaaddr,test.eind.ll); + writememl(easeg,cpu_state.eaaddr,test.eind.ll & 0xffffffff); writememl(easeg,cpu_state.eaaddr+4,test.eind.ll>>32); writememw(easeg,cpu_state.eaaddr+8,test.begin); } @@ -245,14 +283,14 @@ static __inline void x87_stmmx(MMX_REG r) static __inline uint16_t x87_compare(double a, double b) { #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _WIN32 - uint32_t out; + uint32_t result; if (!is386) { if (((a == INFINITY) || (a == -INFINITY)) && ((b == INFINITY) || (b == -INFINITY))) { /* pclog("Comparing infinity\n"); */ - +#ifndef _MSC_VER __asm volatile ("" : : : "memory"); __asm( @@ -261,14 +299,26 @@ static __inline uint16_t x87_compare(double a, double b) "fclex\n" "fcompp\n" "fnstsw %0\n" - : "=m" (out) + : "=m" (result) : "m" (a), "m" (a) ); +#else + _ReadWriteBarrier(); + __asm + { + fld a + fld a + fclex + fcompp + fnstsw result + } +#endif - return out & (C0|C2|C3); + return result & (C0|C2|C3); } } +#ifndef _MSC_VER /* Memory barrier, to force GCC to write to the input parameters * before the compare rather than after */ __asm volatile ("" : : : "memory"); @@ -279,11 +329,22 @@ static __inline uint16_t x87_compare(double a, double b) "fclex\n" "fcompp\n" "fnstsw %0\n" - : "=m" (out) + : "=m" (result) : "m" (a), "m" (b) ); +#else + _ReadWriteBarrier(); + _asm + { + fld b + fld a + fclex + fcompp + fnstsw result + } +#endif - return out & (C0|C2|C3); + return result & (C0|C2|C3); #else /* Generic C version is known to give incorrect results in some * situations, eg comparison of infinity (Unreal) */ @@ -293,32 +354,33 @@ static __inline uint16_t x87_compare(double a, double b) { if (((a == INFINITY) || (a == -INFINITY)) && ((b == INFINITY) || (b == -INFINITY))) { - out |= C3; - return out; + result |= C3; + return result; } if (a == b) - out |= C3; + result |= C3; else if (a < b) - out |= C0; + result |= C0; } else { if (a == b) - out |= C3; + result |= C3; else if (a < b) - out |= C0; + result |= C0; } - return out; + return result; #endif } static __inline uint16_t x87_ucompare(double a, double b) { #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _WIN32 - uint32_t out; + uint32_t result; +#ifndef _MSC_VER /* Memory barrier, to force GCC to write to the input parameters * before the compare rather than after */ __asm volatile ("" : : : "memory"); @@ -329,22 +391,33 @@ static __inline uint16_t x87_ucompare(double a, double b) "fclex\n" "fucompp\n" "fnstsw %0\n" - : "=m" (out) + : "=m" (result) : "m" (a), "m" (b) ); +#else + _ReadWriteBarrier(); + _asm + { + fld b + fld a + fclex + fcompp + fnstsw result + } +#endif - return out & (C0|C2|C3); + return result & (C0|C2|C3); #else /* Generic C version is known to give incorrect results in some * situations, eg comparison of infinity (Unreal) */ - uint32_t out = 0; + uint32_t result = 0; if (a == b) - out |= C3; + result |= C3; else if (a < b) - out |= C0; + result |= C0; - return out; + return result; #endif } @@ -420,14 +493,14 @@ static int FPU_ILLEGAL_a32(uint32_t fetchdat) #define ILLEGAL_a16 FPU_ILLEGAL_a16 #define ILLEGAL_a32 FPU_ILLEGAL_a32 -OpFn OP_TABLE(fpu_d8_a16)[32] = +const OpFn OP_TABLE(fpu_d8_a16)[32] = { opFADDs_a16, opFMULs_a16, opFCOMs_a16, opFCOMPs_a16, opFSUBs_a16, opFSUBRs_a16, opFDIVs_a16, opFDIVRs_a16, opFADDs_a16, opFMULs_a16, opFCOMs_a16, opFCOMPs_a16, opFSUBs_a16, opFSUBRs_a16, opFDIVs_a16, opFDIVRs_a16, opFADDs_a16, opFMULs_a16, opFCOMs_a16, opFCOMPs_a16, opFSUBs_a16, opFSUBRs_a16, opFDIVs_a16, opFDIVRs_a16, opFADD, opFMUL, opFCOM, opFCOMP, opFSUB, opFSUBR, opFDIV, opFDIVR }; -OpFn OP_TABLE(fpu_d8_a32)[32] = +const OpFn OP_TABLE(fpu_d8_a32)[32] = { opFADDs_a32, opFMULs_a32, opFCOMs_a32, opFCOMPs_a32, opFSUBs_a32, opFSUBRs_a32, opFDIVs_a32, opFDIVRs_a32, opFADDs_a32, opFMULs_a32, opFCOMs_a32, opFCOMPs_a32, opFSUBs_a32, opFSUBRs_a32, opFDIVs_a32, opFDIVRs_a32, @@ -435,7 +508,7 @@ OpFn OP_TABLE(fpu_d8_a32)[32] = opFADD, opFMUL, opFCOM, opFCOMP, opFSUB, opFSUBR, opFDIV, opFDIVR }; -OpFn OP_TABLE(fpu_287_d9_a16)[256] = +const OpFn OP_TABLE(fpu_287_d9_a16)[256] = { opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, @@ -474,7 +547,7 @@ OpFn OP_TABLE(fpu_287_d9_a16)[256] = opFPREM, opFYL2XP1, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS }; -OpFn OP_TABLE(fpu_287_d9_a32)[256] = +const OpFn OP_TABLE(fpu_287_d9_a32)[256] = { opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, @@ -513,7 +586,7 @@ OpFn OP_TABLE(fpu_287_d9_a32)[256] = opFPREM, opFYL2XP1, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS }; -OpFn OP_TABLE(fpu_d9_a16)[256] = +const OpFn OP_TABLE(fpu_d9_a16)[256] = { opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, @@ -552,7 +625,7 @@ OpFn OP_TABLE(fpu_d9_a16)[256] = opFPREM, opFYL2XP1, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS }; -OpFn OP_TABLE(fpu_d9_a32)[256] = +const OpFn OP_TABLE(fpu_d9_a32)[256] = { opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, @@ -591,7 +664,7 @@ OpFn OP_TABLE(fpu_d9_a32)[256] = opFPREM, opFYL2XP1, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS }; -OpFn OP_TABLE(fpu_287_da_a16)[256] = +const OpFn OP_TABLE(fpu_287_da_a16)[256] = { opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, @@ -629,7 +702,7 @@ OpFn OP_TABLE(fpu_287_da_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, }; -OpFn OP_TABLE(fpu_287_da_a32)[256] = +const OpFn OP_TABLE(fpu_287_da_a32)[256] = { opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, @@ -668,7 +741,7 @@ OpFn OP_TABLE(fpu_287_da_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; -OpFn OP_TABLE(fpu_da_a16)[256] = +const OpFn OP_TABLE(fpu_da_a16)[256] = { opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, @@ -706,7 +779,7 @@ OpFn OP_TABLE(fpu_da_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, }; -OpFn OP_TABLE(fpu_da_a32)[256] = +const OpFn OP_TABLE(fpu_da_a32)[256] = { opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, @@ -745,7 +818,7 @@ OpFn OP_TABLE(fpu_da_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; -OpFn OP_TABLE(fpu_686_da_a16)[256] = +const OpFn OP_TABLE(fpu_686_da_a16)[256] = { opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, @@ -783,7 +856,7 @@ OpFn OP_TABLE(fpu_686_da_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, }; -OpFn OP_TABLE(fpu_686_da_a32)[256] = +const OpFn OP_TABLE(fpu_686_da_a32)[256] = { opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, @@ -822,7 +895,7 @@ OpFn OP_TABLE(fpu_686_da_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; -OpFn OP_TABLE(fpu_287_db_a16)[256] = +const OpFn OP_TABLE(fpu_287_db_a16)[256] = { opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, @@ -860,7 +933,7 @@ OpFn OP_TABLE(fpu_287_db_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, }; -OpFn OP_TABLE(fpu_287_db_a32)[256] = +const OpFn OP_TABLE(fpu_287_db_a32)[256] = { opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, @@ -899,7 +972,7 @@ OpFn OP_TABLE(fpu_287_db_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; -OpFn OP_TABLE(fpu_db_a16)[256] = +const OpFn OP_TABLE(fpu_db_a16)[256] = { opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, @@ -937,7 +1010,7 @@ OpFn OP_TABLE(fpu_db_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, }; -OpFn OP_TABLE(fpu_db_a32)[256] = +const OpFn OP_TABLE(fpu_db_a32)[256] = { opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, @@ -976,7 +1049,7 @@ OpFn OP_TABLE(fpu_db_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; -OpFn OP_TABLE(fpu_686_db_a16)[256] = +const OpFn OP_TABLE(fpu_686_db_a16)[256] = { opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, @@ -1014,7 +1087,7 @@ OpFn OP_TABLE(fpu_686_db_a16)[256] = opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, }; -OpFn OP_TABLE(fpu_686_db_a32)[256] = +const OpFn OP_TABLE(fpu_686_db_a32)[256] = { opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, @@ -1053,14 +1126,14 @@ OpFn OP_TABLE(fpu_686_db_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; -OpFn OP_TABLE(fpu_287_dc_a16)[32] = +const OpFn OP_TABLE(fpu_287_dc_a16)[32] = { opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, opFADDr, opFMULr, ILLEGAL_a16, ILLEGAL_a16, opFSUBRr, opFSUBr, opFDIVRr, opFDIVr }; -OpFn OP_TABLE(fpu_287_dc_a32)[32] = +const OpFn OP_TABLE(fpu_287_dc_a32)[32] = { opFADDd_a32, opFMULd_a32, opFCOMd_a32, opFCOMPd_a32, opFSUBd_a32, opFSUBRd_a32, opFDIVd_a32, opFDIVRd_a32, opFADDd_a32, opFMULd_a32, opFCOMd_a32, opFCOMPd_a32, opFSUBd_a32, opFSUBRd_a32, opFDIVd_a32, opFDIVRd_a32, @@ -1068,14 +1141,14 @@ OpFn OP_TABLE(fpu_287_dc_a32)[32] = opFADDr, opFMULr, ILLEGAL_a32, ILLEGAL_a32, opFSUBRr, opFSUBr, opFDIVRr, opFDIVr }; -OpFn OP_TABLE(fpu_dc_a16)[32] = +const OpFn OP_TABLE(fpu_dc_a16)[32] = { opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, opFADDr, opFMULr, opFCOM, opFCOMP, opFSUBRr, opFSUBr, opFDIVRr, opFDIVr }; -OpFn OP_TABLE(fpu_dc_a32)[32] = +const OpFn OP_TABLE(fpu_dc_a32)[32] = { opFADDd_a32, opFMULd_a32, opFCOMd_a32, opFCOMPd_a32, opFSUBd_a32, opFSUBRd_a32, opFDIVd_a32, opFDIVRd_a32, opFADDd_a32, opFMULd_a32, opFCOMd_a32, opFCOMPd_a32, opFSUBd_a32, opFSUBRd_a32, opFDIVd_a32, opFDIVRd_a32, @@ -1083,7 +1156,7 @@ OpFn OP_TABLE(fpu_dc_a32)[32] = opFADDr, opFMULr, opFCOM, opFCOMP, opFSUBRr, opFSUBr, opFDIVRr, opFDIVr }; -OpFn OP_TABLE(fpu_287_dd_a16)[256] = +const OpFn OP_TABLE(fpu_287_dd_a16)[256] = { opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, @@ -1121,7 +1194,7 @@ OpFn OP_TABLE(fpu_287_dd_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, }; -OpFn OP_TABLE(fpu_287_dd_a32)[256] = +const OpFn OP_TABLE(fpu_287_dd_a32)[256] = { opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, @@ -1160,7 +1233,7 @@ OpFn OP_TABLE(fpu_287_dd_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; -OpFn OP_TABLE(fpu_dd_a16)[256] = +const OpFn OP_TABLE(fpu_dd_a16)[256] = { opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, @@ -1198,7 +1271,7 @@ OpFn OP_TABLE(fpu_dd_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, }; -OpFn OP_TABLE(fpu_dd_a32)[256] = +const OpFn OP_TABLE(fpu_dd_a32)[256] = { opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, @@ -1237,7 +1310,7 @@ OpFn OP_TABLE(fpu_dd_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; -OpFn OP_TABLE(fpu_287_de_a16)[256] = +const OpFn OP_TABLE(fpu_287_de_a16)[256] = { opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, @@ -1276,7 +1349,7 @@ OpFn OP_TABLE(fpu_287_de_a16)[256] = opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, }; -OpFn OP_TABLE(fpu_287_de_a32)[256] = +const OpFn OP_TABLE(fpu_287_de_a32)[256] = { opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, @@ -1315,7 +1388,7 @@ OpFn OP_TABLE(fpu_287_de_a32)[256] = opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, }; -OpFn OP_TABLE(fpu_de_a16)[256] = +const OpFn OP_TABLE(fpu_de_a16)[256] = { opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, @@ -1354,7 +1427,7 @@ OpFn OP_TABLE(fpu_de_a16)[256] = opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, }; -OpFn OP_TABLE(fpu_de_a32)[256] = +const OpFn OP_TABLE(fpu_de_a32)[256] = { opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, @@ -1393,7 +1466,7 @@ OpFn OP_TABLE(fpu_de_a32)[256] = opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, }; -OpFn OP_TABLE(fpu_287_df_a16)[256] = +const OpFn OP_TABLE(fpu_287_df_a16)[256] = { opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, @@ -1431,7 +1504,7 @@ OpFn OP_TABLE(fpu_287_df_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, }; -OpFn OP_TABLE(fpu_287_df_a32)[256] = +const OpFn OP_TABLE(fpu_287_df_a32)[256] = { opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, @@ -1470,7 +1543,7 @@ OpFn OP_TABLE(fpu_287_df_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; -OpFn OP_TABLE(fpu_df_a16)[256] = +const OpFn OP_TABLE(fpu_df_a16)[256] = { opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, @@ -1508,7 +1581,7 @@ OpFn OP_TABLE(fpu_df_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, }; -OpFn OP_TABLE(fpu_df_a32)[256] = +const OpFn OP_TABLE(fpu_df_a32)[256] = { opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, @@ -1547,7 +1620,7 @@ OpFn OP_TABLE(fpu_df_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; -OpFn OP_TABLE(fpu_686_df_a16)[256] = +const OpFn OP_TABLE(fpu_686_df_a16)[256] = { opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, @@ -1585,7 +1658,7 @@ OpFn OP_TABLE(fpu_686_df_a16)[256] = opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, }; -OpFn OP_TABLE(fpu_686_df_a32)[256] = +const OpFn OP_TABLE(fpu_686_df_a32)[256] = { opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, @@ -1624,7 +1697,7 @@ OpFn OP_TABLE(fpu_686_df_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; -OpFn OP_TABLE(nofpu_a16)[256] = +const OpFn OP_TABLE(nofpu_a16)[256] = { op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, @@ -1662,7 +1735,7 @@ OpFn OP_TABLE(nofpu_a16)[256] = op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, }; -OpFn OP_TABLE(nofpu_a32)[256] = +const OpFn OP_TABLE(nofpu_a32)[256] = { op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, diff --git a/src/cpu/x87_ops_misc.h b/src/cpu/x87_ops_misc.h index fd1cc3de6..bf4eb3c7f 100644 --- a/src/cpu/x87_ops_misc.h +++ b/src/cpu/x87_ops_misc.h @@ -478,7 +478,7 @@ static int opFLDLN2(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; if (fplog) pclog("FLDLN2\n"); - x87_push(0.693147180559945); + x87_push_u64(0x3fe62e42fefa39f0ull); CLOCK_CYCLES(8); return 0; } diff --git a/src/device.c b/src/device.c index 98f665a5e..2d1cd5df9 100644 --- a/src/device.c +++ b/src/device.c @@ -9,7 +9,7 @@ * Implementation of the generic device interface to handle * all devices attached to the emulator. * - * Version: @(#)device.c 1.0.5 2018/03/18 + * Version: @(#)device.c 1.0.8 2018/04/29 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -37,10 +37,12 @@ * Boston, MA 02111-1307 * USA. */ +#include #include #include #include #include +#define HAVE_STDARG_H #include "86box.h" #include "cpu/cpu.h" #include "config.h" @@ -57,6 +59,26 @@ static device_t *devices[DEVICE_MAX]; static device_t *device_current; +#ifdef ENABLE_DEVICE_LOG +int device_do_log = ENABLE_DEVICE_LOG; +#endif + + +static void +device_log(const char *format, ...) +{ +#ifdef ENABLE_DEVICE_LOG + va_list ap; + + if (device_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + void device_init(void) { @@ -72,7 +94,7 @@ device_add(const device_t *d) for (c=0; c<256; c++) { if (devices[c] == (device_t *)d) { - pclog("DEVICE: device already exists!\n"); + device_log("DEVICE: device already exists!\n"); return(NULL); } if (devices[c] == NULL) break; @@ -82,18 +104,22 @@ device_add(const device_t *d) device_current = (device_t *)d; + devices[c] = (device_t *)d; + if (d->init != NULL) { priv = d->init(d); if (priv == NULL) { if (d->name) - pclog("DEVICE: device '%s' init failed\n", d->name); - else - pclog("DEVICE: device init failed\n"); + device_log("DEVICE: device '%s' init failed\n", d->name); + else + device_log("DEVICE: device init failed\n"); + + device_priv[c] = NULL; + return(NULL); } } - devices[c] = (device_t *)d; device_priv[c] = priv; return(priv); @@ -152,6 +178,21 @@ device_reset_all(void) } +/* Reset all attached PCI devices - needed for PCI turbo reset control. */ +void +device_reset_all_pci(void) +{ + int c; + + for (c=0; creset != NULL) && (devices[c]->flags & DEVICE_PCI)) + devices[c]->reset(device_priv[c]); + } + } +} + + void * device_get_priv(const device_t *d) { @@ -211,20 +252,6 @@ device_force_redraw(void) } -void -device_add_status_info(char *s, int max_len) -{ - int c; - - for (c=0; cadd_status_info != NULL) - devices[c]->add_status_info(s, max_len, device_priv[c]); - } - } -} - - char * device_get_config_string(char *s) { diff --git a/src/device.h b/src/device.h index 32f803aff..6256a3ea5 100644 --- a/src/device.h +++ b/src/device.h @@ -8,7 +8,7 @@ * * Definitions for the device handler. * - * Version: @(#)device.h 1.0.3 2018/03/15 + * Version: @(#)device.h 1.0.5 2018/04/26 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -104,7 +104,6 @@ typedef struct _device_ { int (*available)(/*void*/); void (*speed_changed)(void *p); void (*force_redraw)(void *p); - void (*add_status_info)(char *s, int max_len, void *p); const device_config_t *config; } device_t; @@ -119,11 +118,11 @@ extern void *device_add(const device_t *d); extern void device_add_ex(const device_t *d, void *priv); extern void device_close_all(void); extern void device_reset_all(void); +extern void device_reset_all_pci(void); extern void *device_get_priv(const device_t *d); extern int device_available(const device_t *d); extern void device_speed_changed(void); extern void device_force_redraw(void); -extern void device_add_status_info(char *s, int max_len); extern int device_get_config_int(char *name); extern int device_get_config_int_ex(char *s, int default_int); diff --git a/src/disk/hdc.c b/src/disk/hdc.c index f2cb9b2b3..37d036e99 100644 --- a/src/disk/hdc.c +++ b/src/disk/hdc.c @@ -8,7 +8,7 @@ * * Common code to handle all sorts of disk controllers. * - * Version: @(#)hdc.c 1.0.12 2018/03/19 + * Version: @(#)hdc.c 1.0.15 2018/04/29 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -16,21 +16,44 @@ * Copyright 2016-2018 Miran Grca. * Copyright 2017,2018 Fred N. van Kempen. */ -#include +#include #include +#include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../machine/machine.h" #include "../device.h" #include "hdc.h" #include "hdc_ide.h" +#include "hdd.h" char *hdc_name; /* configured HDC name */ int hdc_current; +#ifdef ENABLE_HDC_LOG +int hdc_do_log = ENABLE_HDC_LOG; +#endif + + +static void +hdc_log(const char *fmt, ...) +{ +#ifdef ENABLE_HDC_LOG + va_list ap; + + if (hdc_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + static void * null_init(const device_t *info) { @@ -47,7 +70,7 @@ null_close(void *priv) static const device_t null_device = { "Null HDC", 0, 0, null_init, null_close, NULL, - NULL, NULL, NULL, NULL, NULL + NULL, NULL, NULL, NULL }; @@ -67,7 +90,7 @@ inthdc_close(void *priv) static const device_t inthdc_device = { "Internal Controller", 0, 0, inthdc_init, inthdc_close, NULL, - NULL, NULL, NULL, NULL, NULL + NULL, NULL, NULL, NULL }; @@ -106,6 +129,9 @@ static const struct { { "[ISA] [IDE] PS/2 AT XTIDE (1.1.5)", "xtide_at_ps2", &xtide_at_ps2_device }, + { "[ISA] [IDE] WDXT-150 IDE (XTA) Adapter", "xta_wdxt150", + &xta_wdxt150_device }, + { "[ISA] [XT IDE] Acculogic XT IDE", "xtide_acculogic", &xtide_acculogic_device }, @@ -138,7 +164,7 @@ hdc_init(char *name) { int c; - pclog("HDC: initializing..\n"); + hdc_log("HDC: initializing..\n"); for (c = 0; controllers[c].device; c++) { if (! strcmp(name, (char *) controllers[c].internal_name)) { @@ -146,6 +172,9 @@ hdc_init(char *name) break; } } + + /* Zero all the hard disk image arrays. */ + hdd_image_init(); } @@ -153,21 +182,18 @@ hdc_init(char *name) void hdc_reset(void) { - pclog("HDC: reset(current=%d, internal=%d)\n", - hdc_current, (machines[machine].flags & MACHINE_HDC)?1:0); + hdc_log("HDC: reset(current=%d, internal=%d)\n", + hdc_current, (machines[machine].flags & MACHINE_HDC) ? 1 : 0); /* If we have a valid controller, add its device. */ if (hdc_current > 1) device_add(controllers[hdc_current].device); - /* Reconfire and reset the IDE layer. */ - ide_ter_disable(); - ide_qua_disable(); - if (ide_enable[2]) - ide_ter_init(); - if (ide_enable[3]) - ide_qua_init(); - ide_reset_hard(); + /* Now, add the tertiary and/or quaternary IDE controllers. */ + if (ide_ter_enabled) + device_add(&ide_ter_device); + if (ide_qua_enabled) + device_add(&ide_qua_device); } @@ -185,6 +211,22 @@ hdc_get_internal_name(int hdc) } +int +hdc_get_from_internal_name(char *s) +{ + int c = 0; + + while (strlen((char *) controllers[c].internal_name)) + { + if (!strcmp((char *) controllers[c].internal_name, s)) + return c; + c++; + } + + return 0; +} + + const device_t * hdc_get_device(int hdc) { @@ -192,6 +234,19 @@ hdc_get_device(int hdc) } +int +hdc_has_config(int hdc) +{ + const device_t *dev = hdc_get_device(hdc); + + if (dev == NULL) return(0); + + if (dev->config == NULL) return(0); + + return(1); +} + + int hdc_get_flags(int hdc) { diff --git a/src/disk/hdc.h b/src/disk/hdc.h index 8dd1ac8a5..89e34a1d9 100644 --- a/src/disk/hdc.h +++ b/src/disk/hdc.h @@ -8,7 +8,7 @@ * * Definitions for the common disk controller handler. * - * Version: @(#)hdc.h 1.0.7 2018/03/19 + * Version: @(#)hdc.h 1.0.8 2018/04/05 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -22,7 +22,7 @@ #define MFM_NUM 2 /* 2 drives per controller supported */ #define ESDI_NUM 2 /* 2 drives per controller supported */ -#define XTIDE_NUM 2 /* 2 drives per controller supported */ +#define XTA_NUM 2 /* 2 drives per controller supported */ #define IDE_NUM 8 #define SCSI_NUM 16 /* theoretically the controller can have at * least 7 devices, with each device being @@ -47,6 +47,12 @@ extern const device_t ide_vlb_2ch_device; /* vlb_ide_2ch */ extern const device_t ide_pci_device; /* pci_ide */ extern const device_t ide_pci_2ch_device; /* pci_ide_2ch */ +extern const device_t ide_ter_device; +extern const device_t ide_qua_device; + +extern const device_t xta_wdxt150_device; /* xta_wdxt150 */ +extern const device_t xta_hd20_device; /* EuroPC internal */ + extern const device_t xtide_device; /* xtide_xt */ extern const device_t xtide_at_device; /* xtide_at */ extern const device_t xtide_acculogic_device; /* xtide_ps2 */ @@ -58,6 +64,8 @@ extern void hdc_reset(void); extern char *hdc_get_name(int hdc); extern char *hdc_get_internal_name(int hdc); +extern int hdc_get_from_internal_name(char *s); +extern int hdc_has_config(int hdc); extern const device_t *hdc_get_device(int hdc); extern int hdc_get_flags(int hdc); extern int hdc_available(int hdc); diff --git a/src/disk/hdc_esdi_at.c b/src/disk/hdc_esdi_at.c index fe8dd1870..1a4539388 100644 --- a/src/disk/hdc_esdi_at.c +++ b/src/disk/hdc_esdi_at.c @@ -8,7 +8,7 @@ * * Driver for the ESDI controller (WD1007-vse1) for PC/AT. * - * Version: @(#)hdc_esdi_at.c 1.0.9 2018/03/18 + * Version: @(#)hdc_esdi_at.c 1.0.13 2018/05/02 * * Authors: Sarah Walker, * Miran Grca, @@ -21,11 +21,13 @@ #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE #define _GNU_SOURCE -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../device.h" #include "../io.h" @@ -104,33 +106,43 @@ typedef struct { } esdi_t; -static __inline void irq_raise(esdi_t *esdi) -{ - /* If not already pending.. */ - if (! esdi->irqstat) { - /* If enabled in the control register.. */ - if (! (esdi->fdisk & 0x02)) { - /* .. raise IRQ14. */ - picint(1<<14); - } +#ifdef ENABLE_ESDI_AT_LOG +int esdi_at_do_log = ENABLE_ESDI_AT_LOG; +#endif - /* Remember this. */ - esdi->irqstat = 1; + +static void +esdi_at_log(const char *fmt, ...) +{ +#ifdef ENABLE_ESDI_AT_LOG + va_list ap; + + if (esdi_at_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } +#endif } -static __inline void irq_lower(esdi_t *esdi) +static inline void +irq_raise(esdi_t *esdi) { - /* If raised.. */ - if (esdi->irqstat) { - /* If enabled in the control register.. */ - if (! (esdi->fdisk & 0x02)) { - /* .. drop IRQ14. */ - picintc(1<<14); - } + if (!(esdi->fdisk & 2)) + picint(1 << 14); + + esdi->irqstat = 1; +} + + +static inline void +irq_lower(esdi_t *esdi) +{ + if (esdi->irqstat) { + if (!(esdi->fdisk & 2)) + picintc(1 << 14); - /* Remember this. */ esdi->irqstat = 0; } } @@ -146,12 +158,12 @@ get_sector(esdi_t *esdi, off64_t *addr) int c, h, s; if (esdi->head > heads) { - pclog("esdi_get_sector: past end of configured heads\n"); + esdi_at_log("esdi_get_sector: past end of configured heads\n"); return(1); } if (esdi->sector >= sectors+1) { - pclog("esdi_get_sector: past end of configured sectors\n"); + esdi_at_log("esdi_get_sector: past end of configured sectors\n"); return(1); } @@ -209,7 +221,8 @@ esdi_writew(uint16_t port, uint16_t val, void *priv) esdi->pos = 0; esdi->status = STAT_BUSY; timer_clock(); - esdi->callback = 6LL*HDC_TIME; + /* 390.625 us per sector at 10 Mbit/s = 1280 kB/s. */ + esdi->callback = (3125LL * TIMER_USEC) / 8LL; timer_update_outstanding(); } } @@ -220,9 +233,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) { esdi_t *esdi = (esdi_t *)priv; -#ifdef ENABLE_HDD_LOG - pclog("WD1007 write(%04x, %02x)\n", port, val); -#endif + esdi_at_log("WD1007 write(%04x, %02x)\n", port, val); switch (port) { case 0x1f0: /* data */ @@ -264,9 +275,8 @@ esdi_write(uint16_t port, uint8_t val, void *priv) esdi->command = val; esdi->error = 0; -#ifdef ENABLE_HDD_LOG - pclog("WD1007: command %02x\n", val & 0xf0); -#endif + esdi_at_log("WD1007: command %02x\n", val & 0xf0); + switch (val & 0xf0) { case CMD_RESTORE: esdi->command &= ~0x0f; /*mask off step rate*/ @@ -356,7 +366,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) break; default: - pclog("WD1007: bad command %02X\n", val); + esdi_at_log("WD1007: bad command %02X\n", val); case 0xe8: /*???*/ esdi->status = STAT_BUSY; timer_clock(); @@ -384,6 +394,9 @@ esdi_write(uint16_t port, uint8_t val, void *priv) esdi->status = STAT_BUSY; } esdi->fdisk = val; + /* Lower IRQ on IRQ disable. */ + if ((val & 2) && !(esdi->fdisk & 0x02)) + picintc(1 << 14); break; } } @@ -407,7 +420,8 @@ esdi_readw(uint16_t port, void *priv) next_sector(esdi); esdi->status = STAT_BUSY; timer_clock(); - esdi->callback = 6LL*HDC_TIME; + /* 390.625 us per sector at 10 Mbit/s = 1280 kB/s. */ + esdi->callback = (3125LL * TIMER_USEC) / 8LL; timer_update_outstanding(); } else { ui_sb_update_icon(SB_HDD|HDD_BUS_ESDI, 0); @@ -460,9 +474,7 @@ esdi_read(uint16_t port, void *priv) break; } -#ifdef ENABLE_HDD_LOG - pclog("WD1007 read(%04x) = %02x\n", port, temp); -#endif + esdi_at_log("WD1007 read(%04x) = %02x\n", port, temp); return(temp); } @@ -490,9 +502,7 @@ esdi_callback(void *priv) return; } -#ifdef ENABLE_HDD_LOG - pclog("WD1007: command %02x\n", esdi->command); -#endif + esdi_at_log("WD1007: command %02x\n", esdi->command); switch (esdi->command) { case CMD_RESTORE: @@ -638,9 +648,9 @@ esdi_callback(void *priv) drive->cfg_spt = esdi->secount; drive->cfg_hpc = esdi->head+1; -#ifdef ENABLE_HDD_LOG - pclog("WD1007: parameters: spt=%i hpc=%i\n", drive->cfg_spt,drive->cfg_hpc); -#endif + + esdi_at_log("WD1007: parameters: spt=%i hpc=%i\n", drive->cfg_spt,drive->cfg_hpc); + if (! esdi->secount) fatal("WD1007: secount=0\n"); esdi->status = STAT_READY|STAT_DSC; @@ -679,7 +689,7 @@ esdi_callback(void *priv) break; default: - pclog("WD1007: bad read config %02x\n", + esdi_at_log("WD1007: bad read config %02x\n", esdi->cylinder >> 8); } esdi->status = STAT_READY|STAT_DSC; @@ -736,7 +746,7 @@ esdi_callback(void *priv) break; default: - pclog("WD1007: callback on unknown command %02x\n", esdi->command); + esdi_at_log("WD1007: callback on unknown command %02x\n", esdi->command); /*FALLTHROUGH*/ case 0xe8: @@ -756,7 +766,7 @@ loadhd(esdi_t *esdi, int hdd_num, int d, const wchar_t *fn) drive_t *drive = &esdi->drives[hdd_num]; if (! hdd_image_load(d)) { - pclog("WD1007: drive %d not present!\n", d); + esdi_at_log("WD1007: drive %d not present!\n", d); drive->present = 0; return; } @@ -841,6 +851,6 @@ const device_t esdi_at_wd1007vse1_device = { 0, wd1007vse1_init, wd1007vse1_close, NULL, wd1007vse1_available, - NULL, NULL, NULL, + NULL, NULL, NULL }; diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index b7dbeb515..f92301415 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -52,7 +52,7 @@ * however, are auto-configured by the system software as * shown above. * - * Version: @(#)hdc_esdi_mca.c 1.0.9 2018/03/18 + * Version: @(#)hdc_esdi_mca.c 1.0.13 2018/04/29 * * Authors: Sarah Walker, * Fred N. van Kempen, @@ -60,11 +60,13 @@ * Copyright 2008-2018 Sarah Walker. * Copyright 2017,2018 Fred N. van Kempen. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../device.h" #include "../dma.h" @@ -101,8 +103,6 @@ typedef struct esdi_drive { } drive_t; typedef struct esdi { - uint16_t base; - int8_t irq; int8_t dma; uint32_t bios; @@ -190,21 +190,42 @@ typedef struct esdi { #define CMD_GET_POS_INFO 0x0a #define STATUS_LEN(x) ((x) << 8) +#define STATUS_DEVICE(x) ((x) << 5) #define STATUS_DEVICE_HOST_ADAPTER (7 << 5) +#ifdef ENABLE_ESDI_MCA_LOG +int esdi_mca_do_log = ENABLE_ESDI_MCA_LOG; +#endif + + +static void +esdi_mca_log(const char *fmt, ...) +{ +#ifdef ENABLE_ESDI_MCA_LOG + va_list ap; + + if (esdi_mca_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + static __inline void set_irq(esdi_t *dev) { if (dev->basic_ctrl & CTRL_IRQ_ENA) - picint(1 << dev->irq); + picint(1 << 14); } static __inline void clear_irq(esdi_t *dev) { - picintc(1 << dev->irq); + picintc(1 << 14); } @@ -250,23 +271,42 @@ device_not_present(esdi_t *dev) set_irq(dev); } -static void rba_out_of_range(esdi_t *dev) -{ - dev->status_len = 9; - dev->status_data[0] = dev->command | STATUS_LEN(9) | dev->cmd_dev; - dev->status_data[1] = 0x0e01; /*Command block error, invalid parameter*/ - dev->status_data[2] = 0x0007; /*RBA out of range*/ - dev->status_data[3] = 0; - dev->status_data[4] = 0; - dev->status_data[5] = 0; - dev->status_data[6] = 0; - dev->status_data[7] = 0; - dev->status_data[8] = 0; - dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; - dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_FAILURE; - dev->irq_in_progress = 1; - set_irq(dev); +static void +rba_out_of_range(esdi_t *dev) +{ + dev->status_len = 9; + dev->status_data[0] = dev->command | STATUS_LEN(9) | dev->cmd_dev; + dev->status_data[1] = 0x0e01; /*Command block error, invalid parameter*/ + dev->status_data[2] = 0x0007; /*RBA out of range*/ + dev->status_data[3] = 0; + dev->status_data[4] = 0; + dev->status_data[5] = 0; + dev->status_data[6] = 0; + dev->status_data[7] = 0; + dev->status_data[8] = 0; + + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; + dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_FAILURE; + dev->irq_in_progress = 1; + set_irq(dev); +} + + +static void +complete_command_status(esdi_t *dev) +{ + dev->status_len = 7; + if (dev->cmd_dev == ATTN_DEVICE_0) + dev->status_data[0] = CMD_READ | STATUS_LEN(7) | STATUS_DEVICE(0); + else + dev->status_data[0] = CMD_READ | STATUS_LEN(7) | STATUS_DEVICE(1); + dev->status_data[1] = 0x0000; /*Error bits*/ + dev->status_data[2] = 0x1900; /*Device status*/ + dev->status_data[3] = 0; /*Number of blocks left to do*/ + dev->status_data[4] = (dev->rba-1) & 0xffff; /*Last RBA processed*/ + dev->status_data[5] = (dev->rba-1) >> 8; + dev->status_data[6] = 0; /*Number of blocks requiring error recovery*/ } #define ESDI_ADAPTER_ONLY() do \ @@ -377,7 +417,8 @@ esdi_callback(void *priv) break; case 2: - dev->status = STATUS_IRQ; + complete_command_status(dev); + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; dev->irq_in_progress = 1; set_irq(dev); @@ -438,11 +479,11 @@ esdi_callback(void *priv) hdd_image_write(drive->hdd_num, dev->rba, 1, (uint8_t *)dev->data); dev->rba++; dev->sector_pos++; - ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1); + ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, + dev->cmd_dev == ATTN_DEVICE_0 ? 0 : 1); dev->data_pos = 0; } - ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); dev->status = STATUS_CMD_IN_PROGRESS; dev->cmd_state = 2; @@ -450,7 +491,8 @@ esdi_callback(void *priv) break; case 2: - dev->status = STATUS_IRQ; + complete_command_status(dev); + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; dev->irq_in_progress = 1; set_irq(dev); @@ -471,7 +513,9 @@ esdi_callback(void *priv) return; } - dev->status = STATUS_IRQ; + dev->rba += dev->sector_count; + complete_command_status(dev); + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; dev->irq_in_progress = 1; set_irq(dev); @@ -485,7 +529,8 @@ esdi_callback(void *priv) return; } - dev->status = STATUS_IRQ; + complete_command_status(dev); + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; dev->irq_in_progress = 1; set_irq(dev); @@ -499,8 +544,6 @@ esdi_callback(void *priv) return; } - if (dev->status_pos) - fatal("Status send in progress\n"); if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); @@ -529,8 +572,6 @@ esdi_callback(void *priv) return; } - if (dev->status_pos) - fatal("Status send in progress\n"); if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); @@ -542,13 +583,12 @@ esdi_callback(void *priv) dev->status_data[4] = drive->tracks; dev->status_data[5] = drive->hpc | (drive->spt << 16); -#if 0 - pclog("CMD_GET_DEV_CONFIG %i %04x %04x %04x %04x %04x %04x\n", + esdi_mca_log("CMD_GET_DEV_CONFIG %i %04x %04x %04x %04x %04x %04x\n", drive->sectors, dev->status_data[0], dev->status_data[1], dev->status_data[2], dev->status_data[3], dev->status_data[4], dev->status_data[5]); -#endif + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; dev->irq_in_progress = 1; @@ -557,8 +597,7 @@ esdi_callback(void *priv) case CMD_GET_POS_INFO: ESDI_ADAPTER_ONLY(); - if (dev->status_pos) - fatal("Status send in progress\n"); + if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); @@ -567,8 +606,8 @@ esdi_callback(void *priv) dev->status_data[1] = 0xffdd; /*MCA ID*/ dev->status_data[2] = dev->pos_regs[3] | (dev->pos_regs[2] << 8); - dev->status_data[3] = 0xffff; - dev->status_data[4] = 0xffff; + dev->status_data[3] = 0xff; + dev->status_data[4] = 0xff; dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; dev->irq_status = IRQ_HOST_ADAPTER | IRQ_CMD_COMPLETE_SUCCESS; @@ -688,8 +727,6 @@ esdi_callback(void *priv) case 0x12: ESDI_ADAPTER_ONLY(); - if (dev->status_pos) - fatal("Status send in progress\n"); if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); @@ -715,7 +752,7 @@ esdi_read(uint16_t port, void *priv) esdi_t *dev = (esdi_t *)priv; uint8_t ret = 0xff; - switch (port-dev->base) { + switch (port & 7) { case 2: /*Basic status register*/ ret = dev->status; break; @@ -738,10 +775,9 @@ esdi_write(uint16_t port, uint8_t val, void *priv) { esdi_t *dev = (esdi_t *)priv; -#if 0 - pclog("ESDI: wr(%04x, %02x)\n", port-dev->base, val); -#endif - switch (port-dev->base) { + esdi_mca_log("ESDI: wr(%04x, %02x)\n", port & 7, val); + + switch (port & 7) { case 2: /*Basic control register*/ if ((dev->basic_ctrl & CTRL_RESET) && !(val & CTRL_RESET)) { dev->in_reset = 1; @@ -751,7 +787,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) dev->basic_ctrl = val; if (! (dev->basic_ctrl & CTRL_IRQ_ENA)) - picintc(1 << dev->irq); + picintc(1 << 14); break; case 3: /*Attention register*/ @@ -765,6 +801,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) dev->cmd_dev = ATTN_HOST_ADAPTER; dev->status |= STATUS_BUSY; dev->cmd_pos = 0; + dev->status_pos = 0; break; case ATTN_EOI: @@ -793,6 +830,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) dev->cmd_dev = ATTN_DEVICE_0; dev->status |= STATUS_BUSY; dev->cmd_pos = 0; + dev->status_pos = 0; break; case ATTN_EOI: @@ -815,6 +853,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) dev->cmd_dev = ATTN_DEVICE_1; dev->status |= STATUS_BUSY; dev->cmd_pos = 0; + dev->status_pos = 0; break; case ATTN_EOI: @@ -845,12 +884,11 @@ esdi_readw(uint16_t port, void *priv) esdi_t *dev = (esdi_t *)priv; uint16_t ret = 0xffff; - switch (port-dev->base) { + switch (port & 7) { case 0: /*Status Interface Register*/ if (dev->status_pos >= dev->status_len) return(0); - ret = dev->status_data[dev->status_pos++]; - if (dev->status_pos >= dev->status_len) { + ret = dev->status_data[dev->status_pos++]; if (dev->status_pos >= dev->status_len) { dev->status &= ~STATUS_STATUS_OUT_FULL; dev->status_pos = dev->status_len = 0; } @@ -869,10 +907,9 @@ esdi_writew(uint16_t port, uint16_t val, void *priv) { esdi_t *dev = (esdi_t *)priv; -#if 0 - pclog("ESDI: wrw(%04x, %04x)\n", port-dev->base, val); -#endif - switch (port-dev->base) { + esdi_mca_log("ESDI: wrw(%04x, %04x)\n", port & 7, val); + + switch (port & 7) { case 0: /*Command Interface Register*/ if (dev->cmd_pos >= 4) fatal("CIR pos 4\n"); @@ -903,9 +940,8 @@ esdi_mca_read(int port, void *priv) { esdi_t *dev = (esdi_t *)priv; -#if 0 - pclog("ESDI: mcard(%04x)\n", port); -#endif + esdi_mca_log("ESDI: mcard(%04x)\n", port); + return(dev->pos_regs[port & 7]); } @@ -915,127 +951,58 @@ esdi_mca_write(int port, uint8_t val, void *priv) { esdi_t *dev = (esdi_t *)priv; -#if 0 - pclog("ESDI: mcawr(%04x, %02x) pos[2]=%02x pos[3]=%02x\n", + esdi_mca_log("ESDI: mcawr(%04x, %02x) pos[2]=%02x pos[3]=%02x\n", port, val, dev->pos_regs[2], dev->pos_regs[3]); -#endif - if (port < 0x102) return; - /* - * The PS/2 Model 80 BIOS always enables a card if it finds one, - * even if no resources were assigned yet (because we only added - * the card, but have not run AutoConfig yet...) - * - * So, remove current address, if any. - * - * Note by Kotori: Moved this to the beginning of esdi_mca_write, - * so the *old* base is removed rather than the - * new base. - */ - io_removehandler(dev->base, 8, - esdi_read, esdi_readw, NULL, - esdi_write, esdi_writew, NULL, dev); - mem_mapping_disable(&dev->bios_rom.mapping); + if (port < 0x102) + return; /* Save the new value. */ dev->pos_regs[port & 7] = val; - /* Extract the new I/O base. */ - switch(dev->pos_regs[2] & 0x02) { - case 0x00: /* PRIMARY [0]=XXxx xx0X 0x3510 */ - dev->base = ESDI_IOADDR_PRI; - break; + io_removehandler(ESDI_IOADDR_PRI, 8, + esdi_read, esdi_readw, NULL, + esdi_write, esdi_writew, NULL, dev); + mem_mapping_disable(&dev->bios_rom.mapping); - case 0x02: /* SECONDARY [0]=XXxx xx1X 0x3518 */ - dev->base = ESDI_IOADDR_SEC; - break; - } - - /* Extract the new DMA channel. */ switch(dev->pos_regs[2] & 0x3c) { - case 0x14: /* DMA 5 [0]=XX01 01XX */ + case 0x14: dev->dma = 5; break; - - case 0x18: /* DMA 6 [0]=XX01 10XX */ + case 0x18: dev->dma = 6; break; - - case 0x1c: /* DMA 7 [0]=XX01 11XX */ + case 0x1c: dev->dma = 7; break; - - case 0x00: /* DMA 0 [0]=XX00 00XX */ + case 0x00: dev->dma = 0; break; - - case 0x01: /* DMA 1 [0]=XX00 01XX */ + case 0x04: dev->dma = 1; break; - - case 0x04: /* DMA 3 [0]=XX00 11XX */ + case 0x0c: dev->dma = 3; break; - - case 0x10: /* DMA 4 [0]=XX01 00XX */ + case 0x10: dev->dma = 4; break; } - /* Extract the new BIOS address. */ - if (! (dev->pos_regs[3] & 0x08)) switch(dev->pos_regs[3] & 0x0f) { - case 0: /* ROM C000 [1]=XXXX 0000 */ - dev->bios = 0xC0000; - break; - - case 1: /* ROM C400 [1]=XXXX 0001 */ - dev->bios = 0xC4000; - break; - - case 2: /* ROM C800 [1]=XXXX 0010 */ - dev->bios = 0xC8000; - break; - - case 3: /* ROM CC00 [1]=XXXX 0011 */ - dev->bios = 0xCC000; - break; - - case 4: /* ROM D000 [1]=XXXX 0100 */ - dev->bios = 0xD0000; - break; - - case 5: /* ROM D400 [1]=XXXX 0101 */ - dev->bios = 0xD4000; - break; - - case 6: /* ROM D800 [1]=XXXX 0110 */ - dev->bios = 0xD8000; - break; - - case 7: /* ROM DC00 [1]=XXXX 0111 */ - dev->bios = 0xDC000; - break; - } else { - /* BIOS ROM disabled. */ - dev->bios = 0x000000; - } - - if (dev->pos_regs[2] & 0x01) { - /* Card enabled; register (new) I/O handler. */ - io_sethandler(dev->base, 8, + if (dev->pos_regs[2] & 1) { + io_sethandler(ESDI_IOADDR_PRI, 8, esdi_read, esdi_readw, NULL, esdi_write, esdi_writew, NULL, dev); - /* Enable or disable the BIOS ROM. */ - if (dev->bios != 0x000000) { + if (!(dev->pos_regs[3] & 8)) { mem_mapping_enable(&dev->bios_rom.mapping); mem_mapping_set_addr(&dev->bios_rom.mapping, - dev->bios, 0x4000); + ((dev->pos_regs[3] & 7) * 0x4000) + 0xc0000, 0x4000); } /* Say hello. */ - pclog("ESDI: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X\n", - dev->base, dev->irq, dev->dma, dev->bios); + esdi_mca_log("ESDI: I/O=3510, IRQ=14, DMA=%d, BIOS @%05X\n", + dev->dma, dev->bios); } } @@ -1054,9 +1021,6 @@ esdi_init(const device_t *info) /* Mark as unconfigured. */ dev->irq_status = 0xff; - /* This is hardwired. */ - dev->irq = ESDI_IRQCHAN; - rom_init_interleaved(&dev->bios_rom, BIOS_FILE_H, BIOS_FILE_L, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); @@ -1080,7 +1044,7 @@ esdi_init(const device_t *info) drive->spt = hdd[i].spt; drive->hpc = hdd[i].hpc; drive->tracks = hdd[i].tracks; - drive->sectors = hdd[i].spt*hdd[i].hpc*hdd[i].tracks; + drive->sectors = hdd_image_get_last_sector(i) + 1; drive->hdd_num = i; /* Mark drive as present. */ @@ -1139,5 +1103,5 @@ const device_t esdi_ps2_device = { "IBM ESDI Fixed Disk Adapter (MCA)", DEVICE_MCA, 0, esdi_init, esdi_close, NULL, - esdi_available, NULL, NULL, NULL, NULL + esdi_available, NULL, NULL, NULL }; diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index d5a5f36d5..8ed9d188e 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -9,7 +9,7 @@ * Implementation of the IDE emulation for hard disks and ATAPI * CD-ROM devices. * - * Version: @(#)hdc_ide.c 1.0.43 2018/03/20 + * Version: @(#)hdc_ide.c 1.0.47 2018/06/02 * * Authors: Sarah Walker, * Miran Grca, @@ -32,12 +32,14 @@ #include "../cpu/cpu.h" #include "../machine/machine.h" #include "../io.h" +#include "../mem.h" #include "../pic.h" #include "../pci.h" +#include "../rom.h" #include "../timer.h" #include "../device.h" -#include "../cdrom/cdrom.h" #include "../scsi/scsi.h" +#include "../cdrom/cdrom.h" #include "../plat.h" #include "../ui.h" #include "hdc.h" @@ -47,26 +49,34 @@ /* Bits of 'atastat' */ -#define ERR_STAT 0x01 -#define DRQ_STAT 0x08 /* Data request */ -#define DSC_STAT 0x10 -#define SERVICE_STAT 0x10 -#define READY_STAT 0x40 -#define BUSY_STAT 0x80 +#define ERR_STAT 0x01 /* Error */ +#define IDX_STAT 0x02 /* Index */ +#define CORR_STAT 0x04 /* Corrected data */ +#define DRQ_STAT 0x08 /* Data request */ +#define DSC_STAT 0x10 /* Drive seek complete */ +#define SERVICE_STAT 0x10 /* ATAPI service */ +#define DWF_STAT 0x20 /* Drive write fault */ +#define DRDY_STAT 0x40 /* Ready */ +#define BSY_STAT 0x80 /* Busy */ /* Bits of 'error' */ -#define ABRT_ERR 0x04 /* Command aborted */ -#define MCR_ERR 0x08 /* Media change request */ +#define AMNF_ERR 0x01 /* Address mark not found */ +#define TK0NF_ERR 0x02 /* Track 0 not found */ +#define ABRT_ERR 0x04 /* Command aborted */ +#define MCR_ERR 0x08 /* Media change request */ +#define IDNF_ERR 0x10 /* Sector ID not found */ +#define MC_ERR 0x20 /* Media change */ +#define UNC_ERR 0x40 /* Uncorrectable data error */ +#define BBK_ERR 0x80 /* Bad block mark detected */ /* ATA Commands */ #define WIN_NOP 0x00 #define WIN_SRST 0x08 /* ATAPI Device Reset */ #define WIN_RECAL 0x10 -#define WIN_RESTORE WIN_RECAL #define WIN_READ 0x20 /* 28-Bit Read */ -#define WIN_READ_NORETRY 0x21 /* 28-Bit Read - no retry*/ +#define WIN_READ_NORETRY 0x21 /* 28-Bit Read - no retry */ #define WIN_WRITE 0x30 /* 28-Bit Write */ -#define WIN_WRITE_NORETRY 0x31 /* 28-Bit Write */ +#define WIN_WRITE_NORETRY 0x31 /* 28-Bit Write - no retry */ #define WIN_VERIFY 0x40 /* 28-Bit Verify */ #define WIN_VERIFY_ONCE 0x41 /* Added by OBattler - deprected older ATA command, according to the specification I found, it is identical to 0x40 */ #define WIN_FORMAT 0x50 @@ -91,31 +101,60 @@ #define WIN_SET_FEATURES 0xEF #define WIN_READ_NATIVE_MAX 0xF8 -#define FEATURE_SET_TRANSFER_MODE 0x03 -#define FEATURE_ENABLE_IRQ_OVERLAPPED 0x5d -#define FEATURE_ENABLE_IRQ_SERVICE 0x5e -#define FEATURE_DISABLE_REVERT 0x66 -#define FEATURE_ENABLE_REVERT 0xcc -#define FEATURE_DISABLE_IRQ_OVERLAPPED 0xdd -#define FEATURE_DISABLE_IRQ_SERVICE 0xde +#define FEATURE_SET_TRANSFER_MODE 0x03 +#define FEATURE_ENABLE_IRQ_OVERLAPPED 0x5d +#define FEATURE_ENABLE_IRQ_SERVICE 0x5e +#define FEATURE_DISABLE_REVERT 0x66 +#define FEATURE_ENABLE_REVERT 0xcc +#define FEATURE_DISABLE_IRQ_OVERLAPPED 0xdd +#define FEATURE_DISABLE_IRQ_SERVICE 0xde +#if 0 +/* In the future, there's going to be just the IDE_ATAPI type, + leaving it to the common ATAPI/SCSI device handler to know + what type the device is. */ enum { - IDE_NONE = 0, - IDE_HDD, - IDE_CDROM, - IDE_ZIP + IDE_NONE = 0, + IDE_HDD, + IDE_ATAPI }; +#else +enum +{ + IDE_NONE = 0, + IDE_HDD, + IDE_CDROM, + IDE_ZIP +}; +#endif + +#define IDE_PCI (PCI && (romset != ROM_PB640)) -IDE ide_drives[IDE_NUM + XTIDE_NUM]; -IDE *ext_ide; -int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length); -int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length); -void (*ide_bus_master_set_irq)(int channel); -int64_t idecallback[5] = {0LL, 0LL, 0LL, 0LL, 0LL}; -int cur_ide[5]; -int ide_init_ch[2] = {0, 0}; +typedef struct { + int bit32, cur_dev, + irq; + int64_t callback; +} ide_board_t; + +static ide_board_t *ide_boards[4]; + +ide_t *ide_drives[IDE_NUM]; +int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length, void *priv); +int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length, void *priv); +void (*ide_bus_master_set_irq)(int channel, void *priv); +void *ide_bus_master_priv[2]; +int ide_inited = 0; +int ide_ter_enabled = 0, ide_qua_enabled = 0; + +static uint16_t ide_base_main[4] = { 0x1f0, 0x170, 0x168, 0x1e8 }; +static uint16_t ide_side_main[4] = { 0x3f6, 0x376, 0x36e, 0x3ee }; + +static void ide_callback(void *priv); + + +#define IDE_TIME (20LL * TIMER_USEC) / 3LL #ifdef ENABLE_IDE_LOG @@ -123,139 +162,215 @@ int ide_do_log = ENABLE_IDE_LOG; #endif -static void ide_log(const char *fmt, ...) +static void +ide_log(const char *fmt, ...) { #ifdef ENABLE_IDE_LOG - va_list ap; + va_list ap; - if (ide_do_log) - { + if (ide_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); - } + } #endif } -uint8_t getstat(IDE *ide) { return ide->atastat; } +uint8_t +getstat(ide_t *ide) { + return ide->atastat; +} -int ide_drive_is_cdrom(IDE *ide) +int64_t +ide_get_period(ide_t *ide, int size) { - if (ide->channel >= 8) - { - return 0; - } + double period = 10.0 / 3.0; - if (atapi_cdrom_drives[ide->channel] >= CDROM_NUM) - { - return 0; - } + switch(ide->mdma_mode & 0x300) { + case 0x000: /* PIO */ + switch(ide->mdma_mode & 0xff) { + case 0: + period = 10.0 / 3.0; + break; + case 1: + period = (period * 600.0) / 383.0; + break; + case 2: + period = 25.0 / 3.0; + break; + case 3: + period = 100.0 / 9.0; + break; + case 4: + period = 50.0 / 3.0; + break; + } + break; + case 0x100: /* Single Word DMA */ + switch(ide->mdma_mode & 0xff) { + case 0: + period = 25.0 / 12.0; + break; + case 1: + period = 25.0 / 6.0; + break; + case 2: + period = 25.0 / 3.0; + break; + } + break; + case 0x200: /* Multiword DMA */ + switch(ide->mdma_mode & 0xff) { + case 0: + period = 25.0 / 6.0; + break; + case 1: + period = 40.0 / 3.0; + break; + case 2: + period = 50.0 / 3.0; + break; + } + break; + case 0x300: /* Ultra DMA */ + switch(ide->mdma_mode & 0xff) { + case 0: + period = 50.0 / 3.0; + break; + case 1: + period = 25.0; + break; + case 2: + period = 100.0 / 3.0; + break; + case 3: + period = 400.0 / 9.0; + break; + case 4: + period = 200.0 / 3.0; + break; + case 5: + period = 100.0; + break; + } + break; + } + + period *= 1048576.0; /* period * MB */ + period = 1000000.0 / period; + period *= (double) TIMER_USEC; + period *= (double) size; + return (int64_t) period; +} + + +#if 0 +int64_t +ide_get_seek_time(ide_t *ide, uint32_t new_pos) +{ + double dusec, time; + uint32_t pos = hdd_image_get_pos(ide->hdd_num); + uint32_t t, nt; + t = pos / ide->spt; + nt = new_pos / ide->spt; + + dusec = (double) TIMER_USEC; + time = (1000000.0 / 2800.0) * dusec; /* Revolution (1/2800 s). */ + + if ((t % ide->hpc) != (pos % ide->hpc)) /* Head change. */ + time += (dusec / 250.0); /* 4ns */ + + t /= ide->hpc; + nt /= ide->hpc; + + if (t != nt) { + t = ABS(t - nt); + time += ((40000.0 * dusec) / ((double) ide->tracks)) * ((double) t); + } + return (int64_t) time; +} +#endif + + +int +ide_drive_is_cdrom(ide_t *ide) +{ + int ch = ide->channel; + + if (ch >= 8) + return 0; + + if (atapi_cdrom_drives[ch] >= CDROM_NUM) + return 0; + else { + if (cdrom_drives[atapi_cdrom_drives[ch]].bus_type == CDROM_BUS_ATAPI) + return 1; else - { - if ((cdrom_drives[atapi_cdrom_drives[ide->channel]].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) || (cdrom_drives[atapi_cdrom_drives[ide->channel]].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA)) - { - return 1; - } - else - { - return 0; - } - } -} - -int ide_drive_is_zip(IDE *ide) -{ - if (ide->channel >= 8) - { return 0; - } + } +} - if (atapi_zip_drives[ide->channel] >= ZIP_NUM) - { + +int +ide_drive_is_zip(ide_t *ide) +{ + int ch = ide->channel; + + if (ch >= 8) + return 0; + + if (atapi_zip_drives[ch] >= ZIP_NUM) + return 0; + else { + if (zip_drives[atapi_zip_drives[ch]].bus_type == ZIP_BUS_ATAPI) + return 1; + else return 0; - } - else - { - if ((zip_drives[atapi_zip_drives[ide->channel]].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || (zip_drives[atapi_zip_drives[ide->channel]].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA)) - { - return 1; - } - else - { - return 0; - } - } + } } -int ide_enable[5] = { 1, 1, 0, 0, 1 }; -int ide_irq[5] = { 14, 15, 10, 11, 0 }; -void ide_irq_raise(IDE *ide) +void +ide_irq_raise(ide_t *ide) { - /* ide_log("Attempting to raise IRQ %i (board %i)\n", ide_irq[ide->board], ide->board); */ + if (!ide_boards[ide->board]) + return; - if ((ide->board > 3) || ide->irqstat) - { - ide->irqstat=1; - ide->service=1; + /* ide_log("Raising IRQ %i (board %i)\n", ide_boards[ide->board]->irq, ide->board); */ - return; - } - - ide_log("Raising IRQ %i (board %i)\n", ide_irq[ide->board], ide->board); - - if (!(ide->fdisk&2)) - { - if (pci_use_mirq(0) && (ide->board == 1)) - { - pci_set_mirq(0); - } - else - { - picint(1 << ide_irq[ide->board]); - } - - if (ide->board < 2) - { - if (ide_bus_master_set_irq) - { - ide_bus_master_set_irq(ide->board | 0x40); - } - } - } - - ide->irqstat=1; - ide->service=1; -} - -void ide_irq_lower(IDE *ide) -{ - if ((ide->board > 3) || !(ide->irqstat)) - { - ide->irqstat=0; - return; - } - - ide_log("Lowering IRQ %i (board %i)\n", ide_irq[ide->board], ide->board); - - if (pci_use_mirq(0) && (ide->board == 1)) - { - pci_clear_mirq(0); - } + if (!(ide->fdisk & 2) && (ide_boards[ide->board]->irq != -1)) { + if ((ide->board < 2) && ide_bus_master_set_irq) + ide_bus_master_set_irq(ide->board | 0x40, ide_bus_master_priv[ide->board]); else - { - picintc(1 << ide_irq[ide->board]); - } + picint(1 << ide_boards[ide->board]->irq); + } - if (ide_bus_master_set_irq) - { - ide_bus_master_set_irq(ide->board); - } - ide->irqstat=0; + ide->irqstat=1; + ide->service=1; } + +void +ide_irq_lower(ide_t *ide) +{ + if (!ide_boards[ide->board]) + return; + + /* ide_log("Lowering IRQ %i (board %i)\n", ide_boards[ide->board]->irq, ide->board); */ + + if ((ide_boards[ide->board]->irq != -1) && ide->irqstat) { + if ((ide->board < 2) && ide_bus_master_set_irq) + ide_bus_master_set_irq(ide->board, ide_bus_master_priv[ide->board]); + else + picintc(1 << ide_boards[ide->board]->irq); + } + + ide->irqstat=0; +} + + /** * Copy a string into a buffer, padding with spaces, and placing characters as * if they were packed into 16-bit values, stored little-endian. @@ -268,22 +383,18 @@ void ide_irq_lower(IDE *ide) static void ide_padstr(char *str, const char *src, int len) { - int i, v; + int i, v; - for (i = 0; i < len; i++) - { - if (*src != '\0') - { - v = *src++; - } - else - { - v = ' '; - } - str[i ^ 1] = v; - } + for (i = 0; i < len; i++) { + if (*src != '\0') + v = *src++; + else + v = ' '; + str[i ^ 1] = v; + } } + /** * Copy a string into a buffer, padding with spaces. Does not add string * terminator. @@ -295,1017 +406,1073 @@ ide_padstr(char *str, const char *src, int len) */ void ide_padstr8(uint8_t *buf, int buf_size, const char *src) { - int i; + int i; - for (i = 0; i < buf_size; i++) - { - if (*src != '\0') - { - buf[i] = *src++; - } - else - { - buf[i] = ' '; - } - } + for (i = 0; i < buf_size; i++) { + if (*src != '\0') + buf[i] = *src++; + else + buf[i] = ' '; + } } + +/* Type: + 0 = PIO, + 1 = SDMA, + 2 = MDMA, + 3 = UDMA + Return: + -1 = Not supported, + Anything else = maximum mode + + This will eventually be hookable. */ +enum { + TYPE_PIO = 0, + TYPE_SDMA, + TYPE_MDMA, + TYPE_UDMA +}; + +static int +ide_get_max(ide_t *ide, int type) +{ + switch(type) { + case TYPE_PIO: /* PIO */ + if (!IDE_PCI || (ide->board >= 2)) + return 0; /* Maximum PIO 0 for legacy PIO-only drive. */ + else { + if (ide_drive_is_zip(ide)) + return 3; + else + return 4; + } + break; + case TYPE_SDMA: /* SDMA */ + if (!IDE_PCI || (ide->board >= 2) || ide_drive_is_zip(ide)) + return -1; + else + return 2; + case TYPE_MDMA: /* MDMA */ + if (!IDE_PCI || (ide->board >= 2)) + return -1; + else { + if (ide_drive_is_zip(ide)) + return 1; + else + return 2; + } + case TYPE_UDMA: /* UDMA */ + if (!IDE_PCI || (ide->board >= 2)) + return -1; + else + return 2; + default: + fatal("Unknown transfer type: %i\n", type); + return -1; + } +} + + +/* Return: + 0 = Not supported, + Anything else = timings + + This will eventually be hookable. */ +enum { + TIMINGS_DMA = 0, + TIMINGS_PIO, + TIMINGS_PIO_FC +}; + +static int +ide_get_timings(ide_t *ide, int type) +{ + switch(type) { + case TIMINGS_DMA: + if (!IDE_PCI || (ide->board >= 2)) + return 0; + else { + if (ide_drive_is_zip(ide)) + return 0x96; + else + return 120; + } + break; + case TIMINGS_PIO: + if (!IDE_PCI || (ide->board >= 2)) + return 0; + else { + if (ide_drive_is_zip(ide)) + return 0xb4; + else + return 120; + } + break; + case TIMINGS_PIO_FC: + if (!IDE_PCI || (ide->board >= 2)) + return 0; + else { + if (ide_drive_is_zip(ide)) + return 0xb4; + else + return 0; + } + break; + default: + fatal("Unknown transfer type: %i\n", type); + return 0; + } +} + + /** * Fill in ide->buffer with the output of the "IDENTIFY DEVICE" command */ -static void ide_identify(IDE *ide) +static void ide_hd_identify(ide_t *ide) { - uint32_t d; - char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; + char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; - uint64_t d_hpc, d_spt, d_tracks; - uint64_t full_size = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); + uint32_t d_hpc, d_spt, d_tracks; + uint64_t full_size = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); - device_identify[6] = (ide->hdd_num / 10) + 0x30; - device_identify[7] = (ide->hdd_num % 10) + 0x30; - ide_log("IDE Identify: %s\n", device_identify); + device_identify[6] = (ide->hdd_num / 10) + 0x30; + device_identify[7] = (ide->hdd_num % 10) + 0x30; + ide_log("IDE Identify: %s\n", device_identify); - memset(ide->buffer, 0, 512); - d_spt = ide->spt; - if (ide->hpc <= 16) { - /* HPC <= 16, report as needed. */ - d_tracks = ide->tracks; - d_hpc = ide->hpc; + d_spt = ide->spt; + if (ide->hpc <= 16) { + /* HPC <= 16, report as needed. */ + d_tracks = ide->tracks; + d_hpc = ide->hpc; + } else { + /* HPC > 16, convert to 16 HPC. */ + d_hpc = 16; + d_tracks = (ide->tracks * ide->hpc) / 16; + } + + /* Specify default CHS translation */ + if (full_size <= 16514064) { + ide->buffer[1] = d_tracks; /* Tracks in default CHS translation. */ + ide->buffer[3] = d_hpc; /* Heads in default CHS translation. */ + ide->buffer[6] = d_spt; /* Heads in default CHS translation. */ + } else { + ide->buffer[1] = 16383; /* Tracks in default CHS translation. */ + ide->buffer[3] = 16; /* Heads in default CHS translation. */ + ide->buffer[6] = 63; /* Heads in default CHS translation. */ + } + ide_log("Default CHS translation: %i, %i, %i\n", ide->buffer[1], ide->buffer[3], ide->buffer[6]); + + ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ + ide_padstr((char *) (ide->buffer + 23), EMU_VERSION, 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ + ide->buffer[20] = 3; /*Buffer type*/ + ide->buffer[21] = 512; /*Buffer size*/ + ide->buffer[50] = 0x4000; /* Capabilities */ + ide->buffer[59] = ide->blocksize ? (ide->blocksize | 0x100) : 0; + + if ((ide->tracks >= 1024) || (ide->hpc > 16) || (ide->spt > 63)) { + ide->buffer[49] = (1 << 9); + ide_log("LBA supported\n"); + + ide->buffer[60] = full_size & 0xFFFF; /* Total addressable sectors (LBA) */ + ide->buffer[61] = (full_size >> 16) & 0x0FFF; + ide_log("Full size: %" PRIu64 "\n", full_size); + + /* + Bit 0 = The fields reported in words 54-58 are valid; + Bit 1 = The fields reported in words 64-70 are valid; + Bit 2 = The fields reported in word 88 are valid. */ + ide->buffer[53] = 1; + + if (ide->cfg_spt != 0) { + ide->buffer[54] = (full_size / ide->cfg_hpc) / ide->cfg_spt; + ide->buffer[55] = ide->cfg_hpc; + ide->buffer[56] = ide->cfg_spt; } else { - /* HPC > 16, convert to 16 HPC. */ - d_hpc = 16; - d_tracks = (ide->tracks * ide->hpc) / 16; - } - - /* Specify default CHS translation */ - if (full_size <= 16514064) { - ide->buffer[1] = d_tracks; /* Tracks in default CHS translation. */ - ide->buffer[3] = d_hpc; /* Heads in default CHS translation. */ - ide->buffer[6] = d_spt; /* Heads in default CHS translation. */ - } else { - ide->buffer[1] = 16383; /* Tracks in default CHS translation. */ - ide->buffer[3] = 16; /* Heads in default CHS translation. */ - ide->buffer[6] = 63; /* Heads in default CHS translation. */ - } - ide_log("Default CHS translation: %i, %i, %i\n", ide->buffer[1], ide->buffer[3], ide->buffer[6]); - - ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ - ide_padstr((char *) (ide->buffer + 23), EMU_VERSION, 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ - ide->buffer[20] = 3; /*Buffer type*/ - ide->buffer[21] = 512; /*Buffer size*/ - ide->buffer[48] = 1; /*Dword transfers supported*/ - if (PCI && (ide->board < 2) && (hdd[ide->hdd_num].bus == HDD_BUS_IDE_PIO_AND_DMA)) { - ide->buffer[47] = 32 | 0x8000; /*Max sectors on multiple transfer command*/ - ide->buffer[49] = (1 << 8); /* LBA and DMA supported */ - } else { - ide->buffer[47] = 16 | 0x8000; /*Max sectors on multiple transfer command*/ - ide->buffer[49] = 0; - } - if ((ide->tracks >= 1024) || (ide->hpc > 16) || (ide->spt > 63)) - { - ide->buffer[49] |= (1 << 9); - ide_log("LBA supported\n"); - } - ide->buffer[50] = 0x4000; /* Capabilities */ - ide->buffer[51] = 2 << 8; /*PIO timing mode*/ - - if (ide->buffer[49] & (1 << 9)) - { - ide->buffer[60] = full_size & 0xFFFF; /* Total addressable sectors (LBA) */ - ide->buffer[61] = (full_size >> 16) & 0x0FFF; - ide_log("Full size: %" PRIu64 "\n", full_size); - - ide->buffer[53] |= 1; - - if (ide->specify_success) { - ide->buffer[54] = (full_size / ide->t_hpc) / ide->t_spt; - ide->buffer[55] = ide->t_hpc; - ide->buffer[56] = ide->t_spt; + if (full_size <= 16514064) { + ide->buffer[54] = d_tracks; + ide->buffer[55] = d_hpc; + ide->buffer[56] = d_spt; } else { - if (full_size <= 16514064) { - ide->buffer[54] = d_tracks; - ide->buffer[55] = d_hpc; - ide->buffer[56] = d_spt; - } else { - ide->buffer[54] = 16383; - ide->buffer[55] = 16; - ide->buffer[56] = 63; - } + ide->buffer[54] = 16383; + ide->buffer[55] = 16; + ide->buffer[56] = 63; } - - full_size = ((uint64_t) ide->buffer[54]) * ((uint64_t) ide->buffer[55]) * ((uint64_t) ide->buffer[56]); - - ide->buffer[57] = full_size & 0xFFFF; /* Total addressable sectors (LBA) */ - ide->buffer[58] = (full_size >> 16) & 0x0FFF; - - ide_log("Current CHS translation: %i, %i, %i\n", ide->buffer[54], ide->buffer[55], ide->buffer[56]); } - ide->buffer[59] = ide->blocksize ? (ide->blocksize | 0x100) : 0; + full_size = ((uint64_t) ide->buffer[54]) * ((uint64_t) ide->buffer[55]) * ((uint64_t) ide->buffer[56]); - if (ide->buffer[49] & (1 << 8)) - { - ide->buffer[51] = 120; - ide->buffer[52] = 120; /*DMA timing mode*/ - ide->buffer[53] |= 6; + ide->buffer[57] = full_size & 0xFFFF; /* Total addressable sectors (LBA) */ + ide->buffer[58] = (full_size >> 16) & 0x0FFF; - ide->buffer[62] = 7; - ide->buffer[63] = 7; - ide->buffer[64] = 3; /*PIO Modes 3 & 4*/ - ide->buffer[88] = 7; - if (ide->mdma_mode != -1) - { - d = (ide->mdma_mode & 0xff); - d <<= 8; - if ((ide->mdma_mode & 0x300) == 0x200) - ide->buffer[88] |= d; - else if ((ide->mdma_mode & 0x300) == 0x100) - ide->buffer[63] |= d; - else if ((ide->mdma_mode & 0x300) == 0x400) { - if ((ide->mdma_mode & 0xff) >= 3) - ide->buffer[64] |= d; - } else - ide->buffer[62] |= d; - ide_log(" IDENTIFY DMA Mode: %04X, %04X\n", ide->buffer[62], ide->buffer[63]); - } - ide->buffer[65] = 120; - ide->buffer[66] = 120; - ide->buffer[80] = 0x1e; /*ATA-1 to ATA-4 supported*/ - ide->buffer[81] = 0x18; /*ATA-4 revision 18 supported*/ - } else { - ide->buffer[80] = 0x0e; /*ATA-1 to ATA-3 supported*/ - } + ide_log("Current CHS translation: %i, %i, %i\n", ide->buffer[54], ide->buffer[55], ide->buffer[56]); + } + + if (IDE_PCI && (ide->board < 2)) { + ide->buffer[47] = 32 | 0x8000; /*Max sectors on multiple transfer command*/ + ide->buffer[80] = 0x1e; /*ATA-1 to ATA-4 supported*/ + ide->buffer[81] = 0x18; /*ATA-4 revision 18 supported*/ + } else { + ide->buffer[47] = 16 | 0x8000; /*Max sectors on multiple transfer command*/ + ide->buffer[80] = 0x0e; /*ATA-1 to ATA-3 supported*/ + } } + /** * Fill in ide->buffer with the output of the "IDENTIFY PACKET DEVICE" command */ -static void ide_atapi_identify(IDE *ide) +static void +ide_atapi_cdrom_identify(ide_t *ide) { - char device_identify[9] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', 0 }; + char device_identify[9] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', 0 }; - uint8_t cdrom_id; - int32_t d; + uint8_t cdrom_id; - memset(ide->buffer, 0, 512); - cdrom_id = atapi_cdrom_drives[ide->channel]; + cdrom_id = atapi_cdrom_drives[ide->channel]; - device_identify[7] = cdrom_id + 0x30; - ide_log("ATAPI Identify: %s\n", device_identify); + device_identify[7] = cdrom_id + 0x30; + ide_log("ATAPI Identify: %s\n", device_identify); - ide->buffer[0] = 0x8000 | (5<<8) | 0x80 | (2<<5); /* ATAPI device, CD-ROM drive, removable media, accelerated DRQ */ - ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ - ide_padstr((char *) (ide->buffer + 23), EMU_VERSION, 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ - ide->buffer[48] = 1; /*Dword transfers supported*/ - ide->buffer[49] = 0x200; /* LBA supported */ - ide->buffer[51] = 2 << 8; /*PIO timing mode*/ - ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ + ide->buffer[0] = 0x8000 | (5<<8) | 0x80 | (2<<5); /* ATAPI device, CD-ROM drive, removable media, accelerated DRQ */ + ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ +#if 0 + ide_padstr((char *) (ide->buffer + 23), EMU_VERSION, 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ +#else + ide_padstr((char *) (ide->buffer + 23), "4.20 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "NEC CD-ROM DRIVE:273 ", 40); /* Model */ +#endif + ide->buffer[49] = 0x200; /* LBA supported */ + ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ - if (PCI && (ide->board < 2) && (cdrom_drives[cdrom_id].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA)) - { - ide->buffer[49] |= 0x100; /* DMA supported */ - ide->buffer[51] = 120; - ide->buffer[52] = 120; /*DMA timing mode*/ - ide->buffer[53] = 7; - ide->buffer[62] = 7; - ide->buffer[63] = 7; - ide->buffer[64] = 3; /*PIO Modes 3 & 4*/ - ide->buffer[88] = 7; - if (ide->mdma_mode != -1) - { - d = (ide->mdma_mode & 0xff); - d <<= 8; - if ((ide->mdma_mode & 0x300) == 0x200) - ide->buffer[88] |= d; - else if ((ide->mdma_mode & 0x300) == 0x100) - ide->buffer[63] |= d; - else if ((ide->mdma_mode & 0x300) == 0x400) { - if ((ide->mdma_mode & 0xff) >= 3) - ide->buffer[64] |= d; - } else - ide->buffer[62] |= d; - ide_log("PIDENTIFY DMA Mode: %04X, %04X\n", ide->buffer[62], ide->buffer[63]); - } - ide->buffer[65] = 120; - ide->buffer[66] = 120; - ide->buffer[67] = 120; - ide->buffer[71] = 30; - ide->buffer[72] = 30; - ide->buffer[80] = 0x1e; /*ATA-1 to ATA-4 supported*/ - ide->buffer[81] = 0x18; /*ATA-4 revision 18 supported*/ - } + if (IDE_PCI && (ide->board < 2)) { + ide->buffer[71] = 30; + ide->buffer[72] = 30; + } } -static void ide_atapi_zip_identify(IDE *ide) + +static void +ide_atapi_zip_100_identify(ide_t *ide) { - uint8_t zip_id; - int32_t d; - - memset(ide->buffer, 0, 512); - zip_id = atapi_zip_drives[ide->channel]; - - /* Using (2<<5) below makes the ASUS P/I-P54TP4XE misdentify the ZIP drive - as a LS-120. */ - ide->buffer[0] = 0x8000 | (0<<8) | 0x80 | (1<<5); /* ATAPI device, direct-access device, removable media, interrupt DRQ */ - ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ - if (zip_drives[zip_id].is_250) { - ide_padstr((char *) (ide->buffer + 23), "42.S", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 250 ATAPI", 40); /* Model */ - } else { - ide_padstr((char *) (ide->buffer + 23), "E.08", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 100 ATAPI", 40); /* Model */ - } - - ide->buffer[48] = 1; /*Dword transfers supported*/ - ide->buffer[49] = 0x200; /* LBA supported */ - - /* Note by Kotori: Look at this if this is supported by ZIP at all. */ - ide->buffer[51] = 2 << 8; /*PIO timing mode*/ - - ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ - - if (PCI && (ide->board < 2) && (zip_drives[zip_id].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA)) - { - ide->buffer[49] |= 0x100; /* DMA supported */ - if (zip_drives[zip_id].is_250) { - ide->buffer[52] = 0 << 8; /*DMA timing mode*/ - ide->buffer[53] = 6; - ide->buffer[63] = 3; - ide->buffer[88] = 7; - ide->buffer[64] = 0x0001; /*PIO Mode 3*/ - ide->buffer[65] = 0x96; - ide->buffer[66] = 0x96; - ide->buffer[67] = 0xb4; - ide->buffer[68] = 0xb4; - ide->buffer[80] = 0x30; /*Supported ATA versions : ATA/ATAPI-4 ATA/ATAPI-5*/ - ide->buffer[81] = 0x15; /*Maximum ATA revision supported : ATA/ATAPI-5 T13 1321D revision 1*/ - } else { - ide->buffer[51] = 120; - ide->buffer[52] = 120; - ide->buffer[53] = 2; /*Words 64-70 are valid*/ - ide->buffer[63] = 0x0003; /*Multi-word DMA 0 & 1*/ - ide->buffer[88] = 7; - ide->buffer[64] = 0x0001; /*PIO Mode 3*/ - ide->buffer[65] = 120; - ide->buffer[66] = 120; - ide->buffer[67] = 120; - } - - if (ide->mdma_mode != -1) - { - d = (ide->mdma_mode & 0xff); - d <<= 8; - if ((ide->mdma_mode & 0x300) == 0x200) - ide->buffer[88] |= d; - else if ((ide->mdma_mode & 0x300) == 0x100) - ide->buffer[63] |= d; - else if ((ide->mdma_mode & 0x300) == 0x400) { - if ((ide->mdma_mode & 0xff) >= 3) - ide->buffer[64] |= d; - } - ide_log("PIDENTIFY DMA Mode: %04X, %04X\n", ide->buffer[62], ide->buffer[63]); - } - } + ide_padstr((char *) (ide->buffer + 23), "E.08", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 100 ATAPI", 40); /* Model */ } + +static void +ide_atapi_zip_250_identify(ide_t *ide) +{ + ide_padstr((char *) (ide->buffer + 23), "42.S", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 250 ATAPI", 40); /* Model */ + + if (IDE_PCI && (ide->board < 2)) { + ide->buffer[80] = 0x30; /*Supported ATA versions : ATA/ATAPI-4 ATA/ATAPI-5*/ + ide->buffer[81] = 0x15; /*Maximum ATA revision supported : ATA/ATAPI-5 T13 1321D revision 1*/ + } +} + + +static void +ide_atapi_zip_identify(ide_t *ide) +{ + uint8_t zip_id; + + zip_id = atapi_zip_drives[ide->channel]; + + /* Using (2<<5) below makes the ASUS P/I-P54TP4XE misdentify the ZIP drive + as a LS-120. */ + ide->buffer[0] = 0x8000 | (0<<8) | 0x80 | (1<<5); /* ATAPI device, direct-access device, removable media, interrupt DRQ */ + ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ + ide->buffer[49] = 0x200; /* LBA supported */ + ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ + + if (zip_drives[zip_id].is_250) + ide_atapi_zip_250_identify(ide); + else + ide_atapi_zip_100_identify(ide); +} + +static void +ide_identify(ide_t *ide) +{ + int d, i, max_pio, max_sdma, max_mdma, max_udma; + + ide_log("IDE IDENTIFY or IDENTIFY PACKET DEVICE on board %i (channel %i)\n", ide->board, ide->channel); + + memset(ide->buffer, 0, 512); + + if (ide_drive_is_cdrom(ide)) + ide_atapi_cdrom_identify(ide); + else if (ide_drive_is_zip(ide)) + ide_atapi_zip_identify(ide); + else if (ide->type != IDE_NONE) + ide_hd_identify(ide); + else { + fatal("IDE IDENTIFY or IDENTIFY PACKET DEVICE on non-attached IDE device\n"); + return; + } + + max_pio = ide_get_max(ide, TYPE_PIO); + max_sdma = ide_get_max(ide, TYPE_SDMA); + max_mdma = ide_get_max(ide, TYPE_MDMA); + max_udma = ide_get_max(ide, TYPE_UDMA); + + if (ide_boards[ide->board]->bit32) + ide->buffer[48] |= 1; /*Dword transfers supported*/ + ide->buffer[51] = ide_get_timings(ide, TIMINGS_PIO); + ide->buffer[53] &= 0x0006; + ide->buffer[52] = ide->buffer[62] = ide->buffer[63] = ide->buffer[64] = 0x0000; + ide->buffer[65] = ide->buffer[66] = ide->buffer[67] = ide->buffer[68] = 0x0000; + ide->buffer[88] = 0x0000; + + if (max_pio >= 3) { + ide->buffer[53] |= 0x0002; + ide->buffer[67] = ide_get_timings(ide, TIMINGS_PIO); + ide->buffer[68] = ide_get_timings(ide, TIMINGS_PIO_FC); + for (i = 3; i <= max_pio; i++) + ide->buffer[64] |= (1 << (i - 3)); + } + if (max_sdma != -1) { + for (i = 0; i <= max_sdma; i++) + ide->buffer[62] |= (1 << i); + } + if (max_mdma != -1) { + for (i = 0; i <= max_mdma; i++) + ide->buffer[63] |= (1 << i); + } + if (max_udma != -1) { + ide->buffer[53] |= 0x0004; + for (i = 0; i <= max_udma; i++) + ide->buffer[88] |= (1 << i); + } + + if ((max_sdma != -1) || (max_mdma != -1) || (max_udma != -1)) { + ide->buffer[49] |= 0x100; /* DMA supported */ + ide->buffer[52] = ide_get_timings(ide, TIMINGS_DMA); + } + + if ((max_mdma != -1) || (max_udma != -1)) { + ide->buffer[65] = ide_get_timings(ide, TIMINGS_DMA); + ide->buffer[66] = ide_get_timings(ide, TIMINGS_DMA); + } + + if (ide->mdma_mode != -1) { + d = (ide->mdma_mode & 0xff); + d <<= 8; + if ((ide->mdma_mode & 0x300) == 0x000) { + if ((ide->mdma_mode & 0xff) >= 3) + ide->buffer[64] |= d; + } else if ((ide->mdma_mode & 0x300) == 0x100) + ide->buffer[62] |= d; + else if ((ide->mdma_mode & 0x300) == 0x200) + ide->buffer[63] |= d; + else if ((ide->mdma_mode & 0x300) == 0x300) + ide->buffer[88] |= d; + ide_log("PIDENTIFY DMA Mode: %04X, %04X\n", ide->buffer[62], ide->buffer[63]); + } +} + + /* * Return the sector offset for the current register values */ -static off64_t ide_get_sector(IDE *ide) +static off64_t +ide_get_sector(ide_t *ide) { - if (ide->lba) - { - return (off64_t)ide->lba_addr + ide->skip512; - } - else - { - uint32_t heads = ide->t_hpc; - uint32_t sectors = ide->t_spt; + uint32_t heads, sectors; - return ((((off64_t) ide->cylinder * heads) + ide->head) * - sectors) + (ide->sector - 1) + ide->skip512; - } + if (ide->lba) + return (off64_t)ide->lba_addr + ide->skip512; + else { + heads = ide->cfg_hpc; + sectors = ide->cfg_spt; + + return ((((off64_t) ide->cylinder * heads) + ide->head) * + sectors) + (ide->sector - 1) + ide->skip512; + } } + /** * Move to the next sector using CHS addressing */ -static void ide_next_sector(IDE *ide) +static void +ide_next_sector(ide_t *ide) { - if (ide->lba) - { - ide->lba_addr++; - } - else - { - ide->sector++; - if (ide->sector == (ide->t_spt + 1)) - { - ide->sector = 1; - ide->head++; - if (ide->head == ide->t_hpc) - { - ide->head = 0; - ide->cylinder++; - } - } - } -} - -static void loadhd(IDE *ide, int d, const wchar_t *fn) -{ - if (! hdd_image_load(d)) { - ide->type = IDE_NONE; - return; - } - - ide->spt = hdd[d].spt; - ide->hpc = hdd[d].hpc; - ide->tracks = hdd[d].tracks; - ide->type = IDE_HDD; - ide->hdd_num = d; - ide->hdi = hdd_image_get_type(d); -} - -void ide_set_signature(IDE *ide) -{ - uint8_t cdrom_id = atapi_cdrom_drives[ide->channel]; - uint8_t zip_id = atapi_zip_drives[ide->channel]; - ide->sector=1; - ide->head=0; - if (ide_drive_is_zip(ide)) - { - zip_set_signature(zip_id); - ide->secount = zip[zip_id].phase; - ide->cylinder = zip[zip_id].request_length; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom_set_signature(cdrom_id); - ide->secount = cdrom[cdrom_id]->phase; - ide->cylinder = cdrom[cdrom_id]->request_length; - } - else - { - ide->secount=1; - ide->cylinder=((ide->type == IDE_HDD) ? 0 : 0xFFFF); - if (ide->type == IDE_HDD) - { - ide->drive = 0; + if (ide->lba) + ide->lba_addr++; + else { + ide->sector++; + if (ide->sector == (ide->cfg_spt + 1)) { + ide->sector = 1; + ide->head++; + if (ide->head == ide->cfg_hpc) { + ide->head = 0; + ide->cylinder++; } } + } } -static int ide_set_features(IDE *ide) + +static void +loadhd(ide_t *ide, int d, const wchar_t *fn) { - uint8_t features, features_data; - uint8_t mode, submode; + if (! hdd_image_load(d)) { + ide->type = IDE_NONE; + return; + } - int bus, dma; - int max_pio = 2, max_mdma = 2; + ide->spt = hdd[d].spt; + ide->hpc = hdd[d].hpc; + ide->tracks = hdd[d].tracks; + ide->type = IDE_HDD; + ide->hdd_num = d; +} - features = ide->cylprecomp; - features_data = ide->secount; - if (ide_drive_is_zip(ide)) { - bus = zip_drives[atapi_zip_drives[ide->channel]].bus_type; - dma = (bus == ZIP_BUS_ATAPI_PIO_AND_DMA); - if (!PCI || !dma || (ide->board >= 2)) - max_pio = 0; - else - max_pio = 3; - max_mdma = 1; - } else if (ide_drive_is_cdrom(ide)) { - bus = cdrom_drives[atapi_cdrom_drives[ide->channel]].bus_type; - dma = (bus == CDROM_BUS_ATAPI_PIO_AND_DMA); - if (!PCI || !dma || (ide->board >= 2)) - max_pio = 0; - else - max_pio = 4; - } else { - bus = hdd[ide->hdd_num].bus; - dma = (bus == HDD_BUS_IDE_PIO_AND_DMA); - if (!PCI || !dma || (ide->board >= 2)) - max_pio = 0; - else - max_pio = 4; - } +void +ide_set_signature(ide_t *ide) +{ + uint8_t cdrom_id = atapi_cdrom_drives[ide->channel]; + uint8_t zip_id = atapi_zip_drives[ide->channel]; - ide_log("Features code %02X\n", features); + ide->sector=1; + ide->head=0; - ide_log("IDE %02X: Set features: %02X, %02X\n", ide->channel, features, features_data); + if (ide_drive_is_zip(ide)) { + zip_set_signature(zip[zip_id]); + ide->secount = zip[zip_id]->phase; + ide->cylinder = zip[zip_id]->request_length; + } else if (ide_drive_is_cdrom(ide)) { + cdrom_set_signature(cdrom[cdrom_id]); + ide->secount = cdrom[cdrom_id]->phase; + ide->cylinder = cdrom[cdrom_id]->request_length; + } else { + ide->secount=1; + ide->cylinder=((ide->type == IDE_HDD) ? 0 : 0xFFFF); + if (ide->type == IDE_HDD) + ide->drive = 0; + } +} - switch(features) - { - case FEATURE_SET_TRANSFER_MODE: /* Set transfer mode. */ - ide_log("Transfer mode %02X\n", features_data >> 3); - mode = (features_data >> 3); - submode = features_data & 7; +static int +ide_set_features(ide_t *ide) +{ + uint8_t features, features_data; + int mode, submode, max; - switch(mode) - { - case 0x00: /* PIO default */ - if (submode != 0) - { - return 0; - } - ide->mdma_mode = -1; - ide_log("IDE %02X: Setting DPIO mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); - break; + features = ide->cylprecomp; + features_data = ide->secount; - case 0x01: /* PIO mode */ - if (submode > max_pio) - { - return 0; - } - ide->mdma_mode = (1 << submode) | 0x400; - ide_log("IDE %02X: Setting PIO mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); - break; + ide_log("Features code %02X\n", features); - case 0x02: /* Singleword DMA mode */ - if (!PCI || !dma || ide_drive_is_zip(ide) || (ide->board >= 2) || (submode > 2)) - { - return 0; - } - ide->mdma_mode = (1 << submode); - ide_log("IDE %02X: Setting SDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); - break; + ide_log("IDE %02X: Set features: %02X, %02X\n", ide->channel, features, features_data); - case 0x04: /* Multiword DMA mode */ - if (!PCI || !dma || (ide->board >= 2) || (submode > max_mdma)) - { - return 0; - } - ide->mdma_mode = (1 << submode) | 0x100; - ide_log("IDE %02X: Setting MDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); - break; + switch(features) { + case FEATURE_SET_TRANSFER_MODE: /* Set transfer mode. */ + ide_log("Transfer mode %02X\n", features_data >> 3); - case 0x08: /* Ultra DMA mode */ - if (!PCI || !dma || (ide->board >= 2) || (submode > 2)) - { - return 0; - } - ide->mdma_mode = (1 << submode) | 0x200; - ide_log("IDE %02X: Setting UDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); - break; + mode = (features_data >> 3); + submode = features_data & 7; - default: + switch(mode) { + case 0x00: /* PIO default */ + if (submode != 0) return 0; - } + max = ide_get_max(ide, TYPE_PIO); + ide->mdma_mode = (1 << max); + ide_log("IDE %02X: Setting DPIO mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); + break; - case FEATURE_ENABLE_IRQ_OVERLAPPED: - case FEATURE_ENABLE_IRQ_SERVICE: - case FEATURE_DISABLE_IRQ_OVERLAPPED: - case FEATURE_DISABLE_IRQ_SERVICE: - if (!PCI || !dma || (ide->board >= 2)) + case 0x01: /* PIO mode */ + max = ide_get_max(ide, TYPE_PIO); + if (submode > max) + return 0; + ide->mdma_mode = (1 << submode); + ide_log("IDE %02X: Setting PIO mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); + break; + + case 0x02: /* Singleword DMA mode */ + max = ide_get_max(ide, TYPE_SDMA); + if (submode > max) + return 0; + ide->mdma_mode = (1 << submode) | 0x100; + ide_log("IDE %02X: Setting SDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); + break; + + case 0x04: /* Multiword DMA mode */ + max = ide_get_max(ide, TYPE_MDMA); + if (submode > max) + return 0; + ide->mdma_mode = (1 << submode) | 0x200; + ide_log("IDE %02X: Setting MDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); + break; + + case 0x08: /* Ultra DMA mode */ + max = ide_get_max(ide, TYPE_UDMA); + if (submode > max) + return 0; + ide->mdma_mode = (1 << submode) | 0x300; + ide_log("IDE %02X: Setting UDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); + break; + + default: return 0; - else - return 1; + } - case FEATURE_DISABLE_REVERT: /* Disable reverting to power on defaults. */ - case FEATURE_ENABLE_REVERT: /* Enable reverting to power on defaults. */ + case FEATURE_ENABLE_IRQ_OVERLAPPED: + case FEATURE_ENABLE_IRQ_SERVICE: + case FEATURE_DISABLE_IRQ_OVERLAPPED: + case FEATURE_DISABLE_IRQ_SERVICE: + max = ide_get_max(ide, TYPE_MDMA); + if (max == -1) + return 0; + else return 1; - default: - return 0; - } + case FEATURE_DISABLE_REVERT: /* Disable reverting to power on defaults. */ + case FEATURE_ENABLE_REVERT: /* Enable reverting to power on defaults. */ + return 1; - return 1; -} + default: + return 0; + } -void ide_set_sector(IDE *ide, int64_t sector_num) -{ - unsigned int cyl, r; - if (ide->lba) - { - ide->head = (sector_num >> 24); - ide->cylinder = (sector_num >> 8); - ide->sector = (sector_num); - } - else - { - cyl = sector_num / (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); - r = sector_num % (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); - ide->cylinder = cyl; - ide->head = ((r / hdd[ide->hdd_num].spt) & 0x0f); - ide->sector = (r % hdd[ide->hdd_num].spt) + 1; - } -} - -void ide_ter_disable_cond(); -void ide_qua_disable_cond(); - - -void ide_destroy_buffers(void) -{ - int d; - - for (d = 0; d < (IDE_NUM+XTIDE_NUM); d++) - { - if (ide_drives[d].buffer) { - free(ide_drives[d].buffer); - ide_drives[d].buffer = NULL; - } - - if (ide_drives[d].sector_buffer) { - free(ide_drives[d].sector_buffer); - ide_drives[d].sector_buffer = NULL; - } - } -} - -void ide_reset(void) -{ - int c, d; - - build_atapi_cdrom_map(); - build_atapi_zip_map(); - - /* Close hard disk image files (if previously open) */ - for (d = 0; d < (IDE_NUM+XTIDE_NUM); d++) - { - ide_drives[d].channel = d; - ide_drives[d].type = IDE_NONE; - if (ide_drives[d].hdd_num != -1) - hdd_image_close(ide_drives[d].hdd_num); - if ((d < 8) && ide_drive_is_zip(&ide_drives[d])) - { - zip[atapi_zip_drives[d]].status = READY_STAT | DSC_STAT; - } - else if ((d < 8) && ide_drive_is_cdrom(&ide_drives[d])) - { - cdrom[atapi_cdrom_drives[d]]->status = READY_STAT | DSC_STAT; - } - ide_drives[d].atastat = READY_STAT | DSC_STAT; - ide_drives[d].service = 0; - ide_drives[d].board = d >> 1; - - if (ide_drives[d].buffer) { - free(ide_drives[d].buffer); - ide_drives[d].buffer = NULL; - } - - if (ide_drives[d].sector_buffer) { - free(ide_drives[d].sector_buffer); - ide_drives[d].sector_buffer = NULL; - } - } - - idecallback[0]=idecallback[1]=0LL; - idecallback[2]=idecallback[3]=0LL; - idecallback[4]=0LL; - - ide_log("IDE: loading disks...\n"); - c = 0; - for (d = 0; d < HDD_NUM; d++) - { - if (((hdd[d].bus == HDD_BUS_IDE_PIO_ONLY) || (hdd[d].bus == HDD_BUS_IDE_PIO_AND_DMA)) && (hdd[d].ide_channel < IDE_NUM)) - { - ide_log("Found IDE hard disk on channel %i\n", hdd[d].ide_channel); - loadhd(&ide_drives[hdd[d].ide_channel], d, hdd[d].fn); - ide_drives[hdd[d].ide_channel].sector_buffer = (uint8_t *) malloc(256*512); - memset(ide_drives[hdd[d].ide_channel].sector_buffer, 0, 256*512); - if (++c >= (IDE_NUM+XTIDE_NUM)) break; - } - if ((hdd[d].bus==HDD_BUS_XTIDE) && (hdd[d].xtide_channel < XTIDE_NUM)) - { - ide_log("Found XT IDE hard disk on channel %i\n", hdd[d].xtide_channel); - loadhd(&ide_drives[hdd[d].xtide_channel | 8], d, hdd[d].fn); - ide_drives[hdd[d].xtide_channel | 8].sector_buffer = (uint8_t *) malloc(256*512); - memset(ide_drives[hdd[d].ide_channel].sector_buffer, 0, 256*512); - if (++c >= (IDE_NUM+XTIDE_NUM)) break; - } - } - ide_log("IDE: done, loaded %d disks.\n", c); - - for (d = 0; d < IDE_NUM; d++) - { - if (ide_drive_is_zip(&ide_drives[d]) && (ide_drives[d].type == IDE_NONE)) - ide_drives[d].type = IDE_ZIP; - else if (ide_drive_is_cdrom(&ide_drives[d]) && (ide_drives[d].type == IDE_NONE)) - ide_drives[d].type = IDE_CDROM; - - if (ide_drives[d].type != IDE_NONE) { - ide_drives[d].buffer = (uint16_t *) malloc(65536 * sizeof(uint16_t)); - memset(ide_drives[d].buffer, 0, 65536 * sizeof(uint16_t)); - } - - ide_set_signature(&ide_drives[d]); - - ide_drives[d].mdma_mode = -1; - ide_drives[d].error = 1; - } - - for (d = 0; d < XTIDE_NUM; d++) - { - ide_set_signature(&ide_drives[d | 8]); - - ide_drives[d | 8].mdma_mode = -1; - ide_drives[d | 8].error = 1; - } - - for (d = 0; d < 5; d++) - { - cur_ide[d] = d << 1; - } - - ide_ter_disable_cond(); - ide_qua_disable_cond(); + return 1; } -void ide_set_all_signatures(void) +void +ide_set_sector(ide_t *ide, int64_t sector_num) { - int d; - - for (d = 0; d < IDE_NUM; d++) - { - ide_set_signature(&ide_drives[d]); - - if (ide_drives[d].sector_buffer) - memset(ide_drives[d].sector_buffer, 0, 256*512); - - if (ide_drives[d].buffer) - memset(ide_drives[d].buffer, 0, 65536 * sizeof(uint16_t)); - } + unsigned int cyl, r; + if (ide->lba) { + ide->head = (sector_num >> 24); + ide->cylinder = (sector_num >> 8); + ide->sector = (sector_num); + } else { + cyl = sector_num / (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); + r = sector_num % (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); + ide->cylinder = cyl; + ide->head = ((r / hdd[ide->hdd_num].spt) & 0x0f); + ide->sector = (r % hdd[ide->hdd_num].spt) + 1; + } } -void ide_reset_hard(void) +static void +ide_zero(int d) { - int d; + ide_t *dev; + ide_drives[d] = (ide_t *) malloc(sizeof(ide_t)); + memset(ide_drives[d], 0, sizeof(ide_t)); + dev = ide_drives[d]; + dev->channel = d; + dev->type = IDE_NONE; + dev->hdd_num = -1; + dev->atastat = DRDY_STAT | DSC_STAT; + dev->service = 0; + dev->board = d >> 1; +} - for (d = 0; d < (IDE_NUM+XTIDE_NUM); d++) - { - ide_drives[d].t_spt = ide_drives[d].spt; - ide_drives[d].t_hpc = ide_drives[d].hpc; - ide_drives[d].specify_success = 0; + +static void +ide_board_close(int board) +{ + ide_t *dev; + int c, d; + + /* Close hard disk image files (if previously open) */ + for (d = 0; d < 2; d++) { + c = (board << 1) + d; + dev = ide_drives[c]; + + if ((dev->type == IDE_HDD) && (dev->hdd_num != -1)) + hdd_image_close(dev->hdd_num); + + if (board < 4) { + if (ide_drive_is_zip(dev)) + zip[atapi_zip_drives[c]]->status = DRDY_STAT | DSC_STAT; + else if (ide_drive_is_cdrom(dev)) + cdrom[atapi_cdrom_drives[c]]->status = DRDY_STAT | DSC_STAT; } - ide_reset(); + if (dev->buffer) + free(dev->buffer); + + if (dev->sector_buffer) + free(dev->sector_buffer); + + if (dev) + free(dev); + } } -int idetimes = 0; - -void ide_set_callback(uint8_t channel, int64_t callback) +static void +ide_board_init(int board) { - IDE *ide = &ide_drives[channel]; - if (callback) - idecallback[ide->board] += callback; - else - idecallback[ide->board] = 0LL; + ide_t *dev; + int c, d; + int max, ch; + int is_ide, valid_ch; + int min_ch, max_ch; + + min_ch = (board << 1); + max_ch = min_ch + 1; + + ide_log("IDE: board %i: loading disks...\n", board); + for (d = 0; d < 2; d++) { + c = (board << 1) + d; + ide_zero(c); + } + + c = 0; + for (d = 0; d < HDD_NUM; d++) { + is_ide = (hdd[d].bus == HDD_BUS_IDE); + ch = hdd[d].ide_channel; + + if (board == 4) { + valid_ch = ((ch >= 0) && (ch <= 1)); + ch |= 8; + } else + valid_ch = ((ch >= min_ch) && (ch <= max_ch)); + + if (is_ide && valid_ch) { + ide_log("Found IDE hard disk on channel %i\n", ch); + loadhd(ide_drives[ch], d, hdd[d].fn); + ide_drives[ch]->sector_buffer = (uint8_t *) malloc(256*512); + memset(ide_drives[ch]->sector_buffer, 0, 256*512); + if (++c >= 2) break; + } + } + ide_log("IDE: board %i: done, loaded %d disks.\n", board, c); + + for (d = 0; d < 2; d++) { + c = (board << 1) + d; + dev = ide_drives[c]; + + if (board < 4) { + if (ide_drive_is_zip(dev) && (dev->type == IDE_NONE)) + dev->type = IDE_ZIP; + else if (ide_drive_is_cdrom(dev) && (dev->type == IDE_NONE)) + dev->type = IDE_CDROM; + } + + if (dev->type != IDE_NONE) { + dev->buffer = (uint16_t *) malloc(65536 * sizeof(uint16_t)); + memset(dev->buffer, 0, 65536 * sizeof(uint16_t)); + } + + ide_set_signature(dev); + + max = ide_get_max(dev, TYPE_PIO); + dev->mdma_mode = (1 << max); + dev->error = 1; + dev->cfg_spt = dev->cfg_hpc = 0; + } } -void ide_write_data(int ide_board, uint32_t val, int length) + +void +ide_set_callback(uint8_t board, int64_t callback) { - IDE *ide = &ide_drives[cur_ide[ide_board]]; + ide_board_t *dev = ide_boards[board]; - uint8_t *idebufferb = (uint8_t *) ide->buffer; - uint16_t *idebufferw = ide->buffer; - uint32_t *idebufferl = (uint32_t *) ide->buffer; - - if (ide->command == WIN_PACKETCMD) - { - ide->pos = 0; + ide_log("ide_set_callback(%i)\n", board); - if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) - { - return; - } + if (!dev) { + ide_log("Set callback failed\n"); + return; + } - if (ide_drive_is_zip(ide)) - zip_write(cur_ide[ide_board], val, length); - else - cdrom_write(cur_ide[ide_board], val, length); + if (callback) + dev->callback = callback; + else + dev->callback = 0LL; +} + + +void +ide_write_data(ide_t *ide, uint32_t val, int length) +{ + int ch = ide->channel; + + uint8_t *idebufferb = (uint8_t *) ide->buffer; + uint16_t *idebufferw = ide->buffer; + uint32_t *idebufferl = (uint32_t *) ide->buffer; + + if (ide->command == WIN_PACKETCMD) { + ide->pos = 0; + + if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) return; - } + + if (ide_drive_is_zip(ide)) + zip_write(ch, val, length); else - { - switch(length) - { - case 1: - idebufferb[ide->pos] = val & 0xff; - ide->pos++; - break; - case 2: - idebufferw[ide->pos >> 1] = val & 0xffff; - ide->pos += 2; - break; - case 4: - idebufferl[ide->pos >> 2] = val; - ide->pos += 4; - break; - default: - return; - } - - if (ide->pos>=512) - { - ide->pos=0; - ide->atastat = BUSY_STAT; - timer_process(); - if (ide->command == WIN_WRITE_MULTIPLE) - { - callbackide(ide_board); - } - else - { - idecallback[ide_board]=6LL*IDE_TIME; - } - timer_update_outstanding(); - } + cdrom_write(ch, val, length); + return; + } else { + switch(length) { + case 1: + idebufferb[ide->pos] = val & 0xff; + ide->pos++; + break; + case 2: + idebufferw[ide->pos >> 1] = val & 0xffff; + ide->pos += 2; + break; + case 4: + idebufferl[ide->pos >> 2] = val; + ide->pos += 4; + break; + default: + return; } + + if (ide->pos>=512) { + ide->pos=0; + ide->atastat = BSY_STAT; + timer_process(); + if (ide->command == WIN_WRITE_MULTIPLE) + ide_callback(ide_boards[ide->board]); + else + ide_set_callback(ide->board, ide_get_period(ide, 512)); + timer_update_outstanding(); + } + } } -void writeidew(int ide_board, uint16_t val) + +void +ide_writew(uint16_t addr, uint16_t val, void *priv) { - ide_write_data(ide_board, val, 2); + ide_board_t *dev = (ide_board_t *) priv; + + ide_t *ide; + int ch; + + ch = dev->cur_dev; + ide = ide_drives[ch]; + + /* ide_log("ide_writew %04X %04X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); */ + + addr &= 0x7; + + if ((ide->type == IDE_NONE) && ((addr == 0x0) || (addr == 0x7))) + return; + + switch (addr) { + case 0x0: /* Data */ + ide_write_data(ide, val, 2); + break; + } } -void writeidel(int ide_board, uint32_t val) + +static void +ide_writel(uint16_t addr, uint32_t val, void *priv) { - writeidew(ide_board, val); - writeidew(ide_board, val >> 16); + ide_board_t *dev = (ide_board_t *) priv; + + ide_t *ide; + int ch; + + ch = dev->cur_dev; + ide = ide_drives[ch]; + + /* ide_log("ide_writel %04X %08X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); */ + + addr &= 0x7; + + if ((ide->type == IDE_NONE) && ((addr == 0x0) || (addr == 0x7))) + return; + + switch (addr) { + case 0x0: /* Data */ + ide_write_data(ide, val & 0xffff, 2); + ide_write_data(ide, val >> 16, 2); + break; + } } -void writeide(int ide_board, uint16_t addr, uint8_t val) + +void +ide_write_devctl(uint16_t addr, uint8_t val, void *priv) { - IDE *ide = &ide_drives[cur_ide[ide_board]]; - IDE *ide_other = &ide_drives[cur_ide[ide_board] ^ 1]; + ide_board_t *dev = (ide_board_t *) priv; - ide_log("WriteIDE %04X %02X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); - addr|=0x90; - addr&=0xFFF7; + ide_t *ide, *ide_other; + int ch; - if (ide->type == IDE_NONE && (addr == 0x1f0 || addr == 0x1f7)) return; - - switch (addr) - { - case 0x1F0: /* Data */ - writeidew(ide_board, val | (val << 8)); - return; + ch = dev->cur_dev; + ide = ide_drives[ch]; + ide_other = ide_drives[ch ^ 1]; - /* Note to self: for ATAPI, bit 0 of this is DMA if set, PIO if clear. */ - case 0x1F1: /* Features */ - if (ide_drive_is_zip(ide)) - { - ide_log("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO"); - zip[atapi_zip_drives[cur_ide[ide_board]]].features = val; - } - else if (ide_drive_is_cdrom(ide)) - { - ide_log("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO"); - cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->features = val; - } - ide->cylprecomp = val; + ide_log("ide_write_devctl %04X %02X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); - if (ide_drive_is_zip(ide_other)) - { - zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].features = val; - } - else if (ide_drive_is_cdrom(ide_other)) - { - cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]]->features = val; - } - ide_other->cylprecomp = val; - return; + if ((ide->fdisk & 4) && !(val&4) && (ide->type != IDE_NONE || ide_other->type != IDE_NONE)) { + timer_process(); + if (ide_drive_is_zip(ide)) + zip[atapi_zip_drives[ide->channel]]->callback = 0LL; + else if (ide_drive_is_cdrom(ide)) + cdrom[atapi_cdrom_drives[ide->channel]]->callback = 0LL; + ide_set_callback(ide->board, 500LL * IDE_TIME); + timer_update_outstanding(); - case 0x1F2: /* Sector count */ - if (ide_drive_is_zip(ide)) - { - ide_log("Sector count write: %i\n", val); - zip[atapi_zip_drives[cur_ide[ide_board]]].phase = val; - } - else if (ide_drive_is_cdrom(ide)) - { - ide_log("Sector count write: %i\n", val); - cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->phase = val; - } - ide->secount = val; + if (ide->type != IDE_NONE) + ide->reset = 1; + if (ide_other->type != IDE_NONE) + ide->reset = 1; + if (ide_drive_is_zip(ide)) + zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; + else if (ide_drive_is_cdrom(ide)) + cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; + ide->atastat = ide_other->atastat = BSY_STAT; + } - if (ide_drive_is_zip(ide_other)) - { - ide_log("Other sector count write: %i\n", val); - zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].phase = val; - } - else if (ide_drive_is_cdrom(ide_other)) - { - ide_log("Other sector count write: %i\n", val); - cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]]->phase = val; - } - ide_other->secount = val; - return; + if (val & 4) { + /*Drive held in reset*/ + timer_process(); + ide_set_callback(ide->board, 0LL); + timer_update_outstanding(); + ide->atastat = ide_other->atastat = BSY_STAT; + } + ide->fdisk = ide_other->fdisk = val; + return; +} - case 0x1F3: /* Sector */ - ide->sector = val; - ide->lba_addr = (ide->lba_addr & 0xFFFFF00) | val; - ide_other->sector = val; - ide_other->lba_addr = (ide_other->lba_addr & 0xFFFFF00) | val; - return; - case 0x1F4: /* Cylinder low */ - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[cur_ide[ide_board]]].request_length &= 0xFF00; - zip[atapi_zip_drives[cur_ide[ide_board]]].request_length |= val; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->request_length &= 0xFF00; - cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->request_length |= val; - } - ide->cylinder = (ide->cylinder & 0xFF00) | val; - ide->lba_addr = (ide->lba_addr & 0xFFF00FF) | (val << 8); +void +ide_writeb(uint16_t addr, uint8_t val, void *priv) +{ + ide_board_t *dev = (ide_board_t *) priv; - if (ide_drive_is_zip(ide_other)) - { - zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].request_length &= 0xFF00; - zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].request_length |= val; - } - else if (ide_drive_is_cdrom(ide_other)) - { - cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]]->request_length &= 0xFF00; - cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]]->request_length |= val; - } - ide_other->cylinder = (ide_other->cylinder&0xFF00) | val; - ide_other->lba_addr = (ide_other->lba_addr&0xFFF00FF) | (val << 8); - return; + ide_t *ide, *ide_other; + int ch; - case 0x1F5: /* Cylinder high */ - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[cur_ide[ide_board]]].request_length &= 0xFF; - zip[atapi_zip_drives[cur_ide[ide_board]]].request_length |= (val << 8); - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->request_length &= 0xFF; - cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->request_length |= (val << 8); - } - ide->cylinder = (ide->cylinder & 0xFF) | (val << 8); - ide->lba_addr = (ide->lba_addr & 0xF00FFFF) | (val << 16); + ch = dev->cur_dev; + ide = ide_drives[ch]; + ide_other = ide_drives[ch ^ 1]; - if (ide_drive_is_zip(ide_other)) - { - zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].request_length &= 0xFF; - zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].request_length |= (val << 8); - } - else if (ide_drive_is_cdrom(ide_other)) - { - cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]]->request_length &= 0xFF; - cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]]->request_length |= (val << 8); - } - ide_other->cylinder = (ide_other->cylinder & 0xFF) | (val << 8); - ide_other->lba_addr = (ide_other->lba_addr & 0xF00FFFF) | (val << 16); - return; + ide_log("ide_write %04X %02X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); - case 0x1F6: /* Drive/Head */ - if (cur_ide[ide_board] != ((val>>4)&1)+(ide_board<<1)) - { - cur_ide[ide_board]=((val>>4)&1)+(ide_board<<1); + addr &= 0x7; - if (ide->reset || ide_other->reset) - { - ide->atastat = ide_other->atastat = READY_STAT | DSC_STAT; - ide->error = ide_other->error = 1; - ide->secount = ide_other->secount = 1; - ide->sector = ide_other->sector = 1; - ide->head = ide_other->head = 0; - ide->cylinder = ide_other->cylinder = 0; - ide->reset = ide_other->reset = 0; + if ((ide->type == IDE_NONE) && ((addr == 0x0) || (addr == 0x7))) + return; - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = READY_STAT | DSC_STAT; - zip[atapi_zip_drives[ide->channel]].error = 1; - zip[atapi_zip_drives[ide->channel]].phase = 1; - zip[atapi_zip_drives[ide->channel]].request_length = 0xEB14; - zip[atapi_zip_drives[ide->channel]].callback = 0LL; - ide->cylinder = 0xEB14; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = READY_STAT | DSC_STAT; - cdrom[atapi_cdrom_drives[ide->channel]]->error = 1; - cdrom[atapi_cdrom_drives[ide->channel]]->phase = 1; - cdrom[atapi_cdrom_drives[ide->channel]]->request_length = 0xEB14; - cdrom[atapi_cdrom_drives[ide->channel]]->callback = 0LL; - ide->cylinder = 0xEB14; - } + switch (addr) { + case 0x0: /* Data */ + ide_write_data(ide, val | (val << 8), 2); + return; - if (ide_drive_is_zip(ide_other)) - { - zip[atapi_zip_drives[ide_other->channel]].status = READY_STAT | DSC_STAT; - zip[atapi_zip_drives[ide_other->channel]].error = 1; - zip[atapi_zip_drives[ide_other->channel]].phase = 1; - zip[atapi_zip_drives[ide_other->channel]].request_length = 0xEB14; - zip[atapi_zip_drives[ide_other->channel]].callback = 0LL; - ide->cylinder = 0xEB14; - } - else if (ide_drive_is_cdrom(ide_other)) - { - cdrom[atapi_cdrom_drives[ide_other->channel]]->status = READY_STAT | DSC_STAT; - cdrom[atapi_cdrom_drives[ide_other->channel]]->error = 1; - cdrom[atapi_cdrom_drives[ide_other->channel]]->phase = 1; - cdrom[atapi_cdrom_drives[ide_other->channel]]->request_length = 0xEB14; - cdrom[atapi_cdrom_drives[ide_other->channel]]->callback = 0LL; - ide->cylinder = 0xEB14; - } + /* Note to self: for ATAPI, bit 0 of this is DMA if set, PIO if clear. */ + case 0x1: /* Features */ + if (ide_drive_is_zip(ide)) { + ide_log("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO"); + zip[atapi_zip_drives[ch]]->features = val; + } else if (ide_drive_is_cdrom(ide)) { + ide_log("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO"); + cdrom[atapi_cdrom_drives[ch]]->features = val; + } + ide->cylprecomp = val; - idecallback[ide_board] = 0LL; - timer_update_outstanding(); - return; + if (ide_drive_is_zip(ide_other)) + zip[atapi_zip_drives[ch ^ 1]]->features = val; + else if (ide_drive_is_cdrom(ide_other)) + cdrom[atapi_cdrom_drives[ch ^ 1]]->features = val; + ide_other->cylprecomp = val; + return; + + case 0x2: /* Sector count */ + if (ide_drive_is_zip(ide)) { + ide_log("Sector count write: %i\n", val); + zip[atapi_zip_drives[ch]]->phase = val; + } else if (ide_drive_is_cdrom(ide)) { + ide_log("Sector count write: %i\n", val); + cdrom[atapi_cdrom_drives[ch]]->phase = val; + } + ide->secount = val; + + if (ide_drive_is_zip(ide_other)) { + ide_log("Other sector count write: %i\n", val); + zip[atapi_zip_drives[ch ^ 1]]->phase = val; + } else if (ide_drive_is_cdrom(ide_other)) { + ide_log("Other sector count write: %i\n", val); + cdrom[atapi_cdrom_drives[ch ^ 1]]->phase = val; + } + ide_other->secount = val; + return; + + case 0x3: /* Sector */ + ide->sector = val; + ide->lba_addr = (ide->lba_addr & 0xFFFFF00) | val; + ide_other->sector = val; + ide_other->lba_addr = (ide_other->lba_addr & 0xFFFFF00) | val; + return; + + case 0x4: /* Cylinder low */ + if (ide_drive_is_zip(ide)) { + zip[atapi_zip_drives[ch]]->request_length &= 0xFF00; + zip[atapi_zip_drives[ch]]->request_length |= val; + } else if (ide_drive_is_cdrom(ide)) { + cdrom[atapi_cdrom_drives[ch]]->request_length &= 0xFF00; + cdrom[atapi_cdrom_drives[ch]]->request_length |= val; + } + ide->cylinder = (ide->cylinder & 0xFF00) | val; + ide->lba_addr = (ide->lba_addr & 0xFFF00FF) | (val << 8); + + if (ide_drive_is_zip(ide_other)) { + zip[atapi_zip_drives[ch ^ 1]]->request_length &= 0xFF00; + zip[atapi_zip_drives[ch ^ 1]]->request_length |= val; + } else if (ide_drive_is_cdrom(ide_other)) { + cdrom[atapi_cdrom_drives[ch ^ 1]]->request_length &= 0xFF00; + cdrom[atapi_cdrom_drives[ch ^ 1]]->request_length |= val; + } + ide_other->cylinder = (ide_other->cylinder & 0xFF00) | val; + ide_other->lba_addr = (ide_other->lba_addr & 0xFFF00FF) | (val << 8); + return; + + case 0x5: /* Cylinder high */ + if (ide_drive_is_zip(ide)) { + zip[atapi_zip_drives[ch]]->request_length &= 0xFF; + zip[atapi_zip_drives[ch]]->request_length |= (val << 8); + } else if (ide_drive_is_cdrom(ide)) { + cdrom[atapi_cdrom_drives[ch]]->request_length &= 0xFF; + cdrom[atapi_cdrom_drives[ch]]->request_length |= (val << 8); + } + ide->cylinder = (ide->cylinder & 0xFF) | (val << 8); + ide->lba_addr = (ide->lba_addr & 0xF00FFFF) | (val << 16); + + if (ide_drive_is_zip(ide_other)) { + zip[atapi_zip_drives[ch ^ 1]]->request_length &= 0xFF; + zip[atapi_zip_drives[ch ^ 1]]->request_length |= (val << 8); + } else if (ide_drive_is_cdrom(ide_other)) { + cdrom[atapi_cdrom_drives[ch ^ 1]]->request_length &= 0xFF; + cdrom[atapi_cdrom_drives[ch ^ 1]]->request_length |= (val << 8); + } + ide_other->cylinder = (ide_other->cylinder & 0xFF) | (val << 8); + ide_other->lba_addr = (ide_other->lba_addr & 0xF00FFFF) | (val << 16); + return; + + case 0x6: /* Drive/Head */ + if (ch != ((val >> 4) & 1) + (ide->board << 1)) { + ide_boards[ide->board]->cur_dev = ((val >> 4) & 1) + (ide->board << 1); + ch = ide_boards[ide->board]->cur_dev; + + if (ide->reset || ide_other->reset) { + ide->atastat = ide_other->atastat = DRDY_STAT | DSC_STAT; + ide->error = ide_other->error = 1; + ide->secount = ide_other->secount = 1; + ide->sector = ide_other->sector = 1; + ide->head = ide_other->head = 0; + ide->cylinder = ide_other->cylinder = 0; + ide->reset = ide_other->reset = 0; + + if (ide_drive_is_zip(ide)) { + zip[atapi_zip_drives[ide->channel]]->status = DRDY_STAT | DSC_STAT; + zip[atapi_zip_drives[ide->channel]]->error = 1; + zip[atapi_zip_drives[ide->channel]]->phase = 1; + zip[atapi_zip_drives[ide->channel]]->request_length = 0xEB14; + zip[atapi_zip_drives[ide->channel]]->callback = 0LL; + ide->cylinder = 0xEB14; + } else if (ide_drive_is_cdrom(ide)) { + cdrom[atapi_cdrom_drives[ide->channel]]->status = DRDY_STAT | DSC_STAT; + cdrom[atapi_cdrom_drives[ide->channel]]->error = 1; + cdrom[atapi_cdrom_drives[ide->channel]]->phase = 1; + cdrom[atapi_cdrom_drives[ide->channel]]->request_length = 0xEB14; + cdrom[atapi_cdrom_drives[ide->channel]]->callback = 0LL; + ide->cylinder = 0xEB14; } - ide = &ide_drives[cur_ide[ide_board]]; - } - - ide->head = val & 0xF; - ide->lba = val & 0x40; - ide_other->head = val & 0xF; - ide_other->lba = val & 0x40; - - ide->lba_addr = (ide->lba_addr & 0x0FFFFFF) | ((val & 0xF) << 24); - ide_other->lba_addr = (ide_other->lba_addr & 0x0FFFFFF)|((val & 0xF) << 24); + if (ide_drive_is_zip(ide_other)) { + zip[atapi_zip_drives[ide_other->channel]]->status = DRDY_STAT | DSC_STAT; + zip[atapi_zip_drives[ide_other->channel]]->error = 1; + zip[atapi_zip_drives[ide_other->channel]]->phase = 1; + zip[atapi_zip_drives[ide_other->channel]]->request_length = 0xEB14; + zip[atapi_zip_drives[ide_other->channel]]->callback = 0LL; + ide->cylinder = 0xEB14; + } else if (ide_drive_is_cdrom(ide_other)) { + cdrom[atapi_cdrom_drives[ide_other->channel]]->status = DRDY_STAT | DSC_STAT; + cdrom[atapi_cdrom_drives[ide_other->channel]]->error = 1; + cdrom[atapi_cdrom_drives[ide_other->channel]]->phase = 1; + cdrom[atapi_cdrom_drives[ide_other->channel]]->request_length = 0xEB14; + cdrom[atapi_cdrom_drives[ide_other->channel]]->callback = 0LL; + ide->cylinder = 0xEB14; + } - return; - - case 0x1F7: /* Command register */ - if (ide->type == IDE_NONE) - { + ide_set_callback(ide->board, 0LL); + timer_update_outstanding(); return; } + ide = ide_drives[ch]; + } + + ide->head = val & 0xF; + ide->lba = val & 0x40; + ide_other->head = val & 0xF; + ide_other->lba = val & 0x40; + + ide->lba_addr = (ide->lba_addr & 0x0FFFFFF) | ((val & 0xF) << 24); + ide_other->lba_addr = (ide_other->lba_addr & 0x0FFFFFF)|((val & 0xF) << 24); + return; + + case 0x7: /* Command register */ + if (ide->type == IDE_NONE) + return; + ide_irq_lower(ide); ide->command=val; ide->error=0; if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].error = 0; - } + zip[atapi_zip_drives[ide->channel]]->error = 0; else if (ide_drive_is_cdrom(ide)) - { cdrom[atapi_cdrom_drives[ide->channel]]->error = 0; - } - if (((val >= WIN_RESTORE) && (val <= 0x1F)) || ((val >= WIN_SEEK) && (val <= 0x7F))) - { + + if (((val >= WIN_RECAL) && (val <= 0x1F)) || ((val >= WIN_SEEK) && (val <= 0x7F))) { if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = READY_STAT; - } + zip[atapi_zip_drives[ide->channel]]->status = DRDY_STAT; else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = READY_STAT; - } + cdrom[atapi_cdrom_drives[ide->channel]]->status = DRDY_STAT; else - { - ide->atastat = BUSY_STAT; - } + ide->atastat = BSY_STAT; timer_process(); + if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].callback = 100LL*IDE_TIME; - } - if (ide_drive_is_cdrom(ide)) - { + zip[atapi_zip_drives[ide->channel]]->callback = 100LL*IDE_TIME; + else if (ide_drive_is_cdrom(ide)) cdrom[atapi_cdrom_drives[ide->channel]]->callback = 100LL*IDE_TIME; - } - idecallback[ide_board]=40000LL * TIMER_USEC /*100LL*IDE_TIME*/; + ide_set_callback(ide->board, 100LL * IDE_TIME); timer_update_outstanding(); return; } - switch (val) - { + + switch (val) { case WIN_SRST: /* ATAPI Device Reset */ if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; - } + zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = BUSY_STAT; - } + cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; else - { - ide->atastat = READY_STAT; - } + ide->atastat = DRDY_STAT; timer_process(); + if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].callback = 100LL*IDE_TIME; - } + zip[atapi_zip_drives[ide->channel]]->callback = 100LL*IDE_TIME; else if (ide_drive_is_cdrom(ide)) - { cdrom[atapi_cdrom_drives[ide->channel]]->callback = 100LL*IDE_TIME; - } - idecallback[ide_board]=100LL*IDE_TIME; - timer_update_outstanding(); - return; + ide_set_callback(ide->board, 100LL * IDE_TIME); + timer_update_outstanding(); + return; case WIN_READ_MULTIPLE: /* Fatal removed in accordance with the official ATAPI reference: @@ -1314,124 +1481,99 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) disabled, the Read Multiple operation is rejected with an Aborted Com- mand error. */ ide->blockcount = 0; + /* Turn on the activity indicator *here* so that it gets turned on + less times. */ + /* ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); */ case WIN_READ: case WIN_READ_NORETRY: case WIN_READ_DMA: case WIN_READ_DMA_ALT: if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; - } + zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = BUSY_STAT; - } + cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; else - { - ide->atastat = BUSY_STAT; - } + ide->atastat = BSY_STAT; timer_process(); + if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].callback = 200LL*IDE_TIME; - } + zip[atapi_zip_drives[ide->channel]]->callback = 200LL*IDE_TIME; else if (ide_drive_is_cdrom(ide)) - { cdrom[atapi_cdrom_drives[ide->channel]]->callback = 200LL*IDE_TIME; - } - idecallback[ide_board]=200LL*IDE_TIME; + if (ide->type == IDE_HDD) { + if ((val == WIN_READ_DMA) || (val == WIN_READ_DMA_ALT)) { + if (ide->secount) + ide_set_callback(ide->board, ide_get_period(ide, (int) ide->secount << 9)); + else + ide_set_callback(ide->board, ide_get_period(ide, 131072)); + } else + ide_set_callback(ide->board, ide_get_period(ide, 512)); + } else + ide_set_callback(ide->board, 200LL * IDE_TIME); timer_update_outstanding(); ide->do_initial_read = 1; return; case WIN_WRITE_MULTIPLE: if (!ide->blocksize && !ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) - { fatal("Write_MULTIPLE - blocksize = 0\n"); - } ide->blockcount = 0; + /* Turn on the activity indicator *here* so that it gets turned on + less times. */ + /* ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); */ case WIN_WRITE: case WIN_WRITE_NORETRY: - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = DRQ_STAT | DSC_STAT | READY_STAT; - zip[atapi_zip_drives[ide->channel]].pos = 0; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = DRQ_STAT | DSC_STAT | READY_STAT; + if (ide_drive_is_zip(ide)) { + zip[atapi_zip_drives[ide->channel]]->status = DRQ_STAT | DSC_STAT | DRDY_STAT; + zip[atapi_zip_drives[ide->channel]]->pos = 0; + } else if (ide_drive_is_cdrom(ide)) { + cdrom[atapi_cdrom_drives[ide->channel]]->status = DRQ_STAT | DSC_STAT | DRDY_STAT; cdrom[atapi_cdrom_drives[ide->channel]]->pos = 0; - } - else - { - ide->atastat = DRQ_STAT | DSC_STAT | READY_STAT; + } else { + ide->atastat = DRQ_STAT | DSC_STAT | DRDY_STAT; ide->pos=0; } return; case WIN_WRITE_DMA: case WIN_WRITE_DMA_ALT: - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = BUSY_STAT; - } - else - { - ide->atastat = BUSY_STAT; - } - timer_process(); - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].callback = 200LL*IDE_TIME; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->callback = 200LL*IDE_TIME; - } - idecallback[ide_board]=200LL*IDE_TIME; - timer_update_outstanding(); - return; - case WIN_VERIFY: case WIN_VERIFY_ONCE: + case WIN_IDENTIFY: /* Identify Device */ + case WIN_SET_FEATURES: /* Set Features */ + case WIN_READ_NATIVE_MAX: if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; - } + zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = BUSY_STAT; - } + cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; else - { - ide->atastat = BUSY_STAT; - } + ide->atastat = BSY_STAT; timer_process(); + if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].callback = 200LL*IDE_TIME; - } + zip[atapi_zip_drives[ide->channel]]->callback = 200LL*IDE_TIME; else if (ide_drive_is_cdrom(ide)) - { cdrom[atapi_cdrom_drives[ide->channel]]->callback = 200LL*IDE_TIME; - } - idecallback[ide_board]=200LL*IDE_TIME; + if ((ide->type == IDE_HDD) && + ((val == WIN_WRITE_DMA) || (val == WIN_WRITE_DMA_ALT))) { + if (ide->secount) + ide_set_callback(ide->board, ide_get_period(ide, (int) ide->secount << 9)); + else + ide_set_callback(ide->board, ide_get_period(ide, 131072)); + } else if ((ide->type == IDE_HDD) && + ((val == WIN_VERIFY) || (val == WIN_VERIFY_ONCE))) + ide_set_callback(ide->board, ide_get_period(ide, 512)); + else + ide_set_callback(ide->board, 200LL * IDE_TIME); timer_update_outstanding(); return; case WIN_FORMAT: if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { goto ide_bad_command; - } - else - { + else { ide->atastat = DRQ_STAT; ide->pos=0; } @@ -1439,51 +1581,42 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_SPECIFY: /* Initialize Drive Parameters */ if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; - } + zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = BUSY_STAT; - } + cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; else - { - ide->atastat = BUSY_STAT; - } + ide->atastat = BSY_STAT; timer_process(); + if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].callback = 30LL*IDE_TIME; - } + zip[atapi_zip_drives[ide->channel]]->callback = 30LL*IDE_TIME; else if (ide_drive_is_cdrom(ide)) - { cdrom[atapi_cdrom_drives[ide->channel]]->callback = 30LL*IDE_TIME; - } - idecallback[ide_board]=30LL*IDE_TIME; + ide_set_callback(ide->board, 30LL * IDE_TIME); timer_update_outstanding(); return; case WIN_DRIVE_DIAGNOSTICS: /* Execute Drive Diagnostics */ if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; + zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->status = BUSY_STAT; + cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; else - ide->atastat = BUSY_STAT; + ide->atastat = BSY_STAT; if (ide_drive_is_zip(ide_other)) - zip[atapi_zip_drives[ide_other->channel]].status = BUSY_STAT; + zip[atapi_zip_drives[ide_other->channel]]->status = BSY_STAT; else if (ide_drive_is_cdrom(ide_other)) - cdrom[atapi_cdrom_drives[ide_other->channel]]->status = BUSY_STAT; + cdrom[atapi_cdrom_drives[ide_other->channel]]->status = BSY_STAT; else - ide_other->atastat = BUSY_STAT; + ide_other->atastat = BSY_STAT; timer_process(); if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]].callback = 200LL * IDE_TIME; + zip[atapi_zip_drives[ide->channel]]->callback = 200LL * IDE_TIME; else if (ide_drive_is_cdrom(ide)) cdrom[atapi_cdrom_drives[ide->channel]]->callback = 200LL * IDE_TIME; - idecallback[ide_board] = 200LL * IDE_TIME; + ide_set_callback(ide->board, 200LL * IDE_TIME); timer_update_outstanding(); return; @@ -1496,66 +1629,33 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_CHECKPOWERMODE1: case WIN_SLEEP1: if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; + zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->status = BUSY_STAT; + cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; else - ide->atastat = BUSY_STAT; + ide->atastat = BSY_STAT; timer_process(); - callbackide(ide_board); - timer_update_outstanding(); - return; - - case WIN_IDENTIFY: /* Identify Device */ - case WIN_SET_FEATURES: /* Set Features */ - case WIN_READ_NATIVE_MAX: - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = BUSY_STAT; - } - else - { - ide->atastat = BUSY_STAT; - } - timer_process(); - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].callback = 200LL*IDE_TIME; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->callback = 200LL*IDE_TIME; - } - idecallback[ide_board]=200LL*IDE_TIME; + ide_callback(dev); timer_update_outstanding(); return; case WIN_PACKETCMD: /* ATAPI Packet */ /* Skip the command callback wait, and process immediately. */ - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].packet_status = ZIP_PHASE_IDLE; - zip[atapi_zip_drives[ide->channel]].pos=0; - zip[atapi_zip_drives[ide->channel]].phase = 1; - zip[atapi_zip_drives[ide->channel]].status = READY_STAT | DRQ_STAT; - ide_irq_raise(ide); /* Interrupt IRQ, requires IRQ on any DRQ. */ - } - else if (ide_drive_is_cdrom(ide)) - { + if (ide_drive_is_zip(ide)) { + zip[atapi_zip_drives[ide->channel]]->packet_status = ZIP_PHASE_IDLE; + zip[atapi_zip_drives[ide->channel]]->pos=0; + zip[atapi_zip_drives[ide->channel]]->phase = 1; + zip[atapi_zip_drives[ide->channel]]->status = DRDY_STAT | DRQ_STAT; + ide_irq_raise(ide); /* Interrupt DRQ, requires IRQ on any DRQ. */ + } else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]]->packet_status = CDROM_PHASE_IDLE; cdrom[atapi_cdrom_drives[ide->channel]]->pos=0; cdrom[atapi_cdrom_drives[ide->channel]]->phase = 1; - cdrom[atapi_cdrom_drives[ide->channel]]->status = READY_STAT | DRQ_STAT; - } - else - { - ide->atastat = BUSY_STAT; + cdrom[atapi_cdrom_drives[ide->channel]]->status = DRDY_STAT | DRQ_STAT; + } else { + ide->atastat = BSY_STAT; timer_process(); - idecallback[ide_board]=200LL*IDE_TIME; + ide_set_callback(ide->board, 200LL * IDE_TIME); timer_update_outstanding(); ide->pos=0; } @@ -1564,1318 +1664,1063 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case 0xF0: default: ide_bad_command: - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = READY_STAT | ERR_STAT | DSC_STAT; - zip[atapi_zip_drives[ide->channel]].error = ABRT_ERR; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = READY_STAT | ERR_STAT | DSC_STAT; + if (ide_drive_is_zip(ide)) { + zip[atapi_zip_drives[ide->channel]]->status = DRDY_STAT | ERR_STAT | DSC_STAT; + zip[atapi_zip_drives[ide->channel]]->error = ABRT_ERR; + } else if (ide_drive_is_cdrom(ide)) { + cdrom[atapi_cdrom_drives[ide->channel]]->status = DRDY_STAT | ERR_STAT | DSC_STAT; cdrom[atapi_cdrom_drives[ide->channel]]->error = ABRT_ERR; - } - else - { - ide->atastat = READY_STAT | ERR_STAT | DSC_STAT; + } else { + ide->atastat = DRDY_STAT | ERR_STAT | DSC_STAT; ide->error = ABRT_ERR; } ide_irq_raise(ide); return; } return; - - case 0x3F6: /* Device control */ - if ((ide->fdisk & 4) && !(val&4) && (ide->type != IDE_NONE || ide_other->type != IDE_NONE)) - { - timer_process(); - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].callback = 0LL; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->callback = 0LL; - } - idecallback[ide_board]=500LL*IDE_TIME; - timer_update_outstanding(); - - if (ide->type != IDE_NONE) - { - ide->reset = 1; - } - if (ide_other->type != IDE_NONE) - { - ide->reset = 1; - } - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = BUSY_STAT; - } - ide->atastat = ide_other->atastat = BUSY_STAT; - } - if (val & 4) - { - /*Drive held in reset*/ - timer_process(); - idecallback[ide_board] = 0LL; - timer_update_outstanding(); - ide->atastat = ide_other->atastat = BUSY_STAT; - } - ide->fdisk = ide_other->fdisk = val; - return; - } + } } -uint32_t ide_read_data(int ide_board, int length) + +static uint32_t +ide_read_data(ide_t *ide, int length) { - IDE *ide = &ide_drives[cur_ide[ide_board]]; - uint32_t temp; - - if (!ide->buffer) { - switch (length) - { - case 1: - return 0xff; - case 2: - return 0xffff; - case 4: - return 0xffffffff; - default: - return 0; - } - } - - uint8_t *idebufferb = (uint8_t *) ide->buffer; - uint16_t *idebufferw = ide->buffer; - uint32_t *idebufferl = (uint32_t *) ide->buffer; - - if (ide->command == WIN_PACKETCMD) - { - ide->pos = 0; - if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) - { - ide_log("Drive not ZIP or CD-ROM (position: %i)\n", ide->pos); - return 0; - } - if (ide_drive_is_zip(ide)) - temp = zip_read(cur_ide[ide_board], length); - else - temp = cdrom_read(cur_ide[ide_board], length); - } - else - { - switch (length) - { - case 1: - temp = idebufferb[ide->pos]; - ide->pos++; - break; - case 2: - temp = idebufferw[ide->pos >> 1]; - ide->pos += 2; - break; - case 4: - temp = idebufferl[ide->pos >> 2]; - ide->pos += 4; - break; - default: - return 0; - } - } - if (ide->pos>=512 && ide->command != WIN_PACKETCMD) - { - ide->pos=0; - ide->atastat = READY_STAT | DSC_STAT; - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[cur_ide[ide_board]]].status = READY_STAT | DSC_STAT; - zip[atapi_zip_drives[cur_ide[ide_board]]].packet_status = ZIP_PHASE_IDLE; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->status = READY_STAT | DSC_STAT; - cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->packet_status = CDROM_PHASE_IDLE; - } - if (ide->command == WIN_READ || ide->command == WIN_READ_NORETRY || ide->command == WIN_READ_MULTIPLE) - { - ide->secount = (ide->secount - 1) & 0xff; - if (ide->secount) - { - ide_next_sector(ide); - ide->atastat = BUSY_STAT; - timer_process(); - if (ide->command == WIN_READ_MULTIPLE) - { - callbackide(ide_board); - } - else - { - idecallback[ide_board]=6LL*IDE_TIME; - } - timer_update_outstanding(); - } - else - { - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); - } - } - } - - return temp; -} - -uint8_t readide(int ide_board, uint16_t addr) -{ - IDE *ide = &ide_drives[cur_ide[ide_board]]; - uint8_t temp; - uint16_t tempw; - - addr |= 0x90; - addr &= 0xFFF7; - - switch (addr) - { - case 0x1F0: /* Data */ - tempw = readidew(ide_board); - temp = tempw & 0xff; - break; - - /* For ATAPI: Bits 7-4 = sense key, bit 3 = MCR (media change requested), - Bit 2 = ABRT (aborted command), Bit 1 = EOM (end of media), - and Bit 0 = ILI (illegal length indication). */ - case 0x1F1: /* Error */ - if (ide->type == IDE_NONE) - { - temp = 0; - } - else - { - if (ide_drive_is_zip(ide)) - { - temp = zip[atapi_zip_drives[cur_ide[ide_board]]].error; - } - else if (ide_drive_is_cdrom(ide)) - { - temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->error; - } - else - { - temp = ide->error; - } - } - break; - - /* For ATAPI: - Bit 0: Command or Data: - Data if clear, Command if set; - Bit 1: I/OB - Direction: - To device if set; - From device if clear. - IO DRQ CoD - 0 1 1 Ready to accept command packet - 1 1 1 Message - ready to send message to host - 1 1 0 Data to host - 0 1 0 Data from host - 1 0 1 Status. */ - case 0x1F2: /* Sector count */ - if (ide_drive_is_zip(ide)) - { - temp = zip[atapi_zip_drives[cur_ide[ide_board]]].phase; - } - else if (ide_drive_is_cdrom(ide)) - { - temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->phase; - } - else - { - temp = ide->secount; - } - break; - - case 0x1F3: /* Sector */ - temp = (uint8_t)ide->sector; - break; - - case 0x1F4: /* Cylinder low */ - if (ide->type == IDE_NONE) - { - temp = 0xFF; - } - else - { - if (ide_drive_is_zip(ide)) - { - temp = zip[atapi_zip_drives[cur_ide[ide_board]]].request_length & 0xff; - } - else if (ide_drive_is_cdrom(ide)) - { - temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->request_length & 0xff; - } - else - { - temp = ide->cylinder & 0xff; - } - } - break; - - case 0x1F5: /* Cylinder high */ - if (ide->type == IDE_NONE) - { - temp = 0xFF; - } - else - { - if (ide_drive_is_zip(ide)) - { - temp = zip[atapi_zip_drives[cur_ide[ide_board]]].request_length >> 8; - } - else if (ide_drive_is_cdrom(ide)) - { - temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->request_length >> 8; - } - else - { - temp = ide->cylinder >> 8; - } - } - break; - - case 0x1F6: /* Drive/Head */ - temp = (uint8_t)(ide->head | ((cur_ide[ide_board] & 1) ? 0x10 : 0) | (ide->lba ? 0x40 : 0) | 0xa0); - break; - - /* For ATAPI: Bit 5 is DMA ready, but without overlapped or interlaved DMA, it is - DF (drive fault). */ - case 0x1F7: /* Status */ - ide_irq_lower(ide); - if (ide->type == IDE_NONE) - { - temp = 0; - } - else - { - if (ide_drive_is_zip(ide)) - { - temp = (zip[atapi_zip_drives[cur_ide[ide_board]]].status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); - } - else if (ide_drive_is_cdrom(ide)) - { - temp = (cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); - } - else - { - temp = ide->atastat; - } - } - break; - - case 0x3F6: /* Alternate Status */ - if (ide->type == IDE_NONE) - { - temp = 0; - } - else - { - if (ide_drive_is_zip(ide)) - { - temp = (zip[atapi_zip_drives[cur_ide[ide_board]]].status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); - } - else if (ide_drive_is_cdrom(ide)) - { - temp = (cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); - } - else - { - temp = ide->atastat; - } - } - break; + int ch = ide->channel; + uint32_t temp; + if (!ide->buffer) { + switch (length) { + case 1: + return 0xff; + case 2: + return 0xffff; + case 4: + return 0xffffffff; default: - temp = 0xff; - break; + return 0; } - /* if (ide_board) */ ide_log("Read IDEb %04X %02X %02X %02X %i %04X:%04X %i\n", addr, temp, ide->atastat,(ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0),cur_ide[ide_board],CS,cpu_state.pc,ide_board); - return temp; -} + } -uint8_t cdb[16]; + uint8_t *idebufferb = (uint8_t *) ide->buffer; + uint16_t *idebufferw = ide->buffer; + uint32_t *idebufferl = (uint32_t *) ide->buffer; -int old_len = 0; - -int total_read = 0; - -int block_total = 0; -int all_blocks_total = 0; - -uint16_t readidew(int ide_board) -{ - return ide_read_data(ide_board, 2); -} - -uint32_t readidel(int ide_board) -{ - uint16_t temp; - temp = readidew(ide_board); - return temp | (readidew(ide_board) << 16); -} - -int times30=0; -void callbackide(int ide_board) -{ - IDE *ide, *ide_other; - int64_t snum; - int cdrom_id; - int cdrom_id_other; - int zip_id; - int zip_id_other; - uint64_t full_size = 0; - - ide = &ide_drives[cur_ide[ide_board]]; - ide_other = &ide_drives[cur_ide[ide_board] ^ 1]; - if (ide->type == IDE_HDD) - { - full_size = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); + if (ide->command == WIN_PACKETCMD) { + ide->pos = 0; + if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) { + ide_log("Drive not ZIP or CD-ROM (position: %i)\n", ide->pos); + return 0; } - ext_ide = ide; - - if (ide->command==0x30) times30++; - /*if (ide_board) */ide_log("CALLBACK %02X %i %i %i\n",ide->command,times30,ide->reset,cur_ide[ide_board]); - - if (ide->reset) - { - ide->atastat = ide_other->atastat = READY_STAT | DSC_STAT; - ide->error = ide_other->error = 1; - ide->secount = ide_other->secount = 1; - ide->sector = ide_other->sector = 1; - ide->head = ide_other->head = 0; - ide->cylinder = ide_other->cylinder = 0; - ide->reset = ide_other->reset = 0; - - if (ide_drive_is_zip(ide)) - { - zip_id = atapi_zip_drives[cur_ide[ide_board]]; - zip[zip_id].status = READY_STAT | DSC_STAT; - zip[zip_id].error = 1; - zip[zip_id].phase = 1; - zip[zip_id].request_length=0xEB14; - ide->cylinder = 0xEB14; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom_id = atapi_cdrom_drives[cur_ide[ide_board]]; - cdrom[cdrom_id]->status = READY_STAT | DSC_STAT; - cdrom[cdrom_id]->error = 1; - cdrom[cdrom_id]->phase = 1; - cdrom[cdrom_id]->request_length=0xEB14; - ide->cylinder = 0xEB14; - if (cdrom_drives[cdrom_id].handler->stop) - { - cdrom_drives[cdrom_id].handler->stop(cdrom_id); - } - } - if (ide->type == IDE_NONE) - { - ide->cylinder=0xFFFF; - } - if (ide_drive_is_zip(ide_other)) - { - zip_id_other = atapi_zip_drives[cur_ide[ide_board] ^ 1]; - zip[zip_id_other].status = READY_STAT | DSC_STAT; - zip[zip_id_other].error = 1; - zip[zip_id_other].phase = 1; - zip[zip_id_other].request_length=0xEB14; - ide->cylinder = 0xEB14; - } - else if (ide_drive_is_cdrom(ide_other)) - { - cdrom_id_other = atapi_cdrom_drives[cur_ide[ide_board] ^ 1]; - cdrom[cdrom_id_other]->status = READY_STAT | DSC_STAT; - cdrom[cdrom_id_other]->error = 1; - cdrom[cdrom_id_other]->phase = 1; - cdrom[cdrom_id_other]->request_length=0xEB14; - ide_other->cylinder = 0xEB14; - if (cdrom_drives[cdrom_id_other].handler->stop) - { - cdrom_drives[cdrom_id_other].handler->stop(cdrom_id_other); - } - } - if (ide_other->type == IDE_NONE) - { - ide_other->cylinder=0xFFFF; - } - return; - } - - cdrom_id = atapi_cdrom_drives[cur_ide[ide_board]]; - cdrom_id_other = atapi_cdrom_drives[cur_ide[ide_board] ^ 1]; - - zip_id = atapi_zip_drives[cur_ide[ide_board]]; - zip_id_other = atapi_zip_drives[cur_ide[ide_board] ^ 1]; - - if (((ide->command >= WIN_RESTORE) && (ide->command <= 0x1F)) || ((ide->command >= WIN_SEEK) && (ide->command <= 0x7F))) - { - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { - goto abort_cmd; - } - if ((ide->command >= WIN_SEEK) && (ide->command <= 0x7F)) - { - full_size /= ide->t_hpc; - full_size /= ide->t_spt; - - if ((ide->cylinder >= full_size) || (ide->head >= ide->t_hpc) || !ide->sector || (ide->sector > ide->t_spt)) - goto id_not_found; - } - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - } - switch (ide->command) - { - /* Initialize the Task File Registers as follows: Status = 00h, Error = 01h, Sector Count = 01h, Sector Number = 01h, - Cylinder Low = 14h, Cylinder High =EBh and Drive/Head = 00h. */ - case WIN_SRST: /*ATAPI Device Reset */ - ide->atastat = READY_STAT | DSC_STAT; - ide->error=1; /*Device passed*/ - ide->secount = ide->sector = 1; - ide_set_signature(ide); - - if (ide_drive_is_zip(ide)) - { - zip[zip_id].status = READY_STAT | DSC_STAT; - zip[zip_id].error = 1; - zip[zip_id].phase = 1; - zip_reset(zip_id); - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[cdrom_id]->status = READY_STAT | DSC_STAT; - cdrom[cdrom_id]->error = 1; - cdrom[cdrom_id]->phase = 1; - cdrom_reset(cdrom_id); - } - ide_irq_raise(ide); - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { - ide->service = 0; - } - return; - - case WIN_NOP: - case WIN_STANDBYNOW1: - case WIN_IDLENOW1: - case WIN_SETIDLE1: - if (ide_drive_is_zip(ide)) - { - zip[zip_id].status = READY_STAT | DSC_STAT; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[cdrom_id]->status = READY_STAT | DSC_STAT; - } - else - { - ide->atastat = READY_STAT | DSC_STAT; - } - ide_irq_raise(ide); - return; - - case WIN_CHECKPOWERMODE1: - case WIN_SLEEP1: - if (ide_drive_is_zip(ide)) - { - zip[zip_id].phase = 0xFF; - zip[zip_id].status = READY_STAT | DSC_STAT; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[cdrom_id]->phase = 0xFF; - cdrom[cdrom_id]->status = READY_STAT | DSC_STAT; - } - ide->secount = 0xFF; - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - - case WIN_READ: - case WIN_READ_NORETRY: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { - ide_set_signature(ide); - goto abort_cmd; - } - if (!ide->specify_success) - { - goto id_not_found; - } - - if (ide->do_initial_read) - { - ide->do_initial_read = 0; - ide->sector_pos = 0; - if (ide->secount) - { - hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer); - } - else - { - hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer); - } - } - - memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos*512], 512); - - ide->sector_pos++; - ide->pos=0; - - ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; - - ide_irq_raise(ide); - - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); - return; - - case WIN_READ_DMA: - case WIN_READ_DMA_ALT: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || (ide->board >= 2)) - { - ide_log("IDE %i: DMA read aborted (bad device or board)\n", ide->channel); - goto abort_cmd; - } - if (!ide->specify_success) - { - ide_log("IDE %i: DMA read aborted (SPECIFY failed)\n", ide->channel); - goto id_not_found; - } - - ide->sector_pos = 0; - if (ide->secount) - { - ide->sector_pos = ide->secount; - } - else - { - ide->sector_pos = 256; - } - hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->sector_pos, ide->sector_buffer); - - ide->pos=0; - - if (ide_bus_master_read) - { - if (ide_bus_master_read(ide_board, ide->sector_buffer, ide->sector_pos * 512)) - { - ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel); - goto abort_cmd; - } - else - { - /*DMA successful*/ - ide_log("IDE %i: DMA read successful\n", ide->channel); - - ide->atastat = READY_STAT | DSC_STAT; - - ide_irq_raise(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); - } - } else { - ide_log("IDE %i: DMA read aborted (no bus master)\n", ide->channel); - goto abort_cmd; - } - - return; - - case WIN_READ_MULTIPLE: - /* According to the official ATA reference: - - If the Read Multiple command is attempted before the Set Multiple Mode - command has been executed or when Read Multiple commands are - disabled, the Read Multiple operation is rejected with an Aborted Com- - mand error. */ - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || !ide->blocksize) - { - goto abort_cmd; - } - if (!ide->specify_success) - { - goto id_not_found; - } - - if (ide->do_initial_read) - { - ide->do_initial_read = 0; - ide->sector_pos = 0; - if (ide->secount) - { - hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer); - } - else - { - hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer); - } - } - - memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos*512], 512); - - ide->sector_pos++; - ide->pos=0; - - ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; - if (!ide->blockcount) - { - ide_irq_raise(ide); - } - ide->blockcount++; - if (ide->blockcount >= ide->blocksize) - { - ide->blockcount = 0; - } - - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); - return; - - case WIN_WRITE: - case WIN_WRITE_NORETRY: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { - goto abort_cmd; - } - if (!ide->specify_success) - { - goto id_not_found; - } - hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); - ide_irq_raise(ide); - ide->secount = (ide->secount - 1) & 0xff; - if (ide->secount) - { - ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; - ide->pos=0; - ide_next_sector(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); - } - else - { - ide->atastat = READY_STAT | DSC_STAT; - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); - } - - return; - - case WIN_WRITE_DMA: - case WIN_WRITE_DMA_ALT: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || (ide_board >= 2)) - { - ide_log("IDE %i: DMA write aborted (bad device type or board)\n", ide->channel); - goto abort_cmd; - } - if (!ide->specify_success) - { - ide_log("IDE %i: DMA write aborted (SPECIFY failed)\n", ide->channel); - goto id_not_found; - } - - if (ide_bus_master_read) - { - if (ide->secount) - ide->sector_pos = ide->secount; - else - ide->sector_pos = 256; - - if (ide_bus_master_write(ide_board, ide->sector_buffer, ide->sector_pos * 512)) - { - ide_log("IDE %i: DMA write aborted (failed)\n", ide->channel); - goto abort_cmd; - } - else - { - /*DMA successful*/ - ide_log("IDE %i: DMA write successful\n", ide->channel); - - hdd_image_write(ide->hdd_num, ide_get_sector(ide), ide->sector_pos, ide->sector_buffer); - - ide->atastat = READY_STAT | DSC_STAT; - - ide_irq_raise(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); - } - } else { - ide_log("IDE %i: DMA write aborted (no bus master)\n", ide->channel); - goto abort_cmd; - } - - return; - - case WIN_WRITE_MULTIPLE: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { - goto abort_cmd; - } - if (!ide->specify_success) - { - goto id_not_found; - } - hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); - ide->blockcount++; - if (ide->blockcount >= ide->blocksize || ide->secount == 1) - { - ide->blockcount = 0; - ide_irq_raise(ide); - } - ide->secount = (ide->secount - 1) & 0xff; - if (ide->secount) - { - ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; - ide->pos=0; - ide_next_sector(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); - } - else - { - ide->atastat = READY_STAT | DSC_STAT; - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); - } - return; - - case WIN_VERIFY: - case WIN_VERIFY_ONCE: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { - goto abort_cmd; - } - if (!ide->specify_success) - { - goto id_not_found; - } - ide->pos=0; - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); - return; - - case WIN_FORMAT: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { - goto abort_cmd; - } - if (!ide->specify_success) - { - goto id_not_found; - } - hdd_image_zero(ide->hdd_num, ide_get_sector(ide), ide->secount); - - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - - /* ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); */ - return; - - case WIN_DRIVE_DIAGNOSTICS: - ide_set_signature(ide); - ide->error=1; /*No error detected*/ - - if (ide_drive_is_zip(ide)) - { - zip[zip_id].status = 0; - zip[zip_id].error = 1; - ide_irq_raise(ide); - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[cdrom_id]->status = 0; - cdrom[cdrom_id]->error = 1; - ide_irq_raise(ide); - } - else - { - ide->atastat = READY_STAT | DSC_STAT; - ide->error = 1; - ide_irq_raise(ide); - } - - ide_set_signature(ide_other); - ide_other->error=1; /*No error detected*/ - - if (ide_drive_is_zip(ide_other)) - { - zip[zip_id_other].status = 0; - zip[zip_id_other].error = 1; - } - else if (ide_drive_is_cdrom(ide_other)) - { - cdrom[cdrom_id_other]->status = 0; - cdrom[cdrom_id_other]->error = 1; - } - else - { - ide_other->atastat = READY_STAT | DSC_STAT; - ide_other->error = 1; - } - - cur_ide[ide_board] &= ~1; - return; - - case WIN_SPECIFY: /* Initialize Drive Parameters */ - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { - goto abort_cmd; - } - full_size /= (ide->head+1); - full_size /= ide->secount; - ide->specify_success = 1; - hdd_image_specify(ide->hdd_num, ide->head + 1, ide->secount); - ide->t_spt=ide->secount; - ide->t_hpc=ide->head; - ide->t_hpc++; - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - - case WIN_PIDENTIFY: /* Identify Packet Device */ - if (ide_drive_is_zip(ide)) - { - ide_atapi_zip_identify(ide); - ide->pos = 0; - zip[zip_id].phase = 2; - zip[zip_id].pos = 0; - zip[zip_id].error = 0; - zip[zip_id].status = DRQ_STAT | READY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - } - else if (ide_drive_is_cdrom(ide)) - { - ide_atapi_identify(ide); - ide->pos = 0; - cdrom[cdrom_id]->phase = 2; - cdrom[cdrom_id]->pos = 0; - cdrom[cdrom_id]->error = 0; - cdrom[cdrom_id]->status = DRQ_STAT | READY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - } - goto abort_cmd; - - case WIN_SET_MULTIPLE_MODE: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { - goto abort_cmd; - } - ide->blocksize = ide->secount; - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - - case WIN_SET_FEATURES: - if (ide->type == IDE_NONE) - { - goto abort_cmd; - } - - if (!ide_set_features(ide)) - { - goto abort_cmd; - } - else - { - if (ide_drive_is_zip(ide)) { - zip[zip_id].status = READY_STAT | DSC_STAT; - zip[zip_id].pos = 0; - } - else if (ide_drive_is_cdrom(ide)) { - cdrom[cdrom_id]->status = READY_STAT | DSC_STAT; - cdrom[cdrom_id]->pos = 0; - } - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - } - return; - - case WIN_READ_NATIVE_MAX: - if (ide->type != IDE_HDD) - { - goto abort_cmd; - } - snum = hdd[ide->hdd_num].spt; - snum *= hdd[ide->hdd_num].hpc; - snum *= hdd[ide->hdd_num].tracks; - ide_set_sector(ide, snum - 1); - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - - case WIN_IDENTIFY: /* Identify Device */ - if (ide->type != IDE_HDD) - { - ide_set_signature(ide); - goto abort_cmd; - } - else - { - ide_identify(ide); - ide->pos=0; - ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; - ide_irq_raise(ide); - } - return; - - case WIN_PACKETCMD: /* ATAPI Packet */ - if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) - { - goto abort_cmd; - } - - if (ide_drive_is_zip(ide)) - zip_phase_callback(atapi_zip_drives[cur_ide[ide_board]]); - else - cdrom_phase_callback(atapi_cdrom_drives[cur_ide[ide_board]]); - ide_log("IDE callback now: %i\n", idecallback[ide_board]); - return; - - case 0xFF: - goto abort_cmd; - } - -abort_cmd: - ide->command = 0; if (ide_drive_is_zip(ide)) - { - zip[zip_id].status = READY_STAT | ERR_STAT | DSC_STAT; - zip[zip_id].error = ABRT_ERR; - zip[zip_id].pos = 0; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[cdrom_id]->status = READY_STAT | ERR_STAT | DSC_STAT; - cdrom[cdrom_id]->error = ABRT_ERR; - cdrom[cdrom_id]->pos = 0; - } + temp = zip_read(ch, length); else - { - ide->atastat = READY_STAT | ERR_STAT | DSC_STAT; - ide->error = ABRT_ERR; - ide->pos = 0; + temp = cdrom_read(ch, length); + } else { + switch (length) { + case 1: + temp = idebufferb[ide->pos]; + ide->pos++; + break; + case 2: + temp = idebufferw[ide->pos >> 1]; + ide->pos += 2; + break; + case 4: + temp = idebufferl[ide->pos >> 2]; + ide->pos += 4; + break; + default: + return 0; } + } + if (ide->pos>=512 && ide->command != WIN_PACKETCMD) { + ide->pos=0; + ide->atastat = DRDY_STAT | DSC_STAT; + if (ide_drive_is_zip(ide)) { + zip[atapi_zip_drives[ch]]->status = DRDY_STAT | DSC_STAT; + zip[atapi_zip_drives[ch]]->packet_status = ZIP_PHASE_IDLE; + } else if (ide_drive_is_cdrom(ide)) { + cdrom[atapi_cdrom_drives[ch]]->status = DRDY_STAT | DSC_STAT; + cdrom[atapi_cdrom_drives[ch]]->packet_status = CDROM_PHASE_IDLE; + } + if (ide->command == WIN_READ || ide->command == WIN_READ_NORETRY || ide->command == WIN_READ_MULTIPLE) { + ide->secount = (ide->secount - 1) & 0xff; + if (ide->secount) { + ide_next_sector(ide); + ide->atastat = BSY_STAT; + timer_process(); + if (ide->command == WIN_READ_MULTIPLE) + ide_callback(ide_boards[ide->board]); + else + ide_set_callback(ide->board, ide_get_period(ide, 512)); + timer_update_outstanding(); + } else { + if (ide->command != WIN_READ_MULTIPLE) + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + } + } + } + + return temp; +} + + +static uint8_t +ide_status(ide_t *ide, int ch) +{ + if (ide->type == IDE_NONE) + return 0; + else { + if (ide_drive_is_zip(ide)) + return (zip[atapi_zip_drives[ch]]->status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); + else if (ide_drive_is_cdrom(ide)) + return (cdrom[atapi_cdrom_drives[ch]]->status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); + else + return ide->atastat; + } +} + + +uint8_t +ide_readb(uint16_t addr, void *priv) +{ + ide_board_t *dev = (ide_board_t *) priv; + + int ch; + ide_t *ide; + + ch = dev->cur_dev; + ide = ide_drives[ch]; + + uint8_t temp = 0xff; + uint16_t tempw; + + addr |= 0x90; + addr &= 0xFFF7; + + switch (addr & 0x7) { + case 0x0: /* Data */ + tempw = ide_read_data(ide, 2); + temp = tempw & 0xff; + break; + + /* For ATAPI: Bits 7-4 = sense key, bit 3 = MCR (media change requested), + Bit 2 = ABRT (aborted command), Bit 1 = EOM (end of media), + and Bit 0 = ILI (illegal length indication). */ + case 0x1: /* Error */ + if (ide->type == IDE_NONE) + temp = 0; + else { + if (ide_drive_is_zip(ide)) + temp = zip[atapi_zip_drives[ch]]->error; + else if (ide_drive_is_cdrom(ide)) + temp = cdrom[atapi_cdrom_drives[ch]]->error; + else + temp = ide->error; + } + break; + + /* For ATAPI: + Bit 0: Command or Data: + Data if clear, Command if set; + Bit 1: I/OB + Direction: + To device if set; + From device if clear. + IO DRQ CoD + 0 1 1 Ready to accept command packet + 1 1 1 Message - ready to send message to host + 1 1 0 Data to host + 0 1 0 Data from host + 1 0 1 Status. */ + case 0x2: /* Sector count */ + if (ide_drive_is_zip(ide)) + temp = zip[atapi_zip_drives[ch]]->phase; + else if (ide_drive_is_cdrom(ide)) + temp = cdrom[atapi_cdrom_drives[ch]]->phase; + else + temp = ide->secount; + break; + + case 0x3: /* Sector */ + temp = (uint8_t)ide->sector; + break; + + case 0x4: /* Cylinder low */ + if (ide->type == IDE_NONE) + temp = 0xFF; + else { + if (ide_drive_is_zip(ide)) + temp = zip[atapi_zip_drives[ch]]->request_length & 0xff; + else if (ide_drive_is_cdrom(ide)) + temp = cdrom[atapi_cdrom_drives[ch]]->request_length & 0xff; + else + temp = ide->cylinder & 0xff; + } + break; + + case 0x5: /* Cylinder high */ + if (ide->type == IDE_NONE) + temp = 0xFF; + else { + if (ide_drive_is_zip(ide)) + temp = zip[atapi_zip_drives[ch]]->request_length >> 8; + else if (ide_drive_is_cdrom(ide)) + temp = cdrom[atapi_cdrom_drives[ch]]->request_length >> 8; + else + temp = ide->cylinder >> 8; + } + break; + + case 0x6: /* Drive/Head */ + temp = (uint8_t)(ide->head | ((ch & 1) ? 0x10 : 0) | (ide->lba ? 0x40 : 0) | 0xa0); + break; + + /* For ATAPI: Bit 5 is DMA ready, but without overlapped or interlaved DMA, it is + DF (drive fault). */ + case 0x7: /* Status */ + ide_irq_lower(ide); + temp = ide_status(ide, ch); + break; + } + + ide_log("ide_readb(%04X, %08X) = %02X\n", addr, priv, temp); + return temp; +} + + +uint8_t +ide_read_alt_status(uint16_t addr, void *priv) +{ + uint8_t temp = 0xff; + + ide_board_t *dev = (ide_board_t *) priv; + + ide_t *ide; + int ch; + + ch = dev->cur_dev; + ide = ide_drives[ch]; + + /* Per the Seagate ATA-3 specification: + Reading the alternate status does *NOT* clear the IRQ. */ + temp = ide_status(ide, ch); + + ide_log("ide_read_alt_status(%04X, %08X) = %02X\n", addr, priv, temp); + return temp; +} + + +uint16_t +ide_readw(uint16_t addr, void *priv) +{ + uint16_t temp = 0xffff; + + ide_board_t *dev = (ide_board_t *) priv; + + ide_t *ide; + int ch; + + ch = dev->cur_dev; + ide = ide_drives[ch]; + + switch (addr & 0x7) { + case 0x0: /* Data */ + temp = ide_read_data(ide, 2); + break; + } + + /* ide_log("ide_readw(%04X, %08X) = %04X\n", addr, priv, temp); */ + return temp; +} + + +static uint32_t +ide_readl(uint16_t addr, void *priv) +{ + uint16_t temp2; + uint32_t temp = 0xffffffff; + + ide_board_t *dev = (ide_board_t *) priv; + + ide_t *ide; + int ch; + + ch = dev->cur_dev; + ide = ide_drives[ch]; + + switch (addr & 0x7) { + case 0x0: /* Data */ + temp2 = ide_read_data(ide, 2); + temp = temp2 | (ide_read_data(ide, 2) << 16); + break; + } + + /* ide_log("ide_readl(%04X, %08X) = %04X\n", addr, priv, temp); */ + return temp; +} + + +static void +ide_callback(void *priv) +{ + ide_t *ide, *ide_other; + int snum, ret, ch; + int cdrom_id, cdrom_id_other; + int zip_id, zip_id_other; + + ide_board_t *dev = (ide_board_t *) priv; + ch = dev->cur_dev; + + ide = ide_drives[ch]; + ide_other = ide_drives[ch ^ 1]; + + ide_set_callback(ide->board, 0LL); + + if (ide->reset) { + ide_log("CALLBACK RESET %i %i\n", ide->reset,ch); + + ide->atastat = ide_other->atastat = DRDY_STAT | DSC_STAT; + ide->error = ide_other->error = 1; + ide->secount = ide_other->secount = 1; + ide->sector = ide_other->sector = 1; + ide->head = ide_other->head = 0; + ide->cylinder = ide_other->cylinder = 0; + + // ide->cfg_spt = ide->cfg_hpc = 0; /* need new parameters (drive 0) */ + // ide_other->cfg_spt = ide_other->cfg_hpc = 0; /* need new parameters (drive 1) */ + + ide->reset = ide_other->reset = 0; + + ide_set_signature(ide); + if (ide_drive_is_zip(ide)) { + zip_id = atapi_zip_drives[ch]; + zip[zip_id]->status = DRDY_STAT | DSC_STAT; + zip[zip_id]->error = 1; + } else if (ide_drive_is_cdrom(ide)) { + cdrom_id = atapi_cdrom_drives[ch]; + cdrom[cdrom_id]->status = DRDY_STAT | DSC_STAT; + cdrom[cdrom_id]->error = 1; + if (cdrom[cdrom_id]->handler->stop) + cdrom[cdrom_id]->handler->stop(cdrom_id); + } + + ide_set_signature(ide_other); + if (ide_drive_is_zip(ide_other)) { + zip_id_other = atapi_zip_drives[ch ^ 1]; + zip[zip_id_other]->status = DRDY_STAT | DSC_STAT; + zip[zip_id_other]->error = 1; + } else if (ide_drive_is_cdrom(ide_other)) { + cdrom_id_other = atapi_cdrom_drives[ch ^ 1]; + cdrom[cdrom_id_other]->status = DRDY_STAT | DSC_STAT; + cdrom[cdrom_id_other]->error = 1; + if (cdrom[cdrom_id_other]->handler->stop) + cdrom[cdrom_id_other]->handler->stop(cdrom_id_other); + } + + return; + } + + ide_log("CALLBACK %02X %i %i\n", ide->command, ide->reset,ch); + + cdrom_id = atapi_cdrom_drives[ch]; + cdrom_id_other = atapi_cdrom_drives[ch ^ 1]; + + zip_id = atapi_zip_drives[ch]; + zip_id_other = atapi_zip_drives[ch ^ 1]; + + if (((ide->command >= WIN_RECAL) && (ide->command <= 0x1F)) || + ((ide->command >= WIN_SEEK) && (ide->command <= 0x7F))) { + if (ide->type != IDE_HDD) + goto abort_cmd; + if ((ide->command >= WIN_SEEK) && (ide->command <= 0x7F)) { + if ((ide->cylinder >= ide->tracks) || (ide->head >= ide->hpc) || + !ide->sector || (ide->sector > ide->spt)) + goto id_not_found; + } + ide->atastat = DRDY_STAT | DSC_STAT; ide_irq_raise(ide); return; + } + + switch (ide->command) { + /* Initialize the Task File Registers as follows: Status = 00h, Error = 01h, Sector Count = 01h, Sector Number = 01h, + Cylinder Low = 14h, Cylinder High =EBh and Drive/Head = 00h. */ + case WIN_SRST: /*ATAPI Device Reset */ + + ide->atastat = DRDY_STAT | DSC_STAT; + ide->error = 1; /*Device passed*/ + ide->secount = 1; + ide->sector = 1; + + ide_set_signature(ide); + + if (ide_drive_is_zip(ide)) { + zip[zip_id]->status = DRDY_STAT | DSC_STAT; + zip[zip_id]->error = 1; + zip_reset(zip[zip_id]); + } else if (ide_drive_is_cdrom(ide)) { + cdrom[cdrom_id]->status = DRDY_STAT | DSC_STAT; + cdrom[cdrom_id]->error = 1; + cdrom_reset(cdrom[cdrom_id]); + } + ide_irq_raise(ide); + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + ide->service = 0; + return; + + case WIN_NOP: + case WIN_STANDBYNOW1: + case WIN_IDLENOW1: + case WIN_SETIDLE1: + if (ide_drive_is_zip(ide)) + zip[zip_id]->status = DRDY_STAT | DSC_STAT; + else if (ide_drive_is_cdrom(ide)) + cdrom[cdrom_id]->status = DRDY_STAT | DSC_STAT; + else + ide->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + return; + + case WIN_CHECKPOWERMODE1: + case WIN_SLEEP1: + if (ide_drive_is_zip(ide)) { + zip[zip_id]->phase = 0xFF; + zip[zip_id]->status = DRDY_STAT | DSC_STAT; + } else if (ide_drive_is_cdrom(ide)) { + cdrom[cdrom_id]->phase = 0xFF; + cdrom[cdrom_id]->status = DRDY_STAT | DSC_STAT; + } + ide->secount = 0xFF; + ide->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + return; + + case WIN_READ: + case WIN_READ_NORETRY: + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) { + ide_set_signature(ide); + goto abort_cmd; + } + if (ide->cfg_spt == 0) + goto id_not_found; + + if (ide->do_initial_read) { + ide->do_initial_read = 0; + ide->sector_pos = 0; + if (ide->secount) + hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer); + else + hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer); + } + + memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos*512], 512); + + ide->sector_pos++; + ide->pos = 0; + + ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + + ide_irq_raise(ide); + + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + return; + + case WIN_READ_DMA: + case WIN_READ_DMA_ALT: + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || (ide->board >= 2)) { + ide_log("IDE %i: DMA read aborted (bad device or board)\n", ide->channel); + goto abort_cmd; + } + if (ide->cfg_spt == 0) { + ide_log("IDE %i: DMA read aborted (SPECIFY failed)\n", ide->channel); + goto id_not_found; + } + + ide->sector_pos = 0; + if (ide->secount) + ide->sector_pos = ide->secount; + else + ide->sector_pos = 256; + hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->sector_pos, ide->sector_buffer); + + ide->pos=0; + + if (ide_bus_master_read) { + /* We should not abort - we should simply wait for the host to start DMA. */ + ret = ide_bus_master_read(ide->board, + ide->sector_buffer, ide->sector_pos * 512, + ide_bus_master_priv[ide->board]); + if (ret == 2) { + /* Bus master DMA disabled, simply wait for the host to enable DMA. */ + ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide_set_callback(ide->board, 6LL * IDE_TIME); + return; + } else if (ret == 1) { + /* Bus master DMAS error, abort the command. */ + ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel); + goto abort_cmd; + } else { + /*DMA successful*/ + ide_log("IDE %i: DMA read successful\n", ide->channel); + + ide->atastat = DRDY_STAT | DSC_STAT; + + ide_irq_raise(ide); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + } + } else { + ide_log("IDE %i: DMA read aborted (no bus master)\n", ide->channel); + goto abort_cmd; + } + return; + + case WIN_READ_MULTIPLE: + /* According to the official ATA reference: + + If the Read Multiple command is attempted before the Set Multiple Mode + command has been executed or when Read Multiple commands are + disabled, the Read Multiple operation is rejected with an Aborted Com- + mand error. */ + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || !ide->blocksize) + goto abort_cmd; + if (ide->cfg_spt == 0) + goto id_not_found; + + if (ide->do_initial_read) { + ide->do_initial_read = 0; + ide->sector_pos = 0; + if (ide->secount) + hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer); + else + hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer); + } + + memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos*512], 512); + + ide->sector_pos++; + ide->pos=0; + + ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + if (!ide->blockcount) + ide_irq_raise(ide); + ide->blockcount++; + if (ide->blockcount >= ide->blocksize) + ide->blockcount = 0; + return; + + case WIN_WRITE: + case WIN_WRITE_NORETRY: + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + goto abort_cmd; + if (ide->cfg_spt == 0) + goto id_not_found; + hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); + ide_irq_raise(ide); + ide->secount = (ide->secount - 1) & 0xff; + if (ide->secount) { + ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide->pos=0; + ide_next_sector(ide); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + } else { + ide->atastat = DRDY_STAT | DSC_STAT; + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + } + return; + + case WIN_WRITE_DMA: + case WIN_WRITE_DMA_ALT: + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || (ide->board >= 2)) { + ide_log("IDE %i: DMA write aborted (bad device type or board)\n", ide->channel); + goto abort_cmd; + } + if (ide->cfg_spt == 0) { + ide_log("IDE %i: DMA write aborted (SPECIFY failed)\n", ide->channel); + goto id_not_found; + } + + if (ide_bus_master_read) { + if (ide->secount) + ide->sector_pos = ide->secount; + else + ide->sector_pos = 256; + + ret = ide_bus_master_write(ide->board, + ide->sector_buffer, ide->sector_pos * 512, + ide_bus_master_priv[ide->board]); + + if (ret == 2) { + /* Bus master DMA disabled, simply wait for the host to enable DMA. */ + ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide_set_callback(ide->board, 6LL * IDE_TIME); + return; + } else if (ret == 1) { + /* Bus master DMA error, abort the command. */ + ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel); + goto abort_cmd; + } else { + /*DMA successful*/ + ide_log("IDE %i: DMA write successful\n", ide->channel); + + hdd_image_write(ide->hdd_num, ide_get_sector(ide), ide->sector_pos, ide->sector_buffer); + + ide->atastat = DRDY_STAT | DSC_STAT; + + ide_irq_raise(ide); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + } + } else { + ide_log("IDE %i: DMA write aborted (no bus master)\n", ide->channel); + goto abort_cmd; + } + + return; + + case WIN_WRITE_MULTIPLE: + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + goto abort_cmd; + if (ide->cfg_spt == 0) + goto id_not_found; + hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); + ide->blockcount++; + if (ide->blockcount >= ide->blocksize || ide->secount == 1) { + ide->blockcount = 0; + ide_irq_raise(ide); + } + ide->secount = (ide->secount - 1) & 0xff; + if (ide->secount) { + ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide->pos=0; + ide_next_sector(ide); + } else { + ide->atastat = DRDY_STAT | DSC_STAT; + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + } + return; + + case WIN_VERIFY: + case WIN_VERIFY_ONCE: + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + goto abort_cmd; + if (ide->cfg_spt == 0) + goto id_not_found; + ide->pos=0; + ide->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + return; + + case WIN_FORMAT: + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + goto abort_cmd; + if (ide->cfg_spt == 0) + goto id_not_found; + hdd_image_zero(ide->hdd_num, ide_get_sector(ide), ide->secount); + + ide->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + + /* ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); */ + return; + + case WIN_DRIVE_DIAGNOSTICS: + ide_set_signature(ide); + ide->error=1; /*No error detected*/ + + if (ide_drive_is_zip(ide)) { + zip[zip_id]->status = 0; + zip[zip_id]->error = 1; + ide_irq_raise(ide); + } else if (ide_drive_is_cdrom(ide)) { + cdrom[cdrom_id]->status = 0; + cdrom[cdrom_id]->error = 1; + ide_irq_raise(ide); + } else { + ide->atastat = DRDY_STAT | DSC_STAT; + ide->error = 1; + ide_irq_raise(ide); + } + + ide_set_signature(ide_other); + ide_other->error=1; /*No error detected*/ + + if (ide_drive_is_zip(ide_other)) { + zip[zip_id_other]->status = 0; + zip[zip_id_other]->error = 1; + } else if (ide_drive_is_cdrom(ide_other)) { + cdrom[cdrom_id_other]->status = 0; + cdrom[cdrom_id_other]->error = 1; + } else { + ide_other->atastat = DRDY_STAT | DSC_STAT; + ide_other->error = 1; + } + + ide_boards[ide->board]->cur_dev &= ~1; + ch = ide_boards[ide->board]->cur_dev; + return; + + case WIN_SPECIFY: /* Initialize Drive Parameters */ + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + goto abort_cmd; + if (ide->cfg_spt == 0) { + /* Only accept after RESET or DIAG. */ + ide->cfg_spt = ide->secount; + ide->cfg_hpc = ide->head + 1; + } + ide->command = 0x00; + ide->atastat = DRDY_STAT | DSC_STAT; + ide->error = 1; + ide_irq_raise(ide); + return; + + case WIN_PIDENTIFY: /* Identify Packet Device */ + if (ide_drive_is_zip(ide)) { + ide_identify(ide); + ide->pos = 0; + zip[zip_id]->phase = 2; + zip[zip_id]->pos = 0; + zip[zip_id]->error = 0; + zip[zip_id]->status = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + return; + } else if (ide_drive_is_cdrom(ide)) { + ide_identify(ide); + ide->pos = 0; + cdrom[cdrom_id]->phase = 2; + cdrom[cdrom_id]->pos = 0; + cdrom[cdrom_id]->error = 0; + cdrom[cdrom_id]->status = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + return; + } + goto abort_cmd; + + case WIN_SET_MULTIPLE_MODE: + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + goto abort_cmd; + ide->blocksize = ide->secount; + ide->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + return; + + case WIN_SET_FEATURES: + if (ide->type == IDE_NONE) + goto abort_cmd; + + if (!ide_set_features(ide)) + goto abort_cmd; + else { + if (ide_drive_is_zip(ide)) { + zip[zip_id]->status = DRDY_STAT | DSC_STAT; + zip[zip_id]->pos = 0; + } else if (ide_drive_is_cdrom(ide)) { + cdrom[cdrom_id]->status = DRDY_STAT | DSC_STAT; + cdrom[cdrom_id]->pos = 0; + } + ide->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + } + return; + + case WIN_READ_NATIVE_MAX: + if (ide->type != IDE_HDD) + goto abort_cmd; + snum = hdd[ide->hdd_num].spt; + snum *= hdd[ide->hdd_num].hpc; + snum *= hdd[ide->hdd_num].tracks; + ide_set_sector(ide, snum - 1); + ide->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + return; + + case WIN_IDENTIFY: /* Identify Device */ + if (ide->type != IDE_HDD) { + ide_set_signature(ide); + goto abort_cmd; + } else { + ide_identify(ide); + ide->pos=0; + ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + } + return; + + case WIN_PACKETCMD: /* ATAPI Packet */ + if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) + goto abort_cmd; + + if (ide_drive_is_zip(ide)) + zip_phase_callback(zip[atapi_zip_drives[ch]]); + else + cdrom_phase_callback(cdrom[atapi_cdrom_drives[ch]]); + return; + + case 0xFF: + goto abort_cmd; + } + +abort_cmd: + ide->command = 0; + if (ide_drive_is_zip(ide)) { + zip[zip_id]->status = DRDY_STAT | ERR_STAT | DSC_STAT; + zip[zip_id]->error = ABRT_ERR; + zip[zip_id]->pos = 0; + } else if (ide_drive_is_cdrom(ide)) { + cdrom[cdrom_id]->status = DRDY_STAT | ERR_STAT | DSC_STAT; + cdrom[cdrom_id]->error = ABRT_ERR; + cdrom[cdrom_id]->pos = 0; + } else { + ide->atastat = DRDY_STAT | ERR_STAT | DSC_STAT; + ide->error = ABRT_ERR; + ide->pos = 0; + } + ide_irq_raise(ide); + return; id_not_found: - ide->atastat = READY_STAT | ERR_STAT | DSC_STAT; - ide->error = ABRT_ERR | 0x10; - ide->pos = 0; - ide_irq_raise(ide); + ide->atastat = DRDY_STAT | ERR_STAT | DSC_STAT; + ide->error = IDNF_ERR; + ide->pos = 0; + ide_irq_raise(ide); } -void ide_callback_pri() -{ - idecallback[0] = 0LL; - callbackide(0); -} -void ide_callback_sec() +static void +ide_set_handlers(uint8_t board) { - idecallback[1] = 0LL; - callbackide(1); -} - -void ide_callback_ter() -{ - idecallback[2] = 0LL; - callbackide(2); -} - -void ide_callback_qua() -{ - idecallback[3] = 0LL; - callbackide(3); -} - -void ide_callback_xtide() -{ - idecallback[4] = 0LL; - callbackide(4); -} - -void ide_write_pri(uint16_t addr, uint8_t val, void *priv) -{ - writeide(0, addr, val); -} -void ide_write_pri_w(uint16_t addr, uint16_t val, void *priv) -{ - writeidew(0, val); -} -void ide_write_pri_l(uint16_t addr, uint32_t val, void *priv) -{ - writeidel(0, val); -} -uint8_t ide_read_pri(uint16_t addr, void *priv) -{ - return readide(0, addr); -} -uint16_t ide_read_pri_w(uint16_t addr, void *priv) -{ - return readidew(0); -} -uint32_t ide_read_pri_l(uint16_t addr, void *priv) -{ - return readidel(0); -} - -void ide_write_sec(uint16_t addr, uint8_t val, void *priv) -{ - writeide(1, addr, val); -} -void ide_write_sec_w(uint16_t addr, uint16_t val, void *priv) -{ - writeidew(1, val); -} -void ide_write_sec_l(uint16_t addr, uint32_t val, void *priv) -{ - writeidel(1, val); -} -uint8_t ide_read_sec(uint16_t addr, void *priv) -{ - return readide(1, addr); -} -uint16_t ide_read_sec_w(uint16_t addr, void *priv) -{ - return readidew(1); -} -uint32_t ide_read_sec_l(uint16_t addr, void *priv) -{ - return readidel(1); -} - -void ide_write_ter(uint16_t addr, uint8_t val, void *priv) -{ - writeide(2, addr, val); -} -void ide_write_ter_w(uint16_t addr, uint16_t val, void *priv) -{ - writeidew(2, val); -} -void ide_write_ter_l(uint16_t addr, uint32_t val, void *priv) -{ - writeidel(2, val); -} -uint8_t ide_read_ter(uint16_t addr, void *priv) -{ - return readide(2, addr); -} -uint16_t ide_read_ter_w(uint16_t addr, void *priv) -{ - return readidew(2); -} -uint32_t ide_read_ter_l(uint16_t addr, void *priv) -{ - return readidel(2); -} - -void ide_write_qua(uint16_t addr, uint8_t val, void *priv) -{ - writeide(3, addr, val); -} -void ide_write_qua_w(uint16_t addr, uint16_t val, void *priv) -{ - writeidew(3, val); -} -void ide_write_qua_l(uint16_t addr, uint32_t val, void *priv) -{ - writeidel(3, val); -} -uint8_t ide_read_qua(uint16_t addr, void *priv) -{ - return readide(3, addr); -} -uint16_t ide_read_qua_w(uint16_t addr, void *priv) -{ - return readidew(3); -} -uint32_t ide_read_qua_l(uint16_t addr, void *priv) -{ - return readidel(3); -} - -static uint16_t ide_base_main[2] = { 0x1f0, 0x170 }; -static uint16_t ide_side_main[2] = { 0x3f6, 0x376 }; - - -void ide_pri_enable(void) -{ - io_sethandler(0x01f0, 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL); - io_sethandler(0x03f6, 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL); - ide_base_main[0] = 0x1f0; - ide_side_main[0] = 0x3f6; -} - -void ide_pri_enable_ex(void) -{ - if (ide_base_main[0] & 0x300) - { - ide_log("Enabling primary base (%04X)...\n", ide_base_main[0]); - io_sethandler(ide_base_main[0], 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL); + if (ide_base_main[board] & 0x300) { + if (ide_boards[board]->bit32) { + io_sethandler(ide_base_main[board], 1, + ide_readb, ide_readw, ide_readl, + ide_writeb, ide_writew, ide_writel, + ide_boards[board]); + } else { + io_sethandler(ide_base_main[board], 1, + ide_readb, ide_readw, NULL, + ide_writeb, ide_writew, NULL, + ide_boards[board]); } - if (ide_side_main[0] & 0x300) - { - ide_log("Enabling primary side (%04X)...\n", ide_side_main[0]); - io_sethandler(ide_side_main[0], 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL); - } -} - -void ide_pri_disable(void) -{ - io_removehandler(ide_base_main[0], 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL); - io_removehandler(ide_side_main[0], 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL); -} - -void ide_sec_enable(void) -{ - io_sethandler(0x0170, 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL); - io_sethandler(0x0376, 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL); - ide_base_main[1] = 0x170; - ide_side_main[1] = 0x376; -} - -void ide_sec_enable_ex(void) -{ - if (ide_base_main[1] & 0x300) - { - io_sethandler(ide_base_main[1], 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL); - } - if (ide_side_main[1] & 0x300) - { - io_sethandler(ide_side_main[1], 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL); - } -} - -void ide_sec_disable(void) -{ - io_removehandler(ide_base_main[1], 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL); - io_removehandler(ide_side_main[1], 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL); + io_sethandler(ide_base_main[board] + 1, 7, + ide_readb, NULL, NULL, + ide_writeb, NULL, NULL, + ide_boards[board]); + } + if (ide_side_main[board] & 0x300) { + io_sethandler(ide_side_main[board], 1, + ide_read_alt_status, NULL, NULL, + ide_write_devctl, NULL, NULL, + ide_boards[board]); + } } -void ide_set_base(int controller, uint16_t port) +static void +ide_remove_handlers(uint8_t board) { - ide_base_main[controller] = port; -} - -void ide_set_side(int controller, uint16_t port) -{ - ide_side_main[controller] = port; -} - -void ide_ter_enable(void) -{ - io_sethandler(0x0168, 0x0008, ide_read_ter, ide_read_ter_w, ide_read_ter_l, ide_write_ter, ide_write_ter_w, ide_write_ter_l, NULL); - io_sethandler(0x036e, 0x0001, ide_read_ter, NULL, NULL, ide_write_ter, NULL, NULL , NULL); -} - -void ide_ter_disable(void) -{ - io_removehandler(0x0168, 0x0008, ide_read_ter, ide_read_ter_w, ide_read_ter_l, ide_write_ter, ide_write_ter_w, ide_write_ter_l, NULL); - io_removehandler(0x036e, 0x0001, ide_read_ter, NULL, NULL, ide_write_ter, NULL, NULL , NULL); -} - -void ide_ter_disable_cond(void) -{ - if ((ide_drives[4].type == IDE_NONE) && (ide_drives[5].type == IDE_NONE)) - { - ide_ter_disable(); - } -} - -void ide_ter_init(void) -{ - ide_ter_enable(); - - timer_add(ide_callback_ter, &idecallback[2], &idecallback[2], NULL); -} - -void ide_qua_enable(void) -{ - io_sethandler(0x01e8, 0x0008, ide_read_qua, ide_read_qua_w, ide_read_qua_l, ide_write_qua, ide_write_qua_w, ide_write_qua_l, NULL); - io_sethandler(0x03ee, 0x0001, ide_read_qua, NULL, NULL, ide_write_qua, NULL, NULL , NULL); -} - -void ide_qua_disable_cond(void) -{ - if ((ide_drives[6].type == IDE_NONE) && (ide_drives[7].type == IDE_NONE)) - { - ide_qua_disable(); - } -} - -void ide_qua_disable(void) -{ - io_removehandler(0x01e8, 0x0008, ide_read_qua, ide_read_qua_w, ide_read_qua_l, ide_write_qua, ide_write_qua_w, ide_write_qua_l, NULL); - io_removehandler(0x03ee, 0x0001, ide_read_qua, NULL, NULL, ide_write_qua, NULL, NULL , NULL); -} - -void ide_qua_init(void) -{ - ide_qua_enable(); - - timer_add(ide_callback_qua, &idecallback[3], &idecallback[3], NULL); + if (ide_boards[board]->bit32) { + io_removehandler(ide_base_main[board], 1, + ide_readb, ide_readw, ide_readl, + ide_writeb, ide_writew, ide_writel, + ide_boards[board]); + } else { + io_removehandler(ide_base_main[board], 1, + ide_readb, ide_readw, NULL, + ide_writeb, ide_writew, NULL, + ide_boards[board]); + } + io_removehandler(ide_base_main[board] + 1, 7, + ide_readb, NULL, NULL, + ide_writeb, NULL, NULL, + ide_boards[board]); + io_removehandler(ide_side_main[board], 1, + ide_read_alt_status, NULL, NULL, + ide_write_devctl, NULL, NULL, + ide_boards[board]); } -/*FIXME: this will go away after Kotori's rewrite. --FvK */ -void ide_init_first(void) +void +ide_pri_enable(void) { - int d; - - memset(ide_drives, 0x00, sizeof(ide_drives)); - for (d = 0; d < (IDE_NUM+XTIDE_NUM); d++) - { - ide_drives[d].channel = d; - ide_drives[d].type = IDE_NONE; - ide_drives[d].hdd_num = -1; - ide_drives[d].atastat = READY_STAT | DSC_STAT; - ide_drives[d].service = 0; - ide_drives[d].board = d >> 1; - } + ide_set_handlers(0); } -void ide_xtide_init(void) +void +ide_pri_disable(void) { - ide_bus_master_read = ide_bus_master_write = NULL; - - timer_add(ide_callback_xtide, &idecallback[4], &idecallback[4], NULL); + ide_remove_handlers(0); } -void ide_set_bus_master(int (*read)(int channel, uint8_t *data, int transfer_length), int (*write)(int channel, uint8_t *data, int transfer_length), void (*set_irq)(int channel)) + +void +ide_sec_enable(void) { - ide_bus_master_read = read; - ide_bus_master_write = write; - ide_bus_master_set_irq = set_irq; + ide_set_handlers(1); } -void secondary_ide_check(void) -{ - int i = 0; - int secondary_cdroms = 0; - int secondary_zips = 0; - for (i=0; i= 2) && (zip_drives[i].ide_channel <= 3) && ((zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || (zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA))) - secondary_zips++; - } - for (i=0; i= 2) && (cdrom_drives[i].ide_channel <= 3) && ((cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) || (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA))) - secondary_cdroms++; - } - if (!secondary_zips && !secondary_cdroms) { - ide_sec_disable(); - ide_init_ch[1] = 0; - } +void +ide_sec_disable(void) +{ + ide_remove_handlers(1); +} + + +void +ide_set_base(int controller, uint16_t port) +{ + ide_base_main[controller] = port; +} + + +void +ide_set_side(int controller, uint16_t port) +{ + ide_side_main[controller] = port; +} + + +static void * +ide_ter_init(const device_t *info) +{ + ide_boards[2] = (ide_board_t *) malloc(sizeof(ide_board_t)); + memset(ide_boards[2], 0, sizeof(ide_board_t)); + + ide_boards[2]->irq = device_get_config_int("irq"); + ide_boards[2]->cur_dev = 4; + + ide_set_handlers(2); + + timer_add(ide_callback, &ide_boards[2]->callback, &ide_boards[2]->callback, ide_boards[2]); + + ide_board_init(2); + + return(ide_drives); +} + + +/* Close a standalone IDE unit. */ +static void +ide_ter_close(void *priv) +{ + if (ide_boards[2]) { + free(ide_boards[2]); + ide_boards[2] = NULL; + + ide_board_close(2); + } +} + + +static void * +ide_qua_init(const device_t *info) +{ + ide_boards[3] = (ide_board_t *) malloc(sizeof(ide_board_t)); + memset(ide_boards[3], 0, sizeof(ide_board_t)); + + ide_boards[3]->irq = device_get_config_int("irq"); + ide_boards[3]->cur_dev = 6; + + ide_set_handlers(3); + + timer_add(ide_callback, &ide_boards[3]->callback, &ide_boards[3]->callback, ide_boards[3]); + + ide_board_init(3); + + return(ide_drives); +} + + +/* Close a standalone IDE unit. */ +static void +ide_qua_close(void *priv) +{ + if (ide_boards[3]) { + free(ide_boards[3]); + ide_boards[3] = NULL; + + ide_board_close(3); + } +} + + +static void +ide_clear_bus_master(void) +{ + ide_bus_master_read = ide_bus_master_write = NULL; + ide_bus_master_set_irq = NULL; + ide_bus_master_priv[0] = ide_bus_master_priv[1] = NULL; +} + + +void * +ide_xtide_init(void) +{ + ide_clear_bus_master(); + + if (!ide_boards[0]) { + ide_boards[0] = (ide_board_t *) malloc(sizeof(ide_board_t)); + memset(ide_boards[0], 0, sizeof(ide_board_t)); + ide_boards[0]->cur_dev = 0; + + timer_add(ide_callback, &ide_boards[0]->callback, &ide_boards[0]->callback, + ide_boards[0]); + + ide_board_init(0); + } + ide_boards[0]->irq = -1; + + return ide_boards[0]; +} + + +void +ide_xtide_close(void) +{ + if (ide_boards[0]) { + free(ide_boards[0]); + ide_boards[0] = NULL; + + ide_board_close(0); + } +} + + +void +ide_set_bus_master(int (*read)(int channel, uint8_t *data, int transfer_length, void *priv), + int (*write)(int channel, uint8_t *data, int transfer_length, void *priv), + void (*set_irq)(int channel, void *priv), + void *priv0, void *priv1) +{ + ide_bus_master_read = read; + ide_bus_master_write = write; + ide_bus_master_set_irq = set_irq; + ide_bus_master_priv[0] = priv0; + ide_bus_master_priv[1] = priv1; +} + + +void +secondary_ide_check(void) +{ + int i = 0; + int secondary_cdroms = 0; + int secondary_zips = 0; + + for (i=0; i= 2) && (zip_drives[i].ide_channel <= 3) && + (zip_drives[i].bus_type == ZIP_BUS_ATAPI)) + secondary_zips++; + } + for (i=0; i= 2) && (cdrom_drives[i].ide_channel <= 3) && + (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI)) + secondary_cdroms++; + } + if (!secondary_zips && !secondary_cdroms) + ide_remove_handlers(1); } @@ -2890,6 +2735,8 @@ void secondary_ide_check(void) static void * ide_sainit(const device_t *info) { + ide_log("Initializing IDE...\n"); + switch(info->local) { case 0: /* ISA, single-channel */ case 2: /* ISA, dual-channel */ @@ -2898,23 +2745,51 @@ ide_sainit(const device_t *info) case 6: /* VLB, dual-channel */ case 8: /* PCI, single-channel */ case 10: /* PCI, dual-channel */ - if (!ide_init_ch[0]) { - ide_pri_enable(); - timer_add(ide_callback_pri, &idecallback[0], &idecallback[0], NULL); - ide_init_ch[0] = 1; + if (!ide_inited) { + if (!(info->local & 8)) + ide_clear_bus_master(); } - if ((info->local & 2) && !ide_init_ch[1]) { - ide_sec_enable(); - timer_add(ide_callback_sec, &idecallback[1], &idecallback[1], NULL); - ide_init_ch[1] = 1; + if (!(ide_inited & 1)) { + ide_boards[0] = (ide_board_t *) malloc(sizeof(ide_board_t)); + memset(ide_boards[0], 0, sizeof(ide_board_t)); + ide_boards[0]->irq = 14; + ide_boards[0]->cur_dev = 0; + if (info->local & 8) + ide_boards[0]->bit32 = 1; + ide_base_main[0] = 0x1f0; + ide_side_main[0] = 0x3f6; + ide_set_handlers(0); + timer_add(ide_callback, &ide_boards[0]->callback, &ide_boards[0]->callback, + ide_boards[0]); + ide_log("Callback 0 pointer: %08X\n", &ide_boards[0]->callback); + + ide_board_init(0); + + ide_inited |= 1; + } + + if ((info->local & 3) && !(ide_inited & 2)) { + ide_boards[1] = (ide_board_t *) malloc(sizeof(ide_board_t)); + memset(ide_boards[1], 0, sizeof(ide_board_t)); + ide_boards[1]->irq = 15; + ide_boards[1]->cur_dev = 2; + if (info->local & 8) + ide_boards[1]->bit32 = 1; + ide_base_main[1] = 0x170; + ide_side_main[1] = 0x376; + ide_set_handlers(1); + timer_add(ide_callback, &ide_boards[1]->callback, &ide_boards[1]->callback, + ide_boards[1]); + ide_log("Callback 1 pointer: %08X\n", &ide_boards[1]->callback); + + ide_board_init(1); if (info->local & 1) secondary_ide_check(); - } - if (!(info->local & 8)) - ide_bus_master_read = ide_bus_master_write = NULL; + ide_inited |= 2; + } break; } @@ -2922,11 +2797,70 @@ ide_sainit(const device_t *info) } +static void +ide_drive_reset(int d) +{ + ide_drives[d]->channel = d; + ide_drives[d]->atastat = DRDY_STAT | DSC_STAT; + ide_drives[d]->service = 0; + ide_drives[d]->board = d >> 1; + + if (ide_boards[d >> 1]) { + ide_boards[d >> 1]->cur_dev = d & ~1; + ide_boards[d >> 1]->callback = 0LL; + } + + ide_set_signature(ide_drives[d]); + + if (ide_drives[d]->sector_buffer) + memset(ide_drives[d]->sector_buffer, 0, 256*512); + + if (ide_drives[d]->buffer) + memset(ide_drives[d]->buffer, 0, 65536 * sizeof(uint16_t)); +} + + +/* Reset a standalone IDE unit. */ +static void +ide_sareset(void *p) +{ + int d; + + ide_log("Resetting IDE...\n"); + + if (ide_inited & 1) { + for (d = 0; d < 2; d++) + ide_drive_reset(d); + } + + if (ide_inited & 2) { + for (d = 2; d < 4; d++) + ide_drive_reset(d); + } +} + + /* Close a standalone IDE unit. */ static void ide_saclose(void *priv) { - ide_init_ch[0] = ide_init_ch[1] = 0; + ide_log("Closing IDE...\n"); + + if ((ide_inited & 1) && (ide_boards[0])) { + free(ide_boards[0]); + ide_boards[0] = NULL; + + ide_board_close(0); + } + + if ((ide_inited & 2) && (ide_boards[1])) { + free(ide_boards[1]); + ide_boards[1] = NULL; + + ide_board_close(1); + } + + ide_inited = 0; } @@ -2934,61 +2868,156 @@ const device_t ide_isa_device = { "ISA PC/AT IDE Controller", DEVICE_ISA | DEVICE_AT, 0, - ide_sainit, ide_saclose, NULL, - NULL, NULL, NULL, NULL, - NULL + ide_sainit, ide_saclose, ide_sareset, + NULL, NULL, NULL, NULL }; const device_t ide_isa_2ch_device = { "ISA PC/AT IDE Controller (Dual-Channel)", DEVICE_ISA | DEVICE_AT, 2, - ide_sainit, ide_saclose, NULL, - NULL, NULL, NULL, NULL, - NULL + ide_sainit, ide_saclose, ide_sareset, + NULL, NULL, NULL, NULL }; const device_t ide_isa_2ch_opt_device = { "ISA PC/AT IDE Controller (Single/Dual)", DEVICE_ISA | DEVICE_AT, 3, - ide_sainit, ide_saclose, NULL, - NULL, NULL, NULL, NULL, - NULL + ide_sainit, ide_saclose, ide_sareset, + NULL, NULL, NULL, NULL }; const device_t ide_vlb_device = { "VLB IDE Controller", DEVICE_VLB | DEVICE_AT, 4, - ide_sainit, ide_saclose, NULL, - NULL, NULL, NULL, NULL, - NULL + ide_sainit, ide_saclose, ide_sareset, + NULL, NULL, NULL, NULL }; const device_t ide_vlb_2ch_device = { "VLB IDE Controller (Dual-Channel)", DEVICE_VLB | DEVICE_AT, 6, - ide_sainit, ide_saclose, NULL, - NULL, NULL, NULL, NULL, - NULL + ide_sainit, ide_saclose, ide_sareset, + NULL, NULL, NULL, NULL }; const device_t ide_pci_device = { "PCI IDE Controller", DEVICE_PCI | DEVICE_AT, 8, - ide_sainit, ide_saclose, NULL, - NULL, NULL, NULL, NULL, - NULL + ide_sainit, ide_saclose, ide_sareset, + NULL, NULL, NULL, NULL }; const device_t ide_pci_2ch_device = { "PCI IDE Controller (Dual-Channel)", DEVICE_PCI | DEVICE_AT, 10, - ide_sainit, ide_saclose, NULL, - NULL, NULL, NULL, NULL, - NULL + ide_sainit, ide_saclose, ide_sareset, + NULL, NULL, NULL, NULL +}; + +static const device_config_t ide_ter_config[] = +{ + { + "irq", "IRQ", CONFIG_SELECTION, "", 10, + { + { + "IRQ 2", 2 + }, + { + "IRQ 3", 3 + }, + { + "IRQ 4", 4 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 7", 7 + }, + { + "IRQ 9", 9 + }, + { + "IRQ 10", 10 + }, + { + "IRQ 11", 11 + }, + { + "IRQ 12", 12 + }, + { + "" + } + } + }, + { + "", "", -1 + } +}; + +static const device_config_t ide_qua_config[] = +{ + { + "irq", "IRQ", CONFIG_SELECTION, "", 11, + { + { + "IRQ 2", 2 + }, + { + "IRQ 3", 3 + }, + { + "IRQ 4", 4 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 7", 7 + }, + { + "IRQ 9", 9 + }, + { + "IRQ 10", 10 + }, + { + "IRQ 11", 11 + }, + { + "IRQ 12", 12 + }, + { + "" + } + } + }, + { + "", "", -1 + } +}; + +const device_t ide_ter_device = { + "Tertiary IDE Controller", + DEVICE_AT, + 0, + ide_ter_init, ide_ter_close, NULL, + NULL, NULL, NULL, + ide_ter_config +}; + +const device_t ide_qua_device = { + "Quaternary IDE Controller", + DEVICE_AT, + 0, + ide_qua_init, ide_qua_close, NULL, + NULL, NULL, NULL, + ide_qua_config }; diff --git a/src/disk/hdc_ide.h b/src/disk/hdc_ide.h index 5258d389e..69a81276d 100644 --- a/src/disk/hdc_ide.h +++ b/src/disk/hdc_ide.h @@ -9,7 +9,7 @@ * Implementation of the IDE emulation for hard disks and ATAPI * CD-ROM devices. * - * Version: @(#)hdd_ide.h 1.0.8 2018/03/20 + * Version: @(#)hdd_ide.h 1.0.10 2018/05/02 * * Authors: Sarah Walker, * Miran Grca, @@ -21,59 +21,52 @@ typedef struct { - int type; - int board; - uint8_t atastat; - uint8_t error; - int secount,sector,cylinder,head,drive,cylprecomp; - uint8_t command; - uint8_t fdisk; - int pos; - int packlen; - int spt,hpc; - int t_spt,t_hpc; - int tracks; - int packetstatus; - uint8_t asc; - int reset; + uint8_t atastat, error, + command, fdisk; + int type, board, + irqstat, service, + blocksize, blockcount, + hdd_num, channel, + pos, sector_pos, + lba, skip512, + reset, tracks, + spt, hpc, + mdma_mode, do_initial_read; + uint32_t secount, sector, + cylinder, head, + drive, cylprecomp, + cfg_spt, cfg_hpc, + lba_addr; + uint16_t *buffer; - int irqstat; - int service; - int lba; - int channel; - uint32_t lba_addr; - int skip512; - int blocksize, blockcount; - uint16_t dma_identify_data[3]; - int hdi,base; - int hdd_num; - uint8_t specify_success; - int mdma_mode; uint8_t *sector_buffer; - int do_initial_read; - int sector_pos; -} IDE; +} ide_t; extern int ideboard; +extern int ide_ter_enabled, ide_qua_enabled; -extern int ide_enable[5]; -extern int ide_irq[5]; - -extern IDE ide_drives[IDE_NUM + XTIDE_NUM]; +extern ide_t *ide_drives[IDE_NUM]; extern int64_t idecallback[5]; -extern void ide_irq_raise(IDE *ide); -extern void ide_irq_lower(IDE *ide); +extern void ide_irq_raise(ide_t *ide); +extern void ide_irq_lower(ide_t *ide); -extern void writeide(int ide_board, uint16_t addr, uint8_t val); -extern void writeidew(int ide_board, uint16_t val); -extern uint8_t readide(int ide_board, uint16_t addr); -extern uint16_t readidew(int ide_board); -extern void callbackide(int ide_board); +extern void * ide_xtide_init(void); +extern void ide_xtide_close(void); -extern void ide_set_bus_master(int (*read)(int channel, uint8_t *data, int transfer_length), int (*write)(int channel, uint8_t *data, int transfer_length), void (*set_irq)(int channel)); +extern void ide_writew(uint16_t addr, uint16_t val, void *priv); +extern void ide_write_devctl(uint16_t addr, uint8_t val, void *priv); +extern void ide_writeb(uint16_t addr, uint8_t val, void *priv); +extern uint8_t ide_readb(uint16_t addr, void *priv); +extern uint8_t ide_read_alt_status(uint16_t addr, void *priv); +extern uint16_t ide_readw(uint16_t addr, void *priv); + +extern void ide_set_bus_master(int (*read)(int channel, uint8_t *data, int transfer_length, void *priv), + int (*write)(int channel, uint8_t *data, int transfer_length, void *priv), + void (*set_irq)(int channel, void *priv), + void *priv0, void *priv1); extern void win_cdrom_eject(uint8_t id); extern void win_cdrom_reload(uint8_t id); @@ -81,36 +74,20 @@ extern void win_cdrom_reload(uint8_t id); extern void ide_set_base(int controller, uint16_t port); extern void ide_set_side(int controller, uint16_t port); -extern void ide_init_first(void); - -extern void ide_reset(void); -extern void ide_reset_hard(void); - -extern void ide_set_all_signatures(void); - -extern void ide_xtide_init(void); - extern void ide_pri_enable(void); -extern void ide_pri_enable_ex(void); extern void ide_pri_disable(void); extern void ide_sec_enable(void); extern void ide_sec_disable(void); -extern void ide_ter_enable(void); -extern void ide_ter_disable(void); -extern void ide_ter_init(void); -extern void ide_qua_enable(void); -extern void ide_qua_disable(void); -extern void ide_qua_init(void); extern void ide_set_callback(uint8_t channel, int64_t callback); extern void secondary_ide_check(void); extern void ide_padstr8(uint8_t *buf, int buf_size, const char *src); -extern void ide_destroy_buffers(void); -extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length); -extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length); -extern void (*ide_bus_master_set_irq)(int channel); +extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length, void *priv); +extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length, void *priv); +extern void (*ide_bus_master_set_irq)(int channel, void *priv); +extern void *ide_bus_master_priv[2]; #endif /*EMU_IDE_H*/ diff --git a/src/disk/hdc_mfm_at.c b/src/disk/hdc_mfm_at.c index 0879c75b5..de2bf728e 100644 --- a/src/disk/hdc_mfm_at.c +++ b/src/disk/hdc_mfm_at.c @@ -12,7 +12,7 @@ * based design. Most cards were WD1003-WA2 or -WAH, where the * -WA2 cards had a floppy controller as well (to save space.) * - * Version: @(#)hdc_mfm_at.c 1.0.13 2018/03/18 + * Version: @(#)hdc_mfm_at.c 1.0.17 2018/05/02 * * Authors: Sarah Walker, * Fred N. van Kempen, @@ -23,11 +23,13 @@ #define __USE_LARGEFILE64 #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../device.h" #include "../io.h" @@ -110,33 +112,43 @@ typedef struct { } mfm_t; -static __inline void irq_raise(mfm_t *mfm) -{ - /* If not already pending.. */ - if (! mfm->irqstat) { - /* If enabled in the control register.. */ - if (! (mfm->fdisk&0x02)) { - /* .. raise IRQ14. */ - picint(1<<14); - } +#ifdef ENABLE_MFM_AT_LOG +int mfm_at_do_log = ENABLE_MFM_AT_LOG; +#endif - /* Remember this. */ - mfm->irqstat = 1; + +static void +mfm_at_log(const char *fmt, ...) +{ +#ifdef ENABLE_MFM_AT_LOG + va_list ap; + + if (mfm_at_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } +#endif } -static __inline void irq_lower(mfm_t *mfm) +static inline void +irq_raise(mfm_t *mfm) { - /* If raised.. */ - if (mfm->irqstat) { - /* If enabled in the control register.. */ - if (! (mfm->fdisk&0x02)) { - /* .. drop IRQ14. */ - picintc(1<<14); - } + if (!(mfm->fdisk & 2)) + picint(1 << 14); + + mfm->irqstat = 1; +} + + +static inline void +irq_lower(mfm_t *mfm) +{ + if (mfm->irqstat) { + if (!(mfm->fdisk & 2)) + picintc(1 << 14); - /* Remember this. */ mfm->irqstat = 0; } } @@ -160,18 +172,18 @@ get_sector(mfm_t *mfm, off64_t *addr) drive_t *drive = &mfm->drives[mfm->drvsel]; if (drive->curcyl != mfm->cylinder) { - pclog("WD1003(%d) sector: wrong cylinder\n"); + mfm_at_log("WD1003(%d) sector: wrong cylinder\n"); return(1); } if (mfm->head > drive->cfg_hpc) { - pclog("WD1003(%d) get_sector: past end of configured heads\n", + mfm_at_log("WD1003(%d) get_sector: past end of configured heads\n", mfm->drvsel); return(1); } if (mfm->sector >= drive->cfg_spt+1) { - pclog("WD1003(%d) get_sector: past end of configured sectors\n", + mfm_at_log("WD1003(%d) get_sector: past end of configured sectors\n", mfm->drvsel); return(1); } @@ -179,12 +191,12 @@ get_sector(mfm_t *mfm, off64_t *addr) #if 1 /* We should check this in the SET_DRIVE_PARAMETERS command! --FvK */ if (mfm->head > drive->hpc) { - pclog("WD1003(%d) get_sector: past end of heads\n", mfm->drvsel); + mfm_at_log("WD1003(%d) get_sector: past end of heads\n", mfm->drvsel); return(1); } if (mfm->sector >= drive->spt+1) { - pclog("WD1003(%d) get_sector: past end of sectors\n", mfm->drvsel); + mfm_at_log("WD1003(%d) get_sector: past end of sectors\n", mfm->drvsel); return(1); } #endif @@ -221,7 +233,7 @@ mfm_cmd(mfm_t *mfm, uint8_t val) if (! drive->present) { /* This happens if sofware polls all drives. */ - pclog("WD1003(%d) command %02x on non-present drive\n", + mfm_at_log("WD1003(%d) command %02x on non-present drive\n", mfm->drvsel, val); mfm->command = 0xff; mfm->status = STAT_BUSY; @@ -233,24 +245,23 @@ mfm_cmd(mfm_t *mfm, uint8_t val) } irq_lower(mfm); + mfm->command = val; mfm->error = 0; switch (val & 0xf0) { case CMD_RESTORE: drive->steprate = (val & 0x0f); -#if ENABLE_HDC_LOG - pclog("WD1003(%d) restore, step=%d\n", + mfm_at_log("WD1003(%d) restore, step=%d\n", mfm->drvsel, drive->steprate); -#endif drive->curcyl = 0; mfm->status = STAT_READY|STAT_DSC; - mfm->command = 0x00; + mfm->command &= 0xf0; irq_raise(mfm); break; case CMD_SEEK: drive->steprate = (val & 0x0f); - mfm->command = (val & 0xf0); + mfm->command &= 0xf0; mfm->status = STAT_BUSY; timer_clock(); mfm->callback = 200LL*MFM_TIME; @@ -258,16 +269,15 @@ mfm_cmd(mfm_t *mfm, uint8_t val) break; default: + mfm->command = val; switch (val) { case CMD_READ: case CMD_READ+1: case CMD_READ+2: case CMD_READ+3: -#if ENABLE_HDC_LOG - pclog("WD1003(%d) read, opt=%d\n", + mfm_at_log("WD1003(%d) read, opt=%d\n", mfm->drvsel, val&0x03); -#endif - mfm->command = (val & 0xf0); + mfm->command &= 0xfc; if (val & 2) fatal("WD1003: READ with ECC\n"); mfm->status = STAT_BUSY; @@ -280,11 +290,9 @@ mfm_cmd(mfm_t *mfm, uint8_t val) case CMD_WRITE+1: case CMD_WRITE+2: case CMD_WRITE+3: -#if ENABLE_HDC_LOG - pclog("WD1003(%d) write, opt=%d\n", + mfm_at_log("WD1003(%d) write, opt=%d\n", mfm->drvsel, val & 0x03); -#endif - mfm->command = (val & 0xf0); + mfm->command &= 0xfc; if (val & 2) fatal("WD1003: WRITE with ECC\n"); mfm->status = STAT_DRQ|STAT_DSC; @@ -293,7 +301,7 @@ mfm_cmd(mfm_t *mfm, uint8_t val) case CMD_VERIFY: case CMD_VERIFY+1: - mfm->command = (val & 0xfe); + mfm->command &= 0xfe; mfm->status = STAT_BUSY; timer_clock(); mfm->callback = 200LL*MFM_TIME; @@ -301,13 +309,11 @@ mfm_cmd(mfm_t *mfm, uint8_t val) break; case CMD_FORMAT: - mfm->command = val; mfm->status = STAT_DRQ|STAT_BUSY; mfm->pos = 0; break; case CMD_DIAGNOSE: - mfm->command = val; mfm->status = STAT_BUSY; timer_clock(); mfm->callback = 200LL*MFM_TIME; @@ -335,11 +341,11 @@ mfm_cmd(mfm_t *mfm, uint8_t val) /* Only accept after RESET or DIAG. */ drive->cfg_spt = mfm->secount; drive->cfg_hpc = mfm->head+1; - pclog("WD1003(%d) parameters: tracks=%d, spt=%i, hpc=%i\n", + mfm_at_log("WD1003(%d) parameters: tracks=%d, spt=%i, hpc=%i\n", mfm->drvsel, drive->tracks, drive->cfg_spt, drive->cfg_hpc); } else { - pclog("WD1003(%d) parameters: tracks=%d,spt=%i,hpc=%i (IGNORED)\n", + mfm_at_log("WD1003(%d) parameters: tracks=%d,spt=%i,hpc=%i (IGNORED)\n", mfm->drvsel, drive->tracks, drive->cfg_spt, drive->cfg_hpc); } @@ -350,7 +356,7 @@ mfm_cmd(mfm_t *mfm, uint8_t val) break; default: - pclog("WD1003: bad command %02X\n", val); + mfm_at_log("WD1003: bad command %02X\n", val); mfm->status = STAT_BUSY; timer_clock(); mfm->callback = 200LL*MFM_TIME; @@ -373,7 +379,9 @@ mfm_writew(uint16_t port, uint16_t val, void *priv) mfm->pos = 0; mfm->status = STAT_BUSY; timer_clock(); - mfm->callback = 6LL*MFM_TIME; + /* 781.25 us per sector at 5 Mbit/s = 640 kB/s. */ + mfm->callback = ((3125LL * TIMER_USEC) / 4LL); + /* mfm->callback = 10LL * MFM_TIME; */ timer_update_outstanding(); } } @@ -384,9 +392,8 @@ mfm_write(uint16_t port, uint8_t val, void *priv) { mfm_t *mfm = (mfm_t *)priv; -#if ENABLE_HDC_LOG > 1 - pclog("WD1003 write(%04x, %02x)\n", port, val); -#endif + mfm_at_log("WD1003 write(%04x, %02x)\n", port, val); + switch (port) { case 0x01f0: /* data */ mfm_writew(port, val | (val << 8), priv); @@ -417,7 +424,7 @@ mfm_write(uint16_t port, uint8_t val, void *priv) mfm->drvsel = (val & 0x10) ? 1 : 0; if (mfm->drives[mfm->drvsel].present) mfm->status = STAT_READY|STAT_DSC; - else + else mfm->status = 0; return; @@ -428,21 +435,24 @@ mfm_write(uint16_t port, uint8_t val, void *priv) case 0x03f6: /* device control */ val &= 0x0f; if ((mfm->fdisk & 0x04) && !(val & 0x04)) { - mfm->status = STAT_BUSY; - mfm->reset = 1; timer_clock(); mfm->callback = 500LL*MFM_TIME; timer_update_outstanding(); + mfm->reset = 1; + mfm->status = STAT_BUSY; } if (val & 0x04) { /* Drive held in reset. */ - mfm->status = STAT_BUSY; - mfm->callback = 0LL; timer_clock(); + mfm->callback = 0LL; timer_update_outstanding(); + mfm->status = STAT_BUSY; } mfm->fdisk = val; + /* Lower IRQ on IRQ disable. */ + if ((val & 2) && !(mfm->fdisk & 0x02)) + picintc(1 << 14); break; } } @@ -465,7 +475,9 @@ mfm_readw(uint16_t port, void *priv) next_sector(mfm); mfm->status = STAT_BUSY; timer_clock(); - mfm->callback = 6LL*MFM_TIME; + /* 781.25 us per sector at 5 Mbit/s = 640 kB/s. */ + mfm->callback = ((3125LL * TIMER_USEC) / 4LL); + /* mfm->callback = 10LL * MFM_TIME; */ timer_update_outstanding(); } else { ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0); @@ -520,9 +532,8 @@ mfm_read(uint16_t port, void *priv) default: break; } -#if ENABLE_HDC_LOG > 1 - pclog("WD1003 read(%04x) = %02x\n", port, ret); -#endif + + mfm_at_log("WD1003 read(%04x) = %02x\n", port, ret); return(ret); } @@ -533,10 +544,9 @@ do_seek(mfm_t *mfm) { drive_t *drive = &mfm->drives[mfm->drvsel]; -#if ENABLE_HDC_LOG - pclog("WD1003(%d) seek(%d) max=%d\n", + mfm_at_log("WD1003(%d) seek(%d) max=%d\n", mfm->drvsel,mfm->cylinder,drive->tracks); -#endif + if (mfm->cylinder < drive->tracks) drive->curcyl = mfm->cylinder; else @@ -553,9 +563,8 @@ do_callback(void *priv) mfm->callback = 0LL; if (mfm->reset) { -#if ENABLE_HDC_LOG - pclog("WD1003(%d) reset\n", mfm->drvsel); -#endif + mfm_at_log("WD1003(%d) reset\n", mfm->drvsel); + mfm->status = STAT_READY|STAT_DSC; mfm->error = 1; mfm->secount = 1; @@ -575,20 +584,16 @@ do_callback(void *priv) switch (mfm->command) { case CMD_SEEK: -#if ENABLE_HDC_LOG - pclog("WD1003(%d) seek, step=%d\n", + mfm_at_log("WD1003(%d) seek, step=%d\n", mfm->drvsel, drive->steprate); -#endif do_seek(mfm); mfm->status = STAT_READY|STAT_DSC; irq_raise(mfm); break; case CMD_READ: -#if ENABLE_HDC_LOG - pclog("WD1003(%d) read(%d,%d,%d)\n", + mfm_at_log("WD1003(%d) read(%d,%d,%d)\n", mfm->drvsel, mfm->cylinder, mfm->head, mfm->sector); -#endif do_seek(mfm); if (get_sector(mfm, &addr)) { mfm->error = ERR_ID_NOT_FOUND; @@ -606,10 +611,8 @@ do_callback(void *priv) break; case CMD_WRITE: -#if ENABLE_HDC_LOG - pclog("WD1003(%d) write(%d,%d,%d)\n", + mfm_at_log("WD1003(%d) write(%d,%d,%d)\n", mfm->drvsel, mfm->cylinder, mfm->head, mfm->sector); -#endif do_seek(mfm); if (get_sector(mfm, &addr)) { mfm->error = ERR_ID_NOT_FOUND; @@ -619,26 +622,23 @@ do_callback(void *priv) } hdd_image_write(drive->hdd_num, addr, 1,(uint8_t *)mfm->buffer); + irq_raise(mfm); + mfm->secount = (mfm->secount - 1) & 0xff; mfm->status = STAT_READY|STAT_DSC; - mfm->secount = (mfm->secount - 1) & 0xff; if (mfm->secount) { /* More sectors to do.. */ mfm->status |= STAT_DRQ; mfm->pos = 0; next_sector(mfm); ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1); - } else { + } else ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0); - } - irq_raise(mfm); break; case CMD_VERIFY: -#if ENABLE_HDC_LOG - pclog("WD1003(%d) verify(%d,%d,%d)\n", + mfm_at_log("WD1003(%d) verify(%d,%d,%d)\n", mfm->drvsel, mfm->cylinder, mfm->head, mfm->sector); -#endif do_seek(mfm); mfm->pos = 0; mfm->status = STAT_READY|STAT_DSC; @@ -647,10 +647,8 @@ do_callback(void *priv) break; case CMD_FORMAT: -#if ENABLE_HDC_LOG - pclog("WD1003(%d) format(%d,%d)\n", + mfm_at_log("WD1003(%d) format(%d,%d)\n", mfm->drvsel, mfm->cylinder, mfm->head); -#endif do_seek(mfm); if (get_sector(mfm, &addr)) { mfm->error = ERR_ID_NOT_FOUND; @@ -667,9 +665,7 @@ do_callback(void *priv) break; case CMD_DIAGNOSE: -#if ENABLE_HDC_LOG - pclog("WD1003(%d) diag\n", mfm->drvsel); -#endif + mfm_at_log("WD1003(%d) diag\n", mfm->drvsel); drive->steprate = 0x0f; mfm->error = 1; mfm->status = STAT_READY|STAT_DSC; @@ -677,7 +673,7 @@ do_callback(void *priv) break; default: - pclog("WD1003(%d) callback on unknown command %02x\n", + mfm_at_log("WD1003(%d) callback on unknown command %02x\n", mfm->drvsel, mfm->command); mfm->status = STAT_READY|STAT_ERR|STAT_DSC; mfm->error = ERR_ABRT; @@ -712,7 +708,7 @@ mfm_init(const device_t *info) mfm_t *mfm; int c, d; - pclog("WD1003: ISA MFM/RLL Fixed Disk Adapter initializing ...\n"); + mfm_at_log("WD1003: ISA MFM/RLL Fixed Disk Adapter initializing ...\n"); mfm = malloc(sizeof(mfm_t)); memset(mfm, 0x00, sizeof(mfm_t)); @@ -721,7 +717,7 @@ mfm_init(const device_t *info) if ((hdd[d].bus == HDD_BUS_MFM) && (hdd[d].mfm_channel < MFM_NUM)) { loadhd(mfm, hdd[d].mfm_channel, d, hdd[d].fn); - pclog("WD1003(%d): (%ls) geometry %d/%d/%d\n", c, hdd[d].fn, + mfm_at_log("WD1003(%d): (%ls) geometry %d/%d/%d\n", c, hdd[d].fn, (int)hdd[d].tracks, (int)hdd[d].hpc, (int)hdd[d].spt); if (++c >= MFM_NUM) break; @@ -769,5 +765,5 @@ const device_t mfm_at_wd1003_device = { DEVICE_ISA | DEVICE_AT, 0, mfm_init, mfm_close, NULL, - NULL, NULL, NULL, NULL, NULL + NULL, NULL, NULL, NULL }; diff --git a/src/disk/hdc_mfm_xt.c b/src/disk/hdc_mfm_xt.c index 2eb2fd2c4..6d86fe070 100644 --- a/src/disk/hdc_mfm_xt.c +++ b/src/disk/hdc_mfm_xt.c @@ -41,7 +41,7 @@ * Since all controllers (including the ones made by DTC) use * (mostly) the same API, we keep them all in this module. * - * Version: @(#)hdc_mfm_xt.c 1.0.14 2018/03/18 + * Version: @(#)hdc_mfm_xt.c 1.0.17 2018/04/29 * * Authors: Sarah Walker, * Fred N. van Kempen, @@ -52,11 +52,13 @@ #define __USE_LARGEFILE64 #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../device.h" #include "../dma.h" @@ -71,7 +73,8 @@ #include "hdd.h" -#define MFM_TIME (2000LL*TIMER_USEC) +// #define MFM_TIME (2000LL*TIMER_USEC) +#define MFM_TIME (50LL*TIMER_USEC) #define XEBEC_BIOS_FILE L"roms/hdd/mfm_xebec/ibm_xebec_62x0822_1985.bin" #define DTC_BIOS_FILE L"roms/hdd/mfm_xebec/dtc_cxd21a.bin" @@ -152,6 +155,26 @@ typedef struct { #define ERR_ILLEGAL_SECTOR_ADDRESS 0x21 +#ifdef ENABLE_MFM_XT_LOG +int mfm_xt_do_log = ENABLE_MFM_XT_LOG; +#endif + + +static void +mfm_xt_log(const char *fmt, ...) +{ +#ifdef ENABLE_MFM_XT_LOG + va_list ap; + + if (mfm_xt_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + static uint8_t mfm_read(uint16_t port, void *priv) { @@ -278,7 +301,7 @@ mfm_error(mfm_t *mfm, uint8_t error) mfm->completion_byte |= 0x02; mfm->error = error; - pclog("mfm_error - %02x\n", mfm->error); + mfm_xt_log("mfm_error - %02x\n", mfm->error); } @@ -289,22 +312,22 @@ get_sector(mfm_t *mfm, off64_t *addr) int heads = drive->cfg_hpc; if (drive->current_cylinder != mfm->cylinder) { - pclog("mfm_get_sector: wrong cylinder\n"); + mfm_xt_log("mfm_get_sector: wrong cylinder\n"); mfm->error = ERR_ILLEGAL_SECTOR_ADDRESS; return(1); } if (mfm->head > heads) { - pclog("mfm_get_sector: past end of configured heads\n"); + mfm_xt_log("mfm_get_sector: past end of configured heads\n"); mfm->error = ERR_ILLEGAL_SECTOR_ADDRESS; return(1); } if (mfm->head > drive->hpc) { - pclog("mfm_get_sector: past end of heads\n"); + mfm_xt_log("mfm_get_sector: past end of heads\n"); mfm->error = ERR_ILLEGAL_SECTOR_ADDRESS; return(1); } if (mfm->sector >= 17) { - pclog("mfm_get_sector: past end of sectors\n"); + mfm_xt_log("mfm_get_sector: past end of sectors\n"); mfm->error = ERR_ILLEGAL_SECTOR_ADDRESS; return(1); } @@ -395,7 +418,7 @@ mfm_callback(void *priv) mfm->sector_count = mfm->command[4]; do { if (get_sector(mfm, &addr)) { - pclog("get_sector failed\n"); + mfm_xt_log("get_sector failed\n"); mfm_error(mfm, mfm->error); mfm_complete(mfm); return; @@ -422,14 +445,14 @@ mfm_callback(void *priv) mfm->head = mfm->command[1] & 0x1f; if (get_sector(mfm, &addr)) { - pclog("get_sector failed\n"); + mfm_xt_log("get_sector failed\n"); mfm_error(mfm, mfm->error); mfm_complete(mfm); return; } hdd_image_zero(drive->hdd_num, addr, 17); - + mfm_complete(mfm); break; @@ -470,7 +493,7 @@ mfm_callback(void *priv) int val = dma_channel_write(3, mfm->sector_buf[mfm->data_pos]); if (val == DMA_NODATA) { - pclog("CMD_READ_SECTORS out of data!\n"); + mfm_xt_log("CMD_READ_SECTORS out of data!\n"); mfm->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ; mfm->callback = MFM_TIME; return; @@ -543,7 +566,7 @@ mfm_callback(void *priv) int val = dma_channel_read(3); if (val == DMA_NODATA) { - pclog("CMD_WRITE_SECTORS out of data!\n"); + mfm_xt_log("CMD_WRITE_SECTORS out of data!\n"); mfm->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ; mfm->callback = MFM_TIME; return; @@ -618,7 +641,7 @@ mfm_callback(void *priv) case STATE_RECEIVED_DATA: drive->cfg_cyl = mfm->data[1] | (mfm->data[0] << 8); drive->cfg_hpc = mfm->data[2]; - pclog("Drive %i: cylinders=%i, heads=%i\n", mfm->drive_sel, drive->cfg_cyl, drive->cfg_hpc); + mfm_xt_log("Drive %i: cylinders=%i, heads=%i\n", mfm->drive_sel, drive->cfg_cyl, drive->cfg_hpc); mfm_complete(mfm); break; @@ -647,7 +670,7 @@ mfm_callback(void *priv) int val = dma_channel_read(3); if (val == DMA_NODATA) { - pclog("CMD_WRITE_SECTOR_BUFFER out of data!\n"); + mfm_xt_log("CMD_WRITE_SECTOR_BUFFER out of data!\n"); mfm->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ; mfm->callback = MFM_TIME; return; @@ -696,7 +719,7 @@ mfm_callback(void *priv) mfm->data[0] = drive->tracks & 0xff; mfm->data[1] = 17 | ((drive->tracks >> 2) & 0xc0); mfm->data[2] = drive->hpc-1; - pclog("Get drive params %02x %02x %02x %i\n", mfm->data[0], mfm->data[1], mfm->data[2], drive->tracks); + mfm_xt_log("Get drive params %02x %02x %02x %i\n", mfm->data[0], mfm->data[1], mfm->data[2], drive->tracks); break; case STATE_SENT_DATA: @@ -757,7 +780,7 @@ loadhd(mfm_t *mfm, int c, int d, const wchar_t *fn) { drive_t *drive = &mfm->drives[d]; - if (! hdd_image_load(d)) { + if (! hdd_image_load(c)) { drive->present = 0; return; } @@ -802,7 +825,7 @@ mfm_set_switches(mfm_t *mfm) } if (c == 4) - pclog("WARNING: Drive %c: has format not supported by Fixed Disk Adapter", d ? 'D' : 'C'); + mfm_xt_log("WARNING: Drive %c: has format not supported by Fixed Disk Adapter", d ? 'D' : 'C'); } } @@ -815,16 +838,16 @@ xebec_init(const device_t *info) mfm_t *xebec = malloc(sizeof(mfm_t)); memset(xebec, 0x00, sizeof(mfm_t)); - pclog("MFM: looking for disks..\n"); + mfm_xt_log("MFM: looking for disks..\n"); for (i=0; i MFM_NUM) break; } } - pclog("MFM: %d disks loaded.\n", c); + mfm_xt_log("MFM: %d disks loaded.\n", c); mfm_set_switches(xebec); @@ -859,7 +882,7 @@ mfm_close(void *priv) static int xebec_available(void) { - return(rom_present(XEBEC_BIOS_FILE)); + return(rom_present(XEBEC_BIOS_FILE)); } @@ -868,8 +891,7 @@ const device_t mfm_xt_xebec_device = { DEVICE_ISA, 0, xebec_init, mfm_close, NULL, - xebec_available, NULL, NULL, NULL, - NULL + xebec_available, NULL, NULL, NULL }; @@ -881,16 +903,16 @@ dtc5150x_init(const device_t *info) mfm_t *dtc = malloc(sizeof(mfm_t)); memset(dtc, 0x00, sizeof(mfm_t)); - pclog("MFM: looking for disks..\n"); + mfm_xt_log("MFM: looking for disks..\n"); for (i=0; i MFM_NUM) break; } } - pclog("MFM: %d disks loaded.\n", c); + mfm_xt_log("MFM: %d disks loaded.\n", c); dtc->switches = 0xff; @@ -923,6 +945,5 @@ const device_t mfm_xt_dtc5150x_device = { DEVICE_ISA, 0, dtc5150x_init, mfm_close, NULL, - dtc5150x_available, NULL, NULL, NULL, - NULL + dtc5150x_available, NULL, NULL, NULL }; diff --git a/src/disk/hdc_xta.c b/src/disk/hdc_xta.c new file mode 100644 index 000000000..00528b096 --- /dev/null +++ b/src/disk/hdc_xta.c @@ -0,0 +1,1161 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of a generic IDE-XTA disk controller. + * + * XTA is the acronym for 'XT-Attached', which was basically + * the XT-counterpart to what we know now as IDE (which is + * also named ATA - AT Attachment.) The basic ideas was to + * put the actual drive controller electronics onto the drive + * itself, and have the host machine just talk to that using + * a simpe, standardized I/O path- hence the name IDE, for + * Integrated Drive Electronics. + * + * In the ATA version of IDE, the programming interface of + * the IBM PC/AT (which used the Western Digitial 1002/1003 + * controllers) was kept, and, so, ATA-IDE assumes a 16bit + * data path: it reads and writes 16bit words of data. The + * disk drives for this bus commonly have an 'A' suffix to + * identify them as 'ATBUS'. + * + * In XTA-IDE, which is slightly older, the programming + * interface of the IBM PC/XT (which used the MFM controller + * from Xebec) was kept, and, so, it uses an 8bit data path. + * Disk drives for this bus commonly have the 'X' suffix to + * mark them as being for this XTBUS variant. + * + * So, XTA and ATA try to do the same thing, but they use + * different ways to achive their goal. + * + * Also, XTA is **not** the same as XTIDE. XTIDE is a modern + * variant of ATA-IDE, but retro-fitted for use on 8bit XT + * systems: an extra register is used to deal with the extra + * data byte per transfer. XTIDE uses regular IDE drives, + * and uses the regular ATA/IDE programming interface, just + * with the extra register. + * + * NOTE: This driver implements both the 'standard' XTA interface, + * sold by Western Digital as the WDXT-140 (no BIOS) and the + * WDXT-150 (with BIOS), as well as some variants customized + * for specific machines. + * + * NOTE: The XTA interface is 0-based for sector numbers !! + * + * Version: @(#)hdc_ide_xta.c 1.0.8 2018/04/29 + * + * Author: Fred N. van Kempen, + * + * Based on my earlier HD20 driver for the EuroPC. + * + * Copyright 2017,2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#define __USE_LARGEFILE64 +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include "../86box.h" +#include "../io.h" +#include "../dma.h" +#include "../pic.h" +#include "../mem.h" +#include "../rom.h" +#include "../device.h" +#include "../timer.h" +#include "../plat.h" +#include "../ui.h" +#include "hdc.h" +#include "hdd.h" + + +#define HDC_TIME (50*TIMER_USEC) + +#define WD_BIOS_FILE L"roms/hdd/xta/idexywd2.bin" + + +enum { + STATE_IDLE = 0, + STATE_RECV, + STATE_RDATA, + STATE_RDONE, + STATE_SEND, + STATE_SDATA, + STATE_SDONE, + STATE_COMPL +}; + + +/* Command values. */ +#define CMD_TEST_READY 0x00 +#define CMD_RECALIBRATE 0x01 + /* unused 0x02 */ +#define CMD_READ_SENSE 0x03 +#define CMD_FORMAT_DRIVE 0x04 +#define CMD_READ_VERIFY 0x05 +#define CMD_FORMAT_TRACK 0x06 +#define CMD_FORMAT_BAD_TRACK 0x07 +#define CMD_READ_SECTORS 0x08 + /* unused 0x09 */ +#define CMD_WRITE_SECTORS 0x0a +#define CMD_SEEK 0x0b +#define CMD_SET_DRIVE_PARAMS 0x0c +#define CMD_READ_ECC_BURST 0x0d +#define CMD_READ_SECTOR_BUFFER 0x0e +#define CMD_WRITE_SECTOR_BUFFER 0x0f +#define CMD_RAM_DIAGS 0xe0 + /* unused 0xe1 */ + /* unused 0xe2 */ +#define CMD_DRIVE_DIAGS 0xe3 +#define CMD_CTRL_DIAGS 0xe4 +#define CMD_READ_LONG 0xe5 +#define CMD_WRITE_LONG 0xe6 + +/* Status register (reg 1) values. */ +#define STAT_REQ 0x01 /* controller needs data transfer */ +#define STAT_IO 0x02 /* direction of transfer (TO bus) */ +#define STAT_CD 0x04 /* transfer of Command or Data */ +#define STAT_BSY 0x08 /* controller is busy */ +#define STAT_DRQ 0x10 /* DMA requested */ +#define STAT_IRQ 0x20 /* interrupt requested */ +#define STAT_DCB 0x80 /* not seen by driver */ + +/* Sense Error codes. */ +#define ERR_NOERROR 0x00 /* no error detected */ +#define ERR_NOINDEX 0x01 /* drive did not detect IDX pulse */ +#define ERR_NOSEEK 0x02 /* drive did not complete SEEK */ +#define ERR_WRFAULT 0x03 /* write fault during last cmd */ +#define ERR_NOTRDY 0x04 /* drive did not go READY after cmd */ +#define ERR_NOTRK000 0x06 /* drive did not see TRK0 signal */ +#define ERR_LONGSEEK 0x08 /* long seek in progress */ +#define ERR_IDREAD 0x10 /* ECC error during ID field */ +#define ERR_DATA 0x11 /* uncorrectable ECC err in data */ +#define ERR_NOMARK 0x12 /* no address mark detected */ +#define ERR_NOSECT 0x14 /* sector not found */ +#define ERR_SEEK 0x15 /* seek error */ +#define ERR_ECCDATA 0x18 /* ECC corrected data */ +#define ERR_BADTRK 0x19 /* bad track detected */ +#define ERR_ILLCMD 0x20 /* invalid command received */ +#define ERR_ILLADDR 0x21 /* invalid disk address received */ +#define ERR_BADRAM 0x30 /* bad RAM in sector data buffer */ +#define ERR_BADROM 0x31 /* bad checksum in ROM test */ +#define ERR_BADECC 0x32 /* ECC polynomial generator bad */ + +/* Completion Byte fields. */ +#define COMP_DRIVE 0x20 +#define COMP_ERR 0x02 + +#define IRQ_ENA 0x02 +#define DMA_ENA 0x01 + + +/* The device control block (6 bytes) */ +#pragma pack(push,1) +typedef struct { + uint8_t cmd; /* [7:5] class, [4:0] opcode */ + + uint8_t head :5, /* [4:0] head number */ + drvsel :1, /* [5] drive select */ + mbz :2; /* [7:6] 00 */ + + uint8_t sector :6, /* [5:0] sector number 0-63 */ + cyl_high :2; /* [7:6] cylinder [9:8] bits */ + + uint8_t cyl_low; /* [7:0] cylinder [7:0] bits */ + + uint8_t count; /* [7:0] blk count / interleave */ + + uint8_t ctrl; /* [7:0] control field */ +} dcb_t; +#pragma pack(pop) + +/* The (configured) Drive Parameters. */ +#pragma pack(push,1) +typedef struct { + uint8_t cyl_high; /* (MSB) number of cylinders */ + uint8_t cyl_low; /* (LSB) number of cylinders */ + uint8_t heads; /* number of heads per cylinder */ + uint8_t rwc_high; /* (MSB) reduced write current cylinder */ + uint8_t rwc_low; /* (LSB) reduced write current cylinder */ + uint8_t wp_high; /* (MSB) write precompensation cylinder */ + uint8_t wp_low; /* (LSB) write precompensation cylinder */ + uint8_t maxecc; /* max ECC data burst length */ +} dprm_t; +#pragma pack(pop) + +/* Define an attached drive. */ +typedef struct { + int8_t id, /* drive ID on bus */ + present, /* drive is present */ + hdd_num, /* index to global disk table */ + type; /* drive type ID */ + + uint16_t cur_cyl; /* last known position of heads */ + + uint8_t spt, /* active drive parameters */ + hpc; + uint16_t tracks; + + uint8_t cfg_spt, /* configured drive parameters */ + cfg_hpc; + uint16_t cfg_tracks; +} drive_t; + + +typedef struct { + const char *name; /* controller name */ + + uint16_t base; /* controller base I/O address */ + int8_t irq; /* controller IRQ channel */ + int8_t dma; /* controller DMA channel */ + int8_t type; /* controller type ID */ + + uint32_t rom_addr; /* address where ROM is */ + rom_t bios_rom; /* descriptor for the BIOS */ + + /* Controller state. */ + int8_t state; /* controller state */ + uint8_t sense; /* current SENSE ERROR value */ + uint8_t status; /* current operational status */ + uint8_t intr; + int64_t callback; + + /* Data transfer. */ + int16_t buf_idx, /* buffer index and pointer */ + buf_len; + uint8_t *buf_ptr; + + /* Current operation parameters. */ + dcb_t dcb; /* device control block */ + uint16_t track; /* requested track# */ + uint8_t head, /* requested head# */ + sector, /* requested sector# */ + comp; /* operation completion byte */ + int count; /* requested sector count */ + + drive_t drives[XTA_NUM]; /* the attached drive(s) */ + + uint8_t data[512]; /* data buffer */ + uint8_t sector_buf[512]; /* sector buffer */ +} hdc_t; + + +#ifdef ENABLE_XTA_LOG +int xta_do_log = ENABLE_XTA_LOG; +#endif + + +static void +xta_log(const char *fmt, ...) +{ +#ifdef ENABLE_XTA_LOG + va_list ap; + + if (xta_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + +static void +set_intr(hdc_t *dev) +{ + dev->status = STAT_REQ|STAT_CD|STAT_IO|STAT_BSY; + dev->state = STATE_COMPL; + + if (dev->intr & IRQ_ENA) { + dev->status |= STAT_IRQ; + picint(1 << dev->irq); + } +} + + +/* Get the logical (block) address of a CHS triplet. */ +static int +get_sector(hdc_t *dev, drive_t *drive, off64_t *addr) +{ + if (drive->cur_cyl != dev->track) { + xta_log("%s: get_sector: wrong cylinder %d/%d\n", + dev->name, drive->cur_cyl, dev->track); + dev->sense = ERR_ILLADDR; + return(1); + } + + if (dev->head >= drive->hpc) { + xta_log("%s: get_sector: past end of heads\n", dev->name); + dev->sense = ERR_ILLADDR; + return(1); + } + + if (dev->sector >= drive->spt) { + xta_log("%s: get_sector: past end of sectors\n", dev->name); + dev->sense = ERR_ILLADDR; + return(1); + } + + /* Calculate logical address (block number) of desired sector. */ + *addr = ((((off64_t) dev->track*drive->hpc) + \ + dev->head)*drive->spt) + dev->sector; + + return(0); +} + + +static void +next_sector(hdc_t *dev, drive_t *drive) +{ + if (++dev->sector >= drive->spt) { + dev->sector = 0; + if (++dev->head >= drive->hpc) { + dev->head = 0; + dev->track++; + if (++drive->cur_cyl >= drive->tracks) + drive->cur_cyl = (drive->tracks - 1); + } + } +} + + +/* Perform the seek operation. */ +static void +do_seek(hdc_t *dev, drive_t *drive, int cyl) +{ + dev->track = cyl; + + if (dev->track >= drive->tracks) + drive->cur_cyl = (drive->tracks - 1); + else + drive->cur_cyl = dev->track; + + if (drive->cur_cyl < 0) + drive->cur_cyl = 0; +} + + +/* Format a track or an entire drive. */ +static void +do_format(hdc_t *dev, drive_t *drive, dcb_t *dcb) +{ + int start_cyl, end_cyl; + int start_hd, end_hd; + off64_t addr; + int h, s; + + /* Get the parameters from the DCB. */ + if (dcb->cmd == CMD_FORMAT_DRIVE) { + start_cyl = 0; + start_hd = 0; + end_cyl = drive->tracks; + end_hd = drive->hpc; + } else { + start_cyl = (dcb->cyl_low | (dcb->cyl_high << 8)); + start_hd = dcb->head; + end_cyl = start_cyl + 1; + end_hd = start_hd + 1; + } + + switch (dev->state) { + case STATE_IDLE: + /* Seek to cylinder. */ + do_seek(dev, drive, start_cyl); + dev->head = dcb->head; + dev->sector = 0; + + /* Activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 1); + +do_fmt: + /* + * For now, we don't use the interleave factor (in + * dcb->count), although we should one day use an + * image format that can handle it.. + * + * That said, we have been given a sector_buf of + * data to fill the sectors with, so we will use + * that at least. + */ + for (h = start_hd; h < end_hd; h++) { + for (s = 0; s < drive->spt; s++) { + /* Set the sector we need to write. */ + dev->head = h; + dev->sector = s; + + /* Get address of sector to write. */ + if (get_sector(dev, drive, &addr)) break; + + /* Write the block to the image. */ + hdd_image_write(drive->hdd_num, addr, 1, + (uint8_t *)dev->sector_buf); + } + } + + /* One more track done. */ + if (++start_cyl == end_cyl) break; + + /* This saves us a LOT of code. */ + goto do_fmt; + } + + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); +} + + +/* Execute the DCB we just received. */ +static void +hdc_callback(void *priv) +{ + hdc_t *dev = (hdc_t *)priv; + dcb_t *dcb = &dev->dcb; + drive_t *drive; + dprm_t *params; + off64_t addr; + int no_data = 0; + int val; + + /* Cancel timer. */ + dev->callback = 0; + + drive = &dev->drives[dcb->drvsel]; + dev->comp = (dcb->drvsel) ? COMP_DRIVE : 0x00; + dev->status |= STAT_DCB; + + switch (dcb->cmd) { + case CMD_TEST_READY: + if (! drive->present) { + dev->comp |= COMP_ERR; + dev->sense = ERR_NOTRDY; + } + set_intr(dev); + break; + + case CMD_RECALIBRATE: + if (! drive->present) { + dev->comp |= COMP_ERR; + dev->sense = ERR_NOTRDY; + } else { + dev->track = drive->cur_cyl = 0; + } + set_intr(dev); + break; + + case CMD_READ_SENSE: + switch(dev->state) { + case STATE_IDLE: + dev->buf_idx = 0; + dev->buf_len = 4; + dev->buf_ptr = dev->data; + dev->buf_ptr[0] = dev->sense; + dev->buf_ptr[1] = dcb->drvsel ? 0x20 : 0x00; + dev->buf_ptr[2] = (drive->cur_cyl >> 2) | \ + (dev->sector & 0x3f); + dev->buf_ptr[3] = (drive->cur_cyl & 0xff); + dev->sense = ERR_NOERROR; + dev->status |= (STAT_IO | STAT_REQ); + dev->state = STATE_SDATA; + break; + + case STATE_SDONE: + set_intr(dev); + } + break; + + case CMD_READ_VERIFY: + no_data = 1; + /*FALLTHROUGH*/ + + case CMD_READ_SECTORS: + if (! drive->present) { + dev->comp |= COMP_ERR; + dev->sense = ERR_NOTRDY; + set_intr(dev); + break; + } + + switch (dev->state) { + case STATE_IDLE: + /* Seek to cylinder. */ + do_seek(dev, drive, + (dcb->cyl_low|(dcb->cyl_high<<8))); + dev->head = dcb->head; + dev->sector = dcb->sector; + + /* Get sector count; count=0 means 256. */ + dev->count = (int)dcb->count; + if (dev->count == 0) + dev->count = 256; + dev->buf_len = 512; + + dev->state = STATE_SEND; + /*FALLTHROUGH*/ + + case STATE_SEND: + /* Activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 1); +do_send: + /* Get address of sector to load. */ + if (get_sector(dev, drive, &addr)) { + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + dev->comp |= COMP_ERR; + set_intr(dev); + return; + } + + /* Read the block from the image. */ + hdd_image_read(drive->hdd_num, addr, 1, + (uint8_t *)dev->sector_buf); + + /* Ready to transfer the data out. */ + dev->state = STATE_SDATA; + dev->buf_idx = 0; + if (no_data) { + /* Delay a bit, no actual transfer. */ + dev->callback = HDC_TIME; + } else { + if (dev->intr & DMA_ENA) { + /* DMA enabled. */ + dev->buf_ptr = dev->sector_buf; + dev->callback = HDC_TIME; + } else { + /* Copy from sector to data. */ + memcpy(dev->data, + dev->sector_buf, + dev->buf_len); + dev->buf_ptr = dev->data; + + dev->status |= (STAT_IO | STAT_REQ); + } + } + break; + + case STATE_SDATA: + if (! no_data) { + /* Perform DMA. */ + while (dev->buf_idx < dev->buf_len) { + val = dma_channel_write(dev->dma, + *dev->buf_ptr); + if (val == DMA_NODATA) { + xta_log("%s: CMD_READ_SECTORS out of data (idx=%d, len=%d)!\n", dev->name, dev->buf_idx, dev->buf_len); + + dev->status |= (STAT_CD | STAT_IO| STAT_REQ); + dev->callback = HDC_TIME; + return; + } + dev->buf_ptr++; + dev->buf_idx++; + } + } + dev->callback = HDC_TIME; + dev->state = STATE_SDONE; + break; + + case STATE_SDONE: + dev->buf_idx = 0; + if (--dev->count == 0) { + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + + set_intr(dev); + return; + } + + /* Addvance to next sector. */ + next_sector(dev, drive); + + /* This saves us a LOT of code. */ + dev->state = STATE_SEND; + goto do_send; + } + break; + +#if 0 + case CMD_WRITE_VERIFY: + no_data = 1; + /*FALLTHROUGH*/ +#endif + + case CMD_WRITE_SECTORS: + if (! drive->present) { + dev->comp |= COMP_ERR; + dev->sense = ERR_NOTRDY; + set_intr(dev); + break; + } + + switch (dev->state) { + case STATE_IDLE: + /* Seek to cylinder. */ + do_seek(dev, drive, + (dcb->cyl_low|(dcb->cyl_high<<8))); + dev->head = dcb->head; + dev->sector = dcb->sector; + + /* Get sector count; count=0 means 256. */ + dev->count = (int)dev->dcb.count; + if (dev->count == 0) + dev->count = 256; + dev->buf_len = 512; + + dev->state = STATE_RECV; + /*FALLTHROUGH*/ + + case STATE_RECV: + /* Activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 1); +do_recv: + /* Ready to transfer the data in. */ + dev->state = STATE_RDATA; + dev->buf_idx = 0; + if (no_data) { + /* Delay a bit, no actual transfer. */ + dev->callback = HDC_TIME; + } else { + if (dev->intr & DMA_ENA) { + /* DMA enabled. */ + dev->buf_ptr = dev->sector_buf; + dev->callback = HDC_TIME; + } else { + /* No DMA, do PIO. */ + dev->buf_ptr = dev->data; + dev->status |= STAT_REQ; + } + } + break; + + case STATE_RDATA: + if (! no_data) { + /* Perform DMA. */ + dev->status = STAT_BSY; + while (dev->buf_idx < dev->buf_len) { + val = dma_channel_read(dev->dma); + if (val == DMA_NODATA) { + xta_log("%s: CMD_WRITE_SECTORS out of data (idx=%d, len=%d)!\n", dev->name, dev->buf_idx, dev->buf_len); + + xta_log("%s: CMD_WRITE_SECTORS out of data!\n", dev->name); + dev->status |= (STAT_CD | STAT_IO | STAT_REQ); + dev->callback = HDC_TIME; + return; + } + + dev->buf_ptr[dev->buf_idx] = (val & 0xff); + dev->buf_idx++; + } + dev->state = STATE_RDONE; + dev->callback = HDC_TIME; + } + break; + + case STATE_RDONE: + /* Copy from data to sector if PIO. */ + if (! (dev->intr & DMA_ENA)) + memcpy(dev->sector_buf, dev->data, + dev->buf_len); + + /* Get address of sector to write. */ + if (get_sector(dev, drive, &addr)) { + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + + dev->comp |= COMP_ERR; + set_intr(dev); + return; + } + + /* Write the block to the image. */ + hdd_image_write(drive->hdd_num, addr, 1, + (uint8_t *)dev->sector_buf); + + dev->buf_idx = 0; + if (--dev->count == 0) { + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + + set_intr(dev); + return; + } + + /* Advance to next sector. */ + next_sector(dev, drive); + + /* This saves us a LOT of code. */ + dev->state = STATE_RECV; + goto do_recv; + } + break; + + case CMD_FORMAT_DRIVE: + case CMD_FORMAT_TRACK: + if (drive->present) { + do_format(dev, drive, dcb); + } else { + dev->comp |= COMP_ERR; + dev->sense = ERR_NOTRDY; + } + set_intr(dev); + break; + + case CMD_SEEK: + /* Seek to cylinder. */ + val = (dcb->cyl_low | (dcb->cyl_high << 8)); + if (drive->present) { + do_seek(dev, drive, val); + if (val != drive->cur_cyl) { + dev->comp |= COMP_ERR; + dev->sense = ERR_SEEK; + } + } else { + dev->comp |= COMP_ERR; + dev->sense = ERR_NOTRDY; + } + set_intr(dev); + break; + + case CMD_SET_DRIVE_PARAMS: + switch(dev->state) { + case STATE_IDLE: + dev->state = STATE_RDATA; + dev->buf_idx = 0; + dev->buf_len = sizeof(dprm_t); + dev->buf_ptr = (uint8_t *)dev->data; + dev->status |= STAT_REQ; + break; + + case STATE_RDONE: + params = (dprm_t *)dev->data; + drive->tracks = + (params->cyl_high << 8) | params->cyl_low; + drive->hpc = params->heads; + drive->spt = 17 /*hardcoded*/; + dev->status &= ~STAT_REQ; + set_intr(dev); + break; + } + break; + + case CMD_WRITE_SECTOR_BUFFER: + switch (dev->state) { + case STATE_IDLE: + dev->buf_idx = 0; + dev->buf_len = 512; + dev->state = STATE_RDATA; + if (dev->intr & DMA_ENA) { + dev->buf_ptr = dev->sector_buf; + dev->callback = HDC_TIME; + } else { + dev->buf_ptr = dev->data; + dev->status |= STAT_REQ; + } + break; + + case STATE_RDATA: + if (dev->intr & DMA_ENA) { + /* Perform DMA. */ + while (dev->buf_idx < dev->buf_len) { + val = dma_channel_read(dev->dma); + if (val == DMA_NODATA) { + xta_log("%s: CMD_WRITE_BUFFER out of data!\n", dev->name); + dev->status |= (STAT_CD | STAT_IO | STAT_REQ); + dev->callback = HDC_TIME; + return; + } + + dev->buf_ptr[dev->buf_idx] = (val & 0xff); + dev->buf_idx++; + } + dev->state = STATE_RDONE; + dev->callback = HDC_TIME; + } + break; + + case STATE_RDONE: + if (! (dev->intr & DMA_ENA)) + memcpy(dev->sector_buf, + dev->data, dev->buf_len); + set_intr(dev); + break; + } + break; + + case CMD_RAM_DIAGS: + switch(dev->state) { + case STATE_IDLE: + dev->state = STATE_RDONE; + dev->callback = 5*HDC_TIME; + break; + + case STATE_RDONE: + set_intr(dev); + break; + } + break; + + case CMD_DRIVE_DIAGS: + switch(dev->state) { + case STATE_IDLE: + if (drive->present) { + dev->state = STATE_RDONE; + dev->callback = 5*HDC_TIME; + } else { + dev->comp |= COMP_ERR; + dev->sense = ERR_NOTRDY; + set_intr(dev); + } + break; + + case STATE_RDONE: + set_intr(dev); + break; + } + break; + + case CMD_CTRL_DIAGS: + switch(dev->state) { + case STATE_IDLE: + dev->state = STATE_RDONE; + dev->callback = 10*HDC_TIME; + break; + + case STATE_RDONE: + set_intr(dev); + break; + } + break; + + default: + xta_log("%s: unknown command - %02x\n", dev->name, dcb->cmd); + dev->comp |= COMP_ERR; + dev->sense = ERR_ILLCMD; + set_intr(dev); + } +} + + +/* Read one of the controller registers. */ +static uint8_t +hdc_read(uint16_t port, void *priv) +{ + hdc_t *dev = (hdc_t *)priv; + uint8_t ret = 0xff; + + switch (port & 7) { + case 0: /* DATA register */ + dev->status &= ~STAT_IRQ; + + if (dev->state == STATE_SDATA) { + if (dev->buf_idx > dev->buf_len) { + xta_log("%s: read with empty buffer!\n", + dev->name); + dev->comp |= COMP_ERR; + dev->sense = ERR_ILLCMD; + break; + } + + ret = dev->buf_ptr[dev->buf_idx]; + if (++dev->buf_idx == dev->buf_len) { + /* All data sent. */ + dev->status &= ~STAT_REQ; + dev->state = STATE_SDONE; + dev->callback = HDC_TIME; + } + } else if (dev->state == STATE_COMPL) { +xta_log("DCB=%02X status=%02X comp=%02X\n", dev->dcb.cmd, dev->status, dev->comp); + ret = dev->comp; + dev->status = 0x00; + dev->state = STATE_IDLE; + } + break; + + case 1: /* STATUS register */ + ret = (dev->status & ~STAT_DCB); + break; + + case 2: /* "read option jumpers" */ + ret = 0xff; /* all switches off */ + break; + } + + return(ret); +} + + +/* Write to one of the controller registers. */ +static void +hdc_write(uint16_t port, uint8_t val, void *priv) +{ + hdc_t *dev = (hdc_t *)priv; + + switch (port & 7) { + case 0: /* DATA register */ + if (dev->state == STATE_RDATA) { + if (! (dev->status & STAT_REQ)) { + xta_log("%s: not ready for command/data!\n", dev->name); + dev->comp |= COMP_ERR; + dev->sense = ERR_ILLCMD; + break; + } + + if (dev->buf_idx >= dev->buf_len) { + xta_log("%s: write with full buffer!\n", dev->name); + dev->comp |= COMP_ERR; + dev->sense = ERR_ILLCMD; + break; + } + + /* Store the data into the buffer. */ + dev->buf_ptr[dev->buf_idx] = val; + if (++dev->buf_idx == dev->buf_len) { + /* We got all the data we need. */ + dev->status &= ~STAT_REQ; + if (dev->status & STAT_DCB) + dev->state = STATE_RDONE; + else + dev->state = STATE_IDLE; + dev->status &= ~STAT_CD; + dev->callback = HDC_TIME; + } + } + break; + + case 1: /* RESET register */ + dev->sense = 0x00; + dev->state = STATE_IDLE; + break; + + case 2: /* "controller-select" */ + /* Reset the DCB buffer. */ + dev->buf_idx = 0; + dev->buf_len = sizeof(dcb_t); + dev->buf_ptr = (uint8_t *)&dev->dcb; + dev->state = STATE_RDATA; + dev->status = (STAT_BSY | STAT_CD | STAT_REQ); + break; + + case 3: /* DMA/IRQ intr register */ +//xta_log("%s: WriteMASK(%02X)\n", dev->name, val); + dev->intr = val; + break; + } +} + + +static void * +xta_init(const device_t *info) +{ + drive_t *drive; + wchar_t *fn = NULL; + hdc_t *dev; + int c, i; + int max = XTA_NUM; + + /* Allocate and initialize device block. */ + dev = malloc(sizeof(hdc_t)); + memset(dev, 0x00, sizeof(hdc_t)); + dev->type = info->local; + + /* Do per-controller-type setup. */ + switch(dev->type) { + case 0: /* WDXT-150, with BIOS */ + dev->name = "WDXT-150"; + dev->base = device_get_config_hex16("base"); + dev->irq = device_get_config_int("irq"); + dev->rom_addr = device_get_config_hex20("bios_addr"); + dev->dma = 3; + fn = WD_BIOS_FILE; + max = 1; + break; + + case 1: /* EuroPC */ + dev->name = "HD20"; + dev->base = 0x0320; + dev->irq = 5; + dev->dma = 3; + break; + } + + xta_log("%s: initializing (I/O=%04X, IRQ=%d, DMA=%d", + dev->name, dev->base, dev->irq, dev->dma); + if (dev->rom_addr != 0x000000) + xta_log(", BIOS=%06X", dev->rom_addr); + xta_log(")\n"); + + /* Load any disks for this device class. */ + c = 0; + for (i = 0; i < HDD_NUM; i++) { + if ((hdd[i].bus == HDD_BUS_XTA) && (hdd[i].xta_channel < max)) { + drive = &dev->drives[hdd[i].xta_channel]; + + if (! hdd_image_load(i)) { + drive->present = 0; + continue; + } + drive->id = c; + drive->hdd_num = i; + drive->present = 1; + + /* These are the "hardware" parameters (from the image.) */ + drive->cfg_spt = (uint8_t)(hdd[i].spt & 0xff); + drive->cfg_hpc = (uint8_t)(hdd[i].hpc & 0xff); + drive->cfg_tracks = (uint16_t)hdd[i].tracks; + + /* Use them as "configured" parameters until overwritten. */ + drive->spt = drive->cfg_spt; + drive->hpc = drive->cfg_hpc; + drive->tracks = drive->cfg_tracks; + + xta_log("%s: drive%d (cyl=%d,hd=%d,spt=%d), disk %d\n", + dev->name, hdd[i].xta_channel, drive->tracks, + drive->hpc, drive->spt, i); + + if (++c > max) break; + } + } + + /* Enable the I/O block. */ + io_sethandler(dev->base, 4, + hdc_read,NULL,NULL, hdc_write,NULL,NULL, dev); + + /* Load BIOS if it has one. */ + if (dev->rom_addr != 0x000000) + rom_init(&dev->bios_rom, fn, + dev->rom_addr, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); + + /* Create a timer for command delays. */ + timer_add(hdc_callback, &dev->callback, &dev->callback, dev); + + return(dev); +} + + +static void +xta_close(void *priv) +{ + hdc_t *dev = (hdc_t *)priv; + drive_t *drive; + int d; + + /* Remove the I/O handler. */ + io_removehandler(dev->base, 4, + hdc_read,NULL,NULL, hdc_write,NULL,NULL, dev); + + /* Close all disks and their images. */ + for (d = 0; d < XTA_NUM; d++) { + drive = &dev->drives[d]; + + hdd_image_close(drive->hdd_num); + } + + /* Release the device. */ + free(dev); +} + + +static const device_config_t wdxt150_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x0320, /*W2*/ + { + { + "320H", 0x0320 + }, + { + "324H", 0x0324 + }, + { + "" + } + }, + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 5, /*W3*/ + { + { + "IRQ 5", 5 + }, + { + "IRQ 4", 4 + }, + { + "" + } + }, + }, + { + "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xc8000, /*W1*/ + { + { + "C800H", 0xc8000 + }, + { + "CA00H", 0xca000 + }, + { + "" + } + }, + }, + { + "", "", -1 + } +}; + + +const device_t xta_wdxt150_device = { + "WDXT-150 Fixed Disk Controller", + DEVICE_ISA, + 0, + xta_init, xta_close, NULL, + NULL, NULL, NULL, + wdxt150_config +}; + + +const device_t xta_hd20_device = { + "EuroPC HD20 Fixed Disk Controller", + DEVICE_ISA, + 1, + xta_init, xta_close, NULL, + NULL, NULL, NULL, + NULL +}; diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c index bc4cdcd92..a558a3318 100644 --- a/src/disk/hdc_xtide.c +++ b/src/disk/hdc_xtide.c @@ -21,7 +21,7 @@ * already on their way out, the newer IDE standard based on the * PC/AT controller and 16b design became the IDE we now know. * - * Version: @(#)hdc_xtide.c 1.0.11 2018/03/18 + * Version: @(#)hdc_xtide.c 1.0.13 2018/04/26 * * Authors: Sarah Walker, * Miran Grca, @@ -52,6 +52,7 @@ typedef struct { + void *ide_board; uint8_t data_high; rom_t bios_rom; } xtide_t; @@ -64,7 +65,7 @@ xtide_write(uint16_t port, uint8_t val, void *priv) switch (port & 0xf) { case 0x0: - writeidew(4, val | (xtide->data_high << 8)); + ide_writew(0x0, val | (xtide->data_high << 8), xtide->ide_board); return; case 0x1: @@ -74,7 +75,7 @@ xtide_write(uint16_t port, uint8_t val, void *priv) case 0x5: case 0x6: case 0x7: - writeide(4, (port & 0xf) | 0x1f0, val); + ide_writeb((port & 0xf), val, xtide->ide_board); return; case 0x8: @@ -82,7 +83,7 @@ xtide_write(uint16_t port, uint8_t val, void *priv) return; case 0xe: - writeide(4, 0x3f6, val); + ide_write_devctl(0x0, val, xtide->ide_board); return; } } @@ -96,7 +97,7 @@ xtide_read(uint16_t port, void *priv) switch (port & 0xf) { case 0x0: - tempw = readidew(4); + tempw = ide_readw(0x0, xtide->ide_board); xtide->data_high = tempw >> 8; break; @@ -107,7 +108,7 @@ xtide_read(uint16_t port, void *priv) case 0x5: case 0x6: case 0x7: - tempw = readide(4, (port & 0xf) | 0x1f0); + tempw = ide_readb((port & 0xf), xtide->ide_board); break; case 0x8: @@ -115,7 +116,7 @@ xtide_read(uint16_t port, void *priv) break; case 0xe: - tempw = readide(4, 0x3f6); + tempw = ide_read_alt_status(0x0, xtide->ide_board); break; default: @@ -136,7 +137,7 @@ xtide_init(const device_t *info) rom_init(&xtide->bios_rom, ROM_PATH_XT, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - ide_xtide_init(); + xtide->ide_board = ide_xtide_init(); io_sethandler(0x0300, 16, xtide_read, NULL, NULL, @@ -186,7 +187,7 @@ xtide_acculogic_init(const device_t *info) rom_init(&xtide->bios_rom, ROM_PATH_PS2, 0xc8000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - ide_xtide_init(); + xtide->ide_board = ide_xtide_init(); io_sethandler(0x0360, 16, xtide_read, NULL, NULL, @@ -203,6 +204,17 @@ xtide_acculogic_available(void) } +static void +xtide_close(void *priv) +{ + xtide_t *xtide = (xtide_t *)priv; + + free(xtide); + + ide_xtide_close(); +} + + static void * xtide_at_ps2_init(const device_t *info) { @@ -227,7 +239,7 @@ xtide_at_ps2_available(void) static void -xtide_close(void *priv) +xtide_at_close(void *priv) { xtide_t *xtide = (xtide_t *)priv; @@ -240,7 +252,7 @@ const device_t xtide_device = { DEVICE_ISA, 0, xtide_init, xtide_close, NULL, - xtide_available, NULL, NULL, NULL, + xtide_available, NULL, NULL, NULL }; @@ -248,8 +260,8 @@ const device_t xtide_at_device = { "XTIDE (AT)", DEVICE_ISA | DEVICE_AT, 0, - xtide_at_init, xtide_close, NULL, - xtide_at_available, NULL, NULL, NULL, + xtide_at_init, xtide_at_close, NULL, + xtide_at_available, NULL, NULL, NULL }; @@ -258,7 +270,7 @@ const device_t xtide_acculogic_device = { DEVICE_ISA, 0, xtide_acculogic_init, xtide_close, NULL, - xtide_acculogic_available, NULL, NULL, NULL, + xtide_acculogic_available, NULL, NULL, NULL }; @@ -266,7 +278,7 @@ const device_t xtide_at_ps2_device = { "XTIDE (AT) (1.1.5)", DEVICE_ISA | DEVICE_PS2, 0, - xtide_at_ps2_init, xtide_close, NULL, - xtide_at_ps2_available, NULL, NULL, NULL, + xtide_at_ps2_init, xtide_at_close, NULL, + xtide_at_ps2_available, NULL, NULL, NULL }; diff --git a/src/disk/hdd.c b/src/disk/hdd.c index e4f682dd9..805618a75 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -8,13 +8,13 @@ * * Common code to handle all sorts of hard disk images. * - * Version: @(#)hdd.c 1.0.7 2017/11/18 + * Version: @(#)hdd.c 1.0.9 2018/05/25 * * Authors: Miran Grca, * Fred N. van Kempen, * - * Copyright 2016,2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -48,7 +48,7 @@ hdd_string_to_bus(char *str, int cdrom) if (! strcmp(str, "mfm")) { if (cdrom) { no_cdrom: - ui_msgbox(MBX_ERROR, (wchar_t *)IDS_4114); + ui_msgbox(MBX_ERROR, (wchar_t *)IDS_4099); return(0); } @@ -63,53 +63,35 @@ no_cdrom: } if (! strcmp(str, "ide_pio_only")) - return(HDD_BUS_IDE_PIO_ONLY); + return(HDD_BUS_IDE); if (! strcmp(str, "ide")) - return(HDD_BUS_IDE_PIO_ONLY); + return(HDD_BUS_IDE); if (! strcmp(str, "atapi_pio_only")) - return(HDD_BUS_IDE_PIO_ONLY); + return(HDD_BUS_IDE); if (! strcmp(str, "atapi")) - return(HDD_BUS_IDE_PIO_ONLY); + return(HDD_BUS_IDE); if (! strcmp(str, "eide")) - return(HDD_BUS_IDE_PIO_ONLY); + return(HDD_BUS_IDE); - if (! strcmp(str, "xtide")) - return(HDD_BUS_XTIDE); + if (! strcmp(str, "xta")) + return(HDD_BUS_XTA); if (! strcmp(str, "atide")) - return(HDD_BUS_IDE_PIO_ONLY); + return(HDD_BUS_IDE); if (! strcmp(str, "ide_pio_and_dma")) - return(HDD_BUS_IDE_PIO_AND_DMA); + return(HDD_BUS_IDE); if (! strcmp(str, "atapi_pio_and_dma")) - return(HDD_BUS_IDE_PIO_AND_DMA); + return(HDD_BUS_IDE); if (! strcmp(str, "scsi")) return(HDD_BUS_SCSI); - if (! strcmp(str, "removable")) { - if (cdrom) goto no_cdrom; - - return(HDD_BUS_SCSI_REMOVABLE); - } - - if (! strcmp(str, "scsi_removable")) { - if (cdrom) goto no_cdrom; - - return(HDD_BUS_SCSI_REMOVABLE); - } - - if (! strcmp(str, "removable_scsi")) { - if (cdrom) goto no_cdrom; - - return(HDD_BUS_SCSI_REMOVABLE); - } - if (! strcmp(str, "usb")) ui_msgbox(MBX_ERROR, (wchar_t *)IDS_4110); @@ -131,29 +113,21 @@ hdd_bus_to_string(int bus, int cdrom) s = "mfm"; break; - case HDD_BUS_XTIDE: - s = "xtide"; + case HDD_BUS_XTA: + s = "xta"; break; case HDD_BUS_ESDI: s = "esdi"; break; - case HDD_BUS_IDE_PIO_ONLY: - s = cdrom ? "atapi_pio_only" : "ide_pio_only"; - break; - - case HDD_BUS_IDE_PIO_AND_DMA: - s = cdrom ? "atapi_pio_and_dma" : "ide_pio_and_dma"; + case HDD_BUS_IDE: + s = cdrom ? "atapi" : "ide"; break; case HDD_BUS_SCSI: s = "scsi"; break; - - case HDD_BUS_SCSI_REMOVABLE: - s = "scsi_removable"; - break; } return(s); @@ -163,12 +137,14 @@ hdd_bus_to_string(int bus, int cdrom) int hdd_is_valid(int c) { - if (hdd[c].bus == HDD_BUS_DISABLED) return(0); + if (hdd[c].bus == HDD_BUS_DISABLED) + return(0); - if ((wcslen(hdd[c].fn) == 0) && - (hdd[c].bus != HDD_BUS_SCSI_REMOVABLE)) return(0); + if (wcslen(hdd[c].fn) == 0) + return(0); - if ((hdd[c].tracks==0) || (hdd[c].hpc==0) || (hdd[c].spt==0)) return(0); + if ((hdd[c].tracks==0) || (hdd[c].hpc==0) || (hdd[c].spt==0)) + return(0); return(1); } diff --git a/src/disk/hdd.h b/src/disk/hdd.h index dbb951bac..b9b439a4b 100644 --- a/src/disk/hdd.h +++ b/src/disk/hdd.h @@ -8,12 +8,12 @@ * * Definitions for the hard disk image handler. * - * Version: @(#)hdd.h 1.0.3 2017/10/05 + * Version: @(#)hdd.h 1.0.6 2018/06/09 * * Authors: Miran Grca, * Fred N. van Kempen, - * Copyright 2016,2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #ifndef EMU_HDD_H # define EMU_HDD_H @@ -23,17 +23,53 @@ /* Hard Disk bus types. */ +#if 0 +/* Bit 4 = DMA supported (0 = no, 1 yes) - used for IDE and ATAPI only; + Bit 5 = Removable (0 = no, 1 yes). */ + +enum { + BUS_DISABLED = 0x00, + + BUS_MFM = 0x01, /* These four are for hard disk only. */ + BUS_XIDE = 0x02, + BUS_XTA = 0x03, + BUS_ESDI = 0x04, + + BUS_PANASONIC = 0x21, / These four are for CD-ROM only. */ + BUS_PHILIPS = 0x22, + BUS_SONY = 0x23, + BUS_MITSUMI = 0x24, + + BUS_IDE_PIO_ONLY = 0x05, + BUS_IDE_PIO_AND_DMA = 0x15, + BUS_IDE_R_PIO_ONLY = 0x25, + BUS_IDE_R_PIO_AND_DMA = 0x35, + + BUS_ATAPI_PIO_ONLY = 0x06, + BUS_ATAPI_PIO_AND_DMA = 0x16, + BUS_ATAPI_R_PIO_ONLY = 0x26, + BUS_ATAPI_R_PIO_AND_DMA = 0x36, + + BUS_SASI = 0x07, + BUS_SASI_R = 0x27, + + BUS_SCSI = 0x08, + BUS_SCSI_R = 0x28, + + BUS_USB = 0x09, + BUS_USB_R = 0x29 +}; +#else enum { HDD_BUS_DISABLED = 0, HDD_BUS_MFM, - HDD_BUS_XTIDE, + HDD_BUS_XTA, HDD_BUS_ESDI, - HDD_BUS_IDE_PIO_ONLY, - HDD_BUS_IDE_PIO_AND_DMA, + HDD_BUS_IDE, HDD_BUS_SCSI, - HDD_BUS_SCSI_REMOVABLE, HDD_BUS_USB }; +#endif /* Define the virtual Hard Disk. */ @@ -45,18 +81,15 @@ typedef struct { uint8_t mfm_channel; /* should rename and/or unionize */ uint8_t esdi_channel; - uint8_t xtide_channel; + uint8_t xta_channel; uint8_t ide_channel; uint8_t scsi_id; - uint8_t scsi_lun; - uint32_t base; - - uint64_t spt, + uint32_t base, + spt, hpc, /* physical geometry parameters */ - tracks; - - uint64_t at_spt, /* [Translation] parameters */ + tracks, + at_spt, /* [Translation] parameters */ at_hpc; FILE *f; /* current file handle to image */ @@ -67,7 +100,32 @@ typedef struct { extern hard_disk_t hdd[HDD_NUM]; -extern uint64_t hdd_table[128][3]; +extern unsigned int hdd_table[128][3]; + + +typedef struct vhd_footer_t +{ + uint8_t cookie[8]; + uint32_t features; + uint32_t version; + uint64_t offset; + uint32_t timestamp; + uint8_t creator[4]; + uint32_t creator_vers; + uint8_t creator_host_os[4]; + uint64_t orig_size; + uint64_t curr_size; + struct { + uint16_t cyl; + uint8_t heads; + uint8_t spt; + } geom; + uint32_t type; + uint32_t checksum; + uint8_t uuid[16]; + uint8_t saved_state; + uint8_t reserved[427]; +} vhd_footer_t; extern int hdd_init(void); @@ -75,6 +133,7 @@ extern int hdd_string_to_bus(char *str, int cdrom); extern char *hdd_bus_to_string(int bus, int cdrom); extern int hdd_is_valid(int c); +extern void hdd_image_init(void); extern int hdd_image_load(int id); extern void hdd_image_seek(uint8_t id, uint32_t sector); extern void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer); @@ -84,13 +143,21 @@ extern int hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8 extern void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count); extern int hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count); extern uint32_t hdd_image_get_last_sector(uint8_t id); +extern uint32_t hdd_image_get_pos(uint8_t id); extern uint8_t hdd_image_get_type(uint8_t id); extern void hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt); extern void hdd_image_unload(uint8_t id, int fn_preserve); extern void hdd_image_close(uint8_t id); +extern void hdd_image_calc_chs(uint32_t *c, uint32_t *h, uint32_t *s, uint32_t size); + +extern void vhd_footer_from_bytes(vhd_footer_t *vhd, uint8_t *bytes); +extern void vhd_footer_to_bytes(uint8_t *bytes, vhd_footer_t *vhd); +extern void new_vhd_footer(vhd_footer_t **vhd); +extern void generate_vhd_checksum(vhd_footer_t *vhd); extern int image_is_hdi(const wchar_t *s); extern int image_is_hdx(const wchar_t *s, int check_signature); +extern int image_is_vhd(const wchar_t *s, int check_signature); #endif /*EMU_HDD_H*/ diff --git a/src/disk/hdd_image.c b/src/disk/hdd_image.c index 272138b38..b895158cb 100644 --- a/src/disk/hdd_image.c +++ b/src/disk/hdd_image.c @@ -8,7 +8,7 @@ * * Handling of hard disk image files. * - * Version: @(#)hdd_image.c 1.0.13 2018/03/19 + * Version: @(#)hdd_image.c 1.0.16 2018/06/09 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -19,26 +19,28 @@ #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE #define _GNU_SOURCE -#include +#include #include +#include #include #include -#include +#include #include #include #define HAVE_STDARG_H #include "../86box.h" #include "../plat.h" +#include "../random.h" #include "hdd.h" typedef struct { - FILE *file; - uint32_t base; - uint32_t last_sector; - uint8_t type; - uint8_t loaded; + FILE *file; + uint32_t base; + uint32_t pos, last_sector; + uint8_t type; + uint8_t loaded; } hdd_image_t; @@ -48,414 +50,856 @@ static char empty_sector[512]; static char *empty_sector_1mb; -#ifdef ENABLE_HDD_LOG -int hdd_image_do_log = ENABLE_HDD_LOG; +#define VHD_OFFSET_COOKIE 0 +#define VHD_OFFSET_FEATURES 8 +#define VHD_OFFSET_VERSION 12 +#define VHD_OFFSET_DATA_OFFSET 16 +#define VHD_OFFSET_TIMESTAMP 24 +#define VHD_OFFSET_CREATOR 28 +#define VHD_OFFSET_CREATOR_VERS 32 +#define VHD_OFFSET_CREATOR_HOST 36 +#define VHD_OFFSET_ORIG_SIZE 40 +#define VHD_OFFSET_CURR_SIZE 48 +#define VHD_OFFSET_GEOM_CYL 56 +#define VHD_OFFSET_GEOM_HEAD 58 +#define VHD_OFFSET_GEOM_SPT 59 +#define VHD_OFFSET_TYPE 60 +#define VHD_OFFSET_CHECKSUM 64 +#define VHD_OFFSET_UUID 68 +#define VHD_OFFSET_SAVED_STATE 84 +#define VHD_OFFSET_RESERVED 85 + + +#ifdef ENABLE_HDD_IMAGE_LOG +int hdd_image_do_log = ENABLE_HDD_IMAGE_LOG; #endif static void hdd_image_log(const char *fmt, ...) { -#ifdef ENABLE_HDD_LOG - va_list ap; +#ifdef ENABLE_HDD_IMAGE_LOG + va_list ap; - if (hdd_image_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + if (hdd_image_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } #endif } -int image_is_hdi(const wchar_t *s) +int +image_is_hdi(const wchar_t *s) { - int len; - wchar_t ext[5] = { 0, 0, 0, 0, 0 }; - char *ws = (char *) s; - len = wcslen(s); - if ((len < 4) || (s[0] == L'.')) - return 0; - memcpy(ext, ws + ((len - 4) << 1), 8); - if (! wcscasecmp(ext, L".HDI")) - return 1; - else - return 0; + int len; + wchar_t ext[5] = { 0, 0, 0, 0, 0 }; + char *ws = (char *) s; + len = wcslen(s); + if ((len < 4) || (s[0] == L'.')) + return 0; + memcpy(ext, ws + ((len - 4) << 1), 8); + if (! wcscasecmp(ext, L".HDI")) + return 1; + else + return 0; } int image_is_hdx(const wchar_t *s, int check_signature) { - int len; - FILE *f; - uint64_t filelen; - uint64_t signature; - char *ws = (char *) s; - wchar_t ext[5] = { 0, 0, 0, 0, 0 }; - len = wcslen(s); - if ((len < 4) || (s[0] == L'.')) - return 0; - memcpy(ext, ws + ((len - 4) << 1), 8); - if (wcscasecmp(ext, L".HDX") == 0) { - if (check_signature) { - f = plat_fopen((wchar_t *)s, L"rb"); - if (!f) - return 0; - fseeko64(f, 0, SEEK_END); - filelen = ftello64(f); - fseeko64(f, 0, SEEK_SET); - if (filelen < 44) - return 0; - fread(&signature, 1, 8, f); - fclose(f); - if (signature == 0xD778A82044445459ll) - return 1; - return 0; - } - return 1; - } + int len; + FILE *f; + uint64_t filelen; + uint64_t signature; + char *ws = (char *) s; + wchar_t ext[5] = { 0, 0, 0, 0, 0 }; + len = wcslen(s); + if ((len < 4) || (s[0] == L'.')) return 0; + memcpy(ext, ws + ((len - 4) << 1), 8); + if (wcscasecmp(ext, L".HDX") == 0) { + if (check_signature) { + f = plat_fopen((wchar_t *)s, L"rb"); + if (!f) + return 0; + fseeko64(f, 0, SEEK_END); + filelen = ftello64(f); + fseeko64(f, 0, SEEK_SET); + if (filelen < 44) + return 0; + fread(&signature, 1, 8, f); + fclose(f); + if (signature == 0xD778A82044445459ll) + return 1; + else + return 0; + } else + return 1; + } else + return 0; } -int hdd_image_load(int id) +int +image_is_vhd(const wchar_t *s, int check_signature) { - uint32_t sector_size = 512; - uint32_t zero = 0; - uint64_t signature = 0xD778A82044445459ll; - uint64_t full_size = 0; - uint64_t spt = 0, hpc = 0, tracks = 0; - int c; - uint64_t i = 0, s = 0, t = 0; - wchar_t *fn = hdd[id].fn; - int is_hdx[2] = { 0, 0 }; + int len; + FILE *f; + uint64_t filelen; + uint64_t signature; + char *ws = (char *) s; + wchar_t ext[5] = { 0, 0, 0, 0, 0 }; + len = wcslen(s); + if ((len < 4) || (s[0] == L'.')) + return 0; + memcpy(ext, ws + ((len - 4) << 1), 8); + if (wcscasecmp(ext, L".VHD") == 0) { + if (check_signature) { + f = plat_fopen((wchar_t *)s, L"rb"); + if (!f) + return 0; + fseeko64(f, 0, SEEK_END); + filelen = ftello64(f); + fseeko64(f, -512, SEEK_END); + if (filelen < 512) + return 0; + fread(&signature, 1, 8, f); + fclose(f); + if (signature == 0x78697463656E6F63ll) + return 1; + else + return 0; + } else + return 1; + } else + return 0; +} - memset(empty_sector, 0, sizeof(empty_sector)); - hdd_images[id].base = 0; +static uint64_t +be_to_u64(uint8_t *bytes, int start) +{ + uint64_t n = ((uint64_t)bytes[start+7] << 0) | + ((uint64_t)bytes[start+6] << 8) | + ((uint64_t)bytes[start+5] << 16) | + ((uint64_t)bytes[start+4] << 24) | + ((uint64_t)bytes[start+3] << 32) | + ((uint64_t)bytes[start+2] << 40) | + ((uint64_t)bytes[start+1] << 48) | + ((uint64_t)bytes[start] << 56); + return n; +} - if (hdd_images[id].loaded) { - if (hdd_images[id].file) { - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; - } - hdd_images[id].loaded = 0; + +static uint32_t +be_to_u32(uint8_t *bytes, int start) +{ + uint32_t n = ((uint32_t)bytes[start+3] << 0) | + ((uint32_t)bytes[start+2] << 8) | + ((uint32_t)bytes[start+1] << 16) | + ((uint32_t)bytes[start] << 24); + return n; +} + + +static uint16_t +be_to_u16(uint8_t *bytes, int start) +{ + uint16_t n = ((uint16_t)bytes[start+1] << 0) | + ((uint16_t)bytes[start] <<8); + return n; +} + + +static uint64_t +u64_to_be(uint64_t value, int is_be) +{ + uint64_t res = 0; + if (is_be) + res = value; + else { + uint64_t mask = 0xff00000000000000; + res = ((value & (mask >> 0)) >> 56) | + ((value & (mask >> 8)) >> 40) | + ((value & (mask >> 16)) >> 24) | + ((value & (mask >> 24)) >> 8) | + ((value & (mask >> 32)) << 8) | + ((value & (mask >> 40)) << 24) | + ((value & (mask >> 48)) << 40) | + ((value & (mask >> 56)) << 56); + } + return res; +} + + +static uint32_t +u32_to_be(uint32_t value, int is_be) +{ + uint32_t res = 0; + if (is_be) + res = value; + else { + uint32_t mask = 0xff000000; + res = ((value & (mask >> 0)) >> 24) | + ((value & (mask >> 8)) >> 8) | + ((value & (mask >> 16)) << 8) | + ((value & (mask >> 24)) << 24); + } + return res; +} + + +static uint16_t +u16_to_be(uint16_t value, int is_be) +{ + uint16_t res = 0; + if (is_be) + res = value; + else + res = (value >> 8) | (value << 8); + + return res; +} + + +static void +mk_guid(uint8_t *guid) +{ + int n; + + for (n = 0; n < 16; n++) + guid[n] = random_generate(); + + guid[6] &= 0x0F; + guid[6] |= 0x40; /* Type 4 */ + guid[8] &= 0x3F; + guid[8] |= 0x80; /* Variant 1 */ +} + + +static uint32_t +calc_vhd_timestamp() +{ + time_t start_time; + time_t curr_time; + double vhd_time; + start_time = 946684800; /* 1 Jan 2000 00:00 */ + curr_time = time(NULL); + vhd_time = difftime(curr_time, start_time); + + return (uint32_t)vhd_time; +} + + +void +vhd_footer_from_bytes(vhd_footer_t *vhd, uint8_t *bytes) +{ + memcpy(vhd->cookie, bytes + VHD_OFFSET_COOKIE, sizeof(vhd->cookie)); + vhd->features = be_to_u32(bytes, VHD_OFFSET_FEATURES); + vhd->version = be_to_u32(bytes, VHD_OFFSET_VERSION); + vhd->offset = be_to_u64(bytes, VHD_OFFSET_DATA_OFFSET); + vhd->timestamp = be_to_u32(bytes, VHD_OFFSET_TIMESTAMP); + memcpy(vhd->creator, bytes + VHD_OFFSET_CREATOR, sizeof(vhd->creator)); + vhd->creator_vers = be_to_u32(bytes, VHD_OFFSET_CREATOR_VERS); + memcpy(vhd->creator_host_os, bytes + VHD_OFFSET_CREATOR_HOST, sizeof(vhd->creator_host_os)); + vhd->orig_size = be_to_u64(bytes, VHD_OFFSET_ORIG_SIZE); + vhd->curr_size = be_to_u64(bytes, VHD_OFFSET_CURR_SIZE); + vhd->geom.cyl = be_to_u16(bytes, VHD_OFFSET_GEOM_CYL); + vhd->geom.heads = bytes[VHD_OFFSET_GEOM_HEAD]; + vhd->geom.spt = bytes[VHD_OFFSET_GEOM_SPT]; + vhd->type = be_to_u32(bytes, VHD_OFFSET_TYPE); + vhd->checksum = be_to_u32(bytes, VHD_OFFSET_CHECKSUM); + memcpy(vhd->uuid, bytes + VHD_OFFSET_UUID, sizeof(vhd->uuid)); /* TODO: handle UUID's properly */ + vhd->saved_state = bytes[VHD_OFFSET_SAVED_STATE]; + memcpy(vhd->reserved, bytes + VHD_OFFSET_RESERVED, sizeof(vhd->reserved)); +} + + +void +vhd_footer_to_bytes(uint8_t *bytes, vhd_footer_t *vhd) +{ + /* Quick endian check */ + int is_be = 0; + uint8_t e = 1; + uint8_t *ep = &e; + uint16_t u16; + uint32_t u32; + uint64_t u64; + + if (ep[0] == 0) + is_be = 1; + + memcpy(bytes + VHD_OFFSET_COOKIE, vhd->cookie, sizeof(vhd->cookie)); + u32 = u32_to_be(vhd->features, is_be); + memcpy(bytes + VHD_OFFSET_FEATURES, &u32, sizeof(vhd->features)); + u32 = u32_to_be(vhd->version, is_be); + memcpy(bytes + VHD_OFFSET_VERSION, &u32, sizeof(vhd->version)); + u64 = u64_to_be(vhd->offset, is_be); + memcpy(bytes + VHD_OFFSET_DATA_OFFSET, &u64, sizeof(vhd->offset)); + u32 = u32_to_be(vhd->timestamp, is_be); + memcpy(bytes + VHD_OFFSET_TIMESTAMP, &u32, sizeof(vhd->timestamp)); + memcpy(bytes + VHD_OFFSET_CREATOR, vhd->creator, sizeof(vhd->creator)); + u32 = u32_to_be(vhd->creator_vers, is_be); + memcpy(bytes + VHD_OFFSET_CREATOR_VERS, &u32, sizeof(vhd->creator_vers)); + memcpy(bytes + VHD_OFFSET_CREATOR_HOST, vhd->creator_host_os, sizeof(vhd->creator_host_os)); + u64 = u64_to_be(vhd->orig_size, is_be); + memcpy(bytes + VHD_OFFSET_ORIG_SIZE, &u64, sizeof(vhd->orig_size)); + u64 = u64_to_be(vhd->curr_size, is_be); + memcpy(bytes + VHD_OFFSET_CURR_SIZE, &u64, sizeof(vhd->curr_size)); + u16 = u16_to_be(vhd->geom.cyl, is_be); + memcpy(bytes + VHD_OFFSET_GEOM_CYL, &u16, sizeof(vhd->geom.cyl)); + memcpy(bytes + VHD_OFFSET_GEOM_HEAD, &(vhd->geom.heads), sizeof(vhd->geom.heads)); + memcpy(bytes + VHD_OFFSET_GEOM_SPT, &(vhd->geom.spt), sizeof(vhd->geom.spt)); + u32 = u32_to_be(vhd->type, is_be); + memcpy(bytes + VHD_OFFSET_TYPE, &u32, sizeof(vhd->type)); + u32 = u32_to_be(vhd->checksum, is_be); + memcpy(bytes + VHD_OFFSET_CHECKSUM, &u32, sizeof(vhd->checksum)); + memcpy(bytes + VHD_OFFSET_UUID, vhd->uuid, sizeof(vhd->uuid)); + memcpy(bytes + VHD_OFFSET_SAVED_STATE, &(vhd->saved_state), sizeof(vhd->saved_state)); + memcpy(bytes + VHD_OFFSET_RESERVED, vhd->reserved, sizeof(vhd->reserved)); +} + + +void +new_vhd_footer(vhd_footer_t **vhd) +{ + uint8_t cookie[8] = {'c', 'o', 'n', 'e', 'c', 't', 'i', 'x'}; + uint8_t creator[4] = {'8', '6', 'b', 'x'}; + uint8_t cr_host_os[4] = {'W', 'i', '2', 'k'}; + + if (*vhd == NULL) + *vhd = (vhd_footer_t *) malloc(sizeof(vhd_footer_t)); + + memcpy((*vhd)->cookie, cookie, 8); + (*vhd)->features = 0x00000002; + (*vhd)->version = 0x00010000; + (*vhd)->offset = 0xffffffffffffffff; /* fixed disk */ + (*vhd)->timestamp = calc_vhd_timestamp(); + memcpy((*vhd)->creator, creator, 4); + (*vhd)->creator_vers = 0x00010000; + memcpy((*vhd)->creator_host_os, cr_host_os, 4); + (*vhd)->type = 2; /* fixed disk */ + mk_guid((*vhd)->uuid); + (*vhd)->saved_state = 0; + memset((*vhd)->reserved, 0, 427); +} + + +void +generate_vhd_checksum(vhd_footer_t *vhd) +{ + uint32_t chk = 0; + int i; + for (i = 0; i < sizeof(vhd_footer_t); i++) { + /* We don't include the checksum field in the checksum */ + if ((i < VHD_OFFSET_CHECKSUM) || (i >= VHD_OFFSET_UUID)) + chk += ((uint8_t*)vhd)[i]; + } + vhd->checksum = ~chk; +} + + +void +hdd_image_calc_chs(uint32_t *c, uint32_t *h, uint32_t *s, uint32_t size) +{ + /* Calculate the geometry from size (in MB), using the algorithm provided in + "Virtual Hard Disk Image Format Specification, Appendix: CHS Calculation" */ + uint64_t ts = ((uint64_t) size) << 11LL; + uint32_t spt, heads, cyl, cth; + if (ts > 65535 * 16 * 255) + ts = 65535 * 16 * 255; + + if (ts >= 65535 * 16 * 63) { + spt = 255; + heads = 16; + cth = ts / spt; + } else { + spt = 17; + cth = ts / spt; + heads = (cth +1023) / 1024; + if (heads < 4) + heads = 4; + if ((cth >= (heads * 1024)) || (heads > 16)) { + spt = 31; + heads = 16; + cth = ts / spt; } - - is_hdx[0] = image_is_hdx(fn, 0); - is_hdx[1] = image_is_hdx(fn, 1); - - /* Try to open existing hard disk image */ - if (fn[0] == '.') { - hdd_image_log("File name starts with .\n"); - memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); - return 0; + if (cth >= (heads * 1024)) { + spt = 63; + heads = 16; + cth = ts / spt; } - hdd_images[id].file = plat_fopen(fn, L"rb+"); - if (hdd_images[id].file == NULL) { - /* Failed to open existing hard disk image */ - if (errno == ENOENT) { - /* Failed because it does not exist, - so try to create new file */ - if (hdd[id].wp) { - hdd_image_log("A write-protected image must exist\n"); - memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); - return 0; - } + } + cyl = cth / heads; + *c = cyl; + *h = heads; + *s = spt; +} - hdd_images[id].file = plat_fopen(fn, L"wb+"); - if (hdd_images[id].file == NULL) { - hdd_image_log("Unable to open image\n"); - memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); - return 0; - } else { - if (image_is_hdi(fn)) { - full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512; - hdd_images[id].base = 0x1000; - fwrite(&zero, 1, 4, hdd_images[id].file); - fwrite(&zero, 1, 4, hdd_images[id].file); - fwrite(&(hdd_images[id].base), 1, 4, hdd_images[id].file); - fwrite(&full_size, 1, 4, hdd_images[id].file); - fwrite(§or_size, 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file); - for (c = 0; c < 0x3f8; c++) - fwrite(&zero, 1, 4, hdd_images[id].file); - hdd_images[id].type = 1; - } else if (is_hdx[0]) { - full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512; - hdd_images[id].base = 0x28; - fwrite(&signature, 1, 8, hdd_images[id].file); - fwrite(&full_size, 1, 8, hdd_images[id].file); - fwrite(§or_size, 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file); - fwrite(&zero, 1, 4, hdd_images[id].file); - fwrite(&zero, 1, 4, hdd_images[id].file); - hdd_images[id].type = 2; - } - else - hdd_images[id].type = 0; - hdd_images[id].last_sector = 0; - } - s = full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512; +static int +prepare_new_hard_disk(uint8_t id, uint64_t full_size) +{ + uint64_t target_size = (full_size + hdd_images[id].base) - ftello64(hdd_images[id].file); - goto prepare_new_hard_disk; - } else { - /* Failed for another reason */ - hdd_image_log("Failed for another reason\n"); + uint32_t size; + uint32_t t, i; + + t = (uint32_t) (target_size >> 20); /* Amount of 1 MB blocks. */ + size = (uint32_t) (target_size & 0xfffff); /* 1 MB mask. */ + + empty_sector_1mb = (char *) malloc(1048576); + memset(empty_sector_1mb, 0, 1048576); + + /* Temporarily switch off suppression of seen messages so that the + progress gets displayed. */ + pclog_toggle_suppr(); + pclog("Writing image sectors: ["); + + /* First, write all the 1 MB blocks. */ + if (t > 0) { + for (i = 0; i < t; i++) { + fwrite(empty_sector_1mb, 1, 1045876, hdd_images[id].file); + pclog("#"); + } + } + + /* Then, write the remainder. */ + fwrite(empty_sector_1mb, 1, size, hdd_images[id].file); + pclog("#]\n"); + /* Switch the suppression of seen messages back on. */ + pclog_toggle_suppr(); + + free(empty_sector_1mb); + + hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1; + + hdd_images[id].loaded = 1; + + return 1; +} + + +void +hdd_image_init(void) +{ + int i; + + for (i = 0; i < HDD_NUM; i++) + memset(&hdd_images[i], 0, sizeof(hdd_image_t)); +} + + +int +hdd_image_load(int id) +{ + uint32_t sector_size = 512; + uint32_t zero = 0; + uint64_t signature = 0xD778A82044445459ll; + uint64_t full_size = 0; + uint64_t spt = 0, hpc = 0, tracks = 0; + int c, ret; + uint64_t s = 0; + wchar_t *fn = hdd[id].fn; + int is_hdx[2] = { 0, 0 }; + int is_vhd[2] = { 0, 0 }; + vhd_footer_t *vft = NULL; + + memset(empty_sector, 0, sizeof(empty_sector)); + + hdd_images[id].base = 0; + + if (hdd_images[id].loaded) { + if (hdd_images[id].file) { + fclose(hdd_images[id].file); + hdd_images[id].file = NULL; + } + hdd_images[id].loaded = 0; + } + + is_hdx[0] = image_is_hdx(fn, 0); + is_hdx[1] = image_is_hdx(fn, 1); + + is_vhd[0] = image_is_vhd(fn, 0); + is_vhd[1] = image_is_vhd(fn, 1); + + hdd_images[id].pos = 0; + + /* Try to open existing hard disk image */ + if (fn[0] == '.') { + hdd_image_log("File name starts with .\n"); + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); + return 0; + } + hdd_images[id].file = plat_fopen(fn, L"rb+"); + if (hdd_images[id].file == NULL) { + /* Failed to open existing hard disk image */ + if (errno == ENOENT) { + /* Failed because it does not exist, + so try to create new file */ + if (hdd[id].wp) { + hdd_image_log("A write-protected image must exist\n"); memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; } - } else { - if (image_is_hdi(fn)) { - fseeko64(hdd_images[id].file, 0x8, SEEK_SET); - fread(&(hdd_images[id].base), 1, 4, hdd_images[id].file); - fseeko64(hdd_images[id].file, 0xC, SEEK_SET); - full_size = 0; - fread(&full_size, 1, 4, hdd_images[id].file); - fseeko64(hdd_images[id].file, 0x10, SEEK_SET); - fread(§or_size, 1, 4, hdd_images[id].file); - if (sector_size != 512) { - /* Sector size is not 512 */ - hdd_image_log("HDI: Sector size is not 512\n"); - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; - memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); - return 0; - } - fread(&spt, 1, 4, hdd_images[id].file); - fread(&hpc, 1, 4, hdd_images[id].file); - fread(&tracks, 1, 4, hdd_images[id].file); - if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) { - if ((spt != hdd[id].spt) || (hpc != hdd[id].hpc) || (tracks != hdd[id].tracks)) { - hdd_image_log("HDI: Geometry mismatch\n"); - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; - memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); - return 0; - } - } - hdd[id].spt = spt; - hdd[id].hpc = hpc; - hdd[id].tracks = tracks; - hdd_images[id].type = 1; - } - else if (is_hdx[1]) { - hdd_images[id].base = 0x28; - fseeko64(hdd_images[id].file, 8, SEEK_SET); - fread(&full_size, 1, 8, hdd_images[id].file); - fseeko64(hdd_images[id].file, 0x10, SEEK_SET); - fread(§or_size, 1, 4, hdd_images[id].file); - if (sector_size != 512) { - /* Sector size is not 512 */ - hdd_image_log("HDX: Sector size is not 512\n"); - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; - memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); - return 0; - } - fread(&spt, 1, 4, hdd_images[id].file); - fread(&hpc, 1, 4, hdd_images[id].file); - fread(&tracks, 1, 4, hdd_images[id].file); - if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) { - if ((spt != hdd[id].spt) || (hpc != hdd[id].hpc) || (tracks != hdd[id].tracks)) { - hdd_image_log("HDX: Geometry mismatch\n"); - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; - memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); - return 0; - } - } - hdd[id].spt = spt; - hdd[id].hpc = hpc; - hdd[id].tracks = tracks; - fread(&(hdd[id].at_spt), 1, 4, hdd_images[id].file); - fread(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file); - hdd_images[id].type = 2; + + hdd_images[id].file = plat_fopen(fn, L"wb+"); + if (hdd_images[id].file == NULL) { + hdd_image_log("Unable to open image\n"); + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); + return 0; } else { - full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512; - hdd_images[id].type = 0; - } - } - - fseeko64(hdd_images[id].file, 0, SEEK_END); - if (ftello64(hdd_images[id].file) < (full_size + hdd_images[id].base)) { - s = (full_size + hdd_images[id].base) - ftello64(hdd_images[id].file); -prepare_new_hard_disk: - t = s >> 20; /* Amount of 1 MB blocks. */ - s &= 0xfffff; /* 1 MB mask. */ - - empty_sector_1mb = (char *) malloc(1048576); - memset(empty_sector_1mb, 0, 1048576); - - /* Temporarily switch off suppression of seen messages so that the - progress gets displayed. */ - pclog_toggle_suppr(); - pclog("Writing image sectors: ["); - - /* First, write all the 1 MB blocks. */ - if (t > 0) { - for (i = 0; i < t; i++) { - fwrite(empty_sector_1mb, 1, 1045876, hdd_images[id].file); - pclog("#"); + if (image_is_hdi(fn)) { + full_size = ((uint64_t) hdd[id].spt) * + ((uint64_t) hdd[id].hpc) * + ((uint64_t) hdd[id].tracks) << 9LL; + hdd_images[id].base = 0x1000; + fwrite(&zero, 1, 4, hdd_images[id].file); + fwrite(&zero, 1, 4, hdd_images[id].file); + fwrite(&(hdd_images[id].base), 1, 4, hdd_images[id].file); + fwrite(&full_size, 1, 4, hdd_images[id].file); + fwrite(§or_size, 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file); + for (c = 0; c < 0x3f8; c++) + fwrite(&zero, 1, 4, hdd_images[id].file); + hdd_images[id].type = 1; + } else if (is_hdx[0]) { + full_size = ((uint64_t) hdd[id].spt) * + ((uint64_t) hdd[id].hpc) * + ((uint64_t) hdd[id].tracks) << 9LL; + hdd_images[id].base = 0x28; + fwrite(&signature, 1, 8, hdd_images[id].file); + fwrite(&full_size, 1, 8, hdd_images[id].file); + fwrite(§or_size, 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file); + fwrite(&zero, 1, 4, hdd_images[id].file); + fwrite(&zero, 1, 4, hdd_images[id].file); + hdd_images[id].type = 2; } + else + hdd_images[id].type = 0; + hdd_images[id].last_sector = 0; } - /* Then, write the remainder. */ - fwrite(empty_sector_1mb, 1, s, hdd_images[id].file); - pclog("#]\n"); - pclog_toggle_suppr(); + s = full_size = ((uint64_t) hdd[id].spt) * + ((uint64_t) hdd[id].hpc) * + ((uint64_t) hdd[id].tracks) << 9LL; - free(empty_sector_1mb); + ret = prepare_new_hard_disk(id, full_size); + + if (is_vhd[0]) { + /* VHD image. */ + /* Generate new footer. */ + empty_sector_1mb = (char *) malloc(512); + new_vhd_footer(&vft); + vft->orig_size = vft->curr_size = full_size; + vft->geom.cyl = tracks; + vft->geom.heads = hpc; + vft->geom.spt = spt; + generate_vhd_checksum(vft); + memset(empty_sector_1mb, 0, 512); + vhd_footer_to_bytes((uint8_t *) empty_sector_1mb, vft); + fwrite(empty_sector_1mb, 1, 512, hdd_images[id].file); + free(vft); + vft = NULL; + free(empty_sector_1mb); + empty_sector_1mb = NULL; + hdd_images[id].type = 3; + } + + return ret; + } else { + /* Failed for another reason */ + hdd_image_log("Failed for another reason\n"); + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); + return 0; } - - hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1; - - hdd_images[id].loaded = 1; - - return 1; -} - -void hdd_image_seek(uint8_t id, uint32_t sector) -{ - off64_t addr = sector; - addr = (uint64_t)sector * 512; - - fseeko64(hdd_images[id].file, addr + hdd_images[id].base, SEEK_SET); -} - -void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) -{ - fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET); - fread(buffer, 1, count * 512, hdd_images[id].file); -} - -uint32_t hdd_sectors(uint8_t id) -{ - fseeko64(hdd_images[id].file, 0, SEEK_END); - return (uint32_t) (ftello64(hdd_images[id].file) >> 9); -} - -int hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) -{ - uint32_t transfer_sectors = count; - uint32_t sectors = hdd_sectors(id); - - if ((sectors - sector) < transfer_sectors) - transfer_sectors = sectors - sector; - - fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET); - fread(buffer, 1, transfer_sectors * 512, hdd_images[id].file); - - if (count != transfer_sectors) - return 1; - return 0; -} - -void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) -{ - fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET); - fwrite(buffer, count * 512, 1, hdd_images[id].file); -} - -int hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) -{ - uint32_t transfer_sectors = count; - uint32_t sectors = hdd_sectors(id); - - if ((sectors - sector) < transfer_sectors) - transfer_sectors = sectors - sector; - - fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET); - fwrite(buffer, transfer_sectors * 512, 1, hdd_images[id].file); - - if (count != transfer_sectors) - return 1; - return 0; -} - -void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count) -{ - int i = 0; - - fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET); - for (i = 0; i < count; i++) - fwrite(empty_sector, 512, 1, hdd_images[id].file); -} - -int hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count) -{ - int i = 0; - - uint32_t transfer_sectors = count; - uint32_t sectors = hdd_sectors(id); - - if ((sectors - sector) < transfer_sectors) - transfer_sectors = sectors - sector; - - fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET); - for (i = 0; i < transfer_sectors; i++) - fwrite(empty_sector, 1, 512, hdd_images[id].file); - - if (count != transfer_sectors) - return 1; - return 0; -} - -uint32_t hdd_image_get_last_sector(uint8_t id) -{ - return hdd_images[id].last_sector; -} - -uint8_t hdd_image_get_type(uint8_t id) -{ - return hdd_images[id].type; -} - -void hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt) -{ - if (hdd_images[id].type == 2) - { - hdd[id].at_hpc = hpc; - hdd[id].at_spt = spt; - fseeko64(hdd_images[id].file, 0x20, SEEK_SET); - fwrite(&(hdd[id].at_spt), 1, 4, hdd_images[id].file); - fwrite(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file); - } -} - -void hdd_image_unload(uint8_t id, int fn_preserve) -{ - if (wcslen(hdd[id].fn) == 0) - return; - - if (hdd_images[id].loaded) { - if (hdd_images[id].file != NULL) { + } else { + if (image_is_hdi(fn)) { + fseeko64(hdd_images[id].file, 0x8, SEEK_SET); + fread(&(hdd_images[id].base), 1, 4, hdd_images[id].file); + fseeko64(hdd_images[id].file, 0xC, SEEK_SET); + full_size = 0LL; + fread(&full_size, 1, 4, hdd_images[id].file); + fseeko64(hdd_images[id].file, 0x10, SEEK_SET); + fread(§or_size, 1, 4, hdd_images[id].file); + if (sector_size != 512) { + /* Sector size is not 512 */ + hdd_image_log("HDI: Sector size is not 512\n"); fclose(hdd_images[id].file); hdd_images[id].file = NULL; + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); + return 0; } - hdd_images[id].loaded = 0; + fread(&spt, 1, 4, hdd_images[id].file); + fread(&hpc, 1, 4, hdd_images[id].file); + fread(&tracks, 1, 4, hdd_images[id].file); + hdd[id].spt = spt; + hdd[id].hpc = hpc; + hdd[id].tracks = tracks; + hdd_images[id].type = 1; + } else if (is_hdx[1]) { + hdd_images[id].base = 0x28; + fseeko64(hdd_images[id].file, 8, SEEK_SET); + fread(&full_size, 1, 8, hdd_images[id].file); + fseeko64(hdd_images[id].file, 0x10, SEEK_SET); + fread(§or_size, 1, 4, hdd_images[id].file); + if (sector_size != 512) { + /* Sector size is not 512 */ + hdd_image_log("HDX: Sector size is not 512\n"); + fclose(hdd_images[id].file); + hdd_images[id].file = NULL; + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); + return 0; + } + fread(&spt, 1, 4, hdd_images[id].file); + fread(&hpc, 1, 4, hdd_images[id].file); + fread(&tracks, 1, 4, hdd_images[id].file); + hdd[id].spt = spt; + hdd[id].hpc = hpc; + hdd[id].tracks = tracks; + fread(&(hdd[id].at_spt), 1, 4, hdd_images[id].file); + fread(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file); + hdd_images[id].type = 2; + } else if (is_vhd[1]) { + empty_sector_1mb = (char *) malloc(512); + memset(empty_sector_1mb, 0, 512); + fseeko64(hdd_images[id].file, -512, SEEK_END); + fread(empty_sector_1mb, 1, 512, hdd_images[id].file); + new_vhd_footer(&vft); + vhd_footer_from_bytes(vft, (uint8_t *) empty_sector_1mb); + if (vft->type != 2) { + /* VHD is not fixed size */ + hdd_image_log("VHD: Image is not fixed size\n"); + free(vft); + vft = NULL; + free(empty_sector_1mb); + empty_sector_1mb = NULL; + fclose(hdd_images[id].file); + hdd_images[id].file = NULL; + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); + return 0; + } + full_size = vft->orig_size; + hdd[id].tracks = vft->geom.cyl; + hdd[id].hpc = vft->geom.heads; + hdd[id].spt = vft->geom.spt; + free(vft); + vft = NULL; + free(empty_sector_1mb); + empty_sector_1mb = NULL; + hdd_images[id].type = 3; + /* If we're here, this means there is a valid VHD footer in the + image, which means that by definition, all valid sectors + are there. */ + hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1; + hdd_images[id].loaded = 1; + return 1; + } else { + full_size = ((uint64_t) hdd[id].spt) * + ((uint64_t) hdd[id].hpc) * + ((uint64_t) hdd[id].tracks) << 9LL; + hdd_images[id].type = 0; } + } - hdd_images[id].last_sector = -1; - - memset(hdd[id].prev_fn, 0, sizeof(hdd[id].prev_fn)); - if (fn_preserve) - wcscpy(hdd[id].prev_fn, hdd[id].fn); - memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); + fseeko64(hdd_images[id].file, 0, SEEK_END); + s = ftello64(hdd_images[id].file); + if (s < (full_size + hdd_images[id].base)) + return prepare_new_hard_disk(id, full_size); + else { + hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1; + hdd_images[id].loaded = 1; + return 1; + } } -void hdd_image_close(uint8_t id) + +void +hdd_image_seek(uint8_t id, uint32_t sector) { + off64_t addr = sector; + addr = (uint64_t)sector << 9LL; + + hdd_images[id].pos = sector; + fseeko64(hdd_images[id].file, addr + hdd_images[id].base, SEEK_SET); +} + + +void +hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) +{ + hdd_images[id].pos = sector; + fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET); + fread(buffer, 1, count << 9, hdd_images[id].file); +} + + +uint32_t +hdd_sectors(uint8_t id) +{ + fseeko64(hdd_images[id].file, 0, SEEK_END); + return (uint32_t) ((ftello64(hdd_images[id].file) - hdd_images[id].base) >> 9); +} + + +int +hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) +{ + uint32_t transfer_sectors = count; + uint32_t sectors = hdd_sectors(id); + + if ((sectors - sector) < transfer_sectors) + transfer_sectors = sectors - sector; + + hdd_images[id].pos = sector; + fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET); + fread(buffer, 1, transfer_sectors << 9, hdd_images[id].file); + + if (count != transfer_sectors) + return 1; + return 0; +} + + +void +hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) +{ + hdd_images[id].pos = sector; + fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET); + fwrite(buffer, count << 9, 1, hdd_images[id].file); +} + + +int +hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) +{ + uint32_t transfer_sectors = count; + uint32_t sectors = hdd_sectors(id); + + if ((sectors - sector) < transfer_sectors) + transfer_sectors = sectors - sector; + + hdd_images[id].pos = sector; + fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET); + fwrite(buffer, transfer_sectors << 9, 1, hdd_images[id].file); + + if (count != transfer_sectors) + return 1; + return 0; +} + + +void +hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count) +{ + uint32_t i = 0; + + hdd_images[id].pos = sector; + fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET); + for (i = 0; i < count; i++) + fwrite(empty_sector, 512, 1, hdd_images[id].file); +} + + +int +hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count) +{ + uint32_t i = 0; + + uint32_t transfer_sectors = count; + uint32_t sectors = hdd_sectors(id); + + if ((sectors - sector) < transfer_sectors) + transfer_sectors = sectors - sector; + + hdd_images[id].pos = sector; + fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET); + for (i = 0; i < transfer_sectors; i++) + fwrite(empty_sector, 1, 512, hdd_images[id].file); + + if (count != transfer_sectors) + return 1; + return 0; +} + + +uint32_t +hdd_image_get_last_sector(uint8_t id) +{ + return hdd_images[id].last_sector; +} + + +uint32_t +hdd_image_get_pos(uint8_t id) +{ + return hdd_images[id].pos; +} + + +uint8_t +hdd_image_get_type(uint8_t id) +{ + return hdd_images[id].type; +} + + +void +hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt) +{ + if (hdd_images[id].type == 2) { + hdd[id].at_hpc = hpc; + hdd[id].at_spt = spt; + fseeko64(hdd_images[id].file, 0x20, SEEK_SET); + fwrite(&(hdd[id].at_spt), 1, 4, hdd_images[id].file); + fwrite(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file); + } +} + + +void +hdd_image_unload(uint8_t id, int fn_preserve) +{ + if (wcslen(hdd[id].fn) == 0) + return; + + if (hdd_images[id].loaded) { if (hdd_images[id].file != NULL) { fclose(hdd_images[id].file); hdd_images[id].file = NULL; } hdd_images[id].loaded = 0; + } + + hdd_images[id].last_sector = -1; + + memset(hdd[id].prev_fn, 0, sizeof(hdd[id].prev_fn)); + if (fn_preserve) + wcscpy(hdd[id].prev_fn, hdd[id].fn); + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); +} + + +void +hdd_image_close(uint8_t id) +{ + hdd_image_log("hdd_image_close(%i)\n", id); + + if (!hdd_images[id].loaded) + return; + + if (hdd_images[id].file != NULL) { + fclose(hdd_images[id].file); + hdd_images[id].file = NULL; + } + memset(&hdd_images[id], 0, sizeof(hdd_image_t)); + hdd_images[id].loaded = 0; } diff --git a/src/disk/hdd_table.c b/src/disk/hdd_table.c index 95490a014..0ef0829e1 100644 --- a/src/disk/hdd_table.c +++ b/src/disk/hdd_table.c @@ -9,13 +9,13 @@ * Implementation of the IDE emulation for hard disks and ATAPI * CD-ROM devices. * - * Version: @(#)hdd_table.c 1.0.5 2017/11/01 + * Version: @(#)hdd_table.c 1.0.5 2018/04/08 * * Authors: Miran Grca, * Fred N. van Kempen, * - * Copyright 2016,2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -26,7 +26,7 @@ #include "hdd.h" -uint64_t hdd_table[128][3] = { +unsigned int hdd_table[128][3] = { { 306, 4, 17 }, /* 0 - 7 */ { 615, 2, 17 }, { 306, 4, 26 }, diff --git a/src/disk/zip.c b/src/disk/zip.c index 1a7289503..e2a4c28d3 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -9,7 +9,7 @@ * Implementation of the Iomega ZIP drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)zip.c 1.0.19 2018/03/21 + * Version: @(#)zip.c 1.0.21 2018/05/28 * * Author: Miran Grca, * @@ -48,25 +48,14 @@ #define ABRT_ERR 0x04 /* Command aborted */ #define MCR_ERR 0x08 /* Media change request */ -zip_t zip[ZIP_NUM]; +#define zipbufferb dev->buffer + + +zip_t *zip[ZIP_NUM]; zip_drive_t zip_drives[ZIP_NUM]; uint8_t atapi_zip_drives[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -uint8_t scsi_zip_drives[16][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } }; +uint8_t scsi_zip_drives[16] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ @@ -83,7 +72,7 @@ const uint8_t zip_command_flags[0x100] = IMPLEMENTED | CHECK_READY, /* 0x08 */ 0, IMPLEMENTED | CHECK_READY, /* 0x0A */ - 0, + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ IMPLEMENTED, /* 0x0C */ IMPLEMENTED | ATAPI_ONLY, /* 0x0D */ 0, 0, 0, 0, @@ -94,7 +83,7 @@ const uint8_t zip_command_flags[0x100] = IMPLEMENTED | SCSI_ONLY, /* 0x16 */ IMPLEMENTED | SCSI_ONLY, /* 0x17 */ 0, 0, - IMPLEMENTED, + IMPLEMENTED, /* 0x1A */ IMPLEMENTED | CHECK_READY, /* 0x1B */ 0, IMPLEMENTED, /* 0x1D */ @@ -107,7 +96,8 @@ const uint8_t zip_command_flags[0x100] = IMPLEMENTED | CHECK_READY, /* 0x28 */ 0, IMPLEMENTED | CHECK_READY, /* 0x2A */ - 0, 0, 0, + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ + 0, 0, IMPLEMENTED | CHECK_READY, /* 0x2E */ IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -139,322 +129,331 @@ const uint8_t zip_command_flags[0x100] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -uint64_t zip_mode_sense_page_flags = (1LL << GPMODE_R_W_ERROR_PAGE) | (1LL << 0x02LL) | (1LL << 0x2FLL) | (1LL << GPMODE_ALL_PAGES); -uint64_t zip_250_mode_sense_page_flags = (1LL << GPMODE_R_W_ERROR_PAGE) | (1LL << 0x05LL) | (1LL << 0x08LL) | (1LL << 0x2FLL) | (1LL << GPMODE_ALL_PAGES); +static uint64_t zip_mode_sense_page_flags = (1LL << GPMODE_R_W_ERROR_PAGE) | + (1LL << 0x02LL) | (1LL << 0x2FLL) | + (1LL << GPMODE_ALL_PAGES); +static uint64_t zip_250_mode_sense_page_flags = (1LL << GPMODE_R_W_ERROR_PAGE) | + (1LL << 0x05LL) | (1LL << 0x08LL) | + (1LL << 0x2FLL) | + (1LL << GPMODE_ALL_PAGES); static const mode_sense_pages_t zip_mode_sense_pages_default = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, - { 0x02, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x2f, 0x04, 0x5c, 0x0f, 0xff, 0x0f } -} }; +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, + { 0x02, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x2f, 0x04, 0x5c, 0x0f, 0xff, 0x0f } +} }; static const mode_sense_pages_t zip_250_mode_sense_pages_default = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x05, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x08, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x2f, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } -} }; +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x05, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x08, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x2f, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } +} }; static const mode_sense_pages_t zip_mode_sense_pages_default_scsi = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, - { 0x02, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x2f, 0x04, 0x5c, 0x0f, 0xff, 0x0f } -} }; +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, + { 0x02, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x2f, 0x04, 0x5c, 0x0f, 0xff, 0x0f } +} }; static const mode_sense_pages_t zip_250_mode_sense_pages_default_scsi = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x05, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x08, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x2f, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } -} }; +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x05, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x08, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x2f, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } +} }; static const mode_sense_pages_t zip_mode_sense_pages_changeable = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, - { 0x02, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x2f, 0x04, 0x5c, 0x0f, 0xff, 0x0f } -} }; +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, + { 0x02, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x2f, 0x04, 0x5c, 0x0f, 0xff, 0x0f } +} }; static const mode_sense_pages_t zip_250_mode_sense_pages_changeable = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x05, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x08, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x2f, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } -} }; +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x05, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x08, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x2f, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } +} }; -static mode_sense_pages_t zip_mode_sense_pages_saved[ZIP_NUM]; + +static void zip_command_complete(zip_t *dev); +static void zip_init(zip_t *dev); + +void zip_phase_callback(zip_t *dev); #ifdef ENABLE_ZIP_LOG @@ -466,2100 +465,2247 @@ static void zip_log(const char *format, ...) { #ifdef ENABLE_ZIP_LOG - va_list ap; + va_list ap; - if (zip_do_log) - { - va_start(ap, format); - pclog_ex(format, ap); - va_end(ap); - } + if (zip_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } #endif } -int find_zip_for_channel(uint8_t channel) +int +find_zip_for_channel(uint8_t channel) { - uint8_t i = 0; + uint8_t i = 0; - for (i = 0; i < ZIP_NUM; i++) { - if (((zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || (zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA)) && (zip_drives[i].ide_channel == channel)) - return i; - } - return 0xff; + for (i = 0; i < ZIP_NUM; i++) { + if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel == channel)) + return i; + } + return 0xff; } -void zip_init(int id, int cdb_len_setting); -int zip_load(uint8_t id, wchar_t *fn) +int +zip_load(zip_t *dev, wchar_t *fn) { - int read_only = zip_drives[id].ui_writeprot; - int size = 0; + int read_only = dev->drv->ui_writeprot; + int size = 0; - zip_drives[id].f = plat_fopen(fn, zip_drives[id].ui_writeprot ? L"rb" : L"rb+"); - if (!zip_drives[id].ui_writeprot && !zip_drives[id].f) { - zip_drives[id].f = plat_fopen(fn, L"rb"); - read_only = 1; - } - if (zip_drives[id].f) { - fseek(zip_drives[id].f, 0, SEEK_END); - size = ftell(zip_drives[id].f); + dev->drv->f = plat_fopen(fn, dev->drv->ui_writeprot ? L"rb" : L"rb+"); + if (!dev->drv->ui_writeprot && !dev->drv->f) { + dev->drv->f = plat_fopen(fn, L"rb"); + read_only = 1; + } + if (dev->drv->f) { + fseek(dev->drv->f, 0, SEEK_END); + size = ftell(dev->drv->f); - if ((size == ((ZIP_250_SECTORS << 9) + 0x1000)) || (size == ((ZIP_SECTORS << 9) + 0x1000))) { - /* This is a ZDI image. */ - size -= 0x1000; - zip_drives[id].base = 0x1000; - } else - zip_drives[id].base = 0; + if ((size == ((ZIP_250_SECTORS << 9) + 0x1000)) || (size == ((ZIP_SECTORS << 9) + 0x1000))) { + /* This is a ZDI image. */ + size -= 0x1000; + dev->drv->base = 0x1000; + } else + dev->drv->base = 0; - if (zip_drives[id].is_250) { - if ((size != (ZIP_250_SECTORS << 9)) && (size != (ZIP_SECTORS << 9))) { - zip_log("File is incorrect size for a ZIP image\nMust be exactly %i or %i bytes\n", ZIP_250_SECTORS << 9, ZIP_SECTORS << 9); - fclose(zip_drives[id].f); - zip_drives[id].f = NULL; - zip_drives[id].medium_size = 0; - zip_eject(id); /* Make sure the host OS knows we've rejected (and ejected) the image. */ - return 0; - } - } else { - if (size != (ZIP_SECTORS << 9)) { - zip_log("File is incorrect size for a ZIP image\nMust be exactly %i bytes\n", ZIP_SECTORS << 9); - fclose(zip_drives[id].f); - zip_drives[id].f = NULL; - zip_drives[id].medium_size = 0; - zip_eject(id); /* Make sure the host OS knows we've rejected (and ejected) the image. */ - return 0; - } - } - - zip_drives[id].medium_size = size >> 9; - - fseek(zip_drives[id].f, zip_drives[id].base, SEEK_SET); - - memcpy(zip_drives[id].image_path, fn, sizeof(zip_drives[id].image_path)); - - zip_drives[id].read_only = read_only; - - return 1; - } - - return 0; -} - -void zip_disk_reload(uint8_t id) -{ - int ret = 0; - - if (wcslen(zip_drives[id].prev_image_path) == 0) - return; - else - ret = zip_load(id, zip_drives[id].prev_image_path); - - if (ret) - zip[id].unit_attention = 1; -} - -void zip_close(uint8_t id) -{ - if (zip_drives[id].f) { - fclose(zip_drives[id].f); - zip_drives[id].f = NULL; - - memcpy(zip_drives[id].prev_image_path, zip_drives[id].image_path, sizeof(zip_drives[id].prev_image_path)); - memset(zip_drives[id].image_path, 0, sizeof(zip_drives[id].image_path)); - - zip_drives[id].medium_size = 0; - } -} - -void build_atapi_zip_map() -{ - uint8_t i = 0; - - memset(atapi_zip_drives, 0xff, 8); - - for (i = 0; i < 8; i++) { - atapi_zip_drives[i] = find_zip_for_channel(i); - if (atapi_zip_drives[i] != 0xff) - zip_init(atapi_zip_drives[i], 12); - } -} - -int find_zip_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun) -{ - uint8_t i = 0; - - for (i = 0; i < ZIP_NUM; i++) { - if ((zip_drives[i].bus_type == ZIP_BUS_SCSI) && (zip_drives[i].scsi_device_id == scsi_id) && (zip_drives[i].scsi_device_lun == scsi_lun)) - return i; - } - return 0xff; -} - -void build_scsi_zip_map() -{ - uint8_t i = 0; - uint8_t j = 0; - - for (i = 0; i < 16; i++) - memset(scsi_zip_drives[i], 0xff, 8); - - for (i = 0; i < 16; i++) { - for (j = 0; j < 8; j++) { - scsi_zip_drives[i][j] = find_zip_for_scsi_id(i, j); - if (scsi_zip_drives[i][j] != 0xff) - zip_init(scsi_zip_drives[i][j], 12); - } - } -} - -void zip_set_callback(uint8_t id) -{ - if (zip_drives[id].bus_type != ZIP_BUS_SCSI) - ide_set_callback(zip_drives[id].ide_channel, zip[id].callback); -} - -void zip_set_cdb_len(int id, int cdb_len) -{ - zip[id].cdb_len = cdb_len; -} - -void zip_reset_cdb_len(int id) -{ - zip[id].cdb_len = zip[id].cdb_len_setting ? 16 : 12; -} - -void zip_set_signature(int id) -{ - if (id >= ZIP_NUM) - return; - zip[id].phase = 1; - zip[id].request_length = 0xEB14; -} - -void zip_init(int id, int cdb_len_setting) -{ - if (id >= ZIP_NUM) - return; - memset(&(zip[id]), 0, sizeof(zip_t)); - zip[id].requested_blocks = 1; - if (cdb_len_setting <= 1) - zip[id].cdb_len_setting = cdb_len_setting; - zip_reset_cdb_len(id); - zip[id].sense[0] = 0xf0; - zip[id].sense[7] = 10; - zip_drives[id].bus_mode = 0; - if (zip_drives[id].bus_type >= ZIP_BUS_ATAPI_PIO_AND_DMA) - zip_drives[id].bus_mode |= 2; - if (zip_drives[id].bus_type < ZIP_BUS_SCSI) - zip_drives[id].bus_mode |= 1; - zip_log("ZIP %i: Bus type %i, bus mode %i\n", id, zip_drives[id].bus_type, zip_drives[id].bus_mode); - if (zip_drives[id].bus_type < ZIP_BUS_SCSI) - zip_set_signature(id); - zip[id].status = READY_STAT | DSC_STAT; - zip[id].pos = 0; - zip[id].packet_status = 0xff; - zip_sense_key = zip_asc = zip_ascq = zip[id].unit_attention = 0; - zip[id].cdb_len_setting = 0; - zip[id].cdb_len = 12; -} - -int zip_supports_pio(int id) -{ - return (zip_drives[id].bus_mode & 1); -} - -int zip_supports_dma(int id) -{ - return (zip_drives[id].bus_mode & 2); -} - -/* Returns: 0 for none, 1 for PIO, 2 for DMA. */ -int zip_current_mode(int id) -{ - if (!zip_supports_pio(id) && !zip_supports_dma(id)) - return 0; - if (zip_supports_pio(id) && !zip_supports_dma(id)) { - zip_log("ZIP %i: Drive does not support DMA, setting to PIO\n", id); - return 1; - } - if (!zip_supports_pio(id) && zip_supports_dma(id)) - return 2; - if (zip_supports_pio(id) && zip_supports_dma(id)) { - zip_log("ZIP %i: Drive supports both, setting to %s\n", id, (zip[id].features & 1) ? "DMA" : "PIO", id); - return (zip[id].features & 1) ? 2 : 1; - } - - return 0; -} - -/* Translates ATAPI status (ERR_STAT flag) to SCSI status. */ -int zip_ZIP_PHASE_to_scsi(uint8_t id) -{ - if (zip[id].status & ERR_STAT) - return SCSI_STATUS_CHECK_CONDITION; - else - return SCSI_STATUS_OK; -} - -/* Translates ATAPI phase (DRQ, I/O, C/D) to SCSI phase (MSG, C/D, I/O). */ -int zip_atapi_phase_to_scsi(uint8_t id) -{ - if (zip[id].status & 8) { - switch (zip[id].phase & 3) { - case 0: - return 0; - case 1: - return 2; - case 2: - return 1; - case 3: - return 7; + if (dev->drv->is_250) { + if ((size != (ZIP_250_SECTORS << 9)) && (size != (ZIP_SECTORS << 9))) { + zip_log("File is incorrect size for a ZIP image\nMust be exactly %i or %i bytes\n", + ZIP_250_SECTORS << 9, ZIP_SECTORS << 9); + fclose(dev->drv->f); + dev->drv->f = NULL; + dev->drv->medium_size = 0; + zip_eject(dev->id); /* Make sure the host OS knows we've rejected (and ejected) the image. */ + return 0; } } else { - if ((zip[id].phase & 3) == 3) - return 3; - else - return 4; - } - - return 0; -} - -int zip_lba_to_msf_accurate(int lba) -{ - int temp_pos; - int m, s, f; - - temp_pos = lba + 150; - f = temp_pos % 75; - temp_pos -= f; - temp_pos /= 75; - s = temp_pos % 60; - temp_pos -= s; - temp_pos /= 60; - m = temp_pos; - - return ((m << 16) | (s << 8) | f); -} - -void zip_mode_sense_load(uint8_t id) -{ - FILE *f; - wchar_t file_name[512]; - int i; - memset(&zip_mode_sense_pages_saved[id], 0, sizeof(mode_sense_pages_t)); - for (i = 0; i < 0x3f; i++) { - if (zip_drives[id].is_250) { - if (zip_250_mode_sense_pages_default.pages[i][1] != 0) { - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) - memcpy(zip_mode_sense_pages_saved[id].pages[i], zip_250_mode_sense_pages_default_scsi.pages[i], zip_250_mode_sense_pages_default_scsi.pages[i][1] + 2); - else - memcpy(zip_mode_sense_pages_saved[id].pages[i], zip_250_mode_sense_pages_default.pages[i], zip_250_mode_sense_pages_default.pages[i][1] + 2); - } - } else { - if (zip_mode_sense_pages_default.pages[i][1] != 0) { - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) - memcpy(zip_mode_sense_pages_saved[id].pages[i], zip_mode_sense_pages_default_scsi.pages[i], zip_mode_sense_pages_default_scsi.pages[i][1] + 2); - else - memcpy(zip_mode_sense_pages_saved[id].pages[i], zip_mode_sense_pages_default.pages[i], zip_mode_sense_pages_default.pages[i][1] + 2); - } + if (size != (ZIP_SECTORS << 9)) { + zip_log("File is incorrect size for a ZIP image\nMust be exactly %i bytes\n", + ZIP_SECTORS << 9); + fclose(dev->drv->f); + dev->drv->f = NULL; + dev->drv->medium_size = 0; + zip_eject(dev->id); /* Make sure the host OS knows we've rejected (and ejected) the image. */ + return 0; } } - memset(file_name, 0, 512 * sizeof(wchar_t)); - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) - swprintf(file_name, 512, L"scsi_zip_%02i_mode_sense_bin", id); - else - swprintf(file_name, 512, L"zip_%02i_mode_sense_bin", id); - f = plat_fopen(nvr_path(file_name), L"rb"); - if (f) - fclose(f); -} -void zip_mode_sense_save(uint8_t id) -{ - FILE *f; - wchar_t file_name[512]; - memset(file_name, 0, 512 * sizeof(wchar_t)); - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) - swprintf(file_name, 512, L"scsi_zip_%02i_mode_sense_bin", id); - else - swprintf(file_name, 512, L"zip_%02i_mode_sense_bin", id); - f = plat_fopen(nvr_path(file_name), L"wb"); - if (f) - fclose(f); -} + dev->drv->medium_size = size >> 9; -static void zip_command_complete(uint8_t id); + fseek(dev->drv->f, dev->drv->base, SEEK_SET); -uint8_t zip_read_capacity_cdb[12] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + memcpy(dev->drv->image_path, fn, sizeof(dev->drv->image_path)); -int zip_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len) -{ - int size = 0; - - if (zip_drives[id].is_250) - size = zip_drives[id].medium_size - 1; /* IMPORTANT: What's returned is the last LBA block. */ - else - size = ZIP_SECTORS - 1; /* IMPORTANT: What's returned is the last LBA block. */ - memset(buffer, 0, 8); - buffer[0] = (size >> 24) & 0xff; - buffer[1] = (size >> 16) & 0xff; - buffer[2] = (size >> 8) & 0xff; - buffer[3] = size & 0xff; - buffer[6] = 2; /* 512 = 0x0200 */ - *len = 8; + dev->drv->read_only = read_only; return 1; + } + + return 0; } + +void +zip_disk_reload(zip_t *dev) +{ + int ret = 0; + + if (wcslen(dev->drv->prev_image_path) == 0) + return; + else + ret = zip_load(dev, dev->drv->prev_image_path); + + if (ret) + dev->unit_attention = 1; +} + + +void +zip_disk_close(zip_t *dev) +{ + if (dev->drv->f) { + fclose(dev->drv->f); + dev->drv->f = NULL; + + memcpy(dev->drv->prev_image_path, dev->drv->image_path, sizeof(dev->drv->prev_image_path)); + memset(dev->drv->image_path, 0, sizeof(dev->drv->image_path)); + + dev->drv->medium_size = 0; + } +} + + +void +build_atapi_zip_map() +{ + uint8_t i = 0; + + memset(atapi_zip_drives, 0xff, 8); + + for (i = 0; i < 8; i++) + atapi_zip_drives[i] = find_zip_for_channel(i); +} + + +int +find_zip_for_scsi_id(uint8_t scsi_id) +{ + uint8_t i = 0; + + for (i = 0; i < ZIP_NUM; i++) { + if ((zip_drives[i].bus_type == ZIP_BUS_SCSI) && (zip_drives[i].scsi_device_id == scsi_id)) + return i; + } + return 0xff; +} + + +void +build_scsi_zip_map() +{ + uint8_t i = 0; + + memset(scsi_zip_drives, 0xff, 16); + + for (i = 0; i < 16; i++) + scsi_zip_drives[i] = find_zip_for_scsi_id(i); +} + + +static void +zip_set_callback(zip_t *dev) +{ + if (dev->drv->bus_type != ZIP_BUS_SCSI) + ide_set_callback(dev->drv->ide_channel >> 1, dev->callback); +} + + +void +zip_set_signature(zip_t *dev) +{ + if (dev->id >= ZIP_NUM) + return; + dev->phase = 1; + dev->request_length = 0xEB14; +} + + +static void +zip_init(zip_t *dev) +{ + if (dev->id >= ZIP_NUM) + return; + + dev->requested_blocks = 1; + dev->sense[0] = 0xf0; + dev->sense[7] = 10; + dev->drv->bus_mode = 0; + if (dev->drv->bus_type >= ZIP_BUS_ATAPI) + dev->drv->bus_mode |= 2; + if (dev->drv->bus_type < ZIP_BUS_SCSI) + dev->drv->bus_mode |= 1; + zip_log("ZIP %i: Bus type %i, bus mode %i\n", dev->id, dev->drv->bus_type, dev->drv->bus_mode); + if (dev->drv->bus_type < ZIP_BUS_SCSI) + zip_set_signature(dev); + dev->status = READY_STAT | DSC_STAT; + dev->pos = 0; + dev->packet_status = 0xff; + zip_sense_key = zip_asc = zip_ascq = dev->unit_attention = 0; +} + + +static int +zip_supports_pio(zip_t *dev) +{ + return (dev->drv->bus_mode & 1); +} + + +static int +zip_supports_dma(zip_t *dev) +{ + return (dev->drv->bus_mode & 2); +} + + +/* Returns: 0 for none, 1 for PIO, 2 for DMA. */ +static int +zip_current_mode(zip_t *dev) +{ + if (!zip_supports_pio(dev) && !zip_supports_dma(dev)) + return 0; + if (zip_supports_pio(dev) && !zip_supports_dma(dev)) { + zip_log("ZIP %i: Drive does not support DMA, setting to PIO\n", dev->id); + return 1; + } + if (!zip_supports_pio(dev) && zip_supports_dma(dev)) + return 2; + if (zip_supports_pio(dev) && zip_supports_dma(dev)) { + zip_log("ZIP %i: Drive supports both, setting to %s\n", dev->id, (dev->features & 1) ? "DMA" : "PIO"); + return (dev->features & 1) ? 2 : 1; + } + + return 0; +} + + +/* Translates ATAPI status (ERR_STAT flag) to SCSI status. */ +int +zip_ZIP_PHASE_to_scsi(zip_t *dev) +{ + if (dev->status & ERR_STAT) + return SCSI_STATUS_CHECK_CONDITION; + else + return SCSI_STATUS_OK; +} + + +/* Translates ATAPI phase (DRQ, I/O, C/D) to SCSI phase (MSG, C/D, I/O). */ +int +zip_atapi_phase_to_scsi(zip_t *dev) +{ + if (dev->status & 8) { + switch (dev->phase & 3) { + case 0: + return 0; + case 1: + return 2; + case 2: + return 1; + case 3: + return 7; + } + } else { + if ((dev->phase & 3) == 3) + return 3; + else + return 4; + } + + return 0; +} + + +static void +zip_mode_sense_load(zip_t *dev) +{ + FILE *f; + wchar_t file_name[512]; + int i; + + memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); + for (i = 0; i < 0x3f; i++) { + if (dev->drv->is_250) { + if (zip_250_mode_sense_pages_default.pages[i][1] != 0) { + if (zip_drives[dev->id].bus_type == ZIP_BUS_SCSI) { + memcpy(dev->ms_pages_saved.pages[i], + zip_250_mode_sense_pages_default_scsi.pages[i], + zip_250_mode_sense_pages_default_scsi.pages[i][1] + 2); + } else { + memcpy(dev->ms_pages_saved.pages[i], + zip_250_mode_sense_pages_default.pages[i], + zip_250_mode_sense_pages_default.pages[i][1] + 2); + } + } + } else { + if (zip_mode_sense_pages_default.pages[i][1] != 0) { + if (dev->drv->bus_type == ZIP_BUS_SCSI) { + memcpy(dev->ms_pages_saved.pages[i], + zip_mode_sense_pages_default_scsi.pages[i], + zip_mode_sense_pages_default_scsi.pages[i][1] + 2); + } else { + memcpy(dev->ms_pages_saved.pages[i], + zip_mode_sense_pages_default.pages[i], + zip_mode_sense_pages_default.pages[i][1] + 2); + } + } + } + } + memset(file_name, 0, 512 * sizeof(wchar_t)); + if (dev->drv->bus_type == ZIP_BUS_SCSI) + swprintf(file_name, 512, L"scsi_zip_%02i_mode_sense_bin", dev->id); + else + swprintf(file_name, 512, L"zip_%02i_mode_sense_bin", dev->id); + f = plat_fopen(nvr_path(file_name), L"rb"); + if (f) + fclose(f); +} + + +static void +zip_mode_sense_save(zip_t *dev) +{ + FILE *f; + wchar_t file_name[512]; + + memset(file_name, 0, 512 * sizeof(wchar_t)); + if (dev->drv->bus_type == ZIP_BUS_SCSI) + swprintf(file_name, 512, L"scsi_zip_%02i_mode_sense_bin", dev->id); + else + swprintf(file_name, 512, L"zip_%02i_mode_sense_bin", dev->id); + f = plat_fopen(nvr_path(file_name), L"wb"); + if (f) + fclose(f); +} + + +int +zip_read_capacity(zip_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len) +{ + int size = 0; + + if (dev->drv->is_250) + size = dev->drv->medium_size - 1; /* IMPORTANT: What's returned is the last LBA block. */ + else + size = ZIP_SECTORS - 1; /* IMPORTANT: What's returned is the last LBA block. */ + memset(buffer, 0, 8); + buffer[0] = (size >> 24) & 0xff; + buffer[1] = (size >> 16) & 0xff; + buffer[2] = (size >> 8) & 0xff; + buffer[3] = size & 0xff; + buffer[6] = 2; /* 512 = 0x0200 */ + *len = 8; + + return 1; +} + + /*SCSI Mode Sense 6/10*/ -uint8_t zip_mode_sense_read(uint8_t id, uint8_t page_control, uint8_t page, uint8_t pos) +static uint8_t +zip_mode_sense_read(zip_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) { - switch (page_control) { - case 0: - case 3: - if (zip_drives[id].is_250 && (page == 5) && (pos == 9) && (zip_drives[id].medium_size == ZIP_SECTORS)) + switch (page_control) { + case 0: + case 3: + if (dev->drv->is_250 && (page == 5) && (pos == 9) && (dev->drv->medium_size == ZIP_SECTORS)) + return 0x60; + return dev->ms_pages_saved.pages[page][pos]; + break; + case 1: + if (dev->drv->is_250) + return zip_250_mode_sense_pages_changeable.pages[page][pos]; + else + return zip_mode_sense_pages_changeable.pages[page][pos]; + break; + case 2: + if (dev->drv->is_250) { + if ((page == 5) && (pos == 9) && (dev->drv->medium_size == ZIP_SECTORS)) return 0x60; - return zip_mode_sense_pages_saved[id].pages[page][pos]; - break; - case 1: - if (zip_drives[id].is_250) - return zip_250_mode_sense_pages_changeable.pages[page][pos]; + if (dev->drv->bus_type == ZIP_BUS_SCSI) + return zip_250_mode_sense_pages_default_scsi.pages[page][pos]; else - return zip_mode_sense_pages_changeable.pages[page][pos]; - break; - case 2: - if (zip_drives[id].is_250) { - if ((page == 5) && (pos == 9) && (zip_drives[id].medium_size == ZIP_SECTORS)) - return 0x60; - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) - return zip_250_mode_sense_pages_default_scsi.pages[page][pos]; - else - return zip_250_mode_sense_pages_default.pages[page][pos]; - } else { - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) - return zip_mode_sense_pages_default_scsi.pages[page][pos]; - else - return zip_mode_sense_pages_default.pages[page][pos]; - } - break; - } - - return 0; -} - -uint32_t zip_mode_sense(uint8_t id, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len) -{ - uint64_t page_flags; - uint8_t page_control = (type >> 6) & 3; - - if (zip_drives[id].is_250) - page_flags = zip_250_mode_sense_page_flags; - else - page_flags = zip_mode_sense_page_flags; - - int i = 0; - int j = 0; - - uint8_t msplen; - - type &= 0x3f; - - if (block_descriptor_len) { - if (zip_drives[id].is_250) { - buf[pos++] = ((zip_drives[id].medium_size >> 24) & 0xff); - buf[pos++] = ((zip_drives[id].medium_size >> 16) & 0xff); - buf[pos++] = ((zip_drives[id].medium_size >> 8) & 0xff); - buf[pos++] = ( zip_drives[id].medium_size & 0xff); + return zip_250_mode_sense_pages_default.pages[page][pos]; } else { - buf[pos++] = ((ZIP_SECTORS >> 24) & 0xff); - buf[pos++] = ((ZIP_SECTORS >> 16) & 0xff); - buf[pos++] = ((ZIP_SECTORS >> 8) & 0xff); - buf[pos++] = ( ZIP_SECTORS & 0xff); + if (dev->drv->bus_type == ZIP_BUS_SCSI) + return zip_mode_sense_pages_default_scsi.pages[page][pos]; + else + return zip_mode_sense_pages_default.pages[page][pos]; } - buf[pos++] = 0; /* Reserved. */ - buf[pos++] = 0; /* Block length (0x200 = 512 bytes). */ - buf[pos++] = 2; - buf[pos++] = 0; - } + break; + } - for (i = 0; i < 0x40; i++) { - if ((type == GPMODE_ALL_PAGES) || (type == i)) { - if (page_flags & (1LL << zip[id].current_page_code)) { - buf[pos++] = zip_mode_sense_read(id, page_control, i, 0); - msplen = zip_mode_sense_read(id, page_control, i, 1); - buf[pos++] = msplen; - zip_log("ZIP %i: MODE SENSE: Page [%02X] length %i\n", id, i, msplen); - for (j = 0; j < msplen; j++) - buf[pos++] = zip_mode_sense_read(id, page_control, i, 2 + j); + return 0; +} + + +static uint32_t +zip_mode_sense(zip_t *dev, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len) +{ + uint64_t page_flags; + uint8_t page_control = (type >> 6) & 3; + + if (dev->drv->is_250) + page_flags = zip_250_mode_sense_page_flags; + else + page_flags = zip_mode_sense_page_flags; + + int i = 0; + int j = 0; + + uint8_t msplen; + + type &= 0x3f; + + if (block_descriptor_len) { + if (dev->drv->is_250) { + buf[pos++] = ((dev->drv->medium_size >> 24) & 0xff); + buf[pos++] = ((dev->drv->medium_size >> 16) & 0xff); + buf[pos++] = ((dev->drv->medium_size >> 8) & 0xff); + buf[pos++] = ( dev->drv->medium_size & 0xff); + } else { + buf[pos++] = ((ZIP_SECTORS >> 24) & 0xff); + buf[pos++] = ((ZIP_SECTORS >> 16) & 0xff); + buf[pos++] = ((ZIP_SECTORS >> 8) & 0xff); + buf[pos++] = ( ZIP_SECTORS & 0xff); + } + buf[pos++] = 0; /* Reserved. */ + buf[pos++] = 0; /* Block length (0x200 = 512 bytes). */ + buf[pos++] = 2; + buf[pos++] = 0; + } + + for (i = 0; i < 0x40; i++) { + if ((type == GPMODE_ALL_PAGES) || (type == i)) { + if (page_flags & (1LL << dev->current_page_code)) { + buf[pos++] = zip_mode_sense_read(dev, page_control, i, 0); + msplen = zip_mode_sense_read(dev, page_control, i, 1); + buf[pos++] = msplen; + zip_log("ZIP %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); + for (j = 0; j < msplen; j++) + buf[pos++] = zip_mode_sense_read(dev, page_control, i, 2 + j); + } + } + } + + return pos; +} + + +static void +zip_update_request_length(zip_t *dev, int len, int block_len) +{ + uint32_t bt, min_len = 0; + + dev->max_transfer_len = dev->request_length; + + /* For media access commands, make sure the requested DRQ length matches the block length. */ + switch (dev->current_cdb[0]) { + case 0x08: + case 0x28: + case 0xa8: + /* Make sure total length is not bigger than sum of the lengths of + all the requested blocks. */ + bt = (dev->requested_blocks * block_len); + if (len > bt) + len = bt; + + min_len = block_len; + + if (len <= block_len) { + /* Total length is less or equal to block length. */ + if (dev->max_transfer_len < block_len) { + /* Transfer a minimum of (block size) bytes. */ + dev->max_transfer_len = block_len; + dev->packet_len = block_len; + break; } } - } + default: + dev->packet_len = len; + break; + } + /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ + if ((dev->max_transfer_len & 1) && (dev->max_transfer_len < len)) + dev->max_transfer_len &= 0xfffe; + /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ + if (!dev->max_transfer_len) + dev->max_transfer_len = 65534; - return pos; + if ((len <= dev->max_transfer_len) && (len >= min_len)) + dev->request_length = dev->max_transfer_len = len; + else if (len > dev->max_transfer_len) + dev->request_length = dev->max_transfer_len; + + return; } -void zip_update_request_length(uint8_t id, int len, int block_len) -{ - uint32_t bt; - if (!zip[id].request_length) - zip[id].max_transfer_len = 65534; - else - zip[id].max_transfer_len = zip[id].request_length; - /* For media access commands, make sure the requested DRQ length matches the block length. */ - switch (zip[id].current_cdb[0]) { - case 0x08: - case 0x28: - case 0xa8: - if (zip[id].max_transfer_len < block_len) - zip[id].max_transfer_len = block_len; - bt = (zip[id].requested_blocks * block_len); - if (len > bt) - len = bt; - default: - zip[id].packet_len = len; - break; - } - /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ - if ((zip[id].max_transfer_len & 1) && (zip[id].max_transfer_len < len)) - zip[id].max_transfer_len &= 0xfffe; - /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ - if (len <= zip[id].max_transfer_len) - zip[id].max_transfer_len = len; - return; +static void +zip_command_bus(zip_t *dev) +{ + dev->status = BUSY_STAT; + dev->phase = 1; + dev->pos = 0; + dev->callback = 1LL * ZIP_TIME; + zip_set_callback(dev); } -static void zip_command_common(uint8_t id) -{ - double bytes_per_second, period; - double dusec; - zip[id].status = BUSY_STAT; - zip[id].phase = 1; - zip[id].pos = 0; - if (zip[id].packet_status == ZIP_PHASE_COMPLETE) { - zip_phase_callback(id); - zip[id].callback = 0LL; +static void +zip_command_common(zip_t *dev) +{ + double bytes_per_second, period; + double dusec; + + dev->status = BUSY_STAT; + dev->phase = 1; + dev->pos = 0; + if (dev->packet_status == ZIP_PHASE_COMPLETE) { + zip_phase_callback(dev); + dev->callback = 0LL; + } else { + if (dev->drv->bus_type == ZIP_BUS_SCSI) { + dev->callback = -1LL; /* Speed depends on SCSI controller */ + return; } else { - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { - zip[id].callback = -1LL; /* Speed depends on SCSI controller */ - return; - } else if (zip_drives[id].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA) { - if (zip_current_mode(id) == 2) - bytes_per_second = 66666666.666666666666666; /* 66 MB/s MDMA-2 speed */ - else - bytes_per_second = 8333333.333333333333333; /* 8.3 MB/s PIO-2 speed */ - } else - bytes_per_second = 3333333.333333333333333; /* 3.3 MB/s PIO-0 speed */ - - period = 1000000.0 / bytes_per_second; - dusec = (double) TIMER_USEC; - dusec = dusec * period * (double) (zip[id].packet_len); - zip[id].callback = ((int64_t) dusec); + if (zip_current_mode(dev) == 2) + bytes_per_second = 66666666.666666666666666; /* 66 MB/s MDMA-2 speed */ + else + bytes_per_second = 8333333.333333333333333; /* 8.3 MB/s PIO-2 speed */ } - zip_set_callback(id); + period = 1000000.0 / bytes_per_second; + dusec = (double) TIMER_USEC; + dusec = dusec * period * (double) (dev->packet_len); + dev->callback = ((int64_t) dusec); + } + + zip_set_callback(dev); } -static void zip_command_complete(uint8_t id) + +static void +zip_command_complete(zip_t *dev) { - zip[id].packet_status = ZIP_PHASE_COMPLETE; - zip_command_common(id); + dev->packet_status = ZIP_PHASE_COMPLETE; + zip_command_common(dev); } -static void zip_command_read(uint8_t id) + +static void +zip_command_read(zip_t *dev) { - zip[id].packet_status = ZIP_PHASE_DATA_IN; - zip_command_common(id); - zip[id].total_read = 0; + dev->packet_status = ZIP_PHASE_DATA_IN; + zip_command_common(dev); + dev->total_read = 0; } -static void zip_command_read_dma(uint8_t id) + +static void +zip_command_read_dma(zip_t *dev) { - zip[id].packet_status = ZIP_PHASE_DATA_IN_DMA; - zip_command_common(id); - zip[id].total_read = 0; + dev->packet_status = ZIP_PHASE_DATA_IN_DMA; + zip_command_common(dev); + dev->total_read = 0; } -static void zip_command_write(uint8_t id) + +static void +zip_command_write(zip_t *dev) { - zip[id].packet_status = ZIP_PHASE_DATA_OUT; - zip_command_common(id); + dev->packet_status = ZIP_PHASE_DATA_OUT; + zip_command_common(dev); } -static void zip_command_write_dma(uint8_t id) + +static void +zip_command_write_dma(zip_t *dev) { - zip[id].packet_status = ZIP_PHASE_DATA_OUT_DMA; - zip_command_common(id); + dev->packet_status = ZIP_PHASE_DATA_OUT_DMA; + zip_command_common(dev); } + /* id = Current ZIP device ID; len = Total transfer length; block_len = Length of a single block (why does it matter?!); alloc_len = Allocated transfer length; direction = Transfer direction (0 = read from host, 1 = write to host). */ -static void zip_data_command_finish(uint8_t id, int len, int block_len, int alloc_len, int direction) +static void +zip_data_command_finish(zip_t *dev, int len, int block_len, int alloc_len, int direction) { - zip_log("ZIP %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", id, zip[id].current_cdb[0], len, block_len, alloc_len, direction, zip[id].request_length); - zip[id].pos=0; - if (alloc_len >= 0) { - if (alloc_len < len) { - len = alloc_len; - } + zip_log("ZIP %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", + dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length); + dev->pos = 0; + if (alloc_len >= 0) { + if (alloc_len < len) + len = alloc_len; + } + if ((len == 0) || (zip_current_mode(dev) == 0)) { + if (dev->drv->bus_type != ZIP_BUS_SCSI) + dev->packet_len = 0; + + zip_command_complete(dev); + } else { + if (zip_current_mode(dev) == 2) { + if (dev->drv->bus_type != ZIP_BUS_SCSI) + dev->packet_len = alloc_len; + + if (direction == 0) + zip_command_read_dma(dev); + else + zip_command_write_dma(dev); + } else { + zip_update_request_length(dev, len, block_len); + if (direction == 0) + zip_command_read(dev); + else + zip_command_write(dev); } - if ((len == 0) || (zip_current_mode(id) == 0)) { - if (zip_drives[id].bus_type != ZIP_BUS_SCSI) { - zip[id].packet_len = 0; - } - zip_command_complete(id); - } - else { - if (zip_current_mode(id) == 2) { - if (zip_drives[id].bus_type != ZIP_BUS_SCSI) { - zip[id].packet_len = alloc_len; - } + } - if (direction == 0) - zip_command_read_dma(id); - else - zip_command_write_dma(id); - } - else { - zip_update_request_length(id, len, block_len); - if (direction == 0) - zip_command_read(id); - else - zip_command_write(id); - } - } - - zip_log("ZIP %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", id, zip[id].packet_status, zip[id].request_length, zip[id].packet_len, zip[id].pos, zip[id].phase); + zip_log("ZIP %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", + dev->id, dev->packet_status, dev->request_length, dev->packet_len, dev->pos, dev->phase); } -static void zip_sense_clear(int id, int command) + +static void +zip_sense_clear(zip_t *dev, int command) { - zip[id].previous_command = command; - zip_sense_key = zip_asc = zip_ascq = 0; + dev->previous_command = command; + zip_sense_key = zip_asc = zip_ascq = 0; } -static void zip_set_phase(uint8_t id, uint8_t phase) + +static void +zip_set_phase(zip_t *dev, uint8_t phase) { - uint8_t scsi_id = zip_drives[id].scsi_device_id; - uint8_t scsi_lun = zip_drives[id].scsi_device_lun; + uint8_t scsi_id = dev->drv->scsi_device_id; - if (zip_drives[id].bus_type != ZIP_BUS_SCSI) - return; + if (dev->drv->bus_type != ZIP_BUS_SCSI) + return; - SCSIDevices[scsi_id][scsi_lun].Phase = phase; + SCSIDevices[scsi_id].Phase = phase; } -static void zip_cmd_error(uint8_t id) + +static void +zip_cmd_error(zip_t *dev) { - zip_set_phase(id, SCSI_PHASE_STATUS); - zip[id].error = ((zip_sense_key & 0xf) << 4) | ABRT_ERR; - if (zip[id].unit_attention) - zip[id].error |= MCR_ERR; - zip[id].status = READY_STAT | ERR_STAT; - zip[id].phase = 3; - zip[id].pos = 0; - zip[id].packet_status = 0x80; - zip[id].callback = 50LL * ZIP_TIME; - zip_set_callback(id); - zip_log("ZIP %i: [%02X] ERROR: %02X/%02X/%02X\n", id, zip[id].current_cdb[0], zip_sense_key, zip_asc, zip_ascq); + zip_set_phase(dev, SCSI_PHASE_STATUS); + dev->error = ((zip_sense_key & 0xf) << 4) | ABRT_ERR; + if (dev->unit_attention) + dev->error |= MCR_ERR; + dev->status = READY_STAT | ERR_STAT; + dev->phase = 3; + dev->pos = 0; + dev->packet_status = 0x80; + dev->callback = 50LL * ZIP_TIME; + zip_set_callback(dev); + zip_log("ZIP %i: [%02X] ERROR: %02X/%02X/%02X\n", dev->id, dev->current_cdb[0], zip_sense_key, zip_asc, zip_ascq); } -static void zip_unit_attention(uint8_t id) + +static void +zip_unit_attention(zip_t *dev) { - zip_set_phase(id, SCSI_PHASE_STATUS); - zip[id].error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; - if (zip[id].unit_attention) - zip[id].error |= MCR_ERR; - zip[id].status = READY_STAT | ERR_STAT; - zip[id].phase = 3; - zip[id].pos = 0; - zip[id].packet_status = 0x80; - zip[id].callback = 50LL * ZIP_TIME; - zip_set_callback(id); - zip_log("ZIP %i: UNIT ATTENTION\n", id); + zip_set_phase(dev, SCSI_PHASE_STATUS); + dev->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; + if (dev->unit_attention) + dev->error |= MCR_ERR; + dev->status = READY_STAT | ERR_STAT; + dev->phase = 3; + dev->pos = 0; + dev->packet_status = 0x80; + dev->callback = 50LL * ZIP_TIME; + zip_set_callback(dev); + zip_log("ZIP %i: UNIT ATTENTION\n", dev->id); } -static void zip_not_ready(uint8_t id) + +static void +zip_bus_master_error(zip_t *dev) { - zip_sense_key = SENSE_NOT_READY; - zip_asc = ASC_MEDIUM_NOT_PRESENT; - zip_ascq = 0; - zip_cmd_error(id); + zip_sense_key = zip_asc = zip_ascq = 0; + zip_cmd_error(dev); } -static void zip_write_protected(uint8_t id) + +static void +zip_not_ready(zip_t *dev) { - zip_sense_key = SENSE_UNIT_ATTENTION; - zip_asc = ASC_WRITE_PROTECTED; - zip_ascq = 0; - zip_cmd_error(id); + zip_sense_key = SENSE_NOT_READY; + zip_asc = ASC_MEDIUM_NOT_PRESENT; + zip_ascq = 0; + zip_cmd_error(dev); } -static void zip_invalid_lun(uint8_t id) + +static void +zip_write_protected(zip_t *dev) { - zip_sense_key = SENSE_ILLEGAL_REQUEST; - zip_asc = ASC_INV_LUN; - zip_ascq = 0; - zip_cmd_error(id); + zip_sense_key = SENSE_UNIT_ATTENTION; + zip_asc = ASC_WRITE_PROTECTED; + zip_ascq = 0; + zip_cmd_error(dev); } -static void zip_illegal_opcode(uint8_t id) + +static void +zip_invalid_lun(zip_t *dev) { - zip_sense_key = SENSE_ILLEGAL_REQUEST; - zip_asc = ASC_ILLEGAL_OPCODE; - zip_ascq = 0; - zip_cmd_error(id); + zip_sense_key = SENSE_ILLEGAL_REQUEST; + zip_asc = ASC_INV_LUN; + zip_ascq = 0; + zip_cmd_error(dev); } -static void zip_lba_out_of_range(uint8_t id) + +static void +zip_illegal_opcode(zip_t *dev) { - zip_sense_key = SENSE_ILLEGAL_REQUEST; - zip_asc = ASC_LBA_OUT_OF_RANGE; - zip_ascq = 0; - zip_cmd_error(id); + zip_sense_key = SENSE_ILLEGAL_REQUEST; + zip_asc = ASC_ILLEGAL_OPCODE; + zip_ascq = 0; + zip_cmd_error(dev); } -static void zip_invalid_field(uint8_t id) + +static void +zip_lba_out_of_range(zip_t *dev) { - zip_sense_key = SENSE_ILLEGAL_REQUEST; - zip_asc = ASC_INV_FIELD_IN_CMD_PACKET; - zip_ascq = 0; - zip_cmd_error(id); - zip[id].status = 0x53; + zip_sense_key = SENSE_ILLEGAL_REQUEST; + zip_asc = ASC_LBA_OUT_OF_RANGE; + zip_ascq = 0; + zip_cmd_error(dev); } -static void zip_invalid_field_pl(uint8_t id) + +static void +zip_invalid_field(zip_t *dev) { - zip_sense_key = SENSE_ILLEGAL_REQUEST; - zip_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; - zip_ascq = 0; - zip_cmd_error(id); - zip[id].status = 0x53; + zip_sense_key = SENSE_ILLEGAL_REQUEST; + zip_asc = ASC_INV_FIELD_IN_CMD_PACKET; + zip_ascq = 0; + zip_cmd_error(dev); + dev->status = 0x53; } -static void zip_data_phase_error(uint8_t id) + +static void +zip_invalid_field_pl(zip_t *dev) { - zip_sense_key = SENSE_ILLEGAL_REQUEST; - zip_asc = ASC_DATA_PHASE_ERROR; - zip_ascq = 0; - zip_cmd_error(id); + zip_sense_key = SENSE_ILLEGAL_REQUEST; + zip_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; + zip_ascq = 0; + zip_cmd_error(dev); + dev->status = 0x53; } -#define zipbufferb zip[id].buffer -int zip_blocks(uint8_t id, uint32_t *len, int first_batch, int out) +static void +zip_data_phase_error(zip_t *dev) { - zip[id].data_pos = 0; - - *len = 0; - - if (!zip[id].sector_len) { - zip_command_complete(id); - return -1; - } - - zip_log("%sing %i blocks starting from %i...\n", out ? "Writ" : "Read", zip[id].requested_blocks, zip[id].sector_pos); - - if (zip[id].sector_pos >= zip_drives[id].medium_size) { - zip_log("ZIP %i: Trying to %s beyond the end of disk\n", id, out ? "write" : "read"); - zip_lba_out_of_range(id); - return 0; - } - - *len = zip[id].requested_blocks << 9; - - fseek(zip_drives[id].f, zip_drives[id].base + (zip[id].sector_pos << 9), SEEK_SET); - if (out) - fwrite(zipbufferb, 1, *len, zip_drives[id].f); - else - fread(zipbufferb, 1, *len, zip_drives[id].f); - - zip_log("%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); - - zip[id].sector_pos += zip[id].requested_blocks; - zip[id].sector_len -= zip[id].requested_blocks; - - return 1; + zip_sense_key = SENSE_ILLEGAL_REQUEST; + zip_asc = ASC_DATA_PHASE_ERROR; + zip_ascq = 0; + zip_cmd_error(dev); } -void zip_insert(uint8_t id) + +static int +zip_blocks(zip_t *dev, uint32_t *len, int first_batch, int out) { - zip[id].unit_attention = 1; + dev->data_pos = 0; + + *len = 0; + + if (!dev->sector_len) { + zip_command_complete(dev); + return -1; + } + + zip_log("%sing %i blocks starting from %i...\n", out ? "Writ" : "Read", dev->requested_blocks, dev->sector_pos); + + if (dev->sector_pos >= dev->drv->medium_size) { + zip_log("ZIP %i: Trying to %s beyond the end of disk\n", dev->id, out ? "write" : "read"); + zip_lba_out_of_range(dev); + return 0; + } + + *len = dev->requested_blocks << 9; + + fseek(dev->drv->f, dev->drv->base + (dev->sector_pos << 9), SEEK_SET); + if (out) + fwrite(zipbufferb, 1, *len, dev->drv->f); + else + fread(zipbufferb, 1, *len, dev->drv->f); + + zip_log("%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); + + dev->sector_pos += dev->requested_blocks; + dev->sector_len -= dev->requested_blocks; + + return 1; } + +void +zip_insert(zip_t *dev) +{ + dev->unit_attention = 1; +} + + /*SCSI Sense Initialization*/ -void zip_sense_code_ok(uint8_t id) +void +zip_sense_code_ok(zip_t *dev) { - zip_sense_key = SENSE_NONE; - zip_asc = 0; - zip_ascq = 0; + zip_sense_key = SENSE_NONE; + zip_asc = 0; + zip_ascq = 0; } -int zip_pre_execution_check(uint8_t id, uint8_t *cdb) + +static int +zip_pre_execution_check(zip_t *dev, uint8_t *cdb) { - int ready = 0; + int ready = 0; - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { - if (((zip[id].request_length >> 5) & 7) != zip_drives[id].scsi_device_lun) { - zip_log("ZIP %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", id, ((zip[id].request_length >> 5) & 7)); - zip_invalid_lun(id); - return 0; - } - } - - if (!(zip_command_flags[cdb[0]] & IMPLEMENTED)) { - zip_log("ZIP %i: Attempting to execute unknown command %02X over %s\n", id, cdb[0], (zip_drives[id].bus_type == ZIP_BUS_SCSI) ? "SCSI" : ((zip_drives[id].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA) ? "ATAPI PIO/DMA" : "ATAPI PIO")); - - zip_illegal_opcode(id); + if (dev->drv->bus_type == ZIP_BUS_SCSI) { + if ((cdb[0] != GPCMD_REQUEST_SENSE) && (cdb[1] & 0xe0)) { + zip_log("ZIP %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", dev->id, ((dev->request_length >> 5) & 7)); + zip_invalid_lun(dev); return 0; } + } - if ((zip_drives[id].bus_type < ZIP_BUS_SCSI) && (zip_command_flags[cdb[0]] & SCSI_ONLY)) { - zip_log("ZIP %i: Attempting to execute SCSI-only command %02X over ATAPI\n", id, cdb[0]); - zip_illegal_opcode(id); + if (!(zip_command_flags[cdb[0]] & IMPLEMENTED)) { + zip_log("ZIP %i: Attempting to execute unknown command %02X over %s\n", dev->id, cdb[0], + (dev->drv->bus_type == ZIP_BUS_SCSI) ? "SCSI" : "ATAPI"); + + zip_illegal_opcode(dev); + return 0; + } + + if ((dev->drv->bus_type < ZIP_BUS_SCSI) && (zip_command_flags[cdb[0]] & SCSI_ONLY)) { + zip_log("ZIP %i: Attempting to execute SCSI-only command %02X over ATAPI\n", dev->id, cdb[0]); + zip_illegal_opcode(dev); + return 0; + } + + if ((dev->drv->bus_type == ZIP_BUS_SCSI) && (zip_command_flags[cdb[0]] & ATAPI_ONLY)) { + zip_log("ZIP %i: Attempting to execute ATAPI-only command %02X over SCSI\n", dev->id, cdb[0]); + zip_illegal_opcode(dev); + return 0; + } + + ready = (dev->drv->f != NULL); + + /* If the drive is not ready, there is no reason to keep the + UNIT ATTENTION condition present, as we only use it to mark + disc changes. */ + if (!ready && dev->unit_attention) + dev->unit_attention = 0; + + /* If the UNIT ATTENTION condition is set and the command does not allow + execution under it, error out and report the condition. */ + if (dev->unit_attention == 1) { + /* Only increment the unit attention phase if the command can not pass through it. */ + if (!(zip_command_flags[cdb[0]] & ALLOW_UA)) { + /* zip_log("ZIP %i: Unit attention now 2\n", dev->id); */ + dev->unit_attention = 2; + zip_log("ZIP %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", dev->id, cdb[0]); + zip_unit_attention(dev); return 0; } - - if ((zip_drives[id].bus_type == ZIP_BUS_SCSI) && (zip_command_flags[cdb[0]] & ATAPI_ONLY)) { - zip_log("ZIP %i: Attempting to execute ATAPI-only command %02X over SCSI\n", id, cdb[0]); - zip_illegal_opcode(id); - return 0; + } else if (dev->unit_attention == 2) { + if (cdb[0] != GPCMD_REQUEST_SENSE) { + /* zip_log("ZIP %i: Unit attention now 0\n", dev->id); */ + dev->unit_attention = 0; } + } - ready = (zip_drives[id].f != NULL); + /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* + the UNIT ATTENTION condition if it's set. */ + if (cdb[0] != GPCMD_REQUEST_SENSE) + zip_sense_clear(dev, cdb[0]); + /* Next it's time for NOT READY. */ + if (!ready) + dev->media_status = MEC_MEDIA_REMOVAL; + else + dev->media_status = (dev->unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE; + + if ((zip_command_flags[cdb[0]] & CHECK_READY) && !ready) { + zip_log("ZIP %i: Not ready (%02X)\n", dev->id, cdb[0]); + zip_not_ready(dev); + return 0; + } + + zip_log("ZIP %i: Continuing with command %02X\n", dev->id, cdb[0]); + + return 1; +} + + +static void +zip_seek(zip_t *dev, uint32_t pos) +{ + /* zip_log("ZIP %i: Seek %08X\n", dev->id, pos); */ + dev->sector_pos = pos; +} + + +static void +zip_rezero(zip_t *dev) +{ + dev->sector_pos = dev->sector_len = 0; + zip_seek(dev, 0); +} + + +void +zip_reset(zip_t *dev) +{ + zip_rezero(dev); + dev->status = 0; + dev->callback = 0LL; + zip_set_callback(dev); + dev->packet_status = 0xff; + dev->unit_attention = 0; +} + + +static void +zip_request_sense(zip_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc) +{ + /*Will return 18 bytes of 0*/ + if (alloc_length != 0) { + memset(buffer, 0, alloc_length); + if (!desc) + memcpy(buffer, dev->sense, alloc_length); + else { + buffer[1] = zip_sense_key; + buffer[2] = zip_asc; + buffer[3] = zip_ascq; + } + } + + buffer[0] = desc ? 0x72 : 0x70; + + if (dev->unit_attention && (zip_sense_key == 0)) { + buffer[desc ? 1 : 2] = SENSE_UNIT_ATTENTION; + buffer[desc ? 2 : 12] = ASC_MEDIUM_MAY_HAVE_CHANGED; + buffer[desc ? 3 : 13] = 0; + } + + zip_log("ZIP %i: Reporting sense: %02X %02X %02X\n", dev->id, buffer[2], buffer[12], buffer[13]); + + if (buffer[desc ? 1 : 2] == SENSE_UNIT_ATTENTION) { + /* If the last remaining sense is unit attention, clear + that condition. */ + dev->unit_attention = 0; + } + + /* Clear the sense stuff as per the spec. */ + zip_sense_clear(dev, GPCMD_REQUEST_SENSE); +} + + +void +zip_request_sense_for_scsi(zip_t *dev, uint8_t *buffer, uint8_t alloc_length) +{ + int ready = 0; + + ready = (dev->drv->f != NULL); + + if (!ready && dev->unit_attention) { /* If the drive is not ready, there is no reason to keep the UNIT ATTENTION condition present, as we only use it to mark disc changes. */ - if (!ready && zip[id].unit_attention) - zip[id].unit_attention = 0; + dev->unit_attention = 0; + } - /* If the UNIT ATTENTION condition is set and the command does not allow - execution under it, error out and report the condition. */ - if (zip[id].unit_attention == 1) { - /* Only increment the unit attention phase if the command can not pass through it. */ - if (!(zip_command_flags[cdb[0]] & ALLOW_UA)) { - /* zip_log("ZIP %i: Unit attention now 2\n", id); */ - zip[id].unit_attention = 2; - zip_log("ZIP %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", id, cdb[0]); - zip_unit_attention(id); - return 0; + /* Do *NOT* advance the unit attention phase. */ + + zip_request_sense(dev, buffer, alloc_length, 0); +} + + +static void +zip_set_buf_len(zip_t *dev, int32_t *BufLen, uint32_t *src_len) +{ + if (dev->drv->bus_type == ZIP_BUS_SCSI) { + if (*BufLen == -1) + *BufLen = *src_len; + else { + *BufLen = MIN(*src_len, *BufLen); + *src_len = *BufLen; + } + zip_log("ZIP %i: Actual transfer length: %i\n", dev->id, *BufLen); + } +} + + +static void +zip_buf_alloc(zip_t *dev, uint32_t len) +{ + zip_log("ZIP %i: Allocated buffer length: %i\n", dev->id, len); + zipbufferb = (uint8_t *) malloc(len); +} + + +static void +zip_buf_free(zip_t *dev) +{ + if (zipbufferb) { + zip_log("ZIP %i: Freeing buffer...\n", dev->id); + free(zipbufferb); + zipbufferb = NULL; + } +} + + +void +zip_command(zip_t *dev, uint8_t *cdb) +{ + int pos = 0, block_desc = 0; + int ret; + uint32_t len, max_len; + uint32_t alloc_length, i = 0; + unsigned size_idx, idx = 0; + unsigned preamble_len; + int32_t blen = 0; + int32_t *BufLen; + + if (dev->drv->bus_type == ZIP_BUS_SCSI) { + BufLen = &SCSIDevices[dev->drv->scsi_device_id].BufferLength; + dev->status &= ~ERR_STAT; + } else { + BufLen = &blen; + dev->error = 0; + } + + dev->packet_len = 0; + dev->request_pos = 0; + + dev->data_pos = 0; + + memcpy(dev->current_cdb, cdb, 12); + + if (cdb[0] != 0) { + zip_log("ZIP %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", + dev->id, cdb[0], zip_sense_key, zip_asc, zip_ascq, dev->unit_attention); + zip_log("ZIP %i: Request length: %04X\n", dev->id, dev->request_length); + + zip_log("ZIP %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, + cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], + cdb[8], cdb[9], cdb[10], cdb[11]); + } + + dev->sector_len = 0; + + zip_set_phase(dev, SCSI_PHASE_STATUS); + + /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ + if (zip_pre_execution_check(dev, cdb) == 0) + return; + + switch (cdb[0]) { + case GPCMD_SEND_DIAGNOSTIC: + if (!(cdb[1] & (1 << 2))) { + zip_invalid_field(dev); + return; } - } - else if (zip[id].unit_attention == 2) { - if (cdb[0] != GPCMD_REQUEST_SENSE) { - /* zip_log("ZIP %i: Unit attention now 0\n", id); */ - zip[id].unit_attention = 0; + case GPCMD_SCSI_RESERVE: + case GPCMD_SCSI_RELEASE: + case GPCMD_TEST_UNIT_READY: + zip_set_phase(dev, SCSI_PHASE_STATUS); + zip_command_complete(dev); + break; + + case GPCMD_FORMAT_UNIT: + if ((dev->drv->bus_type == ZIP_BUS_SCSI) && dev->drv->read_only) { + zip_write_protected(dev); + return; } - } - /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* - the UNIT ATTENTION condition if it's set. */ - if (cdb[0] != GPCMD_REQUEST_SENSE) - zip_sense_clear(id, cdb[0]); + zip_set_phase(dev, SCSI_PHASE_STATUS); + zip_command_complete(dev); + break; - /* Next it's time for NOT READY. */ - if (!ready) - zip[id].media_status = MEC_MEDIA_REMOVAL; - else - zip[id].media_status = (zip[id].unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE; - - if ((zip_command_flags[cdb[0]] & CHECK_READY) && !ready) { - zip_log("ZIP %i: Not ready (%02X)\n", id, cdb[0]); - zip_not_ready(id); - return 0; - } - - zip_log("ZIP %i: Continuing with command %02X\n", id, cdb[0]); - - return 1; -} - -void zip_clear_callback(uint8_t channel) -{ - uint8_t id = atapi_zip_drives[channel]; - - if (id < ZIP_NUM) - { - zip[id].callback = 0LL; - zip_set_callback(id); - } -} - -static void zip_seek(uint8_t id, uint32_t pos) -{ - /* zip_log("ZIP %i: Seek %08X\n", id, pos); */ - zip[id].sector_pos = pos; -} - -static void zip_rezero(uint8_t id) -{ - zip[id].sector_pos = zip[id].sector_len = 0; - zip_seek(id, 0); -} - -void zip_reset(uint8_t id) -{ - zip_rezero(id); - zip[id].status = 0; - zip[id].callback = 0LL; - zip_set_callback(id); - zip[id].packet_status = 0xff; - zip[id].unit_attention = 0; -} - -void zip_request_sense(uint8_t id, uint8_t *buffer, uint8_t alloc_length, int desc) -{ - /*Will return 18 bytes of 0*/ - if (alloc_length != 0) { - memset(buffer, 0, alloc_length); - if (!desc) - memcpy(buffer, zip[id].sense, alloc_length); - else { - buffer[1] = zip_sense_key; - buffer[2] = zip_asc; - buffer[3] = zip_ascq; + case GPCMD_IOMEGA_SENSE: + zip_set_phase(dev, SCSI_PHASE_DATA_IN); + max_len = cdb[4]; + zip_buf_alloc(dev, 256); + zip_set_buf_len(dev, BufLen, &max_len); + memset(zipbufferb, 0, 256); + if (cdb[2] == 1) { + /* This page is related to disk health status - setting + this page to 0 makes disk health read as "marginal". */ + zipbufferb[0] = 0x58; + zipbufferb[1] = 0x00; + for (i = 0x00; i < 0x58; i++) + zipbufferb[i + 0x02] = 0xff; + } else if (cdb[2] == 2) { + zipbufferb[0] = 0x3d; + zipbufferb[1] = 0x00; + for (i = 0x00; i < 0x13; i++) + zipbufferb[i + 0x02] = 0x00; + zipbufferb[0x15] = 0x00; + if (dev->drv->read_only) + zipbufferb[0x15] |= 0x02; + for (i = 0x00; i < 0x27; i++) + zipbufferb[i + 0x16] = 0x00; + } else { + zip_invalid_field(dev); + zip_buf_free(dev); + return; } - } + zip_data_command_finish(dev, 18, 18, cdb[4], 0); + break; - buffer[0] = desc ? 0x72 : 0x70; + case GPCMD_REZERO_UNIT: + dev->sector_pos = dev->sector_len = 0; + zip_seek(dev, 0); + zip_set_phase(dev, SCSI_PHASE_STATUS); + break; - if (zip[id].unit_attention && (zip_sense_key == 0)) { - buffer[desc ? 1 : 2]=SENSE_UNIT_ATTENTION; - buffer[desc ? 2 : 12]=ASC_MEDIUM_MAY_HAVE_CHANGED; - buffer[desc ? 3 : 13]=0; - } + case GPCMD_REQUEST_SENSE: + /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE + should forget about the not ready, and report unit attention straight away. */ + zip_set_phase(dev, SCSI_PHASE_DATA_IN); + max_len = cdb[4]; + zip_buf_alloc(dev, 256); + zip_set_buf_len(dev, BufLen, &max_len); + len = (cdb[1] & 1) ? 8 : 18; + zip_request_sense(dev, zipbufferb, max_len, cdb[1] & 1); + zip_data_command_finish(dev, len, len, cdb[4], 0); + break; - zip_log("ZIP %i: Reporting sense: %02X %02X %02X\n", id, buffer[2], buffer[12], buffer[13]); + case GPCMD_MECHANISM_STATUS: + zip_set_phase(dev, SCSI_PHASE_DATA_IN); + len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - if (buffer[desc ? 1 : 2] == SENSE_UNIT_ATTENTION) { - /* If the last remaining sense is unit attention, clear - that condition. */ - zip[id].unit_attention = 0; - } + zip_buf_alloc(dev, 8); - /* Clear the sense stuff as per the spec. */ - zip_sense_clear(id, GPCMD_REQUEST_SENSE); -} + zip_set_buf_len(dev, BufLen, &len); -void zip_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length) -{ - int ready = 0; + memset(zipbufferb, 0, 8); + zipbufferb[5] = 1; - ready = (zip_drives[id].f != NULL); + zip_data_command_finish(dev, 8, 8, len, 0); + break; - if (!ready && zip[id].unit_attention) { - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - zip[id].unit_attention = 0; - } + case GPCMD_READ_6: + case GPCMD_READ_10: + case GPCMD_READ_12: + zip_set_phase(dev, SCSI_PHASE_DATA_IN); + alloc_length = 512; - /* Do *NOT* advance the unit attention phase. */ - - zip_request_sense(id, buffer, alloc_length, 0); -} - -void zip_set_buf_len(uint8_t id, int32_t *BufLen, uint32_t *src_len) -{ - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { - if (*BufLen == -1) - *BufLen = *src_len; - else { - *BufLen = MIN(*src_len, *BufLen); - *src_len = *BufLen; + switch(cdb[0]) { + case GPCMD_READ_6: + dev->sector_len = cdb[4]; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + break; + case GPCMD_READ_10: + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + break; + case GPCMD_READ_12: + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + break; } - zip_log("ZIP %i: Actual transfer length: %i\n", id, *BufLen); - } -} -void zip_buf_alloc(uint8_t id, uint32_t len) -{ - zip_log("ZIP %i: Allocated buffer length: %i\n", id, len); - zipbufferb = (uint8_t *) malloc(len); -} + if (!dev->sector_len) { + zip_set_phase(dev, SCSI_PHASE_STATUS); + /* zip_log("ZIP %i: All done - callback set\n", dev->id); */ + dev->packet_status = ZIP_PHASE_COMPLETE; + dev->callback = 20LL * ZIP_TIME; + zip_set_callback(dev); + break; + } -void zip_buf_free(uint8_t id) -{ - if (zipbufferb) { - zip_log("ZIP %i: Freeing buffer...\n", id); - free(zipbufferb); - zipbufferb = NULL; - } -} + max_len = dev->sector_len; + dev->requested_blocks = max_len; /* If we're reading all blocks in one go for DMA, why not also for PIO, it should NOT + matter anyway, this step should be identical and only the way the read dat is + transferred to the host should be different. */ -void zip_command(uint8_t id, uint8_t *cdb) -{ - uint32_t len; - int pos=0; - uint32_t max_len; - unsigned idx = 0; - unsigned size_idx; - unsigned preamble_len; - uint32_t alloc_length; - int block_desc = 0; - int ret; - int32_t blen = 0; - int32_t *BufLen; - uint32_t i = 0; + dev->packet_len = max_len * alloc_length; + zip_buf_alloc(dev, dev->packet_len); - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { - BufLen = &SCSIDevices[zip_drives[id].scsi_device_id][zip_drives[id].scsi_device_lun].BufferLength; - zip[id].status &= ~ERR_STAT; - } else { - BufLen = &blen; - zip[id].error = 0; - } + ret = zip_blocks(dev, &alloc_length, 1, 0); + if (ret <= 0) { + zip_buf_free(dev); + return; + } - zip[id].packet_len = 0; - zip[id].request_pos = 0; + dev->requested_blocks = max_len; + dev->packet_len = alloc_length; - zip[id].data_pos = 0; + zip_set_buf_len(dev, BufLen, &dev->packet_len); - memcpy(zip[id].current_cdb, cdb, zip[id].cdb_len); + zip_data_command_finish(dev, alloc_length, 512, alloc_length, 0); - if (cdb[0] != 0) { - zip_log("ZIP %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", id, cdb[0], zip_sense_key, zip_asc, zip_ascq, zip[id].unit_attention); - zip_log("ZIP %i: Request length: %04X\n", id, zip[id].request_length); - - zip_log("ZIP %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", id, - cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], - cdb[8], cdb[9], cdb[10], cdb[11]); - } - - zip[id].sector_len = 0; - - zip_set_phase(id, SCSI_PHASE_STATUS); - - /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ - if (zip_pre_execution_check(id, cdb) == 0) + dev->all_blocks_total = dev->block_total; + if (dev->packet_status != ZIP_PHASE_COMPLETE) + ui_sb_update_icon(SB_ZIP | dev->id, 1); + else + ui_sb_update_icon(SB_ZIP | dev->id, 0); return; - switch (cdb[0]) { - case GPCMD_SEND_DIAGNOSTIC: - if (!(cdb[1] & (1 << 2))) { - zip_invalid_field(id); - return; - } - case GPCMD_SCSI_RESERVE: - case GPCMD_SCSI_RELEASE: - case GPCMD_TEST_UNIT_READY: - zip_set_phase(id, SCSI_PHASE_STATUS); - zip_command_complete(id); + case GPCMD_VERIFY_6: + case GPCMD_VERIFY_10: + case GPCMD_VERIFY_12: + if (!(cdb[1] & 2)) { + zip_set_phase(dev, SCSI_PHASE_STATUS); + zip_command_complete(dev); break; + } + case GPCMD_WRITE_6: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + zip_set_phase(dev, SCSI_PHASE_DATA_OUT); + alloc_length = 512; - case GPCMD_FORMAT_UNIT: - if ((zip_drives[id].bus_type == ZIP_BUS_SCSI) && zip_drives[id].read_only) - { - zip_write_protected(id); - return; - } + if ((dev->drv->bus_type == ZIP_BUS_SCSI) && dev->drv->read_only) { + zip_write_protected(dev); + return; + } - zip_set_phase(id, SCSI_PHASE_STATUS); - zip_command_complete(id); - break; - - case GPCMD_IOMEGA_SENSE: - zip_set_phase(id, SCSI_PHASE_DATA_IN); - max_len = cdb[4]; - zip_buf_alloc(id, 256); - zip_set_buf_len(id, BufLen, &max_len); - memset(zipbufferb, 0, 256); - if (cdb[2] == 1) { - /* This page is related to disk health status - setting - this page to 0 makes disk health read as "marginal". */ - zipbufferb[0] = 0x58; - zipbufferb[1] = 0x00; - for (i = 0x00; i < 0x58; i++) - zipbufferb[i + 0x02] = 0xff; - } else if (cdb[2] == 2) { - zipbufferb[0] = 0x3d; - zipbufferb[1] = 0x00; - for (i = 0x00; i < 0x13; i++) - zipbufferb[i + 0x02] = 0x00; - zipbufferb[0x15] = 0x00; - if (zip_drives[id].read_only) - zipbufferb[0x15] |= 0x02; - for (i = 0x00; i < 0x27; i++) - zipbufferb[i + 0x16] = 0x00; - } else { - zip_invalid_field(id); - zip_buf_free(id); - return; - } - zip_data_command_finish(id, 18, 18, cdb[4], 0); - break; - - case GPCMD_REZERO_UNIT: - zip[id].sector_pos = zip[id].sector_len = 0; - zip_seek(id, 0); - zip_set_phase(id, SCSI_PHASE_STATUS); - break; - - case GPCMD_REQUEST_SENSE: - /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE - should forget about the not ready, and report unit attention straight away. */ - zip_set_phase(id, SCSI_PHASE_DATA_IN); - max_len = cdb[4]; - zip_buf_alloc(id, 256); - zip_set_buf_len(id, BufLen, &max_len); - len = (cdb[1] & 1) ? 8 : 18; - zip_request_sense(id, zipbufferb, max_len, cdb[1] & 1); - zip_data_command_finish(id, len, len, cdb[4], 0); - break; - - case GPCMD_SET_SPEED: - case GPCMD_SET_SPEED_ALT: - zip_set_phase(id, SCSI_PHASE_STATUS); - zip_command_complete(id); - break; - - case GPCMD_MECHANISM_STATUS: - zip_set_phase(id, SCSI_PHASE_DATA_IN); - len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - - zip_buf_alloc(id, 8); - - zip_set_buf_len(id, BufLen, &len); - - memset(zipbufferb, 0, 8); - zipbufferb[5] = 1; - - zip_data_command_finish(id, 8, 8, len, 0); - break; - - case GPCMD_READ_6: - case GPCMD_READ_10: - case GPCMD_READ_12: - zip_set_phase(id, SCSI_PHASE_DATA_IN); - alloc_length = 512; - - switch(cdb[0]) { - case GPCMD_READ_6: - zip[id].sector_len = cdb[4]; - zip[id].sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - zip_log("ZIP %i: Length: %i, LBA: %i\n", id, zip[id].sector_len, zip[id].sector_pos); - break; - case GPCMD_READ_10: - zip[id].sector_len = (cdb[7] << 8) | cdb[8]; - zip[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - zip_log("ZIP %i: Length: %i, LBA: %i\n", id, zip[id].sector_len, zip[id].sector_pos); - break; - case GPCMD_READ_12: - zip[id].sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - zip[id].sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - break; - } - - if (!zip[id].sector_len) { - zip_set_phase(id, SCSI_PHASE_STATUS); - /* zip_log("ZIP %i: All done - callback set\n", id); */ - zip[id].packet_status = ZIP_PHASE_COMPLETE; - zip[id].callback = 20LL * ZIP_TIME; - zip_set_callback(id); + switch(cdb[0]) { + case GPCMD_VERIFY_6: + case GPCMD_WRITE_6: + dev->sector_len = cdb[4]; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); break; - } - - max_len = zip[id].sector_len; - zip[id].requested_blocks = max_len; /* If we're reading all blocks in one go for DMA, why not also for PIO, it should NOT - matter anyway, this step should be identical and only the way the read dat is - transferred to the host should be different. */ - - zip[id].packet_len = max_len * alloc_length; - zip_buf_alloc(id, zip[id].packet_len); - - ret = zip_blocks(id, &alloc_length, 1, 0); - if (ret <= 0) { - zip_buf_free(id); - return; - } - - zip[id].requested_blocks = max_len; - zip[id].packet_len = alloc_length; - - zip_set_buf_len(id, BufLen, &zip[id].packet_len); - - zip_data_command_finish(id, alloc_length, 512, alloc_length, 0); - - zip[id].all_blocks_total = zip[id].block_total; - if (zip[id].packet_status != ZIP_PHASE_COMPLETE) - ui_sb_update_icon(SB_ZIP | id, 1); - else - ui_sb_update_icon(SB_ZIP | id, 0); - return; - - case GPCMD_VERIFY_6: - case GPCMD_VERIFY_10: - case GPCMD_VERIFY_12: - if (!(cdb[1] & 2)) { - zip_set_phase(id, SCSI_PHASE_STATUS); - zip_command_complete(id); + case GPCMD_VERIFY_10: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); break; - } - case GPCMD_WRITE_6: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - zip_set_phase(id, SCSI_PHASE_DATA_OUT); - alloc_length = 512; - - if ((zip_drives[id].bus_type == ZIP_BUS_SCSI) && zip_drives[id].read_only) - { - zip_write_protected(id); - return; - } - - switch(cdb[0]) { - case GPCMD_VERIFY_6: - case GPCMD_WRITE_6: - zip[id].sector_len = cdb[4]; - zip[id].sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - break; - case GPCMD_VERIFY_10: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - zip[id].sector_len = (cdb[7] << 8) | cdb[8]; - zip[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - zip_log("ZIP %i: Length: %i, LBA: %i\n", id, zip[id].sector_len, zip[id].sector_pos); - break; - case GPCMD_VERIFY_12: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - zip[id].sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - zip[id].sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - break; - } - - if (zip_drives[id].is_250) { - if ((zip[id].sector_pos >= zip_drives[id].medium_size) || ((zip[id].sector_pos + zip[id].sector_len - 1) >= zip_drives[id].medium_size)) - { - zip_lba_out_of_range(id); - return; - } - } else { - if ((zip[id].sector_pos >= ZIP_SECTORS) || ((zip[id].sector_pos + zip[id].sector_len - 1) >= ZIP_SECTORS)) - { - zip_lba_out_of_range(id); - return; - } - } - - if (!zip[id].sector_len) { - zip_set_phase(id, SCSI_PHASE_STATUS); - /* zip_log("ZIP %i: All done - callback set\n", id); */ - zip[id].packet_status = ZIP_PHASE_COMPLETE; - zip[id].callback = 20LL * ZIP_TIME; - zip_set_callback(id); + case GPCMD_VERIFY_12: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); break; - } + } - max_len = zip[id].sector_len; - zip[id].requested_blocks = max_len; /* If we're writing all blocks in one go for DMA, why not also for PIO, it should NOT - matter anyway, this step should be identical and only the way the read dat is - transferred to the host should be different. */ - - zip[id].packet_len = max_len * alloc_length; - zip_buf_alloc(id, zip[id].packet_len); - - zip[id].requested_blocks = max_len; - zip[id].packet_len = max_len << 9; - - zip_set_buf_len(id, BufLen, &zip[id].packet_len); - - zip_data_command_finish(id, zip[id].packet_len, 512, zip[id].packet_len, 1); - - zip[id].all_blocks_total = zip[id].block_total; - if (zip[id].packet_status != ZIP_PHASE_COMPLETE) - ui_sb_update_icon(SB_ZIP | id, 1); - else - ui_sb_update_icon(SB_ZIP | id, 0); - return; - - case GPCMD_WRITE_SAME_10: - zip_set_phase(id, SCSI_PHASE_DATA_OUT); - alloc_length = 512; - - if ((cdb[1] & 6) == 6) - { - zip_invalid_field(id); + if (dev->drv->is_250) { + if ((dev->sector_pos >= dev->drv->medium_size) || + ((dev->sector_pos + dev->sector_len - 1) >= dev->drv->medium_size)) { + zip_lba_out_of_range(dev); return; } - - if ((zip_drives[id].bus_type == ZIP_BUS_SCSI) && zip_drives[id].read_only) - { - zip_write_protected(id); + } else { + if ((dev->sector_pos >= ZIP_SECTORS) || + ((dev->sector_pos + dev->sector_len - 1) >= ZIP_SECTORS)) { + zip_lba_out_of_range(dev); return; } + } - zip[id].sector_len = (cdb[7] << 8) | cdb[8]; - zip[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - - if (zip_drives[id].is_250) { - if ((zip[id].sector_pos >= zip_drives[id].medium_size) || ((zip[id].sector_pos + zip[id].sector_len - 1) >= zip_drives[id].medium_size)) - { - zip_lba_out_of_range(id); - return; - } - } else { - if ((zip[id].sector_pos >= ZIP_SECTORS) || ((zip[id].sector_pos + zip[id].sector_len - 1) >= ZIP_SECTORS)) - { - zip_lba_out_of_range(id); - return; - } - } - - if (!zip[id].sector_len) { - zip_set_phase(id, SCSI_PHASE_STATUS); - /* zip_log("ZIP %i: All done - callback set\n", id); */ - zip[id].packet_status = ZIP_PHASE_COMPLETE; - zip[id].callback = 20LL * ZIP_TIME; - zip_set_callback(id); - break; - } - - max_len = zip[id].sector_len; - zip[id].requested_blocks = max_len; /* If we're writing all blocks in one go for DMA, why not also for PIO, it should NOT - matter anyway, this step should be identical and only the way the read dat is - transferred to the host should be different. */ - - zip[id].packet_len = max_len * alloc_length; - zip_buf_alloc(id, zip[id].packet_len); - - zip[id].requested_blocks = max_len; - zip[id].packet_len = alloc_length; - - zip_set_buf_len(id, BufLen, &zip[id].packet_len); - - zip_data_command_finish(id, zip[id].packet_len, 512, zip[id].packet_len, 1); - - zip[id].all_blocks_total = zip[id].block_total; - if (zip[id].packet_status != ZIP_PHASE_COMPLETE) - ui_sb_update_icon(SB_ZIP | id, 1); - else - ui_sb_update_icon(SB_ZIP | id, 0); - return; - - case GPCMD_MODE_SENSE_6: - case GPCMD_MODE_SENSE_10: - zip_set_phase(id, SCSI_PHASE_DATA_IN); - - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) - block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; - else - block_desc = 0; - - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = cdb[4]; - zip_buf_alloc(id, 256); - } else { - len = (cdb[8] | (cdb[7] << 8)); - zip_buf_alloc(id, 65536); - } - - zip[id].current_page_code = cdb[2] & 0x3F; - zip_log("Mode sense page: %02X\n", zip[id].current_page_code); - - if (!(zip_mode_sense_page_flags & (1LL << zip[id].current_page_code))) { - zip_invalid_field(id); - zip_buf_free(id); - return; - } - - memset(zipbufferb, 0, len); - alloc_length = len; - - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = zip_mode_sense(id, zipbufferb, 4, cdb[2], block_desc); - len = MIN(len, alloc_length); - zipbufferb[0] = len - 1; - zipbufferb[1] = 0; - if (block_desc) - zipbufferb[3] = 8; - } else { - len = zip_mode_sense(id, zipbufferb, 8, cdb[2], block_desc); - len = MIN(len, alloc_length); - zipbufferb[0]=(len - 2) >> 8; - zipbufferb[1]=(len - 2) & 255; - zipbufferb[2] = 0; - if (block_desc) { - zipbufferb[6] = 0; - zipbufferb[7] = 8; - } - } - - zip_set_buf_len(id, BufLen, &len); - - zip_log("ZIP %i: Reading mode page: %02X...\n", id, cdb[2]); - - zip_data_command_finish(id, len, len, alloc_length, 0); - return; - - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - zip_set_phase(id, SCSI_PHASE_DATA_OUT); - - if (cdb[0] == GPCMD_MODE_SELECT_6) { - len = cdb[4]; - zip_buf_alloc(id, 256); - } else { - len = (cdb[7] << 8) | cdb[8]; - zip_buf_alloc(id, 65536); - } - - zip_set_buf_len(id, BufLen, &len); - - zip[id].total_length = len; - zip[id].do_page_save = cdb[1] & 1; - - zip[id].current_page_pos = 0; - - zip_data_command_finish(id, len, len, len, 1); - return; - - case GPCMD_START_STOP_UNIT: - zip_set_phase(id, SCSI_PHASE_STATUS); - - switch(cdb[4] & 3) { - case 0: /* Stop the disc. */ - zip_eject(id); /* The Iomega Windows 9x drivers require this. */ - break; - case 1: /* Start the disc and read the TOC. */ - break; - case 2: /* Eject the disc if possible. */ - /* zip_eject(id); */ - break; - case 3: /* Load the disc (close tray). */ - zip_reload(id); - break; - } - - zip_command_complete(id); + if (!dev->sector_len) { + zip_set_phase(dev, SCSI_PHASE_STATUS); + /* zip_log("ZIP %i: All done - callback set\n", dev->id); */ + dev->packet_status = ZIP_PHASE_COMPLETE; + dev->callback = 20LL * ZIP_TIME; + zip_set_callback(dev); break; - - case GPCMD_INQUIRY: - zip_set_phase(id, SCSI_PHASE_DATA_IN); - - max_len = cdb[3]; - max_len <<= 8; - max_len |= cdb[4]; + } - zip_buf_alloc(id, 65536); + max_len = dev->sector_len; + dev->requested_blocks = max_len; /* If we're writing all blocks in one go for DMA, why not also for PIO, it should NOT + matter anyway, this step should be identical and only the way the read dat is + transferred to the host should be different. */ - if (cdb[1] & 1) { - preamble_len = 4; - size_idx = 3; - - zipbufferb[idx++] = 05; - zipbufferb[idx++] = cdb[2]; - zipbufferb[idx++] = 0; + dev->packet_len = max_len * alloc_length; + zip_buf_alloc(dev, dev->packet_len); - idx++; + dev->requested_blocks = max_len; + dev->packet_len = max_len << 9; - switch (cdb[2]) { - case 0x00: - zipbufferb[idx++] = 0x00; - zipbufferb[idx++] = 0x83; - break; - case 0x83: - if (idx + 24 > max_len) { - zip_data_phase_error(id); - zip_buf_free(id); - return; - } + zip_set_buf_len(dev, BufLen, &dev->packet_len); - zipbufferb[idx++] = 0x02; - zipbufferb[idx++] = 0x00; - zipbufferb[idx++] = 0x00; - zipbufferb[idx++] = 20; - ide_padstr8(zipbufferb + idx, 20, "53R141"); /* Serial */ - idx += 20; + zip_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1); - if (idx + 72 > cdb[4]) - goto atapi_out; - zipbufferb[idx++] = 0x02; - zipbufferb[idx++] = 0x01; - zipbufferb[idx++] = 0x00; - zipbufferb[idx++] = 68; - ide_padstr8(zipbufferb + idx, 8, "IOMEGA "); /* Vendor */ - idx += 8; - if (zip_drives[id].is_250) - ide_padstr8(zipbufferb + idx, 40, "ZIP 250 "); /* Product */ - else - ide_padstr8(zipbufferb + idx, 40, "ZIP 100 "); /* Product */ - idx += 40; - ide_padstr8(zipbufferb + idx, 20, "53R141"); /* Product */ - idx += 20; - break; - default: - zip_log("INQUIRY: Invalid page: %02X\n", cdb[2]); - zip_invalid_field(id); - zip_buf_free(id); + dev->all_blocks_total = dev->block_total; + if (dev->packet_status != ZIP_PHASE_COMPLETE) + ui_sb_update_icon(SB_ZIP | dev->id, 1); + else + ui_sb_update_icon(SB_ZIP | dev->id, 0); + return; + + case GPCMD_WRITE_SAME_10: + zip_set_phase(dev, SCSI_PHASE_DATA_OUT); + alloc_length = 512; + + if ((cdb[1] & 6) == 6) { + zip_invalid_field(dev); + return; + } + + if ((dev->drv->bus_type == ZIP_BUS_SCSI) && dev->drv->read_only) { + zip_write_protected(dev); + return; + } + + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + + if (dev->drv->is_250) { + if ((dev->sector_pos >= dev->drv->medium_size) || + ((dev->sector_pos + dev->sector_len - 1) >= dev->drv->medium_size)) { + zip_lba_out_of_range(dev); + return; + } + } else { + if ((dev->sector_pos >= ZIP_SECTORS) || + ((dev->sector_pos + dev->sector_len - 1) >= ZIP_SECTORS)) { + zip_lba_out_of_range(dev); + return; + } + } + + if (!dev->sector_len) { + zip_set_phase(dev, SCSI_PHASE_STATUS); + /* zip_log("ZIP %i: All done - callback set\n", dev->id); */ + dev->packet_status = ZIP_PHASE_COMPLETE; + dev->callback = 20LL * ZIP_TIME; + zip_set_callback(dev); + break; + } + + max_len = dev->sector_len; + dev->requested_blocks = max_len; /* If we're writing all blocks in one go for DMA, why not also for PIO, it should NOT + matter anyway, this step should be identical and only the way the read dat is + transferred to the host should be different. */ + + dev->packet_len = max_len * alloc_length; + zip_buf_alloc(dev, dev->packet_len); + + dev->requested_blocks = max_len; + dev->packet_len = alloc_length; + + zip_set_buf_len(dev, BufLen, &dev->packet_len); + + zip_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1); + + dev->all_blocks_total = dev->block_total; + if (dev->packet_status != ZIP_PHASE_COMPLETE) + ui_sb_update_icon(SB_ZIP | dev->id, 1); + else + ui_sb_update_icon(SB_ZIP | dev->id, 0); + return; + + case GPCMD_MODE_SENSE_6: + case GPCMD_MODE_SENSE_10: + zip_set_phase(dev, SCSI_PHASE_DATA_IN); + + if (dev->drv->bus_type == ZIP_BUS_SCSI) + block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; + else + block_desc = 0; + + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = cdb[4]; + zip_buf_alloc(dev, 256); + } else { + len = (cdb[8] | (cdb[7] << 8)); + zip_buf_alloc(dev, 65536); + } + + dev->current_page_code = cdb[2] & 0x3F; + zip_log("Mode sense page: %02X\n", dev->current_page_code); + + if (!(zip_mode_sense_page_flags & (1LL << dev->current_page_code))) { + zip_invalid_field(dev); + zip_buf_free(dev); + return; + } + + memset(zipbufferb, 0, len); + alloc_length = len; + + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = zip_mode_sense(dev, zipbufferb, 4, cdb[2], block_desc); + len = MIN(len, alloc_length); + zipbufferb[0] = len - 1; + zipbufferb[1] = 0; + if (block_desc) + zipbufferb[3] = 8; + } else { + len = zip_mode_sense(dev, zipbufferb, 8, cdb[2], block_desc); + len = MIN(len, alloc_length); + zipbufferb[0]=(len - 2) >> 8; + zipbufferb[1]=(len - 2) & 255; + zipbufferb[2] = 0; + if (block_desc) { + zipbufferb[6] = 0; + zipbufferb[7] = 8; + } + } + + zip_set_buf_len(dev, BufLen, &len); + + zip_log("ZIP %i: Reading mode page: %02X...\n", dev->id, cdb[2]); + + zip_data_command_finish(dev, len, len, alloc_length, 0); + return; + + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + zip_set_phase(dev, SCSI_PHASE_DATA_OUT); + + if (cdb[0] == GPCMD_MODE_SELECT_6) { + len = cdb[4]; + zip_buf_alloc(dev, 256); + } else { + len = (cdb[7] << 8) | cdb[8]; + zip_buf_alloc(dev, 65536); + } + + zip_set_buf_len(dev, BufLen, &len); + + dev->total_length = len; + dev->do_page_save = cdb[1] & 1; + + dev->current_page_pos = 0; + + zip_data_command_finish(dev, len, len, len, 1); + return; + + case GPCMD_START_STOP_UNIT: + zip_set_phase(dev, SCSI_PHASE_STATUS); + + switch(cdb[4] & 3) { + case 0: /* Stop the disc. */ + zip_eject(dev->id); /* The Iomega Windows 9x drivers require this. */ + break; + case 1: /* Start the disc and read the TOC. */ + break; + case 2: /* Eject the disc if possible. */ + /* zip_eject(dev->id); */ + break; + case 3: /* Load the disc (close tray). */ + zip_reload(dev->id); + break; + } + + zip_command_complete(dev); + break; + + case GPCMD_INQUIRY: + zip_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[3]; + max_len <<= 8; + max_len |= cdb[4]; + + zip_buf_alloc(dev, 65536); + + if (cdb[1] & 1) { + preamble_len = 4; + size_idx = 3; + + zipbufferb[idx++] = 05; + zipbufferb[idx++] = cdb[2]; + zipbufferb[idx++] = 0; + + idx++; + + switch (cdb[2]) { + case 0x00: + zipbufferb[idx++] = 0x00; + zipbufferb[idx++] = 0x83; + break; + case 0x83: + if (idx + 24 > max_len) { + zip_data_phase_error(dev); + zip_buf_free(dev); return; - } - } else { - preamble_len = 5; - size_idx = 4; + } - memset(zipbufferb, 0, 8); - if (cdb[1] & 0xe0) - zipbufferb[0] = 0x60; /*No physical device on this LUN*/ - else - zipbufferb[0] = 0x00; /*Hard disk*/ - zipbufferb[1] = 0x80; /*Removable*/ - if (zip_drives[id].is_250) { - zipbufferb[2] = (zip_drives[id].bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ - zipbufferb[3] = (zip_drives[id].bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x21; - } else { - zipbufferb[2] = (zip_drives[id].bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ - zipbufferb[3] = (zip_drives[id].bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x21; - } - zipbufferb[4] = 31; - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { - zipbufferb[6] = 1; /* 16-bit transfers supported */ - zipbufferb[7] = 0x20; /* Wide bus supported */ - } + zipbufferb[idx++] = 0x02; + zipbufferb[idx++] = 0x00; + zipbufferb[idx++] = 0x00; + zipbufferb[idx++] = 20; + ide_padstr8(zipbufferb + idx, 20, "53R141"); /* Serial */ + idx += 20; - ide_padstr8(zipbufferb + 8, 8, "IOMEGA "); /* Vendor */ - if (zip_drives[id].is_250) { - ide_padstr8(zipbufferb + 16, 16, "ZIP 250 "); /* Product */ - ide_padstr8(zipbufferb + 32, 4, "42.S"); /* Revision */ - if (max_len >= 44) - ide_padstr8(zipbufferb + 36, 8, "08/08/01"); /* Date? */ - if (max_len >= 122) - ide_padstr8(zipbufferb + 96, 26, "(c) Copyright IOMEGA 2000 "); /* Copyright string */ - - } else { - ide_padstr8(zipbufferb + 16, 16, "ZIP 100 "); /* Product */ - ide_padstr8(zipbufferb + 32, 4, "E.08"); /* Revision */ - } - idx = 36; - - if (max_len == 96) { - zipbufferb[4] = 91; - idx = 96; - } else if (max_len == 128) { - zipbufferb[4] = 0x75; - idx = 128; - } + if (idx + 72 > cdb[4]) + goto atapi_out; + zipbufferb[idx++] = 0x02; + zipbufferb[idx++] = 0x01; + zipbufferb[idx++] = 0x00; + zipbufferb[idx++] = 68; + ide_padstr8(zipbufferb + idx, 8, "IOMEGA "); /* Vendor */ + idx += 8; + if (dev->drv->is_250) + ide_padstr8(zipbufferb + idx, 40, "ZIP 250 "); /* Product */ + else + ide_padstr8(zipbufferb + idx, 40, "ZIP 100 "); /* Product */ + idx += 40; + ide_padstr8(zipbufferb + idx, 20, "53R141"); /* Product */ + idx += 20; + break; + default: + zip_log("INQUIRY: Invalid page: %02X\n", cdb[2]); + zip_invalid_field(dev); + zip_buf_free(dev); + return; } + } else { + preamble_len = 5; + size_idx = 4; + + memset(zipbufferb, 0, 8); + if (cdb[1] & 0xe0) + zipbufferb[0] = 0x60; /*No physical device on this LUN*/ + else + zipbufferb[0] = 0x00; /*Hard disk*/ + zipbufferb[1] = 0x80; /*Removable*/ + if (dev->drv->is_250) { + zipbufferb[2] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ + zipbufferb[3] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x21; + } else { + zipbufferb[2] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ + zipbufferb[3] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x21; + } + zipbufferb[4] = 31; + if (dev->drv->bus_type == ZIP_BUS_SCSI) { + zipbufferb[6] = 1; /* 16-bit transfers supported */ + zipbufferb[7] = 0x20; /* Wide bus supported */ + } + + ide_padstr8(zipbufferb + 8, 8, "IOMEGA "); /* Vendor */ + if (dev->drv->is_250) { + ide_padstr8(zipbufferb + 16, 16, "ZIP 250 "); /* Product */ + ide_padstr8(zipbufferb + 32, 4, "42.S"); /* Revision */ + if (max_len >= 44) + ide_padstr8(zipbufferb + 36, 8, "08/08/01"); /* Date? */ + if (max_len >= 122) + ide_padstr8(zipbufferb + 96, 26, "(c) Copyright IOMEGA 2000 "); /* Copyright string */ + } else { + ide_padstr8(zipbufferb + 16, 16, "ZIP 100 "); /* Product */ + ide_padstr8(zipbufferb + 32, 4, "E.08"); /* Revision */ + } + idx = 36; + + if (max_len == 96) { + zipbufferb[4] = 91; + idx = 96; + } else if (max_len == 128) { + zipbufferb[4] = 0x75; + idx = 128; + } + } atapi_out: - zipbufferb[size_idx] = idx - preamble_len; - len=idx; + zipbufferb[size_idx] = idx - preamble_len; + len=idx; - len = MIN(len, max_len); - zip_set_buf_len(id, BufLen, &len); + len = MIN(len, max_len); + zip_set_buf_len(dev, BufLen, &len); - zip_data_command_finish(id, len, len, max_len, 0); - break; + zip_data_command_finish(dev, len, len, max_len, 0); + break; - case GPCMD_PREVENT_REMOVAL: - zip_set_phase(id, SCSI_PHASE_STATUS); - zip_command_complete(id); - break; + case GPCMD_PREVENT_REMOVAL: + zip_set_phase(dev, SCSI_PHASE_STATUS); + zip_command_complete(dev); + break; - case GPCMD_SEEK_6: - case GPCMD_SEEK_10: - zip_set_phase(id, SCSI_PHASE_STATUS); - - switch(cdb[0]) { - case GPCMD_SEEK_6: - pos = (cdb[2] << 8) | cdb[3]; - break; - case GPCMD_SEEK_10: - pos = (cdb[2] << 24) | (cdb[3]<<16) | (cdb[4]<<8) | cdb[5]; - break; - } - zip_seek(id, pos); - zip_command_complete(id); - break; + case GPCMD_SEEK_6: + case GPCMD_SEEK_10: + zip_set_phase(dev, SCSI_PHASE_STATUS); - case GPCMD_READ_CDROM_CAPACITY: - zip_set_phase(id, SCSI_PHASE_DATA_IN); + switch(cdb[0]) { + case GPCMD_SEEK_6: + pos = (cdb[2] << 8) | cdb[3]; + break; + case GPCMD_SEEK_10: + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + break; + } + zip_seek(dev, pos); + zip_command_complete(dev); + break; - zip_buf_alloc(id, 8); + case GPCMD_READ_CDROM_CAPACITY: + zip_set_phase(dev, SCSI_PHASE_DATA_IN); - if (zip_read_capacity(id, zip[id].current_cdb, zipbufferb, &len) == 0) { - zip_buf_free(id); - return; - } + zip_buf_alloc(dev, 8); - zip_set_buf_len(id, BufLen, &len); + if (zip_read_capacity(dev, dev->current_cdb, zipbufferb, &len) == 0) { + zip_buf_free(dev); + return; + } - zip_data_command_finish(id, len, len, len, 0); - break; + zip_set_buf_len(dev, BufLen, &len); - case GPCMD_IOMEGA_EJECT: - zip_set_phase(id, SCSI_PHASE_STATUS); - zip_eject(id); - zip_command_complete(id); - break; + zip_data_command_finish(dev, len, len, len, 0); + break; - case GPCMD_READ_FORMAT_CAPACITIES: - len = (cdb[7] << 8) | cdb[8]; + case GPCMD_IOMEGA_EJECT: + zip_set_phase(dev, SCSI_PHASE_STATUS); + zip_eject(dev->id); + zip_command_complete(dev); + break; - zip_buf_alloc(id, len); - memset(zipbufferb, 0, len); + case GPCMD_READ_FORMAT_CAPACITIES: + len = (cdb[7] << 8) | cdb[8]; - pos = 0; + zip_buf_alloc(dev, len); + memset(zipbufferb, 0, len); - /* List header */ - zipbufferb[pos++] = 0; - zipbufferb[pos++] = 0; - zipbufferb[pos++] = 0; - if (zip_drives[id].f != NULL) - zipbufferb[pos++] = 16; - else - zipbufferb[pos++] = 8; + pos = 0; - /* Current/Maximum capacity header */ - if (zip_drives[id].is_250) { - if (zip_drives[id].f != NULL) { - zipbufferb[pos++] = (zip_drives[id].medium_size >> 24) & 0xff; - zipbufferb[pos++] = (zip_drives[id].medium_size >> 16) & 0xff; - zipbufferb[pos++] = (zip_drives[id].medium_size >> 8) & 0xff; - zipbufferb[pos++] = zip_drives[id].medium_size & 0xff; - zipbufferb[pos++] = 2; /* Current medium capacity */ - } else { - zipbufferb[pos++] = (ZIP_250_SECTORS >> 24) & 0xff; - zipbufferb[pos++] = (ZIP_250_SECTORS >> 16) & 0xff; - zipbufferb[pos++] = (ZIP_250_SECTORS >> 8) & 0xff; - zipbufferb[pos++] = ZIP_250_SECTORS & 0xff; - zipbufferb[pos++] = 3; /* Maximum medium capacity */ - } + /* List header */ + zipbufferb[pos++] = 0; + zipbufferb[pos++] = 0; + zipbufferb[pos++] = 0; + if (dev->drv->f != NULL) + zipbufferb[pos++] = 16; + else + zipbufferb[pos++] = 8; + + /* Current/Maximum capacity header */ + if (dev->drv->is_250) { + if (dev->drv->f != NULL) { + zipbufferb[pos++] = (dev->drv->medium_size >> 24) & 0xff; + zipbufferb[pos++] = (dev->drv->medium_size >> 16) & 0xff; + zipbufferb[pos++] = (dev->drv->medium_size >> 8) & 0xff; + zipbufferb[pos++] = dev->drv->medium_size & 0xff; + zipbufferb[pos++] = 2; /* Current medium capacity */ } else { - zipbufferb[pos++] = (ZIP_SECTORS >> 24) & 0xff; - zipbufferb[pos++] = (ZIP_SECTORS >> 16) & 0xff; - zipbufferb[pos++] = (ZIP_SECTORS >> 8) & 0xff; - zipbufferb[pos++] = ZIP_SECTORS & 0xff; - if (zip_drives[id].f != NULL) - zipbufferb[pos++] = 2; - else - zipbufferb[pos++] = 3; + zipbufferb[pos++] = (ZIP_250_SECTORS >> 24) & 0xff; + zipbufferb[pos++] = (ZIP_250_SECTORS >> 16) & 0xff; + zipbufferb[pos++] = (ZIP_250_SECTORS >> 8) & 0xff; + zipbufferb[pos++] = ZIP_250_SECTORS & 0xff; + zipbufferb[pos++] = 3; /* Maximum medium capacity */ } + } else { + zipbufferb[pos++] = (ZIP_SECTORS >> 24) & 0xff; + zipbufferb[pos++] = (ZIP_SECTORS >> 16) & 0xff; + zipbufferb[pos++] = (ZIP_SECTORS >> 8) & 0xff; + zipbufferb[pos++] = ZIP_SECTORS & 0xff; + if (dev->drv->f != NULL) + zipbufferb[pos++] = 2; + else + zipbufferb[pos++] = 3; + } + zipbufferb[pos++] = 512 >> 16; + zipbufferb[pos++] = 512 >> 8; + zipbufferb[pos++] = 512 & 0xff; + + if (dev->drv->f != NULL) { + /* Formattable capacity descriptor */ + zipbufferb[pos++] = (dev->drv->medium_size >> 24) & 0xff; + zipbufferb[pos++] = (dev->drv->medium_size >> 16) & 0xff; + zipbufferb[pos++] = (dev->drv->medium_size >> 8) & 0xff; + zipbufferb[pos++] = dev->drv->medium_size & 0xff; + zipbufferb[pos++] = 0; zipbufferb[pos++] = 512 >> 16; zipbufferb[pos++] = 512 >> 8; zipbufferb[pos++] = 512 & 0xff; + } - if (zip_drives[id].f != NULL) { - /* Formattable capacity descriptor */ - zipbufferb[pos++] = (zip_drives[id].medium_size >> 24) & 0xff; - zipbufferb[pos++] = (zip_drives[id].medium_size >> 16) & 0xff; - zipbufferb[pos++] = (zip_drives[id].medium_size >> 8) & 0xff; - zipbufferb[pos++] = zip_drives[id].medium_size & 0xff; - zipbufferb[pos++] = 0; - zipbufferb[pos++] = 512 >> 16; - zipbufferb[pos++] = 512 >> 8; - zipbufferb[pos++] = 512 & 0xff; - } + zip_set_buf_len(dev, BufLen, &len); - zip_set_buf_len(id, BufLen, &len); + zip_data_command_finish(dev, len, len, len, 0); + break; - zip_data_command_finish(id, len, len, len, 0); - break; + default: + zip_illegal_opcode(dev); + break; + } - default: - zip_illegal_opcode(id); - break; - } + /* zip_log("ZIP %i: Phase: %02X, request length: %i\n", dev->id, dev->phase, dev->request_length); */ - /* zip_log("ZIP %i: Phase: %02X, request length: %i\n", zip[id].phase, zip[id].request_length); */ - - if (zip_atapi_phase_to_scsi(id) == SCSI_PHASE_STATUS) - zip_buf_free(id); + if (zip_atapi_phase_to_scsi(dev) == SCSI_PHASE_STATUS) + zip_buf_free(dev); } + /* The command second phase function, needed for Mode Select. */ -uint8_t zip_phase_data_out(uint8_t id) +static uint8_t +zip_phase_data_out(zip_t *dev) { - uint16_t block_desc_len; - uint16_t pos; + uint16_t block_desc_len; + uint16_t pos; - uint8_t error = 0; - uint8_t page, page_len; + uint8_t error = 0; + uint8_t page, page_len; - uint16_t i = 0; + uint16_t i = 0; - uint8_t hdr_len, val, old_val, ch; + uint8_t hdr_len, val, old_val, ch; - uint32_t last_to_write = 0, len = 0; - uint32_t c, h, s; + uint32_t last_to_write = 0, len = 0; + uint32_t c, h, s; - switch(zip[id].current_cdb[0]) { - case GPCMD_VERIFY_6: - case GPCMD_VERIFY_10: - case GPCMD_VERIFY_12: - break; - case GPCMD_WRITE_6: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - if (zip[id].requested_blocks > 0) - zip_blocks(id, &len, 1, 1); - break; - case GPCMD_WRITE_SAME_10: - if (!zip[id].current_cdb[7] && !zip[id].current_cdb[8]) { - if (zip_drives[id].is_250) - last_to_write = (zip_drives[id].medium_size - 1); - else - last_to_write = (ZIP_SECTORS - 1); - } else - last_to_write = zip[id].sector_pos + zip[id].sector_len - 1; - - for (i = zip[id].sector_pos; i <= last_to_write; i++) { - if (zip[id].current_cdb[1] & 2) { - zipbufferb[0] = (i >> 24) & 0xff; - zipbufferb[1] = (i >> 16) & 0xff; - zipbufferb[2] = (i >> 8) & 0xff; - zipbufferb[3] = i & 0xff; - } else if (zip[id].current_cdb[1] & 4) { - /* CHS are 96,1,2048 (ZIP 100) and 239,1,2048 (ZIP 250) */ - s = (i % 2048); - h = ((i - s) / 2048) % 1; - c = ((i - s) / 2048) / 1; - zipbufferb[0] = (c >> 16) & 0xff; - zipbufferb[1] = (c >> 8) & 0xff; - zipbufferb[2] = c & 0xff; - zipbufferb[3] = h & 0xff; - zipbufferb[4] = (s >> 24) & 0xff; - zipbufferb[5] = (s >> 16) & 0xff; - zipbufferb[6] = (s >> 8) & 0xff; - zipbufferb[7] = s & 0xff; - } - fseek(zip_drives[id].f, zip_drives[id].base + (i << 9), SEEK_SET); - fwrite(zipbufferb, 1, 512, zip_drives[id].f); - } - break; - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - if (zip[id].current_cdb[0] == GPCMD_MODE_SELECT_10) - hdr_len = 8; + switch(dev->current_cdb[0]) { + case GPCMD_VERIFY_6: + case GPCMD_VERIFY_10: + case GPCMD_VERIFY_12: + break; + case GPCMD_WRITE_6: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + if (dev->requested_blocks > 0) + zip_blocks(dev, &len, 1, 1); + break; + case GPCMD_WRITE_SAME_10: + if (!dev->current_cdb[7] && !dev->current_cdb[8]) { + if (dev->drv->is_250) + last_to_write = (dev->drv->medium_size - 1); else - hdr_len = 4; + last_to_write = (ZIP_SECTORS - 1); + } else + last_to_write = dev->sector_pos + dev->sector_len - 1; - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { - if (zip[id].current_cdb[0] == GPCMD_MODE_SELECT_6) { - block_desc_len = zipbufferb[2]; - block_desc_len <<= 8; - block_desc_len |= zipbufferb[3]; - } else { - block_desc_len = zipbufferb[6]; - block_desc_len <<= 8; - block_desc_len |= zipbufferb[7]; - } - } else - block_desc_len = 0; + for (i = dev->sector_pos; i <= last_to_write; i++) { + if (dev->current_cdb[1] & 2) { + zipbufferb[0] = (i >> 24) & 0xff; + zipbufferb[1] = (i >> 16) & 0xff; + zipbufferb[2] = (i >> 8) & 0xff; + zipbufferb[3] = i & 0xff; + } else if (dev->current_cdb[1] & 4) { + /* CHS are 96,1,2048 (ZIP 100) and 239,1,2048 (ZIP 250) */ + s = (i % 2048); + h = ((i - s) / 2048) % 1; + c = ((i - s) / 2048) / 1; + zipbufferb[0] = (c >> 16) & 0xff; + zipbufferb[1] = (c >> 8) & 0xff; + zipbufferb[2] = c & 0xff; + zipbufferb[3] = h & 0xff; + zipbufferb[4] = (s >> 24) & 0xff; + zipbufferb[5] = (s >> 16) & 0xff; + zipbufferb[6] = (s >> 8) & 0xff; + zipbufferb[7] = s & 0xff; + } + fseek(dev->drv->f, dev->drv->base + (i << 9), SEEK_SET); + fwrite(zipbufferb, 1, 512, dev->drv->f); + } + break; + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) + hdr_len = 8; + else + hdr_len = 4; - pos = hdr_len + block_desc_len; + if (dev->drv->bus_type == ZIP_BUS_SCSI) { + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { + block_desc_len = zipbufferb[2]; + block_desc_len <<= 8; + block_desc_len |= zipbufferb[3]; + } else { + block_desc_len = zipbufferb[6]; + block_desc_len <<= 8; + block_desc_len |= zipbufferb[7]; + } + } else + block_desc_len = 0; - while(1) { - page = zipbufferb[pos] & 0x3F; - page_len = zipbufferb[pos + 1]; + pos = hdr_len + block_desc_len; - pos += 2; + while(1) { + page = zipbufferb[pos] & 0x3F; + page_len = zipbufferb[pos + 1]; - if (!(zip_mode_sense_page_flags & (1LL << ((uint64_t) page)))) - error |= 1; - else { - for (i = 0; i < page_len; i++) { - ch = zip_mode_sense_pages_changeable.pages[page][i + 2]; - val = zipbufferb[pos + i]; - old_val = zip_mode_sense_pages_saved[id].pages[page][i + 2]; - if (val != old_val) { - if (ch) - zip_mode_sense_pages_saved[id].pages[page][i + 2] = val; - else - error |= 1; - } + pos += 2; + + if (!(zip_mode_sense_page_flags & (1LL << ((uint64_t) page)))) + error |= 1; + else { + for (i = 0; i < page_len; i++) { + ch = zip_mode_sense_pages_changeable.pages[page][i + 2]; + val = zipbufferb[pos + i]; + old_val = dev->ms_pages_saved.pages[page][i + 2]; + if (val != old_val) { + if (ch) + dev->ms_pages_saved.pages[page][i + 2] = val; + else + error |= 1; } } - - pos += page_len; - - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) - val = zip_mode_sense_pages_default_scsi.pages[page][0] & 0x80; - else - val = zip_mode_sense_pages_default.pages[page][0] & 0x80; - if (zip[id].do_page_save && val) - zip_mode_sense_save(id); - - if (pos >= zip[id].total_length) - break; } - if (error) { - zip_invalid_field_pl(id); - return 0; - } - break; - } + pos += page_len; - return 1; + if (dev->drv->bus_type == ZIP_BUS_SCSI) + val = zip_mode_sense_pages_default_scsi.pages[page][0] & 0x80; + else + val = zip_mode_sense_pages_default.pages[page][0] & 0x80; + if (dev->do_page_save && val) + zip_mode_sense_save(dev); + + if (pos >= dev->total_length) + break; + } + + if (error) { + zip_invalid_field_pl(dev); + return 0; + } + break; + } + + return 1; } + /* This is the general ATAPI PIO request function. */ -void zip_pio_request(uint8_t id, uint8_t out) +static void +zip_pio_request(zip_t *dev, uint8_t out) { - int old_pos = 0; - int ret = 0; + int ret = 0; - if (zip_drives[id].bus_type < ZIP_BUS_SCSI) { - zip_log("ZIP %i: Lowering IDE IRQ\n", id); - ide_irq_lower(&(ide_drives[zip_drives[id].ide_channel])); - } - - zip[id].status = BUSY_STAT; + if (dev->drv->bus_type < ZIP_BUS_SCSI) { + zip_log("ZIP %i: Lowering IDE IRQ\n", dev->id); + ide_irq_lower(ide_drives[dev->drv->ide_channel]); + } - if (zip[id].pos >= zip[id].packet_len) { - zip_log("ZIP %i: %i bytes %s, command done\n", id, zip[id].pos, out ? "written" : "read"); + dev->status = BUSY_STAT; - zip[id].pos = zip[id].request_pos = 0; - if (out) { - ret = zip_phase_data_out(id); - /* If ret = 0 (phase 1 error), then we do not do anything else other than - free the buffer, as the phase and callback have already been set by the - error function. */ - if (ret) - zip_command_complete(id); - } else - zip_command_complete(id); - ui_sb_update_icon(SB_ZIP | id, 0); - zip_buf_free(id); - } else { - zip_log("ZIP %i: %i bytes %s, %i bytes are still left\n", id, zip[id].pos, out ? "written" : "read", zip[id].packet_len - zip[id].pos); + if (dev->pos >= dev->packet_len) { + zip_log("ZIP %i: %i bytes %s, command done\n", dev->id, dev->pos, out ? "written" : "read"); - /* Make sure to keep pos, and reset request_pos to 0. */ - /* Also make sure to not reset total_read. */ - - /* If less than (packet length) bytes are remaining, update packet length - accordingly. */ - if ((zip[id].packet_len - zip[id].pos) < (zip[id].max_transfer_len)) - zip[id].max_transfer_len = zip[id].packet_len - zip[id].pos; - - old_pos = zip[id].pos; - zip[id].packet_status = out ? ZIP_PHASE_DATA_OUT : ZIP_PHASE_DATA_IN; - zip_command_common(id); - zip[id].pos = old_pos; - zip[id].request_pos = 0; - } -} - -void zip_phase_callback(uint8_t id); - -int zip_read_from_ide_dma(uint8_t channel) -{ - uint8_t id = atapi_zip_drives[channel]; - - if (id > ZIP_NUM) - return 0; - - if (ide_bus_master_write) { - if (ide_bus_master_write(channel >> 1, zipbufferb, zip[id].packet_len)) - return 0; - else - return 1; - } else - return 0; -} - -int zip_read_from_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) -{ - uint8_t id = scsi_zip_drives[scsi_id][scsi_lun]; - int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; - - if (id > ZIP_NUM) - return 0; - - zip_log("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); - memcpy(zipbufferb, SCSIDevices[scsi_id][scsi_lun].CmdBuffer, *BufLen); - return 1; -} - -void zip_irq_raise(uint8_t id) -{ - if (zip_drives[id].bus_type < ZIP_BUS_SCSI) - ide_irq_raise(&(ide_drives[zip_drives[id].ide_channel])); -} - -int zip_read_from_dma(uint8_t id) -{ - int32_t *BufLen = &SCSIDevices[zip_drives[id].scsi_device_id][zip_drives[id].scsi_device_lun].BufferLength; - - int ret = 0; - - int in_data_length = 0; - - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) - ret = zip_read_from_scsi_dma(zip_drives[id].scsi_device_id, zip_drives[id].scsi_device_lun); - else - ret = zip_read_from_ide_dma(zip_drives[id].ide_channel); - - if (!ret) - return 0; - - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { - in_data_length = *BufLen; - zip_log("ZIP %i: SCSI Input data length: %i\n", id, in_data_length); - } else { - in_data_length = zip[id].max_transfer_len; - zip_log("ZIP %i: ATAPI Input data length: %i\n", id, in_data_length); - } - - ret = zip_phase_data_out(id); - - if (ret || (zip_drives[id].bus_type == ZIP_BUS_SCSI)) { - zip_buf_free(id); - zip[id].packet_status = ZIP_PHASE_COMPLETE; - zip[id].status = READY_STAT; - zip[id].phase = 3; - ui_sb_update_icon(SB_ZIP | id, 0); - zip_irq_raise(id); + dev->pos = dev->request_pos = 0; + if (out) { + ret = zip_phase_data_out(dev); + /* If ret = 0 (phase 1 error), then we do not do anything else other than + free the buffer, as the phase and callback have already been set by the + error function. */ if (ret) - return 1; - else - return 0; + zip_command_complete(dev); } else - return 0; + zip_command_complete(dev); + zip_buf_free(dev); + } else { + zip_log("ZIP %i: %i bytes %s, %i bytes are still left\n", dev->id, dev->pos, + out ? "written" : "read", dev->packet_len - dev->pos); + + /* If less than (packet length) bytes are remaining, update packet length + accordingly. */ + if ((dev->packet_len - dev->pos) < (dev->max_transfer_len)) + dev->max_transfer_len = dev->packet_len - dev->pos; + zip_log("ZIP %i: Packet length %i, request length %i\n", dev->id, dev->packet_len, + dev->max_transfer_len); + + dev->packet_status = out ? ZIP_PHASE_DATA_OUT : ZIP_PHASE_DATA_IN; + + dev->status = BUSY_STAT; + dev->phase = 1; + zip_phase_callback(dev); + dev->callback = 0LL; + zip_set_callback(dev); + + dev->request_pos = 0; + } } -int zip_write_to_ide_dma(uint8_t channel) + +static int +zip_read_from_ide_dma(uint8_t channel) { - uint8_t id = atapi_zip_drives[channel]; + zip_t *dev; - if (id > ZIP_NUM) { - zip_log("ZIP %i: Drive not found\n", id); + uint8_t id = atapi_zip_drives[channel]; + int ret; + + if (id > ZIP_NUM) + return 0; + + dev = zip[id]; + + if (ide_bus_master_write) { + ret = ide_bus_master_write(channel >> 1, + zipbufferb, dev->packet_len, + ide_bus_master_priv[channel >> 1]); + if (ret == 2) /* DMA not enabled, wait for it to be enabled. */ + return 2; + else if (ret == 1) { /* DMA error. */ + zip_bus_master_error(dev); return 0; - } - - if (ide_bus_master_read) { - if (ide_bus_master_read(channel >> 1, zipbufferb, zip[id].packet_len)) - return 0; - else - return 1; } else - return 0; + return 1; + } else + return 0; } -int zip_write_to_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) + +static int +zip_read_from_scsi_dma(uint8_t scsi_id) { - uint8_t id = scsi_zip_drives[scsi_id][scsi_lun]; - int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; + zip_t *dev; - if (id > ZIP_NUM) - return 0; + uint8_t id = scsi_zip_drives[scsi_id]; + int32_t *BufLen = &SCSIDevices[scsi_id].BufferLength; - zip_log("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); - memcpy(SCSIDevices[scsi_id][scsi_lun].CmdBuffer, zipbufferb, *BufLen); - zip_log("ZIP %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, zipbufferb[0], zipbufferb[1], zipbufferb[2], zipbufferb[3], zipbufferb[4], zipbufferb[5], zipbufferb[6], zipbufferb[7]); - zip_log("ZIP %i: Data from SCSI DMA : %02X %02X %02X %02X %02X %02X %02X %02X\n", id, SCSIDevices[scsi_id][scsi_lun].CmdBuffer[0], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[1], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[2], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[3], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[4], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[5], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[6], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[7]); + if (id > ZIP_NUM) + return 0; + + dev = zip[id]; + + zip_log("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); + memcpy(zipbufferb, SCSIDevices[scsi_id].CmdBuffer, *BufLen); + return 1; +} + + +static void +zip_irq_raise(zip_t *dev) +{ + if (dev->drv->bus_type < ZIP_BUS_SCSI) + ide_irq_raise(ide_drives[dev->drv->ide_channel]); +} + + +static int +zip_read_from_dma(zip_t *dev) +{ + int32_t *BufLen = &SCSIDevices[dev->drv->scsi_device_id].BufferLength; + int ret = 0; + + if (dev->drv->bus_type == ZIP_BUS_SCSI) + ret = zip_read_from_scsi_dma(dev->drv->scsi_device_id); + else + ret = zip_read_from_ide_dma(dev->drv->ide_channel); + + if (ret != 1) + return ret; + + if (dev->drv->bus_type == ZIP_BUS_SCSI) + zip_log("ZIP %i: SCSI Input data length: %i\n", dev->id, *BufLen); + else + zip_log("ZIP %i: ATAPI Input data length: %i\n", dev->id, dev->packet_len); + + ret = zip_phase_data_out(dev); + + if (ret) return 1; + else + return 0; } -int zip_write_to_dma(uint8_t id) -{ - int ret = 0; - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { - zip_log("Write to SCSI DMA: (%02X:%02X)\n", zip_drives[id].scsi_device_id, zip_drives[id].scsi_device_lun); - ret = zip_write_to_scsi_dma(zip_drives[id].scsi_device_id, zip_drives[id].scsi_device_lun); +static int +zip_write_to_ide_dma(uint8_t channel) +{ + zip_t *dev; + + uint8_t id = atapi_zip_drives[channel]; + int ret; + + if (id > ZIP_NUM) { + zip_log("ZIP %i: Drive not found\n", id); + return 0; + } + + dev = zip[id]; + + if (ide_bus_master_read) { + ret = ide_bus_master_read(channel >> 1, + zipbufferb, dev->packet_len, + ide_bus_master_priv[channel >> 1]); + if (ret == 2) /* DMA not enabled, wait for it to be enabled. */ + return 2; + else if (ret == 1) { /* DMA error. */ + zip_bus_master_error(dev); + return 0; } else - ret = zip_write_to_ide_dma(zip_drives[id].ide_channel); - - if (ret || (zip_drives[id].bus_type == ZIP_BUS_SCSI)) { - zip_buf_free(id); - zip[id].packet_status = ZIP_PHASE_COMPLETE; - zip[id].status = READY_STAT; - zip[id].phase = 3; - ui_sb_update_icon(SB_ZIP | id, 0); - zip_irq_raise(id); - if (ret) - return 1; - else - return 0; - } else - return 0; + return 1; + } else + return 0; } -/* If the result is 1, issue an IRQ, otherwise not. */ -void zip_phase_callback(uint8_t id) + +static int +zip_write_to_scsi_dma(uint8_t scsi_id) { - switch(zip[id].packet_status) { - case ZIP_PHASE_IDLE: - zip_log("ZIP %i: ZIP_PHASE_IDLE\n", id); - zip[id].pos=0; - zip[id].phase = 1; - zip[id].status = READY_STAT | DRQ_STAT | (zip[id].status & ERR_STAT); - return; - case ZIP_PHASE_COMMAND: - zip_log("ZIP %i: ZIP_PHASE_COMMAND\n", id); - zip[id].status = BUSY_STAT | (zip[id].status &ERR_STAT); - memcpy(zip[id].atapi_cdb, zipbufferb, zip[id].cdb_len); - zip_command(id, zip[id].atapi_cdb); - return; - case ZIP_PHASE_COMPLETE: - zip_log("ZIP %i: ZIP_PHASE_COMPLETE\n", id); - zip[id].status = READY_STAT; - zip[id].phase = 3; - zip[id].packet_status = 0xFF; - ui_sb_update_icon(SB_ZIP | id, 0); - zip_irq_raise(id); - return; - case ZIP_PHASE_DATA_OUT: - zip_log("ZIP %i: ZIP_PHASE_DATA_OUT\n", id); - zip[id].status = READY_STAT | DRQ_STAT | (zip[id].status & ERR_STAT); - zip[id].phase = 0; - zip_irq_raise(id); - return; - case ZIP_PHASE_DATA_OUT_DMA: - zip_log("ZIP %i: ZIP_PHASE_DATA_OUT_DMA\n", id); - zip_read_from_dma(id); - return; - case ZIP_PHASE_DATA_IN: - zip_log("ZIP %i: ZIP_PHASE_DATA_IN\n", id); - zip[id].status = READY_STAT | DRQ_STAT | (zip[id].status & ERR_STAT); - zip[id].phase = 2; - zip_irq_raise(id); - return; - case ZIP_PHASE_DATA_IN_DMA: - zip_log("ZIP %i: ZIP_PHASE_DATA_IN_DMA\n", id); - zip_write_to_dma(id); - return; - case ZIP_PHASE_ERROR: - zip_log("ZIP %i: ZIP_PHASE_ERROR\n", id); - zip[id].status = READY_STAT | ERR_STAT; - zip[id].phase = 3; - zip[id].packet_status = 0xFF; - zip_irq_raise(id); - ui_sb_update_icon(SB_ZIP | id, 0); - return; + zip_t *dev; + + uint8_t id = scsi_zip_drives[scsi_id]; + int32_t *BufLen = &SCSIDevices[scsi_id].BufferLength; + + if (id > ZIP_NUM) + return 0; + + dev = zip[id]; + + zip_log("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); + memcpy(SCSIDevices[scsi_id].CmdBuffer, zipbufferb, *BufLen); + zip_log("ZIP %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, + zipbufferb[0], zipbufferb[1], zipbufferb[2], zipbufferb[3], zipbufferb[4], zipbufferb[5], + zipbufferb[6], zipbufferb[7]); + zip_log("ZIP %i: Data from SCSI DMA : %02X %02X %02X %02X %02X %02X %02X %02X\n", id, + SCSIDevices[scsi_id].CmdBuffer[0], SCSIDevices[scsi_id].CmdBuffer[1], + SCSIDevices[scsi_id].CmdBuffer[2], SCSIDevices[scsi_id].CmdBuffer[3], + SCSIDevices[scsi_id].CmdBuffer[4], SCSIDevices[scsi_id].CmdBuffer[5], + SCSIDevices[scsi_id].CmdBuffer[6], SCSIDevices[scsi_id].CmdBuffer[7]); + return 1; +} + + +static int +zip_write_to_dma(zip_t *dev) +{ + int32_t *BufLen = &SCSIDevices[dev->drv->scsi_device_id].BufferLength; + int ret = 0; + + if (dev->drv->bus_type == ZIP_BUS_SCSI) { + zip_log("Write to SCSI DMA: (ID %02X)\n", dev->drv->scsi_device_id); + ret = zip_write_to_scsi_dma(dev->drv->scsi_device_id); + } else + ret = zip_write_to_ide_dma(dev->drv->ide_channel); + + if (dev->drv->bus_type == ZIP_BUS_SCSI) + zip_log("ZIP %i: SCSI Output data length: %i\n", dev->id, *BufLen); + else + zip_log("ZIP %i: ATAPI Output data length: %i\n", dev->id, dev->packet_len); + + return ret; +} + + +void +zip_phase_callback(zip_t *dev) +{ + int ret; + + switch(dev->packet_status) { + case ZIP_PHASE_IDLE: + zip_log("ZIP %i: ZIP_PHASE_IDLE\n", dev->id); + dev->pos = 0; + dev->phase = 1; + dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); + return; + case ZIP_PHASE_COMMAND: + zip_log("ZIP %i: ZIP_PHASE_COMMAND\n", dev->id); + dev->status = BUSY_STAT | (dev->status & ERR_STAT); + memcpy(dev->atapi_cdb, zipbufferb, 12); + zip_command(dev, dev->atapi_cdb); + return; + case ZIP_PHASE_COMPLETE: + zip_log("ZIP %i: ZIP_PHASE_COMPLETE\n", dev->id); + dev->status = READY_STAT; + dev->phase = 3; + dev->packet_status = 0xFF; + ui_sb_update_icon(SB_ZIP | dev->id, 0); + zip_irq_raise(dev); + return; + case ZIP_PHASE_DATA_OUT: + zip_log("ZIP %i: ZIP_PHASE_DATA_OUT\n", dev->id); + dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); + dev->phase = 0; + zip_irq_raise(dev); + return; + case ZIP_PHASE_DATA_OUT_DMA: + zip_log("ZIP %i: ZIP_PHASE_DATA_OUT_DMA\n", dev->id); + ret = zip_read_from_dma(dev); + + if ((ret == 1) || (dev->drv->bus_type == ZIP_BUS_SCSI)) { + zip_log("ZIP %i: DMA data out phase done\n"); + zip_buf_free(dev); + zip_command_complete(dev); + } else if (ret == 2) { + zip_log("ZIP %i: DMA out not enabled, wait\n"); + zip_command_bus(dev); + } else { + zip_log("ZIP %i: DMA data out phase failure\n"); + zip_buf_free(dev); + } + return; + case ZIP_PHASE_DATA_IN: + zip_log("ZIP %i: ZIP_PHASE_DATA_IN\n", dev->id); + dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); + dev->phase = 2; + zip_irq_raise(dev); + return; + case ZIP_PHASE_DATA_IN_DMA: + zip_log("ZIP %i: ZIP_PHASE_DATA_IN_DMA\n", dev->id); + ret = zip_write_to_dma(dev); + + if ((ret == 1) || (dev->drv->bus_type == ZIP_BUS_SCSI)) { + zip_log("ZIP %i: DMA data in phase done\n", dev->id); + zip_buf_free(dev); + zip_command_complete(dev); + } else if (ret == 2) { + zip_log("ZIP %i: DMA in not enabled, wait\n", dev->id); + zip_command_bus(dev); + } else { + zip_log("ZIP %i: DMA data in phase failure\n", dev->id); + zip_buf_free(dev); + } + return; + case ZIP_PHASE_ERROR: + zip_log("ZIP %i: ZIP_PHASE_ERROR\n", dev->id); + dev->status = READY_STAT | ERR_STAT; + dev->phase = 3; + dev->packet_status = 0xFF; + zip_irq_raise(dev); + ui_sb_update_icon(SB_ZIP | dev->id, 0); + return; + } +} + + +uint32_t +zip_read(uint8_t channel, int length) +{ + zip_t *dev; + + uint16_t *zipbufferw; + uint32_t *zipbufferl; + + uint8_t id = atapi_zip_drives[channel]; + + uint32_t temp = 0; + + if (id > ZIP_NUM) + return 0; + + dev = zip[id]; + + zipbufferw = (uint16_t *) zipbufferb; + zipbufferl = (uint32_t *) zipbufferb; + + if (!zipbufferb) + return 0; + + /* Make sure we return a 0 and don't attempt to read from the buffer if we're transferring bytes beyond it, + which can happen when issuing media access commands with an allocated length below minimum request length + (which is 1 sector = 512 bytes). */ + switch(length) { + case 1: + temp = (dev->pos < dev->packet_len) ? zipbufferb[dev->pos] : 0; + dev->pos++; + dev->request_pos++; + break; + case 2: + temp = (dev->pos < dev->packet_len) ? zipbufferw[dev->pos >> 1] : 0; + dev->pos += 2; + dev->request_pos += 2; + break; + case 4: + temp = (dev->pos < dev->packet_len) ? zipbufferl[dev->pos >> 2] : 0; + dev->pos += 4; + dev->request_pos += 4; + break; + default: + return 0; + } + + if (dev->packet_status == ZIP_PHASE_DATA_IN) { + zip_log("ZIP %i: Returning: %04X (buffer position: %05i, request position: %05i)\n", + id, temp, (dev->pos - 2) & 0xffff, (dev->request_pos - 2) & 0xffff); + if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { + /* Time for a DRQ. */ + zip_log("ZIP %i: Issuing read callback\n", id); + zip_pio_request(dev, 0); } + return temp; + } else { + zip_log("ZIP %i: Returning: 0000 (buffer position: %05i, request position: %05i)\n", + id, (dev->pos - 2) & 0xffff, (dev->request_pos - 2) & 0xffff); + return 0; + } } -/* Reimplement as 8-bit due to reimplementation of IDE data read and write. */ -uint32_t zip_read(uint8_t channel, int length) + +void +zip_write(uint8_t channel, uint32_t val, int length) { - uint16_t *zipbufferw; - uint32_t *zipbufferl; + zip_t *dev; - uint8_t id = atapi_zip_drives[channel]; + uint16_t *zipbufferw; + uint32_t *zipbufferl; - uint32_t temp = 0; + uint8_t id = atapi_zip_drives[channel]; - if (id > ZIP_NUM) - return 0; + if (id > ZIP_NUM) + return; - zipbufferw = (uint16_t *) zipbufferb; - zipbufferl = (uint32_t *) zipbufferb; + dev = zip[id]; + if (dev->packet_status == ZIP_PHASE_IDLE) { if (!zipbufferb) - return 0; + zip_buf_alloc(dev, 12); + } - /* Make sure we return a 0 and don't attempt to read from the buffer if we're transferring bytes beyond it, - which can happen when issuing media access commands with an allocated length below minimum request length - (which is 1 sector = 512 bytes). */ - switch(length) { - case 1: - temp = (zip[id].pos < zip[id].packet_len) ? zipbufferb[zip[id].pos] : 0; - zip[id].pos++; - zip[id].request_pos++; - break; - case 2: - temp = (zip[id].pos < zip[id].packet_len) ? zipbufferw[zip[id].pos >> 1] : 0; - zip[id].pos += 2; - zip[id].request_pos += 2; - break; - case 4: - temp = (zip[id].pos < zip[id].packet_len) ? zipbufferl[zip[id].pos >> 2] : 0; - zip[id].pos += 4; - zip[id].request_pos += 4; - break; - default: - return 0; - } + zipbufferw = (uint16_t *) zipbufferb; + zipbufferl = (uint32_t *) zipbufferb; - if (zip[id].packet_status == ZIP_PHASE_DATA_IN) { - if ((zip[id].request_pos >= zip[id].max_transfer_len) || (zip[id].pos >= zip[id].packet_len)) { - /* Time for a DRQ. */ - // zip_log("ZIP %i: Issuing read callback\n", id); - zip_pio_request(id, 0); - } - // zip_log("ZIP %i: Returning: %02X (buffer position: %i, request position: %i)\n", id, temp, zip[id].pos, zip[id].request_pos); - return temp; - } else { - // zip_log("ZIP %i: Returning zero (buffer position: %i, request position: %i)\n", id, zip[id].pos, zip[id].request_pos); - return 0; + if (!zipbufferb) + return; + + switch(length) { + case 1: + zipbufferb[dev->pos] = val & 0xff; + dev->pos++; + dev->request_pos++; + break; + case 2: + zipbufferw[dev->pos >> 1] = val & 0xffff; + dev->pos += 2; + dev->request_pos += 2; + break; + case 4: + zipbufferl[dev->pos >> 2] = val; + dev->pos += 4; + dev->request_pos += 4; + break; + default: + return; + } + + if (dev->packet_status == ZIP_PHASE_DATA_OUT) { + if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { + /* Time for a DRQ. */ + zip_pio_request(dev, 1); } + return; + } else if (dev->packet_status == ZIP_PHASE_IDLE) { + if (dev->pos >= 12) { + dev->pos = 0; + dev->status = BUSY_STAT; + dev->packet_status = ZIP_PHASE_COMMAND; + timer_process(); + zip_phase_callback(dev); + timer_update_outstanding(); + } + return; + } } -/* Reimplement as 8-bit due to reimplementation of IDE data read and write. */ -void zip_write(uint8_t channel, uint32_t val, int length) -{ - uint16_t *zipbufferw; - uint32_t *zipbufferl; - - uint8_t id = atapi_zip_drives[channel]; - - if (id > ZIP_NUM) - return; - - if (zip[id].packet_status == ZIP_PHASE_IDLE) { - if (!zipbufferb) - zip_buf_alloc(id, zip[id].cdb_len); - } - - zipbufferw = (uint16_t *) zipbufferb; - zipbufferl = (uint32_t *) zipbufferb; - - if (!zipbufferb) - return; - - switch(length) { - case 1: - zipbufferb[zip[id].pos] = val & 0xff; - zip[id].pos++; - zip[id].request_pos++; - break; - case 2: - zipbufferw[zip[id].pos >> 1] = val & 0xffff; - zip[id].pos += 2; - zip[id].request_pos += 2; - break; - case 4: - zipbufferl[zip[id].pos >> 2] = val; - zip[id].pos += 4; - zip[id].request_pos += 4; - break; - default: - return; - } - - if (zip[id].packet_status == ZIP_PHASE_DATA_OUT) { - if ((zip[id].request_pos >= zip[id].max_transfer_len) || (zip[id].pos >= zip[id].packet_len)) { - /* Time for a DRQ. */ - zip_pio_request(id, 1); - } - return; - } else if (zip[id].packet_status == ZIP_PHASE_IDLE) { - if (zip[id].pos >= zip[id].cdb_len) { - zip[id].pos=0; - zip[id].status = BUSY_STAT; - zip[id].packet_status = ZIP_PHASE_COMMAND; - timer_process(); - zip_phase_callback(id); - timer_update_outstanding(); - } - return; - } -} /* Peform a master init on the entire module. */ void @@ -2576,14 +2722,45 @@ zip_hard_reset(void) { int c; - for (c=0; cid = c; + zip[c]->drv = &zip_drives[c]; + + zip_init(zip[c]); + + if (wcslen(zip_drives[c].image_path)) + zip_load(zip[c], zip_drives[c].image_path); + + zip_mode_sense_load(zip[c]); + } + } + + build_atapi_zip_map(); +} + + +void +zip_close(void) +{ + zip_t *dev; + int c; + + for (c = 0; c < ZIP_NUM; c++) { + dev = zip[c]; + + if (dev) { + zip_disk_close(dev); + + free(zip[c]); + zip[c] = NULL; + } } } diff --git a/src/disk/zip.h b/src/disk/zip.h index 63b96f9b6..67be6797b 100644 --- a/src/disk/zip.h +++ b/src/disk/zip.h @@ -9,7 +9,7 @@ * Implementation of the Iomega ZIP drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)zip.h 1.0.4 2018/03/20 + * Version: @(#)zip.h 1.0.6 2018/04/30 * * Author: Miran Grca, * @@ -19,20 +19,19 @@ #define EMU_ZIP_H -#define ZIP_NUM 4 +#define ZIP_NUM 4 -#define ZIP_PHASE_IDLE 0 -#define ZIP_PHASE_COMMAND 1 -#define ZIP_PHASE_COMPLETE 2 -#define ZIP_PHASE_DATA_IN 3 -#define ZIP_PHASE_DATA_IN_DMA 4 -#define ZIP_PHASE_DATA_OUT 5 -#define ZIP_PHASE_DATA_OUT_DMA 6 +#define ZIP_PHASE_IDLE 0x00 +#define ZIP_PHASE_COMMAND 0x01 +#define ZIP_PHASE_COMPLETE 0x02 +#define ZIP_PHASE_DATA_IN 0x03 +#define ZIP_PHASE_DATA_IN_DMA 0x04 +#define ZIP_PHASE_DATA_OUT 0x05 +#define ZIP_PHASE_DATA_OUT_DMA 0x06 #define ZIP_PHASE_ERROR 0x80 #define BUF_SIZE 32768 -#define IDE_TIME (5LL * 100LL * (1LL << TIMER_SHIFT)) #define ZIP_TIME (5LL * 100LL * (1LL << TIMER_SHIFT)) #define ZIP_SECTORS (96*2048) @@ -42,165 +41,111 @@ enum { ZIP_BUS_DISABLED = 0, - ZIP_BUS_ATAPI_PIO_ONLY = 4, - ZIP_BUS_ATAPI_PIO_AND_DMA, + ZIP_BUS_ATAPI = 4, ZIP_BUS_SCSI, - ZIP_BUS_USB = 8 + ZIP_BUS_USB }; typedef struct { - uint8_t previous_command; + unsigned int bus_type; /* 0 = ATAPI, 1 = SCSI */ + uint8_t ide_channel, + bus_mode; /* Bit 0 = PIO suported; + Bit 1 = DMA supportd. */ - int toctimes; - int media_status; + unsigned int scsi_device_id, is_250; - int is_dma; + wchar_t image_path[1024], + prev_image_path[1024]; - int requested_blocks; /* This will be set to something other than 1 when block reads are implemented. */ + int read_only, ui_writeprot; - uint64_t current_page_code; - int current_page_len; + uint32_t medium_size, base; - int current_page_pos; - - int mode_select_phase; - - int total_length; - int written_length; - - int do_page_save; - - uint8_t error; - uint8_t features; - uint16_t request_length; - uint16_t max_transfer_len; - uint8_t status; - uint8_t phase; - - uint32_t sector_pos; - uint32_t sector_len; - - uint32_t packet_len; - int packet_status; - - uint8_t atapi_cdb[16]; - uint8_t current_cdb[16]; - - uint32_t pos; - - int callback; - - int data_pos; - - int cdb_len_setting; - int cdb_len; - - int cd_status; - int prev_status; - - int unit_attention; - uint8_t sense[256]; - - int request_pos; - - uint8_t *buffer; - - int times; - - uint32_t seek_pos; - - int total_read; - - int block_total; - int all_blocks_total; - - int old_len; - int block_descriptor_len; - - int init_length; -} zip_t; - -typedef struct { - int host_drive; - int prev_host_drive; - - unsigned int bus_type; /* 0 = ATAPI, 1 = SCSI */ - uint8_t bus_mode; /* Bit 0 = PIO suported; - Bit 1 = DMA supportd. */ - - uint8_t ide_channel; - - unsigned int scsi_device_id; - unsigned int scsi_device_lun; - - unsigned int is_250; - unsigned int atapi_dma; - - wchar_t image_path[1024]; - wchar_t prev_image_path[1024]; - - uint32_t medium_size; - - int read_only; - int ui_writeprot; - - uint32_t base; - - FILE *f; + FILE *f; } zip_drive_t; +typedef struct { + mode_sense_pages_t ms_pages_saved; -extern zip_t zip[ZIP_NUM]; + zip_drive_t *drv; + + uint8_t previous_command, + error, features, + status, phase, + id, *buffer, + atapi_cdb[16], + current_cdb[16], + sense[256]; + + uint16_t request_length, max_transfer_len; + + int toctimes, media_status, + is_dma, requested_blocks, + current_page_len, current_page_pos, + total_length, written_length, + mode_select_phase, do_page_save, + callback, data_pos, + packet_status, unit_attention, + cdb_len_setting, cdb_len, + request_pos, total_read, + block_total, all_blocks_total, + old_len, block_descriptor_len, + init_length; + + uint32_t sector_pos, sector_len, + packet_len, pos, + seek_pos; + + uint64_t current_page_code; +} zip_t; + + +extern zip_t *zip[ZIP_NUM]; extern zip_drive_t zip_drives[ZIP_NUM]; extern uint8_t atapi_zip_drives[8]; -extern uint8_t scsi_zip_drives[16][8]; +extern uint8_t scsi_zip_drives[16]; -#define zip_sense_error zip[id].sense[0] -#define zip_sense_key zip[id].sense[2] -#define zip_asc zip[id].sense[12] -#define zip_ascq zip[id].sense[13] -#define zip_drive zip_drives[id].host_drive +#define zip_sense_error dev->sense[0] +#define zip_sense_key dev->sense[2] +#define zip_asc dev->sense[12] +#define zip_ascq dev->sense[13] #ifdef __cplusplus extern "C" { #endif -extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length); -extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length); -extern void (*ide_bus_master_set_irq)(int channel); -extern void ioctl_close(uint8_t id); +extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length, void *priv); +extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length, void *priv); +extern void (*ide_bus_master_set_irq)(int channel, void *priv); +extern void *ide_bus_master_priv[2]; -extern uint32_t zip_mode_sense_get_channel(uint8_t id, int channel); -extern uint32_t zip_mode_sense_get_volume(uint8_t id, int channel); extern void build_atapi_zip_map(void); extern void build_scsi_zip_map(void); -extern int zip_ZIP_PHASE_to_scsi(uint8_t id); -extern int zip_atapi_phase_to_scsi(uint8_t id); -extern void zip_command(uint8_t id, uint8_t *cdb); -extern void zip_phase_callback(uint8_t id); +extern int zip_ZIP_PHASE_to_scsi(zip_t *dev); +extern int zip_atapi_phase_to_scsi(zip_t *dev); +extern void zip_command(zip_t *dev, uint8_t *cdb); +extern void zip_phase_callback(zip_t *dev); extern uint32_t zip_read(uint8_t channel, int length); extern void zip_write(uint8_t channel, uint32_t val, int length); -extern int zip_lba_to_msf_accurate(int lba); - -extern void zip_close(uint8_t id); -extern void zip_disk_reload(uint8_t id); -extern void zip_reset(uint8_t id); -extern void zip_set_signature(int id); -extern void zip_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length); +extern void zip_disk_close(zip_t *dev); +extern void zip_disk_reload(zip_t *dev); +extern void zip_reset(zip_t *dev); +extern void zip_set_signature(zip_t *dev); +extern void zip_request_sense_for_scsi(zip_t *dev, uint8_t *buffer, uint8_t alloc_length); extern void zip_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks); -extern void zip_insert(uint8_t id); +extern void zip_insert(zip_t *dev); -extern int find_zip_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun); -extern int zip_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len); +extern int find_zip_for_scsi_id(uint8_t scsi_id); +extern int zip_read_capacity(zip_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len); extern void zip_global_init(void); extern void zip_hard_reset(void); -extern int zip_load(uint8_t id, wchar_t *fn); -extern void zip_close(uint8_t id); +extern int zip_load(zip_t *dev, wchar_t *fn); +extern void zip_close(); #ifdef __cplusplus } diff --git a/src/dma.c b/src/dma.c index 89fcb9c8a..ef07c6137 100644 --- a/src/dma.c +++ b/src/dma.c @@ -1,20 +1,40 @@ /* - * 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. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Implementation of the Intel DMA controllers. * - * Version: @(#)dma.c 1.0.8 2018/03/11 + * Version: @(#)dma.c 1.0.3 2018/03/13 * - * Authors: Sarah Walker, + * Authors: Fred N. van Kempen, * Miran Grca, + * Sarah Walker, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #include #include @@ -30,824 +50,868 @@ #include "dma.h" -static uint8_t dmaregs[16]; -static uint8_t dma16regs[16]; -static uint8_t dmapages[16]; +dma_t dma[8]; -dma_t dma[8]; -static int dma_wp, dma16_wp; -static uint8_t dma_m; -static uint8_t dma_stat; -static uint8_t dma_stat_rq; -static uint8_t dma_command, dma16_command; +static uint8_t dmaregs[16]; +static uint8_t dma16regs[16]; +static uint8_t dmapages[16]; +static int dma_wp, + dma16_wp; +static uint8_t dma_m; +static uint8_t dma_stat; +static uint8_t dma_stat_rq; +static uint8_t dma_command, + dma16_command; +static struct { + int xfr_command, + xfr_channel; + int byte_ptr; -static struct -{ - int xfr_command, xfr_channel; - int byte_ptr; - - int is_ps2; + int is_ps2; } dma_ps2; -#define DMA_PS2_IOA (1 << 0) -#define DMA_PS2_XFER_MEM_TO_IO (1 << 2) -#define DMA_PS2_XFER_IO_TO_MEM (3 << 2) -#define DMA_PS2_XFER_MASK (3 << 2) -#define DMA_PS2_DEC2 (1 << 4) -#define DMA_PS2_SIZE16 (1 << 6) + +#define DMA_PS2_IOA (1 << 0) +#define DMA_PS2_XFER_MEM_TO_IO (1 << 2) +#define DMA_PS2_XFER_IO_TO_MEM (3 << 2) +#define DMA_PS2_XFER_MASK (3 << 2) +#define DMA_PS2_DEC2 (1 << 4) +#define DMA_PS2_SIZE16 (1 << 6) + static void dma_ps2_run(int channel); -void dma_reset(void) + +static uint8_t +dma_read(uint16_t addr, void *priv) { - int c; - - dma_wp = dma16_wp = 0; - dma_m = 0; - - for (c = 0; c < 16; c++) - dmaregs[c] = 0; - for (c = 0; c < 8; c++) - { - dma[c].mode = 0; - dma[c].ac = 0; - dma[c].cc = 0; - dma[c].ab = 0; - dma[c].cb = 0; - dma[c].size = (c & 4) ? 1 : 0; + int channel = (addr >> 1) & 3; + uint8_t temp; + + switch (addr & 0xf) { + case 0: + case 2: + case 4: + case 6: /*Address registers*/ + dma_wp ^= 1; + if (dma_wp) + return(dma[channel].ac & 0xff); + return((dma[channel].ac >> 8) & 0xff); + + case 1: + case 3: + case 5: + case 7: /*Count registers*/ + dma_wp ^= 1; + if (dma_wp) + temp = dma[channel].cc & 0xff; + else + temp = dma[channel].cc >> 8; + return(temp); + + case 8: /*Status register*/ + temp = dma_stat & 0xf; + dma_stat &= ~0xf; + return(temp); + + case 0xd: + return(0); + } + + return(dmaregs[addr & 0xf]); +} + + +static void +dma_write(uint16_t addr, uint8_t val, void *priv) +{ + int channel = (addr >> 1) & 3; + + dmaregs[addr & 0xf] = val; + switch (addr & 0xf) { + case 0: + case 2: + case 4: + case 6: /*Address registers*/ + dma_wp ^= 1; + if (dma_wp) + dma[channel].ab = (dma[channel].ab & 0xffff00) | val; + else + dma[channel].ab = (dma[channel].ab & 0xff00ff) | (val << 8); + dma[channel].ac = dma[channel].ab; + return; + + case 1: + case 3: + case 5: + case 7: /*Count registers*/ + dma_wp ^= 1; + if (dma_wp) + dma[channel].cb = (dma[channel].cb & 0xff00) | val; + else + dma[channel].cb = (dma[channel].cb & 0x00ff) | (val << 8); + dma[channel].cc = dma[channel].cb; + return; + + case 8: /*Control register*/ + dma_command = val; + return; + + case 0xa: /*Mask*/ + if (val & 4) + dma_m |= (1 << (val & 3)); + else + dma_m &= ~(1 << (val & 3)); + return; + + case 0xb: /*Mode*/ + channel = (val & 3); + dma[channel].mode = val; + if (dma_ps2.is_ps2) { + dma[channel].ps2_mode &= ~0x1c; + if (val & 0x20) + dma[channel].ps2_mode |= 0x10; + if ((val & 0xc) == 8) + dma[channel].ps2_mode |= 4; + else if ((val & 0xc) == 4) + dma[channel].ps2_mode |= 0xc; + } + return; + + case 0xc: /*Clear FF*/ + dma_wp = 0; + return; + + case 0xd: /*Master clear*/ + dma_wp = 0; + dma_m |= 0xf; + return; + + case 0xf: /*Mask write*/ + dma_m = (dma_m & 0xf0) | (val & 0xf); + return; + } +} + + +static uint8_t +dma_ps2_read(uint16_t addr, void *priv) +{ + dma_t *dma_c = &dma[dma_ps2.xfr_channel]; + uint8_t temp = 0xff; + + switch (addr) { + case 0x1a: + switch (dma_ps2.xfr_command) { + case 2: /*Address*/ + case 3: + switch (dma_ps2.byte_ptr) { + case 0: + temp = dma_c->ac & 0xff; + dma_ps2.byte_ptr = 1; + break; + case 1: + temp = (dma_c->ac >> 8) & 0xff; + dma_ps2.byte_ptr = 2; + break; + case 2: + temp = (dma_c->ac >> 16) & 0xff; + dma_ps2.byte_ptr = 0; + break; + } + break; + + case 4: /*Count*/ + case 5: + if (dma_ps2.byte_ptr) + temp = dma_c->cc >> 8; + else + temp = dma_c->cc & 0xff; + dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; + break; + + case 6: /*Read DMA status*/ + if (dma_ps2.byte_ptr) { + temp = ((dma_stat_rq & 0xf0) >> 4) | (dma_stat & 0xf0); + dma_stat &= ~0xf0; + dma_stat_rq &= ~0xf0; + } else { + temp = (dma_stat_rq & 0xf) | ((dma_stat & 0xf) << 4); + dma_stat &= ~0xf; + dma_stat_rq &= ~0xf; + } + dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; + break; + + case 7: /*Mode*/ + temp = dma_c->ps2_mode; + break; + + case 8: /*Arbitration Level*/ + temp = dma_c->arb_level; + break; + + default: + fatal("Bad XFR Read command %i channel %i\n", dma_ps2.xfr_command, dma_ps2.xfr_channel); + } + break; + } + + return(temp); +} + + +static void +dma_ps2_write(uint16_t addr, uint8_t val, void *priv) +{ + dma_t *dma_c = &dma[dma_ps2.xfr_channel]; + uint8_t mode; + + switch (addr) { + case 0x18: + dma_ps2.xfr_channel = val & 0x7; + dma_ps2.xfr_command = val >> 4; + dma_ps2.byte_ptr = 0; + switch (dma_ps2.xfr_command) { + case 9: /*Set DMA mask*/ + dma_m |= (1 << dma_ps2.xfr_channel); + break; + + case 0xa: /*Reset DMA mask*/ + dma_m &= ~(1 << dma_ps2.xfr_channel); + break; + + case 0xb: + if (!(dma_m & (1 << dma_ps2.xfr_channel))) + dma_ps2_run(dma_ps2.xfr_channel); + break; + } + break; + + case 0x1a: + switch (dma_ps2.xfr_command) { + case 0: /*I/O address*/ + if (dma_ps2.byte_ptr) + dma_c->io_addr = (dma_c->io_addr & 0x00ff) | (val << 8); + else + dma_c->io_addr = (dma_c->io_addr & 0xff00) | val; + dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; + break; + + case 2: /*Address*/ + switch (dma_ps2.byte_ptr) { + case 0: + dma_c->ac = (dma_c->ac & 0xffff00) | val; + dma_ps2.byte_ptr = 1; + break; + + case 1: + dma_c->ac = (dma_c->ac & 0xff00ff) | (val << 8); + dma_ps2.byte_ptr = 2; + break; + + case 2: + dma_c->ac = (dma_c->ac & 0x00ffff) | (val << 16); + dma_ps2.byte_ptr = 0; + break; + } + dma_c->ab = dma_c->ac; + break; + + case 4: /*Count*/ + if (dma_ps2.byte_ptr) + dma_c->cc = (dma_c->cc & 0xff) | (val << 8); + else + dma_c->cc = (dma_c->cc & 0xff00) | val; + dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; + dma_c->cb = dma_c->cc; + break; + + case 7: /*Mode register*/ + mode = 0; + if (val & DMA_PS2_DEC2) + mode |= 0x20; + if ((val & DMA_PS2_XFER_MASK) == DMA_PS2_XFER_MEM_TO_IO) + mode |= 8; + else if ((val & DMA_PS2_XFER_MASK) == DMA_PS2_XFER_IO_TO_MEM) + mode |= 4; + dma_c->mode = (dma_c->mode & ~0x2c) | mode; + dma_c->ps2_mode = val; + dma_c->size = val & DMA_PS2_SIZE16; + break; + + case 8: /*Arbitration Level*/ + dma_c->arb_level = val; + break; + + default: + fatal("Bad XFR command %i channel %i val %02x\n", dma_ps2.xfr_command, dma_ps2.xfr_channel, val); + } + break; + } +} + + +static uint8_t +dma16_read(uint16_t addr, void *priv) +{ + int channel = ((addr >> 2) & 3) + 4; + uint8_t temp; + + addr >>= 1; + switch (addr & 0xf) { + case 0: + case 2: + case 4: + case 6: /*Address registers*/ + dma16_wp ^= 1; + if (dma_ps2.is_ps2) { + if (dma16_wp) + return(dma[channel].ac); + return((dma[channel].ac >> 8) & 0xff); + } + if (dma16_wp) + return((dma[channel].ac >> 1) & 0xff); + return((dma[channel].ac >> 9) & 0xff); + + case 1: + case 3: + case 5: + case 7: /*Count registers*/ + dma16_wp ^= 1; + if (dma16_wp) + temp = dma[channel].cc & 0xff; + else + temp = dma[channel].cc >> 8; + return(temp); + + case 8: /*Status register*/ + temp = dma_stat >> 4; + dma_stat &= ~0xf0; + return(temp); + } + + return(dma16regs[addr & 0xf]); +} + + +static void +dma16_write(uint16_t addr, uint8_t val, void *priv) +{ + int channel = ((addr >> 2) & 3) + 4; + addr >>= 1; + + dma16regs[addr & 0xf] = val; + switch (addr & 0xf) { + case 0: + case 2: + case 4: + case 6: /*Address registers*/ + dma16_wp ^= 1; + if (dma_ps2.is_ps2) { + if (dma16_wp) + dma[channel].ab = (dma[channel].ab & 0xffff00) | val; + else + dma[channel].ab = (dma[channel].ab & 0xff00ff) | (val << 8); + } else { + if (dma16_wp) + dma[channel].ab = (dma[channel].ab & 0xfffe00) | (val << 1); + else + dma[channel].ab = (dma[channel].ab & 0xfe01ff) | (val << 9); + } + dma[channel].ac = dma[channel].ab; + return; + + case 1: + case 3: + case 5: + case 7: /*Count registers*/ + dma16_wp ^= 1; + if (dma16_wp) + dma[channel].cb = (dma[channel].cb & 0xff00) | val; + else + dma[channel].cb = (dma[channel].cb & 0x00ff) | (val << 8); + dma[channel].cc = dma[channel].cb; + return; + + case 8: /*Control register*/ + return; + + case 0xa: /*Mask*/ + if (val & 4) + dma_m |= (0x10 << (val & 3)); + else + dma_m &= ~(0x10 << (val & 3)); + return; + + case 0xb: /*Mode*/ + channel = (val & 3) + 4; + dma[channel].mode = val; + if (dma_ps2.is_ps2) { + dma[channel].ps2_mode &= ~0x1c; + if (val & 0x20) + dma[channel].ps2_mode |= 0x10; + if ((val & 0xc) == 8) + dma[channel].ps2_mode |= 4; + else if ((val & 0xc) == 4) + dma[channel].ps2_mode |= 0xc; + } + return; + + case 0xc: /*Clear FF*/ + dma16_wp = 0; + return; + + case 0xd: /*Master clear*/ + dma16_wp = 0; + dma_m |= 0xf0; + return; + + case 0xf: /*Mask write*/ + dma_m = (dma_m & 0x0f) | ((val & 0xf) << 4); + return; + } +} + + +static void +dma_page_write(uint16_t addr, uint8_t val, void *priv) +{ + dmapages[addr & 0xf] = val; + + switch (addr & 0xf) { + case 1: + dma[2].page = (AT) ? val : val & 0xf; + dma[2].ab = (dma[2].ab & 0xffff) | (dma[2].page << 16); + dma[2].ac = (dma[2].ac & 0xffff) | (dma[2].page << 16); + break; + + case 2: + dma[3].page = (AT) ? val : val & 0xf; + dma[3].ab = (dma[3].ab & 0xffff) | (dma[3].page << 16); + dma[3].ac = (dma[3].ac & 0xffff) | (dma[3].page << 16); + break; + + case 3: + dma[1].page = (AT) ? val : val & 0xf; + dma[1].ab = (dma[1].ab & 0xffff) | (dma[1].page << 16); + dma[1].ac = (dma[1].ac & 0xffff) | (dma[1].page << 16); + break; + + case 7: + dma[0].page = (AT) ? val : val & 0xf; + dma[0].ab = (dma[0].ab & 0xffff) | (dma[0].page << 16); + dma[0].ac = (dma[0].ac & 0xffff) | (dma[0].page << 16); + break; + + case 0x9: + dma[6].page = val & 0xfe; + dma[6].ab = (dma[6].ab & 0x1ffff) | (dma[6].page << 16); + dma[6].ac = (dma[6].ac & 0x1ffff) | (dma[6].page << 16); + break; + + case 0xa: + dma[7].page = val & 0xfe; + dma[7].ab = (dma[7].ab & 0x1ffff) | (dma[7].page << 16); + dma[7].ac = (dma[7].ac & 0x1ffff) | (dma[7].page << 16); + break; + + case 0xb: + dma[5].page = val & 0xfe; + dma[5].ab = (dma[5].ab & 0x1ffff) | (dma[5].page << 16); + dma[5].ac = (dma[5].ac & 0x1ffff) | (dma[5].page << 16); + break; + + case 0xf: + dma[4].page = val & 0xfe; + dma[4].ab = (dma[4].ab & 0x1ffff) | (dma[4].page << 16); + dma[4].ac = (dma[4].ac & 0x1ffff) | (dma[4].page << 16); + break; + } +} + + +static uint8_t +dma_page_read(uint16_t addr, void *priv) +{ + return(dmapages[addr & 0xf]); +} + + +void +dma_reset(void) +{ + int c; + + dma_wp = dma16_wp = 0; + dma_m = 0; + + for (c = 0; c < 16; c++) + dmaregs[c] = 0; + for (c = 0; c < 8; c++) { + dma[c].mode = 0; + dma[c].ac = 0; + dma[c].cc = 0; + dma[c].ab = 0; + dma[c].cb = 0; + dma[c].size = (c & 4) ? 1 : 0; + } +} + + +void +dma_init(void) +{ + io_sethandler(0x0000, 16, + dma_read,NULL,NULL, dma_write,NULL,NULL, NULL); + io_sethandler(0x0080, 8, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + dma_ps2.is_ps2 = 0; +} + + +void +dma16_init(void) +{ + io_sethandler(0x00C0, 32, + dma16_read,NULL,NULL, dma16_write,NULL,NULL, NULL); + io_sethandler(0x0088, 8, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); +} + + +void +dma_alias_set(void) +{ + io_sethandler(0x0090, 16, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); +} + + +void +dma_alias_remove(void) +{ + io_removehandler(0x0090, 16, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); +} + + +void +dma_alias_remove_piix(void) +{ + io_removehandler(0x0090, 1, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + io_removehandler(0x0094, 3, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + io_removehandler(0x0098, 1, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + io_removehandler(0x009C, 3, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); +} + + +void +ps2_dma_init(void) +{ + io_sethandler(0x0018, 1, + dma_ps2_read,NULL,NULL, dma_ps2_write,NULL,NULL, NULL); + io_sethandler(0x001a, 1, + dma_ps2_read,NULL,NULL, dma_ps2_write,NULL,NULL, NULL); + dma_ps2.is_ps2 = 1; +} + + +uint8_t +_dma_read(uint32_t addr) +{ + uint8_t temp = mem_readb_phys_dma(addr); + + return(temp); +} + + +void +_dma_write(uint32_t addr, uint8_t val) +{ + mem_writeb_phys_dma(addr, val); + mem_invalidate_range(addr, addr); +} + + +int +dma_channel_read(int channel) +{ + dma_t *dma_c = &dma[channel]; + uint16_t temp; + int tc = 0; + + if (channel < 4) { + if (dma_command & 0x04) + return(DMA_NODATA); + } else { + if (dma16_command & 0x04) + return(DMA_NODATA); + } + + if (! AT) + refreshread(); + + if (dma_m & (1 << channel)) + return(DMA_NODATA); + if ((dma_c->mode & 0xC) != 8) + return(DMA_NODATA); + + if (! dma_c->size) { + temp = _dma_read(dma_c->ac); + + if (dma_c->mode & 0x20) { + if (dma_ps2.is_ps2) + dma_c->ac--; + else + dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac - 1) & 0xffff); + } else { + if (dma_ps2.is_ps2) + dma_c->ac++; + else + dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac + 1) & 0xffff); } -} + } else { + temp = _dma_read(dma_c->ac) | (_dma_read(dma_c->ac + 1) << 8); -uint8_t dma_read(uint16_t addr, void *priv) -{ - int channel = (addr >> 1) & 3; - uint8_t temp; - switch (addr & 0xf) - { - case 0: case 2: case 4: case 6: /*Address registers*/ - dma_wp ^= 1; - if (dma_wp) - return dma[channel].ac & 0xff; - return (dma[channel].ac >> 8) & 0xff; - - case 1: case 3: case 5: case 7: /*Count registers*/ - dma_wp ^= 1; - if (dma_wp) - temp = dma[channel].cc & 0xff; - else - temp = dma[channel].cc >> 8; - return temp; - - case 8: /*Status register*/ - temp = dma_stat & 0xf; - dma_stat &= ~0xf; - return temp; - - case 0xd: - return 0; - } - return dmaregs[addr & 0xf]; -} - -void dma_write(uint16_t addr, uint8_t val, void *priv) -{ - int channel = (addr >> 1) & 3; - dmaregs[addr & 0xf] = val; - switch (addr & 0xf) - { - case 0: case 2: case 4: case 6: /*Address registers*/ - dma_wp ^= 1; - if (dma_wp) - dma[channel].ab = (dma[channel].ab & 0xffff00) | val; - else - dma[channel].ab = (dma[channel].ab & 0xff00ff) | (val << 8); - dma[channel].ac = dma[channel].ab; - return; - - case 1: case 3: case 5: case 7: /*Count registers*/ - dma_wp ^= 1; - if (dma_wp) - dma[channel].cb = (dma[channel].cb & 0xff00) | val; - else - dma[channel].cb = (dma[channel].cb & 0x00ff) | (val << 8); - dma[channel].cc = dma[channel].cb; - return; - - case 8: /*Control register*/ - dma_command = val; - return; - - case 0xa: /*Mask*/ - if (val & 4) - dma_m |= (1 << (val & 3)); - else - dma_m &= ~(1 << (val & 3)); - return; - - case 0xb: /*Mode*/ - channel = (val & 3); - dma[channel].mode = val; - if (dma_ps2.is_ps2) - { - dma[channel].ps2_mode &= ~0x1c; - if (val & 0x20) - dma[channel].ps2_mode |= 0x10; - if ((val & 0xc) == 8) - dma[channel].ps2_mode |= 4; - else if ((val & 0xc) == 4) - dma[channel].ps2_mode |= 0xc; - } - return; - - case 0xc: /*Clear FF*/ - dma_wp = 0; - return; - - case 0xd: /*Master clear*/ - dma_wp = 0; - dma_m |= 0xf; - return; - - case 0xf: /*Mask write*/ - dma_m = (dma_m & 0xf0) | (val & 0xf); - return; - } -} - -static uint8_t dma_ps2_read(uint16_t addr, void *priv) -{ - dma_t *dma_c = &dma[dma_ps2.xfr_channel]; - uint8_t temp = 0xff; - - switch (addr) - { - case 0x1a: - switch (dma_ps2.xfr_command) - { - case 2: /*Address*/ - case 3: - switch (dma_ps2.byte_ptr) - { - case 0: - temp = dma_c->ac & 0xff; - dma_ps2.byte_ptr = 1; - break; - case 1: - temp = (dma_c->ac >> 8) & 0xff; - dma_ps2.byte_ptr = 2; - break; - case 2: - temp = (dma_c->ac >> 16) & 0xff; - dma_ps2.byte_ptr = 0; - break; - } - break; - case 4: /*Count*/ - case 5: - if (dma_ps2.byte_ptr) - temp = dma_c->cc >> 8; - else - temp = dma_c->cc & 0xff; - dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; - break; - case 6: /*Read DMA status*/ - if (dma_ps2.byte_ptr) - { - temp = ((dma_stat_rq & 0xf0) >> 4) | (dma_stat & 0xf0); - dma_stat &= ~0xf0; - dma_stat_rq &= ~0xf0; - } - else - { - temp = (dma_stat_rq & 0xf) | ((dma_stat & 0xf) << 4); - dma_stat &= ~0xf; - dma_stat_rq &= ~0xf; - } - dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; - break; - case 7: /*Mode*/ - temp = dma_c->ps2_mode; - break; - case 8: /*Arbitration Level*/ - temp = dma_c->arb_level; - break; - - default: - fatal("Bad XFR Read command %i channel %i\n", dma_ps2.xfr_command, dma_ps2.xfr_channel); - } - break; - } - - return temp; -} - -static void dma_ps2_write(uint16_t addr, uint8_t val, void *priv) -{ - dma_t *dma_c = &dma[dma_ps2.xfr_channel]; - uint8_t mode; - - switch (addr) - { - case 0x18: - dma_ps2.xfr_channel = val & 0x7; - dma_ps2.xfr_command = val >> 4; - dma_ps2.byte_ptr = 0; - switch (dma_ps2.xfr_command) - { - case 9: /*Set DMA mask*/ - dma_m |= (1 << dma_ps2.xfr_channel); - break; - case 0xa: /*Reset DMA mask*/ - dma_m &= ~(1 << dma_ps2.xfr_channel); - break; - case 0xb: - if (!(dma_m & (1 << dma_ps2.xfr_channel))) - dma_ps2_run(dma_ps2.xfr_channel); - break; - } - break; - case 0x1a: - switch (dma_ps2.xfr_command) - { - case 0: /*I/O address*/ - if (dma_ps2.byte_ptr) - dma_c->io_addr = (dma_c->io_addr & 0x00ff) | (val << 8); - else - dma_c->io_addr = (dma_c->io_addr & 0xff00) | val; - dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; - break; - - case 2: /*Address*/ - switch (dma_ps2.byte_ptr) - { - case 0: - dma_c->ac = (dma_c->ac & 0xffff00) | val; - dma_ps2.byte_ptr = 1; - break; - case 1: - dma_c->ac = (dma_c->ac & 0xff00ff) | (val << 8); - dma_ps2.byte_ptr = 2; - break; - case 2: - dma_c->ac = (dma_c->ac & 0x00ffff) | (val << 16); - dma_ps2.byte_ptr = 0; - break; - } - dma_c->ab = dma_c->ac; - break; - - case 4: /*Count*/ - if (dma_ps2.byte_ptr) - dma_c->cc = (dma_c->cc & 0xff) | (val << 8); - else - dma_c->cc = (dma_c->cc & 0xff00) | val; - dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1; - dma_c->cb = dma_c->cc; - break; - - case 7: /*Mode register*/ - mode = 0; - if (val & DMA_PS2_DEC2) - mode |= 0x20; - if ((val & DMA_PS2_XFER_MASK) == DMA_PS2_XFER_MEM_TO_IO) - mode |= 8; - else if ((val & DMA_PS2_XFER_MASK) == DMA_PS2_XFER_IO_TO_MEM) - mode |= 4; - dma_c->mode = (dma_c->mode & ~0x2c) | mode; - dma_c->ps2_mode = val; - dma_c->size = val & DMA_PS2_SIZE16; - break; - - case 8: /*Arbitration Level*/ - dma_c->arb_level = val; - break; - - default: - fatal("Bad XFR command %i channel %i val %02x\n", dma_ps2.xfr_command, dma_ps2.xfr_channel, val); - } - break; - } -} - -uint8_t dma16_read(uint16_t addr, void *priv) -{ - int channel = ((addr >> 2) & 3) + 4; - uint8_t temp; - addr >>= 1; - switch (addr & 0xf) - { - case 0: case 2: case 4: case 6: /*Address registers*/ - dma16_wp ^= 1; - if (dma_ps2.is_ps2) - { - if (dma16_wp) - return dma[channel].ac; - return (dma[channel].ac >> 8) & 0xff; - } - if (dma16_wp) - return (dma[channel].ac >> 1) & 0xff; - return (dma[channel].ac >> 9) & 0xff; - - case 1: case 3: case 5: case 7: /*Count registers*/ - dma16_wp ^= 1; - if (dma16_wp) - temp = dma[channel].cc & 0xff; - else - temp = dma[channel].cc >> 8; - return temp; - - case 8: /*Status register*/ - temp = dma_stat >> 4; - dma_stat &= ~0xf0; - return temp; - } - return dma16regs[addr & 0xf]; -} - -void dma16_write(uint16_t addr, uint8_t val, void *priv) -{ - int channel = ((addr >> 2) & 3) + 4; - addr >>= 1; - dma16regs[addr & 0xf] = val; - switch (addr & 0xf) - { - case 0: case 2: case 4: case 6: /*Address registers*/ - dma16_wp ^= 1; - if (dma_ps2.is_ps2) - { - if (dma16_wp) - dma[channel].ab = (dma[channel].ab & 0xffff00) | val; - else - dma[channel].ab = (dma[channel].ab & 0xff00ff) | (val << 8); - } - else - { - if (dma16_wp) - dma[channel].ab = (dma[channel].ab & 0xfffe00) | (val << 1); - else - dma[channel].ab = (dma[channel].ab & 0xfe01ff) | (val << 9); - } - dma[channel].ac = dma[channel].ab; - return; - - case 1: case 3: case 5: case 7: /*Count registers*/ - dma16_wp ^= 1; - if (dma16_wp) - dma[channel].cb = (dma[channel].cb & 0xff00) | val; - else - dma[channel].cb = (dma[channel].cb & 0x00ff) | (val << 8); - dma[channel].cc = dma[channel].cb; - return; - - case 8: /*Control register*/ - return; - - case 0xa: /*Mask*/ - if (val & 4) - dma_m |= (0x10 << (val & 3)); - else - dma_m &= ~(0x10 << (val & 3)); - return; - - case 0xb: /*Mode*/ - channel = (val & 3) + 4; - dma[channel].mode = val; - if (dma_ps2.is_ps2) - { - dma[channel].ps2_mode &= ~0x1c; - if (val & 0x20) - dma[channel].ps2_mode |= 0x10; - if ((val & 0xc) == 8) - dma[channel].ps2_mode |= 4; - else if ((val & 0xc) == 4) - dma[channel].ps2_mode |= 0xc; - } - return; - - case 0xc: /*Clear FF*/ - dma16_wp = 0; - return; - - case 0xd: /*Master clear*/ - dma16_wp = 0; - dma_m |= 0xf0; - return; - - case 0xf: /*Mask write*/ - dma_m = (dma_m & 0x0f) | ((val & 0xf) << 4); - return; - } -} - - -void dma_page_write(uint16_t addr, uint8_t val, void *priv) -{ - dmapages[addr & 0xf] = val; - switch (addr & 0xf) - { - case 1: - dma[2].page = (AT) ? val : val & 0xf; - dma[2].ab = (dma[2].ab & 0xffff) | (dma[2].page << 16); - dma[2].ac = (dma[2].ac & 0xffff) | (dma[2].page << 16); - break; - case 2: - dma[3].page = (AT) ? val : val & 0xf; - dma[3].ab = (dma[3].ab & 0xffff) | (dma[3].page << 16); - dma[3].ac = (dma[3].ac & 0xffff) | (dma[3].page << 16); - break; - case 3: - dma[1].page = (AT) ? val : val & 0xf; - dma[1].ab = (dma[1].ab & 0xffff) | (dma[1].page << 16); - dma[1].ac = (dma[1].ac & 0xffff) | (dma[1].page << 16); - break; - case 7: - dma[0].page = (AT) ? val : val & 0xf; - dma[0].ab = (dma[0].ab & 0xffff) | (dma[0].page << 16); - dma[0].ac = (dma[0].ac & 0xffff) | (dma[0].page << 16); - break; - case 0x9: - dma[6].page = val & 0xfe; - dma[6].ab = (dma[6].ab & 0x1ffff) | (dma[6].page << 16); - dma[6].ac = (dma[6].ac & 0x1ffff) | (dma[6].page << 16); - break; - case 0xa: - dma[7].page = val & 0xfe; - dma[7].ab = (dma[7].ab & 0x1ffff) | (dma[7].page << 16); - dma[7].ac = (dma[7].ac & 0x1ffff) | (dma[7].page << 16); - break; - case 0xb: - dma[5].page = val & 0xfe; - dma[5].ab = (dma[5].ab & 0x1ffff) | (dma[5].page << 16); - dma[5].ac = (dma[5].ac & 0x1ffff) | (dma[5].page << 16); - break; - case 0xf: - dma[4].page = val & 0xfe; - dma[4].ab = (dma[4].ab & 0x1ffff) | (dma[4].page << 16); - dma[4].ac = (dma[4].ac & 0x1ffff) | (dma[4].page << 16); - break; - } -} - -uint8_t dma_page_read(uint16_t addr, void *priv) -{ - return dmapages[addr & 0xf]; -} - -void dma_init(void) -{ - io_sethandler(0x0000, 0x0010, dma_read, NULL, NULL, dma_write, NULL, NULL, NULL); - io_sethandler(0x0080, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); - dma_ps2.is_ps2 = 0; -} - -void dma16_init(void) -{ - io_sethandler(0x00C0, 0x0020, dma16_read, NULL, NULL, dma16_write, NULL, NULL, NULL); - io_sethandler(0x0088, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); -} - -void dma_alias_set(void) -{ - io_sethandler(0x0090, 0x0010, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); -} - -void dma_alias_remove(void) -{ - io_removehandler(0x0090, 0x0010, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); -} - -void dma_alias_remove_piix(void) -{ - io_removehandler(0x0090, 0x0001, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); - io_removehandler(0x0094, 0x0003, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); - io_removehandler(0x0098, 0x0001, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); - io_removehandler(0x009C, 0x0003, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL); -} - -void ps2_dma_init(void) -{ - io_sethandler(0x0018, 0x0001, dma_ps2_read, NULL, NULL, dma_ps2_write, NULL, NULL, NULL); - io_sethandler(0x001a, 0x0001, dma_ps2_read, NULL, NULL, dma_ps2_write, NULL, NULL, NULL); - dma_ps2.is_ps2 = 1; -} - - -uint8_t _dma_read(uint32_t addr) -{ - uint8_t temp = mem_readb_phys_dma(addr); - return temp; -} - -void _dma_write(uint32_t addr, uint8_t val) -{ - mem_writeb_phys_dma(addr, val); - mem_invalidate_range(addr, addr); -} - -int dma_channel_read(int channel) -{ - dma_t *dma_c = &dma[channel]; - uint16_t temp; - int tc = 0; - - if (channel < 4) - { - if (dma_command & 0x04) - return DMA_NODATA; - } - else - { - if (dma16_command & 0x04) - return DMA_NODATA; - } - - if (!AT) - refreshread(); - - if (dma_m & (1 << channel)) - return DMA_NODATA; - if ((dma_c->mode & 0xC) != 8) - return DMA_NODATA; - - if (!dma_c->size) - { - temp = _dma_read(dma_c->ac); - - if (dma_c->mode & 0x20) - { - if (dma_ps2.is_ps2) - dma_c->ac--; - else - dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac - 1) & 0xffff); - } - else - { - if (dma_ps2.is_ps2) - dma_c->ac++; - else - dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac + 1) & 0xffff); - } - } - else - { - temp = _dma_read(dma_c->ac) | - (_dma_read(dma_c->ac + 1) << 8); - - if (dma_c->mode & 0x20) - { - if (dma_ps2.is_ps2) - dma_c->ac -= 2; - else - dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac - 2) & 0x1ffff); - } - else - { - if (dma_ps2.is_ps2) - dma_c->ac += 2; - else - dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac + 2) & 0x1ffff); - } - } - - dma_stat_rq |= (1 << channel); - - dma_c->cc--; - if (dma_c->cc < 0) - { - tc = 1; - if (dma_c->mode & 0x10) /*Auto-init*/ - { - dma_c->cc = dma_c->cb; - dma_c->ac = dma_c->ab; - } - else - dma_m |= (1 << channel); - dma_stat |= (1 << channel); - } - - if (tc) - return temp | DMA_OVER; - return temp; -} - -int dma_channel_write(int channel, uint16_t val) -{ - dma_t *dma_c = &dma[channel]; - - if (channel < 4) - { - if (dma_command & 0x04) - return DMA_NODATA; - } - else - { - if (dma16_command & 0x04) - return DMA_NODATA; - } - - if (!AT) - refreshread(); - - if (dma_m & (1 << channel)) - return DMA_NODATA; - if ((dma_c->mode & 0xC) != 4) - return DMA_NODATA; - - if (!dma_c->size) - { - _dma_write(dma_c->ac, val); - - if (dma_c->mode & 0x20) - { - if (dma_ps2.is_ps2) - dma_c->ac--; - else - dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac - 1) & 0xffff); - } - else - { - if (dma_ps2.is_ps2) - dma_c->ac++; - else - dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac + 1) & 0xffff); - } - } - else - { - _dma_write(dma_c->ac, val); - _dma_write(dma_c->ac + 1, val >> 8); - - if (dma_c->mode & 0x20) - { - if (dma_ps2.is_ps2) - dma_c->ac -= 2; - else - dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac - 2) & 0x1ffff); - } - else - { - if (dma_ps2.is_ps2) - dma_c->ac += 2; - else - dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac + 2) & 0x1ffff); - } - } - - dma_stat_rq |= (1 << channel); - - dma_c->cc--; - if (dma_c->cc < 0) - { - if (dma_c->mode & 0x10) /*Auto-init*/ - { - dma_c->cc = dma_c->cb; - dma_c->ac = dma_c->ab; - } - else - dma_m |= (1 << channel); - dma_stat |= (1 << channel); - } - - if (dma_m & (1 << channel)) - return DMA_OVER; - - return 0; -} - -static void dma_ps2_run(int channel) -{ - dma_t *dma_c = &dma[channel]; - - switch (dma_c->ps2_mode & DMA_PS2_XFER_MASK) - { - case DMA_PS2_XFER_MEM_TO_IO: - do - { - if (!dma_c->size) - { - uint8_t temp = _dma_read(dma_c->ac); - outb(dma_c->io_addr, temp); - - if (dma_c->ps2_mode & DMA_PS2_DEC2) - dma_c->ac--; - else - dma_c->ac++; - } - else - { - uint16_t temp = _dma_read(dma_c->ac) | (_dma_read(dma_c->ac + 1) << 8); - outw(dma_c->io_addr, temp); - - if (dma_c->ps2_mode & DMA_PS2_DEC2) - dma_c->ac -= 2; - else - dma_c->ac += 2; - } - - dma_stat_rq |= (1 << channel); - dma_c->cc--; - } while (dma_c->cc > 0); - - dma_stat |= (1 << channel); - break; - - case DMA_PS2_XFER_IO_TO_MEM: - do - { - if (!dma_c->size) - { - uint8_t temp = inb(dma_c->io_addr); - _dma_write(dma_c->ac, temp); - - if (dma_c->ps2_mode & DMA_PS2_DEC2) - dma_c->ac--; - else - dma_c->ac++; - } - else - { - uint16_t temp = inw(dma_c->io_addr); - _dma_write(dma_c->ac, temp & 0xff); - _dma_write(dma_c->ac + 1, temp >> 8); - - if (dma_c->ps2_mode & DMA_PS2_DEC2) - dma_c->ac -= 2; - else - dma_c->ac += 2; - } - - dma_stat_rq |= (1 << channel); - dma_c->cc--; - } while (dma_c->cc > 0); - - ps2_cache_clean(); - dma_stat |= (1 << channel); - break; - - default: /*Memory verify*/ - do - { - if (!dma_c->size) - { - if (dma_c->ps2_mode & DMA_PS2_DEC2) - dma_c->ac--; - else - dma_c->ac++; - } - else - { - if (dma_c->ps2_mode & DMA_PS2_DEC2) - dma_c->ac -= 2; - else - dma_c->ac += 2; - } - - dma_stat_rq |= (1 << channel); - dma->cc--; - } while (dma->cc > 0); - - dma_stat |= (1 << channel); - break; - } -} - -int dma_mode(int channel) -{ - if (channel < 4) - { - return dma[channel].mode; - } - else - { - return dma[channel & 3].mode; + if (dma_c->mode & 0x20) { + if (dma_ps2.is_ps2) + dma_c->ac -= 2; + else + dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac - 2) & 0x1ffff); + } else { + if (dma_ps2.is_ps2) + dma_c->ac += 2; + else + dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac + 2) & 0x1ffff); } + } + + dma_stat_rq |= (1 << channel); + + dma_c->cc--; + if (dma_c->cc < 0) { + tc = 1; + if (dma_c->mode & 0x10) { /*Auto-init*/ + dma_c->cc = dma_c->cb; + dma_c->ac = dma_c->ab; + } else + dma_m |= (1 << channel); + dma_stat |= (1 << channel); + } + + if (tc) + return(temp | DMA_OVER); + + return(temp); } + +int +dma_channel_write(int channel, uint16_t val) +{ + dma_t *dma_c = &dma[channel]; + + if (channel < 4) { + if (dma_command & 0x04) + return(DMA_NODATA); + } else { + if (dma16_command & 0x04) + return(DMA_NODATA); + } + + if (! AT) + refreshread(); + + if (dma_m & (1 << channel)) + return(DMA_NODATA); + if ((dma_c->mode & 0xC) != 4) + return(DMA_NODATA); + + if (! dma_c->size) { + _dma_write(dma_c->ac, val & 0xff); + + if (dma_c->mode & 0x20) { + if (dma_ps2.is_ps2) + dma_c->ac--; + else + dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac - 1) & 0xffff); + } else { + if (dma_ps2.is_ps2) + dma_c->ac++; + else + dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac + 1) & 0xffff); + } + } else { + _dma_write(dma_c->ac, val & 0xff); + _dma_write(dma_c->ac + 1, val >> 8); + + if (dma_c->mode & 0x20) { + if (dma_ps2.is_ps2) + dma_c->ac -= 2; + else + dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac - 2) & 0x1ffff); + dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac - 2) & 0x1ffff); + } else { + if (dma_ps2.is_ps2) + dma_c->ac += 2; + else + dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac + 2) & 0x1ffff); + } + } + + dma_stat_rq |= (1 << channel); + + dma_c->cc--; + if (dma_c->cc < 0) { + if (dma_c->mode & 0x10) { /*Auto-init*/ + dma_c->cc = dma_c->cb; + dma_c->ac = dma_c->ab; + } else + dma_m |= (1 << channel); + dma_stat |= (1 << channel); + } + + if (dma_m & (1 << channel)) + return(DMA_OVER); + + return(0); +} + + +static void +dma_ps2_run(int channel) +{ + dma_t *dma_c = &dma[channel]; + + switch (dma_c->ps2_mode & DMA_PS2_XFER_MASK) { + case DMA_PS2_XFER_MEM_TO_IO: + do { + if (! dma_c->size) { + uint8_t temp = _dma_read(dma_c->ac); + + outb(dma_c->io_addr, temp); + + if (dma_c->ps2_mode & DMA_PS2_DEC2) + dma_c->ac--; + else + dma_c->ac++; + } else { + uint16_t temp = _dma_read(dma_c->ac) | (_dma_read(dma_c->ac + 1) << 8); + + outw(dma_c->io_addr, temp); + + if (dma_c->ps2_mode & DMA_PS2_DEC2) + dma_c->ac -= 2; + else + dma_c->ac += 2; + } + + dma_stat_rq |= (1 << channel); + dma_c->cc--; + } while (dma_c->cc > 0); + + dma_stat |= (1 << channel); + break; + + case DMA_PS2_XFER_IO_TO_MEM: + do { + if (! dma_c->size) { + uint8_t temp = inb(dma_c->io_addr); + + _dma_write(dma_c->ac, temp); + + if (dma_c->ps2_mode & DMA_PS2_DEC2) + dma_c->ac--; + else + dma_c->ac++; + } else { + uint16_t temp = inw(dma_c->io_addr); + + _dma_write(dma_c->ac, temp & 0xff); + _dma_write(dma_c->ac + 1, temp >> 8); + + if (dma_c->ps2_mode & DMA_PS2_DEC2) + dma_c->ac -= 2; + else + dma_c->ac += 2; + } + + dma_stat_rq |= (1 << channel); + dma_c->cc--; + } while (dma_c->cc > 0); + + ps2_cache_clean(); + dma_stat |= (1 << channel); + break; + + default: /*Memory verify*/ + do { + if (! dma_c->size) { + if (dma_c->ps2_mode & DMA_PS2_DEC2) + dma_c->ac--; + else + dma_c->ac++; + } else { + if (dma_c->ps2_mode & DMA_PS2_DEC2) + dma_c->ac -= 2; + else + dma_c->ac += 2; + } + + dma_stat_rq |= (1 << channel); + dma->cc--; + } while (dma->cc > 0); + + dma_stat |= (1 << channel); + break; + + } +} + + +int +dma_mode(int channel) +{ + if (channel < 4) + return(dma[channel].mode); + else + return(dma[channel & 3].mode); +} + + /* DMA Bus Master Page Read/Write */ -void DMAPageRead(uint32_t PhysAddress, uint8_t *DataRead, uint32_t TotalSize) +void +DMAPageRead(uint32_t PhysAddress, uint8_t *DataRead, uint32_t TotalSize) { - int i = 0; + uint32_t i = 0; #if 0 - memcpy(DataRead, &ram[PhysAddress], TotalSize); + memcpy(DataRead, &ram[PhysAddress], TotalSize); #else - for (i = 0; i < TotalSize; i++) - DataRead[i] = mem_readb_phys_dma(PhysAddress + i); + for (i = 0; i < TotalSize; i++) + DataRead[i] = mem_readb_phys_dma(PhysAddress + i); #endif } -void DMAPageWrite(uint32_t PhysAddress, const uint8_t *DataWrite, uint32_t TotalSize) + +void +DMAPageWrite(uint32_t PhysAddress, const uint8_t *DataWrite, uint32_t TotalSize) { - int i = 0; + uint32_t i = 0; #if 0 - mem_invalidate_range(PhysAddress, PhysAddress + TotalSize - 1); - memcpy(&ram[PhysAddress], DataWrite, TotalSize); + mem_invalidate_range(PhysAddress, PhysAddress + TotalSize - 1); + memcpy(&ram[PhysAddress], DataWrite, TotalSize); #else - for (i = 0; i < TotalSize; i++) - mem_writeb_phys_dma(PhysAddress + i, DataWrite[i]); + for (i = 0; i < TotalSize; i++) + mem_writeb_phys_dma(PhysAddress + i, DataWrite[i]); - mem_invalidate_range(PhysAddress, PhysAddress + TotalSize - 1); + mem_invalidate_range(PhysAddress, PhysAddress + TotalSize - 1); #endif } diff --git a/src/dma.h b/src/dma.h index 223994a17..32f90c4e7 100644 --- a/src/dma.h +++ b/src/dma.h @@ -1,20 +1,40 @@ /* - * 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. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * - * Implementation of the Intel DMA controllers. + * Definitions for the Intel DMA controller. * - * Version: @(#)dma.h 1.0.5 2018/03/11 + * Version: @(#)dma.h 1.0.2 2018/03/12 * - * Authors: Sarah Walker, + * Authors: Fred N. van Kempen, * Miran Grca, + * Sarah Walker, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #ifndef EMU_DMA_H # define EMU_DMA_H @@ -25,25 +45,25 @@ #define DMA_VERIFY 0x20000 -/*DMA*/ -typedef struct dma_t -{ - uint32_t ab, ac; - uint16_t cb; - int cc; - int wp; - uint8_t m, mode; - uint8_t page; - uint8_t stat, stat_rq; - uint8_t command; - int size; - - uint8_t ps2_mode; - uint8_t arb_level; - uint16_t io_addr; +typedef struct { + uint32_t ab, ac; + uint16_t cb; + int cc; + int wp; + uint8_t m, mode; + uint8_t page; + uint8_t stat, stat_rq; + uint8_t command; + int size; + + uint8_t ps2_mode; + uint8_t arb_level; + uint16_t io_addr; } dma_t; -extern dma_t dma[8]; + +extern dma_t dma[8]; + extern void dma_init(void); extern void dma16_init(void); diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index ab4e8c4ef..2b4e38514 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -9,7 +9,7 @@ * Implementation of the NEC uPD-765 and compatible floppy disk * controller. * - * Version: @(#)fdc.c 1.0.5 2018/03/16 + * Version: @(#)fdc.c 1.0.9 2018/06/12 * * Authors: Miran Grca, * Sarah Walker, @@ -133,10 +133,14 @@ fdc_log(const char *fmt, ...) uint8_t fdc_ps1_525(void) { - if ((romset == ROM_IBMPS1_2011) && fdd_is_525(current_drive)) - return 0x40; - else - return 0; + switch (romset) { + case ROM_IBMPS1_2011: + case ROM_IBMPS1_2121: + case ROM_IBMPS1_2121_ISA: + return fdd_is_525(current_drive) ? 0x40 : 0x00; + default: + return 0x00; + } } @@ -151,6 +155,7 @@ fdc_ctrl_reset(void *p) fdc->lock = 0; fdc->head = 0; fdc->abort = 0; + fdc->step = 0; if (!(fdc->flags & FDC_FLAG_AT)) fdc->rate = 2; } @@ -214,7 +219,7 @@ static void fdc_rate(fdc_t *fdc, int drive); int fdc_get_perp(fdc_t *fdc) { - if (!(fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_PCJR) || (fdc->flags & FDC_FLAG_PS1)) + if (!(fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_PCJR)) return 0; return fdc->perp; @@ -226,7 +231,7 @@ fdc_get_gap2(fdc_t *fdc, int drive) { int auto_gap2 = 22; - if (!(fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_PCJR) || (fdc->flags & FDC_FLAG_PS1)) + if (!(fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_PCJR)) return 22; if (fdc->perp & 3) @@ -608,7 +613,7 @@ void fdc_seek(fdc_t *fdc, int drive, int params) { fdd_seek(real_drive(fdc, drive), params); - fdc->time = 5000 * TIMER_SHIFT; + fdc->time = 5000LL * (1 << TIMER_SHIFT); fdc->stat |= (1 << fdc->drive); } @@ -715,7 +720,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) case 1: return; case 2: /*DOR*/ - if ((fdc->flags & FDC_FLAG_PCJR)) { + if (fdc->flags & FDC_FLAG_PCJR) { if ((fdc->dor & 0x40) && !(val & 0x40)) { fdc->watchdog_timer = 1000LL * TIMER_USEC; fdc->watchdog_count = 1000LL; @@ -728,6 +733,10 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->interrupt = -1; ui_sb_update_icon(SB_FLOPPY | 0, 0); fdc_ctrl_reset(fdc); + fdd_changed[0] = 1; + fdd_changed[1] = 1; + fdd_changed[2] = 1; + fdd_changed[3] = 1; } if (!fdd_get_flags(0)) val &= 0xfe; @@ -793,6 +802,8 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->perp &= 0xfc; fdc_ctrl_reset(fdc); } + /* if (fdc->flags & FDC_FLAG_PS1) + fdc->rate = val & 0x03; */ return; case 5: /*Command register*/ if ((fdc->stat & 0xf0) == 0xb0) { @@ -935,7 +946,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc_callback(fdc); break; case 0x12: /*Set perpendicular mode*/ - if ((fdc->flags & FDC_FLAG_AT) && !(fdc->flags & FDC_FLAG_PCJR) && !(fdc->flags & FDC_FLAG_PS1)) { + if ((fdc->flags & FDC_FLAG_AT) && !(fdc->flags & FDC_FLAG_PCJR)) { fdc->pnum=0; fdc->ptot=1; fdc->stat |= 0x90; @@ -981,6 +992,10 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->read_track_sector.id.h = fdc->params[2]; fdc->read_track_sector.id.r = 1; fdc->read_track_sector.id.n = fdc->params[4]; + if ((fdc->head & 0x01) && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) { + fdc_noidam(fdc); + return; + } fdd_readsector(real_drive(fdc, fdc->drive), SECTOR_FIRST, fdc->params[1], fdc->head, fdc->rate, fdc->params[4]); break; case 3: /*Specify*/ @@ -1006,12 +1021,20 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) case 5: /*Write data*/ case 9: /*Write deleted data*/ fdc_io_command_phase1(fdc, 1); + if ((fdc->head & 0x01) && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) { + fdc_noidam(fdc); + return; + } fdd_writesector(real_drive(fdc, fdc->drive), fdc->sector, fdc->params[1], fdc->head, fdc->rate, fdc->params[4]); break; case 0x11: /*Scan equal*/ case 0x19: /*Scan low or equal*/ case 0x1D: /*Scan high or equal*/ fdc_io_command_phase1(fdc, 1); + if ((fdc->head & 0x01) && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) { + fdc_noidam(fdc); + return; + } fdd_comparesector(real_drive(fdc, fdc->drive), fdc->sector, fdc->params[1], fdc->head, fdc->rate, fdc->params[4]); break; case 0x16: /*Verify*/ @@ -1021,6 +1044,10 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) case 0xC: /*Read deleted data*/ fdc_io_command_phase1(fdc, 0); fdc_log("Reading sector (drive %i) (%i) (%i %i %i %i) (%i %i %i)\n", fdc->drive, fdc->params[0], fdc->params[1], fdc->params[2], fdc->params[3], fdc->params[4], fdc->params[5], fdc->params[6], fdc->params[7]); + if ((fdc->head & 0x01) && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) { + fdc_noidam(fdc); + return; + } if (((dma_mode(2) & 0x0C) == 0x00) && !(fdc->flags & FDC_FLAG_PCJR) && fdc->dma) { /* DMA is in verify mode, treat this like a VERIFY command. */ fdc_log("Verify-mode read!\n"); @@ -1054,7 +1081,8 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) if ((real_drive(fdc, fdc->drive) != 1) || fdc->drv2en) fdc_seek(fdc, fdc->drive, -fdc->max_track); fdc_log("Recalibrating...\n"); - fdc->time = 5000LL; + fdc->time = 5000LL * (1 << TIMER_SHIFT); + fdc->step = fdc->seek_dir = 1; break; case 0x0d: /*Format*/ fdc_rate(fdc, fdc->drive); @@ -1098,14 +1126,17 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) if (fdc->params[1]) { if (fdc->command & 0x40) { /* Relative seek inwards. */ + fdc->seek_dir = 0; fdc_seek(fdc, fdc->drive, fdc->params[1]); fdc->pcn[fdc->params[0] & 3] += fdc->params[1]; } else { /* Relative seek outwards. */ + fdc->seek_dir = 1; fdc_seek(fdc, fdc->drive, -fdc->params[1]); fdc->pcn[fdc->params[0] & 3] -= fdc->params[1]; } - fdc->time = 5000LL; + fdc->time = 5000LL * (1 << TIMER_SHIFT); + fdc->step = 1; } else { fdc->st0 = 0x20 | (fdc->params[0] & 7); fdc->interrupt = -3; @@ -1125,9 +1156,14 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) timer_update_outstanding(); break; } + if (fdc->params[1] > fdc->pcn[fdc->params[0] & 3]) + fdc->seek_dir = 0; + else + fdc->seek_dir = 1; fdc_seek(fdc, fdc->drive, fdc->params[1] - fdc->pcn[fdc->params[0] & 3]); fdc->pcn[fdc->params[0] & 3] = fdc->params[1]; - fdc->time = 5000LL; + fdc->time = 5000LL * (1 << TIMER_SHIFT); + fdc->step = 1; fdc_log("fdc->time = %i\n", fdc->time); } break; @@ -1154,7 +1190,9 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) case 7: if (!(fdc->flags & FDC_FLAG_AT)) return; - fdc->rate=val&3; + fdc->rate = val & 0x03; + if (fdc->flags & FDC_FLAG_PS1) + fdc->noprec = !!(val & 0x04); return; } } @@ -1171,24 +1209,58 @@ fdc_read(uint16_t addr, void *priv) switch (addr&7) { case 0: /* STA */ - ret = 0xff; + if (fdc->flags & FDC_FLAG_PS1) { + drive = real_drive(fdc, fdc->dor & 3); + ret = 0x00; + /* TODO: + Bit 2: INDEX (best return always 0 as it goes by very fast) + Bit 6: DRQ + */ + if (writeprot[drive]) /* WRITEPROT */ + ret |= 0x01; + if (fdc->seek_dir) /* nDIRECTION */ + ret |= 0x02; + if (!fdd_get_head(drive)) /* nHDSEL */ + ret |= 0x08; + if (fdd_track0(drive)) /* TRK0 */ + ret |= 0x10; + if (fdc->step) /* STEP */ + ret |= 0x20; + if (fdc->fintr || fdc->reset_stat) /* INTR */ + ret |= 0x80; + } else + ret = 0xff; break; case 1: /* STB */ - if (is486) - return 0xff; - drive = real_drive(fdc, fdc->dor & 3); - if (!fdc->enable_3f1) - ret = 0xff; - ret = 0x70; - if (drive) - ret &= ~0x40; - else - ret &= ~0x20; + if (fdc->flags & FDC_FLAG_PS1) { + drive = real_drive(fdc, fdc->dor & 3); + ret = 0x00; + /* -Drive 2 Installed */ + if (!fdd_get_type(1)) + ret |= 80; + /* -Drive Select 1,0 */ + if (drive) + ret |= 0x20; + else + ret |= 0x40; + } else { + if (is486) + return 0xff; + drive = real_drive(fdc, fdc->dor & 3); + if (!fdc->enable_3f1) + ret = 0xff; - if (fdc->dor & 0x10) - ret |= 1; - if (fdc->dor & 0x20) - ret |= 2; + ret = 0x70; + if (drive) + ret &= ~0x40; + else + ret &= ~0x20; + + if (fdc->dor & 0x10) + ret |= 1; + if (fdc->dor & 0x20) + ret |= 2; + } break; case 2: ret = fdc->dor; @@ -1252,13 +1324,27 @@ fdc_read(uint16_t addr, void *priv) break; case 7: /*Disk change*/ drive = real_drive(fdc, fdc->dor & 3); - if (fdc->dor & (0x10 << drive)) - ret = (fdd_changed[drive] || drive_empty[drive])?0x80:0; - else - ret = 0; - if (fdc->flags & FDC_FLAG_DISKCHG_ACTLOW) /*PC2086/3086 seem to reverse this bit*/ - ret ^= 0x80; - ret |= 0x01; + + if (fdc->flags & FDC_FLAG_PS1) { + if (fdc->dor & (0x10 << drive)) { + ret = (fdd_changed[drive] || drive_empty[drive]) ? 0x00 : 0x80; + ret |= (fdc->dor & 0x08); + ret |= (fdc->noprec << 2); + ret |= (fdc->rate & 0x03); + } else + ret = 0x00; + } else { + if (fdc->dor & (0x10 << drive)) + ret = (fdd_changed[drive] || drive_empty[drive]) ? 0x80 : 0x00; + else + ret = 0x00; + if (fdc->flags & FDC_FLAG_DISKCHG_ACTLOW) /*PC2086/3086 seem to reverse this bit*/ + ret ^= 0x80; + + ret |= 0x01; + } + + fdc->step = 0; break; default: ret = 0xFF; @@ -1271,7 +1357,8 @@ static void fdc_poll_common_finish(fdc_t *fdc, int compare, int st5) { fdc_int(fdc); - fdc->fintr = 0; + if (!(fdc->flags & FDC_FLAG_PS1)) + fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; fdc->res[5] = st5; @@ -1376,7 +1463,9 @@ fdc_callback(void *priv) fdc->inread = 1; return; case 4: /*Sense drive status*/ - fdc->res[10] = (fdc->params[0] & 7) | 0x28; + fdc->res[10] = (fdc->params[0] & 7) | 0x20; + if (fdd_is_double_sided(real_drive(fdc, fdc->drive))) + fdc->res[10] |= 0x08; if ((real_drive(fdc, fdc->drive) != 1) || fdc->drv2en) { if (fdd_track0(real_drive(fdc, fdc->drive))) fdc->res[10] |= 0x10; @@ -1468,10 +1557,14 @@ fdc_callback(void *priv) fdc_poll_readwrite_finish(fdc, compare); return; } - if ((fdc->command & 0x80) && (fdd_get_head(real_drive(fdc, fdc->drive)) == 0)) { + if ((fdd_get_head(real_drive(fdc, fdc->drive)) == 0)) { fdc->sector = 1; fdc->head |= 1; fdd_set_head(real_drive(fdc, fdc->drive), 1); + if (!fdd_is_double_sided(real_drive(fdc, fdc->drive))) { + fdc_noidam(fdc); + return; + } } } else if (fdc->sector < fdc->params[5]) fdc->sector++; @@ -1530,7 +1623,8 @@ fdc_callback(void *priv) } else { fdc->interrupt = -2; fdc_int(fdc); - fdc->fintr = 0; + if (!(fdc->flags & FDC_FLAG_PS1)) + fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->drive; fdc->res[5] = fdc->res[6] = 0; @@ -1612,9 +1706,12 @@ fdc_error(fdc_t *fdc, int st5, int st6) fdc->time = 0LL; fdc_int(fdc); - fdc->fintr = 0; + if (!(fdc->flags & FDC_FLAG_PS1)) + fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = 0x40 | (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; + if (fdc->head && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) + fdc->st0 |= 0x08; fdc->res[5] = st5; fdc->res[6] = st6; fdc_log("FDC Error: %02X %02X %02X\n", fdc->res[4], fdc->res[5], fdc->res[6]); @@ -1977,7 +2074,10 @@ fdc_reset(void *priv) fdc_update_is_nsc(fdc, 0); fdc_update_enh_mode(fdc, 0); - fdc_update_densel_polarity(fdc, 1); + if (fdc->flags & FDC_FLAG_PS1) + fdc_update_densel_polarity(fdc, 0); + else + fdc_update_densel_polarity(fdc, 1); fdc_update_densel_force(fdc, 0); fdc_update_rwc(fdc, 0, default_rwc); fdc_update_rwc(fdc, 1, default_rwc); @@ -1992,7 +2092,7 @@ fdc_reset(void *priv) fdc->fifo = 0; fdc->tfifo = 1; - if ((fdc->flags & FDC_FLAG_PCJR)) { + if (fdc->flags & FDC_FLAG_PCJR) { fdc->dma = 0; fdc->specify[1] = 1; } else { @@ -2082,7 +2182,7 @@ const device_t fdc_xt_device = { fdc_init, fdc_close, fdc_reset, - NULL, NULL, NULL, NULL + NULL, NULL, NULL }; const device_t fdc_pcjr_device = { @@ -2092,7 +2192,7 @@ const device_t fdc_pcjr_device = { fdc_init, fdc_close, fdc_reset, - NULL, NULL, NULL, NULL + NULL, NULL, NULL }; const device_t fdc_at_device = { @@ -2102,7 +2202,7 @@ const device_t fdc_at_device = { fdc_init, fdc_close, fdc_reset, - NULL, NULL, NULL, NULL + NULL, NULL, NULL }; const device_t fdc_at_actlow_device = { @@ -2112,7 +2212,7 @@ const device_t fdc_at_actlow_device = { fdc_init, fdc_close, fdc_reset, - NULL, NULL, NULL, NULL + NULL, NULL, NULL }; const device_t fdc_at_ps1_device = { @@ -2122,7 +2222,7 @@ const device_t fdc_at_ps1_device = { fdc_init, fdc_close, fdc_reset, - NULL, NULL, NULL, NULL + NULL, NULL, NULL }; const device_t fdc_at_smc_device = { @@ -2132,7 +2232,7 @@ const device_t fdc_at_smc_device = { fdc_init, fdc_close, fdc_reset, - NULL, NULL, NULL, NULL + NULL, NULL, NULL }; const device_t fdc_at_winbond_device = { @@ -2142,7 +2242,7 @@ const device_t fdc_at_winbond_device = { fdc_init, fdc_close, fdc_reset, - NULL, NULL, NULL, NULL + NULL, NULL, NULL }; const device_t fdc_at_nsc_device = { @@ -2152,5 +2252,5 @@ const device_t fdc_at_nsc_device = { fdc_init, fdc_close, fdc_reset, - NULL, NULL, NULL, NULL + NULL, NULL, NULL }; diff --git a/src/floppy/fdc.h b/src/floppy/fdc.h index 0d540e918..dbc3fdd0a 100644 --- a/src/floppy/fdc.h +++ b/src/floppy/fdc.h @@ -9,7 +9,7 @@ * Implementation of the NEC uPD-765 and compatible floppy disk * controller. * - * Version: @(#)fdc.h 1.0.3 2018/03/17 + * Version: @(#)fdc.h 1.0.4 2018/04/12 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -70,6 +70,8 @@ typedef struct { int abort; int format_state, format_n; int tc, written; + int step, seek_dir; + int noprec; int data_ready, inread; int bitcell_period, enh_mode; diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index 006a6ed87..0508d5343 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -8,7 +8,7 @@ * * Implementation of the floppy drive emulation. * - * Version: @(#)fdd.c 1.0.5 2018/03/16 + * Version: @(#)fdd.c 1.0.9 2018/05/13 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -36,10 +36,12 @@ * Boston, MA 02111-1307 * USA. */ -#include +#include #include +#include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../machine/machine.h" #include "../mem.h" @@ -114,6 +116,7 @@ static const struct {L"BIN", img_load, img_close, -1}, {L"CQ", img_load, img_close, -1}, {L"CQM", img_load, img_close, -1}, + {L"DDI", img_load, img_close, -1}, {L"DSK", img_load, img_close, -1}, {L"FDI", fdi_load, fdi_close, -1}, {L"FDF", img_load, img_close, -1}, @@ -226,6 +229,27 @@ static const struct } }; +#ifdef ENABLE_FDD_LOG +int fdd_do_log = ENABLE_FDD_LOG; +#endif + + +static void +fdd_log(const char *fmt, ...) +{ +#ifdef ENABLE_FDD_LOG + va_list ap; + + if (fdd_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + char *fdd_getname(int type) { return (char *)drive_types[type].name; @@ -357,7 +381,7 @@ int fdd_can_read_medium(int drive) { int hole = fdd_hole(drive); - hole = 1 << (hole + 3); + hole = 1 << (hole + 4); return (drive_types[fdd[drive].type].flags & hole) ? 1 : 0; } @@ -409,11 +433,16 @@ int fdd_is_double_sided(int drive) void fdd_set_head(int drive, int head) { - fdd[drive].head = head; + if (head && !fdd_is_double_sided(drive)) + fdd[drive].head = 0; + else + fdd[drive].head = head; } int fdd_get_head(int drive) { + if (!fdd_is_double_sided(drive)) + return 0; return fdd[drive].head; } @@ -455,7 +484,7 @@ void fdd_load(int drive, wchar_t *fn) wchar_t *p; FILE *f; - pclog("FDD: loading drive %d with '%ls'\n", drive, fn); + fdd_log("FDD: loading drive %d with '%ls'\n", drive, fn); if (!fn) return; p = plat_get_extension(fn); @@ -480,7 +509,7 @@ void fdd_load(int drive, wchar_t *fn) } c++; } - pclog("FDD: could not load '%ls' %s\n",fn,p); + fdd_log("FDD: could not load '%ls' %s\n",fn,p); drive_empty[drive] = 1; fdd_set_head(drive, 0); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); @@ -489,13 +518,12 @@ void fdd_load(int drive, wchar_t *fn) void fdd_close(int drive) { - pclog("FDD: closing drive %d\n", drive); + fdd_log("FDD: closing drive %d\n", drive); if (loaders[driveloaders[drive]].close) loaders[driveloaders[drive]].close(drive); drive_empty[drive] = 1; fdd_set_head(drive, 0); floppyfns[drive][0] = 0; - d86f_destroy(drive); drives[drive].hole = NULL; drives[drive].poll = NULL; drives[drive].seek = NULL; @@ -506,6 +534,7 @@ void fdd_close(int drive) drives[drive].format = NULL; drives[drive].byteperiod = NULL; drives[drive].stop = NULL; + d86f_destroy(drive); ui_sb_update_icon_state(drive, 1); } diff --git a/src/floppy/fdd.h b/src/floppy/fdd.h index 7610cee46..70414804f 100644 --- a/src/floppy/fdd.h +++ b/src/floppy/fdd.h @@ -8,7 +8,7 @@ * * Definitions for the floppy drive emulation. * - * Version: @(#)fdd.h 1.0.3 2018/03/17 + * Version: @(#)fdd.h 1.0.4 2018/04/12 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -135,7 +135,6 @@ extern void fdd_format(int drive, int side, int density, uint8_t fill); extern int fdd_hole(int drive); extern double fdd_byteperiod(int drive); extern void fdd_stop(int drive); -extern int fdd_empty(int drive); extern void fdd_set_rate(int drive, int drvden, int rate); extern int motorspin; diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index ded25f291..60df4620e 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -10,7 +10,7 @@ * data in the form of FM/MFM-encoded transitions) which also * forms the core of the emulator's floppy disk emulation. * - * Version: @(#)fdd_86f.c 1.0.7 2018/03/19 + * Version: @(#)fdd_86f.c 1.0.10 2018/06/12 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -46,6 +46,7 @@ #define HAVE_STDARG_H #include "../86box.h" #include "../config.h" +#include "../device.h" #include "../dma.h" #include "../nvr.h" #include "../random.h" @@ -54,7 +55,9 @@ #include "fdd.h" #include "fdc.h" #include "fdd_86f.h" +#ifdef D86F_COMPRESS #include "lzf/lzf.h" +#endif /* @@ -225,7 +228,9 @@ typedef struct { uint16_t current_bit[2]; int cur_track; uint32_t error_condition; +#ifdef D86F_COMPRESS int is_compressed; +#endif int id_found; wchar_t original_file_name[2048]; uint8_t *filebuf; @@ -1430,9 +1435,9 @@ d86f_read_sector_id(int drive, int side, int match) dev->state = STATE_IDLE; fdc_finishread(d86f_fdc); fdc_headercrcerror(d86f_fdc); - } else if (dev->state == STATE_0A_READ_ID) { + } else if (dev->state == STATE_0A_READ_ID) dev->state--; - } else { + else { dev->error_condition |= 1; /* Mark that there was an ID CRC error. */ dev->state++; } @@ -1544,6 +1549,7 @@ d86f_read_sector_data(int drive, int side) if (dev->data_find.bits_obtained) { if (!(dev->data_find.bits_obtained & 15)) { /* We've got a byte. */ + d86f_log("86F: We've got a byte.\n"); if (dev->data_find.bytes_obtained < sector_len) { data = decodefm(drive, dev->last_word[side]); if (dev->state == STATE_11_SCAN_DATA) { @@ -1554,33 +1560,18 @@ d86f_read_sector_data(int drive, int side) if (dev->data_find.bytes_obtained < d86f_get_data_len(drive)) { if (dev->state != STATE_16_VERIFY_DATA) { read_status = fdc_data(d86f_fdc, data); - if (read_status == -1) { + if (read_status == -1) dev->dma_over++; - } } } } fdd_calccrc(data, &(dev->calc_crc)); - } else if (dev->data_find.bytes_obtained < crc_pos) { + } else if (dev->data_find.bytes_obtained < crc_pos) dev->track_crc.bytes[(dev->data_find.bytes_obtained - sector_len) ^ 1] = decodefm(drive, dev->last_word[side]); - } dev->data_find.bytes_obtained++; if (dev->data_find.bytes_obtained == (crc_pos + fdc_get_gap(d86f_fdc))) { /* We've got the data. */ - if (dev->dma_over > 1) { - dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; - dev->error_condition = 0; - dev->state = STATE_IDLE; - fdc_finishread(d86f_fdc); - fdc_overrun(d86f_fdc); - - d86f_get_bit(drive, side); - - dev->data_find.bits_obtained++; - return; - } - if ((dev->calc_crc.word != dev->track_crc.word) && (dev->state != STATE_02_READ_DATA)) { d86f_log("86F: Data CRC error: %04X != %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword); dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; @@ -1595,15 +1586,14 @@ d86f_read_sector_data(int drive, int side) fdc_track_finishread(d86f_fdc, dev->error_condition); } else { /* CRC is valid. */ + d86f_log("86F: Data CRC OK: %04X != %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword); dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; dev->error_condition = 0; - if (dev->state == STATE_11_SCAN_DATA) { - dev->state = STATE_IDLE; + dev->state = STATE_IDLE; + if (dev->state == STATE_11_SCAN_DATA) fdc_sector_finishcompare(d86f_fdc, (dev->satisfying_bytes == ((128 << ((uint32_t) dev->last_sector.id.n)) - 1)) ? 1 : 0); - } else { - dev->state = STATE_IDLE; + else fdc_sector_finishread(d86f_fdc); - } } } } @@ -1699,17 +1689,6 @@ d86f_write_sector_data(int drive, int side, int mfm, uint16_t am) dev->data_find.bytes_obtained++; if (dev->data_find.bytes_obtained == (crc_pos + fdc_get_gap(d86f_fdc))) { - if (dev->dma_over > 1) { - dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; - dev->error_condition = 0; - dev->state = STATE_IDLE; - fdc_finishread(d86f_fdc); - fdc_overrun(d86f_fdc); - - dev->data_find.bits_obtained++; - return; - } - /* We've written the data. */ dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; dev->error_condition = 0; @@ -2138,15 +2117,6 @@ d86f_turbo_read(int drive, int side) } } - if (dev->dma_over > 1) { - dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; - dev->error_condition = 0; - dev->state = STATE_IDLE; - fdc_finishread(d86f_fdc); - fdc_overrun(d86f_fdc); - return; - } - if (dev->turbo_pos >= (128 << dev->last_sector.id.n)) { /* CRC is valid. */ dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; @@ -2568,7 +2538,8 @@ d86f_poll(int drive) fdc_wrongcylinder(d86f_fdc); else fdc_nosector(d86f_fdc); - } + } else + fdc_nosector(d86f_fdc); } else { fdc_noidam(d86f_fdc); } @@ -3084,9 +3055,11 @@ d86f_writeback(int drive) d86f_t *dev = d86f[drive]; uint8_t header[32]; int header_size; +#ifdef D86F_COMPRESS uint32_t len; int ret = 0; FILE *cf; +#endif header_size = d86f_header_size(drive); if (! dev->f) return; @@ -3100,6 +3073,7 @@ d86f_writeback(int drive) d86f_write_tracks(drive, &dev->f, NULL); +#ifdef D86F_COMPRESS if (dev->is_compressed) { /* The image is compressed. */ @@ -3128,6 +3102,7 @@ d86f_writeback(int drive) free(dev->outbuf); free(dev->filebuf); } +#endif } @@ -3182,7 +3157,8 @@ d86f_readsector(int drive, int sector, int track, int side, int rate, int sector int ret = 0; ret = d86f_common_command(drive, sector, track, side, rate, sector_size); - if (! ret) return; + if (! ret) + return; if (sector == SECTOR_FIRST) dev->state = STATE_02_SPIN_TO_INDEX; @@ -3450,13 +3426,15 @@ d86f_export(int drive, wchar_t *fn) void d86f_load(int drive, wchar_t *fn) { - wchar_t temp_file_name[2048]; d86f_t *dev = d86f[drive]; uint32_t magic = 0; uint32_t len = 0; - uint16_t temp = 0; int i = 0, j = 0; +#ifdef D86F_COMPRESS + wchar_t temp_file_name[2048]; + uint16_t temp = 0; FILE *tf; +#endif d86f_unregister(drive); @@ -3533,8 +3511,12 @@ d86f_load(int drive, wchar_t *fn) } } +#ifdef D86F_COMPRESS dev->is_compressed = (magic == 0x66623638) ? 1 : 0; if ((len < 51052) && !dev->is_compressed) { +#else + if (len < 51052) { +#endif /* File too small, abort. */ fclose(dev->f); dev->f = NULL; @@ -3567,6 +3549,7 @@ d86f_load(int drive, wchar_t *fn) } #endif +#ifdef D86F_COMPRESS if (dev->is_compressed) { memcpy(temp_file_name, drive ? nvr_path(L"TEMP$$$1.$$$") : nvr_path(L"TEMP$$$0.$$$"), 256); memcpy(dev->original_file_name, fn, (wcslen(fn) << 1) + 2); @@ -3613,15 +3596,17 @@ d86f_load(int drive, wchar_t *fn) dev->f = plat_fopen(temp_file_name, L"rb+"); } +#endif if (dev->disk_flags & 0x100) { /* Zoned disk. */ d86f_log("86F: Disk is zoned (Apple or Sony)\n"); fclose(dev->f); dev->f = NULL; - if (dev->is_compressed) { +#ifdef D86F_COMPRESS + if (dev->is_compressed) plat_remove(temp_file_name); - } +#endif memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); free(dev); return; @@ -3632,8 +3617,10 @@ d86f_load(int drive, wchar_t *fn) d86f_log("86F: Disk is fixed-RPM but zone type is not 0\n"); fclose(dev->f); dev->f = NULL; +#ifdef D86F_COMPRESS if (dev->is_compressed) plat_remove(temp_file_name); +#endif memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); free(dev); return; @@ -3648,9 +3635,11 @@ d86f_load(int drive, wchar_t *fn) fclose(dev->f); dev->f = NULL; +#ifdef D86F_COMPRESS if (dev->is_compressed) dev->f = plat_fopen(temp_file_name, L"rb"); - else + else +#endif dev->f = plat_fopen(fn, L"rb"); } @@ -3735,9 +3724,14 @@ d86f_load(int drive, wchar_t *fn) d86f_common_handlers(drive); drives[drive].format = d86f_format; +#ifdef D86F_COMPRESS d86f_log("86F: Disk is %scompressed and does%s have surface description data\n", dev->is_compressed ? "" : "not ", d86f_has_surface_desc(drive) ? "" : " not"); +#else + d86f_log("86F: Disk does%s have surface description data\n", + d86f_has_surface_desc(drive) ? "" : " not"); +#endif } @@ -3795,8 +3789,10 @@ d86f_close(int drive) fclose(dev->f); dev->f = NULL; } +#ifdef D86F_COMPRESS if (dev->is_compressed) plat_remove(temp_file_name); +#endif } diff --git a/src/floppy/fdd_fdi.c b/src/floppy/fdd_fdi.c index b780fa233..a8c7a0dce 100644 --- a/src/floppy/fdd_fdi.c +++ b/src/floppy/fdd_fdi.c @@ -9,7 +9,7 @@ * Implementation of the FDI floppy stream image format * interface to the FDI2RAW module. * - * Version: @(#)fdd_fdi.c 1.0.2 2018/03/17 + * Version: @(#)fdd_fdi.c 1.0.3 2018/04/29 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -37,11 +37,13 @@ * Boston, MA 02111-1307 * USA. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../plat.h" #include "fdd.h" @@ -71,6 +73,27 @@ static fdi_t *fdi[FDD_NUM]; static fdc_t *fdi_fdc; +#ifdef ENABLE_FDI_LOG +int fdi_do_log = ENABLE_FDI_LOG; +#endif + + +static void +fdi_log(const char *fmt, ...) +{ +#ifdef ENABLE_FDI_LOG + va_list ap; + + if (fdi_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + static uint16_t disk_flags(int drive) { @@ -339,7 +362,7 @@ fdi_load(int drive, wchar_t *fn) header[25] = 0; if (strcmp(header, "Formatted Disk Image file") != 0) { /* This is a Japanese FDI file. */ - pclog("fdi_load(): Japanese FDI file detected, redirecting to IMG loader\n"); + fdi_log("fdi_load(): Japanese FDI file detected, redirecting to IMG loader\n"); fclose(dev->f); free(dev); img_load(drive, fn); @@ -372,7 +395,7 @@ fdi_load(int drive, wchar_t *fn) drives[drive].seek = fdi_seek; - pclog("Loaded as FDI\n"); + fdi_log("Loaded as FDI\n"); } diff --git a/src/floppy/fdd_imd.c b/src/floppy/fdd_imd.c index 49eca94e4..9e690a479 100644 --- a/src/floppy/fdd_imd.c +++ b/src/floppy/fdd_imd.c @@ -8,7 +8,7 @@ * * Implementation of the IMD floppy image format. * - * Version: @(#)fdd_imd.c 1.0.6 2018/03/19 + * Version: @(#)fdd_imd.c 1.0.7 2018/04/29 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -34,11 +34,13 @@ * Boston, MA 02111-1307 * USA. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../plat.h" #include "fdd.h" @@ -82,6 +84,27 @@ static imd_t *imd[FDD_NUM]; static fdc_t *imd_fdc; +#ifdef ENABLE_IMD_LOG +int imd_do_log = ENABLE_IMD_LOG; +#endif + + +static void +imd_log(const char *fmt, ...) +{ +#ifdef ENABLE_IMD_LOG + va_list ap; + + if (imd_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + static uint32_t get_raw_tsize(int side_flags, int slower_rpm) { @@ -617,13 +640,13 @@ imd_load(int drive, wchar_t *fn) fseek(dev->f, 0, SEEK_SET); fread(&magic, 1, 4, dev->f); if (magic != 0x20444D49) { - pclog("IMD: Not a valid ImageDisk image\n"); + imd_log("IMD: Not a valid ImageDisk image\n"); fclose(dev->f); free(dev);; memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); return; } else { - pclog("IMD: Valid ImageDisk image\n"); + imd_log("IMD: Valid ImageDisk image\n"); } fseek(dev->f, 0, SEEK_END); @@ -635,24 +658,24 @@ imd_load(int drive, wchar_t *fn) buffer2 = strchr(buffer, 0x1A); if (buffer2 == NULL) { - pclog("IMD: No ASCII EOF character\n"); + imd_log("IMD: No ASCII EOF character\n"); fclose(dev->f); free(dev); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); return; } else { - pclog("IMD: ASCII EOF character found at offset %08X\n", buffer2 - buffer); + imd_log("IMD: ASCII EOF character found at offset %08X\n", buffer2 - buffer); } buffer2++; if ((buffer2 - buffer) == fsize) { - pclog("IMD: File ends after ASCII EOF character\n"); + imd_log("IMD: File ends after ASCII EOF character\n"); fclose(dev->f); free(dev); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); return; } else { - pclog("IMD: File continues after ASCII EOF character\n"); + imd_log("IMD: File continues after ASCII EOF character\n"); } dev->start_offs = (buffer2 - buffer); @@ -691,7 +714,7 @@ imd_load(int drive, wchar_t *fn) dev->tracks[track][side].side_flags |= 0x20; if ((dev->tracks[track][side].side_flags & 7) == 1) dev->tracks[track][side].side_flags |= 0x20; - /* pclog("Side flags for (%02i)(%01i): %02X\n", track, side, dev->tracks[track][side].side_flags); */ + /* imd_log("Side flags for (%02i)(%01i): %02X\n", track, side, dev->tracks[track][side].side_flags); */ dev->tracks[track][side].is_present = 1; dev->tracks[track][side].file_offs = (buffer2 - buffer); memcpy(dev->tracks[track][side].params, buffer2, 5); @@ -766,7 +789,7 @@ imd_load(int drive, wchar_t *fn) dev->disk_flags |= (3 << 5); if ((raw_tsize - track_total + (mfm ? 146 : 73)) < (minimum_gap3 + minimum_gap4)) { /* If we can't fit the sectors with a reasonable minimum gap even at 2% slower RPM, abort. */ - pclog("IMD: Unable to fit the %i sectors in a track\n", track_spt); + imd_log("IMD: Unable to fit the %i sectors in a track\n", track_spt); fclose(dev->f); free(dev); imd[drive] = NULL; @@ -779,7 +802,7 @@ imd_load(int drive, wchar_t *fn) } else if (gap3_sizes[converted_rate][sector_size][track_spt] != 0x00) dev->tracks[track][side].gap3_len = gap3_sizes[converted_rate][sector_size][track_spt]; - /* pclog("GAP3 length for (%02i)(%01i): %i bytes\n", track, side, dev->tracks[track][side].gap3_len); */ + /* imd_log("GAP3 length for (%02i)(%01i): %i bytes\n", track, side, dev->tracks[track][side].gap3_len); */ if (track > dev->track_count) dev->track_count = track; @@ -797,7 +820,7 @@ imd_load(int drive, wchar_t *fn) if (dev->sides == 2) dev->disk_flags |= 8; - /* pclog("%i tracks, %i sides\n", dev->track_count, dev->sides); */ + /* imd_log("%i tracks, %i sides\n", dev->track_count, dev->sides); */ /* Attach this format to the D86F engine. */ d86f_handler[drive].disk_flags = disk_flags; diff --git a/src/floppy/fdd_img.c b/src/floppy/fdd_img.c index ce9dd4837..09bd27655 100644 --- a/src/floppy/fdd_img.c +++ b/src/floppy/fdd_img.c @@ -13,7 +13,7 @@ * re-merged with the other files. Much of it is generic to * all formats. * - * Version: @(#)fdd_img.c 1.0.5 2018/03/17 + * Version: @(#)fdd_img.c 1.0.8 2018/05/09 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,11 +41,13 @@ * Boston, MA 02111-1307 * USA. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../config.h" #include "../plat.h" @@ -297,6 +299,27 @@ const int gap3_sizes[5][8][48] = { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }; +#ifdef ENABLE_IMG_LOG +int img_do_log = ENABLE_IMG_LOG; +#endif + + +static void +img_log(const char *fmt, ...) +{ +#ifdef ENABLE_IMG_LOG + va_list ap; + + if (img_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + /* Generic */ static int sector_size_code(int sector_size) @@ -605,7 +628,7 @@ img_load(int drive, wchar_t *fn) uint8_t bpb_mid; /* Media type ID. */ uint8_t bpb_sectors; uint8_t bpb_sides; - uint8_t fdi, cqm, fdf; + uint8_t cqm, ddi, fdf, fdi; uint16_t comment_len = 0; int16_t block_len = 0; uint32_t cur_pos = 0; @@ -646,13 +669,19 @@ img_load(int drive, wchar_t *fn) writeprot[drive] = 1; fwriteprot[drive] = writeprot[drive]; - fdi = cqm = 0; + cqm = ddi = fdf = fdi = 0; dev->interleave = dev->skew = 0; + if (! wcscasecmp(ext, L"DDI")) { + ddi = 1; + dev->base = 0x2400; + } else + dev->base = 0; + if (! wcscasecmp(ext, L"FDI")) { /* This is a Japanese FDI image, so let's read the header */ - pclog("img_load(): File is a Japanese FDI image...\n"); + img_log("img_load(): File is a Japanese FDI image...\n"); fseek(dev->f, 0x10, SEEK_SET); (void)fread(&bpb_bps, 1, 2, dev->f); fseek(dev->f, 0x0C, SEEK_SET); @@ -689,7 +718,7 @@ img_load(int drive, wchar_t *fn) if ((first_byte == 0x1A) && (second_byte == 'F') && (third_byte == 'D') && (fourth_byte == 'F')) { /* This is a FDF image. */ - pclog("img_load(): File is a FDF image...\n"); + img_log("img_load(): File is a FDF image...\n"); fwriteprot[drive] = writeprot[drive] = 1; fclose(dev->f); dev->f = plat_fopen(fn, L"rb"); @@ -711,10 +740,10 @@ img_load(int drive, wchar_t *fn) /* Skip first 3 bytes - their meaning is unknown to us but could be a checksum. */ first_byte = fgetc(dev->f); fread(&track_bytes, 1, 2, dev->f); - pclog("Block header: %02X %04X ", first_byte, track_bytes); + img_log("Block header: %02X %04X ", first_byte, track_bytes); /* Read the length of encoded data block. */ fread(&track_bytes, 1, 2, dev->f); - pclog("%04X\n", track_bytes); + img_log("%04X\n", track_bytes); } if (feof(dev->f)) break; @@ -765,10 +794,10 @@ img_load(int drive, wchar_t *fn) /* Skip first 3 bytes - their meaning is unknown to us but could be a checksum. */ first_byte = fgetc(dev->f); fread(&track_bytes, 1, 2, dev->f); - pclog("Block header: %02X %04X ", first_byte, track_bytes); + img_log("Block header: %02X %04X ", first_byte, track_bytes); /* Read the length of encoded data block. */ fread(&track_bytes, 1, 2, dev->f); - pclog("%04X\n", track_bytes); + img_log("%04X\n", track_bytes); } if (feof(dev->f)) break; @@ -829,7 +858,7 @@ img_load(int drive, wchar_t *fn) if (((first_byte == 'C') && (second_byte == 'Q')) || ((first_byte == 'c') && (second_byte == 'q'))) { - pclog("img_load(): File is a CopyQM image...\n"); + img_log("img_load(): File is a CopyQM image...\n"); fwriteprot[drive] = writeprot[drive] = 1; fclose(dev->f); dev->f = plat_fopen(fn, L"rb"); @@ -894,7 +923,7 @@ img_load(int drive, wchar_t *fn) } } } - pclog("Finished reading CopyQM image data\n"); + img_log("Finished reading CopyQM image data\n"); cqm = 1; dev->disk_at_once = 1; @@ -903,16 +932,20 @@ img_load(int drive, wchar_t *fn) } else { dev->disk_at_once = 0; /* Read the BPB */ - pclog("img_load(): File is a raw image...\n"); - fseek(dev->f, 0x0B, SEEK_SET); + if (ddi) { + img_log("img_load(): File is a DDI image...\n"); + fwriteprot[drive] = writeprot[drive] = 1; + } else + img_log("img_load(): File is a raw image...\n"); + fseek(dev->f, dev->base + 0x0B, SEEK_SET); fread(&bpb_bps, 1, 2, dev->f); - fseek(dev->f, 0x13, SEEK_SET); + fseek(dev->f, dev->base + 0x13, SEEK_SET); fread(&bpb_total, 1, 2, dev->f); - fseek(dev->f, 0x15, SEEK_SET); + fseek(dev->f, dev->base + 0x15, SEEK_SET); bpb_mid = fgetc(dev->f); - fseek(dev->f, 0x18, SEEK_SET); + fseek(dev->f, dev->base + 0x18, SEEK_SET); bpb_sectors = fgetc(dev->f); - fseek(dev->f, 0x1A, SEEK_SET); + fseek(dev->f, dev->base + 0x1A, SEEK_SET); bpb_sides = fgetc(dev->f); cqm = 0; @@ -920,16 +953,19 @@ img_load(int drive, wchar_t *fn) fseek(dev->f, -1, SEEK_END); size = ftell(dev->f) + 1; + if (ddi) + size -= 0x2400; jump_if_fdf: - dev->base = 0; + if (!ddi) + dev->base = 0; fdi = 0; } dev->sides = 2; dev->sector_size = 2; - pclog("BPB reports %i sides and %i bytes per sector (%i sectors total)\n", + img_log("BPB reports %i sides and %i bytes per sector (%i sectors total)\n", bpb_sides, bpb_bps, bpb_total); guess = (bpb_sides < 1); @@ -1056,7 +1092,7 @@ jump_if_fdf: dev->sectors = 42; dev->tracks = 86; } else { - pclog("Image is bigger than can fit on an ED floppy, ejecting...\n"); + img_log("Image is bigger than can fit on an ED floppy, ejecting...\n"); fclose(dev->f); free(dev); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); @@ -1106,13 +1142,13 @@ jump_if_fdf: dev->dmf = 0; } - pclog("Image parameters: bit rate 300: %f, temporary rate: %i, hole: %i, DMF: %i, XDF type: %i\n", bit_rate_300, temp_rate, dev->disk_flags >> 1, dev->dmf, dev->xdf_type); + img_log("Image parameters: bit rate 300: %f, temporary rate: %i, hole: %i, DMF: %i, XDF type: %i\n", bit_rate_300, temp_rate, dev->disk_flags >> 1, dev->dmf, dev->xdf_type); break; } } if (temp_rate == 0xFF) { - pclog("Image is bigger than can fit on an ED floppy, ejecting...\n"); + img_log("Image is bigger than can fit on an ED floppy, ejecting...\n"); fclose(dev->f); free(dev); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); @@ -1125,7 +1161,7 @@ jump_if_fdf: else dev->gap3_size = gap3_sizes[temp_rate][dev->sector_size][dev->sectors]; if (! dev->gap3_size) { - pclog("ERROR: Floppy image of unknown format was inserted into drive %c:!\n", drive + 0x41); + img_log("ERROR: Floppy image of unknown format was inserted into drive %c:!\n", drive + 0x41); fclose(dev->f); free(dev); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); @@ -1149,7 +1185,7 @@ jump_if_fdf: dev->is_cqm = cqm; - pclog("Disk flags: %i, track flags: %i\n", + img_log("Disk flags: %i, track flags: %i\n", dev->disk_flags, dev->track_flags); /* Set up the drive unit. */ diff --git a/src/floppy/fdd_json.c b/src/floppy/fdd_json.c index d3ae99ac9..c56bbd80d 100644 --- a/src/floppy/fdd_json.c +++ b/src/floppy/fdd_json.c @@ -8,7 +8,7 @@ * * Implementation of the PCjs JSON floppy image format. * - * Version: @(#)fdd_json.c 1.0.4 2018/03/17 + * Version: @(#)fdd_json.c 1.0.5 2018/04/29 * * Author: Fred N. van Kempen, * @@ -44,11 +44,13 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../plat.h" #include "fdd.h" @@ -104,6 +106,27 @@ typedef struct { static json_t *images[FDD_NUM]; +#ifdef ENABLE_JSON_LOG +int json_do_log = ENABLE_JSON_LOG; +#endif + + +static void +json_log(const char *fmt, ...) +{ +#ifdef ENABLE_JSON_LOG + va_list ap; + + if (json_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + static void handle(json_t *dev, char *name, char *str) { @@ -182,7 +205,7 @@ handle(json_t *dev, char *name, char *str) static int unexpect(int c, int state, int level) { - pclog("JSON: Unexpected '%c' in state %d/%d.\n", c, state, level); + json_log("JSON: Unexpected '%c' in state %d/%d.\n", c, state, level); return(-1); } @@ -196,7 +219,7 @@ load_image(json_t *dev) char *ptr; if (dev->f == NULL) { - pclog("JSON: no file loaded!\n"); + json_log("JSON: no file loaded!\n"); return(0); } @@ -373,7 +396,7 @@ json_seek(int drive, int track) int interleave_type; if (dev->f == NULL) { - pclog("JSON: seek: no file loaded!\n"); + json_log("JSON: seek: no file loaded!\n"); return; } @@ -536,7 +559,7 @@ json_load(int drive, wchar_t *fn) /* Load all sectors from the image file. */ if (! load_image(dev)) { - pclog("JSON: failed to initialize\n"); + json_log("JSON: failed to initialize\n"); (void)fclose(dev->f); free(dev); images[drive] = NULL; @@ -544,7 +567,7 @@ json_load(int drive, wchar_t *fn) return; } - pclog("JSON(%d): %ls (%i tracks, %i sides, %i sectors)\n", + json_log("JSON(%d): %ls (%i tracks, %i sides, %i sectors)\n", drive, fn, dev->tracks, dev->sides, dev->spt[0][0]); /* @@ -601,7 +624,7 @@ json_load(int drive, wchar_t *fn) } if (temp_rate == 0xff) { - pclog("JSON: invalid image (temp_rate=0xff)\n"); + json_log("JSON: invalid image (temp_rate=0xff)\n"); (void)fclose(dev->f); dev->f = NULL; free(dev); @@ -622,7 +645,7 @@ json_load(int drive, wchar_t *fn) dev->gap3_len = fdd_get_gap3_size(temp_rate,sec->size,dev->spt[0][0]); if (! dev->gap3_len) { - pclog("JSON: image of unknown format was inserted into drive %c:!\n", + json_log("JSON: image of unknown format was inserted into drive %c:!\n", 'C'+drive); (void)fclose(dev->f); dev->f = NULL; @@ -636,9 +659,9 @@ json_load(int drive, wchar_t *fn) if (temp_rate & 0x04) dev->track_flags |= 0x20; /* RPM */ - pclog(" disk_flags: 0x%02x, track_flags: 0x%02x, GAP3 length: %i\n", + json_log(" disk_flags: 0x%02x, track_flags: 0x%02x, GAP3 length: %i\n", dev->disk_flags, dev->track_flags, dev->gap3_len); - pclog(" bit rate 300: %.2f, temporary rate: %i, hole: %i, DMF: %i\n", + json_log(" bit rate 300: %.2f, temporary rate: %i, hole: %i, DMF: %i\n", bit_rate, temp_rate, (dev->disk_flags >> 1), dev->dmf); /* Set up handlers for 86F layer. */ diff --git a/src/floppy/fdd_td0.c b/src/floppy/fdd_td0.c index 8968694c8..f956e9421 100644 --- a/src/floppy/fdd_td0.c +++ b/src/floppy/fdd_td0.c @@ -8,7 +8,7 @@ * * Implementation of the Teledisk floppy image format. * - * Version: @(#)fdd_td0.c 1.0.5 2018/03/19 + * Version: @(#)fdd_td0.c 1.0.6 2018/04/29 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -46,11 +46,13 @@ * Boston, MA 02111-1307 * USA. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../plat.h" #include "fdd.h" @@ -218,6 +220,27 @@ static const uint8_t d_len[256] = { static td0_t *td0[FDD_NUM]; +#ifdef ENABLE_TD0_LOG +int td0_do_log = ENABLE_TD0_LOG; +#endif + + +static void +td0_log(const char *fmt, ...) +{ +#ifdef ENABLE_TD0_LOG + va_list ap; + + if (td0_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + static void fdd_image_read(int drive, char *buffer, uint32_t offset, uint32_t len) { @@ -611,7 +634,7 @@ td0_initialize(int drive) int i, j, k; if (dev->f == NULL) { - pclog("TD0: Attempted to initialize without loading a file first\n"); + td0_log("TD0: Attempted to initialize without loading a file first\n"); return(0); } @@ -619,12 +642,12 @@ td0_initialize(int drive) file_size = ftell(dev->f); if (file_size < 12) { - pclog("TD0: File is too small to even contain the header\n"); + td0_log("TD0: File is too small to even contain the header\n"); return(0); } if (file_size > TD0_MAX_BUFSZ) { - pclog("TD0: File exceeds the maximum size\n"); + td0_log("TD0: File exceeds the maximum size\n"); return(0); } @@ -633,13 +656,13 @@ td0_initialize(int drive) head_count = header[9]; if (header[0] == 't') { - pclog("TD0: File is compressed\n"); + td0_log("TD0: File is compressed\n"); disk_decode.fdd_file = dev->f; state_init_Decode(&disk_decode); disk_decode.fdd_file_offset = 12; state_Decode(&disk_decode, dev->imagebuf, TD0_MAX_BUFSZ); } else { - pclog("TD0: File is uncompressed\n"); + td0_log("TD0: File is uncompressed\n"); fseek(dev->f, 12, SEEK_SET); fread(dev->imagebuf, 1, file_size - 12, dev->f); } @@ -650,14 +673,14 @@ td0_initialize(int drive) track_spt = dev->imagebuf[offset]; if (track_spt == 255) { /* Empty file? */ - pclog("TD0: File has no tracks\n"); + td0_log("TD0: File has no tracks\n"); return(0); } density = (header[5] >> 1) & 3; if (density == 3) { - pclog("TD0: Unknown density\n"); + td0_log("TD0: Unknown density\n"); return(0); } @@ -725,7 +748,7 @@ td0_initialize(int drive) size = 128 << hs[3]; if ((total_size + size) >= TD0_MAX_BUFSZ) { - pclog("TD0: Processed buffer overflow\n"); + td0_log("TD0: Processed buffer overflow\n"); return(0); } @@ -735,7 +758,7 @@ td0_initialize(int drive) offset += 3; switch (hs[8]) { default: - pclog("TD0: Image uses an unsupported sector data encoding\n"); + td0_log("TD0: Image uses an unsupported sector data encoding\n"); return(0); case 0: @@ -803,7 +826,7 @@ td0_initialize(int drive) dev->disk_flags |= (3 << 5); if ((raw_tsize - track_size + (fm ? 73 : 146)) < (minimum_gap3 + minimum_gap4)) { /* If we can't fit the sectors with a reasonable minimum gap even at 2% slower RPM, abort. */ - pclog("TD0: Unable to fit the %i sectors in a track\n", track_spt); + td0_log("TD0: Unable to fit the %i sectors in a track\n", track_spt); return 0; } } @@ -814,7 +837,7 @@ td0_initialize(int drive) } if ((dev->disk_flags & 0x60) == 0x60) - pclog("TD0: Disk will rotate 2% below perfect RPM\n"); + td0_log("TD0: Disk will rotate 2% below perfect RPM\n"); dev->tracks = track_count + 1; @@ -836,7 +859,7 @@ td0_initialize(int drive) dev->current_side_flags[0] = dev->side_flags[0][0]; dev->current_side_flags[1] = dev->side_flags[0][1]; - pclog("TD0: File loaded: %i tracks, %i sides, disk flags: %02X, side flags: %02X, %02X, GAP3 length: %02X\n", dev->tracks, dev->sides, dev->disk_flags, dev->current_side_flags[0], dev->current_side_flags[1], dev->gap3_len); + td0_log("TD0: File loaded: %i tracks, %i sides, disk flags: %02X, side flags: %02X, %02X, GAP3 length: %02X\n", dev->tracks, dev->sides, dev->disk_flags, dev->current_side_flags[0], dev->current_side_flags[1], dev->gap3_len); return(1); } @@ -1136,13 +1159,13 @@ td0_load(int drive, wchar_t *fn) fwriteprot[drive] = writeprot[drive]; if (! dsk_identify(drive)) { - pclog("TD0: Not a valid Teledisk image\n"); + td0_log("TD0: Not a valid Teledisk image\n"); fclose(dev->f); dev->f = NULL; memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); return; } else { - pclog("TD0: Valid Teledisk image\n"); + td0_log("TD0: Valid Teledisk image\n"); } /* Allocate the processing buffers. */ @@ -1153,14 +1176,14 @@ td0_load(int drive, wchar_t *fn) memset(dev->processed_buf, 0x00, i); if (! td0_initialize(drive)) { - pclog("TD0: Failed to initialize\n"); + td0_log("TD0: Failed to initialize\n"); fclose(dev->f); free(dev->imagebuf); free(dev->processed_buf); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); return; } else { - pclog("TD0: Initialized successfully\n"); + td0_log("TD0: Initialized successfully\n"); } /* Attach this format to the D86F engine. */ diff --git a/src/floppy/fdi2raw.c b/src/floppy/fdi2raw.c index 0cb7ca4fd..dee8dbfdf 100644 --- a/src/floppy/fdi2raw.c +++ b/src/floppy/fdi2raw.c @@ -12,7 +12,7 @@ * addition of get_last_head and C++ callability by Thomas * Harte. * - * Version: @(#)fdi2raw.c 1.0.2 2018/03/12 + * Version: @(#)fdi2raw.c 1.0.3 2018/04/29 * * Authors: Toni Wilen, * and Vincent Joguin, @@ -41,8 +41,9 @@ * USA. */ #define STATIC_INLINE -#include +#include #include +#include #include #include #include @@ -53,6 +54,7 @@ #include "zfile.h"*/ /* ELSE */ #define xmalloc malloc +#define HAVE_STDARG_H #include "../86box.h" #include "fdi2raw.h" @@ -62,6 +64,27 @@ #undef VERBOSE +#ifdef ENABLE_FDI2RAW_LOG +int fdi2raw_do_log = ENABLE_FDI2RAW_LOG; +#endif + + +static void +fdi2raw_log(const char *fmt, ...) +{ +#ifdef ENABLE_FDI2RAW_LOG + va_list ap; + + if (fdi2raw_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + #ifdef DEBUG static char *datalog(uae_u8 *src, int len) { @@ -86,9 +109,6 @@ static char *datalog(uae_u8 *src, int len) static char *datalog(uae_u8 *src, int len) { return ""; } #endif -#define outlog pclog -#define debuglog pclog - static int fdi_allocated; #ifdef DEBUG static void fdi_free (void *p) @@ -333,13 +353,13 @@ static int decode_raw_track (FDI *fdi) /* unknown track */ static void zxx (FDI *fdi) { - outlog ("track %d: unknown track type 0x%02.2X\n", fdi->current_track, fdi->track_type); + fdi2raw_log("track %d: unknown track type 0x%02.2X\n", fdi->current_track, fdi->track_type); } /* unsupported track */ #if 0 static void zyy (FDI *fdi) { - outlog ("track %d: unsupported track type 0x%02.2X\n", fdi->current_track, fdi->track_type); + fdi2raw_log("track %d: unsupported track type 0x%02.2X\n", fdi->current_track, fdi->track_type); } #endif /* empty track */ @@ -351,17 +371,9 @@ static void track_empty (FDI *fdi) /* unknown sector described type */ static void dxx (FDI *fdi) { - outlog ("\ntrack %d: unknown sector described type 0x%02.2X\n", fdi->current_track, fdi->track_type); + fdi2raw_log("\ntrack %d: unknown sector described type 0x%02.2X\n", fdi->current_track, fdi->track_type); fdi->err = 1; } -/* unsupported sector described type */ -#if 0 -static void dyy (FDI *fdi) -{ - outlog ("\ntrack %d: unsupported sector described 0x%02.2X\n", fdi->current_track, fdi->track_type); - fdi->err = 1; -} -#endif /* add position of mfm sync bit */ static void add_mfm_sync_bit (FDI *fdi) { @@ -371,12 +383,12 @@ static void add_mfm_sync_bit (FDI *fdi) } fdi->mfmsync_buffer[fdi->mfmsync_offset++] = fdi->out; if (fdi->out == 0) { - outlog ("illegal position for mfm sync bit, offset=%d\n",fdi->out); + fdi2raw_log("illegal position for mfm sync bit, offset=%d\n",fdi->out); fdi->err = 1; } if (fdi->mfmsync_offset >= MAX_MFM_SYNC_BUFFER) { fdi->mfmsync_offset = 0; - outlog ("mfmsync buffer overflow\n"); + fdi2raw_log("mfmsync buffer overflow\n"); fdi->err = 1; } fdi->out++; @@ -397,7 +409,7 @@ static void bit_add (FDI *fdi, int bit) fdi->track_dst[BIT_BYTEOFFSET] |= (1 << BIT_BITOFFSET); fdi->out++; if (fdi->out >= MAX_DST_BUFFER * 8) { - outlog ("destination buffer overflow\n"); + fdi2raw_log("destination buffer overflow\n"); fdi->err = 1; fdi->out = 1; } @@ -412,13 +424,13 @@ static void bit_mfm_add (FDI *fdi, int bit) static void bit_drop_next (FDI *fdi) { if (fdi->nextdrop > 0) { - outlog("multiple bit_drop_next() called"); + fdi2raw_log("multiple bit_drop_next() called"); } else if (fdi->nextdrop < 0) { fdi->nextdrop = 0; - debuglog(":DNN:"); + fdi2raw_log(":DNN:"); return; } - debuglog(":DN:"); + fdi2raw_log(":DN:"); fdi->nextdrop = 1; } @@ -426,10 +438,10 @@ static void bit_drop_next (FDI *fdi) static void bit_dedrop (FDI *fdi) { if (fdi->nextdrop) { - outlog("bit_drop_next called before bit_dedrop"); + fdi2raw_log("bit_drop_next called before bit_dedrop"); } fdi->nextdrop = -1; - debuglog(":BDD:"); + fdi2raw_log(":BDD:"); } /* add one byte */ @@ -482,7 +494,7 @@ static void s08(FDI *fdi) int bytes = *fdi->track_src++; uae_u8 byte = *fdi->track_src++; if (bytes == 0) bytes = 256; - debuglog ("s08:len=%d,data=%02.2X",bytes,byte); + fdi2raw_log("s08:len=%d,data=%02.2X",bytes,byte); while(bytes--) byte_add (fdi, byte); } /* RLE MFM-decoded data */ @@ -492,7 +504,7 @@ static void s09(FDI *fdi) uae_u8 byte = *fdi->track_src++; if (bytes == 0) bytes = 256; bit_drop_next (fdi); - debuglog ("s09:len=%d,data=%02.2X",bytes,byte); + fdi2raw_log("s09:len=%d,data=%02.2X",bytes,byte); while(bytes--) byte_mfm_add (fdi, byte); } /* MFM-encoded data */ @@ -501,7 +513,7 @@ static void s0a(FDI *fdi) int i, bits = (fdi->track_src[0] << 8) | fdi->track_src[1]; uae_u8 b; fdi->track_src += 2; - debuglog ("s0a:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); + fdi2raw_log("s0a:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); while (bits >= 8) { byte_add (fdi, *fdi->track_src++); bits -= 8; @@ -521,7 +533,7 @@ static void s0b(FDI *fdi) int i, bits = ((fdi->track_src[0] << 8) | fdi->track_src[1]) + 65536; uae_u8 b; fdi->track_src += 2; - debuglog ("s0b:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); + fdi2raw_log("s0b:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); while (bits >= 8) { byte_add (fdi, *fdi->track_src++); bits -= 8; @@ -542,7 +554,7 @@ static void s0c(FDI *fdi) uae_u8 b; fdi->track_src += 2; bit_drop_next (fdi); - debuglog ("s0c:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); + fdi2raw_log("s0c:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); while (bits >= 8) { byte_mfm_add (fdi, *fdi->track_src++); bits -= 8; @@ -563,7 +575,7 @@ static void s0d(FDI *fdi) uae_u8 b; fdi->track_src += 2; bit_drop_next (fdi); - debuglog ("s0d:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); + fdi2raw_log("s0d:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); while (bits >= 8) { byte_mfm_add (fdi, *fdi->track_src++); bits -= 8; @@ -692,13 +704,13 @@ static int amiga_check_track (FDI *fdi) trackoffs = (id & 0xff00) >> 8; if (trackoffs + 1 > drvsec) { - outlog("illegal sector offset %d\n",trackoffs); + fdi2raw_log("illegal sector offset %d\n",trackoffs); ok = 0; mbuf = mbuf2; continue; } if ((id >> 24) != 0xff) { - outlog ("sector %d format type %02.2X?\n", trackoffs, id >> 24); + fdi2raw_log("sector %d format type %02.2X?\n", trackoffs, id >> 24); ok = 0; } chksum = odd ^ even; @@ -717,14 +729,14 @@ static int amiga_check_track (FDI *fdi) even = getmfmlong (mbuf + 2 * 2); mbuf += 4 * 2; if (((odd << 1) | even) != chksum) { - outlog("sector %d header crc error\n", trackoffs); + fdi2raw_log("sector %d header crc error\n", trackoffs); ok = 0; mbuf = mbuf2; continue; } - outlog("sector %d header crc ok\n", trackoffs); + fdi2raw_log("sector %d header crc ok\n", trackoffs); if (((id & 0x00ff0000) >> 16) != (uae_u32)fdi->current_track) { - outlog("illegal track number %d <> %d\n",fdi->current_track,(id & 0x00ff0000) >> 16); + fdi2raw_log("illegal track number %d <> %d\n",fdi->current_track,(id & 0x00ff0000) >> 16); ok++; mbuf = mbuf2; continue; @@ -747,14 +759,14 @@ static int amiga_check_track (FDI *fdi) } mbuf += 256 * 2; if (chksum) { - outlog("sector %d data checksum error\n",trackoffs); + fdi2raw_log("sector %d data checksum error\n",trackoffs); ok = 0; } else if (sectable[trackoffs]) { - outlog("sector %d already found?\n", trackoffs); + fdi2raw_log("sector %d already found?\n", trackoffs); mbuf = mbuf2; } else { - outlog("sector %d ok\n",trackoffs); - if (slabel) outlog("(non-empty sector header)\n"); + fdi2raw_log("sector %d ok\n",trackoffs); + if (slabel) fdi2raw_log("(non-empty sector header)\n"); sectable[trackoffs] = 1; secwritten++; if (trackoffs == 9) @@ -763,7 +775,7 @@ static int amiga_check_track (FDI *fdi) } for (i = 0; i < drvsec; i++) { if (!sectable[i]) { - outlog ("sector %d missing\n", i); + fdi2raw_log("sector %d missing\n", i); ok = 0; } } @@ -884,7 +896,7 @@ static void amiga_sector_header (FDI *fdi, uae_u8 *header, uae_u8 *data, int sec static void s20(FDI *fdi) { bit_drop_next (fdi); - debuglog ("s20:header=%s,data=%s", datalog(fdi->track_src, 4), datalog(fdi->track_src + 4, 16)); + fdi2raw_log("s20:header=%s,data=%s", datalog(fdi->track_src, 4), datalog(fdi->track_src + 4, 16)); amiga_sector_header (fdi, fdi->track_src, fdi->track_src + 4, 0, 0); fdi->track_src += 4 + 16; } @@ -892,7 +904,7 @@ static void s20(FDI *fdi) static void s21(FDI *fdi) { bit_drop_next (fdi); - debuglog ("s21:header=%s", datalog(fdi->track_src, 4)); + fdi2raw_log("s21:header=%s", datalog(fdi->track_src, 4)); amiga_sector_header (fdi, fdi->track_src, 0, 0, 0); fdi->track_src += 4; } @@ -900,14 +912,14 @@ static void s21(FDI *fdi) static void s22(FDI *fdi) { bit_drop_next (fdi); - debuglog("s22:sector=%d,untilgap=%d", fdi->track_src[0], fdi->track_src[1]); + fdi2raw_log("s22:sector=%d,untilgap=%d", fdi->track_src[0], fdi->track_src[1]); amiga_sector_header (fdi, 0, 0, fdi->track_src[0], fdi->track_src[1]); fdi->track_src += 2; } /* standard 512-byte, CRC-correct Amiga data */ static void s23(FDI *fdi) { - debuglog("s23:data=%s", datalog (fdi->track_src, 512)); + fdi2raw_log("s23:data=%s", datalog (fdi->track_src, 512)); amiga_data (fdi, fdi->track_src); fdi->track_src += 512; } @@ -915,7 +927,7 @@ static void s23(FDI *fdi) static void s24(FDI *fdi) { int shift = *fdi->track_src++; - debuglog("s24:shift=%d,data=%s", shift, datalog (fdi->track_src, 128 << shift)); + fdi2raw_log("s24:shift=%d,data=%s", shift, datalog (fdi->track_src, 128 << shift)); amiga_data_raw (fdi, fdi->track_src, 0, 128 << shift); fdi->track_src += 128 << shift; } @@ -923,7 +935,7 @@ static void s24(FDI *fdi) static void s25(FDI *fdi) { int shift = *fdi->track_src++; - debuglog("s25:shift=%d,crc=%s,data=%s", shift, datalog (fdi->track_src, 4), datalog (fdi->track_src + 4, 128 << shift)); + fdi2raw_log("s25:shift=%d,crc=%s,data=%s", shift, datalog (fdi->track_src, 4), datalog (fdi->track_src + 4, 128 << shift)); amiga_data_raw (fdi, fdi->track_src + 4, fdi->track_src, 128 << shift); fdi->track_src += 4 + (128 << shift); } @@ -931,7 +943,7 @@ static void s25(FDI *fdi) static void s26(FDI *fdi) { s21 (fdi); - debuglog("s26:data=%s", datalog (fdi->track_src, 512)); + fdi2raw_log("s26:data=%s", datalog (fdi->track_src, 512)); amiga_data (fdi, fdi->track_src); fdi->track_src += 512; } @@ -939,7 +951,7 @@ static void s26(FDI *fdi) static void s27(FDI *fdi) { s22 (fdi); - debuglog("s27:data=%s", datalog (fdi->track_src, 512)); + fdi2raw_log("s27:data=%s", datalog (fdi->track_src, 512)); amiga_data (fdi, fdi->track_src); fdi->track_src += 512; } @@ -1060,14 +1072,14 @@ static void s12(FDI *fdi) static void s13(FDI *fdi) { bit_drop_next (fdi); - debuglog ("s13:header=%s", datalog (fdi->track_src, 4)); + fdi2raw_log("s13:header=%s", datalog (fdi->track_src, 4)); ibm_sector_header (fdi, fdi->track_src, 0, -1, 1); fdi->track_src += 4; } /* standard mini-extended IBM sector header */ static void s14(FDI *fdi) { - debuglog ("s14:header=%s", datalog (fdi->track_src, 4)); + fdi2raw_log("s14:header=%s", datalog (fdi->track_src, 4)); ibm_sector_header (fdi, fdi->track_src, 0, -1, 0); fdi->track_src += 4; } @@ -1075,33 +1087,33 @@ static void s14(FDI *fdi) static void s15(FDI *fdi) { bit_drop_next (fdi); - debuglog ("s15:sector=%d", *fdi->track_src); + fdi2raw_log("s15:sector=%d", *fdi->track_src); ibm_sector_header (fdi, 0, 0, *fdi->track_src++, 1); } /* standard mini-short IBM sector header */ static void s16(FDI *fdi) { - debuglog ("s16:track=%d", *fdi->track_src); + fdi2raw_log("s16:track=%d", *fdi->track_src); ibm_sector_header (fdi, 0, 0, *fdi->track_src++, 0); } /* standard CRC-incorrect mini-extended IBM sector header */ static void s17(FDI *fdi) { - debuglog ("s17:header=%s,crc=%s", datalog (fdi->track_src, 4), datalog (fdi->track_src + 4, 2)); + fdi2raw_log("s17:header=%s,crc=%s", datalog (fdi->track_src, 4), datalog (fdi->track_src + 4, 2)); ibm_sector_header (fdi, fdi->track_src, fdi->track_src + 4, -1, 0); fdi->track_src += 4 + 2; } /* standard CRC-incorrect mini-short IBM sector header */ static void s18(FDI *fdi) { - debuglog ("s18:sector=%d,header=%s", *fdi->track_src, datalog (fdi->track_src + 1, 4)); + fdi2raw_log("s18:sector=%d,header=%s", *fdi->track_src, datalog (fdi->track_src + 1, 4)); ibm_sector_header (fdi, 0, fdi->track_src + 1, *fdi->track_src, 0); fdi->track_src += 1 + 4; } /* standard 512-byte CRC-correct IBM data */ static void s19(FDI *fdi) { - debuglog ("s19:data=%s", datalog (fdi->track_src , 512)); + fdi2raw_log("s19:data=%s", datalog (fdi->track_src , 512)); ibm_data (fdi, fdi->track_src, 0, 512); fdi->track_src += 512; } @@ -1109,7 +1121,7 @@ static void s19(FDI *fdi) static void s1a(FDI *fdi) { int shift = *fdi->track_src++; - debuglog ("s1a:shift=%d,data=%s", shift, datalog (fdi->track_src , 128 << shift)); + fdi2raw_log("s1a:shift=%d,data=%s", shift, datalog (fdi->track_src , 128 << shift)); ibm_data (fdi, fdi->track_src, 0, 128 << shift); fdi->track_src += 128 << shift; } @@ -1117,7 +1129,7 @@ static void s1a(FDI *fdi) static void s1b(FDI *fdi) { int shift = *fdi->track_src++; - debuglog ("s1b:shift=%d,crc=%s,data=%s", shift, datalog (fdi->track_src + (128 << shift), 2), datalog (fdi->track_src , 128 << shift)); + fdi2raw_log("s1b:shift=%d,crc=%s,data=%s", shift, datalog (fdi->track_src + (128 << shift), 2), datalog (fdi->track_src , 128 << shift)); ibm_data (fdi, fdi->track_src, fdi->track_src + (128 << shift), 128 << shift); fdi->track_src += (128 << shift) + 2; } @@ -1323,25 +1335,25 @@ static int handle_sectors_described_track (FDI *fdi) fdi->index_offset = get_u32(fdi->track_src); fdi->index_offset >>= 8; fdi->track_src += 3; - outlog ("sectors_described, index offset: %d\n",fdi->index_offset); + fdi2raw_log("sectors_described, index offset: %d\n",fdi->index_offset); do { fdi->track_type = *fdi->track_src++; - outlog ("%06.6X %06.6X %02.2X:",fdi->track_src - start_src + 0x200, fdi->out/8, fdi->track_type); + fdi2raw_log("%06.6X %06.6X %02.2X:",fdi->track_src - start_src + 0x200, fdi->out/8, fdi->track_type); oldout = fdi->out; decode_sectors_described_track[fdi->track_type](fdi); - outlog(" %d\n", fdi->out - oldout); + fdi2raw_log(" %d\n", fdi->out - oldout); oldout = fdi->out; if (fdi->out < 0 || fdi->err) { - outlog ("\nin %d bytes, out %d bits\n", fdi->track_src - fdi->track_src_buffer, fdi->out); + fdi2raw_log("\nin %d bytes, out %d bits\n", fdi->track_src - fdi->track_src_buffer, fdi->out); return -1; } if (fdi->track_src - fdi->track_src_buffer >= fdi->track_src_len) { - outlog ("source buffer overrun, previous type: %02.2X\n", fdi->track_type); + fdi2raw_log("source buffer overrun, previous type: %02.2X\n", fdi->track_type); return -1; } } while (fdi->track_type != 0xff); - outlog("\n"); + fdi2raw_log("\n"); fix_mfm_sync (fdi); return fdi->out; } @@ -1445,7 +1457,7 @@ static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *mi || (avgp[i] < (standard_MFM_2_bit_cell_size - (standard_MFM_2_bit_cell_size / 4))) ) ) i++; if (i == pulses) { - outlog ("No stable and long-enough pulse in track.\n"); + fdi2raw_log("No stable and long-enough pulse in track.\n"); return; } i--; @@ -1572,7 +1584,7 @@ static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *mi || (minp[i] < (standard_MFM_2_bit_cell_size - (standard_MFM_2_bit_cell_size / 4))) ) ) i++; if (i == pulses) { - outlog ("FDI: No stable and long-enough pulse in track.\n"); + fdi2raw_log("FDI: No stable and long-enough pulse in track.\n"); return; } nexti = i; @@ -1649,12 +1661,12 @@ static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *mi } avg_pulse += jitter; if ((avg_pulse < min_pulse) || (avg_pulse > max_pulse)) { - outlog ("FDI: avg_pulse outside bounds! avg=%u min=%u max=%u\n", avg_pulse, min_pulse, max_pulse); - outlog ("FDI: avgp=%u (%u) minp=%u (%u) maxp=%u (%u) jitter=%d i=%d ni=%d\n", + fdi2raw_log("FDI: avg_pulse outside bounds! avg=%u min=%u max=%u\n", avg_pulse, min_pulse, max_pulse); + fdi2raw_log("FDI: avgp=%u (%u) minp=%u (%u) maxp=%u (%u) jitter=%d i=%d ni=%d\n", avgp[i], avgp[nexti], minp[i], minp[nexti], maxp[i], maxp[nexti], jitter, i, nexti); } if (avg_pulse < ref_pulse) - outlog ("FDI: avg_pulse < ref_pulse! (%u < %u)\n", avg_pulse, ref_pulse); + fdi2raw_log("FDI: avg_pulse < ref_pulse! (%u < %u)\n", avg_pulse, ref_pulse); pulse += avg_pulse - ref_pulse; ref_pulse = 0; if (i == eodat) @@ -1927,7 +1939,7 @@ static int decode_lowlevel_track (FDI *fdi, int track, struct fdi_cache *cache) idxp[i] = sum; } len = totalavg / 100000; - /* outlog("totalavg=%u index=%d (%d) maxidx=%d weakbits=%d len=%d\n", + /* fdi2raw_log("totalavg=%u index=%d (%d) maxidx=%d weakbits=%d len=%d\n", totalavg, indexoffset, maxidx, weakbits, len); */ cache->avgp = avgp; cache->idxp = idxp; @@ -1970,7 +1982,7 @@ void fdi2raw_header_free (FDI *fdi) fdi_free (c->maxp); } fdi_free (fdi); - debuglog ("FREE: memory allocated %d\n", fdi_allocated); + fdi2raw_log("FREE: memory allocated %d\n", fdi_allocated); } int fdi2raw_get_last_track (FDI *fdi) @@ -2021,7 +2033,7 @@ FDI *fdi2raw_header(FILE *f) uae_u8 type, size; FDI *fdi; - debuglog ("ALLOC: memory allocated %d\n", fdi_allocated); + fdi2raw_log("ALLOC: memory allocated %d\n", fdi_allocated); fdi = fdi_malloc(sizeof(FDI)); memset (fdi, 0, sizeof (FDI)); fdi->file = f; @@ -2051,8 +2063,8 @@ FDI *fdi2raw_header(FILE *f) fdi->disk_type = fdi->header[145]; fdi->rotation_speed = fdi->header[146] + 128; fdi->write_protect = fdi->header[147] & 1; - outlog ("FDI version %d.%d\n", fdi->header[140], fdi->header[141]); - outlog ("last_track=%d rotation_speed=%d\n",fdi->last_track,fdi->rotation_speed); + fdi2raw_log("FDI version %d.%d\n", fdi->header[140], fdi->header[141]); + fdi2raw_log("last_track=%d rotation_speed=%d\n",fdi->last_track,fdi->rotation_speed); offset = 512; i = fdi->last_track; @@ -2091,7 +2103,7 @@ int fdi2raw_loadrevolution_2 (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, i fdi2_decode (fdi, cache->totalavg, cache->avgp, cache->minp, cache->maxp, cache->idxp, cache->maxidx, &idx, cache->pulses, mfm); - /* outlog("track %d: nbits=%d avg len=%.2f weakbits=%d idx=%d\n", + /* fdi2raw_log("track %d: nbits=%d avg len=%.2f weakbits=%d idx=%d\n", track, bitoffset, (double)cache->totalavg / bitoffset, cache->weakbits, cache->indexoffset); */ len = fdi->out; if (cache->weakbits >= 10 && multirev) @@ -2144,7 +2156,7 @@ int fdi2raw_loadtrack (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, int trac else fdi->bit_rate = 250; - /* outlog ("track %d: srclen: %d track_type: %02.2X, bitrate: %d\n", + /* fdi2raw_log("track %d: srclen: %d track_type: %02.2X, bitrate: %d\n", fdi->current_track, fdi->track_src_len, fdi->track_type, fdi->bit_rate); */ if ((fdi->track_type & 0xc0) == 0x80) { diff --git a/src/game/gameport.c b/src/game/gameport.c index 1550e4eab..53b9dac52 100644 --- a/src/game/gameport.c +++ b/src/game/gameport.c @@ -8,7 +8,7 @@ * * Implementation of a generic Game Port. * - * Version: @(#)gameport.c 1.0.4 2018/03/19 + * Version: @(#)gameport.c 1.0.6 2018/04/29 * * Authors: Miran Grca, * Sarah Walker, @@ -177,7 +177,6 @@ gameport_write(uint16_t addr, uint8_t val, void *priv) timer_clock(); p->state |= 0x0f; - pclog("gameport_write : joysticks_present=%i\n", joysticks_present); p->axis[0].count = gameport_time(p->joystick->read_axis(p->joystick_dat, 0)); p->axis[1].count = gameport_time(p->joystick->read_axis(p->joystick_dat, 1)); @@ -321,7 +320,7 @@ const device_t gameport_device = { 0, 0, gameport_init, gameport_close, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; @@ -330,6 +329,6 @@ const device_t gameport_201_device = { 0, 0, gameport_201_init, gameport_close, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; diff --git a/src/intel_flash.c b/src/intel_flash.c index ccf141eff..a619212ac 100644 --- a/src/intel_flash.c +++ b/src/intel_flash.c @@ -8,7 +8,7 @@ * * Implementation of the Intel 1 Mbit 8-bit flash devices. * - * Version: @(#)intel_flash.c 1.0.14 2018/03/18 + * Version: @(#)intel_flash.c 1.0.16 2018/04/29 * * Authors: Sarah Walker, * Miran Grca, @@ -185,8 +185,6 @@ void *intel_flash_init(uint8_t type) wcscpy(flash_path, flash_name); - /* pclog("Flash path: %ls\n", flash_name); */ - flash->flash_id = (type & FLASH_IS_BXB) ? 0x95 : 0x94; flash->invert_high_pin = (type & FLASH_INVERT); @@ -295,7 +293,7 @@ const device_t intel_flash_bxt_ami_device = intel_flash_bxt_ami_init, intel_flash_close, NULL, - NULL, NULL, NULL, NULL, NULL + NULL, NULL, NULL, NULL }; const device_t intel_flash_bxb_ami_device = @@ -305,7 +303,7 @@ const device_t intel_flash_bxb_ami_device = intel_flash_bxb_ami_init, intel_flash_close, NULL, - NULL, NULL, NULL, NULL, NULL + NULL, NULL, NULL, NULL }; const device_t intel_flash_bxt_device = @@ -315,7 +313,7 @@ const device_t intel_flash_bxt_device = intel_flash_bxt_init, intel_flash_close, NULL, - NULL, NULL, NULL, NULL, NULL + NULL, NULL, NULL, NULL }; const device_t intel_flash_bxb_device = @@ -325,5 +323,5 @@ const device_t intel_flash_bxb_device = intel_flash_bxb_init, intel_flash_close, NULL, - NULL, NULL, NULL, NULL, NULL + NULL, NULL, NULL, NULL }; diff --git a/src/intel_piix.c b/src/intel_piix.c index 369d4166b..43f8dd17b 100644 --- a/src/intel_piix.c +++ b/src/intel_piix.c @@ -10,7 +10,7 @@ * word 0 - base address * word 1 - bits 1-15 = byte count, bit 31 = end of transfer * - * Version: @(#)intel_piix.c 1.0.13 2018/02/23 + * Version: @(#)intel_piix.c 1.0.17 2018/06/02 * * Authors: Sarah Walker, * Miran Grca, @@ -18,768 +18,899 @@ * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 Miran Grca. */ -#include +#include #include +#include +#include #include #include +#define HAVE_STDARG_H #include "86box.h" +#include "scsi/scsi.h" +#include "cdrom/cdrom.h" #include "dma.h" #include "io.h" #include "device.h" #include "keyboard.h" #include "mem.h" #include "pci.h" +#include "pic.h" #include "disk/hdc.h" #include "disk/hdc_ide.h" +#include "disk/zip.h" #include "piix.h" -uint8_t piix_33 = 0; - -static uint8_t piix_type = 1; -static uint8_t card_piix[256], card_piix_ide[256]; - - -uint8_t piix_bus_master_read(uint16_t port, void *priv); -void piix_bus_master_write(uint16_t port, uint8_t val, void *priv); - - -void piix_write(int func, int addr, uint8_t val, void *priv) +typedef struct { - uint16_t old_base = (card_piix_ide[0x20] & 0xf0) | (card_piix_ide[0x21] << 8); - if (func > 1) - return; - - if (func == 1) /*IDE*/ - { - /* pclog("PIIX IDE write: %02X %02X\n", addr, val); */ + uint8_t command, status, + ptr0; + uint32_t ptr, ptr_cur, + addr; + int count, eot; +} piix_busmaster_t; - switch (addr) - { - case 0x04: - card_piix_ide[0x04] = (val & 5) | 2; - break; - case 0x07: - card_piix_ide[0x07] = val & 0x3e; - break; - case 0x0d: - card_piix_ide[0x0d] = val; - break; - - case 0x20: - card_piix_ide[0x20] = (val & ~0x0f) | 1; - break; - case 0x21: - card_piix_ide[0x21] = val; - break; - - case 0x40: - card_piix_ide[0x40] = val; - break; - case 0x41: - card_piix_ide[0x41] = val; - break; - case 0x42: - card_piix_ide[0x42] = val; - break; - case 0x43: - card_piix_ide[0x43] = val; - break; - case 0x44: - if (piix_type >= 3) card_piix_ide[0x44] = val; - break; - } - if (addr == 4 || (addr & ~3) == 0x20) /*Bus master base address*/ - { - uint16_t base = (card_piix_ide[0x20] & 0xf0) | (card_piix_ide[0x21] << 8); - if (old_base) - io_removehandler(old_base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL); - if ((card_piix_ide[0x04] & 1) && base) - io_sethandler(base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL); - } - if (addr == 4 || addr == 0x41 || addr == 0x43) - { - ide_pri_disable(); - ide_sec_disable(); - if (card_piix_ide[0x04] & 1) - { - if (card_piix_ide[0x41] & 0x80) - ide_pri_enable(); - if (card_piix_ide[0x43] & 0x80) - ide_sec_enable(); - } - } - } - else - { - /* pclog("PIIX writing value %02X to register %02X\n", val, addr); */ - if ((addr >= 0x0f) && (addr < 0x4c)) - return; +typedef struct +{ + int type; + uint8_t regs[256], regs_ide[256]; + piix_busmaster_t bm[2]; +} piix_t; - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0e: - return; - - case 0x60: - /* pclog("Set IRQ routing: INT A -> %02X\n", val); */ - if (val & 0x80) - pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTA, val & 0xf); - break; - case 0x61: - /* pclog("Set IRQ routing: INT B -> %02X\n", val); */ - if (val & 0x80) - pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTB, val & 0xf); - break; - case 0x62: - /* pclog("Set IRQ routing: INT C -> %02X\n", val); */ - if (val & 0x80) - pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTC, val & 0xf); - break; - case 0x63: - /* pclog("Set IRQ routing: INT D -> %02X\n", val); */ - if (val & 0x80) - pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTD, val & 0xf); - break; - case 0x70: - /* pclog("Set MIRQ routing: MIRQ0 -> %02X\n", val); */ - if (val & 0x80) - pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); - else - pci_set_mirq_routing(PCI_MIRQ0, val & 0xf); - break; - /* pclog("MIRQ0 is %s\n", (val & 0x20) ? "disabled" : "enabled"); */ - case 0x71: - if (piix_type == 1) - { - /* pclog("Set MIRQ routing: MIRQ1 -> %02X\n", val); */ - if (val & 0x80) - pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); - else - pci_set_mirq_routing(PCI_MIRQ1, val & 0xf); - } -#if 0 - else - { - pclog("Set unused MIRQ routing: MIRQ1 -> %02X\n", val); - } + +static uint8_t piix_bus_master_read(uint16_t port, void *priv); +static uint16_t piix_bus_master_readw(uint16_t port, void *priv); +static uint32_t piix_bus_master_readl(uint16_t port, void *priv); +static void piix_bus_master_write(uint16_t port, uint8_t val, void *priv); +static void piix_bus_master_writew(uint16_t port, uint16_t val, void *priv); +static void piix_bus_master_writel(uint16_t port, uint32_t val, void *priv); + + +#ifdef ENABLE_PIIX_LOG +int piix_do_log = ENABLE_PIIX_LOG; #endif - break; - } - if (addr == 0x4C) - { - if (!((val ^ card_piix[addr]) & 0x80)) - { - card_piix[addr] = val; - return; - } - card_piix[addr] = val; - if (val & 0x80) - { - if (piix_type == 3) - { - dma_alias_remove(); - } - else - { - dma_alias_remove_piix(); - } - } - else - { - dma_alias_set(); - } - } - else if (addr == 0x4E) - { - keyboard_at_set_mouse_scan((val & 0x10) ? 1 : 0); - card_piix[addr] = val; - } - else if (addr == 0x6A) - { - if (piix_type == 1) - card_piix[addr] = (val & 0xFC) | (card_piix[addr] | 3); - else if (piix_type == 3) - card_piix[addr] = (val & 0xFD) | (card_piix[addr] | 2); - } - else - card_piix[addr] = val; - } + +static void +piix_log(const char *format, ...) +{ +#ifdef ENABLE_PIIX_LOG + va_list ap; + + if (piix_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif } -uint8_t piix_read(int func, int addr, void *priv) -{ - if (func > 1) - return 0xff; - if (func == 1) /*IDE*/ - { - if (addr == 4) - { - return (card_piix_ide[addr] & 5) | 2; - } - else if (addr == 5) - { - return 0; - } - else if (addr == 6) - { - return 0x80; - } - else if (addr == 7) - { - return card_piix_ide[addr] & 0x3E; - } - else if (addr == 0xD) - { - return card_piix_ide[addr] & 0xF0; - } - else if (addr == 0x20) - { - return (card_piix_ide[addr] & 0xF0) | 1; - } - else if (addr == 0x22) - { - return 0; - } - else if (addr == 0x23) - { - return 0; - } - else if (addr == 0x41) - { - if (piix_type == 1) - return card_piix_ide[addr] & 0xB3; - else if (piix_type == 3) - return card_piix_ide[addr] & 0xF3; - } - else if (addr == 0x43) - { - if (piix_type == 1) - return card_piix_ide[addr] & 0xB3; - else if (piix_type == 3) - return card_piix_ide[addr] & 0xF3; - } - else - { - return card_piix_ide[addr]; - } - } - else - { - if ((addr & 0xFC) == 0x60) - { - return card_piix[addr] & 0x8F; - } - if (addr == 4) - { - return (card_piix[addr] & 0x80) | 7; - } - else if (addr == 5) - { - if (piix_type == 1) - return 0; - else if (piix_type == 3) - return card_piix[addr] & 1; - } - else if (addr == 6) - { - return card_piix[addr] & 0x80; - } - else if (addr == 7) - { - if (piix_type == 1) - return card_piix[addr] & 0x3E; - else if (piix_type == 3) - return card_piix[addr]; - } - else if (addr == 0x4E) - { - return (card_piix[addr] & 0xEF) | keyboard_at_get_mouse_scan(); - } - else if (addr == 0x69) - { - return card_piix[addr] & 0xFE; - } - else if (addr == 0x6A) - { - if (piix_type == 1) - return card_piix[addr] & 0x07; - else if (piix_type == 3) - return card_piix[addr] & 0xD1; - } - else if (addr == 0x6B) - { - if (piix_type == 1) - return 0; - else if (piix_type == 3) - return card_piix[addr] & 0x80; - } - else if (addr == 0x70) - { - if (piix_type == 1) - return card_piix[addr] & 0xCF; - else if (piix_type == 3) - return card_piix[addr] & 0xEF; - } - else if (addr == 0x71) - { - if (piix_type == 1) - return card_piix[addr] & 0xCF; - else if (piix_type == 3) - return 0; - } - else if (addr == 0x76) - { - if (piix_type == 1) - return card_piix[addr] & 0x8F; - else if (piix_type == 3) - return card_piix[addr] & 0x87; - } - else if (addr == 0x77) - { - if (piix_type == 1) - return card_piix[addr] & 0x8F; - else if (piix_type == 3) - return card_piix[addr] & 0x87; - } - else if (addr == 0x80) - { - if (piix_type == 1) - return 0; - else if (piix_type == 3) - return card_piix[addr] & 0x7F; - } - else if (addr == 0x82) - { - if (piix_type == 1) - return 0; - else if (piix_type == 3) - return card_piix[addr] & 0x0F; - } - else if (addr == 0xA0) - { - return card_piix[addr] & 0x1F; - } - else if (addr == 0xA3) - { - if (piix_type == 1) - return 0; - else if (piix_type == 3) - return card_piix[addr] & 1; - } - else if (addr == 0xA7) - { - if (piix_type == 1) - return card_piix[addr] & 0xEF; - else if (piix_type == 3) - return card_piix[addr]; - } - else if (addr == 0xAB) - { - if (piix_type == 1) - return card_piix[addr] & 0xFE; - else if (piix_type == 3) - return card_piix[addr]; - } - else - return card_piix[addr]; +static void +piix_bus_master_handlers(piix_t *dev, uint16_t old_base) +{ + uint16_t base; + + base = (dev->regs_ide[0x20] & 0xf0) | (dev->regs_ide[0x21] << 8); + io_removehandler(old_base, 0x08, + piix_bus_master_read, piix_bus_master_readw, piix_bus_master_readl, + piix_bus_master_write, piix_bus_master_writew, piix_bus_master_writel, + &dev->bm[0]); + io_removehandler(old_base + 8, 0x08, + piix_bus_master_read, piix_bus_master_readw, piix_bus_master_readl, + piix_bus_master_write, piix_bus_master_writew, piix_bus_master_writel, + &dev->bm[1]); + + if ((dev->regs_ide[0x04] & 1) && base) { + io_sethandler(base, 0x08, + piix_bus_master_read, piix_bus_master_readw, piix_bus_master_readl, + piix_bus_master_write, piix_bus_master_writew, piix_bus_master_writel, + &dev->bm[0]); + io_sethandler(base + 8, 0x08, + piix_bus_master_read, piix_bus_master_readw, piix_bus_master_readl, + piix_bus_master_write, piix_bus_master_writew, piix_bus_master_writel, + &dev->bm[1]); + } +} + + +static void +piix_write(int func, int addr, uint8_t val, void *priv) +{ + piix_t *dev = (piix_t *) priv; + uint8_t valxor; + + uint16_t old_base = (dev->regs_ide[0x20] & 0xf0) | (dev->regs_ide[0x21] << 8); + if (func > 1) + return; + + if (func == 1) { /*IDE*/ + piix_log("PIIX IDE write: %02X %02X\n", addr, val); + valxor = val ^ dev->regs_ide[addr]; + + switch (addr) { + case 0x04: + dev->regs_ide[0x04] = (val & 5) | 2; + if (valxor & 0x01) { + ide_pri_disable(); + ide_sec_disable(); + if (val & 0x01) { + if (dev->regs_ide[0x41] & 0x80) + ide_pri_enable(); + if (dev->regs_ide[0x43] & 0x80) + ide_sec_enable(); + } + + piix_bus_master_handlers(dev, old_base); + } + break; + case 0x07: + dev->regs_ide[0x07] = val & 0x3e; + break; + case 0x0d: + dev->regs_ide[0x0d] = val; + break; + + case 0x20: + dev->regs_ide[0x20] = (val & ~0x0f) | 1; + if (valxor) + piix_bus_master_handlers(dev, old_base); + break; + case 0x21: + dev->regs_ide[0x21] = val; + if (valxor) + piix_bus_master_handlers(dev, old_base); + break; + + case 0x40: + dev->regs_ide[0x40] = val; + break; + case 0x41: + dev->regs_ide[0x41] = val; + if (valxor & 0x80) { + ide_pri_disable(); + if ((val & 0x80) && (dev->regs_ide[0x04] & 0x01)) + ide_pri_enable(); + } + break; + case 0x42: + dev->regs_ide[0x42] = val; + break; + case 0x43: + dev->regs_ide[0x43] = val; + if (valxor & 0x80) { + ide_sec_disable(); + if ((val & 0x80) && (dev->regs_ide[0x04] & 0x01)) + ide_sec_enable(); + } + break; + case 0x44: + if (dev->type >= 3) dev->regs_ide[0x44] = val; + break; + } + } else { + piix_log("PIIX writing value %02X to register %02X\n", val, addr); + valxor = val ^ dev->regs[addr]; + + if ((addr >= 0x0f) && (addr < 0x4c)) + return; + + switch (addr) { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0e: + return; + + case 0x4c: + if (valxor) { + if (val & 0x80) { + if (dev->type == 3) + dma_alias_remove(); + else + dma_alias_remove_piix(); + } else + dma_alias_set(); + } + break; + case 0x4e: + keyboard_at_set_mouse_scan((val & 0x10) ? 1 : 0); + break; + case 0x60: + piix_log("Set IRQ routing: INT A -> %02X\n", val); + if (val & 0x80) + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTA, val & 0xf); + break; + case 0x61: + piix_log("Set IRQ routing: INT B -> %02X\n", val); + if (val & 0x80) + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTB, val & 0xf); + break; + case 0x62: + piix_log("Set IRQ routing: INT C -> %02X\n", val); + if (val & 0x80) + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTC, val & 0xf); + break; + case 0x63: + piix_log("Set IRQ routing: INT D -> %02X\n", val); + if (val & 0x80) + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTD, val & 0xf); + break; + case 0x6a: + if (dev->type == 3) + dev->regs[addr] = (val & 0xFD) | (dev->regs[addr] | 2); + else + dev->regs[addr] = (val & 0xFC) | (dev->regs[addr] | 3); + return; + case 0x70: + piix_log("Set MIRQ routing: MIRQ0 -> %02X\n", val); + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ0, val & 0xf); + break; + piix_log("MIRQ0 is %s\n", (val & 0x20) ? "disabled" : "enabled"); + case 0x71: + if (dev->type == 1) { + piix_log("Set MIRQ routing: MIRQ1 -> %02X\n", val); + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ1, val & 0xf); + } + break; } - return 0; + dev->regs[addr] = val; + } } -struct -{ - uint8_t command; - uint8_t status; - uint32_t ptr, ptr_cur; - int count; - uint32_t addr; - int eot; - uint8_t ptr0; -} piix_busmaster[2]; -static void piix_bus_master_next_addr(int channel) +static uint8_t +piix_read(int func, int addr, void *priv) { - DMAPageRead(piix_busmaster[channel].ptr_cur, (uint8_t *)&(piix_busmaster[channel].addr), 4); - DMAPageRead(piix_busmaster[channel].ptr_cur + 4, (uint8_t *)&(piix_busmaster[channel].count), 4); -#if 0 - pclog("PIIX Bus master DWORDs: %08X %08X\n", piix_busmaster[channel].addr, piix_busmaster[channel].count); -#endif - piix_busmaster[channel].eot = piix_busmaster[channel].count >> 31; - piix_busmaster[channel].count &= 0xfffe; - if (!piix_busmaster[channel].count) - piix_busmaster[channel].count = 65536; - piix_busmaster[channel].addr &= 0xfffffffe; - piix_busmaster[channel].ptr_cur += 8; + piix_t *dev = (piix_t *) priv; + + if ((func == 1) && (dev->type & 0x100)) /* PB640's PIIX has no IDE part. */ + return 0xff; + if (func > 1) + return 0xff; + + if (func == 1) { /*IDE*/ + if (addr == 4) + return (dev->regs_ide[addr] & 5) | 2; + else if (addr == 5) + return 0; + else if (addr == 6) + return 0x80; + else if (addr == 7) + return dev->regs_ide[addr] & 0x3E; + else if (addr == 0xD) + return dev->regs_ide[addr] & 0xF0; + else if (addr == 0x20) + return (dev->regs_ide[addr] & 0xF0) | 1; + else if (addr == 0x22) + return 0; + else if (addr == 0x23) + return 0; + else if (addr == 0x41) { + if (dev->type == 3) + return dev->regs_ide[addr] & 0xF3; + else + return dev->regs_ide[addr] & 0xB3; + } else if (addr == 0x43) { + if (dev->type == 3) + return dev->regs_ide[addr] & 0xF3; + else + return dev->regs_ide[addr] & 0xB3; + } else + return dev->regs_ide[addr]; + } else { + if ((addr & 0xFC) == 0x60) + return dev->regs[addr] & 0x8F; + + if (addr == 4) { + if (dev->type & 0x100) + return (dev->regs[addr] & 0x80) | 0x0F; + else + return (dev->regs[addr] & 0x80) | 7; + } else if (addr == 5) { + if (dev->type == 3) + return dev->regs[addr] & 1; + else + return 0; + } else if (addr == 6) + return dev->regs[addr] & 0x80; + else if (addr == 7) { + if (dev->type == 3) + return dev->regs[addr]; + else { + if (dev->type & 0x100) + return dev->regs[addr] & 0x02; + else + return dev->regs[addr] & 0x3E; + } + } else if (addr == 0x4E) + return (dev->regs[addr] & 0xEF) | keyboard_at_get_mouse_scan(); + else if (addr == 0x69) + return dev->regs[addr] & 0xFE; + else if (addr == 0x6A) { + if (dev->type == 3) + return dev->regs[addr] & 0xD1; + else + return dev->regs[addr] & 0x07; + } else if (addr == 0x6B) { + if (dev->type == 3) + return dev->regs[addr] & 0x80; + else + return 0; + } + else if (addr == 0x70) { + if (dev->type == 3) + return dev->regs[addr] & 0xEF; + else + return dev->regs[addr] & 0xCF; + } else if (addr == 0x71) { + if (dev->type == 3) + return 0; + else + return dev->regs[addr] & 0xCF; + } else if (addr == 0x76) { + if (dev->type == 3) + return dev->regs[addr] & 0x87; + else + return dev->regs[addr] & 0x8F; + } else if (addr == 0x77) { + if (dev->type == 3) + return dev->regs[addr] & 0x87; + else + return dev->regs[addr] & 0x8F; + } else if (addr == 0x80) { + if (dev->type == 3) + return dev->regs[addr] & 0x7F; + else if (dev->type == 1) + return 0; + } else if (addr == 0x82) { + if (dev->type == 3) + return dev->regs[addr] & 0x0F; + else + return 0; + } else if (addr == 0xA0) + return dev->regs[addr] & 0x1F; + else if (addr == 0xA3) { + if (dev->type == 3) + return dev->regs[addr] & 1; + else + return 0; + } else if (addr == 0xA7) { + if (dev->type == 3) + return dev->regs[addr]; + else + return dev->regs[addr] & 0xEF; + } else if (addr == 0xAB) { + if (dev->type == 3) + return dev->regs[addr]; + else + return dev->regs[addr] & 0xFE; + } else + return dev->regs[addr]; + } + + return 0; } -void piix_bus_master_write(uint16_t port, uint8_t val, void *priv) + +static void +piix_bus_master_next_addr(piix_busmaster_t *dev) { - /* pclog("PIIX Bus master write: %04X %02X\n", port, val); */ - int channel = (port & 8) ? 1 : 0; - switch (port & 7) { - case 0: - if ((val & 1) && !(piix_busmaster[channel].command & 1)) { /*Start*/ - piix_busmaster[channel].ptr_cur = piix_busmaster[channel].ptr; - piix_bus_master_next_addr(channel); - piix_busmaster[channel].status |= 1; - } - if (!(val & 1) && (piix_busmaster[channel].command & 1)) /*Stop*/ - piix_busmaster[channel].status &= ~1; - - piix_busmaster[channel].command = val; - break; - case 2: - piix_busmaster[channel].status &= 0x07; - piix_busmaster[channel].status |= (val & 0x60); + DMAPageRead(dev->ptr_cur, (uint8_t *)&(dev->addr), 4); + DMAPageRead(dev->ptr_cur + 4, (uint8_t *)&(dev->count), 4); + piix_log("PIIX Bus master DWORDs: %08X %08X\n", dev->addr, dev->count); + dev->eot = dev->count >> 31; + dev->count &= 0xfffe; + if (!dev->count) + dev->count = 65536; + dev->addr &= 0xfffffffe; + dev->ptr_cur += 8; +} + + +static void +piix_bus_master_write(uint16_t port, uint8_t val, void *priv) +{ + piix_busmaster_t *dev = (piix_busmaster_t *) priv; + int channel = (port & 8) ? 1 : 0; + + piix_log("PIIX Bus master BYTE write: %04X %02X\n", port, val); + + switch (port & 7) { + case 0: + piix_log("PIIX Cmd : val = %02X, old = %02X\n", val, dev->command); + if ((val & 1) && !(dev->command & 1)) { /*Start*/ + piix_log("PIIX Bus Master start on channel %i\n", channel); + dev->ptr_cur = dev->ptr; + piix_bus_master_next_addr(dev); + dev->status |= 1; + } + if (!(val & 1) && (dev->command & 1)) { /*Stop*/ + piix_log("PIIX Bus Master stop on channel %i\n", channel); + dev->status &= ~1; + } + + dev->command = val; + break; + case 2: + piix_log("PIIX Status: val = %02X, old = %02X\n", val, dev->status); + dev->status &= 0x07; + dev->status |= (val & 0x60); if (val & 0x04) - piix_busmaster[channel].status &= ~0x04; + dev->status &= ~0x04; if (val & 0x02) - piix_busmaster[channel].status &= ~0x02; - /* piix_busmaster[channel].status = (val & 0x60) | ((piix_busmaster[channel].status & ~val) & 6) | (piix_busmaster[channel].status & 1); */ - break; - case 4: - piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0xffffff00) | (val & 0xfc); - piix_busmaster[channel].ptr %= (mem_size * 1024); - piix_busmaster[channel].ptr0 = val; - break; - case 5: - piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0xffff00fc) | (val << 8); - piix_busmaster[channel].ptr %= (mem_size * 1024); - break; - case 6: - piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0xff00fffc) | (val << 16); - piix_busmaster[channel].ptr %= (mem_size * 1024); - break; - case 7: - piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0x00fffffc) | (val << 24); - piix_busmaster[channel].ptr %= (mem_size * 1024); - break; - - } -} - -uint8_t piix_bus_master_read(uint16_t port, void *priv) -{ - /* pclog("PIIX Bus master read: %04X\n", port); */ - int channel = (port & 8) ? 1 : 0; - switch (port & 7) { - case 0: - return piix_busmaster[channel].command; - case 2: - return piix_busmaster[channel].status & 0x67; - case 4: - return piix_busmaster[channel].ptr0; - case 5: - return piix_busmaster[channel].ptr >> 8; - case 6: - return piix_busmaster[channel].ptr >> 16; - case 7: - return piix_busmaster[channel].ptr >> 24; - } - return 0xff; + dev->status &= ~0x02; + break; + case 4: + dev->ptr = (dev->ptr & 0xffffff00) | (val & 0xfc); + dev->ptr %= (mem_size * 1024); + dev->ptr0 = val; + break; + case 5: + dev->ptr = (dev->ptr & 0xffff00fc) | (val << 8); + dev->ptr %= (mem_size * 1024); + break; + case 6: + dev->ptr = (dev->ptr & 0xff00fffc) | (val << 16); + dev->ptr %= (mem_size * 1024); + break; + case 7: + dev->ptr = (dev->ptr & 0x00fffffc) | (val << 24); + dev->ptr %= (mem_size * 1024); + break; + } } -int piix_bus_master_get_count(int channel) + +static void +piix_bus_master_writew(uint16_t port, uint16_t val, void *priv) { - return piix_busmaster[channel].count; + piix_busmaster_t *dev = (piix_busmaster_t *) priv; + + piix_log("PIIX Bus master WORD write: %04X %04X\n", port, val); + + switch (port & 7) { + case 0: + case 2: + piix_bus_master_write(port, val & 0xff, priv); + break; + case 4: + dev->ptr = (dev->ptr & 0xffff0000) | (val & 0xfffc); + dev->ptr %= (mem_size * 1024); + dev->ptr0 = val & 0xff; + break; + case 6: + dev->ptr = (dev->ptr & 0x0000fffc) | (val << 16); + dev->ptr %= (mem_size * 1024); + break; + } } -int piix_bus_master_get_eot(int channel) + +static void +piix_bus_master_writel(uint16_t port, uint32_t val, void *priv) { - return piix_busmaster[channel].eot; + piix_busmaster_t *dev = (piix_busmaster_t *) priv; + + piix_log("PIIX Bus master DWORD write: %04X %08X\n", port, val); + + switch (port & 7) { + case 0: + case 2: + piix_bus_master_write(port, val & 0xff, priv); + break; + case 4: + dev->ptr = (val & 0xfffffffc); + dev->ptr %= (mem_size * 1024); + dev->ptr0 = val & 0xff; + break; + } } -int piix_bus_master_dma_read(int channel, uint8_t *data, int transfer_length) + +static uint8_t +piix_bus_master_read(uint16_t port, void *priv) { - int force_end = 0; - int buffer_pos = 0; - - if (!(piix_busmaster[channel].status & 1)) - return 1; /*DMA disabled*/ + piix_busmaster_t *dev = (piix_busmaster_t *) priv; -#if 0 - pclog("PIIX Bus master read: %i bytes\n", transfer_length); -#endif + uint8_t ret = 0xff; - while (1) { - if (piix_busmaster[channel].count <= transfer_length) { -#if 0 - pclog("Writing %i bytes to %08X\n", piix_busmaster[channel].count, piix_busmaster[channel].addr); -#endif - DMAPageWrite(piix_busmaster[channel].addr, (uint8_t *)(data + buffer_pos), piix_busmaster[channel].count); - transfer_length -= piix_busmaster[channel].count; - buffer_pos += piix_busmaster[channel].count; - } else { -#if 0 - pclog("Writing %i bytes to %08X\n", piix_busmaster[channel].count, piix_busmaster[channel].addr); -#endif - DMAPageWrite(piix_busmaster[channel].addr, (uint8_t *)(data + buffer_pos), transfer_length); - transfer_length = 0; - force_end = 1; - } + switch (port & 7) { + case 0: + ret = dev->command; + break; + case 2: + ret = dev->status & 0x67; + break; + case 4: + ret = dev->ptr0; + break; + case 5: + ret = dev->ptr >> 8; + break; + case 6: + ret = dev->ptr >> 16; + break; + case 7: + ret = dev->ptr >> 24; + break; + } - if (force_end) { -#if 0 - pclog("Total transfer length smaller than sum of all blocks, partial block\n"); -#endif - piix_busmaster[channel].status &= ~2; - return 0; /* This block has exhausted the data to transfer and it was smaller than the count, break. */ + piix_log("PIIX Bus master BYTE read : %04X %02X\n", port, ret); + + return ret; +} + + +static uint16_t +piix_bus_master_readw(uint16_t port, void *priv) +{ + piix_busmaster_t *dev = (piix_busmaster_t *) priv; + + uint16_t ret = 0xffff; + + switch (port & 7) { + case 0: + case 2: + ret = (uint16_t) piix_bus_master_read(port, priv); + break; + case 4: + ret = dev->ptr0 | (dev->ptr & 0xff00); + break; + case 6: + ret = dev->ptr >> 16; + break; + } + + piix_log("PIIX Bus master WORD read : %04X %04X\n", port, ret); + + return ret; +} + + +static uint32_t +piix_bus_master_readl(uint16_t port, void *priv) +{ + piix_busmaster_t *dev = (piix_busmaster_t *) priv; + + uint32_t ret = 0xffffffff; + + switch (port & 7) { + case 0: + case 2: + ret = (uint32_t) piix_bus_master_read(port, priv); + break; + case 4: + ret = dev->ptr0 | (dev->ptr & 0xffffff00); + break; + } + + piix_log("PIIX Bus master DWORD read : %04X %08X\n", port, ret); + + return ret; +} + + +static int +piix_bus_master_dma_op(int channel, uint8_t *data, int transfer_length, int out, void *priv) +{ + piix_busmaster_t *dev = (piix_busmaster_t *) priv; + char *sop; + + int force_end = 0, buffer_pos = 0; + + sop = out ? "Writ" : "Read"; + + if (!(dev->status & 1)) + return 2; /*DMA disabled*/ + + piix_log("PIIX Bus master %s: %i bytes\n", out ? "read" : "write", transfer_length); + + while (1) { + if (dev->count <= transfer_length) { + piix_log("%sing %i bytes to %08X\n", sop, dev->count, dev->addr); + if (out) + DMAPageWrite(dev->addr, (uint8_t *)(data + buffer_pos), dev->count); + else + DMAPageRead(dev->addr, (uint8_t *)(data + buffer_pos), dev->count); + transfer_length -= dev->count; + buffer_pos += dev->count; + } else { + piix_log("%sing %i bytes to %08X\n", sop, transfer_length, dev->addr); + if (out) + DMAPageWrite(dev->addr, (uint8_t *)(data + buffer_pos), transfer_length); + else + DMAPageRead(dev->addr, (uint8_t *)(data + buffer_pos), transfer_length); + /* Increase addr and decrease count so that resumed transfers do not mess up. */ + dev->addr += transfer_length; + dev->count -= transfer_length; + transfer_length = 0; + force_end = 1; + } + + if (force_end) { + piix_log("Total transfer length smaller than sum of all blocks, partial block\n"); + dev->status &= ~2; + return 0; /* This block has exhausted the data to transfer and it was smaller than the count, break. */ + } else { + if (!transfer_length && !dev->eot) { + piix_log("Total transfer length smaller than sum of all blocks, full block\n"); + dev->status &= ~2; + return 0; /* We have exhausted the data to transfer but there's more blocks left, break. */ + } else if (transfer_length && dev->eot) { + piix_log("Total transfer length greater than sum of all blocks\n"); + dev->status |= 2; + return 1; /* There is data left to transfer but we have reached EOT - return with error. */ + } else if (dev->eot) { + piix_log("Regular EOT\n"); + dev->status &= ~3; + return 0; /* We have regularly reached EOT - clear status and break. */ } else { - if (!transfer_length && !piix_busmaster[channel].eot) { -#if 0 - pclog("Total transfer length smaller than sum of all blocks, full block\n"); -#endif - piix_busmaster[channel].status &= ~2; - return 0; /* We have exhausted the data to transfer but there's more blocks left, break. */ - } else if (transfer_length && piix_busmaster[channel].eot) { -#if 0 - pclog("Total transfer length greater than sum of all blocks\n"); -#endif - piix_busmaster[channel].status |= 2; - return 1; /* There is data left to transfer but we have reached EOT - return with error. */ - } else if (piix_busmaster[channel].eot) { -#if 0 - pclog("Regular EOT\n"); -#endif - piix_busmaster[channel].status &= ~3; - return 0; /* We have regularly reached EOT - clear status and break. */ - } else { - /* We have more to transfer and there are blocks left, get next block. */ - piix_bus_master_next_addr(channel); - } + /* We have more to transfer and there are blocks left, get next block. */ + piix_bus_master_next_addr(dev); } - } - return 0; -} - -int piix_bus_master_dma_write(int channel, uint8_t *data, int transfer_length) -{ - int force_end = 0; - int buffer_pos = 0; - - if (!(piix_busmaster[channel].status & 1)) - return 1; /*DMA disabled*/ - -#if 0 - pclog("PIIX Bus master write: %i bytes\n", transfer_length); -#endif - - while (1) { - if (piix_busmaster[channel].count <= transfer_length) { -#if 0 - pclog("Reading %i bytes from %08X\n", piix_busmaster[channel].count, piix_busmaster[channel].addr); -#endif - DMAPageRead(piix_busmaster[channel].addr, (uint8_t *)(data + buffer_pos), piix_busmaster[channel].count); - transfer_length -= piix_busmaster[channel].count; - buffer_pos += piix_busmaster[channel].count; - } else { -#if 0 - pclog("Reading %i bytes from %08X\n", piix_busmaster[channel].count, piix_busmaster[channel].addr); -#endif - DMAPageRead(piix_busmaster[channel].addr, (uint8_t *)(data + buffer_pos), transfer_length); - transfer_length = 0; - force_end = 1; - } - - if (force_end) { -#if 0 - pclog("Total transfer length smaller than sum of all blocks, partial block\n"); -#endif - piix_busmaster[channel].status &= ~2; - return 0; /* This block has exhausted the data to transfer and it was smaller than the count, break. */ - } else { - if (!transfer_length && !piix_busmaster[channel].eot) { -#if 0 - pclog("Total transfer length smaller than sum of all blocks, full block\n"); -#endif - piix_busmaster[channel].status &= ~2; - return 0; /* We have exhausted the data to transfer but there's more blocks left, break. */ - } else if (transfer_length && piix_busmaster[channel].eot) { -#if 0 - pclog("Total transfer length greater than sum of all blocks\n"); -#endif - piix_busmaster[channel].status |= 2; - return 1; /* There is data left to transfer but we have reached EOT - return with error. */ - } else if (piix_busmaster[channel].eot) { -#if 0 - pclog("Regular EOT\n"); -#endif - piix_busmaster[channel].status &= ~3; - return 0; /* We have regularly reached EOT - clear status and break. */ - } else { - /* We have more to transfer and there are blocks left, get next block. */ - piix_bus_master_next_addr(channel); - } - } - } - return 0; -} - -void piix_bus_master_set_irq(int channel) -{ - // piix_busmaster[channel].status |= 4; - piix_busmaster[channel & 0x0F].status &= ~4; - piix_busmaster[channel & 0x0F].status |= (channel >> 4); + } + } + return 0; } -static void piix_bus_master_reset(void) +int +piix_bus_master_dma_read(int channel, uint8_t *data, int transfer_length, void *priv) { - uint16_t old_base = (card_piix_ide[0x20] & 0xf0) | (card_piix_ide[0x21] << 8); - if (old_base) - io_removehandler(old_base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL); + return piix_bus_master_dma_op(channel, data, transfer_length, 1, priv); } -void piix_reset(void) +int +piix_bus_master_dma_write(int channel, uint8_t *data, int transfer_length, void *priv) { - piix_bus_master_reset(); - memset(card_piix, 0, 256); - card_piix[0x00] = 0x86; card_piix[0x01] = 0x80; /*Intel*/ - card_piix[0x02] = 0x2e; card_piix[0x03] = 0x12; /*82371FB (PIIX)*/ - card_piix[0x04] = 0x07; card_piix[0x05] = 0x00; - card_piix[0x06] = 0x80; card_piix[0x07] = 0x02; - card_piix[0x08] = 0x00; /*A0 stepping*/ - card_piix[0x09] = 0x00; card_piix[0x0a] = 0x01; card_piix[0x0b] = 0x06; - card_piix[0x0e] = 0x80; /*Multi-function device*/ - card_piix[0x4c] = 0x4d; - card_piix[0x4e] = 0x03; - card_piix[0x60] = card_piix[0x61] = card_piix[0x62] = card_piix[0x63] = 0x80; - card_piix[0x69] = 0x02; - card_piix[0x70] = card_piix[0x71] = 0xc0; - card_piix[0x76] = card_piix[0x77] = 0x0c; - card_piix[0x78] = 0x02; card_piix[0x79] = 0x00; - card_piix[0xa0] = 0x08; - card_piix[0xa2] = card_piix[0xa3] = 0x00; - card_piix[0xa4] = card_piix[0xa5] = card_piix[0xa6] = card_piix[0xa7] = 0x00; - card_piix[0xa8] = 0x0f; - card_piix[0xaa] = card_piix[0xab] = 0x00; - card_piix[0xac] = 0x00; - card_piix[0xae] = 0x00; + return piix_bus_master_dma_op(channel, data, transfer_length, 0, priv); +} - card_piix_ide[0x00] = 0x86; card_piix_ide[0x01] = 0x80; /*Intel*/ - card_piix_ide[0x02] = 0x30; card_piix_ide[0x03] = 0x12; /*82371FB (PIIX)*/ - card_piix_ide[0x04] = 0x02; card_piix_ide[0x05] = 0x00; - card_piix_ide[0x06] = 0x80; card_piix_ide[0x07] = 0x02; - card_piix_ide[0x08] = 0x00; - card_piix_ide[0x09] = 0x80; card_piix_ide[0x0a] = 0x01; card_piix_ide[0x0b] = 0x01; - card_piix_ide[0x0d] = 0x00; - card_piix_ide[0x0e] = 0x00; - card_piix_ide[0x20] = 0x01; card_piix_ide[0x21] = card_piix_ide[0x22] = card_piix_ide[0x23] = 0x00; /*Bus master interface base address*/ - card_piix_ide[0x40] = card_piix_ide[0x42] = 0x00; - card_piix_ide[0x41] = card_piix_ide[0x43] = 0x80; - pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); +void +piix_bus_master_set_irq(int channel, void *priv) +{ + piix_busmaster_t *dev = (piix_busmaster_t *) priv; + dev->status &= ~4; + dev->status |= (channel >> 4); + + channel &= 0x01; + if (dev->status & 0x04) { + if (channel && pci_use_mirq(0)) + pci_set_mirq(0); + else + picint(1 << (14 + channel)); + } else { + if ((channel & 1) && pci_use_mirq(0)) + pci_clear_mirq(0); + else + picintc(1 << (14 + channel)); + } +} + + +static void +piix_bus_master_reset(piix_t *dev) +{ + uint8_t i; + + uint16_t old_base = (dev->regs_ide[0x20] & 0xf0) | (dev->regs_ide[0x21] << 8); + if (old_base) { + io_removehandler(old_base, 0x08, + piix_bus_master_read, piix_bus_master_readw, piix_bus_master_readl, + piix_bus_master_write, piix_bus_master_writew, piix_bus_master_writel, + &dev->bm[0]); + io_removehandler(old_base + 8, 0x08, + piix_bus_master_read, piix_bus_master_readw, piix_bus_master_readl, + piix_bus_master_write, piix_bus_master_writew, piix_bus_master_writel, + &dev->bm[1]); + } + + for (i = 0; i < 2; i++) { + dev->bm[i].command = 0x00; + dev->bm[i].status = 0x00; + dev->bm[i].ptr = dev->bm[i].ptr_cur = 0x00000000; + dev->bm[i].addr = 0x00000000; + dev->bm[i].ptr0 = 0x00; + dev->bm[i].count = dev->bm[i].eot = 0x00000000; + } +} + + +static void +piix_reset_hard(void *priv) +{ + piix_t *piix = (piix_t *) priv; + + piix_bus_master_reset(piix); + + memset(piix->regs, 0, 256); + memset(piix->regs_ide, 0, 256); + + piix->regs[0x00] = 0x86; piix->regs[0x01] = 0x80; /*Intel*/ + if (piix->type == 3) { + piix->regs[0x02] = 0x00; piix->regs[0x03] = 0x70; /*82371SB (PIIX3)*/ + } else { + piix->regs[0x02] = 0x2e; piix->regs[0x03] = 0x12; /*82371FB (PIIX)*/ + } + if (piix->type & 0x100) + piix->regs[0x04] = 0x06; + else + piix->regs[0x04] = 0x07; + piix->regs[0x05] = 0x00; + piix->regs[0x06] = 0x80; piix->regs[0x07] = 0x02; + if (piix->type & 0x100) + piix->regs[0x08] = 0x02; /*A0 stepping*/ + else + piix->regs[0x08] = 0x00; /*A0 stepping*/ + piix->regs[0x09] = 0x00; piix->regs[0x0a] = 0x01; piix->regs[0x0b] = 0x06; + if (piix->type & 0x100) + piix->regs[0x0e] = 0x00; /*Single-function device*/ + else + piix->regs[0x0e] = 0x80; /*Multi-function device*/ + piix->regs[0x4c] = 0x4d; + piix->regs[0x4e] = 0x03; + if (piix->type == 3) + piix->regs[0x4f] = 0x00; + piix->regs[0x60] = piix->regs[0x61] = piix->regs[0x62] = piix->regs[0x63] = 0x80; + piix->regs[0x69] = 0x02; + piix->regs[0x70] = 0xc0; + if (piix->type != 3) + piix->regs[0x71] = 0xc0; + piix->regs[0x76] = piix->regs[0x77] = 0x0c; + piix->regs[0x78] = 0x02; piix->regs[0x79] = 0x00; + if (piix->type == 3) { + piix->regs[0x80] = piix->regs[0x82] = 0x00; + } + piix->regs[0xa0] = 0x08; + piix->regs[0xa2] = piix->regs[0xa3] = 0x00; + piix->regs[0xa4] = piix->regs[0xa5] = piix->regs[0xa6] = piix->regs[0xa7] = 0x00; + piix->regs[0xa8] = 0x0f; + piix->regs[0xaa] = piix->regs[0xab] = 0x00; + piix->regs[0xac] = 0x00; + piix->regs[0xae] = 0x00; + + piix->regs_ide[0x00] = 0x86; piix->regs_ide[0x01] = 0x80; /*Intel*/ + if (piix->type == 3) { + piix->regs_ide[0x02] = 0x10; piix->regs_ide[0x03] = 0x70; /*82371SB (PIIX3)*/ + } else { + piix->regs_ide[0x02] = 0x30; piix->regs_ide[0x03] = 0x12; /*82371FB (PIIX)*/ + } + piix->regs_ide[0x04] = 0x03; piix->regs_ide[0x05] = 0x00; + piix->regs_ide[0x06] = 0x80; piix->regs_ide[0x07] = 0x02; + piix->regs_ide[0x08] = 0x00; + piix->regs_ide[0x09] = 0x80; piix->regs_ide[0x0a] = 0x01; piix->regs_ide[0x0b] = 0x01; + piix->regs_ide[0x0d] = 0x00; + piix->regs_ide[0x0e] = 0x00; + piix->regs_ide[0x20] = 0x01; piix->regs_ide[0x21] = piix->regs_ide[0x22] = piix->regs_ide[0x23] = 0x00; /*Bus master interface base address*/ + piix->regs_ide[0x40] = piix->regs_ide[0x42] = 0x00; + piix->regs_ide[0x41] = piix->regs_ide[0x43] = 0x00; + if (piix->type == 3) + piix->regs_ide[0x44] = 0x00; + + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + + pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); + if (piix->type != 3) pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); - ide_pri_disable(); - ide_sec_disable(); + ide_pri_disable(); + ide_sec_disable(); } -void piix3_reset(void) + +static void +piix_reset(void *p) { - piix_bus_master_reset(); - memset(card_piix, 0, 256); - card_piix[0x00] = 0x86; card_piix[0x01] = 0x80; /*Intel*/ - card_piix[0x02] = 0x00; card_piix[0x03] = 0x70; /*82371SB (PIIX3)*/ - card_piix[0x04] = 0x07; card_piix[0x05] = 0x00; - card_piix[0x06] = 0x80; card_piix[0x07] = 0x02; - card_piix[0x08] = 0x00; /*A0 stepping*/ - card_piix[0x09] = 0x00; card_piix[0x0a] = 0x01; card_piix[0x0b] = 0x06; - card_piix[0x0e] = 0x80; /*Multi-function device*/ - card_piix[0x4c] = 0x4d; - card_piix[0x4e] = 0x03; - card_piix[0x4f] = 0x00; - card_piix[0x60] = card_piix[0x61] = card_piix[0x62] = card_piix[0x63] = 0x80; - card_piix[0x69] = 0x02; - card_piix[0x70] = 0xc0; - card_piix[0x76] = card_piix[0x77] = 0x0c; - card_piix[0x78] = 0x02; card_piix[0x79] = 0x00; - card_piix[0x80] = card_piix[0x82] = 0x00; - card_piix[0xa0] = 0x08; - card_piix[0xa2] = card_piix[0xa3] = 0x00; - card_piix[0xa4] = card_piix[0xa5] = card_piix[0xa6] = card_piix[0xa7] = 0x00; - card_piix[0xa8] = 0x0f; - card_piix[0xaa] = card_piix[0xab] = 0x00; - card_piix[0xac] = 0x00; - card_piix[0xae] = 0x00; + int i = 0; - card_piix_ide[0x00] = 0x86; card_piix_ide[0x01] = 0x80; /*Intel*/ - card_piix_ide[0x02] = 0x10; card_piix_ide[0x03] = 0x70; /*82371SB (PIIX3)*/ - card_piix_ide[0x04] = 0x02; card_piix_ide[0x05] = 0x00; - card_piix_ide[0x06] = 0x80; card_piix_ide[0x07] = 0x02; - card_piix_ide[0x08] = 0x00; - card_piix_ide[0x09] = 0x80; card_piix_ide[0x0a] = 0x01; card_piix_ide[0x0b] = 0x01; - card_piix_ide[0x0d] = 0x00; - card_piix_ide[0x0e] = 0x00; - card_piix_ide[0x20] = 0x01; card_piix_ide[0x21] = card_piix_ide[0x22] = card_piix_ide[0x23] = 0x00; /*Bus master interface base address*/ - card_piix_ide[0x40] = card_piix_ide[0x42] = 0x00; - card_piix_ide[0x41] = card_piix_ide[0x43] = 0x80; - card_piix_ide[0x44] = 0x00; - - pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); - - ide_pri_disable(); - ide_sec_disable(); + for (i = 0; i < CDROM_NUM; i++) { + if (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI) + cdrom_reset(cdrom[i]); + } + for (i = 0; i < ZIP_NUM; i++) { + if (zip_drives[i].bus_type == ZIP_BUS_ATAPI) + zip_reset(zip[i]); + } } -void piix_init(int card) + +static void +piix_close(void *p) { - device_add(&ide_pci_2ch_device); + piix_t *piix = (piix_t *)p; - pci_add_card(card, piix_read, piix_write, NULL); - - piix_reset(); - - piix_type = 1; - - ide_set_bus_master(piix_bus_master_dma_read, piix_bus_master_dma_write, piix_bus_master_set_irq); - - port_92_reset(); - - port_92_add(); - - dma_alias_set(); - - pci_reset_handler.pci_set_reset = piix_reset; - - pci_enable_mirq(0); - pci_enable_mirq(1); + free(piix); } -void piix3_init(int card) + +static void +*piix_init(const device_t *info) { - device_add(&ide_pci_2ch_device); + piix_t *piix = (piix_t *) malloc(sizeof(piix_t)); + memset(piix, 0, sizeof(piix_t)); - pci_add_card(card, piix_read, piix_write, NULL); - - piix3_reset(); + device_add(&ide_pci_2ch_device); - piix_type = 3; - - ide_set_bus_master(piix_bus_master_dma_read, piix_bus_master_dma_write, piix_bus_master_set_irq); + pci_add_card(7, piix_read, piix_write, piix); - port_92_reset(); + piix->type = info->local; + piix_reset_hard(piix); - port_92_add(); + ide_set_bus_master(piix_bus_master_dma_read, piix_bus_master_dma_write, + piix_bus_master_set_irq, + &piix->bm[0], &piix->bm[1]); - dma_alias_set(); + port_92_reset(); - pci_reset_handler.pci_set_reset = piix3_reset; + port_92_add(); - pci_enable_mirq(0); + dma_alias_set(); + + pci_enable_mirq(0); + pci_enable_mirq(1); + + return piix; } + + +const device_t piix_device = +{ + "Intel 82371FB (PIIX)", + DEVICE_PCI, + 1, + piix_init, + piix_close, + piix_reset, + NULL, + NULL, + NULL, + NULL +}; + +const device_t piix_pb640_device = +{ + "Intel 82371FB (PIIX) (PB640)", + DEVICE_PCI, + 0x101, + piix_init, + piix_close, + piix_reset, + NULL, + NULL, + NULL, + NULL +}; + +const device_t piix3_device = +{ + "Intel 82371SB (PIIX3)", + DEVICE_PCI, + 3, + piix_init, + piix_close, + piix_reset, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/intel_sio.c b/src/intel_sio.c index cb37a2d48..69c35fa78 100644 --- a/src/intel_sio.c +++ b/src/intel_sio.c @@ -6,18 +6,20 @@ * * Emulation of Intel System I/O PCI chip. * - * Version: @(#)intel_sio.c 1.0.7 2017/11/04 + * Version: @(#)intel_sio.c 1.0.8 2018/04/26 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ -#include #include +#include +#include #include #include +#include "device.h" #include "cpu/cpu.h" #include "io.h" #include "dma.h" @@ -26,144 +28,180 @@ #include "intel_sio.h" -static uint8_t card_sio[256]; - - -static void sio_write(int func, int addr, uint8_t val, void *priv) +typedef struct { - if (func > 0) - return; - - if (addr >= 0x0f && addr < 0x4c) + uint8_t regs[256]; +} sio_t; + + +static void +sio_write(int func, int addr, uint8_t val, void *priv) +{ + sio_t *dev = (sio_t *) priv; + + if (func > 0) + return; + + if (addr >= 0x0f && addr < 0x4c) + return; + + switch (addr) { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0e: return; - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0e: - return; - - case 0x04: /*Command register*/ - val &= 0x08; - val |= 0x07; - break; - case 0x05: - val = 0; - break; - - case 0x06: /*Status*/ - val = 0; - break; - case 0x07: - val = 0x02; - break; - - case 0x40: - if (!((val ^ card_sio[addr]) & 0x40)) - { - return; - } - - if (val & 0x40) - { - dma_alias_remove(); - } - else - { - dma_alias_set(); - } + case 0x04: /*Command register*/ + val &= 0x08; + val |= 0x07; + break; + case 0x05: + val = 0; break; - case 0x4f: - if (!((val ^ card_sio[addr]) & 0x40)) - { + case 0x06: /*Status*/ + val = 0; + break; + case 0x07: + val = 0x02; + break; + + case 0x40: + if (!((val ^ dev->regs[addr]) & 0x40)) return; - } if (val & 0x40) - { - port_92_add(); - } + dma_alias_remove(); + else + dma_alias_set(); + break; + + case 0x4f: + if (!((val ^ dev->regs[addr]) & 0x40)) + return; + + if (val & 0x40) + port_92_add(); else - { port_92_remove(); - } - case 0x60: - if (val & 0x80) - pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTA, val & 0xf); - break; - case 0x61: - if (val & 0x80) - pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTC, val & 0xf); - break; - case 0x62: - if (val & 0x80) - pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTB, val & 0xf); - break; - case 0x63: - if (val & 0x80) - pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTD, val & 0xf); - break; - } - card_sio[addr] = val; + case 0x60: + if (val & 0x80) + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTA, val & 0xf); + break; + case 0x61: + if (val & 0x80) + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTC, val & 0xf); + break; + case 0x62: + if (val & 0x80) + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTB, val & 0xf); + break; + case 0x63: + if (val & 0x80) + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTD, val & 0xf); + break; + } + dev->regs[addr] = val; } -static uint8_t sio_read(int func, int addr, void *priv) +static uint8_t +sio_read(int func, int addr, void *priv) { - if (func > 0) - return 0xff; + sio_t *dev = (sio_t *) priv; + uint8_t ret; - return card_sio[addr]; + ret = 0xff; + + if (func == 0) + ret = dev->regs[addr]; + + return ret; } -static void sio_reset(void) +static void +sio_reset(void *priv) { - memset(card_sio, 0, 256); - card_sio[0x00] = 0x86; card_sio[0x01] = 0x80; /*Intel*/ - card_sio[0x02] = 0x84; card_sio[0x03] = 0x04; /*82378IB (SIO)*/ - card_sio[0x04] = 0x07; card_sio[0x05] = 0x00; - card_sio[0x06] = 0x00; card_sio[0x07] = 0x02; - card_sio[0x08] = 0x03; /*A0 stepping*/ + sio_t *dev = (sio_t *) priv; - card_sio[0x40] = 0x20; card_sio[0x41] = 0x00; - card_sio[0x42] = 0x04; card_sio[0x43] = 0x00; - card_sio[0x44] = 0x20; card_sio[0x45] = 0x10; - card_sio[0x46] = 0x0f; card_sio[0x47] = 0x00; - card_sio[0x48] = 0x01; card_sio[0x49] = 0x10; - card_sio[0x4a] = 0x10; card_sio[0x4b] = 0x0f; - card_sio[0x4c] = 0x56; card_sio[0x4d] = 0x40; - card_sio[0x4e] = 0x07; card_sio[0x4f] = 0x4f; - card_sio[0x54] = 0x00; card_sio[0x55] = 0x00; card_sio[0x56] = 0x00; - card_sio[0x60] = 0x80; card_sio[0x61] = 0x80; card_sio[0x62] = 0x80; card_sio[0x63] = 0x80; - card_sio[0x80] = 0x78; card_sio[0x81] = 0x00; - card_sio[0xa0] = 0x08; - card_sio[0xa8] = 0x0f; + memset(dev->regs, 0, 256); + + dev->regs[0x00] = 0x86; dev->regs[0x01] = 0x80; /*Intel*/ + dev->regs[0x02] = 0x84; dev->regs[0x03] = 0x04; /*82378IB (SIO)*/ + dev->regs[0x04] = 0x07; dev->regs[0x05] = 0x00; + dev->regs[0x06] = 0x00; dev->regs[0x07] = 0x02; + dev->regs[0x08] = 0x03; /*A0 stepping*/ + + dev->regs[0x40] = 0x20; dev->regs[0x41] = 0x00; + dev->regs[0x42] = 0x04; dev->regs[0x43] = 0x00; + dev->regs[0x44] = 0x20; dev->regs[0x45] = 0x10; + dev->regs[0x46] = 0x0f; dev->regs[0x47] = 0x00; + dev->regs[0x48] = 0x01; dev->regs[0x49] = 0x10; + dev->regs[0x4a] = 0x10; dev->regs[0x4b] = 0x0f; + dev->regs[0x4c] = 0x56; dev->regs[0x4d] = 0x40; + dev->regs[0x4e] = 0x07; dev->regs[0x4f] = 0x4f; + dev->regs[0x54] = 0x00; dev->regs[0x55] = 0x00; dev->regs[0x56] = 0x00; + dev->regs[0x60] = 0x80; dev->regs[0x61] = 0x80; dev->regs[0x62] = 0x80; dev->regs[0x63] = 0x80; + dev->regs[0x80] = 0x78; dev->regs[0x81] = 0x00; + dev->regs[0xa0] = 0x08; + dev->regs[0xa8] = 0x0f; + + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); } -void sio_init(int card) +static void +sio_close(void *p) { - pci_add_card(card, sio_read, sio_write, NULL); + sio_t *sio = (sio_t *)p; + + free(sio); +} + + +static void +*sio_init(const device_t *info) +{ + sio_t *sio = (sio_t *) malloc(sizeof(sio_t)); + memset(sio, 0, sizeof(sio_t)); + + pci_add_card(2, sio_read, sio_write, sio); - sio_reset(); + sio_reset(sio); - port_92_reset(); + port_92_reset(); - port_92_add(); + port_92_add(); - dma_alias_set(); + dma_alias_set(); - pci_reset_handler.pci_set_reset = sio_reset; + return sio; } + + +const device_t sio_device = +{ + "Intel 82378IB (SIO)", + DEVICE_PCI, + 0, + sio_init, + sio_close, + NULL, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/intel_sio.h b/src/intel_sio.h index 6ac704d82..b1976b9b2 100644 --- a/src/intel_sio.h +++ b/src/intel_sio.h @@ -6,12 +6,12 @@ * * Emulation of Intel System I/O PCI chip. * - * Version: @(#)sio.h 1.0.2 2017/08/23 + * Version: @(#)sio.h 1.0.3 2018/03/26 * * Author: Sarah Walker, * Miran Grca, - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ -void sio_init(int card); +extern const device_t sio_device; diff --git a/src/io.c b/src/io.c index 8d71dd8e6..8a8b5b6d2 100644 --- a/src/io.c +++ b/src/io.c @@ -8,7 +8,7 @@ * * Implement I/O ports and their operations. * - * Version: @(#)io.c 1.0.3 2018/02/02 + * Version: @(#)io.c 1.0.4 2018/04/29 * * Authors: Sarah Walker, * Miran Grca, @@ -17,11 +17,13 @@ * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 Miran Grca. */ +#include #include #include #include #include #include +#define HAVE_STDARG_H #include "86box.h" #include "io.h" #include "cpu/cpu.h" @@ -48,13 +50,35 @@ int initialized = 0; io_t *io[NPORTS], *io_last[NPORTS]; -#ifdef IO_CATCH -static uint8_t null_inb(uint16_t addr, void *priv) { pclog("IO: read(%04x)\n"); return(0xff); } -static uint16_t null_inw(uint16_t addr, void *priv) { pclog("IO: readw(%04x)\n"); return(0xffff); } -static uint32_t null_inl(uint16_t addr, void *priv) { pclog("IO: readl(%04x)\n"); return(0xffffffff); } -static void null_outb(uint16_t addr, uint8_t val, void *priv) { pclog("IO: write(%04x, %02x)\n", val); } -static void null_outw(uint16_t addr, uint16_t val, void *priv) { pclog("IO: writew(%04x, %04x)\n", val); } -static void null_outl(uint16_t addr, uint32_t val, void *priv) { pclog("IO: writel(%04x, %08lx)\n", val); } +#ifdef ENABLE_IO_LOG +int io_do_log = ENABLE_IO_LOG; +#endif + + +#ifdef ENABLE_IO_LOG +static void +io_log(const char *format, ...) +{ +#ifdef ENABLE_IO_LOG + va_list ap; + + if (io_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} +#endif + + +#ifdef ENABLE_IO_LOG +static uint8_t null_inb(uint16_t addr, void *priv) { io_log("IO: read(%04x)\n"); return(0xff); } +static uint16_t null_inw(uint16_t addr, void *priv) { io_log("IO: readw(%04x)\n"); return(0xffff); } +static uint32_t null_inl(uint16_t addr, void *priv) { io_log("IO: readl(%04x)\n"); return(0xffffffff); } +static void null_outb(uint16_t addr, uint8_t val, void *priv) { io_log("IO: write(%04x, %02x)\n", val); } +static void null_outw(uint16_t addr, uint16_t val, void *priv) { io_log("IO: writew(%04x, %04x)\n", val); } +static void null_outl(uint16_t addr, uint32_t val, void *priv) { io_log("IO: writel(%04x, %08lx)\n", val); } #endif @@ -83,7 +107,7 @@ io_init(void) p = NULL; } -#ifdef IO_CATCH +#ifdef ENABLE_IO_LOG /* io[c] should be the only handler, pointing at the NULL catch handler. */ p = (io_t *) malloc(sizeof(io_t)); memset(p, 0, sizeof(io_t)); @@ -278,9 +302,9 @@ inb(uint16_t port) } } -#ifdef IO_TRACE +#ifdef ENABLE_IO_LOG if (CS == IO_TRACE) - pclog("IOTRACE(%04X): inb(%04x)=%02x\n", IO_TRACE, port, r); + io_log("IOTRACE(%04X): inb(%04x)=%02x\n", IO_TRACE, port, r); #endif return(r); @@ -301,9 +325,9 @@ outb(uint16_t port, uint8_t val) } } -#ifdef IO_TRACE +#ifdef ENABLE_IO_LOG if (CS == IO_TRACE) - pclog("IOTRACE(%04X): outb(%04x,%02x)\n", IO_TRACE, port, val); + io_log("IOTRACE(%04X): outb(%04x,%02x)\n", IO_TRACE, port, val); #endif return; } diff --git a/src/keyboard.h b/src/keyboard.h index 289b1a40c..e4c846b7d 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -8,7 +8,7 @@ * * Definitions for the keyboard interface. * - * Version: @(#)keyboard.h 1.0.14 2018/03/22 + * Version: @(#)keyboard.h 1.0.15 2018/03/26 * * Authors: Sarah Walker, * Miran Grca, @@ -70,6 +70,8 @@ extern const device_t keyboard_ps2_ami_device; extern const device_t keyboard_ps2_mca_device; extern const device_t keyboard_ps2_mca_2_device; extern const device_t keyboard_ps2_quadtel_device; +extern const device_t keyboard_ps2_pci_device; +extern const device_t keyboard_ps2_ami_pci_device; #endif extern void keyboard_init(void); @@ -87,7 +89,6 @@ extern int keyboard_recv(uint16_t key); extern int keyboard_isfsexit(void); extern int keyboard_ismsexit(void); -extern void keyboard_at_reset(void); extern void keyboard_at_adddata_keyboard_raw(uint8_t val); extern void keyboard_at_adddata_mouse(uint8_t val); extern void keyboard_at_set_mouse(void (*mouse_write)(uint8_t val,void *), void *); diff --git a/src/keyboard_at.c b/src/keyboard_at.c index 2a78ef62c..391f725be 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -8,7 +8,7 @@ * * Intel 8042 (AT keyboard controller) emulation. * - * Version: @(#)keyboard_at.c 1.0.33 2018/03/22 + * Version: @(#)keyboard_at.c 1.0.37 2018/05/25 * * Authors: Sarah Walker, * Miran Grca, @@ -44,6 +44,7 @@ #include "sound/snd_speaker.h" #include "video/video.h" #include "keyboard.h" +#include "mouse.h" #define STAT_PARITY 0x80 @@ -121,6 +122,8 @@ typedef struct { uint8_t (*write60_ven)(void *p, uint8_t val); uint8_t (*write64_ven)(void *p, uint8_t val); + + int64_t timeout; } atkbd_t; @@ -1001,6 +1004,20 @@ kbd_pulse_poll(void *p) } +static void +kbd_timeout_poll(void *p) +{ + atkbd_t *kbd = (atkbd_t *) p; + + kbd->key_wantdata = 0; + kbd->want60 = 0; + if (mouse_p) + mouse_clear_data(mouse_p); + + kbd->timeout = 0LL; +} + + static void kbd_keyboard_set(atkbd_t *kbd, uint8_t enable) { @@ -1074,6 +1091,7 @@ kbd_write64_generic(void *p, uint8_t val) if ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) { kbdlog("ATkbd: write mouse output buffer\n"); kbd->want60 = 1; + kbd->timeout = 25000LL * TIMER_USEC; return 0; } break; @@ -1081,6 +1099,7 @@ kbd_write64_generic(void *p, uint8_t val) if ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) { kbdlog("ATkbd: write to mouse\n"); kbd->want60 = 1; + kbd->timeout = 25000LL * TIMER_USEC; return 0; } break; @@ -1122,6 +1141,7 @@ kbd_write60_ami(void *p, uint8_t val) if (kbd->secr_phase == 1) { kbd->mem_addr = val; kbd->want60 = 1; + kbd->timeout = 25000LL * TIMER_USEC; kbd->secr_phase = 2; } else if (kbd->secr_phase == 2) { kbd->mem[kbd->mem_addr] = val; @@ -1164,6 +1184,7 @@ kbd_write64_ami(void *p, uint8_t val) case 0x5c: case 0x5d: case 0x5e: case 0x5f: kbdlog("AMI - alias write to register %08X\n", kbd->command); kbd->want60 = 1; + kbd->timeout = 25000LL * TIMER_USEC; return 0; case 0xa1: /*AMI - get controller version*/ kbdlog("AMI - get controller version\n"); @@ -1229,6 +1250,7 @@ kbd_write64_ami(void *p, uint8_t val) case 0xaf: /*Set extended controller RAM*/ kbdlog("ATkbd: set extended controller RAM\n"); kbd->want60 = 1; + kbd->timeout = 25000LL * TIMER_USEC; kbd->secr_phase = 1; return 0; case 0xb0: case 0xb1: case 0xb2: case 0xb3: @@ -1245,9 +1267,10 @@ kbd_write64_ami(void *p, uint8_t val) return 0; case 0xb8: case 0xb9: case 0xba: case 0xbb: /*Set keyboard controller line P10-P13 (input port bits 0-3) high*/ - if (!PCI || (val > 0xb9)) + if (!PCI || (val > 0xb9)) { kbd->input_port |= (1 << (val & 0x03)); - kbd_adddata(0x00); + kbd_adddata(0x00); + } return 0; case 0xbc: case 0xbd: /*Set keyboard controller line P22-P23 (output port bits 2-3) high*/ @@ -1274,6 +1297,7 @@ kbd_write64_ami(void *p, uint8_t val) case 0xcb: /*AMI - set keyboard mode*/ kbdlog("AMI - set keyboard mode\n"); kbd->want60 = 1; + kbd->timeout = 25000LL * TIMER_USEC; return 0; case 0xef: /*??? - sent by AMI486*/ kbdlog("??? - sent by AMI486\n"); @@ -1343,6 +1367,7 @@ kbd_write64_quadtel(void *p, uint8_t val) case 0xcf: /*??? - sent by MegaPC BIOS*/ kbdlog("??? - sent by MegaPC BIOS\n"); kbd->want60 = 1; + kbd->timeout = 25000LL * TIMER_USEC; return 0; } @@ -1394,6 +1419,7 @@ kbd_write64_toshiba(void *p, uint8_t val) return 0; case 0xb6: /* T3100e: Set colour / mono byte */ kbd->want60 = 1; + kbd->timeout = 25000LL * TIMER_USEC; return 0; case 0xb7: /* T3100e: Emulate PS/2 keyboard - not implemented */ case 0xb8: /* T3100e: Emulate AT keyboard - not implemented */ @@ -1482,10 +1508,8 @@ kbd_write(uint16_t port, uint8_t val, void *priv) kbd_mouse_set(kbd, 1); if (mouse_write && ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1)) mouse_write(val, mouse_p); - else if (!mouse_write && ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1)) { - pclog("Adding 0xFF to queue\n"); + else if (!mouse_write && ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1)) keyboard_at_adddata_mouse(0xff); - } break; default: @@ -1549,6 +1573,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) case 0xed: /*Set/reset LEDs*/ kbdlog("ATkbd: set/reset leds\n"); kbd->key_wantdata = 1; + kbd->timeout = 25000LL * TIMER_USEC; kbd_adddata_keyboard(0xfa); break; @@ -1564,6 +1589,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) case 0xf0: /*Get/set scan code set*/ kbdlog("ATkbd: scan code set\n"); kbd->key_wantdata = 1; + kbd->timeout = 25000LL * TIMER_USEC; kbd_adddata_keyboard(0xfa); break; @@ -1578,6 +1604,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) case 0xf3: /*Set typematic rate/delay*/ kbdlog("ATkbd: set typematic rate/delay\n"); kbd->key_wantdata = 1; + kbd->timeout = 25000LL * TIMER_USEC; kbd_adddata_keyboard(0xfa); break; @@ -1698,6 +1725,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: kbd->want60 = 1; + kbd->timeout = 25000LL * TIMER_USEC; break; case 0xaa: /*Self-test*/ @@ -1755,11 +1783,13 @@ kbd_write(uint16_t port, uint8_t val, void *priv) case 0xd1: /*Write output port*/ // kbdlog("ATkbd: write output port\n"); kbd->want60 = 1; + kbd->timeout = 25000LL * TIMER_USEC; break; case 0xd2: /*Write keyboard output buffer*/ kbdlog("ATkbd: write keyboard output buffer\n"); kbd->want60 = 1; + kbd->timeout = 25000LL * TIMER_USEC; break; case 0xdd: /* Disable A20 Address Line */ @@ -1866,6 +1896,7 @@ kbd_reset(void *priv) kbd->last_irq = 0; kbd->secr_phase = 0; kbd->key_wantdata = 0; + kbd->timeout = 0LL; keyboard_mode = 0x02 | kbd->dtrans; @@ -1911,6 +1942,9 @@ kbd_init(const device_t *info) timer_add(kbd_pulse_poll, &kbd->pulse_cb, &kbd->pulse_cb, kbd); + timer_add(kbd_timeout_poll, + &kbd->timeout, &kbd->timeout, kbd); + kbd->write60_ven = NULL; kbd->write64_ven = NULL; @@ -1971,7 +2005,7 @@ const device_t keyboard_at_device = { kbd_init, kbd_close, kbd_reset, - NULL, NULL, NULL, NULL + NULL, NULL, NULL }; const device_t keyboard_at_ami_device = { @@ -1981,7 +2015,7 @@ const device_t keyboard_at_ami_device = { kbd_init, kbd_close, kbd_reset, - NULL, NULL, NULL, NULL + NULL, NULL, NULL }; const device_t keyboard_at_toshiba_device = { @@ -1991,7 +2025,7 @@ const device_t keyboard_at_toshiba_device = { kbd_init, kbd_close, kbd_reset, - NULL, NULL, NULL, NULL + NULL, NULL, NULL }; const device_t keyboard_ps2_device = { @@ -2001,7 +2035,7 @@ const device_t keyboard_ps2_device = { kbd_init, kbd_close, kbd_reset, - NULL, NULL, NULL, NULL + NULL, NULL, NULL }; const device_t keyboard_ps2_ami_device = { @@ -2011,7 +2045,7 @@ const device_t keyboard_ps2_ami_device = { kbd_init, kbd_close, kbd_reset, - NULL, NULL, NULL, NULL + NULL, NULL, NULL }; const device_t keyboard_ps2_mca_device = { @@ -2021,7 +2055,7 @@ const device_t keyboard_ps2_mca_device = { kbd_init, kbd_close, kbd_reset, - NULL, NULL, NULL, NULL + NULL, NULL, NULL }; const device_t keyboard_ps2_mca_2_device = { @@ -2031,7 +2065,7 @@ const device_t keyboard_ps2_mca_2_device = { kbd_init, kbd_close, kbd_reset, - NULL, NULL, NULL, NULL + NULL, NULL, NULL }; const device_t keyboard_ps2_quadtel_device = { @@ -2041,18 +2075,28 @@ const device_t keyboard_ps2_quadtel_device = { kbd_init, kbd_close, kbd_reset, - NULL, NULL, NULL, NULL + NULL, NULL, NULL }; +const device_t keyboard_ps2_pci_device = { + "PS/2 Keyboard", + DEVICE_PCI, + KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, + kbd_init, + kbd_close, + kbd_reset, + NULL, NULL, NULL +}; -void -keyboard_at_reset(void) -{ - atkbd_t *kbd = CurrentKbd; - - if (kbd != NULL) - kbd_reset(kbd); -} +const device_t keyboard_ps2_ami_pci_device = { + "PS/2 Keyboard (AMI)", + DEVICE_PCI, + KBC_TYPE_PS2_1 | KBC_VEN_AMI, + kbd_init, + kbd_close, + kbd_reset, + NULL, NULL, NULL +}; void diff --git a/src/keyboard_xt.c b/src/keyboard_xt.c index fe9b162a0..80405387c 100644 --- a/src/keyboard_xt.c +++ b/src/keyboard_xt.c @@ -8,7 +8,7 @@ * * Implementation of the XT-style keyboard. * - * Version: @(#)keyboard_xt.c 1.0.11 2018/03/19 + * Version: @(#)keyboard_xt.c 1.0.12 2018/04/26 * * Authors: Sarah Walker, * Miran Grca, @@ -581,7 +581,7 @@ const device_t keyboard_xt_device = { kbd_init, kbd_close, kbd_reset, - NULL, NULL, NULL, NULL + NULL, NULL, NULL }; const device_t keyboard_tandy_device = { @@ -591,5 +591,5 @@ const device_t keyboard_tandy_device = { kbd_init, kbd_close, kbd_reset, - NULL, NULL, NULL, NULL + NULL, NULL, NULL }; diff --git a/src/lang/language.h b/src/lang/language.h index e4c060da8..39e3aff6a 100644 --- a/src/lang/language.h +++ b/src/lang/language.h @@ -10,7 +10,7 @@ * * NOTE: FIXME: Strings 2176 and 2193 are same. * - * Version: @(#)language.h 1.0.7 2018/03/07 + * Version: @(#)language.h 1.0.8 2018/05/25 * * Author: Fred N. van Kempen, * @@ -25,17 +25,17 @@ #define IDS_2049 2049 // "86Box Error" #define IDS_2050 2050 // "86Box Fatal Error" #define IDS_2051 2051 // "This will reset 86Box.." -#define IDS_2052 2052 // "DirectDraw Screenshot Error" -#define IDS_2053 2053 // "Invalid number of sectors.." -#define IDS_2054 2054 // "Invalid number of heads.." -#define IDS_2055 2055 // "Invalid number of cylinders.." +#define IDS_2052 2052 // "Use CTRL+ALT+PAGE DOWN.." +#define IDS_2053 2053 // "Speed" +#define IDS_2054 2054 // "ZIP %i (%03i): %ls" +#define IDS_2055 2055 // "ZIP images (*.IM?)\0*.IM..." #define IDS_2056 2056 // "No usable ROM images found!" #define IDS_2057 2057 // "(empty)" -#define IDS_2058 2058 // "(host drive %c:)" +#define IDS_2058 2058 // "ZIP images (*.IM?)\0*.IM..." #define IDS_2059 2059 // "(Turbo)" #define IDS_2060 2060 // "On" #define IDS_2061 2061 // "Off" -#define IDS_2062 2062 // "86Box was unable to find any.." +#define IDS_2062 2062 // "All floppy images (*.DSK..." #define IDS_2063 2063 // "Configured ROM set not avai.." #define IDS_2064 2064 // "Configured video BIOS not.." #define IDS_2065 2065 // "Machine" @@ -49,114 +49,54 @@ #define IDS_2073 2073 // "Floppy drives" #define IDS_2074 2074 // "Other removable devices" #define IDS_2075 2075 // "CD-ROM images (*.ISO;*.CU.." -#define IDS_2076 2076 // "Host CD/DVD Drive (%c:)" +#define IDS_2076 2076 // "Surface-based images (*.8.." #define IDS_2077 2077 // "Click to capture mouse" #define IDS_2078 2078 // "Press F12-F8 to release mouse" #define IDS_2079 2079 // "Press F12-F8 or middle button.." -#define IDS_2080 2080 // "Drive" -#define IDS_2081 2081 // "Location" +#define IDS_2080 2080 // "E&xport to 86F..." +#define IDS_2081 2081 // "Unable to initialize Flui.." #define IDS_2082 2082 // "Bus" #define IDS_2083 2083 // "File" #define IDS_2084 2084 // "C" #define IDS_2085 2085 // "H" #define IDS_2086 2086 // "S" #define IDS_2087 2087 // "MB" -#define IDS_2088 2088 // "Unable to create bitmap file: %s" -#define IDS_2089 2089 // "Enabled" -#define IDS_2090 2090 // "Mute" -#define IDS_2091 2091 // "Type" -#define IDS_2092 2092 // "Bus" -#define IDS_2093 2093 // "DMA" +#define IDS_2088 2088 // "Check BPB" +#define IDS_2089 2089 // "&Image..." +#define IDS_2090 2090 // "&Reload previous image" +#define IDS_2091 2091 // "E&mpty" +#define IDS_2092 2092 // "&Mute" +#define IDS_2093 2093 // "E&ject" #define IDS_2094 2094 // "KB" #define IDS_2095 2095 // "Neither DirectDraw nor Dire.." -#define IDS_2096 2096 // "Slave" -#define IDS_2097 2097 // "SCSI (ID %s, LUN %s)" -#define IDS_2098 2098 // "Adapter Type" -#define IDS_2099 2099 // "Base Address" -#define IDS_2100 2100 // "IRQ" -#define IDS_2101 2101 // "8-bit DMA" -#define IDS_2102 2102 // "16-bit DMA" -#define IDS_2103 2103 // "BIOS" -#define IDS_2104 2104 // "Network Type" -#define IDS_2105 2105 // "Surround Module" -#define IDS_2106 2106 // "MPU-401 Base Address" -#define IDS_2107 2107 // "Use CTRL+ALT+PAGE DOWN.." -#define IDS_2108 2108 // "On-board RAM" -#define IDS_2109 2109 // "Memory Size" -#define IDS_2110 2110 // "Display Type" -#define IDS_2111 2111 // "RGB" -#define IDS_2112 2112 // "Composite" -#define IDS_2113 2113 // "Composite Type" -#define IDS_2114 2114 // "Old" -#define IDS_2115 2115 // "New" -#define IDS_2116 2116 // "RGB Type" -#define IDS_2117 2117 // "Color" -#define IDS_2118 2118 // "Monochrome (Green)" -#define IDS_2119 2119 // "Monochrome (Amber)" -#define IDS_2120 2120 // "Monochrome (Gray)" -#define IDS_2121 2121 // "Color (no brown)" -#define IDS_2122 2122 // "Monochrome (Default)" -#define IDS_2123 2123 // "Snow Emulation" -#define IDS_2124 2124 // "Bilinear Filtering" -#define IDS_2125 2125 // "Dithering" -#define IDS_2126 2126 // "Framebuffer Memory Size" -#define IDS_2127 2127 // "Texture Memory Size" -#define IDS_2128 2128 // "Screen Filter" -#define IDS_2129 2129 // "Render Threads" -#define IDS_2130 2130 // "Recompiler" -#define IDS_2131 2131 // "System Default" -#define IDS_2132 2132 // "%i Wait state(s)" -#define IDS_2133 2133 // "8-bit" -#define IDS_2134 2134 // "Slow 16-bit" -#define IDS_2135 2135 // "Fast 16-bit" -#define IDS_2136 2136 // "Slow VLB/PCI" -#define IDS_2137 2137 // "Mid VLB/PCI" -#define IDS_2138 2138 // "Fast VLB/PCI" -#define IDS_2139 2139 // "PCap failed to set up.." -#define IDS_2140 2140 // "No PCap devices found" -#define IDS_2141 2141 // "Invalid PCap device" -#define IDS_2142 2142 // "&Notify disk change" -#define IDS_2143 2143 // "Type" -#define IDS_2144 2144 // "Standard 2-button joystick(s)" -#define IDS_2145 2145 // "Standard 4-button joystick" -#define IDS_2146 2146 // "Standard 6-button joystick" -#define IDS_2147 2147 // "Standard 8-button joystick" -#define IDS_2148 2148 // "CH Flightstick Pro" -#define IDS_2149 2149 // "Microsoft SideWinder Pad" -#define IDS_2150 2150 // "Thrustmaster Flight Cont.." -#define IDS_2151 2151 // "Disabled" -#define IDS_2152 2152 // "None" -#define IDS_2153 2153 // "Unable to load Accelerators" -#define IDS_2154 2154 // "Unable to register Raw Input" -#define IDS_2155 2155 // "IRQ %i" -#define IDS_2156 2156 // "%" PRIu64 -#define IDS_2157 2157 // "%" PRIu64 " MB (CHS: %".." -#define IDS_2158 2158 // "Floppy %i (%s): %ls" -#define IDS_2159 2159 // "All floppy images (*.0??;*.." -#define IDS_2160 2160 // "Configuration files (*.CF.." -#define IDS_2161 2161 // "&New image..." -#define IDS_2162 2162 // "&Existing image..." -#define IDS_2163 2163 // "Existing image (&Write-pr..." -#define IDS_2164 2164 // "E&ject" -#define IDS_2165 2165 // "&Mute" -#define IDS_2166 2166 // "E&mpty" -#define IDS_2167 2167 // "&Reload previous image" -#define IDS_2168 2168 // "&Image..." -#define IDS_2169 2169 // "Image (&Write-protected)..." -#define IDS_2170 2170 // "Check BPB" -#define IDS_2171 2171 // "Unable to initialize Flui.." -#define IDS_2172 2172 // "E&xport to 86F..." -#define IDS_2173 2173 // "Surface-based images (*.8.." -#define IDS_2174 2174 // "All floppy images (*.DSK..." -#define IDS_2175 2175 // "ZIP images (*.IM?)\0*.IM..." -#define IDS_2176 2176 // "ZIP images (*.IM?)\0*.IM..." -#define IDS_2177 2177 // "ZIP %i (%03i): %ls" -#define IDS_2178 2178 // "Speed" +#define IDS_2096 2096 // "&New image..." +#define IDS_2097 2097 // "&Existing image..." +#define IDS_2098 2098 // "Existing image (&Write-pr..." +#define IDS_2099 2099 // "Default" +#define IDS_2100 2100 // "%i Wait state(s)" +#define IDS_2101 2101 // "Type" +#define IDS_2102 2102 // "PCap failed to set up.." +#define IDS_2103 2103 // "No PCap devices found" +#define IDS_2104 2104 // "Invalid PCap device" +#define IDS_2105 2105 // "Standard 2-button joystick(s)" +#define IDS_2106 2106 // "Standard 4-button joystick" +#define IDS_2107 2107 // "Standard 6-button joystick" +#define IDS_2108 2108 // "Standard 8-button joystick" +#define IDS_2109 2109 // "CH Flightstick Pro" +#define IDS_2110 2110 // "Microsoft SideWinder Pad" +#define IDS_2111 2111 // "Thrustmaster Flight Cont.." +#define IDS_2112 2112 // "None" +#define IDS_2113 2113 // "Unable to load Accelerators" +#define IDS_2114 2114 // "Unable to register Raw Input" +#define IDS_2115 2115 // "%u" +#define IDS_2116 2116 // "%u MB (CHS: %i, %i, %i)" +#define IDS_2117 2117 // "Floppy %i (%s): %ls" +#define IDS_2118 2118 // "All floppy images (*.0??;*.." #define IDS_4096 4096 // "Hard disk (%s)" #define IDS_4097 4097 // "%01i:%01i" #define IDS_4098 4098 // "%i" -#define IDS_4099 4099 // "Disabled" +#define IDS_4099 4099 // "MFM/RLL or ESDI CD-ROM driv.." #define IDS_4100 4100 // "Custom..." #define IDS_4101 4101 // "Custom (large)..." #define IDS_4102 4102 // "Add New Hard Disk" @@ -171,8 +111,6 @@ #define IDS_4111 4111 // "This image exists and will be.." #define IDS_4112 4112 // "Please enter a valid file name" #define IDS_4113 4113 // "Remember to partition and fo.." -#define IDS_4114 4114 // "MFM/RLL or ESDI CD-ROM driv.." -#define IDS_4115 4115 // "Removable disk %i (SCSI): %ls" #define IDS_4352 4352 // "MFM/RLL" #define IDS_4353 4353 // "XT IDE" @@ -193,17 +131,17 @@ #define IDS_5120 5120 // "CD-ROM %i (%s): %s" #define IDS_5376 5376 // "Disabled" -#define IDS_5377 5377 // "" -#define IDS_5378 5378 // "" -#define IDS_5379 5379 // "" +#define IDS_5377 5377 // +#define IDS_5378 5378 // +#define IDS_5379 5379 // #define IDS_5380 5380 // "ATAPI (PIO-only)" #define IDS_5381 5381 // "ATAPI (PIO and DMA)" #define IDS_5382 5382 // "SCSI" #define IDS_5632 5632 // "Disabled" -#define IDS_5633 5633 // "" -#define IDS_5634 5634 // "" -#define IDS_5635 5635 // "" +#define IDS_5633 5633 // +#define IDS_5634 5634 // +#define IDS_5635 5635 // #define IDS_5636 5636 // "ATAPI (PIO-only) (%01i:%01i)" #define IDS_5637 5637 // "ATAPI (PIO and DMA) (%01i:%01i)" #define IDS_5638 5638 // "SCSI (%02i:%02i)" @@ -232,9 +170,9 @@ #define IDS_LANG_ENUS IDS_7168 -#define STR_NUM_2048 131 +#define STR_NUM_2048 71 #define STR_NUM_3072 11 -#define STR_NUM_4096 20 +#define STR_NUM_4096 18 #define STR_NUM_4352 7 #define STR_NUM_4608 7 #define STR_NUM_5120 1 diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 108a7b638..62614afee 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -32,7 +32,7 @@ * in alpha mode, but in highres ("ECD350") mode, it displays * some semi-random junk. Video-memory pointer maybe? * - * Version: @(#)m_amstrad.c 1.0.11 2018/03/18 + * Version: @(#)m_amstrad.c 1.0.14 2018/04/29 * * Authors: Sarah Walker, * Miran Grca, @@ -42,11 +42,13 @@ * Copyright 2016-2018 Miran Grca. * Copyright 2017,2018 Fred N. van Kempen. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../cpu/cpu.h" #include "../io.h" @@ -150,6 +152,27 @@ static uint8_t crtc_mask[32] = { }; +#ifdef ENABLE_AMSTRAD_LOG +int amstrad_do_log = ENABLE_AMSTRAD_LOG; +#endif + + +static void +amstrad_log(const char *fmt, ...) +{ +#ifdef ENABLE_AMSTRAD_LOG + va_list ap; + + if (amstrad_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + static void recalc_timings_1512(amsvid_t *vid) { @@ -563,7 +586,6 @@ static const device_t vid_1512_device = { NULL, vid_close_1512, NULL, NULL, vid_speed_change_1512, - NULL, NULL }; @@ -727,7 +749,6 @@ static const device_t vid_1640_device = { NULL, vid_close_1640, NULL, NULL, vid_speed_changed_1640, - NULL, NULL }; @@ -862,7 +883,6 @@ static const device_t vid_200_device = { NULL, vid_close_200, NULL, NULL, vid_speed_changed_200, - NULL, NULL }; @@ -918,10 +938,8 @@ static void kbd_adddata(uint16_t val) { key_queue[key_queue_end] = val; -#if ENABLE_KEYBOARD_LOG - pclog("keyboard_amstrad : %02X added to key queue at %i\n", + amstrad_log("keyboard_amstrad : %02X added to key queue at %i\n", val, key_queue_end); -#endif key_queue_end = (key_queue_end + 1) & 0xf; } @@ -937,13 +955,8 @@ static void kbd_write(uint16_t port, uint8_t val, void *priv) { amstrad_t *ams = (amstrad_t *)priv; -#ifdef WALTJE - int i = 0; -#endif -#if ENABLE_KEYBOARD_LOG - pclog("keyboard_amstrad : write %04X %02X %02X\n", port, val, ams->pb); -#endif + amstrad_log("keyboard_amstrad : write %04X %02X %02X\n", port, val, ams->pb); switch (port) { case 0x61: @@ -961,13 +974,9 @@ kbd_write(uint16_t port, uint8_t val, void *priv) * * This register is controlled by BIOS and/or ROS. */ -#if ENABLE_KEYBOARD_LOG - pclog("AMSkb: write PB %02x (%02x)\n", val, ams->pb); -#endif + amstrad_log("AMSkb: write PB %02x (%02x)\n", val, ams->pb); if (!(ams->pb & 0x40) && (val & 0x40)) { /*Reset keyboard*/ -#if ENABLE_KEYBOARD_LOG - pclog("AMSkb: reset keyboard\n"); -#endif + amstrad_log("AMSkb: reset keyboard\n"); kbd_adddata(0xaa); } ams->pb = val; @@ -993,30 +1002,19 @@ kbd_write(uint16_t port, uint8_t val, void *priv) break; case 0x64: -#ifdef WALTJE - pclog("AMSkb: STAT1 = %02x (%02x)\n", val, ams->stat1); -#endif ams->stat1 = val; break; case 0x65: -#ifdef WALTJE - pclog("AMSkb: STAT2 = %02x (%02x)\n", val, ams->stat2); - i = 512 + (((val & 0x1f) - 0x0e) * 32); - pclog("AMSkb: %d KB RAM installed.\n", i); -#endif ams->stat2 = val; break; case 0x66: -#ifdef WALTJE - pclog("AMSkb: RESET REQUESTED !\n"); -#endif pc_reset(1); break; default: - pclog("AMSkb: bad keyboard write %04X %02X\n", port, val); + amstrad_log("AMSkb: bad keyboard write %04X %02X\n", port, val); } } @@ -1105,7 +1103,7 @@ kbd_read(uint16_t port, void *priv) break; default: - pclog("AMDkb: bad keyboard read %04X\n", port); + amstrad_log("AMDkb: bad keyboard read %04X\n", port); } return(ret); @@ -1123,17 +1121,13 @@ kbd_poll(void *priv) ams->wantirq = 0; ams->pa = ams->key_waiting; picint(2); -#if ENABLE_KEYBOARD_LOG - pclog("keyboard_amstrad : take IRQ\n"); -#endif + amstrad_log("keyboard_amstrad : take IRQ\n"); } if (key_queue_start != key_queue_end && !ams->pa) { ams->key_waiting = key_queue[key_queue_start]; -#if ENABLE_KEYBOARD_LOG - pclog("Reading %02X from the key queue at %i\n", + amstrad_log("Reading %02X from the key queue at %i\n", ams->key_waiting, key_queue_start); -#endif key_queue_start = (key_queue_start + 1) & 0xf; ams->wantirq = 1; } @@ -1205,7 +1199,7 @@ machine_amstrad_init(const machine_t *model) ams = (amstrad_t *)malloc(sizeof(amstrad_t)); memset(ams, 0x00, sizeof(amstrad_t)); - nvr_at_init(1); + device_add(&amstrad_nvr_device); machine_common_init(model); diff --git a/src/machine/m_at.c b/src/machine/m_at.c index edbec78a2..d4bf80adb 100644 --- a/src/machine/m_at.c +++ b/src/machine/m_at.c @@ -30,7 +30,7 @@ machine_at_common_init(const machine_t *model) if (lpt_enabled) lpt2_remove(); - nvr_at_init(8); + device_add(&at_nvr_device); if (joystick_type != 7) device_add(&gameport_device); diff --git a/src/machine/m_at_430fx.c b/src/machine/m_at_430fx.c deleted file mode 100644 index 31c63d74a..000000000 --- a/src/machine/m_at_430fx.c +++ /dev/null @@ -1,345 +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 Intel 430FX PCISet chip. - * - * Version: @(#)m_at_430fx.c 1.0.14 2018/03/18 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016,2018 Miran Grca. - */ -#include -#include -#include -#include -#include "../86box.h" -#include "../mem.h" -#include "../memregs.h" -#include "../rom.h" -#include "../pci.h" -#include "../device.h" -#include "../keyboard.h" -#include "../piix.h" -#include "../intel_flash.h" -#include "../sio.h" -#include "../video/video.h" -#include "../video/vid_cl54xx.h" -#include "../video/vid_s3.h" -#include "machine.h" - - -static uint8_t card_i430fx[256]; - - -static void i430fx_map(uint32_t addr, uint32_t size, int state) -{ - switch (state & 3) - { - case 0: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - break; - case 1: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); - break; - case 2: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - break; - case 3: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - } - flushmmucache_nopc(); -} - - -static void i430fx_write(int func, int addr, uint8_t val, void *priv) -{ - if (func) - return; - - if (addr >= 0x10 && addr < 0x4f) - return; - - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0e: - return; - - case 0x04: /*Command register*/ - val &= 0x02; - val |= 0x04; - break; - case 0x05: - val = 0; - break; - - case 0x06: /*Status*/ - val = 0; - break; - case 0x07: - val = 0x02; - break; - - case 0x59: /*PAM0*/ - if ((card_i430fx[0x59] ^ val) & 0xf0) - { - i430fx_map(0xf0000, 0x10000, val >> 4); - shadowbios = (val & 0x10); - } - pclog("i430fx_write : PAM0 write %02X\n", val); - break; - case 0x5a: /*PAM1*/ - if ((card_i430fx[0x5a] ^ val) & 0x0f) - i430fx_map(0xc0000, 0x04000, val & 0xf); - if ((card_i430fx[0x5a] ^ val) & 0xf0) - i430fx_map(0xc4000, 0x04000, val >> 4); - break; - case 0x5b: /*PAM2*/ - if ((card_i430fx[0x5b] ^ val) & 0x0f) - i430fx_map(0xc8000, 0x04000, val & 0xf); - if ((card_i430fx[0x5b] ^ val) & 0xf0) - i430fx_map(0xcc000, 0x04000, val >> 4); - break; - case 0x5c: /*PAM3*/ - if ((card_i430fx[0x5c] ^ val) & 0x0f) - i430fx_map(0xd0000, 0x04000, val & 0xf); - if ((card_i430fx[0x5c] ^ val) & 0xf0) - i430fx_map(0xd4000, 0x04000, val >> 4); - break; - case 0x5d: /*PAM4*/ - if ((card_i430fx[0x5d] ^ val) & 0x0f) - i430fx_map(0xd8000, 0x04000, val & 0xf); - if ((card_i430fx[0x5d] ^ val) & 0xf0) - i430fx_map(0xdc000, 0x04000, val >> 4); - break; - case 0x5e: /*PAM5*/ - if ((card_i430fx[0x5e] ^ val) & 0x0f) - i430fx_map(0xe0000, 0x04000, val & 0xf); - if ((card_i430fx[0x5e] ^ val) & 0xf0) - i430fx_map(0xe4000, 0x04000, val >> 4); - pclog("i430fx_write : PAM5 write %02X\n", val); - break; - case 0x5f: /*PAM6*/ - if ((card_i430fx[0x5f] ^ val) & 0x0f) - i430fx_map(0xe8000, 0x04000, val & 0xf); - if ((card_i430fx[0x5f] ^ val) & 0xf0) - i430fx_map(0xec000, 0x04000, val >> 4); - pclog("i430fx_write : PAM6 write %02X\n", val); - break; - case 0x72: /*SMRAM*/ - if ((card_i430fx[0x72] ^ val) & 0x48) - i430fx_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0); - break; - } - - card_i430fx[addr] = val; -} - - -static uint8_t i430fx_read(int func, int addr, void *priv) -{ - if (func) - return 0xff; - - return card_i430fx[addr]; -} - - -static void i430fx_reset(void) -{ - memset(card_i430fx, 0, 256); - card_i430fx[0x00] = 0x86; card_i430fx[0x01] = 0x80; /*Intel*/ - card_i430fx[0x02] = 0x2d; card_i430fx[0x03] = 0x16; /*SB82437FX-66*/ - card_i430fx[0x04] = 0x06; card_i430fx[0x05] = 0x00; - card_i430fx[0x06] = 0x00; card_i430fx[0x07] = 0x82; - if (romset == ROM_MB500N) card_i430fx[0x07] = 0x02; - card_i430fx[0x08] = 0x00; /*A0 stepping*/ - card_i430fx[0x09] = 0x00; card_i430fx[0x0a] = 0x00; card_i430fx[0x0b] = 0x06; - card_i430fx[0x52] = 0x40; /*256kb PLB cache*/ - if (romset == ROM_MB500N) - { - card_i430fx[0x52] = 0x42; - card_i430fx[0x53] = 0x14; - card_i430fx[0x56] = 0x52; /*DRAM control*/ - } - card_i430fx[0x57] = 0x01; - card_i430fx[0x60] = card_i430fx[0x61] = card_i430fx[0x62] = card_i430fx[0x63] = card_i430fx[0x64] = 0x02; - if (romset == ROM_MB500N) - { - card_i430fx[0x67] = 0x11; - card_i430fx[0x69] = 0x03; - card_i430fx[0x70] = 0x20; - } - card_i430fx[0x72] = 0x02; - if (romset == ROM_MB500N) - { - card_i430fx[0x74] = 0x0e; - card_i430fx[0x78] = 0x23; - } -} - - -static void i430fx_pci_reset(void) -{ - i430fx_write(0, 0x59, 0x00, NULL); - i430fx_write(0, 0x72, 0x02, NULL); -} - - -static void i430fx_init(void) -{ - pci_add_card(0, i430fx_read, i430fx_write, NULL); - - i430fx_reset(); - - pci_reset_handler.pci_master_reset = i430fx_pci_reset; -} - - -void -machine_at_p54tp4xe_init(const machine_t *model) -{ - machine_at_ps2_init(model); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430fx_init(); - piix3_init(7); - fdc37c665_init(); - - device_add(&intel_flash_bxt_device); -} - - -void -machine_at_endeavor_init(const machine_t *model) -{ - machine_at_common_init(model); - device_add(&keyboard_ps2_ami_device); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430fx_init(); - piix_init(7); - pc87306_init(); - - device_add(&intel_flash_bxt_ami_device); - - if (gfxcard == GFX_INTERNAL) - device_add(&s3_phoenix_trio64_onboard_pci_device); -} - - -const device_t * -at_endeavor_get_device(void) -{ - return &s3_phoenix_trio64_onboard_pci_device; -} - - -void -machine_at_zappa_init(const machine_t *model) -{ - machine_at_common_init(model); - device_add(&keyboard_ps2_ami_device); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430fx_init(); - piix_init(7); - pc87306_init(); - - device_add(&intel_flash_bxt_ami_device); -} - - -void -machine_at_mb500n_init(const machine_t *model) -{ - machine_at_ps2_init(model); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430fx_init(); - piix_init(7); - fdc37c665_init(); - - device_add(&intel_flash_bxt_device); -} - - -void -machine_at_president_init(const machine_t *model) -{ - machine_at_ps2_init(model); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430fx_init(); - piix_init(7); - w83877f_init(); - - device_add(&intel_flash_bxt_device); -} - - -void -machine_at_thor_init(const machine_t *model) -{ - machine_at_common_init(model); - device_add(&keyboard_ps2_ami_device); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 2, 1); - pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 3, 2, 1); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430fx_init(); - piix_init(7); - pc87306_init(); - - device_add(&intel_flash_bxt_ami_device); -} diff --git a/src/machine/m_at_430hx.c b/src/machine/m_at_430hx.c deleted file mode 100644 index 74f735a28..000000000 --- a/src/machine/m_at_430hx.c +++ /dev/null @@ -1,329 +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 Intel 430HX PCISet chip. - * - * Version: @(#)m_at_430hx.c 1.0.11 2018/03/18 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ -#include -#include -#include -#include -#include "../86box.h" -#include "../io.h" -#include "../mem.h" -#include "../memregs.h" -#include "../pci.h" -#include "../device.h" -#include "../keyboard.h" -#include "../piix.h" -#include "../intel_flash.h" -#include "../sio.h" -#include "machine.h" - - -static uint8_t card_i430hx[256]; - - -static void i430hx_map(uint32_t addr, uint32_t size, int state) -{ - switch (state & 3) - { - case 0: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - break; - case 1: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); - break; - case 2: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - break; - case 3: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - } - flushmmucache_nopc(); -} - - -static void i430hx_write(int func, int addr, uint8_t val, void *priv) -{ - if (func) - return; - - if ((addr >= 0x10) && (addr < 0x4f)) - return; - - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0e: - return; - - case 0x04: /*Command register*/ - val &= 0x02; - val |= 0x04; - break; - case 0x05: - val = 0; - break; - - case 0x06: /*Status*/ - val = 0; - break; - case 0x07: - val &= 0x80; - val |= 0x02; - break; - - case 0x59: /*PAM0*/ - if ((card_i430hx[0x59] ^ val) & 0xf0) - { - i430hx_map(0xf0000, 0x10000, val >> 4); - shadowbios = (val & 0x10); - } - break; - case 0x5a: /*PAM1*/ - if ((card_i430hx[0x5a] ^ val) & 0x0f) - i430hx_map(0xc0000, 0x04000, val & 0xf); - if ((card_i430hx[0x5a] ^ val) & 0xf0) - i430hx_map(0xc4000, 0x04000, val >> 4); - break; - case 0x5b: /*PAM2*/ - if ((card_i430hx[0x5b] ^ val) & 0x0f) - i430hx_map(0xc8000, 0x04000, val & 0xf); - if ((card_i430hx[0x5b] ^ val) & 0xf0) - i430hx_map(0xcc000, 0x04000, val >> 4); - break; - case 0x5c: /*PAM3*/ - if ((card_i430hx[0x5c] ^ val) & 0x0f) - i430hx_map(0xd0000, 0x04000, val & 0xf); - if ((card_i430hx[0x5c] ^ val) & 0xf0) - i430hx_map(0xd4000, 0x04000, val >> 4); - break; - case 0x5d: /*PAM4*/ - if ((card_i430hx[0x5d] ^ val) & 0x0f) - i430hx_map(0xd8000, 0x04000, val & 0xf); - if ((card_i430hx[0x5d] ^ val) & 0xf0) - i430hx_map(0xdc000, 0x04000, val >> 4); - break; - case 0x5e: /*PAM5*/ - if ((card_i430hx[0x5e] ^ val) & 0x0f) - i430hx_map(0xe0000, 0x04000, val & 0xf); - if ((card_i430hx[0x5e] ^ val) & 0xf0) - i430hx_map(0xe4000, 0x04000, val >> 4); - break; - case 0x5f: /*PAM6*/ - if ((card_i430hx[0x5f] ^ val) & 0x0f) - i430hx_map(0xe8000, 0x04000, val & 0xf); - if ((card_i430hx[0x5f] ^ val) & 0xf0) - i430hx_map(0xec000, 0x04000, val >> 4); - break; - case 0x72: /*SMRAM*/ - if ((card_i430hx[0x72] ^ val) & 0x48) - i430hx_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0); - break; - } - - card_i430hx[addr] = val; -} - - -static uint8_t i430hx_read(int func, int addr, void *priv) -{ - if (func) - return 0xff; - - return card_i430hx[addr]; -} - - -static void i430hx_reset(void) -{ - memset(card_i430hx, 0, 256); - card_i430hx[0x00] = 0x86; card_i430hx[0x01] = 0x80; /*Intel*/ - card_i430hx[0x02] = 0x50; card_i430hx[0x03] = 0x12; /*82439HX*/ - card_i430hx[0x04] = 0x06; card_i430hx[0x05] = 0x00; - card_i430hx[0x06] = 0x00; card_i430hx[0x07] = 0x02; - card_i430hx[0x08] = 0x00; /*A0 stepping*/ - card_i430hx[0x09] = 0x00; card_i430hx[0x0a] = 0x00; card_i430hx[0x0b] = 0x06; - card_i430hx[0x51] = 0x20; - card_i430hx[0x52] = 0xB5; /*512kb cache*/ - - card_i430hx[0x59] = 0x40; - card_i430hx[0x5A] = card_i430hx[0x5B] = card_i430hx[0x5C] = card_i430hx[0x5D] = card_i430hx[0x5E] = card_i430hx[0x5F] = 0x44; - - card_i430hx[0x56] = 0x52; /*DRAM control*/ - card_i430hx[0x57] = 0x01; - card_i430hx[0x60] = card_i430hx[0x61] = card_i430hx[0x62] = card_i430hx[0x63] = card_i430hx[0x64] = card_i430hx[0x65] = card_i430hx[0x66] = card_i430hx[0x67] = 0x02; - card_i430hx[0x68] = 0x11; - card_i430hx[0x72] = 0x02; -} - - -static void i430hx_pci_reset(void) -{ - i430hx_write(0, 0x59, 0x00, NULL); - i430hx_write(0, 0x72, 0x02, NULL); -} - - -static void i430hx_init(void) -{ - pci_add_card(0, i430hx_read, i430hx_write, NULL); - - i430hx_reset(); - - pci_reset_handler.pci_master_reset = i430hx_pci_reset; -} - - -static int acerm3a_index; - - -static void -acerm3a_out(uint16_t port, uint8_t val, void *p) -{ - if (port == 0xea) - acerm3a_index = val; -} - -static uint8_t -acerm3a_in(uint16_t port, void *p) -{ - if (port == 0xeb) - { - switch (acerm3a_index) - { - case 2: - return 0xfd; - } - } - return 0xff; -} - - -void -machine_at_acerm3a_init(const machine_t *model) -{ - machine_at_ps2_init(model); - - powermate_memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x1F, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x10, PCI_CARD_ONBOARD, 4, 0, 0, 0); - i430hx_init(); - piix3_init(7); - fdc37c932fr_init(); - io_sethandler(0x00ea, 0x0002, acerm3a_in, NULL, NULL, acerm3a_out, NULL, NULL, NULL); - - device_add(&intel_flash_bxb_device); -} - - -void -machine_at_acerv35n_init(const machine_t *model) -{ - machine_at_ps2_init(model); - - powermate_memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - i430hx_init(); - piix3_init(7); - fdc37c932fr_init(); - io_sethandler(0x00ea, 0x0002, acerm3a_in, NULL, NULL, acerm3a_out, NULL, NULL, NULL); - - device_add(&intel_flash_bxb_device); -} - - -void -machine_at_ap53_init(const machine_t *model) -{ - machine_at_common_init(model); - device_add(&keyboard_ps2_ami_device); - - memregs_init(); - powermate_memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x06, PCI_CARD_ONBOARD, 1, 2, 3, 4); - i430hx_init(); - piix3_init(7); - fdc37c669_init(); - - device_add(&intel_flash_bxt_device); -} - - -void -machine_at_p55t2p4_init(const machine_t *model) -{ - machine_at_ps2_init(model); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430hx_init(); - piix3_init(7); - w83877f_init(); - - device_add(&intel_flash_bxt_device); -} - - -void -machine_at_p55t2s_init(const machine_t *model) -{ - machine_at_common_init(model); - device_add(&keyboard_ps2_ami_device); - - memregs_init(); - powermate_memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430hx_init(); - piix3_init(7); - pc87306_init(); - - device_add(&intel_flash_bxt_device); -} diff --git a/src/machine/m_at_430lx_nx.c b/src/machine/m_at_430lx_nx.c deleted file mode 100644 index c2c80483e..000000000 --- a/src/machine/m_at_430lx_nx.c +++ /dev/null @@ -1,250 +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 Intel 430LX and 430NX PCISet chips. - * - * Version: @(#)m_at_430lx_nx.c 1.0.10 2018/03/18 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ -#include -#include -#include -#include -#include "../86box.h" -#include "../mem.h" -#include "../memregs.h" -#include "../rom.h" -#include "../pci.h" -#include "../device.h" -#include "../keyboard.h" -#include "../intel.h" -#include "../intel_flash.h" -#include "../intel_sio.h" -#include "../sio.h" -#include "machine.h" - - -static uint8_t card_i430_lx_nx[256]; - - -static void i430lx_nx_map(uint32_t addr, uint32_t size, int state) -{ - switch (state & 3) - { - case 0: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - break; - case 1: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); - break; - case 2: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - break; - case 3: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - } - flushmmucache_nopc(); -} - - -static void i430lx_nx_write(int func, int addr, uint8_t val, void *priv) -{ - if (func) - return; - - if ((addr >= 0x10) && (addr < 0x4f)) - return; - - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0e: - return; - - case 0x04: /*Command register*/ - val &= 0x42; - val |= 0x04; - break; - case 0x05: - val &= 0x01; - break; - - case 0x06: /*Status*/ - val = 0; - break; - case 0x07: - val = 0x02; - break; - - case 0x59: /*PAM0*/ - if ((card_i430_lx_nx[0x59] ^ val) & 0xf0) - { - i430lx_nx_map(0xf0000, 0x10000, val >> 4); - shadowbios = (val & 0x10); - } - pclog("i430lx_write : PAM0 write %02X\n", val); - break; - case 0x5a: /*PAM1*/ - if ((card_i430_lx_nx[0x5a] ^ val) & 0x0f) - i430lx_nx_map(0xc0000, 0x04000, val & 0xf); - if ((card_i430_lx_nx[0x5a] ^ val) & 0xf0) - i430lx_nx_map(0xc4000, 0x04000, val >> 4); - break; - case 0x5b: /*PAM2*/ - if (romset == ROM_REVENGE) - { - if ((card_i430_lx_nx[0x5b] ^ val) & 0x0f) - i430lx_nx_map(0xc8000, 0x04000, val & 0xf); - if ((card_i430_lx_nx[0x5b] ^ val) & 0xf0) - i430lx_nx_map(0xcc000, 0x04000, val >> 4); - } - break; - case 0x5c: /*PAM3*/ - if ((card_i430_lx_nx[0x5c] ^ val) & 0x0f) - i430lx_nx_map(0xd0000, 0x04000, val & 0xf); - if ((card_i430_lx_nx[0x5c] ^ val) & 0xf0) - i430lx_nx_map(0xd4000, 0x04000, val >> 4); - break; - case 0x5d: /*PAM4*/ - if ((card_i430_lx_nx[0x5d] ^ val) & 0x0f) - i430lx_nx_map(0xd8000, 0x04000, val & 0xf); - if ((card_i430_lx_nx[0x5d] ^ val) & 0xf0) - i430lx_nx_map(0xdc000, 0x04000, val >> 4); - break; - case 0x5e: /*PAM5*/ - if ((card_i430_lx_nx[0x5e] ^ val) & 0x0f) - i430lx_nx_map(0xe0000, 0x04000, val & 0xf); - if ((card_i430_lx_nx[0x5e] ^ val) & 0xf0) - i430lx_nx_map(0xe4000, 0x04000, val >> 4); - pclog("i430lx_write : PAM5 write %02X\n", val); - break; - case 0x5f: /*PAM6*/ - if ((card_i430_lx_nx[0x5f] ^ val) & 0x0f) - i430lx_nx_map(0xe8000, 0x04000, val & 0xf); - if ((card_i430_lx_nx[0x5f] ^ val) & 0xf0) - i430lx_nx_map(0xec000, 0x04000, val >> 4); - pclog("i430lx_write : PAM6 write %02X\n", val); - break; - } - - card_i430_lx_nx[addr] = val; -} - - -static uint8_t i430lx_nx_read(int func, int addr, void *priv) -{ - if (func) - return 0xff; - - return card_i430_lx_nx[addr]; -} - - -static void i430lx_nx_reset_common(void) -{ - memset(card_i430_lx_nx, 0, 256); - card_i430_lx_nx[0x00] = 0x86; card_i430_lx_nx[0x01] = 0x80; /*Intel*/ - card_i430_lx_nx[0x02] = 0xa3; card_i430_lx_nx[0x03] = 0x04; /*82434LX/NX*/ - card_i430_lx_nx[0x04] = 0x06; card_i430_lx_nx[0x05] = 0x00; - card_i430_lx_nx[0x06] = 0x00; card_i430_lx_nx[0x07] = 0x02; - card_i430_lx_nx[0x09] = 0x00; card_i430_lx_nx[0x0a] = 0x00; card_i430_lx_nx[0x0b] = 0x06; - card_i430_lx_nx[0x57] = 0x31; - card_i430_lx_nx[0x60] = card_i430_lx_nx[0x61] = card_i430_lx_nx[0x62] = card_i430_lx_nx[0x63] = card_i430_lx_nx[0x64] = 0x02; -} - - -static void i430lx_reset(void) -{ - i430lx_nx_reset_common(); - card_i430_lx_nx[0x08] = 0x03; /*A3 stepping*/ - card_i430_lx_nx[0x50] = 0x80; - card_i430_lx_nx[0x52] = 0x40; /*256kb PLB cache*/ -} - - -static void i430nx_reset(void) -{ - i430lx_nx_reset_common(); - card_i430_lx_nx[0x08] = 0x10; /*A0 stepping*/ - card_i430_lx_nx[0x50] = 0xA0; - card_i430_lx_nx[0x52] = 0x44; /*256kb PLB cache*/ - card_i430_lx_nx[0x66] = card_i430_lx_nx[0x67] = 0x02; -} - - -static void i430lx_nx_pci_reset(void) -{ - i430lx_nx_write(0, 0x59, 0x00, NULL); -} - - -static void i430lx_init(void) -{ - pci_add_card(0, i430lx_nx_read, i430lx_nx_write, NULL); - - i430lx_reset(); - - pci_reset_handler.pci_master_reset = i430lx_nx_pci_reset; -} - - -static void i430nx_init(void) -{ - pci_add_card(0, i430lx_nx_read, i430lx_nx_write, NULL); - - i430nx_reset(); - - pci_reset_handler.pci_master_reset = i430lx_nx_pci_reset; -} - - -static void -machine_at_premiere_common_init(const machine_t *model) -{ - machine_at_common_init(model); - device_add(&keyboard_ps2_ami_device); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_2); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x01, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); - pci_register_slot(0x02, PCI_CARD_SPECIAL, 0, 0, 0, 0); - sio_init(2); - fdc37c665_init(); - intel_batman_init(); - - device_add(&intel_flash_bxt_ami_device); -} - - -void -machine_at_batman_init(const machine_t *model) -{ - machine_at_premiere_common_init(model); - - i430lx_init(); -} - - -void -machine_at_plato_init(const machine_t *model) -{ - machine_at_premiere_common_init(model); - - i430nx_init(); -} diff --git a/src/machine/m_at_430vx.c b/src/machine/m_at_430vx.c deleted file mode 100644 index 9165dd203..000000000 --- a/src/machine/m_at_430vx.c +++ /dev/null @@ -1,254 +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 Intel 430VX PCISet chip. - * - * Version: @(#)m_at_430vx.c 1.0.11 2018/03/18 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ -#include -#include -#include -#include -#include "../86box.h" -#include "../io.h" -#include "../pci.h" -#include "../mem.h" -#include "../memregs.h" -#include "../device.h" -#include "../piix.h" -#include "../intel_flash.h" -#include "../sio.h" -#include "machine.h" - - -static uint8_t card_i430vx[256]; - - -static void i430vx_map(uint32_t addr, uint32_t size, int state) -{ - switch (state & 3) - { - case 0: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - break; - case 1: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); - break; - case 2: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - break; - case 3: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - } - flushmmucache_nopc(); -} - - -static void i430vx_write(int func, int addr, uint8_t val, void *priv) -{ - if (func) - return; - - if ((addr >= 0x10) && (addr < 0x4f)) - return; - - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0e: - return; - - case 0x04: /*Command register*/ - val &= 0x02; - val |= 0x04; - break; - case 0x05: - val = 0; - break; - - case 0x06: /*Status*/ - val = 0; - break; - case 0x07: - val &= 0x80; - val |= 0x02; - break; - - case 0x59: /*PAM0*/ - if ((card_i430vx[0x59] ^ val) & 0xf0) - { - i430vx_map(0xf0000, 0x10000, val >> 4); - shadowbios = (val & 0x10); - } - /* pclog("i430vx_write : PAM0 write %02X\n", val); */ - break; - case 0x5a: /*PAM1*/ - if ((card_i430vx[0x5a] ^ val) & 0x0f) - i430vx_map(0xc0000, 0x04000, val & 0xf); - if ((card_i430vx[0x5a] ^ val) & 0xf0) - i430vx_map(0xc4000, 0x04000, val >> 4); - break; - case 0x5b: /*PAM2*/ - if ((card_i430vx[0x5b] ^ val) & 0x0f) - i430vx_map(0xc8000, 0x04000, val & 0xf); - if ((card_i430vx[0x5b] ^ val) & 0xf0) - i430vx_map(0xcc000, 0x04000, val >> 4); - break; - case 0x5c: /*PAM3*/ - if ((card_i430vx[0x5c] ^ val) & 0x0f) - i430vx_map(0xd0000, 0x04000, val & 0xf); - if ((card_i430vx[0x5c] ^ val) & 0xf0) - i430vx_map(0xd4000, 0x04000, val >> 4); - break; - case 0x5d: /*PAM4*/ - if ((card_i430vx[0x5d] ^ val) & 0x0f) - i430vx_map(0xd8000, 0x04000, val & 0xf); - if ((card_i430vx[0x5d] ^ val) & 0xf0) - i430vx_map(0xdc000, 0x04000, val >> 4); - break; - case 0x5e: /*PAM5*/ - if ((card_i430vx[0x5e] ^ val) & 0x0f) - i430vx_map(0xe0000, 0x04000, val & 0xf); - if ((card_i430vx[0x5e] ^ val) & 0xf0) - i430vx_map(0xe4000, 0x04000, val >> 4); - /* pclog("i430vx_write : PAM5 write %02X\n", val); */ - break; - case 0x5f: /*PAM6*/ - if ((card_i430vx[0x5f] ^ val) & 0x0f) - i430vx_map(0xe8000, 0x04000, val & 0xf); - if ((card_i430vx[0x5f] ^ val) & 0xf0) - i430vx_map(0xec000, 0x04000, val >> 4); - /* pclog("i430vx_write : PAM6 write %02X\n", val); */ - break; - case 0x72: /*SMRAM*/ - if ((card_i430vx[0x72] ^ val) & 0x48) - i430vx_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0); - break; - } - - card_i430vx[addr] = val; -} - - -static uint8_t i430vx_read(int func, int addr, void *priv) -{ - if (func) - return 0xff; - - return card_i430vx[addr]; -} - - -static void i430vx_reset(void) -{ - memset(card_i430vx, 0, 256); - card_i430vx[0x00] = 0x86; card_i430vx[0x01] = 0x80; /*Intel*/ - card_i430vx[0x02] = 0x30; card_i430vx[0x03] = 0x70; /*82437VX*/ - card_i430vx[0x04] = 0x06; card_i430vx[0x05] = 0x00; - card_i430vx[0x06] = 0x00; card_i430vx[0x07] = 0x02; - card_i430vx[0x08] = 0x00; /*A0 stepping*/ - card_i430vx[0x09] = 0x00; card_i430vx[0x0a] = 0x00; card_i430vx[0x0b] = 0x06; - card_i430vx[0x52] = 0x42; /*256kb PLB cache*/ - card_i430vx[0x53] = 0x14; - card_i430vx[0x56] = 0x52; /*DRAM control*/ - card_i430vx[0x57] = 0x01; - card_i430vx[0x60] = card_i430vx[0x61] = card_i430vx[0x62] = card_i430vx[0x63] = card_i430vx[0x64] = 0x02; - card_i430vx[0x67] = 0x11; - card_i430vx[0x69] = 0x03; - card_i430vx[0x70] = 0x20; - card_i430vx[0x72] = 0x02; - card_i430vx[0x74] = 0x0e; - card_i430vx[0x78] = 0x23; -} - - -static void i430vx_pci_reset(void) -{ - i430vx_write(0, 0x59, 0x00, NULL); - i430vx_write(0, 0x72, 0x02, NULL); -} - - -void i430vx_init(void) -{ - pci_add_card(0, i430vx_read, i430vx_write, NULL); - - i430vx_reset(); - - pci_reset_handler.pci_master_reset = i430vx_pci_reset; -} - - -void -machine_at_p55tvp4_init(const machine_t *model) -{ - machine_at_ps2_init(model); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430vx_init(); - piix3_init(7); - w83877f_init(); - - device_add(&intel_flash_bxt_device); -} - - -void -machine_at_i430vx_init(const machine_t *model) -{ - machine_at_ps2_init(model); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430vx_init(); - piix3_init(7); - um8669f_init(); - - device_add(&intel_flash_bxt_device); -} - - -void -machine_at_p55va_init(const machine_t *model) -{ - machine_at_ps2_init(model); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430vx_init(); - piix3_init(7); - fdc37c932fr_init(); - - device_add(&intel_flash_bxt_device); -} diff --git a/src/machine/m_at_440fx.c b/src/machine/m_at_440fx.c deleted file mode 100644 index 6d3038048..000000000 --- a/src/machine/m_at_440fx.c +++ /dev/null @@ -1,239 +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 Intel 440FX PCISet chip. - * - * Version: @(#)m_at_440fx.c 1.0.11 2018/03/18 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ -#include -#include -#include -#include -#include "../86box.h" -#include "../io.h" -#include "../pci.h" -#include "../mem.h" -#include "../memregs.h" -#include "../device.h" -#include "../keyboard.h" -#include "../piix.h" -#include "../intel_flash.h" -#include "../sio.h" -#include "machine.h" - - -static uint8_t card_i440fx[256]; - - -static void i440fx_map(uint32_t addr, uint32_t size, int state) -{ - switch (state & 3) - { - case 0: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - break; - case 1: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); - break; - case 2: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - break; - case 3: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - } - flushmmucache_nopc(); -} - - -static void i440fx_write(int func, int addr, uint8_t val, void *priv) -{ - if (func) - return; - - if ((addr >= 0x10) && (addr < 0x4f)) - return; - - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0e: - return; - - case 0x04: /*Command register*/ - val &= 0x02; - val |= 0x04; - break; - case 0x05: - val = 0; - break; - - case 0x06: /*Status*/ - val = 0; - break; - case 0x07: - val &= 0x80; - val |= 0x02; - break; - - case 0x59: /*PAM0*/ - if ((card_i440fx[0x59] ^ val) & 0xf0) - { - i440fx_map(0xf0000, 0x10000, val >> 4); - shadowbios = (val & 0x10); - } - break; - case 0x5a: /*PAM1*/ - if ((card_i440fx[0x5a] ^ val) & 0x0f) - i440fx_map(0xc0000, 0x04000, val & 0xf); - if ((card_i440fx[0x5a] ^ val) & 0xf0) - i440fx_map(0xc4000, 0x04000, val >> 4); - break; - case 0x5b: /*PAM2*/ - if ((card_i440fx[0x5b] ^ val) & 0x0f) - i440fx_map(0xc8000, 0x04000, val & 0xf); - if ((card_i440fx[0x5b] ^ val) & 0xf0) - i440fx_map(0xcc000, 0x04000, val >> 4); - break; - case 0x5c: /*PAM3*/ - if ((card_i440fx[0x5c] ^ val) & 0x0f) - i440fx_map(0xd0000, 0x04000, val & 0xf); - if ((card_i440fx[0x5c] ^ val) & 0xf0) - i440fx_map(0xd4000, 0x04000, val >> 4); - break; - case 0x5d: /*PAM4*/ - if ((card_i440fx[0x5d] ^ val) & 0x0f) - i440fx_map(0xd8000, 0x04000, val & 0xf); - if ((card_i440fx[0x5d] ^ val) & 0xf0) - i440fx_map(0xdc000, 0x04000, val >> 4); - break; - case 0x5e: /*PAM5*/ - if ((card_i440fx[0x5e] ^ val) & 0x0f) - i440fx_map(0xe0000, 0x04000, val & 0xf); - if ((card_i440fx[0x5e] ^ val) & 0xf0) - i440fx_map(0xe4000, 0x04000, val >> 4); - break; - case 0x5f: /*PAM6*/ - if ((card_i440fx[0x5f] ^ val) & 0x0f) - i440fx_map(0xe8000, 0x04000, val & 0xf); - if ((card_i440fx[0x5f] ^ val) & 0xf0) - i440fx_map(0xec000, 0x04000, val >> 4); - break; - case 0x72: /*SMRAM*/ - if ((card_i440fx[0x72] ^ val) & 0x48) - i440fx_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0); - break; - } - - card_i440fx[addr] = val; -} - - -static uint8_t i440fx_read(int func, int addr, void *priv) -{ - if (func) - return 0xff; - - return card_i440fx[addr]; -} - - -static void i440fx_reset(void) -{ - memset(card_i440fx, 0, 256); - card_i440fx[0x00] = 0x86; card_i440fx[0x01] = 0x80; /*Intel*/ - card_i440fx[0x02] = 0x37; card_i440fx[0x03] = 0x12; /*82441FX*/ - card_i440fx[0x04] = 0x03; card_i440fx[0x05] = 0x01; - card_i440fx[0x06] = 0x80; card_i440fx[0x07] = 0x00; - card_i440fx[0x08] = 0x02; /*A0 stepping*/ - card_i440fx[0x09] = 0x00; card_i440fx[0x0a] = 0x00; card_i440fx[0x0b] = 0x06; - card_i440fx[0x0d] = 0x00; - card_i440fx[0x0f] = 0x00; - card_i440fx[0x2c] = 0xf4; - card_i440fx[0x2d] = 0x1a; - card_i440fx[0x2e] = 0x00; - card_i440fx[0x2f] = 0x11; - card_i440fx[0x50] = 0x00; - card_i440fx[0x51] = 0x01; - card_i440fx[0x52] = card_i440fx[0x54] = card_i440fx[0x55] = card_i440fx[0x56] = 0x00; - card_i440fx[0x53] = 0x80; - card_i440fx[0x57] = 0x01; - card_i440fx[0x58] = 0x10; - card_i440fx[0x5a] = card_i440fx[0x5b] = card_i440fx[0x5c] = card_i440fx[0x5d] = card_i440fx[0x5e] = 0x11; - card_i440fx[0x5f] = 0x31; - card_i440fx[0x72] = 0x02; -} - - -static void i440fx_pci_reset(void) -{ - i440fx_write(0, 0x59, 0x00, NULL); - i440fx_write(0, 0x72, 0x02, NULL); -} - - -static void i440fx_init(void) -{ - pci_add_card(0, i440fx_read, i440fx_write, NULL); - - i440fx_reset(); - - pci_reset_handler.pci_master_reset = i440fx_pci_reset; -} - - -void -machine_at_i440fx_init(const machine_t *model) -{ - machine_at_ps2_init(model); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i440fx_init(); - piix3_init(7); - fdc37c665_init(); - - device_add(&intel_flash_bxt_device); -} - - -void -machine_at_s1668_init(const machine_t *model) -{ - machine_at_common_init(model); - device_add(&keyboard_ps2_ami_device); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); - i440fx_init(); - piix3_init(7); - fdc37c665_init(); - - device_add(&intel_flash_bxt_device); -} diff --git a/src/machine/m_at_4gpv31.c b/src/machine/m_at_4gpv31.c deleted file mode 100644 index b870131bf..000000000 --- a/src/machine/m_at_4gpv31.c +++ /dev/null @@ -1,153 +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. - * - * Emulation for C&T 82C206/82c597 based 4GLX3 board. - * - * NOTE: The NEAT 82c206 code should be moved into a 82c206 module, - * so it can be re-used by other boards. - * - * Version: @(#)m_4gpv31.c 1.0.5 2018/03/18 - * - * Author: Fred N. van Kempen, - * Copyright 2017,2018 Fred N. van Kempen. - */ -#include -#include -#include -#include -#include -#include "../86box.h" -#include "../io.h" -#include "../device.h" -#include "../keyboard.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "machine.h" - - -typedef struct { - uint8_t regs[256]; - int indx; - - int emspg[4]; -} neat_t; - - -#if NOT_USED -static void -neat_wrems(uint32_t addr, uint8_t val, void *priv) -{ - neat_t *dev = (neat_t *)priv; - - ram[(dev->emspg[(addr >> 14) & 3] << 14) + (addr & 0x3fff)] = val; -} - - -static uint8_t -neat_rdems(uint32_t addr, void *priv) -{ - neat_t *dev = (neat_t *)priv; - - return(ram[(dev->emspg[(addr >> 14) & 3] << 14) + (addr & 0x3fff)]); -} -#endif - - -static void -neat_write(uint16_t port, uint8_t val, void *priv) -{ - neat_t *dev = (neat_t *)priv; - - pclog("NEAT: write(%04x, %02x)\n", port, val); - - switch (port) { - case 0x22: - dev->indx = val; - break; - - case 0x23: - dev->regs[dev->indx] = val; - switch (dev->indx) { - case 0x6e: /* EMS page extension */ - dev->emspg[3] = (dev->emspg[3] & 0x7F) | (( val & 3) << 7); - dev->emspg[2] = (dev->emspg[2] & 0x7F) | (((val >> 2) & 3) << 7); - dev->emspg[1] = (dev->emspg[1] & 0x7F) | (((val >> 4) & 3) << 7); - dev->emspg[0] = (dev->emspg[0] & 0x7F) | (((val >> 6) & 3) << 7); - break; - } - break; - - case 0x0208: - case 0x0209: - - case 0x4208: - case 0x4209: - - case 0x8208: - case 0x8209: - - case 0xc208: - case 0xc209: - dev->emspg[port >> 14] = (dev->emspg[port >> 14] & 0x180) | (val & 0x7F); - break; - } -} - - -static uint8_t -neat_read(uint16_t port, void *priv) -{ - neat_t *dev = (neat_t *)priv; - uint8_t ret = 0xff; - - switch (port) { - case 0x22: - ret = dev->indx; - break; - - case 0x23: - ret = dev->regs[dev->indx]; - break; - } - - pclog("NEAT: read(%04x) = %02x\n", port, ret); - - return(ret); -} - - -static void -neat_init(void) -{ - neat_t *dev; - - dev = (neat_t *)malloc(sizeof(neat_t)); - memset(dev, 0x00, sizeof(neat_t)); - - io_sethandler(0x0022, 2, - neat_read,NULL,NULL, neat_write,NULL,NULL, dev); - io_sethandler(0x0208, 2, - neat_read,NULL,NULL, neat_write,NULL,NULL, dev); - io_sethandler(0x4208, 2, - neat_read,NULL,NULL, neat_write,NULL,NULL, dev); - io_sethandler(0x8208, 2, - neat_read,NULL,NULL, neat_write,NULL,NULL, dev); - io_sethandler(0xc208, 2, - neat_read,NULL,NULL, neat_write,NULL,NULL, dev); -} - - -void -machine_at_4gpv31_init(const machine_t *model) -{ - machine_at_common_ide_init(model); - device_add(&keyboard_at_ami_device); - device_add(&fdc_at_device); - - neat_init(); -} diff --git a/src/machine/m_at_4x0.c b/src/machine/m_at_4x0.c new file mode 100644 index 000000000..29833ab99 --- /dev/null +++ b/src/machine/m_at_4x0.c @@ -0,0 +1,919 @@ +/* + * 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 Intel PCISet chips from 430LX to 440FX. + * + * Version: @(#)m_at_430lx_nx.c 1.0.0 2018/05/09 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2016-2018 Miran Grca. + */ +#include +#include +#include +#include +#include +#include "../86box.h" +#include "../mem.h" +#include "../memregs.h" +#include "../io.h" +#include "../rom.h" +#include "../pci.h" +#include "../device.h" +#include "../disk/hdc.h" +#include "../disk/hdc_ide.h" +#include "../keyboard.h" +#include "../intel.h" +#include "../intel_flash.h" +#include "../intel_sio.h" +#include "../piix.h" +#include "../sio.h" +#include "../video/video.h" +#include "../video/vid_cl54xx.h" +#include "../video/vid_s3.h" +#include "machine.h" + + +enum +{ + INTEL_430LX, + INTEL_430NX, + INTEL_430FX, + INTEL_430HX, +#if defined(DEV_BRANCH) && defined(USE_I686) + INTEL_430VX, + INTEL_440FX +#else + INTEL_430VX +#endif +}; + +typedef struct +{ + uint8_t regs[256]; + int type; +} i4x0_t; + + +typedef struct +{ + int index; +} acerm3a_t; + + +static void +i4x0_map(uint32_t addr, uint32_t size, int state) +{ + switch (state & 3) { + case 0: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + case 1: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + case 2: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 3: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + flushmmucache_nopc(); +} + + +static void +i4x0_write(int func, int addr, uint8_t val, void *priv) +{ + i4x0_t *dev = (i4x0_t *) priv; + + if (func) + return; + + if ((addr >= 0x10) && (addr < 0x4f)) + return; + + switch (addr) { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0e: + return; + + case 0x04: /*Command register*/ + if (dev->type >= INTEL_430FX) { + if (romset == ROM_PB640) + val &= 0x06; + else + val &= 0x02; + } else + val &= 0x42; + val |= 0x04; + break; + case 0x05: + if (dev->type >= INTEL_430FX) + val = 0; + else + val &= 0x01; + break; + + case 0x06: /*Status*/ + val = 0; + break; + case 0x07: + if (dev->type >= INTEL_430HX) { + val &= 0x80; + val |= 0x02; + } else { + val = 0x02; + if (romset == ROM_PB640) + val |= 0x20; + } + break; + + case 0x59: /*PAM0*/ + if ((dev->regs[0x59] ^ val) & 0xf0) { + i4x0_map(0xf0000, 0x10000, val >> 4); + shadowbios = (val & 0x10); + } + break; + case 0x5a: /*PAM1*/ + if ((dev->regs[0x5a] ^ val) & 0x0f) + i4x0_map(0xc0000, 0x04000, val & 0xf); + if ((dev->regs[0x5a] ^ val) & 0xf0) + i4x0_map(0xc4000, 0x04000, val >> 4); + break; + case 0x5b: /*PAM2*/ + if ((dev->regs[0x5b] ^ val) & 0x0f) + i4x0_map(0xc8000, 0x04000, val & 0xf); + if ((dev->regs[0x5b] ^ val) & 0xf0) + i4x0_map(0xcc000, 0x04000, val >> 4); + break; + case 0x5c: /*PAM3*/ + if ((dev->regs[0x5c] ^ val) & 0x0f) + i4x0_map(0xd0000, 0x04000, val & 0xf); + if ((dev->regs[0x5c] ^ val) & 0xf0) + i4x0_map(0xd4000, 0x04000, val >> 4); + break; + case 0x5d: /*PAM4*/ + if ((dev->regs[0x5d] ^ val) & 0x0f) + i4x0_map(0xd8000, 0x04000, val & 0xf); + if ((dev->regs[0x5d] ^ val) & 0xf0) + i4x0_map(0xdc000, 0x04000, val >> 4); + break; + case 0x5e: /*PAM5*/ + if ((dev->regs[0x5e] ^ val) & 0x0f) + i4x0_map(0xe0000, 0x04000, val & 0xf); + if ((dev->regs[0x5e] ^ val) & 0xf0) + i4x0_map(0xe4000, 0x04000, val >> 4); + break; + case 0x5f: /*PAM6*/ + if ((dev->regs[0x5f] ^ val) & 0x0f) + i4x0_map(0xe8000, 0x04000, val & 0xf); + if ((dev->regs[0x5f] ^ val) & 0xf0) + i4x0_map(0xec000, 0x04000, val >> 4); + break; + case 0x72: /*SMRAM*/ + if ((dev->type >= INTEL_430FX) && ((dev->regs[0x72] ^ val) & 0x48)) + i4x0_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0); + break; + } + + dev->regs[addr] = val; +} + + +static uint8_t +i4x0_read(int func, int addr, void *priv) +{ + i4x0_t *dev = (i4x0_t *) priv; + + if (func) + return 0xff; + + return dev->regs[addr]; +} + + +static void +i4x0_reset(void *priv) +{ + i4x0_t *i4x0 = (i4x0_t *)priv; + + i4x0_write(0, 0x59, 0x00, priv); + if (i4x0->type >= INTEL_430FX) + i4x0_write(0, 0x72, 0x02, priv); +} + + +static void +i4x0_close(void *p) +{ + i4x0_t *i4x0 = (i4x0_t *)p; + + free(i4x0); +} + + +static void +*i4x0_init(const device_t *info) +{ + i4x0_t *i4x0 = (i4x0_t *) malloc(sizeof(i4x0_t)); + memset(i4x0, 0, sizeof(i4x0_t)); + + i4x0->type = info->local; + + i4x0->regs[0x00] = 0x86; i4x0->regs[0x01] = 0x80; /*Intel*/ + switch(i4x0->type) { + case INTEL_430LX: + i4x0->regs[0x02] = 0xa3; i4x0->regs[0x03] = 0x04; /*82434LX/NX*/ + i4x0->regs[0x08] = 0x03; /*A3 stepping*/ + i4x0->regs[0x50] = 0x80; + i4x0->regs[0x52] = 0x40; /*256kb PLB cache*/ + break; + case INTEL_430NX: + i4x0->regs[0x02] = 0xa3; i4x0->regs[0x03] = 0x04; /*82434LX/NX*/ + i4x0->regs[0x08] = 0x10; /*A0 stepping*/ + i4x0->regs[0x50] = 0xA0; + i4x0->regs[0x52] = 0x44; /*256kb PLB cache*/ + i4x0->regs[0x66] = i4x0->regs[0x67] = 0x02; + break; + case INTEL_430FX: + i4x0->regs[0x02] = 0x2d; i4x0->regs[0x03] = 0x12; /*SB82437FX-66*/ + if (romset == ROM_PB640) + i4x0->regs[0x08] = 0x02; /*???? stepping*/ + else + i4x0->regs[0x08] = 0x00; /*A0 stepping*/ + i4x0->regs[0x52] = 0x40; /*256kb PLB cache*/ + break; + case INTEL_430HX: + i4x0->regs[0x02] = 0x50; i4x0->regs[0x03] = 0x12; /*82439HX*/ + i4x0->regs[0x08] = 0x00; /*A0 stepping*/ + i4x0->regs[0x51] = 0x20; + i4x0->regs[0x52] = 0xB5; /*512kb cache*/ + i4x0->regs[0x56] = 0x52; /*DRAM control*/ + i4x0->regs[0x59] = 0x40; + i4x0->regs[0x5A] = i4x0->regs[0x5B] = i4x0->regs[0x5C] = i4x0->regs[0x5D] = 0x44; + i4x0->regs[0x5E] = i4x0->regs[0x5F] = 0x44; + i4x0->regs[0x65] = i4x0->regs[0x66] = i4x0->regs[0x67] = 0x02; + i4x0->regs[0x68] = 0x11; + break; + case INTEL_430VX: + i4x0->regs[0x02] = 0x30; i4x0->regs[0x03] = 0x70; /*82437VX*/ + i4x0->regs[0x08] = 0x00; /*A0 stepping*/ + i4x0->regs[0x52] = 0x42; /*256kb PLB cache*/ + i4x0->regs[0x53] = 0x14; + i4x0->regs[0x56] = 0x52; /*DRAM control*/ + i4x0->regs[0x67] = 0x11; + i4x0->regs[0x69] = 0x03; + i4x0->regs[0x70] = 0x20; + i4x0->regs[0x74] = 0x0e; + i4x0->regs[0x78] = 0x23; + break; +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: + i4x0->regs[0x02] = 0x37; i4x0->regs[0x03] = 0x12; /*82441FX*/ + i4x0->regs[0x08] = 0x02; /*A0 stepping*/ + i4x0->regs[0x2c] = 0xf4; + i4x0->regs[0x2d] = 0x1a; + i4x0->regs[0x2f] = 0x11; + i4x0->regs[0x51] = 0x01; + i4x0->regs[0x53] = 0x80; + i4x0->regs[0x58] = 0x10; + i4x0->regs[0x5a] = i4x0->regs[0x5b] = i4x0->regs[0x5c] = i4x0->regs[0x5d] = 0x11; + i4x0->regs[0x5e] = 0x11; + i4x0->regs[0x5f] = 0x31; + break; +#endif + } + i4x0->regs[0x04] = 0x06; i4x0->regs[0x05] = 0x00; +#if defined(DEV_BRANCH) && defined(USE_I686) + if (i4x0->type == INTEL_440FX) + i4x0->regs[0x06] = 0x80; +#endif + if ((i4x0->type == INTEL_430FX) && (romset != ROM_PB640)) + i4x0->regs[0x07] = 0x82; +#if defined(DEV_BRANCH) && defined(USE_I686) + else if (i4x0->type != INTEL_440FX) +#else + else +#endif + i4x0->regs[0x07] = 0x02; + i4x0->regs[0x0b] = 0x06; + if (i4x0->type >= INTEL_430FX) + i4x0->regs[0x57] = 0x01; + else + i4x0->regs[0x57] = 0x31; + i4x0->regs[0x60] = i4x0->regs[0x61] = i4x0->regs[0x62] = i4x0->regs[0x63] = 0x02; + i4x0->regs[0x64] = 0x02; + if (i4x0->type >= INTEL_430FX) + i4x0->regs[0x72] = 0x02; + + pci_add_card(0, i4x0_read, i4x0_write, i4x0); + + return i4x0; +} + + +const device_t i430lx_device = +{ + "Intel 82434LX", + DEVICE_PCI, + INTEL_430LX, + i4x0_init, + i4x0_close, + i4x0_reset, + NULL, + NULL, + NULL, + NULL +}; + + +const device_t i430nx_device = +{ + "Intel 82434NX", + DEVICE_PCI, + INTEL_430NX, + i4x0_init, + i4x0_close, + i4x0_reset, + NULL, + NULL, + NULL, + NULL +}; + + +const device_t i430fx_device = +{ + "Intel SB82437FX-66", + DEVICE_PCI, + INTEL_430FX, + i4x0_init, + i4x0_close, + i4x0_reset, + NULL, + NULL, + NULL, + NULL +}; + + +const device_t i430hx_device = +{ + "Intel 82439HX", + DEVICE_PCI, + INTEL_430HX, + i4x0_init, + i4x0_close, + i4x0_reset, + NULL, + NULL, + NULL, + NULL +}; + + +const device_t i430vx_device = +{ + "Intel 82437VX", + DEVICE_PCI, + INTEL_430VX, + i4x0_init, + i4x0_close, + i4x0_reset, + NULL, + NULL, + NULL, + NULL +}; + + +#if defined(DEV_BRANCH) && defined(USE_I686) +const device_t i440fx_device = +{ + "Intel 82441FX", + DEVICE_PCI, + INTEL_440FX, + i4x0_init, + i4x0_close, + i4x0_reset, + NULL, + NULL, + NULL, + NULL +}; +#endif + + +static void +acerm3a_out(uint16_t port, uint8_t val, void *p) +{ + acerm3a_t *dev = (acerm3a_t *) p; + + if (port == 0xea) + dev->index = val; +} + + +static uint8_t +acerm3a_in(uint16_t port, void *p) +{ + acerm3a_t *dev = (acerm3a_t *) p; + + if (port == 0xeb) { + switch (dev->index) { + case 2: + return 0xfd; + } + } + return 0xff; +} + + +static void +acerm3a_close(void *p) +{ + acerm3a_t *dev = (acerm3a_t *)p; + + free(dev); +} + + +static void +*acerm3a_init(const device_t *info) +{ + acerm3a_t *acerm3a = (acerm3a_t *) malloc(sizeof(acerm3a_t)); + memset(acerm3a, 0, sizeof(acerm3a_t)); + + io_sethandler(0x00ea, 0x0002, acerm3a_in, NULL, NULL, acerm3a_out, NULL, NULL, acerm3a); + + return acerm3a; +} + + +const device_t acerm3a_device = +{ + "Acer M3A Register", + 0, + 0, + acerm3a_init, + acerm3a_close, + NULL, + NULL, + NULL, + NULL, + NULL +}; + + +static void +machine_at_premiere_common_init(const machine_t *model) +{ + machine_at_common_init(model); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&ide_pci_2ch_device); + + memregs_init(); + pci_init(PCI_CONFIG_TYPE_2); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x02, PCI_CARD_SPECIAL, 0, 0, 0, 0); + device_add(&sio_device); + fdc37c665_init(); + intel_batman_init(); + + device_add(&intel_flash_bxt_ami_device); +} + + +void +machine_at_batman_init(const machine_t *model) +{ + machine_at_premiere_common_init(model); + + device_add(&i430lx_device); +} + + +void +machine_at_plato_init(const machine_t *model) +{ + machine_at_premiere_common_init(model); + + device_add(&i430nx_device); +} + + +void +machine_at_p54tp4xe_init(const machine_t *model) +{ + machine_at_common_init(model); + device_add(&keyboard_ps2_pci_device); + + memregs_init(); + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + device_add(&i430fx_device); + device_add(&piix_device); + fdc37c665_init(); + + device_add(&intel_flash_bxt_device); +} + + +void +machine_at_endeavor_init(const machine_t *model) +{ + machine_at_common_init(model); + device_add(&keyboard_ps2_ami_pci_device); + + memregs_init(); + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + device_add(&i430fx_device); + device_add(&piix_device); + pc87306_init(); + + device_add(&intel_flash_bxt_ami_device); + + if (gfxcard == GFX_INTERNAL) + device_add(&s3_phoenix_trio64_onboard_pci_device); +} + + +const device_t * +at_endeavor_get_device(void) +{ + return &s3_phoenix_trio64_onboard_pci_device; +} + + +void +machine_at_zappa_init(const machine_t *model) +{ + machine_at_common_init(model); + device_add(&keyboard_ps2_ami_pci_device); + + memregs_init(); + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + device_add(&i430fx_device); + device_add(&piix_device); + pc87306_init(); + + device_add(&intel_flash_bxt_ami_device); +} + + +void +machine_at_mb500n_init(const machine_t *model) +{ + machine_at_common_init(model); + device_add(&keyboard_ps2_pci_device); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + device_add(&i430fx_device); + device_add(&piix_device); + fdc37c665_init(); + + device_add(&intel_flash_bxt_device); +} + + +void +machine_at_president_init(const machine_t *model) +{ + machine_at_common_init(model); + device_add(&keyboard_ps2_pci_device); + + memregs_init(); + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + device_add(&i430fx_device); + device_add(&piix_device); + w83877f_init(); + + device_add(&intel_flash_bxt_device); +} + + +void +machine_at_thor_init(const machine_t *model) +{ + machine_at_common_init(model); + device_add(&keyboard_ps2_ami_pci_device); + + memregs_init(); + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 2, 1); + pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 3, 2, 1); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + device_add(&i430fx_device); + device_add(&piix_device); + pc87306_init(); + + device_add(&intel_flash_bxt_ami_device); +} + + +void +machine_at_pb640_init(const machine_t *model) +{ + machine_at_common_init(model); + device_add(&keyboard_ps2_ami_pci_device); + + memregs_init(); + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + device_add(&i430fx_device); + device_add(&piix_pb640_device); + pc87306_init(); + + device_add(&intel_flash_bxt_ami_device); + + if (gfxcard == GFX_INTERNAL) + device_add(&gd5440_onboard_pci_device); +} + + +const device_t * +at_pb640_get_device(void) +{ + return &gd5440_onboard_pci_device; +} + + +void +machine_at_acerm3a_init(const machine_t *model) +{ + machine_at_common_init(model); + device_add(&keyboard_ps2_pci_device); + + powermate_memregs_init(); + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x1F, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x10, PCI_CARD_ONBOARD, 4, 0, 0, 0); + device_add(&i430hx_device); + device_add(&piix3_device); + fdc37c932fr_init(); + device_add(&acerm3a_device); + + device_add(&intel_flash_bxb_device); +} + + +void +machine_at_acerv35n_init(const machine_t *model) +{ + machine_at_common_init(model); + device_add(&keyboard_ps2_pci_device); + + powermate_memregs_init(); + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + device_add(&i430hx_device); + device_add(&piix3_device); + fdc37c932fr_init(); + device_add(&acerm3a_device); + + device_add(&intel_flash_bxb_device); +} + + +void +machine_at_ap53_init(const machine_t *model) +{ + machine_at_common_init(model); + device_add(&keyboard_ps2_ami_pci_device); + + memregs_init(); + powermate_memregs_init(); + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_ONBOARD, 1, 2, 3, 4); + device_add(&i430hx_device); + device_add(&piix3_device); + fdc37c669_init(); + + device_add(&intel_flash_bxt_device); +} + + +void +machine_at_p55t2p4_init(const machine_t *model) +{ + machine_at_common_init(model); + device_add(&keyboard_ps2_pci_device); + + memregs_init(); + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + device_add(&i430hx_device); + device_add(&piix3_device); + w83877f_init(); + + device_add(&intel_flash_bxt_device); +} + + +void +machine_at_p55t2s_init(const machine_t *model) +{ + machine_at_common_init(model); + device_add(&keyboard_ps2_ami_pci_device); + + memregs_init(); + powermate_memregs_init(); + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + device_add(&i430hx_device); + device_add(&piix3_device); + pc87306_init(); + + device_add(&intel_flash_bxt_device); +} + + +void +machine_at_p55tvp4_init(const machine_t *model) +{ + machine_at_common_init(model); + device_add(&keyboard_ps2_pci_device); + + memregs_init(); + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + device_add(&i430vx_device); + device_add(&piix3_device); + w83877f_init(); + + device_add(&intel_flash_bxt_device); +} + + +void +machine_at_i430vx_init(const machine_t *model) +{ + machine_at_common_init(model); + device_add(&keyboard_ps2_pci_device); + + memregs_init(); + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + device_add(&i430vx_device); + device_add(&piix3_device); + um8669f_init(); + + device_add(&intel_flash_bxt_device); +} + + +void +machine_at_p55va_init(const machine_t *model) +{ + machine_at_common_init(model); + device_add(&keyboard_ps2_pci_device); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + device_add(&i430vx_device); + device_add(&piix3_device); + fdc37c932fr_init(); + + device_add(&intel_flash_bxt_device); +} + + +#if defined(DEV_BRANCH) && defined(USE_I686) +void +machine_at_i440fx_init(const machine_t *model) +{ + machine_at_common_init(model); + device_add(&keyboard_ps2_pci_device); + + memregs_init(); + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + device_add(&i440fx_device); + device_add(&piix3_device); + fdc37c665_init(); + + device_add(&intel_flash_bxt_device); +} + + +void +machine_at_s1668_init(const machine_t *model) +{ + machine_at_common_init(model); + device_add(&keyboard_ps2_ami_pci_device); + + memregs_init(); + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); + device_add(&i440fx_device); + device_add(&piix3_device); + fdc37c665_init(); + + device_add(&intel_flash_bxt_device); +} +#endif diff --git a/src/machine/m_at_opti495.c b/src/machine/m_at_opti495.c index 21f984827..d38e47066 100644 --- a/src/machine/m_at_opti495.c +++ b/src/machine/m_at_opti495.c @@ -251,10 +251,12 @@ Note: the block address is forced to be a multiple of the block size by ignoring the appropriate number of the least-significant bits SeeAlso: #P0178,#P0187 */ -#include +#include #include +#include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../cpu/cpu.h" #include "../io.h" @@ -278,7 +280,6 @@ static void opti495_write(uint16_t addr, uint8_t val, void *p) optireg=val; break; case 0x24: - pclog("OPTI: writing reg %02X %02X\n",optireg,val); if (optireg>=0x20 && optireg<=0x2C) { optiregs[optireg-0x20]=val; diff --git a/src/machine/m_at_scat.c b/src/machine/m_at_scat.c index 420c474a0..c9af19fac 100644 --- a/src/machine/m_at_scat.c +++ b/src/machine/m_at_scat.c @@ -10,16 +10,15 @@ * * Re-worked version based on the 82C235 datasheet and errata. * - * Version: @(#)m_at_scat.c 1.0.13 2018/03/20 + * Version: @(#)m_at_scat.c 1.0.15 2018/04/29 * * Authors: Original by GreatPsycho for PCem. * Fred N. van Kempen, * * Copyright 2017,2018 Fred N. van Kempen. */ -#include -#include #include +#include #include #include #include "../86box.h" @@ -32,6 +31,7 @@ #include "../io.h" #include "../mem.h" #include "../nmi.h" +#include "../rom.h" #include "machine.h" @@ -67,667 +67,1311 @@ static uint8_t scat_regs[256]; static int scat_index; static uint8_t scat_port_92 = 0; static uint8_t scat_ems_reg_2xA = 0; -static mem_mapping_t scat_mapping[32]; +static mem_mapping_t scat_low_mapping[32]; +static mem_mapping_t scat_ems_mapping[32]; static mem_mapping_t scat_high_mapping[16]; static scat_t scat_stat[32]; static uint32_t scat_xms_bound; -static mem_mapping_t scat_shadowram_mapping[6]; -static mem_mapping_t scat_4000_9FFF_mapping[24]; -static mem_mapping_t scat_A000_BFFF_mapping; - -// TODO - 82C836 chipset's memory address mapping isn't fully implemented yet, so memory configuration is hardcoded now. -static int scatsx_mem_conf_val[33] = { 0x00, 0x01, 0x03, 0x04, 0x05, 0x08, 0x06, 0x06, - 0x0c, 0x09, 0x07, 0x07, 0x0d, 0x0a, 0x0f, 0x0f, - 0x0e, 0x0e, 0x10, 0x10, 0x13, 0x13, 0x11, 0x11, - 0x14, 0x14, 0x12, 0x12, 0x15, 0x15, 0x15, 0x15, - 0x16 }; - -uint8_t scat_read(uint16_t port, void *priv); -void scat_write(uint16_t port, uint8_t val, void *priv); +static mem_mapping_t scat_remap_mapping[6]; +static mem_mapping_t scat_4000_EFFF_mapping[44]; +static mem_mapping_t scat_low_ROMCS_mapping[8]; -#ifdef ENABLE_SCAT_LOG -int scat_do_log = ENABLE_SCAT_LOG; -#endif +static int scat_max_map[32] = { 0, 1, 1, 1, 2, 3, 4, 8, + 4, 8, 12, 16, 20, 24, 28, 32, + 0, 5, 9, 13, 6, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }; +static int scatsx_max_map[32] = { 0, 1, 2, 1, 3, 4, 6, 10, + 5, 9, 13, 4, 8, 12, 16, 14, + 18, 22, 26, 20, 24, 28, 32, 18, + 20, 32, 0, 0, 0, 0, 0, 0 }; + +static int external_is_RAS = 0; + +static int scatsx_external_is_RAS[33] = { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0 }; + + +static uint8_t scat_read(uint16_t port, void *priv); +static void scat_write(uint16_t port, uint8_t val, void *priv); + static void -scat_log(const char *format, ...) +scat_romcs_state_update(uint8_t val) { -#ifdef ENABLE_SCAT_LOG - if (scat_do_log) { - va_start(ap, format); - pclog_ex(format, ap); - va_end(ap); + int i; + for(i = 0; i < 4; i++) { + if (val & 1) { + mem_mapping_enable(&scat_low_ROMCS_mapping[i << 1]); + mem_mapping_enable(&scat_low_ROMCS_mapping[(i << 1) + 1]); + } else { + mem_mapping_disable(&scat_low_ROMCS_mapping[i << 1]); + mem_mapping_disable(&scat_low_ROMCS_mapping[(i << 1) + 1]); + } + val >>= 1; } -#endif -} - -void scat_shadow_state_update() -{ - int i, val; - - // TODO - ROMCS enable features should be implemented later. - for (i = 0; i < 24; i++) - { - val = ((scat_regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTERNAL; - if (i < 8) - { - val |= ((scat_regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTERNAL; - } - else - { - if ((scat_regs[SCAT_RAM_WRITE_PROTECT] >> ((i - 8) >> 1)) & 1) - { - val |= MEM_WRITE_DISABLED; - } - else - { - val |= ((scat_regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTERNAL; - } - } - mem_set_mem_state((i + 40) << 14, 0x4000, val); - } - - flushmmucache(); -} - -void scat_set_xms_bound(uint8_t val) -{ - uint32_t max_xms_size = (mem_size >= 16128) ? (((scat_regs[SCAT_VERSION] & 0xF0) != 0 && ((val & 0x10) != 0)) ? 0xFE0000 : 0xFC0000) : mem_size << 10; - int i; - - switch (val & 0x0F) - { - case 1: - scat_xms_bound = 0x100000; - break; - case 2: - scat_xms_bound = 0x140000; - break; - case 3: - scat_xms_bound = 0x180000; - break; - case 4: - scat_xms_bound = 0x200000; - break; - case 5: - scat_xms_bound = 0x300000; - break; - case 6: - scat_xms_bound = 0x400000; - break; - case 7: - scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x600000 : 0x500000; - break; - case 8: - scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x800000 : 0x700000; - break; - case 9: - scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xA00000 : 0x800000; - break; - case 10: - scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xC00000 : 0x900000; - break; - case 11: - scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xE00000 : 0xA00000; - break; - case 12: - scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xB00000; - break; - case 13: - scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xC00000; - break; - case 14: - scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xD00000; - break; - case 15: - scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xF00000; - break; - default: - scat_xms_bound = max_xms_size; - break; - } - - if ((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (val & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3)) - { - if (val != 1) - { - if(mem_size > 1024) mem_mapping_disable(&ram_high_mapping); - for(i=0;i<6;i++) - mem_mapping_enable(&scat_shadowram_mapping[i]); - if ((val & 0x0F) == 0) - scat_xms_bound = 0x160000; - } - else - { - for(i=0;i<6;i++) - mem_mapping_disable(&scat_shadowram_mapping[i]); - if(mem_size > 1024) mem_mapping_enable(&ram_high_mapping); - } - scat_log("Set XMS bound(%02X) = %06X(%dKbytes for EMS access)\n", val, scat_xms_bound, (0x160000 - scat_xms_bound) >> 10); - if (scat_xms_bound > 0x100000) - mem_set_mem_state(0x100000, scat_xms_bound - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - if (scat_xms_bound < 0x160000) - mem_set_mem_state(scat_xms_bound, 0x160000 - scat_xms_bound, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - } - else - { - for(i=0;i<6;i++) - mem_mapping_disable(&scat_shadowram_mapping[i]); - if(mem_size > 1024) mem_mapping_enable(&ram_high_mapping); - - if (scat_xms_bound > max_xms_size) - scat_xms_bound = max_xms_size; - scat_log("Set XMS bound(%02X) = %06X(%dKbytes for EMS access)\n", val, scat_xms_bound, ((mem_size << 10) - scat_xms_bound) >> 10); - if (scat_xms_bound > 0x100000) - mem_set_mem_state(0x100000, scat_xms_bound - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - if (scat_xms_bound < (mem_size << 10)) - mem_set_mem_state(scat_xms_bound, (mem_size << 10) - scat_xms_bound, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - } -} - -uint32_t get_scat_addr(uint32_t addr, scat_t *p) -{ - if (p && (scat_regs[SCAT_EMS_CONTROL] & 0x80) && (p->regs_2x9 & 0x80)) - addr = (addr & 0x3fff) | (((p->regs_2x9 & 3) << 8) | p->regs_2x8) << 14; - - if ((scat_regs[SCAT_VERSION] & 0xF0) == 0) - { - if (mem_size < 2048 && ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) > 7 || (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) != 0)) - addr = (addr & ~0x780000) | ((addr & 0x600000) >> 2); - else if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 8 && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) - { - addr &= ~0x600000; - if(mem_size > 2048 || (mem_size == 2048 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 6)) - addr |= (addr & 0x180000) << 2; - } - - if ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3 && (addr & ~0x600000) >= 0x100000 && (addr & ~0x600000) < 0x160000) - addr ^= mem_size < 2048 ? 0x1F0000 : 0x670000; - } - else - { - if ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3 && (addr & ~0x600000) >= 0x100000 && (addr & ~0x600000) < 0x160000) - addr ^= 0x1F0000; - } - return addr; -} - -void scat_memmap_state_update() -{ - int i; - uint32_t addr; - - for(i=16;i<24;i++) - { - addr = get_scat_addr(0x40000 + (i << 14), NULL); - mem_mapping_set_exec(&scat_4000_9FFF_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL); - } - addr = get_scat_addr(0xA0000, NULL); - mem_mapping_set_exec(&scat_A000_BFFF_mapping, addr < (mem_size << 10) ? ram + addr : NULL); - for(i=0;i<6;i++) - { - addr = get_scat_addr(0x100000 + (i << 16), NULL); - mem_mapping_set_exec(&scat_shadowram_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL); - } - - flushmmucache(); -} - -void scat_set_global_EMS_state(int state) -{ - int i; - uint32_t base_addr, virt_addr; - - for(i=((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0 : 24; i<32; i++) - { - base_addr = (i + 16) << 14; - if(i >= 24) - base_addr += 0x30000; - if(state && (scat_stat[i].regs_2x9 & 0x80)) - { - virt_addr = get_scat_addr(base_addr, &scat_stat[i]); - if(i < 24) mem_mapping_disable(&scat_4000_9FFF_mapping[i]); - mem_mapping_enable(&scat_mapping[i]); - if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_mapping[i], ram + virt_addr); - else mem_mapping_set_exec(&scat_mapping[i], NULL); - } - else - { - mem_mapping_set_exec(&scat_mapping[i], ram + base_addr); - mem_mapping_disable(&scat_mapping[i]); - if(i < 24) mem_mapping_enable(&scat_4000_9FFF_mapping[i]); - } - } - flushmmucache(); -} - -void scat_write(uint16_t port, uint8_t val, void *priv) -{ - uint8_t scat_reg_valid = 0, scat_shadow_update = 0, scat_map_update = 0, index; - uint32_t base_addr, virt_addr; - - switch (port) - { - case 0x22: - scat_index = val; - break; - - case 0x23: - switch (scat_index) - { - case SCAT_DMA_WAIT_STATE_CONTROL: - case SCAT_CLOCK_CONTROL: - case SCAT_PERIPHERAL_CONTROL: - scat_reg_valid = 1; - break; - case SCAT_EMS_CONTROL: - if(val & 0x40) - { - if(val & 1) - { - io_sethandler(0x0218, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); - io_removehandler(0x0208, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); - } - else - { - io_sethandler(0x0208, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); - io_removehandler(0x0218, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); - } - } - else - { - io_removehandler(0x0208, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); - io_removehandler(0x0218, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); - } - scat_set_global_EMS_state(val & 0x80); - scat_reg_valid = 1; - break; - case SCAT_POWER_MANAGEMENT: - // TODO - Only use AUX parity disable bit for this version. Other bits should be implemented later. - val &= (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x40 : 0x60; - scat_reg_valid = 1; - break; - case SCAT_DRAM_CONFIGURATION: - if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) || ((scat_regs[SCAT_VERSION] & 0xF0) != 0)) - { - if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (val & 0x0F) == 3) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (val & 0x1F) == 3)) - { - if(mem_size > 1024) mem_mapping_disable(&ram_high_mapping); - for(index=0;index<6;index++) - mem_mapping_enable(&scat_shadowram_mapping[index]); - } - else - { - for(index=0;index<6;index++) - mem_mapping_disable(&scat_shadowram_mapping[index]); - if(mem_size > 1024) mem_mapping_enable(&ram_high_mapping); - } - } - else - { - for(index=0;index<6;index++) - mem_mapping_disable(&scat_shadowram_mapping[index]); - if(mem_size > 1024) mem_mapping_enable(&ram_high_mapping); - } - scat_map_update = 1; - - if((scat_regs[SCAT_VERSION] & 0xF0) == 0) - { - cpu_waitstates = (val & 0x70) == 0 ? 1 : 2; - cpu_update_waitstates(); - } - else - { - if(mem_size != 1024 || ((val & 0x1F) != 2 && (val & 0x1F) != 3)) - val = (val & 0xe0) | scatsx_mem_conf_val[mem_size >> 9]; - } - - scat_reg_valid = 1; - break; - case SCAT_EXTENDED_BOUNDARY: - scat_set_xms_bound(val & ((scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x4f : 0x1f)); - mem_set_mem_state(0x40000, 0x60000, (val & 0x20) ? MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL : MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - if((val ^ scat_regs[SCAT_EXTENDED_BOUNDARY]) & 0x40) scat_map_update = 1; - scat_reg_valid = 1; - break; - case SCAT_ROM_ENABLE: - case SCAT_RAM_WRITE_PROTECT: - case SCAT_SHADOW_RAM_ENABLE_1: - case SCAT_SHADOW_RAM_ENABLE_2: - case SCAT_SHADOW_RAM_ENABLE_3: - scat_reg_valid = 1; - scat_shadow_update = 1; - break; - case SCATSX_LAPTOP_FEATURES: - if((scat_regs[SCAT_VERSION] & 0xF0) != 0) - { - val = (val & ~8) | (scat_regs[SCATSX_LAPTOP_FEATURES] & 8); - scat_reg_valid = 1; - } - break; - case SCATSX_FAST_VIDEO_CONTROL: - case SCATSX_FAST_VIDEORAM_ENABLE: - case SCATSX_HIGH_PERFORMANCE_REFRESH: - case SCATSX_CAS_TIMING_FOR_DMA: - if((scat_regs[SCAT_VERSION] & 0xF0) != 0) scat_reg_valid = 1; - break; - default: - break; - } - if (scat_reg_valid) - scat_regs[scat_index] = val; - else scat_log("Attemped to write unimplemented SCAT register %02X at %04X:%04X\n", scat_index, val, CS, cpu_state.pc); - if (scat_shadow_update) - scat_shadow_state_update(); - if (scat_map_update) - scat_memmap_state_update(); -// scat_log("Write SCAT Register %02X to %02X at %04X:%04X\n", scat_index, val, CS, cpu_state.pc); - break; - - case 0x92: - if ((mem_a20_alt ^ val) & 2) - { - mem_a20_alt = val & 2; - mem_a20_recalc(); - } - if ((~scat_port_92 & val) & 1) - { - softresetx86(); - cpu_set_edx(); - } - scat_port_92 = val; - break; - - case 0x208: - case 0x218: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) - { -// scat_log("Write SCAT EMS Control Port %04X to %02X at %04X:%04X\n", port, val, CS, cpu_state.pc); - if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; - else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; - scat_stat[index].regs_2x8 = val; - base_addr = (index + 16) << 14; - if(index >= 24) - base_addr += 0x30000; - - if((scat_regs[SCAT_EMS_CONTROL] & 0x80) && (scat_stat[index].regs_2x9 & 0x80)) - { - virt_addr = get_scat_addr(base_addr, &scat_stat[index]); - if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_mapping[index], ram + virt_addr); - else mem_mapping_set_exec(&scat_mapping[index], NULL); - flushmmucache(); - } - } - break; - case 0x209: - case 0x219: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) - { -// scat_log("Write SCAT EMS Control Port %04X to %02X at %04X:%04X\n", port, val, CS, cpu_state.pc); - if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; - else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; - scat_stat[index].regs_2x9 = val; - base_addr = (index + 16) << 14; - if(index >= 24) - base_addr += 0x30000; - - if (scat_regs[SCAT_EMS_CONTROL] & 0x80) - { - if (val & 0x80) - { - virt_addr = get_scat_addr(base_addr, &scat_stat[index]); - if(index < 24) mem_mapping_disable(&scat_4000_9FFF_mapping[index]); - if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_mapping[index], ram + virt_addr); - else mem_mapping_set_exec(&scat_mapping[index], NULL); - mem_mapping_enable(&scat_mapping[index]); -// scat_log("Map page %d(address %05X) to address %06X\n", scat_ems_reg_2xA & 0x1f, base_addr, virt_addr); - } - else - { - mem_mapping_set_exec(&scat_mapping[index], ram + base_addr); - mem_mapping_disable(&scat_mapping[index]); - if(index < 24) mem_mapping_enable(&scat_4000_9FFF_mapping[index]); -// scat_log("Unmap page %d(address %06X)\n", scat_ems_reg_2xA & 0x1f, base_addr); - } - flushmmucache(); - } - - if (scat_ems_reg_2xA & 0x80) - { - scat_ems_reg_2xA = (scat_ems_reg_2xA & 0xe0) | ((scat_ems_reg_2xA + 1) & (((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0x1f : 3)); - } - } - break; - case 0x20A: - case 0x21A: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) - { -// scat_log("Write SCAT EMS Control Port %04X to %02X at %04X:%04X\n", port, val, CS, cpu_state.pc); - scat_ems_reg_2xA = ((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? val : val & 0xc3; - } - break; - } -} - -uint8_t scat_read(uint16_t port, void *priv) -{ - uint8_t val = 0xff, index; - switch (port) - { - case 0x23: - switch (scat_index) - { - case SCAT_MISCELLANEOUS_STATUS: - val = (scat_regs[scat_index] & 0x3f) | (~nmi_mask & 0x80) | ((mem_a20_key & 2) << 5); - break; - case SCAT_DRAM_CONFIGURATION: - if ((scat_regs[SCAT_VERSION] & 0xF0) == 0) val = (scat_regs[scat_index] & 0x8f) | (cpu_waitstates == 1 ? 0 : 0x10); - else if(mem_size != 1024) val = (scat_regs[scat_index] & 0xe0) | scatsx_mem_conf_val[mem_size >> 9]; - else val = scat_regs[scat_index]; - break; - default: - val = scat_regs[scat_index]; - break; - } -// scat_log("Read SCAT Register %02X at %04X:%04X\n", scat_index, CS, cpu_state.pc); - break; - - case 0x92: - val = scat_port_92; - break; - - case 0x208: - case 0x218: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) - { -// scat_log("Read SCAT EMS Control Port %04X at %04X:%04X\n", port, CS, cpu_state.pc); - if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; - else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; - val = scat_stat[index].regs_2x8; - } - break; - case 0x209: - case 0x219: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) - { -// scat_log("Read SCAT EMS Control Port %04X at %04X:%04X\n", port, CS, cpu_state.pc); - if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; - else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; - val = scat_stat[index].regs_2x9; - } - break; - case 0x20A: - case 0x21A: - if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) - { -// scat_log("Read SCAT EMS Control Port %04X at %04X:%04X\n", port, CS, cpu_state.pc); - val = scat_ems_reg_2xA; - } - break; - } - return val; -} - -uint8_t mem_read_scatems(uint32_t addr, void *priv) -{ - uint8_t val = 0xff; - scat_t *stat = (scat_t *)priv; - - addr = get_scat_addr(addr, stat); - if (addr < (mem_size << 10)) - val = mem_read_ram(addr, priv); - - return val; -} - -void mem_write_scatems(uint32_t addr, uint8_t val, void *priv) -{ - scat_t *stat = (scat_t *)priv; - - addr = get_scat_addr(addr, stat); - if (addr < (mem_size << 10)) - mem_write_ram(addr, val, priv); + for(i = 0; i < 4; i++) { + if (val & 1) { + mem_mapping_enable(&bios_mapping[i << 1]); + mem_mapping_enable(&bios_mapping[(i << 1) + 1]); + } else { + mem_mapping_disable(&bios_mapping[i << 1]); + mem_mapping_disable(&bios_mapping[(i << 1) + 1]); + } + val >>= 1; + } } static void -scat_init(void) +scat_shadow_state_update() { + int i, val; + + for (i = 0; i < 24; i++) { + val = ((scat_regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_READ_INTERNAL | MEM_WRITE_INTERNAL : MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL; + mem_set_mem_state((i + 40) << 14, 0x4000, val); + } + + flushmmucache(); +} + + +static void +scat_set_xms_bound(uint8_t val) +{ + uint32_t max_xms_size = ((scat_regs[SCAT_VERSION] & 0xF0) != 0 && ((val & 0x10) != 0)) || (scat_regs[SCAT_VERSION] >= 4) ? 0xFE0000 : 0xFC0000; + + switch (val & 0x0F) { + case 1: + scat_xms_bound = 0x100000; + break; + case 2: + scat_xms_bound = 0x140000; + break; + case 3: + scat_xms_bound = 0x180000; + break; + case 4: + scat_xms_bound = 0x200000; + break; + case 5: + scat_xms_bound = 0x300000; + break; + case 6: + scat_xms_bound = 0x400000; + break; + case 7: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x600000 : 0x500000; + break; + case 8: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x800000 : 0x700000; + break; + case 9: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xA00000 : 0x800000; + break; + case 10: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xC00000 : 0x900000; + break; + case 11: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xE00000 : 0xA00000; + break; + case 12: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xB00000; + break; + case 13: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xC00000; + break; + case 14: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xD00000; + break; + case 15: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xF00000; + break; + default: + scat_xms_bound = max_xms_size; + break; + } + + if ((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (val & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3)) { + if((val & 0x0F) == 0 || scat_xms_bound > 0x160000) + scat_xms_bound = 0x160000; + if (scat_xms_bound > 0x100000) + mem_set_mem_state(0x100000, scat_xms_bound - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + if (scat_xms_bound < 0x160000) + mem_set_mem_state(scat_xms_bound, 0x160000 - scat_xms_bound, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } else { + if (scat_xms_bound > max_xms_size) + scat_xms_bound = max_xms_size; + if (scat_xms_bound > 0x100000) + mem_set_mem_state(0x100000, scat_xms_bound - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + if (scat_xms_bound < (mem_size << 10)) + mem_set_mem_state(scat_xms_bound, (mem_size << 10) - scat_xms_bound, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } + + mem_mapping_set_addr(&scat_low_mapping[31], 0xF80000, ((scat_regs[SCAT_VERSION] & 0xF0) != 0 && ((val & 0x10) != 0)) || (scat_regs[SCAT_VERSION] >= 4) ? 0x60000 : 0x40000); + if(scat_regs[SCAT_VERSION] & 0xF0) { int i; + for(i=0;i<8;i++) { + if(val & 0x10) + mem_mapping_disable(&scat_high_mapping[i]); + else + mem_mapping_enable(&scat_high_mapping[i]); + } + } +} - io_sethandler(0x0022, 2, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); - port_92_reset(); +static uint32_t +get_scat_addr(uint32_t addr, scat_t *p) +{ + int nbank; - port_92_add(); + if (p && (scat_regs[SCAT_EMS_CONTROL] & 0x80) && (p->regs_2x9 & 0x80)) + addr = (addr & 0x3fff) | (((p->regs_2x9 & 3) << 8) | p->regs_2x8) << 14; - for (i = 0; i < 256; i++) - { - scat_regs[i] = 0xff; - } + if ((scat_regs[SCAT_VERSION] & 0xF0) == 0) { + switch((scat_regs[SCAT_EXTENDED_BOUNDARY] & ((scat_regs[SCAT_VERSION] & 0x0F) > 3 ? 0x40 : 0)) | (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F)) { + case 0x41: + nbank = addr >> 19; + if(nbank < 4) + nbank = 1; + else if(nbank == 4) + nbank = 0; + else + nbank -= 3; + break; + case 0x42: + nbank = addr >> 19; + if(nbank < 8) + nbank = 1 + (nbank >> 2); + else if(nbank == 8) + nbank = 0; + else + nbank -= 6; + break; + case 0x43: + nbank = addr >> 19; + if(nbank < 12) + nbank = 1 + (nbank >> 2); + else if(nbank == 12) + nbank = 0; + else + nbank -= 9; + break; + case 0x44: + nbank = addr >> 19; + if(nbank < 4) + nbank = 2; + else if(nbank < 6) + nbank -= 4; + else + nbank -= 3; + break; + case 0x45: + nbank = addr >> 19; + if(nbank < 8) + nbank = 2 + (nbank >> 2); + else if(nbank < 10) + nbank -= 8; + else + nbank -= 6; + break; + default: + nbank = addr >> (((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 8 && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) ? 19 : 21); + break; + } + nbank &= (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) ? 7 : 3; + if ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3 && nbank == 2 && (addr & 0x7FFFF) < 0x60000 && mem_size > 640) { + nbank = 1; + addr ^= 0x70000; + } - scat_regs[SCAT_DMA_WAIT_STATE_CONTROL] = 0; - scat_regs[SCAT_VERSION] = 4; - scat_regs[SCAT_CLOCK_CONTROL] = 2; - scat_regs[SCAT_PERIPHERAL_CONTROL] = 0x80; - scat_regs[SCAT_MISCELLANEOUS_STATUS] = 0x37; - scat_regs[SCAT_POWER_MANAGEMENT] = 0; - scat_regs[SCAT_ROM_ENABLE] = 0xC0; - scat_regs[SCAT_RAM_WRITE_PROTECT] = 0; - scat_regs[SCAT_SHADOW_RAM_ENABLE_1] = 0; - scat_regs[SCAT_SHADOW_RAM_ENABLE_2] = 0; - scat_regs[SCAT_SHADOW_RAM_ENABLE_3] = 0; - scat_regs[SCAT_DRAM_CONFIGURATION] = cpu_waitstates == 1 ? 2 : 0x12; - scat_regs[SCAT_EXTENDED_BOUNDARY] = 0; - scat_regs[SCAT_EMS_CONTROL] = 0; - scat_port_92 = 0; + if(external_is_RAS && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0) { + if(nbank == 3) + nbank = 7; + else + return 0xFFFFFFFF; + } else if(!external_is_RAS && scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) { + switch(nbank) { + case 7: + nbank = 3; + break; + /* Note - In the following cases, the chipset accesses multiple memory banks + at the same time, so it's impossible to predict which memory bank + is actually accessed. */ + case 5: + case 1: + nbank = 1; + break; + case 3: + nbank = 2; + break; + default: + nbank = 0; + break; + } + } - mem_mapping_set_addr(&ram_low_mapping, 0, 0x40000); + if((scat_regs[SCAT_VERSION] & 0x0F) > 3 && (mem_size > 2048) && (mem_size & 1536)) { + if((mem_size & 1536) == 512) { + if(nbank == 0) + addr &= 0x7FFFF; + else + addr = 0x80000 + ((addr & 0x1FFFFF) | ((nbank - 1) << 21)); + } else { + if(nbank < 2) + addr = (addr & 0x7FFFF) | (nbank << 19); + else + addr = 0x100000 + ((addr & 0x1FFFFF) | ((nbank - 2) << 21)); + } + } else { + int nbanks_2048k, nbanks_512k; + if (mem_size <= ((scat_regs[SCAT_VERSION] & 0x0F) > 3 ? 2048 : 4096) && (((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 8) || external_is_RAS)) { + nbanks_2048k = 0; + nbanks_512k = mem_size >> 9; + } else { + nbanks_2048k = mem_size >> 11; + nbanks_512k = (mem_size & 1536) >> 9; + } + if(nbank < nbanks_2048k || (nbanks_2048k > 0 && nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7))) { + addr &= 0x1FFFFF; + addr |= (nbank << 21); + } else if(nbank < nbanks_2048k + nbanks_512k || nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7)) { + addr &= 0x7FFFF; + addr |= (nbanks_2048k << 21) | ((nbank - nbanks_2048k) << 19); + } else { + addr &= 0x1FFFF; + addr |= (nbanks_2048k << 21) | (nbanks_512k << 19) | ((nbank - nbanks_2048k - nbanks_512k) << 17); + } + } + } else { + uint32_t addr2; + switch(scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) { + case 2: + case 4: + nbank = addr >> 19; + if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else + addr2 = addr >> 10; + break; + case 3: + nbank = addr >> 19; + if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) == 2 && (addr & 0x7FFFF) < 0x60000) { + addr ^= 0x1F0000; + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else + addr2 = addr >> 10; + break; + case 5: + nbank = addr >> 19; + if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4) { + nbank = (addr >> 10) & 3; + addr2 = addr >> 12; + } else + addr2 = addr >> 10; + break; + case 6: + nbank = addr >> 19; + if(nbank < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else { + nbank = 2 + ((addr - 0x100000) >> 21); + addr2 = (addr - 0x100000) >> 11; + } + break; + case 7: + case 0x0F: + nbank = addr >> 19; + if(nbank < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else if(nbank < 10) { + nbank = 2 + (((addr - 0x100000) >> 11) & 1); + addr2 = (addr - 0x100000) >> 12; + } else { + nbank = 4 + ((addr - 0x500000) >> 21); + addr2 = (addr - 0x500000) >> 11; + } + break; + case 8: + nbank = addr >> 19; + if(nbank < 4) { + nbank = 1; + addr2 = addr >> 11; + } else if(nbank == 4) { + nbank = 0; + addr2 = addr >> 10; + } else { + nbank -= 3; + addr2 = addr >> 10; + } + break; + case 9: + nbank = addr >> 19; + if(nbank < 8) { + nbank = 1 + ((addr >> 11) & 1); + addr2 = addr >> 12; + } else if(nbank == 8) { + nbank = 0; + addr2 = addr >> 10; + } else { + nbank -= 6; + addr2 = addr >> 10; + } + break; + case 0x0A: + nbank = addr >> 19; + if(nbank < 8) { + nbank = 1 + ((addr >> 11) & 1); + addr2 = addr >> 12; + } else if(nbank < 12) { + nbank = 3; + addr2 = addr >> 11; + } else if(nbank == 12) { + nbank = 0; + addr2 = addr >> 10; + } else { + nbank -= 9; + addr2 = addr >> 10; + } + break; + case 0x0B: + nbank = addr >> 21; + addr2 = addr >> 11; + break; + case 0x0C: + case 0x0D: + nbank = addr >> 21; + if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { + nbank = (addr >> 11) & 1; + addr2 = addr >> 12; + } else + addr2 = addr >> 11; + break; + case 0x0E: + case 0x13: + nbank = addr >> 21; + if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4) { + nbank = (addr >> 11) & 3; + addr2 = addr >> 13; + } else + addr2 = addr >> 11; + break; + case 0x10: + case 0x11: + nbank = addr >> 19; + if(nbank < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else if(nbank < 10) { + nbank = 2 + (((addr - 0x100000) >> 11) & 1); + addr2 = (addr - 0x100000) >> 12; + } else if(nbank < 18) { + nbank = 4 + (((addr - 0x500000) >> 11) & 1); + addr2 = (addr - 0x500000) >> 12; + } else { + nbank = 6 + ((addr - 0x900000) >> 21); + addr2 = (addr - 0x900000) >> 11; + } + break; + case 0x12: + nbank = addr >> 19; + if(nbank < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else if(nbank < 10) { + nbank = 2 + (((addr - 0x100000) >> 11) & 1); + addr2 = (addr - 0x100000) >> 12; + } else { + nbank = 4 + (((addr - 0x500000) >> 11) & 3); + addr2 = (addr - 0x500000) >> 13; + } + break; + case 0x14: + case 0x15: + nbank = addr >> 21; + if((nbank & 7) < 4) { + nbank = (addr >> 11) & 3; + addr2 = addr >> 13; + } else if((nbank & 7) < 6) { + nbank = 4 + (((addr - 0x800000) >> 11) & 1); + addr2 = (addr - 0x800000) >> 12; + } else { + nbank = 6 + (((addr - 0xC00000) >> 11) & 3); + addr2 = (addr - 0xC00000) >> 13; + } + break; + case 0x16: + nbank = ((addr >> 21) & 4) | ((addr >> 11) & 3); + addr2 = addr >> 13; + break; + case 0x17: + if(external_is_RAS && (addr & 0x800) == 0) + return 0xFFFFFFFF; + nbank = addr >> 19; + if(nbank < 2) { + nbank = (addr >> 10) & 1; + addr2 = addr >> 11; + } else { + nbank = 2 + ((addr - 0x100000) >> 23); + addr2 = (addr - 0x100000) >> 12; + } + break; + case 0x18: + if(external_is_RAS && (addr & 0x800) == 0) + return 0xFFFFFFFF; + nbank = addr >> 21; + if(nbank < 4) { + nbank = 1; + addr2 = addr >> 12; + } else if(nbank == 4) { + nbank = 0; + addr2 = addr >> 11; + } else { + nbank -= 3; + addr2 = addr >> 11; + } + break; + case 0x19: + if(external_is_RAS && (addr & 0x800) == 0) + return 0xFFFFFFFF; + nbank = addr >> 23; + if((nbank & 3) < 2) { + nbank = (addr >> 12) & 1; + addr2 = addr >> 13; + } else + addr2 = addr >> 12; + break; + default: + if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 6) { + nbank = addr >> 19; + addr2 = (addr >> 10) & 0x1FF; + } else if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 0x17) { + nbank = addr >> 21; + addr2 = (addr >> 11) & 0x3FF; + } else { + nbank = addr >> 23; + addr2 = (addr >> 12) & 0x7FF; + } + break; + } - for (i = 0; i < 24; i++) - { - mem_mapping_add(&scat_4000_9FFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_enable(&scat_4000_9FFF_mapping[i]); - } + nbank &= (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) ? 7 : 3; + if ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) > 0x16 && nbank == 3) + return 0xFFFFFFFF; - mem_mapping_add(&scat_A000_BFFF_mapping, 0xA0000, 0x20000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, ram + 0xA0000, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_enable(&scat_A000_BFFF_mapping); + if(external_is_RAS && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0) { + if(nbank == 3) + nbank = 7; + else + return 0xFFFFFFFF; + } else if(!external_is_RAS && scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) { + switch(nbank) { + case 7: + nbank = 3; + break; + /* Note - In the following cases, the chipset accesses multiple memory banks + at the same time, so it's impossible to predict which memory bank + is actually accessed. */ + case 5: + case 1: + nbank = 1; + break; + case 3: + nbank = 2; + break; + default: + nbank = 0; + break; + } + } - for (i = 0; i < 32; i++) - { - scat_stat[i].regs_2x8 = 0xff; - scat_stat[i].regs_2x9 = 0x03; - mem_mapping_add(&scat_mapping[i], (i + (i >= 24 ? 28 : 16)) << 14, 0x04000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, ram + ((i + (i >= 24 ? 28 : 16)) << 14), 0, &scat_stat[i]); - mem_mapping_disable(&scat_mapping[i]); - } + switch(mem_size & ~511) { + case 1024: + case 1536: + addr &= 0x3FF; + if(nbank < 2) + addr |= (nbank << 10) | ((addr2 & 0x1FF) << 11); + else + addr |= ((addr2 & 0x1FF) << 10) | (nbank << 19); + break; + case 2048: + if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 5) { + addr &= 0x3FF; + if(nbank < 4) + addr |= (nbank << 10) | ((addr2 & 0x1FF) << 12); + else + addr |= ((addr2 & 0x1FF) << 10) | (nbank << 19); + } else { + addr &= 0x7FF; + addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21); + } + break; + case 2560: + if(nbank == 0) + addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10); + else { + addr &= 0x7FF; + addr2 &= 0x3FF; + addr = addr + 0x80000 + ((addr2 << 11) | ((nbank - 1) << 21)); + } + break; + case 3072: + if(nbank < 2) + addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11); + else + addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21)); + break; + case 4096: + case 6144: + addr &= 0x7FF; + if(nbank < 2) + addr |= (nbank << 11) | ((addr2 & 0x3FF) << 12); + else + addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21); + break; + case 4608: + if(((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) >= 8 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) <= 0x0A) || ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 0x18)) { + if(nbank == 0) + addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10); + else if(nbank < 3) + addr = 0x80000 + ((addr & 0x7FF) | ((nbank - 1) << 11) | ((addr2 & 0x3FF) << 12)); + else + addr = 0x480000 + ((addr & 0x3FF) | ((addr2 & 0x1FF) << 10) | ((nbank - 3) << 19)); + } else if(nbank == 0) + addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10); + else { + addr &= 0x7FF; + addr2 &= 0x3FF; + addr = addr + 0x80000 + ((addr2 << 11) | ((nbank - 1) << 21)); + } + break; + case 5120: + case 7168: + if(nbank < 2) + addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11); + else if(nbank < 4) + addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11)); + else + addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21)); + break; + case 6656: + if(((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) >= 8 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) <= 0x0A) || ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 0x18)) { + if(nbank == 0) + addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10); + else if(nbank < 3) + addr = 0x80000 + ((addr & 0x7FF) | ((nbank - 1) << 11) | ((addr2 & 0x3FF) << 12)); + else if(nbank == 3) + addr = 0x480000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11)); + else + addr = 0x680000 + ((addr & 0x3FF) | ((addr2 & 0x1FF) << 10) | ((nbank - 4) << 19)); + } else if(nbank == 0) + addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10); + else if(nbank == 1) { + addr &= 0x7FF; + addr2 &= 0x3FF; + addr = addr + 0x80000 + (addr2 << 11); + } else { + addr &= 0x7FF; + addr2 &= 0x3FF; + addr = addr + 0x280000 + ((addr2 << 12) | ((nbank & 1) << 11) | (((nbank - 2) & 6) << 21)); + } + break; + case 8192: + addr &= 0x7FF; + if(nbank < 4) + addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13); + else + addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21); + break; + case 9216: + if(nbank < 2) + addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11); + else if(external_is_RAS) { + if(nbank < 6) + addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11)); + else + addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21)); + } else + addr = 0x100000 + ((addr & 0xFFF) | ((addr2 & 0x7FF) << 12) | ((nbank - 2) << 23)); + break; + case 10240: + if(external_is_RAS) { + addr &= 0x7FF; + if(nbank < 4) + addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13); + else + addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21); + } else if(nbank == 0) + addr = (addr & 0x7FF) | ((addr2 & 0x3FF) << 11); + else { + addr &= 0xFFF; + addr2 &= 0x7FF; + addr = addr + 0x200000 + ((addr2 << 12) | ((nbank - 1) << 23)); + } + break; + case 11264: + if(nbank < 2) + addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11); + else if(nbank < 6) + addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11)); + else + addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21)); + break; + case 12288: + if(external_is_RAS) { + addr &= 0x7FF; + if(nbank < 4) + addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13); + else if(nbank < 6) + addr |= ((nbank & 1) << 11) | ((addr2 & 0x3FF) << 12) | ((nbank & 4) << 21); + else + addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21); + } else { + if(nbank < 2) + addr = (addr & 0x7FF) | (nbank << 11) | ((addr2 & 0x3FF) << 12); + else + addr = 0x400000 + ((addr & 0xFFF) | ((addr2 & 0x7FF) << 12) | ((nbank - 2) << 23)); + } + break; + case 13312: + if(nbank < 2) + addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11); + else if(nbank < 4) + addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11)); + else + addr = 0x500000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 13) | ((nbank & 3) << 11)); + break; + case 14336: + addr &= 0x7FF; + if(nbank < 4) + addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13); + else if(nbank < 6) + addr |= ((nbank & 1) << 11) | ((addr2 & 0x3FF) << 12) | ((nbank & 4) << 21); + else + addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21); + break; + case 16384: + if(external_is_RAS) { + addr &= 0x7FF; + addr2 &= 0x3FF; + addr |= ((nbank & 3) << 11) | (addr2 << 13) | ((nbank & 4) << 21); + } else { + addr &= 0xFFF; + addr2 &= 0x7FF; + if(nbank < 2) + addr |= (addr2 << 13) | (nbank << 12); + else + addr |= (addr2 << 12) | (nbank << 23); + } + break; + default: + if(mem_size < 2048 || ((mem_size & 1536) == 512) || (mem_size == 2048 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 6)) { + addr &= 0x3FF; + addr2 &= 0x1FF; + addr |= (addr2 << 10) | (nbank << 19); + } else if(mem_size < 8192 || (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 0x17) { + addr &= 0x7FF; + addr2 &= 0x3FF; + addr |= (addr2 << 11) | (nbank << 21); + } else { + addr &= 0xFFF; + addr2 &= 0x7FF; + addr |= (addr2 << 12) | (nbank << 23); + } + break; + } + } + return addr; +} - for(i=4;i<10;i++) isram[i] = 0; - /* TODO - Only normal CPU accessing address FF0000 to FFFFFF mapped to ROM. - Normal CPU accessing address FC0000 to FEFFFF map to ROM should be implemented later. */ - for (i = 12; i < 16; i++) - { - mem_mapping_add(&scat_high_mapping[i], (i << 14) + 0xFC0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), 0, NULL); - } +static void +scat_set_global_EMS_state(int state) +{ + int i; + uint32_t base_addr, virt_addr; - for(i=0;i<6;i++) - mem_mapping_add(&scat_shadowram_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL); + for(i=((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0 : 24; i<32; i++) { + base_addr = (i + 16) << 14; + if(i >= 24) + base_addr += 0x30000; + if(state && (scat_stat[i].regs_2x9 & 0x80)) { + virt_addr = get_scat_addr(base_addr, &scat_stat[i]); + if(i < 24) mem_mapping_disable(&scat_4000_EFFF_mapping[i]); + else mem_mapping_disable(&scat_4000_EFFF_mapping[i + 12]); + mem_mapping_enable(&scat_ems_mapping[i]); + if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_ems_mapping[i], ram + virt_addr); + else mem_mapping_set_exec(&scat_ems_mapping[i], NULL); + } else { + mem_mapping_set_exec(&scat_ems_mapping[i], ram + base_addr); + mem_mapping_disable(&scat_ems_mapping[i]); - scat_set_xms_bound(0); - scat_shadow_state_update(); + int conf = (scat_regs[SCAT_VERSION] & 0xF0) ? (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) : (scat_regs[SCAT_DRAM_CONFIGURATION] & 0xF) | ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) >> 2); + if(i < 24) { + if(conf > 1 || (conf == 1 && i < 16)) + mem_mapping_enable(&scat_4000_EFFF_mapping[i]); + else + mem_mapping_disable(&scat_4000_EFFF_mapping[i]); + } else if(conf > 3 || ((scat_regs[SCAT_VERSION] & 0xF0) != 0 && conf == 2)) + mem_mapping_enable(&scat_4000_EFFF_mapping[i + 12]); + else + mem_mapping_disable(&scat_4000_EFFF_mapping[i + 12]); + } + } + flushmmucache(); +} + + +static void +scat_memmap_state_update() +{ + int i; + uint32_t addr; + + for(i=(((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0 : 16);i<44;i++) { + addr = get_scat_addr(0x40000 + (i << 14), NULL); + mem_mapping_set_exec(&scat_4000_EFFF_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL); + } + addr = get_scat_addr(0, NULL); + mem_mapping_set_exec(&scat_low_mapping[0], addr < (mem_size << 10) ? ram + addr : NULL); + addr = get_scat_addr(0xF0000, NULL); + mem_mapping_set_exec(&scat_low_mapping[1], addr < (mem_size << 10) ? ram + addr : NULL); + for(i=2;i<32;i++) { + addr = get_scat_addr(i << 19, NULL); + mem_mapping_set_exec(&scat_low_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL); + } + + if((scat_regs[SCAT_VERSION] & 0xF0) == 0) { + for(i=0;i < scat_max_map[(scat_regs[SCAT_DRAM_CONFIGURATION] & 0xF) | ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) >> 2)];i++) + mem_mapping_enable(&scat_low_mapping[i]); + for(;i<32;i++) mem_mapping_disable(&scat_low_mapping[i]); + + for(i=24;i<36;i++) { + if(((scat_regs[SCAT_DRAM_CONFIGURATION] & 0xF) | (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40)) < 4) + mem_mapping_disable(&scat_4000_EFFF_mapping[i]); + else + mem_mapping_enable(&scat_4000_EFFF_mapping[i]); + } + } else { + for(i=0;i < scatsx_max_map[scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F];i++) + mem_mapping_enable(&scat_low_mapping[i]); + for(;i<32;i++) mem_mapping_disable(&scat_low_mapping[i]); + + for(i=24;i<36;i++) { + if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 2 || (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3) + mem_mapping_disable(&scat_4000_EFFF_mapping[i]); + else + mem_mapping_enable(&scat_4000_EFFF_mapping[i]); + } + } + + if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) || ((scat_regs[SCAT_VERSION] & 0xF0) != 0)) { + if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3)) { + mem_mapping_disable(&scat_low_mapping[2]); + for(i=0;i<6;i++) { + addr = get_scat_addr(0x100000 + (i << 16), NULL); + mem_mapping_set_exec(&scat_remap_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL); + mem_mapping_enable(&scat_remap_mapping[i]); + } + } else { + for(i=0;i<6;i++) + mem_mapping_disable(&scat_remap_mapping[i]); + if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) > 4) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) > 3)) + mem_mapping_enable(&scat_low_mapping[2]); + } + } else { + for(i=0;i<6;i++) + mem_mapping_disable(&scat_remap_mapping[i]); + mem_mapping_enable(&scat_low_mapping[2]); + } + + scat_set_global_EMS_state(scat_regs[SCAT_EMS_CONTROL] & 0x80); +} + + +static void +scat_write(uint16_t port, uint8_t val, void *priv) +{ + uint8_t scat_reg_valid = 0, scat_shadow_update = 0, scat_map_update = 0, index; + uint32_t base_addr, virt_addr; + + switch (port) { + case 0x22: + scat_index = val; + break; + + case 0x23: + switch (scat_index) { + case SCAT_DMA_WAIT_STATE_CONTROL: + case SCAT_CLOCK_CONTROL: + case SCAT_PERIPHERAL_CONTROL: + scat_reg_valid = 1; + break; + case SCAT_EMS_CONTROL: + if(val & 0x40) { + if(val & 1) { + io_sethandler(0x0218, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + io_removehandler(0x0208, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + } else { + io_sethandler(0x0208, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + io_removehandler(0x0218, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + } + } else { + io_removehandler(0x0208, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + io_removehandler(0x0218, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + } + scat_set_global_EMS_state(val & 0x80); + scat_reg_valid = 1; + break; + case SCAT_POWER_MANAGEMENT: + /* TODO - Only use AUX parity disable bit for this version. + Other bits should be implemented later. */ + val &= (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x40 : 0x60; + scat_reg_valid = 1; + break; + case SCAT_DRAM_CONFIGURATION: + scat_map_update = 1; + + if((scat_regs[SCAT_VERSION] & 0xF0) == 0) { + cpu_waitstates = (val & 0x70) == 0 ? 1 : 2; + cpu_update_waitstates(); + } + + scat_reg_valid = 1; + break; + case SCAT_EXTENDED_BOUNDARY: + if((scat_regs[SCAT_VERSION] & 0xF0) == 0) { + if(scat_regs[SCAT_VERSION] < 4) { + val &= 0xBF; + scat_set_xms_bound(val & 0x0f); + } else { + val = (val & 0x7F) | 0x80; + scat_set_xms_bound(val & 0x4f); + } + } else + scat_set_xms_bound(val & 0x1f); + mem_set_mem_state(0x40000, 0x60000, (val & 0x20) ? MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL : MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + if((val ^ scat_regs[SCAT_EXTENDED_BOUNDARY]) & 0xC0) scat_map_update = 1; + scat_reg_valid = 1; + break; + case SCAT_ROM_ENABLE: + scat_reg_valid = 1; + scat_romcs_state_update(val); + break; + case SCAT_RAM_WRITE_PROTECT: + scat_reg_valid = 1; + flushmmucache_cr3(); + break; + case SCAT_SHADOW_RAM_ENABLE_1: + case SCAT_SHADOW_RAM_ENABLE_2: + case SCAT_SHADOW_RAM_ENABLE_3: + scat_reg_valid = 1; + scat_shadow_update = 1; + break; + case SCATSX_LAPTOP_FEATURES: + if((scat_regs[SCAT_VERSION] & 0xF0) != 0) { + val = (val & ~8) | (scat_regs[SCATSX_LAPTOP_FEATURES] & 8); + scat_reg_valid = 1; + } + break; + case SCATSX_FAST_VIDEO_CONTROL: + case SCATSX_FAST_VIDEORAM_ENABLE: + case SCATSX_HIGH_PERFORMANCE_REFRESH: + case SCATSX_CAS_TIMING_FOR_DMA: + if((scat_regs[SCAT_VERSION] & 0xF0) != 0) scat_reg_valid = 1; + break; + default: + break; + } + if (scat_reg_valid) + scat_regs[scat_index] = val; + if (scat_shadow_update) + scat_shadow_state_update(); + if (scat_map_update) + scat_memmap_state_update(); + break; + + case 0x92: + if ((mem_a20_alt ^ val) & 2) { + mem_a20_alt = val & 2; + mem_a20_recalc(); + } + if ((~scat_port_92 & val) & 1) { + softresetx86(); + cpu_set_edx(); + } + scat_port_92 = val; + break; + + case 0x208: + case 0x218: + if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { + if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; + else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; + scat_stat[index].regs_2x8 = val; + base_addr = (index + 16) << 14; + if(index >= 24) + base_addr += 0x30000; + + if((scat_regs[SCAT_EMS_CONTROL] & 0x80) && (scat_stat[index].regs_2x9 & 0x80)) { + virt_addr = get_scat_addr(base_addr, &scat_stat[index]); + if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_ems_mapping[index], ram + virt_addr); + else mem_mapping_set_exec(&scat_ems_mapping[index], NULL); + flushmmucache(); + } + } + break; + case 0x209: + case 0x219: + if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { + if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; + else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; + scat_stat[index].regs_2x9 = val; + base_addr = (index + 16) << 14; + if(index >= 24) + base_addr += 0x30000; + + if (scat_regs[SCAT_EMS_CONTROL] & 0x80) { + if (val & 0x80) { + virt_addr = get_scat_addr(base_addr, &scat_stat[index]); + if(index < 24) mem_mapping_disable(&scat_4000_EFFF_mapping[index]); + else mem_mapping_disable(&scat_4000_EFFF_mapping[index + 12]); + if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_ems_mapping[index], ram + virt_addr); + else mem_mapping_set_exec(&scat_ems_mapping[index], NULL); + mem_mapping_enable(&scat_ems_mapping[index]); + } else { + mem_mapping_set_exec(&scat_ems_mapping[index], ram + base_addr); + mem_mapping_disable(&scat_ems_mapping[index]); + if(index < 24) mem_mapping_enable(&scat_4000_EFFF_mapping[index]); + else mem_mapping_enable(&scat_4000_EFFF_mapping[index + 12]); + } + flushmmucache(); + } + + if (scat_ems_reg_2xA & 0x80) + scat_ems_reg_2xA = (scat_ems_reg_2xA & 0xe0) | ((scat_ems_reg_2xA + 1) & (((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0x1f : 3)); + } + break; + case 0x20A: + case 0x21A: + if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) + scat_ems_reg_2xA = ((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? val : val & 0xc3; + break; + } +} + + +static uint8_t +scat_read(uint16_t port, void *priv) +{ + uint8_t val = 0xff, index; + switch (port) { + case 0x23: + switch (scat_index) { + case SCAT_MISCELLANEOUS_STATUS: + val = (scat_regs[scat_index] & 0x3f) | (~nmi_mask & 0x80) | ((mem_a20_key & 2) << 5); + break; + case SCAT_DRAM_CONFIGURATION: + if ((scat_regs[SCAT_VERSION] & 0xF0) == 0) val = (scat_regs[scat_index] & 0x8f) | (cpu_waitstates == 1 ? 0 : 0x10); + else val = scat_regs[scat_index]; + break; + case SCAT_EXTENDED_BOUNDARY: + val = scat_regs[scat_index]; + if ((scat_regs[SCAT_VERSION] & 0xF0) == 0) { + if((scat_regs[SCAT_VERSION] & 0x0F) >= 4) + val |= 0x80; + else + val &= 0xAF; + } + break; + default: + val = scat_regs[scat_index]; + break; + } + break; + + case 0x92: + val = scat_port_92; + break; + + case 0x208: + case 0x218: + if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { + if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; + else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; + val = scat_stat[index].regs_2x8; + } + break; + case 0x209: + case 0x219: + if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { + if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; + else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; + val = scat_stat[index].regs_2x9; + } + break; + case 0x20A: + case 0x21A: + if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) + val = scat_ems_reg_2xA; + break; + } + return val; +} + + +static uint8_t +mem_read_scatb(uint32_t addr, void *priv) +{ + uint8_t val = 0xff; + scat_t *stat = (scat_t *)priv; + + addr = get_scat_addr(addr, stat); + if (addr < (mem_size << 10)) + val = ram[addr]; + + return val; +} + + +static void +mem_write_scatb(uint32_t addr, uint8_t val, void *priv) +{ + scat_t *stat = (scat_t *)priv; + uint32_t oldaddr = addr, chkaddr; + + addr = get_scat_addr(addr, stat); + chkaddr = stat ? addr : oldaddr; + if (chkaddr >= 0xC0000 && chkaddr < 0x100000) { + if(scat_regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xC0000) >> 15))) return; + } + if (addr < (mem_size << 10)) + ram[addr] = val; +} + + +static uint16_t +mem_read_scatw(uint32_t addr, void *priv) +{ + uint16_t val = 0xffff; + scat_t *stat = (scat_t *)priv; + + addr = get_scat_addr(addr, stat); + if (addr < (mem_size << 10)) + val = *(uint16_t *)&ram[addr]; + + return val; +} + + +static void +mem_write_scatw(uint32_t addr, uint16_t val, void *priv) +{ + scat_t *stat = (scat_t *)priv; + uint32_t oldaddr = addr, chkaddr; + + addr = get_scat_addr(addr, stat); + chkaddr = stat ? addr : oldaddr; + if (chkaddr >= 0xC0000 && chkaddr < 0x100000) { + if(scat_regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xC0000) >> 15))) return; + } + if (addr < (mem_size << 10)) + *(uint16_t *)&ram[addr] = val; +} + + +static uint32_t +mem_read_scatl(uint32_t addr, void *priv) +{ + uint32_t val = 0xffffffff; + scat_t *stat = (scat_t *)priv; + + addr = get_scat_addr(addr, stat); + if (addr < (mem_size << 10)) + val = *(uint32_t *)&ram[addr]; + + return val; +} + + +static void +mem_write_scatl(uint32_t addr, uint32_t val, void *priv) +{ + scat_t *stat = (scat_t *)priv; + uint32_t oldaddr = addr, chkaddr; + + addr = get_scat_addr(addr, stat); + chkaddr = stat ? addr : oldaddr; + if (chkaddr >= 0xC0000 && chkaddr < 0x100000) { + if(scat_regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xC0000) >> 15))) return; + } + if (addr < (mem_size << 10)) + *(uint32_t *)&ram[addr] = val; +} + + +static void +scat_init() +{ + int i; + + io_sethandler(0x0022, 0x0002, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + io_sethandler(0x0092, 0x0001, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + + for (i = 0; i < 256; i++) + scat_regs[i] = 0xff; + + scat_regs[SCAT_DMA_WAIT_STATE_CONTROL] = 0; + switch(romset) { + case ROM_GW286CT: + case ROM_SPC4216P: + scat_regs[SCAT_VERSION] = 4; + break; + default: + scat_regs[SCAT_VERSION] = 1; + break; + } + scat_regs[SCAT_CLOCK_CONTROL] = 2; + scat_regs[SCAT_PERIPHERAL_CONTROL] = 0x80; + scat_regs[SCAT_MISCELLANEOUS_STATUS] = 0x37; + scat_regs[SCAT_POWER_MANAGEMENT] = 0; + scat_regs[SCAT_ROM_ENABLE] = 0xC0; + scat_regs[SCAT_RAM_WRITE_PROTECT] = 0; + scat_regs[SCAT_SHADOW_RAM_ENABLE_1] = 0; + scat_regs[SCAT_SHADOW_RAM_ENABLE_2] = 0; + scat_regs[SCAT_SHADOW_RAM_ENABLE_3] = 0; + scat_regs[SCAT_DRAM_CONFIGURATION] = cpu_waitstates == 1 ? 2 : 0x12; + scat_regs[SCAT_EXTENDED_BOUNDARY] = 0; + scat_regs[SCAT_EMS_CONTROL] = 0; + scat_port_92 = 0; + + mem_mapping_disable(&ram_low_mapping); + mem_mapping_disable(&ram_mid_mapping); + mem_mapping_disable(&ram_high_mapping); + for (i = 0; i < 4; i++) + mem_mapping_disable(&bios_mapping[i]); + mem_mapping_add(&scat_low_mapping[0], 0, 0x40000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram, MEM_MAPPING_INTERNAL, NULL); + mem_mapping_add(&scat_low_mapping[1], 0xF0000, 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + 0xF0000, MEM_MAPPING_INTERNAL, NULL); + for(i=2;i<32;i++) + mem_mapping_add(&scat_low_mapping[i], (i << 19), 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + (i << 19), MEM_MAPPING_INTERNAL, NULL); + mem_mapping_set_addr(&scat_low_mapping[31], 0xF80000, scat_regs[SCAT_VERSION] < 4 ? 0x40000 : 0x60000); + + for (i = 0; i < 44; i++) + mem_mapping_add(&scat_4000_EFFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL); + for (i = 0; i < 8; i++) { + mem_mapping_add(&scat_low_ROMCS_mapping[i], 0xC0000 + (i << 14), 0x4000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, NULL); + mem_mapping_disable(&scat_low_ROMCS_mapping[i]); + } + + for (i = 0; i < 32; i++) { + scat_stat[i].regs_2x8 = 0xff; + scat_stat[i].regs_2x9 = 0x03; + mem_mapping_add(&scat_ems_mapping[i], (i + (i >= 24 ? 28 : 16)) << 14, 0x04000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + ((i + (i >= 24 ? 28 : 16)) << 14), 0, &scat_stat[i]); + } + + for(i=4;i<10;i++) isram[i] = 0; + + for (i = (scat_regs[SCAT_VERSION] < 4 ? 0 : 8); i < 16; i++) { + mem_mapping_add(&scat_high_mapping[i], (i << 14) + 0xFC0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), 0, NULL); + mem_mapping_enable(&scat_high_mapping[i]); + } + + for(i=0;i<6;i++) + mem_mapping_add(&scat_remap_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL); + + external_is_RAS = (scat_regs[SCAT_VERSION] > 3) || (((mem_size & ~2047) >> 11) + ((mem_size & 1536) >> 9) + ((mem_size & 511) >> 7)) > 4; + + scat_set_xms_bound(0); + scat_memmap_state_update(); + scat_shadow_state_update(); } static void scatsx_init() { - int i; + int i; - io_sethandler(0x0022, 0x0002, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + io_sethandler(0x0022, 0x0002, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + io_sethandler(0x0092, 0x0001, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); - port_92_reset(); + for (i = 0; i < 256; i++) + scat_regs[i] = 0xff; - port_92_add(); + scat_regs[SCAT_DMA_WAIT_STATE_CONTROL] = 0; + scat_regs[SCAT_VERSION] = 0x13; + scat_regs[SCAT_CLOCK_CONTROL] = 6; + scat_regs[SCAT_PERIPHERAL_CONTROL] = 0; + scat_regs[SCAT_MISCELLANEOUS_STATUS] = 0x37; + scat_regs[SCAT_POWER_MANAGEMENT] = 0; + scat_regs[SCAT_ROM_ENABLE] = 0xC0; + scat_regs[SCAT_RAM_WRITE_PROTECT] = 0; + scat_regs[SCAT_SHADOW_RAM_ENABLE_1] = 0; + scat_regs[SCAT_SHADOW_RAM_ENABLE_2] = 0; + scat_regs[SCAT_SHADOW_RAM_ENABLE_3] = 0; + scat_regs[SCAT_DRAM_CONFIGURATION] = 1; + scat_regs[SCAT_EXTENDED_BOUNDARY] = 0; + scat_regs[SCAT_EMS_CONTROL] = 0; + scat_regs[SCATSX_LAPTOP_FEATURES] = 0; + scat_regs[SCATSX_FAST_VIDEO_CONTROL] = 0; + scat_regs[SCATSX_FAST_VIDEORAM_ENABLE] = 0; + scat_regs[SCATSX_HIGH_PERFORMANCE_REFRESH] = 8; + scat_regs[SCATSX_CAS_TIMING_FOR_DMA] = 3; + scat_port_92 = 0; - for (i = 0; i < 256; i++) - { - scat_regs[i] = 0xff; - } + mem_mapping_disable(&ram_low_mapping); + mem_mapping_disable(&ram_mid_mapping); + mem_mapping_disable(&ram_high_mapping); + for (i = 0; i < 4; i++) + mem_mapping_disable(&bios_mapping[i]); + mem_mapping_add(&scat_low_mapping[0], 0, 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram, MEM_MAPPING_INTERNAL, NULL); + mem_mapping_add(&scat_low_mapping[1], 0xF0000, 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + 0xF0000, MEM_MAPPING_INTERNAL, NULL); + for(i=2;i<32;i++) + mem_mapping_add(&scat_low_mapping[i], (i << 19), 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + (i << 19), MEM_MAPPING_INTERNAL, NULL); + mem_mapping_set_addr(&scat_low_mapping[31], 0xF80000, 0x40000); - scat_regs[SCAT_DMA_WAIT_STATE_CONTROL] = 0; - scat_regs[SCAT_VERSION] = 0x13; - scat_regs[SCAT_CLOCK_CONTROL] = 6; - scat_regs[SCAT_PERIPHERAL_CONTROL] = 0; - scat_regs[SCAT_MISCELLANEOUS_STATUS] = 0x37; - scat_regs[SCAT_POWER_MANAGEMENT] = 0; - scat_regs[SCAT_ROM_ENABLE] = 0xC0; - scat_regs[SCAT_RAM_WRITE_PROTECT] = 0; - scat_regs[SCAT_SHADOW_RAM_ENABLE_1] = 0; - scat_regs[SCAT_SHADOW_RAM_ENABLE_2] = 0; - scat_regs[SCAT_SHADOW_RAM_ENABLE_3] = 0; - scat_regs[SCAT_DRAM_CONFIGURATION] = 1; - scat_regs[SCAT_EXTENDED_BOUNDARY] = 0; - scat_regs[SCAT_EMS_CONTROL] = 0; - scat_regs[SCATSX_LAPTOP_FEATURES] = 0; - scat_regs[SCATSX_FAST_VIDEO_CONTROL] = 0; - scat_regs[SCATSX_FAST_VIDEORAM_ENABLE] = 0; - scat_regs[SCATSX_HIGH_PERFORMANCE_REFRESH] = 8; - scat_regs[SCATSX_CAS_TIMING_FOR_DMA] = 3; - scat_port_92 = 0; + for (i = 16; i < 44; i++) { + mem_mapping_add(&scat_4000_EFFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL); + mem_mapping_enable(&scat_4000_EFFF_mapping[i]); + } + for (i = 0; i < 8; i++) { + mem_mapping_add(&scat_low_ROMCS_mapping[i], 0xC0000 + (i << 14), 0x4000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, NULL); + mem_mapping_disable(&scat_low_ROMCS_mapping[i]); + } - mem_mapping_set_addr(&ram_low_mapping, 0, 0x80000); + for (i = 24; i < 32; i++) { + scat_stat[i].regs_2x8 = 0xff; + scat_stat[i].regs_2x9 = 0x03; + mem_mapping_add(&scat_ems_mapping[i], (i + 28) << 14, 0x04000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + ((i + 28) << 14), 0, &scat_stat[i]); + mem_mapping_disable(&scat_ems_mapping[i]); + } - for (i = 16; i < 24; i++) - { - mem_mapping_add(&scat_4000_9FFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_enable(&scat_4000_9FFF_mapping[i]); - } + for (i = 0; i < 16; i++) { + mem_mapping_add(&scat_high_mapping[i], (i << 14) + 0xFC0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), 0, NULL); + mem_mapping_enable(&scat_high_mapping[i]); + } - mem_mapping_add(&scat_A000_BFFF_mapping, 0xA0000, 0x20000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, ram + 0xA0000, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_enable(&scat_A000_BFFF_mapping); + for(i=0;i<6;i++) + mem_mapping_add(&scat_remap_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL); - for (i = 24; i < 32; i++) - { - scat_stat[i].regs_2x8 = 0xff; - scat_stat[i].regs_2x9 = 0x03; - mem_mapping_add(&scat_mapping[i], (i + 28) << 14, 0x04000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, ram + ((i + 28) << 14), 0, &scat_stat[i]); - mem_mapping_disable(&scat_mapping[i]); - } + external_is_RAS = scatsx_external_is_RAS[mem_size >> 9]; - /* TODO - Only normal CPU accessing address FF0000 to FFFFFF mapped to ROM. - Normal CPU accessing address FC0000 to FEFFFF map to ROM should be implemented later. */ - for (i = 12; i < 16; i++) - { - mem_mapping_add(&scat_high_mapping[i], (i << 14) + 0xFC0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), 0, NULL); - } - - for(i=0;i<6;i++) - mem_mapping_add(&scat_shadowram_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL); - - scat_set_xms_bound(0); - scat_shadow_state_update(); + scat_set_xms_bound(0); + scat_memmap_state_update(); + scat_shadow_state_update(); } diff --git a/src/machine/m_at_sis_85c496.c b/src/machine/m_at_sis_85c496.c index 1705425cb..ca8ffd732 100644 --- a/src/machine/m_at_sis_85c496.c +++ b/src/machine/m_at_sis_85c496.c @@ -1,14 +1,30 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ +/* + * 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 SiS 85c496/85c497 chip. + * + * Version: @(#)m_at_sis_85c496.c 1.0.1 2018/04/26 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + */ #include #include -#include #include +#include #include #include "../86box.h" #include "../cpu/cpu.h" #include "../device.h" +#include "../keyboard.h" #include "../io.h" #include "../pci.h" #include "../mem.h" @@ -20,169 +36,195 @@ typedef struct sis_85c496_t { - uint8_t pci_conf[256]; + uint8_t pci_conf[256]; } sis_85c496_t; -sis_85c496_t sis496; - - -static void sis_85c496_recalcmapping(void) +static void +sis_85c496_recalcmapping(sis_85c496_t *dev) { - int c; - - for (c = 0; c < 8; c++) - { - uint32_t base = 0xc0000 + (c << 15); - if (sis496.pci_conf[0x44] & (1 << c)) - { - switch (sis496.pci_conf[0x45] & 3) - { - case 0: - mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - break; - case 1: - mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - break; - case 2: - mem_set_mem_state(base, 0x8000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - case 3: - mem_set_mem_state(base, 0x8000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); - break; - } - } - else - mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - } + int c; + uint32_t base; - flushmmucache(); - shadowbios = (sis496.pci_conf[0x44] & 0xf0); + for (c = 0; c < 8; c++) { + base = 0xc0000 + (c << 15); + if (dev->pci_conf[0x44] & (1 << c)) { + switch (dev->pci_conf[0x45] & 3) { + case 0: + mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 1: + mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + case 2: + mem_set_mem_state(base, 0x8000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + case 3: + mem_set_mem_state(base, 0x8000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + } + } else + mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } + + flushmmucache(); + shadowbios = (dev->pci_conf[0x44] & 0xf0); } -static void sis_85c496_write(int func, int addr, uint8_t val, void *p) +static void +sis_85c496_write(int func, int addr, uint8_t val, void *p) { - switch (addr) - { - case 0x44: /*Shadow configure*/ - if ((sis496.pci_conf[0x44] & val) ^ 0xf0) - { - sis496.pci_conf[0x44] = val; - sis_85c496_recalcmapping(); - } - break; - case 0x45: /*Shadow configure*/ - if ((sis496.pci_conf[0x45] & val) ^ 0x01) - { - sis496.pci_conf[0x45] = val; - sis_85c496_recalcmapping(); - } - break; - - case 0xc0: - if (val & 0x80) - pci_set_irq_routing(PCI_INTA, val & 0xf); - else - pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); - break; - case 0xc1: - if (val & 0x80) - pci_set_irq_routing(PCI_INTB, val & 0xf); - else - pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); - break; - case 0xc2: - if (val & 0x80) - pci_set_irq_routing(PCI_INTC, val & 0xf); - else - pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); - break; - case 0xc3:// pclog("IRQ routing %02x %02x\n", addr, val); - if (val & 0x80) - pci_set_irq_routing(PCI_INTD, val & 0xf); - else - pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); - break; - } + sis_85c496_t *dev = (sis_85c496_t *) p; + + switch (addr) { + case 0x44: /*Shadow configure*/ + if ((dev->pci_conf[0x44] & val) ^ 0xf0) { + dev->pci_conf[0x44] = val; + sis_85c496_recalcmapping(dev); + } + break; + case 0x45: /*Shadow configure*/ + if ((dev->pci_conf[0x45] & val) ^ 0x01) { + dev->pci_conf[0x45] = val; + sis_85c496_recalcmapping(dev); + } + break; + + case 0xc0: + if (val & 0x80) + pci_set_irq_routing(PCI_INTA, val & 0xf); + else + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + break; + case 0xc1: + if (val & 0x80) + pci_set_irq_routing(PCI_INTB, val & 0xf); + else + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + break; + case 0xc2: + if (val & 0x80) + pci_set_irq_routing(PCI_INTC, val & 0xf); + else + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + break; + case 0xc3: + if (val & 0x80) + pci_set_irq_routing(PCI_INTD, val & 0xf); + else + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + break; + } - if ((addr >= 4 && addr < 8) || addr >= 0x40) - sis496.pci_conf[addr] = val; + if ((addr >= 4 && addr < 8) || addr >= 0x40) + dev->pci_conf[addr] = val; } -static uint8_t sis_85c496_read(int func, int addr, void *p) +static uint8_t +sis_85c496_read(int func, int addr, void *p) { - return sis496.pci_conf[addr]; + sis_85c496_t *dev = (sis_85c496_t *) p; + + return dev->pci_conf[addr]; } -static void sis_85c496_reset(void) +static void +sis_85c496_reset(void *priv) { - memset(&sis496, 0, sizeof(sis_85c496_t)); - - sis496.pci_conf[0x00] = 0x39; /*SiS*/ - sis496.pci_conf[0x01] = 0x10; - sis496.pci_conf[0x02] = 0x96; /*496/497*/ - sis496.pci_conf[0x03] = 0x04; + uint8_t val = 0; - sis496.pci_conf[0x04] = 7; - sis496.pci_conf[0x05] = 0; - - sis496.pci_conf[0x06] = 0x80; - sis496.pci_conf[0x07] = 0x02; - - sis496.pci_conf[0x08] = 2; /*Device revision*/ - - sis496.pci_conf[0x09] = 0x00; /*Device class (PCI bridge)*/ - sis496.pci_conf[0x0a] = 0x00; - sis496.pci_conf[0x0b] = 0x06; - - sis496.pci_conf[0x0e] = 0x00; /*Single function device*/ + val = sis_85c496_read(0, 0x44, priv); /* Read current value of 0x44. */ + sis_85c496_write(0, 0x44, val & 0xf, priv); /* Turn off shadow BIOS but keep the lower 4 bits. */ } -static void sis_85c496_pci_reset(void) +static void +sis_85c496_close(void *p) { - uint8_t val = 0; + sis_85c496_t *sis_85c496 = (sis_85c496_t *)p; - val = sis_85c496_read(0, 0x44, NULL); /* Read current value of 0x44. */ - sis_85c496_write(0, 0x44, val & 0xf, NULL); /* Turn off shadow BIOS but keep the lower 4 bits. */ + free(sis_85c496); } -static void sis_85c496_init(void) +static void +*sis_85c496_init(const device_t *info) { - pci_add_card(5, sis_85c496_read, sis_85c496_write, NULL); + sis_85c496_t *sis496 = malloc(sizeof(sis_85c496_t)); + memset(sis496, 0, sizeof(sis_85c496_t)); - sis_85c496_reset(); + sis496->pci_conf[0x00] = 0x39; /*SiS*/ + sis496->pci_conf[0x01] = 0x10; + sis496->pci_conf[0x02] = 0x96; /*496/497*/ + sis496->pci_conf[0x03] = 0x04; - pci_reset_handler.pci_master_reset = sis_85c496_pci_reset; + sis496->pci_conf[0x04] = 7; + sis496->pci_conf[0x05] = 0; + + sis496->pci_conf[0x06] = 0x80; + sis496->pci_conf[0x07] = 0x02; + + sis496->pci_conf[0x08] = 2; /*Device revision*/ + + sis496->pci_conf[0x09] = 0x00; /*Device class (PCI bridge)*/ + sis496->pci_conf[0x0a] = 0x00; + sis496->pci_conf[0x0b] = 0x06; + + sis496->pci_conf[0x0e] = 0x00; /*Single function device*/ + + pci_add_card(5, sis_85c496_read, sis_85c496_write, sis496); + + return sis496; } +const device_t sis_85c496_device = +{ + "SiS 85c496/85c497", + DEVICE_PCI, + 0, + sis_85c496_init, + sis_85c496_close, + sis_85c496_reset, + NULL, + NULL, + NULL, + NULL +}; + + static void machine_at_sis_85c496_common_init(const machine_t *model) { - machine_at_ps2_init(model); - device_add(&ide_pci_device); + machine_at_common_init(model); + device_add(&keyboard_ps2_pci_device); - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x05, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x07, PCI_CARD_NORMAL, 4, 1, 2, 3); + device_add(&ide_pci_device); - sis_85c496_init(); + memregs_init(); + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x05, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x07, PCI_CARD_NORMAL, 4, 1, 2, 3); + + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + + device_add(&sis_85c496_device); } void machine_at_r418_init(const machine_t *model) { - machine_at_sis_85c496_common_init(model); + machine_at_sis_85c496_common_init(model); - fdc37c665_init(); + fdc37c665_init(); } diff --git a/src/machine/m_at_sis_85c50x.c b/src/machine/m_at_sis_85c50x.c index c5f18eeca..d64ffa48a 100644 --- a/src/machine/m_at_sis_85c50x.c +++ b/src/machine/m_at_sis_85c50x.c @@ -6,14 +6,14 @@ * * Emulation of the SiS 50x PCI chips. * - * Version: @(#)m_at_sis_85c50x.c 1.0.6 2018/03/18 + * Version: @(#)m_at_sis_85c50x.c 1.0.7 2018/04/29 * * Author: Miran Grca, * * Copyright 2015-2018 Miran Grca. */ -#include #include +#include #include #include #include @@ -87,7 +87,6 @@ static void sis_85c501_recalcmapping(void) static void sis_85c501_write(int func, int addr, uint8_t val, void *p) { - /* pclog("sis_85c501_write : addr=%02x val=%02x\n", addr, val); */ if (func) return; @@ -131,8 +130,6 @@ static void sis_85c501_write(int func, int addr, uint8_t val, void *p) static void sis_85c503_write(int func, int addr, uint8_t val, void *p) { - /* pclog("sis_85c503_write : addr=%02x val=%02x\n", addr, val); */ - if (func > 0) return; @@ -162,28 +159,24 @@ static void sis_85c503_write(int func, int addr, uint8_t val, void *p) break; case 0x41: - pclog("Set IRQ routing: INT A -> %02X\n", val); if (val & 0x80) pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); else pci_set_irq_routing(PCI_INTA, val & 0xf); break; case 0x42: - pclog("Set IRQ routing: INT B -> %02X\n", val); if (val & 0x80) pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); else pci_set_irq_routing(PCI_INTC, val & 0xf); break; case 0x43: - pclog("Set IRQ routing: INT C -> %02X\n", val); if (val & 0x80) pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); else pci_set_irq_routing(PCI_INTB, val & 0xf); break; case 0x44: - pclog("Set IRQ routing: INT D -> %02X\n", val); if (val & 0x80) pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); else diff --git a/src/machine/m_at_t3100e.c b/src/machine/m_at_t3100e.c index 799e4055c..6f62b7cf7 100644 --- a/src/machine/m_at_t3100e.c +++ b/src/machine/m_at_t3100e.c @@ -117,7 +117,7 @@ * bit 2 set for single-pixel LCD font * bits 0,1 for display font * - * Version: @(#)m_at_t3100e.c 1.0.4 2018/03/18 + * Version: @(#)m_at_t3100e.c 1.0.5 2018/04/29 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -145,11 +145,13 @@ * Boston, MA 02111-1307 * USA. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../io.h" #include "../mouse.h" @@ -168,9 +170,6 @@ extern uint8_t *ram; /* Physical RAM */ void at_init(); -static const int t3100e_log = 0; - - /* The T3100e motherboard can (and does) dynamically reassign RAM between * conventional, XMS and EMS. This translates to monkeying with the mappings. */ @@ -214,6 +213,27 @@ struct t3100e_ems_regs void t3100e_ems_out(uint16_t addr, uint8_t val, void *p); +#ifdef ENABLE_T3100E_LOG +int t3100e_do_log = ENABLE_T3100E_LOG; +#endif + + +static void +t3100e_log(const char *fmt, ...) +{ +#ifdef ENABLE_T3100E_LOG + va_list ap; + + if (t3100e_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + /* Given a memory address (which ought to be in the page frame at 0xD0000), * which page does it relate to? */ static int addr_to_page(uint32_t addr) @@ -329,7 +349,7 @@ void dump_mappings() offset = t3100e_ems.page_exec[3]; } - pclog(" %p | base=%05x size=%05x %c @ %06x %s\n", mm, + t3100e_log(" %p | base=%05x size=%05x %c @ %06x %s\n", mm, mm->base, mm->size, mm->enable ? 'Y' : 'N', offset, name); @@ -342,16 +362,14 @@ void t3100e_map_ram(uint8_t val) int n; int32_t upper_len; - if (t3100e_log) - { - pclog("OUT 0x8084, %02x [ set memory mapping :", val | 0x40); - if (val & 1) pclog("ENABLE_EMS "); - if (val & 2) pclog("ENABLE_XMS "); - if (val & 4) pclog("640K "); - if (val & 8) pclog("X8X "); - if (val & 16) pclog("UPPER_IS_XMS "); - pclog("\n"); - } + t3100e_log("OUT 0x8084, %02x [ set memory mapping :", val | 0x40); + if (val & 1) t3100e_log("ENABLE_EMS "); + if (val & 2) t3100e_log("ENABLE_XMS "); + if (val & 4) t3100e_log("640K "); + if (val & 8) t3100e_log("X8X "); + if (val & 16) t3100e_log("UPPER_IS_XMS "); + t3100e_log("\n"); + /* Bit 2 controls size of conventional memory */ if (val & 4) { @@ -441,7 +459,7 @@ uint8_t t3100e_sys_in(uint16_t addr, void *p) /* The low 4 bits always seem to be 0x0C. The high 4 are a * notification sent by the keyboard controller when it detects * an [Fn] key combination */ - if (t3100e_log) pclog("IN 0x8084\n"); + t3100e_log("IN 0x8084\n"); return 0x0C | (regs->notify << 4); } @@ -455,7 +473,7 @@ void t3100e_sys_out(uint16_t addr, uint8_t val, void *p) switch (val & 0xE0) { case 0x00: /* Set serial port IRQs. Not implemented */ - if (t3100e_log) pclog("OUT 0x8084, %02x [ set serial port IRQs]\n", val); + t3100e_log("OUT 0x8084, %02x [ set serial port IRQs]\n", val); break; case 0x40: /* Set RAM mappings. */ t3100e_map_ram(val & 0x1F); @@ -465,7 +483,7 @@ void t3100e_sys_out(uint16_t addr, uint8_t val, void *p) t3100e_video_options_set(val & 0x1F); break; /* Other options not implemented. */ - default: if (t3100e_log) pclog("OUT 0x8084, %02x\n", val); break; + default: t3100e_log("OUT 0x8084, %02x\n", val); break; } } @@ -562,7 +580,7 @@ void t3100e_ems_out(uint16_t addr, uint8_t val, void *p) int pg = port_to_page(addr); regs->page_exec[pg & 3] = t3100e_ems_execaddr(regs, pg, val); - if (t3100e_log) pclog("EMS: page %d %02x -> %02x [%06x]\n", + t3100e_log("EMS: page %d %02x -> %02x [%06x]\n", pg, regs->page[pg], val, regs->page_exec[pg & 3]); regs->page[pg] = val; @@ -570,14 +588,14 @@ void t3100e_ems_out(uint16_t addr, uint8_t val, void *p) /* Bit 7 set if page is enabled, reset if page is disabled */ if (regs->page_exec[pg]) { - if (t3100e_log) pclog("Enabling EMS RAM at %05x\n", + t3100e_log("Enabling EMS RAM at %05x\n", page_to_addr(pg)); mem_mapping_enable(®s->mapping[pg]); mem_mapping_set_exec(®s->mapping[pg], ram + regs->page_exec[pg]); } else { - if (t3100e_log) pclog("Disabling EMS RAM at %05x\n", + t3100e_log("Disabling EMS RAM at %05x\n", page_to_addr(pg)); mem_mapping_disable(®s->mapping[pg]); } @@ -604,9 +622,9 @@ static uint16_t ems_read_ramw(uint32_t addr, void *priv) int pg = addr_to_page(addr); if (pg < 0) return 0xFF; - //pclog("ems_read_ramw addr=%05x ", addr); + //t3100e_log("ems_read_ramw addr=%05x ", addr); addr = regs->page_exec[pg] + (addr & 0x3FFF); - //pclog("-> %06x val=%04x\n", addr, *(uint16_t *)&ram[addr]); + //t3100e_log("-> %06x val=%04x\n", addr, *(uint16_t *)&ram[addr]); return *(uint16_t *)&ram[addr]; } @@ -639,9 +657,9 @@ static void ems_write_ramw(uint32_t addr, uint16_t val, void *priv) int pg = addr_to_page(addr); if (pg < 0) return; - //pclog("ems_write_ramw addr=%05x ", addr); + //t3100e_log("ems_write_ramw addr=%05x ", addr); addr = regs->page_exec[pg] + (addr & 0x3FFF); - //pclog("-> %06x val=%04x\n", addr, val); + //t3100e_log("-> %06x val=%04x\n", addr, val); *(uint16_t *)&ram[addr] = val; } @@ -743,7 +761,7 @@ void machine_at_t3100e_init(const machine_t *model) /* Map the EMS page frame */ for (pg = 0; pg < 4; pg++) { - if (t3100e_log) pclog("Adding memory map at %x for page %d\n", page_to_addr(pg), pg); + t3100e_log("Adding memory map at %x for page %d\n", page_to_addr(pg), pg); mem_mapping_add(&t3100e_ems.mapping[pg], page_to_addr(pg), 16384, ems_read_ram, ems_read_ramw, ems_read_raml, diff --git a/src/machine/m_at_t3100e_vid.c b/src/machine/m_at_t3100e_vid.c index 033520034..55abf3149 100644 --- a/src/machine/m_at_t3100e_vid.c +++ b/src/machine/m_at_t3100e_vid.c @@ -22,7 +22,7 @@ * 61 50 52 0F 19 06 19 19 02 0D 0B 0C MONO * 2D 28 22 0A 67 00 64 67 02 03 06 07 640x400 * - * Version: @(#)m_at_t3100e_vid.c 1.0.4 2018/03/18 + * Version: @(#)m_at_t3100e_vid.c 1.0.6 2018/04/29 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -50,11 +50,13 @@ * Boston, MA 02111-1307 * USA. */ +#include #include #include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../device.h" #include "../io.h" @@ -196,7 +198,6 @@ void t3100e_write(uint32_t addr, uint8_t val, void *p) t3100e_t *t3100e = (t3100e_t *)p; egawrites++; -// pclog("CGA_WRITE %04X %02X\n", addr, val); t3100e->vram[addr & 0x7fff] = val; cycles -= 4; } @@ -209,7 +210,6 @@ uint8_t t3100e_read(uint32_t addr, void *p) egareads++; cycles -= 4; -// pclog("CGA_READ %04X\n", addr); return t3100e->vram[addr & 0x7fff]; } @@ -758,6 +758,5 @@ const device_t t3100e_device = NULL, NULL, t3100e_speed_changed, - NULL, NULL }; diff --git a/src/machine/m_at_wd76c10.c b/src/machine/m_at_wd76c10.c index f63cf2b8b..670edb6d9 100644 --- a/src/machine/m_at_wd76c10.c +++ b/src/machine/m_at_wd76c10.c @@ -1,8 +1,8 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ -#include #include +#include #include #include #include "../86box.h" @@ -50,7 +50,6 @@ wd76c10_read(uint16_t port, void *priv) static void wd76c10_write(uint16_t port, uint16_t val, void *priv) { - pclog("WD76C10 write %04X %04X\n", port, val); switch (port) { case 0x0092: diff --git a/src/machine/m_europc.c b/src/machine/m_europc.c index 63d4b4b4d..7e08d3109 100644 --- a/src/machine/m_europc.c +++ b/src/machine/m_europc.c @@ -68,7 +68,7 @@ * * WARNING THIS IS A WORK-IN-PROGRESS MODULE. USE AT OWN RISK. * - * Version: @(#)europc.c 1.0.3 2018/03/18 + * Version: @(#)europc.c 1.0.6 2018/04/29 * * Author: Fred N. van Kempen, * @@ -109,19 +109,21 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include #include +#include #include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../io.h" #include "../nmi.h" #include "../mem.h" #include "../rom.h" -#include "../nvr.h" #include "../device.h" +#include "../nvr.h" #include "../keyboard.h" #include "../mouse.h" #include "../game/gameport.h" @@ -167,6 +169,27 @@ typedef struct { static europc_t europc; +#ifdef ENABLE_EUROPC_LOG +int europc_do_log = ENABLE_EUROPC_LOG; +#endif + + +static void +europc_log(const char *fmt, ...) +{ +#ifdef ENABLE_EUROPC_LOG + va_list ap; + + if (europc_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + /* * This is called every second through the NVR/RTC hook. * @@ -180,7 +203,7 @@ static europc_t europc; * FIXME: should we mark NVR as dirty? */ static void -rtc_tick(nvr_t *nvr) +europc_rtc_tick(nvr_t *nvr) { uint8_t *regs; int mon, yr; @@ -388,7 +411,7 @@ jim_set(europc_t *sys, uint8_t reg, uint8_t val) case 0x1f: /* 0001 1111 */ case 0x0b: /* 0000 1011 */ //europc_jim.mode=AGA_MONO; - pclog("EuroPC: AGA Monochrome mode!\n"); + europc_log("EuroPC: AGA Monochrome mode!\n"); break; case 0x18: /* 0001 1000 */ @@ -398,12 +421,12 @@ jim_set(europc_t *sys, uint8_t reg, uint8_t val) case 0x0e: /* 0000 1100 */ /*80 columns? */ - pclog("EuroPC: AGA 80-column mode!\n"); + europc_log("EuroPC: AGA 80-column mode!\n"); break; case 0x0d: /* 0000 1011 */ /*40 columns? */ - pclog("EuroPC: AGA 40-column mode!\n"); + europc_log("EuroPC: AGA 40-column mode!\n"); break; default: @@ -444,7 +467,7 @@ jim_write(uint16_t addr, uint8_t val, void *priv) uint8_t b; #if EUROPC_DEBUG > 1 - pclog("EuroPC: jim_wr(%04x, %02x)\n", addr, val); + europc_log("EuroPC: jim_wr(%04x, %02x)\n", addr, val); #endif switch (addr & 0x000f) { @@ -485,7 +508,7 @@ jim_write(uint16_t addr, uint8_t val, void *priv) break; default: - pclog("EuroPC: invalid JIM write %02x, val %02x\n", addr, val); + europc_log("EuroPC: invalid JIM write %02x, val %02x\n", addr, val); break; } } @@ -532,12 +555,12 @@ jim_read(uint16_t addr, void *priv) break; default: - pclog("EuroPC: invalid JIM read %02x\n", addr); + europc_log("EuroPC: invalid JIM read %02x\n", addr); break; } #if EUROPC_DEBUG > 1 - pclog("EuroPC: jim_rd(%04x): %02x\n", addr, r); + europc_log("EuroPC: jim_rd(%04x): %02x\n", addr, r); #endif return(r); @@ -552,10 +575,10 @@ europc_boot(const device_t *info) uint8_t b; #if EUROPC_DEBUG - pclog("EuroPC: booting mainboard..\n"); + europc_log("EuroPC: booting mainboard..\n"); #endif - pclog("EuroPC: NVR=[ %02x %02x %02x %02x %02x ] %sVALID\n", + europc_log("EuroPC: NVR=[ %02x %02x %02x %02x %02x ] %sVALID\n", sys->nvr.regs[MRTC_CONF_A], sys->nvr.regs[MRTC_CONF_B], sys->nvr.regs[MRTC_CONF_C], sys->nvr.regs[MRTC_CONF_D], sys->nvr.regs[MRTC_CONF_E], @@ -652,13 +675,16 @@ europc_boot(const device_t *info) /* Only after JIM has been initialized. */ (void)device_add(&keyboard_xt_device); - /* + /* Enable and set up the FDC. */ + (void)device_add(&fdc_xt_device); + + /* * Set up and enable the HD20 disk controller. * * We only do this if we have not configured another one. */ if (hdc_current == 1) - (void)device_add(&europc_hdc_device); + (void)device_add(&xta_hd20_device); return(sys); } @@ -699,7 +725,7 @@ const device_t europc_device = { "EuroPC System Board", 0, 0, europc_boot, europc_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, europc_config }; @@ -715,12 +741,13 @@ const device_t europc_device = { void machine_europc_init(const machine_t *model) { + machine_common_init(model); + nmi_init(); + /* Clear the machine state. */ memset(&europc, 0x00, sizeof(europc_t)); europc.jim = 0x0250; - machine_common_init(model); - nmi_init(); mem_add_bios(); /* This is machine specific. */ @@ -730,14 +757,11 @@ machine_europc_init(const machine_t *model) /* Set up any local handlers here. */ europc.nvr.reset = rtc_reset; europc.nvr.start = rtc_start; - europc.nvr.tick = rtc_tick; + europc.nvr.tick = europc_rtc_tick; /* Initialize the actual NVR. */ nvr_init(&europc.nvr); - /* Enable and set up the FDC. */ - (void)device_add(&fdc_xt_device); - /* Enable and set up the mainboard device. */ device_add(&europc_device); } diff --git a/src/machine/m_europc_hdc.c b/src/machine/m_europc_hdc.c deleted file mode 100644 index 315f0f85c..000000000 --- a/src/machine/m_europc_hdc.c +++ /dev/null @@ -1,987 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Implementation of the EuroPC HD20 internal controller. - * - * The HD20 was an externally-connected drive, very often a - * 8425XT (20MB, 615/4/17) from Miniscribe. These drives used - * an 8-bit version of IDE called X-IDE, also known as XTA. - * Some older units had a 8225XT drive (20MB, 771/2/17.) - * - * To access the HD disk formatter, enter the "debug" program - * in DOS, and type "g=f000:a000" to start that utility, which - * is hidden in the PC's ROM BIOS. - * - * This driver is based on the information found in the IBM-PC - * Technical Reference manual, pp 187 and on. - * - * Based on the original "xebec.c" from Sarah Walker. - * - * Version: @(#)m_europc_hdc.c 1.0.3 2018/03/18 - * - * Authors: Fred N. van Kempen, - * Sarah Walker, - * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2008-2017 Sarah Walker. - * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#define __USE_LARGEFILE64 -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE -#include -#include -#include -#include -#include -#include "../86box.h" -#include "../io.h" -#include "../dma.h" -#include "../pic.h" -#include "../device.h" -#include "../timer.h" -#include "../disk/hdc.h" -#include "../disk/hdd.h" -#include "../plat.h" -#include "../ui.h" -#include "machine.h" - - -#define HDC_DEBUG 0 -#define HDC_NEWPARAMS 1 /* use NEW parameter block */ - -#define HDD_IOADDR 0x0320 -#define HDD_IRQCHAN 5 -#define HDD_DMACHAN 3 - - -#define HDC_TIME (200*TIMER_USEC) - - -enum { - STATE_IDLE, - STATE_CMD, - STATE_RUN, - STATE_RXDTA, - STATE_RDATA, - STATE_TXDTA, - STATE_TDATA, - STATE_COMPL -}; - - -/* Command values. */ -#define CMD_TEST_DRV_RDY 0x00 -#define CMD_RECALIBRATE 0x01 - /* unused 0x02 */ -#define CMD_READ_SENSE 0x03 -#define CMD_FORMAT_DRIVE 0x04 -#define CMD_READY_VERIFY 0x05 -#define CMD_FORMAT_TRACK 0x06 -#define CMD_FORMAT_BAD_TRACK 0x07 -#define CMD_READ_SECTORS 0x08 - /* unused 0x09 */ -#define CMD_WRITE_SECTORS 0x0a -#define CMD_SEEK 0x0b -#define CMD_SET_DRIVE_PARAMS 0x0c -#define CMD_READ_ECC_BURST 0x0d -#define CMD_READ_SECTOR_BUFFER 0x0e -#define CMD_WRITE_SECTOR_BUFFER 0x0f -#define CMD_RAM_DIAGS 0xe0 - /* unused 0xe1 */ - /* unused 0xe2 */ -#define CMD_DRIVE_DIAGS 0xe3 -#define CMD_CTRL_DIAGS 0xe4 -#define CMD_READ_LONG 0xe5 -#define CMD_WRITE_LONG 0xe6 - -/* STATUS register values. */ -#define STAT_REQ 0x01 -#define STAT_IO 0x02 -#define STAT_CD 0x04 -#define STAT_BSY 0x08 -#define STAT_DRQ 0x10 -#define STAT_IRQ 0x20 - -/* Sense Error codes. */ -#define ERR_NOERROR 0x00 /* no error detected */ -#define ERR_NOINDEX 0x01 /* drive did not detect IDX pulse */ -#define ERR_NOSEEK 0x02 /* drive did not complete SEEK */ -#define ERR_WRFAULT 0x03 /* write fault during last cmd */ -#define ERR_NOTRDY 0x04 /* drive did not go READY after cmd */ -#define ERR_NOTRK000 0x06 /* drive did not see TRK0 signal */ -#define ERR_LONGSEEK 0x08 /* long seek in progress */ -#define ERR_IDREAD 0x10 /* ECC error during ID field */ -#define ERR_DATA 0x11 /* uncorrectable ECC err in data */ -#define ERR_NOMARK 0x12 /* no address mark detected */ -#define ERR_NOSECT 0x14 /* sector not found */ -#define ERR_SEEK 0x15 /* seek error */ -#define ERR_ECCDATA 0x18 /* ECC corrected data */ -#define ERR_BADTRK 0x19 /* bad track detected */ -#define ERR_ILLCMD 0x20 /* invalid command received */ -#define ERR_ILLADDR 0x21 /* invalid disk address received */ -#define ERR_BADRAM 0x30 /* bad RAM in sector data buffer */ -#define ERR_BADROM 0x31 /* bad checksum in ROM test */ -#define ERR_BADECC 0x32 /* ECC polynomial generator bad */ - -/* Completion Byte fields. */ -#define COMP_DRIVE 0x20 -#define COMP_ERR 0x02 - -#define IRQ_ENA 0x02 -#define DMA_ENA 0x01 - - -/* The device control block (6 bytes) */ -#pragma pack(push,1) -struct dcb { - uint8_t cmd; /* [7:5] class, [4:0] opcode */ - uint8_t head:5, /* [4:0] head number */ - drvsel:1, /* [5] drive select */ - unused:2; /* [7:6] unused MBZ */ - uint8_t sector:6, /* [5:0] sector number 0-63 */ - cylh:2; /* [7:6] cylinder [9:8] bits */ - uint8_t cyl; /* [7:0] cylinder [7:0] bits */ - uint8_t count; /* [7:0] blk count / interleave */ - uint8_t ctrl; /* [7:0] control field */ -}; -#pragma pack(pop) - -/* - * The (configured) Drive Parameters. - * - * Although the IBM specification calls for a total of 8 bytes - * in the Paramater Block, the EuroPC uses a 16-byte block. It - * looks like it has extended (translated?) information there, - * as well as the actual data we need. - * - * [ 03 ac 04 01 f4 02 67 0b 11 04 67 02 00 00 01 00] - * - * is what was sent for a standard 615/4/17 disk with rdwrcyl - * set to 500, and precomp to 615. - * - * For now, we will just look at the rest of the data. - */ -#pragma pack(push,1) -struct dprm { -#if HDC_NEWPARAMS - uint16_t tracks; /* total number of sectors on drive */ - uint8_t heads; /* number of heads per cylinder */ - uint16_t rwcurrent; /* (MSB) reduced write current cylinder */ - uint16_t wprecomp; /* (MSB) write precompensation cylinder */ - uint8_t maxecc; /* max ECC data burst length */ -#else - uint16_t tracks; /* (MSB) max number of cylinders */ - uint8_t heads; /* number of heads per cylinder */ - uint16_t rwcurrent; /* (MSB) reduced write current cylinder */ - uint16_t wprecomp; /* (MSB) write precompensation cylinder */ - uint8_t maxecc; /* max ECC data burst length */ -#endif -}; - -typedef struct { - uint8_t spt, - hpc; - uint16_t tracks; - - struct dprm params; - uint8_t cfg_spt, - cfg_hpc; - uint16_t cfg_tracks; - - uint16_t cur_cyl; - - int8_t present, - hdd_num; -} drive_t; -#pragma pack(pop) - - -typedef struct { - uint16_t base; - int8_t irq; - int8_t dma; - uint8_t mask; - - int8_t state; - int64_t callback; - - uint8_t sense; /* current SENSE ERROR value */ - uint8_t status; /* current operational status */ - - /* Current operation parameters. */ - int16_t buf_idx, /* command buffer index and pointer */ - buf_len; - uint8_t *buf_ptr; - uint16_t track; /* requested track# */ - uint8_t head, /* requested head# */ - sector, /* requested sector# */ - comp; /* operation completion byte */ - int count; /* requested sector count */ - - struct dcb dcb; /* device control block */ - - drive_t drives[MFM_NUM]; - - uint8_t data[512]; /* data buffer */ - uint8_t sector_buf[512]; -} hd20_t; - - -static void -hd20_intr(hd20_t *dev) -{ - dev->status = STAT_REQ|STAT_CD|STAT_IO|STAT_BSY; - dev->state = STATE_COMPL; - if (dev->mask & IRQ_ENA) { - dev->status |= STAT_IRQ; - picint(1<irq); - } -} - - -static int -get_sector(hd20_t *dev, drive_t *drive, off64_t *addr) -{ - int heads = drive->cfg_hpc; - - if (drive->cur_cyl != dev->track) { - pclog("HD20: get_sector: wrong cylinder %d/%d\n", - drive->cur_cyl, dev->track); - dev->sense = ERR_ILLADDR; - return(1); - } - - if (dev->head > heads) { - pclog("HD20: get_sector: past end of configured heads\n"); - dev->sense = ERR_ILLADDR; - return(1); - } - - if (dev->head > drive->hpc) { - pclog("HD20: get_sector: past end of heads\n"); - dev->sense = ERR_ILLADDR; - return(1); - } - - if (dev->sector >= 17) { - pclog("HD20: get_sector: past end of sectors\n"); - dev->sense = ERR_ILLADDR; - return(1); - } - - *addr = ((((off64_t) dev->track*heads) + dev->head)*17) + dev->sector; - - return(0); -} - - -static void -next_sector(hd20_t *dev, drive_t *drive) -{ - if (++dev->sector >= 17) { - dev->sector = 0; - if (++dev->head >= drive->cfg_hpc) { - dev->head = 0; - dev->track++; - drive->cur_cyl++; - if (drive->cur_cyl >= drive->cfg_tracks) - drive->cur_cyl = drive->cfg_tracks-1; - } - } -} - - -/* Execute the DCB we just received. */ -static void -hd20_callback(void *priv) -{ - hd20_t *dev = (hd20_t *)priv; - struct dcb *dcb = &dev->dcb; - drive_t *drive; - off64_t addr; - int val; - - dev->callback = 0; - - drive = &dev->drives[dcb->drvsel]; - dev->comp = (dcb->drvsel) ? COMP_DRIVE : 0x00; - - switch (dcb->cmd) { - case CMD_TEST_DRV_RDY: -#if HDC_DEBUG - if (dcb->drvsel == 0) - pclog("HD20: test_rdy(%d) ready=%d\n", - dcb->drvsel, drive->present); -#endif - if (! drive->present) { - dev->comp |= COMP_ERR; - dev->sense = ERR_NOTRDY; - } - hd20_intr(dev); - break; - - case CMD_RECALIBRATE: -#if HDC_DEBUG - if (dcb->drvsel == 0) - pclog("HD20: recalibrate(%d) ready=%d\n", - dcb->drvsel, drive->present); -#endif - if (! drive->present) { - dev->comp |= COMP_ERR; - dev->sense = ERR_NOTRDY; - } else { - dev->track = drive->cur_cyl = 0; - } - hd20_intr(dev); - break; - - case CMD_READ_SENSE: - if (dev->state == STATE_RUN) { -#if HDC_DEBUG - if (dcb->drvsel == 0) - pclog("HD20: sense(%d)\n", dcb->drvsel); -#endif - dev->buf_idx = 0; - dev->buf_len = 4; - dev->buf_ptr = dev->data; - dev->data[0] = dev->sense; - dev->data[1] = dcb->drvsel ? 0x20 : 0x00; - dev->data[2] = dev->data[3] = 0x00; - dev->sense = ERR_NOERROR; - dev->status = STAT_BSY|STAT_IO|STAT_REQ; - dev->state = STATE_TXDTA; - } else if (dev->state == STATE_TDATA) { - hd20_intr(dev); - } - break; - - case CMD_READY_VERIFY: - if (dev->state == STATE_RUN) { - /* Seek to cylinder. */ - dev->track = dcb->cyl | (dcb->cylh<<2); - if (dev->track >= drive->cfg_tracks) - drive->cur_cyl = drive->cfg_tracks-1; - else - drive->cur_cyl = dev->track; - dev->head = dcb->head; - dev->sector = dcb->sector; -#if HDC_DEBUG - pclog("HD20: verify_sector(%d) %d,%d,%d\n", - dcb->drvsel, dev->track, dev->head,dev->sector); -#endif - - /* Get sector count; count=0 means 256. */ - dev->count = (int)dcb->count; - if (dev->count == 0) dev->count = 256; - while (dev->count-- > 0) { - if (get_sector(dev, drive, &addr)) { - pclog("HD20: get_sector failed\n"); - dev->comp |= COMP_ERR; - hd20_intr(dev); - return; - } - - next_sector(dev, drive); - } - - hd20_intr(dev); - - ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1); - } - break; - - case CMD_FORMAT_DRIVE: -#if HDC_DEBUG - pclog("HD20: format_drive(%d)\n", dcb->drvsel); -#endif - for (dev->track=0; dev->tracktracks; dev->track++) { - drive->cur_cyl = dev->track; - for (dev->head=0; dev->headhpc; dev->head++) { - dev->sector = 0; - - if (get_sector(dev, drive, &addr)) { - pclog("HD20: get_sector failed\n"); - dev->comp |= COMP_ERR; - hd20_intr(dev); - return; - } - - hdd_image_zero(drive->hdd_num,addr,drive->spt); - - ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1); - } - } - hd20_intr(dev); - break; - - case CMD_FORMAT_TRACK: - /* Seek to cylinder. */ - dev->track = dcb->cyl | (dcb->cylh<<2); - if (dev->track >= drive->cfg_tracks) - drive->cur_cyl = drive->cfg_tracks-1; - else - drive->cur_cyl = dev->track; - dev->head = dcb->head; - dev->sector = 0; -#if HDC_DEBUG - pclog("HD20: format_track(%d) %d,%d\n", - dcb->drvsel, dev->track, dev->head); -#endif - - if (get_sector(dev, drive, &addr)) { - pclog("HD20: get_sector failed\n"); - dev->comp |= COMP_ERR; - hd20_intr(dev); - return; - } - - hdd_image_zero(drive->hdd_num, addr, drive->spt); - - ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1); - - hd20_intr(dev); - break; - - case CMD_READ_SECTORS: - switch (dev->state) { - case STATE_RUN: - /* Seek to cylinder. */ - dev->track = dcb->cyl | (dcb->cylh<<2); - if (dev->track >= drive->cfg_tracks) - drive->cur_cyl = drive->cfg_tracks-1; - else - drive->cur_cyl = dev->track; - dev->head = dcb->head; - dev->sector = dcb->sector; - - /* Get sector count; count=0 means 256. */ - dev->count = (int)dcb->count; - if (dev->count == 0) dev->count = 256; -#if HDC_DEBUG - pclog("HD20: read_sector(%d) %d,%d,%d cnt=%d\n", - dcb->drvsel, dev->track, dev->head, - dev->sector, dev->count); -#endif - - if (get_sector(dev, drive, &addr)) { - dev->comp |= COMP_ERR; - hd20_intr(dev); - return; - } - - hdd_image_read(drive->hdd_num, addr, 1, - (uint8_t *)dev->sector_buf); - ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1); - - /* Ready to transfer the data out. */ - dev->buf_idx = 0; - dev->buf_len = 512; - dev->state = STATE_TXDTA; - - if (! (dev->mask & DMA_ENA)) { - memcpy(dev->data, dev->sector_buf, 512); - dev->buf_ptr = dev->data; - dev->status = STAT_BSY|STAT_IO|STAT_REQ; - } else { - dev->callback = HDC_TIME; - dev->buf_ptr = dev->sector_buf; - } - break; - - case STATE_TXDTA: - dev->status = STAT_BSY; - while (dev->buf_idx < dev->buf_len) { - val = dma_channel_write(dev->dma, - *dev->buf_ptr++); - if (val == DMA_NODATA) { - pclog("CMD_READ_SECTORS out of data!\n"); - dev->status = STAT_BSY|STAT_CD|STAT_IO|STAT_REQ; - dev->callback = HDC_TIME; - return; - } - dev->buf_idx++; - } - dev->state = STATE_TDATA; - dev->callback = HDC_TIME; - break; - - case STATE_TDATA: - next_sector(dev, drive); - - dev->buf_idx = 0; - if (--dev->count == 0) { - ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0); - hd20_intr(dev); - return; - } - - if (get_sector(dev, drive, &addr)) { - dev->comp |= COMP_ERR; - hd20_intr(dev); - return; - } - - hdd_image_read(drive->hdd_num, addr, 1, - (uint8_t *)dev->sector_buf); - ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1); - - dev->state = STATE_TXDTA; - - if (! (dev->mask & DMA_ENA)) { - memcpy(dev->data, dev->sector_buf, 512); - dev->buf_ptr = dev->data; - dev->status = STAT_BSY|STAT_IO|STAT_REQ; - } else { - dev->buf_ptr = dev->sector_buf; - dev->callback = HDC_TIME; - } - break; - } - break; - - case CMD_WRITE_SECTORS: - switch (dev->state) { - case STATE_RUN: - /* Seek to cylinder. */ - dev->track = dcb->cyl | (dcb->cylh<<2); - if (dev->track >= drive->cfg_tracks) - drive->cur_cyl = drive->cfg_tracks-1; - else - drive->cur_cyl = dev->track; - dev->head = dcb->head; - dev->sector = dcb->sector; - - /* Get sector count; count=0 means 256. */ - dev->count = (int)dev->dcb.count; - if (dev->count == 0) dev->count = 256; -#if HDC_DEBUG - pclog("HD20: write_sector(%d) %d,%d,%d cnt=%d\n", - dcb->drvsel, dev->track, dev->head, - dev->sector, dev->count); -#endif - dev->buf_idx = 0; - dev->buf_len = 512; - dev->state = STATE_RXDTA; - if (! (dev->mask & DMA_ENA)) { - dev->buf_ptr = dev->data; - dev->status = STAT_BSY|STAT_REQ; - } else { - dev->buf_ptr = dev->sector_buf; - dev->callback = HDC_TIME; - } - break; - - case STATE_RXDTA: - dev->status = STAT_BSY; - while (dev->buf_idx < dev->buf_len) { - val = dma_channel_read(dev->dma); - if (val == DMA_NODATA) { - pclog("CMD_WRITE_SECTORS out of data!\n"); - dev->status = STAT_BSY|STAT_CD|STAT_IO|STAT_REQ; - dev->callback = HDC_TIME; - return; - } - - *dev->buf_ptr++ = (val & 0xff); - dev->buf_idx++; - } - dev->state = STATE_RDATA; - dev->callback = HDC_TIME; - break; - - case STATE_RDATA: -#if 0 -/* If I enable this, we get data corruption.. ??? -FvK */ - if (! (dev->mask & DMA_ENA)) - memcpy(dev->sector_buf, dev->data, 512); -#endif - - if (get_sector(dev, drive, &addr)) { - dev->comp |= COMP_ERR; - hd20_intr(dev); - - return; - } - - hdd_image_write(drive->hdd_num, addr, 1, - (uint8_t *)dev->sector_buf); - ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1); - - next_sector(dev, drive); - - dev->buf_idx = 0; - if (--dev->count == 0) { - ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0); - hd20_intr(dev); - break; - } - - dev->state = STATE_RXDTA; - if (! (dev->mask & DMA_ENA)) { - dev->buf_ptr = dev->data; - dev->status = STAT_BSY|STAT_REQ; - } else { - dev->buf_ptr = dev->sector_buf; - dev->callback = HDC_TIME; - } - } - break; - - case CMD_SEEK: - if (! drive->present) { - dev->comp |= COMP_ERR; - dev->sense = ERR_NOTRDY; - hd20_intr(dev); - break; - } - - /* Seek to cylinder. */ - val = dcb->cyl | (dcb->cylh<<2); - if (val >= drive->cfg_tracks) - drive->cur_cyl = drive->cfg_tracks-1; - else - drive->cur_cyl = val; -#if HDC_DEBUG - pclog("HD20: seek(%d) %d/%d\n", - dcb->drvsel, val, drive->cur_cyl); -#endif - - if (val != drive->cur_cyl) { - dev->comp |= COMP_ERR; - dev->sense = ERR_SEEK; - } - hd20_intr(dev); - break; - - case CMD_SET_DRIVE_PARAMS: - if (dev->state == STATE_RUN) { - dev->state = STATE_RXDTA; - dev->buf_idx = 0; - dev->buf_len = sizeof(struct dprm); - dev->buf_ptr = (uint8_t *)&drive->params; - dev->status = STAT_BSY|STAT_REQ; - } else { -dev->buf_ptr=(uint8_t *)&drive->params; -pclog("HD20: PARAMS=["); -for(val=0;val<8;val++)pclog(" %02x",*dev->buf_ptr++); -pclog(" ]\n"); -#if 0 - drive->cfg_tracks = drive->params.tracks; - drive->cfg_hpc = drive->params.heads; - drive->cfg_spt = drive->spt; -#endif -#if HDC_DEBUG - pclog("HD20: set_params(%d) cyl=%d,hd=%d,spt=%d\n", - dcb->drvsel, drive->cfg_tracks, - drive->cfg_hpc, drive->cfg_spt); -#endif - hd20_intr(dev); - } - break; - - case CMD_WRITE_SECTOR_BUFFER: - switch (dev->state) { - case STATE_RUN: -#if HDC_DEBUG - pclog("HD20: write_sector_buffer(%d)\n", - dcb->drvsel); -#endif - dev->buf_idx = 0; - dev->buf_len = 512; - dev->state = STATE_RXDTA; - if (! (dev->mask & DMA_ENA)) { - dev->buf_ptr = dev->data; - dev->status = STAT_BSY|STAT_REQ; - } else { - dev->buf_ptr = dev->sector_buf; - dev->callback = HDC_TIME; - } - break; - - case STATE_RXDTA: - dev->status = STAT_BSY; - if (! (dev->mask & DMA_ENA)) break; - - while (dev->buf_idx++ < dev->buf_len) { - val = dma_channel_read(dev->dma); - if (val == DMA_NODATA) { - pclog("CMD_WRITE_SECTORS out of data!\n"); - dev->status = STAT_BSY|STAT_CD|STAT_IO|STAT_REQ; - dev->callback = HDC_TIME; - return; - } - - *dev->buf_ptr++ = (val & 0xff); - } - dev->state = STATE_RDATA; - dev->callback = HDC_TIME; - break; - - case STATE_RDATA: - if (! (dev->mask & DMA_ENA)) - memcpy(dev->sector_buf, dev->data, 512); - - hd20_intr(dev); - break; - } - break; - - case CMD_RAM_DIAGS: -#if HDC_DEBUG - pclog("HD20: ram_diags\n"); -#endif - dev->callback = 5*HDC_TIME; - hd20_intr(dev); - break; - - case CMD_DRIVE_DIAGS: -#if HDC_DEBUG - pclog("HD20: drive_diags(%d)\n", dcb->drvsel); -#endif - dev->callback = 5*HDC_TIME; - hd20_intr(dev); - break; - - case CMD_CTRL_DIAGS: -#if HDC_DEBUG - pclog("HD20: ctrl_diags\n"); -#endif - dev->callback = 5*HDC_TIME; - hd20_intr(dev); - break; - - default: - pclog("HD20: unknown command - %02x\n", dcb->cmd); - dev->comp |= COMP_ERR; - dev->sense = ERR_ILLCMD; - hd20_intr(dev); - } -} - - -/* Read one of the HD controller registers. */ -static uint8_t -hd20_read(uint16_t port, void *priv) -{ - hd20_t *dev = (hd20_t *)priv; - uint8_t ret = 0xff; - - switch (port-dev->base) { - case 0: /* read data */ - dev->status &= ~STAT_IRQ; - - if (dev->state == STATE_TXDTA) { - if ((dev->status & 0x0f) != - (STAT_IO|STAT_REQ|STAT_BSY)) - fatal("Read data STATE_COMPLETION_BYTE, status=%02x\n", dev->status); - if (dev->buf_idx > dev->buf_len) { - pclog("HD20: read with empty buffer!\n"); - dev->comp |= COMP_ERR; - dev->sense = ERR_ILLCMD; - break; - } - - ret = dev->data[dev->buf_idx++]; - if (dev->buf_idx == dev->buf_len) { - dev->status = STAT_BSY; - dev->state = STATE_TDATA; - dev->callback = HDC_TIME; - } - } else if (dev->state == STATE_COMPL) { - if ((dev->status & 0x0f) != - (STAT_CD|STAT_IO|STAT_REQ|STAT_BSY)) - fatal("Read data STATE_COMPL, status=%02x\n", dev->status); - ret = dev->comp; - dev->status = 0x00; - dev->state = STATE_IDLE; - } - break; - - case 1: /* read status */ - ret = dev->status; - break; - - case 2: /* read option jumpers */ - ret = 0x00; - break; - } - -#if HDC_DEBUG > 1 - pclog("HD20: read(%04x) = %02x\n", port, ret); -#endif - return(ret); -} - - -static void -hd20_write(uint16_t port, uint8_t val, void *priv) -{ - hd20_t *dev = (hd20_t *)priv; - -#if HDC_DEBUG > 1 - pclog("HD20: write(%04x,%02x)\n", port, val); -#endif - switch (port-dev->base) { - case 0: /* write command/data */ - if (! (dev->status & STAT_REQ)) { - pclog("HD20: not ready for command/data!\n"); - dev->comp |= COMP_ERR; - dev->sense = ERR_ILLCMD; - break; - } - - if (dev->buf_idx >= dev->buf_len) { - pclog("HD20: write with full buffer!\n"); - dev->comp |= COMP_ERR; - dev->sense = ERR_ILLCMD; - break; - } - - /* Store the data into the buffer. */ - *dev->buf_ptr++ = val; - if (++dev->buf_idx == dev->buf_len) { - /* We got all the data we need. */ - dev->status &= ~STAT_REQ; - dev->state = (dev->state==STATE_CMD) ? STATE_RUN : STATE_RDATA; - dev->callback = HDC_TIME; - } - break; - - case 1: /* controller reset */ - dev->sense = 0x00; - /*FALLTHROUGH*/ - - case 2: /* generate controller-select-pulse */ - dev->status = STAT_BSY|STAT_CD|STAT_REQ; - dev->buf_idx = 0; - dev->buf_len = sizeof(struct dcb); - dev->buf_ptr = (uint8_t *)&dev->dcb; - dev->state = STATE_CMD; - break; - - case 3: /* DMA/IRQ mask register */ - dev->mask = val; - break; - } -} - - -static void * -hd20_init(const device_t *info) -{ - drive_t *drive; - hd20_t *dev; - int c, i; - - pclog("EuroPC: initializing HD20 controller.\n"); - - dev = malloc(sizeof(hd20_t)); - memset(dev, 0x00, sizeof(hd20_t)); - dev->base = HDD_IOADDR; - dev->irq = HDD_IRQCHAN; - dev->dma = HDD_DMACHAN; - - for (c=0,i=0; idrives[hdd[i].mfm_channel]; - - if (! hdd_image_load(i)) { - drive->present = 0; - continue; - } - - /* These are the "hardware" parameters (from the image.) */ - drive->spt = hdd[i].spt; - drive->hpc = hdd[i].hpc; - drive->tracks = hdd[i].tracks; - - /* Use them as "configured" parameters until overwritten. */ - drive->cfg_spt = drive->spt; - drive->cfg_hpc = drive->hpc; - drive->cfg_tracks = drive->tracks; - - drive->hdd_num = i; - drive->present = 1; - - pclog("HD20: drive%d (cyl=%d,hd=%d,spt=%d), disk %d\n", - hdd[i].mfm_channel,drive->tracks,drive->hpc,drive->spt,i); - - if (++c > MFM_NUM) break; - } - } - - io_sethandler(dev->base, 4, - hd20_read, NULL, NULL, hd20_write, NULL, NULL, dev); - - timer_add(hd20_callback, &dev->callback, &dev->callback, dev); - - return(dev); -} - - -static void -hd20_close(void *priv) -{ - hd20_t *dev = (hd20_t *)priv; - drive_t *drive; - int d; - - for (d=0; d<2; d++) { - drive = &dev->drives[d]; - - hdd_image_close(drive->hdd_num); - } - - free(dev); -} - - -static int -hd20_available(void) -{ - return(1); -} - - -const device_t europc_hdc_device = { - "EuroPC HD20", - 0, 0, - hd20_init, hd20_close, NULL, - hd20_available, NULL, NULL, NULL, - NULL -}; diff --git a/src/machine/m_olivetti_m24.c b/src/machine/m_olivetti_m24.c index b8128f25b..57a28d7ea 100644 --- a/src/machine/m_olivetti_m24.c +++ b/src/machine/m_olivetti_m24.c @@ -8,7 +8,7 @@ * * Emulation of the Olivetti M24. * - * Version: @(#)m_olivetti_m24.c 1.0.12 2018/03/19 + * Version: @(#)m_olivetti_m24.c 1.0.14 2018/04/26 * * Authors: Sarah Walker, * Miran Grca, @@ -795,7 +795,7 @@ const device_t m24_device = { NULL, vid_close, NULL, NULL, speed_changed, - NULL, NULL, + NULL, NULL }; @@ -849,7 +849,7 @@ machine_olim24_init(const machine_t *model) device_add(&gameport_device); /* FIXME: make sure this is correct?? */ - nvr_at_init(8); + device_add(&at_nvr_device); nmi_init(); } diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index d2167ff70..52979f72e 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -8,7 +8,7 @@ * * Emulation of the IBM PCjr. * - * Version: @(#)m_pcjr.c 1.0.6 2018/03/18 + * Version: @(#)m_pcjr.c 1.0.8 2018/04/29 * * Authors: Sarah Walker, * Miran Grca, @@ -18,12 +18,14 @@ * Copyright 2016-2018 Miran Grca. * Copyright 2017,2018 Fred N. van Kempen. */ -#include +#include #include +#include #include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../io.h" #include "../nmi.h" @@ -603,9 +605,6 @@ kbd_read(uint16_t port, void *priv) pcjr->latched = 0; ret = 0; break; - - default: - pclog("\nBad PCjr keyboard read %04X\n", port); } return(ret); @@ -721,7 +720,6 @@ static const device_t pcjr_device = { NULL, speed_changed, NULL, - NULL, pcjr_config }; diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 9be9cbd2c..46086b9a6 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -28,7 +28,7 @@ * boot. Sometimes, they do, and then it shows an "Incorrect * DOS" error message?? --FvK * - * Version: @(#)m_ps1.c 1.0.7 2018/03/18 + * Version: @(#)m_ps1.c 1.0.9 2018/04/26 * * Authors: Sarah Walker, * Miran Grca, @@ -88,7 +88,8 @@ typedef struct { rom_t high_rom; - uint8_t ps1_92, + uint8_t ps1_91, + ps1_92, ps1_94, ps1_102, ps1_103, @@ -97,11 +98,6 @@ typedef struct { ps1_190; int ps1_e0_addr; uint8_t ps1_e0_regs[256]; - - struct { - uint8_t status, int_status; - uint8_t attention, ctrl; - } hd; } ps1_t; @@ -271,7 +267,6 @@ static const device_t snd_device = { snd_init, snd_close, NULL, NULL, NULL, - NULL, NULL }; @@ -334,7 +329,7 @@ ps1_write(uint16_t port, uint8_t val, void *priv) lpt1_remove(); if (val & 0x04) serial_setup(1, SERIAL1_ADDR, SERIAL1_IRQ); - else + else serial_remove(1); if (val & 0x10) { switch ((val >> 5) & 3) { @@ -367,22 +362,6 @@ ps1_write(uint16_t port, uint8_t val, void *priv) case 0x0190: ps->ps1_190 = val; break; - - case 0x0322: - if (ps->model == 2011) { - ps->hd.ctrl = val; - if (val & 0x80) - ps->hd.status |= 0x02; - } - break; - - case 0x0324: - if (ps->model == 2011) { - ps->hd.attention = val & 0xf0; - if (ps->hd.attention) - ps->hd.status = 0x14; - } - break; } } @@ -395,7 +374,8 @@ ps1_read(uint16_t port, void *priv) switch (port) { case 0x0091: - ret = 0; + ret = ps->ps1_91; + ps->ps1_91 = 0; break; case 0x0092: @@ -438,19 +418,6 @@ ps1_read(uint16_t port, void *priv) ret = ps->ps1_190; break; - case 0x0322: - if (ps->model == 2011) { - ret = ps->hd.status; - } - break; - - case 0x0324: - if (ps->model == 2011) { - ret = ps->hd.int_status; - ps->hd.int_status &= ~0x02; - } - break; - default: break; } @@ -463,6 +430,7 @@ static void ps1_setup(int model) { ps1_t *ps; + void *priv; ps = (ps1_t *)malloc(sizeof(ps1_t)); memset(ps, 0x00, sizeof(ps1_t)); @@ -479,23 +447,15 @@ ps1_setup(int model) io_sethandler(0x0190, 1, ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); + lpt1_remove(); + lpt1_init(0x3bc); + if (model == 2011) { - io_sethandler(0x0320, 1, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); - io_sethandler(0x0322, 1, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); - io_sethandler(0x0324, 1, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); - -#if 0 rom_init(&ps->high_rom, - L"roms/machines/ibmps1es/f80000_shell.bin", + L"roms/machines/ibmps1es/f80000.bin", 0xf80000, 0x80000, 0x7ffff, 0, MEM_MAPPING_EXTERNAL); -#endif - lpt1_remove(); lpt2_remove(); - lpt1_init(0x03bc); serial_remove(1); serial_remove(2); @@ -505,31 +465,44 @@ ps1_setup(int model) device_add(&ps1vga_device); else device_add(&ibm_ps1_2121_device); + + device_add(&snd_device); + + device_add(&fdc_at_actlow_device); + + /* Enable the builtin HDC. */ + if (hdc_current == 1) { + priv = device_add(&ps1_hdc_device); + + ps1_hdc_inform(priv, ps); + } } if (model == 2121) { io_sethandler(0x00e0, 2, ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); -#if 1 +#if 0 rom_init(&ps->high_rom, L"roms/machines/ibmps1_2121/fc0000.bin", 0xfc0000, 0x20000, 0x1ffff, 0, MEM_MAPPING_EXTERNAL); -#else - rom_init(&ps->high_rom, - L"roms/machines/ibmps1_2121/fc0000_shell.bin", - 0xfc0000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL); #endif - lpt1_init(0x03bc); - /* Initialize the video controller. */ if (gfxcard == GFX_INTERNAL) device_add(&ibm_ps1_2121_device); + + device_add(&fdc_at_ps1_device); + + device_add(&ide_isa_device); + + device_add(&snd_device); } if (model == 2133) { - lpt1_init(0x03bc); + device_add(&fdc_at_device); + + device_add(&ide_isa_device); } } @@ -546,29 +519,26 @@ ps1_common_init(const machine_t *model) dma16_init(); pic2_init(); - nvr_at_init(8); - - if (romset != ROM_IBMPS1_2011) - device_add(&ide_isa_device); + device_add(&ps_nvr_device); device_add(&keyboard_ps2_device); - if (romset == ROM_IBMPS1_2133) - device_add(&fdc_at_device); - else { - if ((romset == ROM_IBMPS1_2121) || (romset == ROM_IBMPS1_2121_ISA)) - device_add(&fdc_at_ps1_device); - else - device_add(&fdc_at_actlow_device); - device_add(&snd_device); - } - /* Audio uses ports 200h and 202-207h, so only initialize gameport on 201h. */ if (joystick_type != 7) device_add(&gameport_201_device); } +/* Set the Card Selected Flag */ +void +ps1_set_feedback(void *priv) +{ + ps1_t *ps = (ps1_t *)priv; + + ps->ps1_91 |= 0x01; +} + + void machine_ps1_m2011_init(const machine_t *model) { diff --git a/src/machine/m_ps1_hdc.c b/src/machine/m_ps1_hdc.c new file mode 100644 index 000000000..096e720b6 --- /dev/null +++ b/src/machine/m_ps1_hdc.c @@ -0,0 +1,1364 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the PS/1 Model 2011 disk controller. + * + * XTA is the acronym for 'XT-Attached', which was basically + * the XT-counterpart to what we know now as IDE (which is + * also named ATA - AT Attachment.) The basic ideas was to + * put the actual drive controller electronics onto the drive + * itself, and have the host machine just talk to that using + * a simpe, standardized I/O path- hence the name IDE, for + * Integrated Drive Electronics. + * + * In the ATA version of IDE, the programming interface of + * the IBM PC/AT (which used the Western Digitial 1002/1003 + * controllers) was kept, and, so, ATA-IDE assumes a 16bit + * data path: it reads and writes 16bit words of data. The + * disk drives for this bus commonly have an 'A' suffix to + * identify them as 'ATBUS'. + * + * In XTA-IDE, which is slightly older, the programming + * interface of the IBM PC/XT (which used the MFM controller + * from Xebec) was kept, and, so, it uses an 8bit data path. + * Disk drives for this bus commonly have the 'X' suffix to + * mark them as being for this XTBUS variant. + * + * So, XTA and ATA try to do the same thing, but they use + * different ways to achive their goal. + * + * Also, XTA is **not** the same as XTIDE. XTIDE is a modern + * variant of ATA-IDE, but retro-fitted for use on 8bit XT + * systems: an extra register is used to deal with the extra + * data byte per transfer. XTIDE uses regular IDE drives, + * and uses the regular ATA/IDE programming interface, just + * with the extra register. + * + * NOTE: We should probably find a nicer way to integrate our Disk + * Type table with the main code, so the user can only select + * items from that list... + * + * Version: @(#)m_ps1_hdc.c 1.0.6 2018/04/29 + * + * Author: Fred N. van Kempen, + * + * Based on my earlier HD20 driver for the EuroPC. + * Thanks to Marco Bortolin for the help and feedback !! + * + * Copyright 2017,2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#define __USE_LARGEFILE64 +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include "../86box.h" +#include "../io.h" +#include "../dma.h" +#include "../pic.h" +#include "../device.h" +#include "../timer.h" +#include "../disk/hdc.h" +#include "../disk/hdd.h" +#include "../plat.h" +#include "../ui.h" +#include "machine.h" + + +#define HDC_TIME (200*TIMER_USEC) +#define HDC_TYPE_USER 47 /* user drive type */ + + +enum { + STATE_IDLE = 0, + STATE_RECV, + STATE_RDATA, + STATE_RDONE, + STATE_SEND, + STATE_SDATA, + STATE_SDONE, + STATE_FINIT, + STATE_FDONE +}; + + +/* Command values. These deviate from the XTA ones. */ +#define CMD_READ_SECTORS 0x01 /* regular read-date */ +#define CMD_READ_VERIFY 0x02 /* read for verify, no data */ +#define CMD_READ_EXT 0x03 /* read extended (ecc) */ +#define CMD_READ_ID 0x05 /* read ID mark on cyl */ +#define CMD_RECALIBRATE 0x08 /* recalibrate to track0 */ +#define CMD_WRITE_SECTORS 0x09 /* regular write-data */ +#define CMD_WRITE_VERIFY 0x0a /* write-data with verify */ +#define CMD_WRITE_EXT 0x0b /* write extended (ecc) */ +#define CMD_FORMAT_DRIVE 0x0d /* format entire disk */ +#define CMD_SEEK 0x0e /* seek */ +#define CMD_FORMAT_TRACK 0x0f /* format one track */ + +/* Attachment Status register (reg 2R) values (IBM PS/1 2011.) */ +#define ASR_TX_EN 0x01 /* transfer enable */ +#define ASR_INT_REQ 0x02 /* interrupt request */ +#define ASR_BUSY 0x04 /* busy */ +#define ASR_DIR 0x08 /* direction */ +#define ASR_DATA_REQ 0x10 /* data request */ + +/* Attachment Control register (2W) values (IBM PS/1 2011.) */ +#define ACR_DMA_EN 0x01 /* DMA enable */ +#define ACR_INT_EN 0x02 /* interrupt enable */ +#define ACR_RESET 0x80 /* reset */ + +/* Interrupt Status register (4R) values (IBM PS/1 2011.) */ +#define ISR_EQUIP_CHECK 0x01 /* internal hardware error */ +#define ISR_ERP_INVOKED 0x02 /* error recovery invoked */ +#define ISR_CMD_REJECT 0x20 /* command reject */ +#define ISR_INVALID_CMD 0x40 /* invalid command */ +#define ISR_TERMINATION 0x80 /* termination error */ + +/* Attention register (4W) values (IBM PS/1 2011.) */ +#define ATT_DATA 0x10 /* data request */ +#define ATT_SSB 0x20 /* sense summary block */ +#define ATT_CSB 0x40 /* command specify block */ +#define ATT_CCB 0x80 /* command control block */ + + +/* + * Define the Sense Summary Block. + * + * The sense summary block contains the current status of the + * drive. The information in the summary block is updated after + * each command is completed, after an error, or before the + * block is transferred. + */ +#pragma pack(push,1) +typedef struct { + /* Status byte 0. */ + uint8_t track_0 :1, /* T0 */ + mbz1 :1, /* 0 */ + mbz2 :1, /* 0 */ + cylinder_err :1, /* CE */ + write_fault :1, /* WF */ + mbz3 :1, /* 0 */ + seek_end :1, /* SE */ + not_ready :1; /* NR */ + + /* Status byte 1. */ + uint8_t id_not_found :1, /* ID */ + mbz4 :1, /* 0 */ + mbz5 :1, /* 0 */ + wrong_cyl :1, /* WC */ + all_bit_set :1, /* BT */ + mark_not_found :1, /* AM */ + ecc_crc_err :1, /* ET */ + ecc_crc_field :1; /* EF */ + + /* Status byte 2. */ + uint8_t headsel_state :4, /* headsel state[4] */ + defective_sector:1, /* DS */ + retried_ok :1, /* RG */ + need_reset :1, /* RR */ +#if 1 + valid :1; /* 0 (abused as VALID) */ +#else + mbz6 :1; /* 0 */ +#endif + + /* Most recent ID field seen. */ + uint8_t last_cyl_low; /* Cyl_Low[8] */ + uint8_t last_head :4, /* HD[4] */ + mbz7 :1, /* 0 */ + last_cyl_high :2, /* Cyl_high[2] */ + last_def_sect :1; /* DS */ + uint8_t last_sect; /* Sect[8] */ + + uint8_t sect_size; /* Size[8] = 02 */ + + /* Current position. */ + uint8_t curr_cyl_high :2, /* Cyl_High_[2] */ + mbz8 :1, /* 0 */ + mbz9 :1, /* 0 */ + curr_head :4; /* HD_2[4] */ + uint8_t curr_cyl_low; /* Cyl_Low_2[8] */ + + uint8_t sect_corr; /* sectors corrected */ + + uint8_t retries; /* retries */ + + /* + * This byte shows the progress of the controller through the + * last command. It allows the system to monitor the controller + * and determine if a reset is needed. When the transfer of the + * control block is started, the value is set to hex 00. The + * progress indicated by this byte is: + * + * 1. Set to hex 01 after the control block is successfully + * transferred. + * + * 2. Set to hex 02 when the command is valid and the drive + * is ready. + * + * 3. Set to hex 03 when the head is in the correct track. + * The most-significant four bits (high nibble) are then + * used to indicate the successful stages of the data + * transfer: + * + * Bit 7 A sector was transferred between the system + * and the sector buffer. + * + * Bit 6 A sector was transferred between the controller + * and the sector buffer. + * + * Bit 5 An error was detected and error recovery + * procedures have been started. + * + * Bit 4 The controller has completed the operation + * and is now not busy. + * + * 4. When the transfer is complete, the low nibble equals hex 4 + * and the high nibble is unchanged. + */ + uint8_t cmd_syndrome; /* command syndrome */ + + uint8_t drive_type; /* drive type */ + + uint8_t rsvd; /* reserved byte */ +} ssb_t; +#pragma pack(pop) + +/* + * Define the Format Control Block. + * + * The format control block (FCB) specifies the ID data used + * in formatting the track. It is used by the Format Track + * and Format Disk commands and contains five bytes for each + * sector formatted on that track. + * + * When the Format Disk command is used, the control block + * contains the sector information of all sectors for head 0, + * cylinder 0. The drive will use the same block to format + * the rest of the disk and automatically increment the head + * number and cylinder number for the remaining tracks. The + * sector numbers, sector size, and the fill byte will be + * the same for each track. + * + * The drive formats the sector IDs on the disk in the same + * order as they are specified in the control block. + * Therefore, sector interleaving is accomplished by filling + * in the control block with the desired interleave. + * + * For example, when formatting 17 sectors per track with an + * interleave of 2, the control block has the first 5 bytes + * with a sector number of 1, the second with a sector number + * of 10, the third with a sector number of 2, and continuing + * until all 17 sectors for that track are defined. + * + * The format for the format control block is described in + * the following. The five bytes are repeated for each + * sector on the track. The control block must contain an + * even number of bytes. If an odd number of sectors are + * being formatted, an additional byte is sent with all + * bits 0. + */ +#pragma pack(push,1) +typedef struct { + uint8_t cyl_high :2, /* cylinder [9:8] bits */ + defective_sector:1, /* DS */ + mbz1 :1, /* 0 */ + head :4; /* head number */ + + uint8_t cyl_low; /* cylinder [7:0] bits */ + + uint8_t sector; /* sector number */ + + uint8_t mbz2 :1, /* 0 */ + mbo :1, /* 1 */ + mbz3 :6; /* 000000 */ + + uint8_t fill; /* filler byte */ +} fcb_t; +#pragma pack(pop) + +/* + * Define the Command Control Block. + * + * The system specifies the operation by sending the 6-byte + * command control block to the controller. It can be sent + * through a DMA or PIO operation. + */ +#pragma pack(push,1) +typedef struct { + uint8_t ec_p :1, /* EC/P (ecc/park) */ + mbz1 :1, /* 0 */ + auto_seek :1, /* AS (auto-seek) */ + no_data :1, /* ND (no data) */ + cmd :4; /* command code[4] */ + + uint8_t cyl_high :2, /* cylinder [9:8] bits */ + mbz2 :2, /* 00 */ + head :4; /* head number */ + + uint8_t cyl_low; /* cylinder [7:0] bits */ + + uint8_t sector; /* sector number */ + + uint8_t mbz3 :1, /* 0 */ + mbo1 :1, /* 1 */ + mbz4 :6; /* 000000 */ + + uint8_t count; /* blk count/interleave */ +} ccb_t; +#pragma pack(pop) + +/* Define the hard drive geometry table. */ +typedef struct { + uint16_t cyl; + uint8_t hpc; + uint8_t spt; + int16_t wpc; + int16_t lz; +} geom_t; + +/* Define an attached drive. */ +typedef struct { + int8_t id, /* drive ID on bus */ + present, /* drive is present */ + hdd_num, /* index to global disk table */ + type; /* drive type ID */ + + uint16_t cur_cyl; /* last known position of heads */ + + uint8_t spt, /* active drive parameters */ + hpc; + uint16_t tracks; + + uint8_t cfg_spt, /* configured drive parameters */ + cfg_hpc; + uint16_t cfg_tracks; +} drive_t; + + +typedef struct { + uint16_t base; /* controller base I/O address */ + int8_t irq; /* controller IRQ channel */ + int8_t dma; /* controller DMA channel */ + + /* Registers. */ + uint8_t attn, /* ATTENTION register */ + ctrl, /* Control register (ACR) */ + status, /* Status register (ASR) */ + intstat; /* Interrupt Status register (ISR) */ + + void *sys; /* handle to system board */ + + /* Controller state. */ + int64_t callback; + int8_t state, /* controller state */ + reset; /* reset state counter */ + + /* Data transfer. */ + int16_t buf_idx, /* buffer index and pointer */ + buf_len; + uint8_t *buf_ptr; + + /* Current operation parameters. */ + ssb_t ssb; /* sense block */ + ccb_t ccb; /* command control block */ + uint16_t track; /* requested track# */ + uint8_t head, /* requested head# */ + sector; /* requested sector# */ + int count; /* requested sector count */ + + drive_t drives[XTA_NUM]; /* the attached drive(s) */ + + uint8_t data[512]; /* data buffer */ + uint8_t sector_buf[512]; /* sector buffer */ +} hdc_t; + + +/* + * IBM hard drive types 1-44. + * + * We need these to translate the selected disk's + * geometry back to a valid type through the SSB. + * + * Cyl. Head Sect. Write Land + * p-comp Zone + */ +static const geom_t ibm_type_table[] = { + { 0, 0, 0, 0, 0 }, /* 0 (none) */ + { 306, 4, 17, 128, 305 }, /* 1 10 MB */ + { 615, 4, 17, 300, 615 }, /* 2 20 MB */ + { 615, 6, 17, 300, 615 }, /* 3 31 MB */ + { 940, 8, 17, 512, 940 }, /* 4 62 MB */ + { 940, 6, 17, 512, 940 }, /* 5 47 MB */ + { 615, 4, 17, -1, 615 }, /* 6 20 MB */ + { 462, 8, 17, 256, 511 }, /* 7 31 MB */ + { 733, 5, 17, -1, 733 }, /* 8 30 MB */ + { 900, 15, 17, -1, 901 }, /* 9 112 MB */ + { 820, 3, 17, -1, 820 }, /* 10 20 MB */ + { 855, 5, 17, -1, 855 }, /* 11 35 MB */ + { 855, 7, 17, -1, 855 }, /* 12 50 MB */ + { 306, 8, 17, 128, 319 }, /* 13 20 MB */ + { 733, 7, 17, -1, 733 }, /* 14 43 MB */ + { 0, 0, 0, 0, 0 }, /* 15 (rsvd) */ + { 612, 4, 17, 0, 663 }, /* 16 20 MB */ + { 977, 5, 17, 300, 977 }, /* 17 41 MB */ + { 977, 7, 17, -1, 977 }, /* 18 57 MB */ + { 1024, 7, 17, 512, 1023 }, /* 19 59 MB */ + { 733, 5, 17, 300, 732 }, /* 20 30 MB */ + { 733, 7, 17, 300, 732 }, /* 21 43 MB */ + { 733, 5, 17, 300, 733 }, /* 22 30 MB */ + { 306, 4, 17, 0, 336 }, /* 23 10 MB */ + { 612, 4, 17, 305, 663 }, /* 24 20 MB */ + { 306, 4, 17, -1, 340 }, /* 25 10 MB */ + { 612, 4, 17, -1, 670 }, /* 26 20 MB */ + { 698, 7, 17, 300, 732 }, /* 27 41 MB */ + { 976, 5, 17, 488, 977 }, /* 28 40 MB */ + { 306, 4, 17, 0, 340 }, /* 29 10 MB */ + { 611, 4, 17, 306, 663 }, /* 30 20 MB */ + { 732, 7, 17, 300, 732 }, /* 31 43 MB */ + { 1023, 5, 17, -1, 1023 }, /* 32 42 MB */ + { 614, 4, 25, -1, 663 }, /* 33 30 MB */ + { 775, 2, 27, -1, 900 }, /* 34 20 MB */ + { 921, 2, 33, -1, 1000 }, /* 35 30 MB * */ + { 402, 4, 26, -1, 460 }, /* 36 20 MB */ + { 580, 6, 26, -1, 640 }, /* 37 44 MB */ + { 845, 2, 36, -1, 1023 }, /* 38 30 MB * */ + { 769, 3, 36, -1, 1023 }, /* 39 41 MB * */ + { 531, 4, 39, -1, 532 }, /* 40 40 MB */ + { 577, 2, 36, -1, 1023 }, /* 41 20 MB */ + { 654, 2, 32, -1, 674 }, /* 42 20 MB */ + { 923, 5, 36, -1, 1023 }, /* 43 81 MB */ + { 531, 8, 39, -1, 532 } /* 44 81 MB */ +}; + + +#ifdef ENABLE_PS1_HDC_LOG +int ps1_hdc_do_log = ENABLE_PS1_HDC_LOG; +#endif + + +static void +ps1_hdc_log(const char *fmt, ...) +{ +#ifdef ENABLE_PS1_HDC_LOG + va_list ap; + + if (ps1_hdc_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + +/* FIXME: we should use the disk/hdd_table.c code with custom tables! */ +static int +ibm_drive_type(drive_t *drive) +{ + const geom_t *ptr; + int i; + + for (i = 0; i < (sizeof(ibm_type_table) / sizeof(geom_t)); i++) { + ptr = &ibm_type_table[i]; + if ((drive->tracks == ptr->cyl) && + (drive->hpc == ptr->hpc) && (drive->spt == ptr->spt)) return(i); + } + + return(HDC_TYPE_USER); +} + + +static void +set_intr(hdc_t *dev, int raise) +{ + if (raise) { + dev->status |= ASR_INT_REQ; + if (dev->ctrl & ACR_INT_EN) + picint(1 << dev->irq); + } else { + dev->status &= ~ASR_INT_REQ; + picintc(1 << dev->irq); + } +} + + +/* Get the logical (block) address of a CHS triplet. */ +static int +get_sector(hdc_t *dev, drive_t *drive, off64_t *addr) +{ + if (drive->cur_cyl != dev->track) { + ps1_hdc_log("HDC: get_sector: wrong cylinder %d/%d\n", + drive->cur_cyl, dev->track); + dev->ssb.wrong_cyl = 1; + return(1); + } + + if (dev->head >= drive->hpc) { + ps1_hdc_log("HDC: get_sector: past end of heads\n"); + dev->ssb.cylinder_err = 1; + return(1); + } + + if (dev->sector > drive->spt) { + ps1_hdc_log("HDC: get_sector: past end of sectors\n"); + dev->ssb.mark_not_found = 1; + return(1); + } + + /* Calculate logical address (block number) of desired sector. */ + *addr = ((((off64_t) dev->track*drive->hpc) + \ + dev->head)*drive->spt) + dev->sector - 1; + + return(0); +} + + +static void +next_sector(hdc_t *dev, drive_t *drive) +{ + if (++dev->sector > drive->spt) { + dev->sector = 1; + if (++dev->head >= drive->hpc) { + dev->head = 0; + dev->track++; + if (++drive->cur_cyl >= drive->tracks) { + drive->cur_cyl = drive->tracks-1; + dev->ssb.cylinder_err = 1; + } + } + } +} + + +/* Finish up. Repeated all over, so a function it is now. */ +static void +do_finish(hdc_t *dev) +{ + dev->state = STATE_IDLE; + + dev->attn &= ~(ATT_CCB | ATT_DATA); + + dev->status = 0x00; + + set_intr(dev, 1); +} + + +/* Seek to a cylinder. */ +static int +do_seek(hdc_t *dev, drive_t *drive, uint16_t cyl) +{ + if (cyl >= drive->tracks) { + dev->ssb.cylinder_err = 1; + return(1); + } + + dev->track = cyl; + drive->cur_cyl = dev->track; + + return(0); +} + + +/* Format a track or an entire drive. */ +static void +do_format(hdc_t *dev, drive_t *drive, ccb_t *ccb) +{ + int start_cyl, end_cyl; + int intr = 0, val; + off64_t addr; +#if 0 + fcb_t *fcb; +#endif + + /* Get the parameters from the CCB. */ + if (ccb->cmd == CMD_FORMAT_DRIVE) { + start_cyl = 0; + end_cyl = drive->tracks; + } else { + start_cyl = (ccb->cyl_low | (ccb->cyl_high << 8)); + end_cyl = start_cyl + 1; + } + + switch (dev->state) { + case STATE_IDLE: + /* Ready to transfer the FCB data in. */ + dev->state = STATE_RDATA; + dev->buf_idx = 0; + dev->buf_ptr = dev->data; + dev->buf_len = ccb->count * sizeof(fcb_t); + if (dev->buf_len & 1) + dev->buf_len++; /* must be even */ + + /* Enable for PIO or DMA, as needed. */ +#if NOT_USED + if (dev->ctrl & ACR_DMA_EN) + dev->callback = HDC_TIME; + else +#endif + dev->status |= ASR_DATA_REQ; + break; + + case STATE_RDATA: + /* Perform DMA. */ + while (dev->buf_idx < dev->buf_len) { + val = dma_channel_read(dev->dma); + if (val == DMA_NODATA) { + dev->intstat |= ISR_EQUIP_CHECK; + dev->ssb.need_reset = 1; + intr = 1; + break; + } + dev->buf_ptr[dev->buf_idx] = (val & 0xff); + dev->buf_idx++; + } + dev->state = STATE_RDONE; + dev->callback = HDC_TIME; + break; + + case STATE_RDONE: + if (! (dev->ctrl & ACR_DMA_EN)) + dev->status &= ~ASR_DATA_REQ; + + /* Point to the FCB we got. */ +#if 0 + fcb = (fcb_t *)dev->data; +#endif + dev->state = STATE_FINIT; + /*FALLTHROUGH*/ + + case STATE_FINIT: +do_fmt: + /* Activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 1); + + /* Seek to cylinder. */ + if (do_seek(dev, drive, start_cyl)) { + intr = 1; + break; + } + dev->head = ccb->head; + dev->sector = 1; + + /* Get address of sector to write. */ + if (get_sector(dev, drive, &addr)) { + intr = 1; + break; + } + + /* + * For now, we don't use the info from + * the FCB, although we should at least + * use it's "filler byte" value... + */ +#if 0 + hdd_image_zero_ex(drive->hdd_num, addr, fcb->fill, drive->spt); +#else + hdd_image_zero(drive->hdd_num, addr, drive->spt); +#endif + + /* Done with this track. */ + dev->state = STATE_FDONE; + /*FALLTHROUGH*/ + + case STATE_FDONE: + /* One more track done. */ + if (++start_cyl == end_cyl) { + intr = 1; + break; + } + + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + + /* This saves us a LOT of code. */ + dev->state = STATE_FINIT; + goto do_fmt; + } + + /* If we errored out, go back idle. */ + if (intr) { + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + + do_finish(dev); + } +} + + +/* Execute the CCB we just received. */ +static void +hdc_callback(void *priv) +{ + hdc_t *dev = (hdc_t *)priv; + ccb_t *ccb = &dev->ccb; + drive_t *drive; + off64_t addr; + int no_data = 0; + int val; + + /* Cancel timer. */ + dev->callback = 0; + + /* Clear the SSB error bits. */ + dev->ssb.track_0 = 0; + dev->ssb.cylinder_err = 0; + dev->ssb.write_fault = 0; + dev->ssb.seek_end = 0; + dev->ssb.not_ready = 0; + dev->ssb.id_not_found = 0; + dev->ssb.wrong_cyl = 0; + dev->ssb.all_bit_set = 0; + dev->ssb.mark_not_found = 0; + dev->ssb.ecc_crc_err = 0; + dev->ssb.ecc_crc_field = 0; + dev->ssb.valid = 1; + + /* We really only support one drive, but ohwell. */ + drive = &dev->drives[0]; + + switch (ccb->cmd) { + case CMD_READ_VERIFY: + no_data = 1; + /*FALLTHROUGH*/ + + case CMD_READ_SECTORS: + if (! drive->present) { + dev->ssb.not_ready = 1; + do_finish(dev); + return; + } + + switch (dev->state) { + case STATE_IDLE: + /* Seek to cylinder if requested. */ + if (ccb->auto_seek) { + if (do_seek(dev, drive, + (ccb->cyl_low|(ccb->cyl_high<<8)))) { + do_finish(dev); + return; + } + } + dev->head = ccb->head; + dev->sector = ccb->sector; + + /* Get sector count and size. */ + dev->count = (int)ccb->count; + dev->buf_len = (128 << dev->ssb.sect_size); + + dev->state = STATE_SEND; + /*FALLTHROUGH*/ + + case STATE_SEND: + /* Activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 1); + +do_send: + /* Get address of sector to load. */ + if (get_sector(dev, drive, &addr)) { + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + do_finish(dev); + return; + } + + /* Read the block from the image. */ + hdd_image_read(drive->hdd_num, addr, 1, + (uint8_t *)dev->sector_buf); + + /* Ready to transfer the data out. */ + dev->state = STATE_SDATA; + dev->buf_idx = 0; + if (no_data) { + /* Delay a bit, no actual transfer. */ + dev->callback = HDC_TIME; + } else { + if (dev->ctrl & ACR_DMA_EN) { + /* DMA enabled. */ + dev->buf_ptr = dev->sector_buf; + dev->callback = HDC_TIME; + } else { + /* No DMA, do PIO. */ + dev->status |= (ASR_DATA_REQ|ASR_DIR); + + /* Copy from sector to data. */ + memcpy(dev->data, + dev->sector_buf, + (128<ssb.sect_size)); + dev->buf_ptr = dev->data; + } + } + break; + + case STATE_SDATA: + if (! no_data) { + /* Perform DMA. */ + while (dev->buf_idx < dev->buf_len) { + val = dma_channel_write(dev->dma, + *dev->buf_ptr++); + if (val == DMA_NODATA) { + ps1_hdc_log("HDC: CMD_READ_SECTORS out of data (idx=%d, len=%d)!\n", dev->buf_idx, dev->buf_len); + + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + + dev->intstat |= ISR_EQUIP_CHECK; + dev->ssb.need_reset = 1; + do_finish(dev); + return; + } + dev->buf_idx++; + } + } + dev->state = STATE_SDONE; + dev->callback = HDC_TIME; + break; + + case STATE_SDONE: + dev->buf_idx = 0; + if (--dev->count == 0) { + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + + if (! (dev->ctrl & ACR_DMA_EN)) + dev->status &= ~(ASR_DATA_REQ|ASR_DIR); + dev->ssb.cmd_syndrome = 0xD4; + do_finish(dev); + return; + } + + /* Addvance to next sector. */ + next_sector(dev, drive); + + /* This saves us a LOT of code. */ + dev->state = STATE_SEND; + goto do_send; + } + break; + + case CMD_READ_EXT: /* READ_EXT */ + case CMD_READ_ID: /* READ_ID */ + if (! drive->present) { + dev->ssb.not_ready = 1; + do_finish(dev); + return; + } + + dev->intstat |= ISR_INVALID_CMD; + do_finish(dev); + break; + + case CMD_RECALIBRATE: /* RECALIBRATE */ + if (drive->present) { + dev->track = drive->cur_cyl = 0; + } else { + dev->ssb.not_ready = 1; + dev->intstat |= ISR_TERMINATION; + } + + do_finish(dev); + break; + + case CMD_WRITE_VERIFY: + no_data = 1; + /*FALLTHROUGH*/ + + case CMD_WRITE_SECTORS: + if (! drive->present) { + dev->ssb.not_ready = 1; + do_finish(dev); + return; + } + + switch (dev->state) { + case STATE_IDLE: + /* Seek to cylinder if requested. */ + if (ccb->auto_seek) { + if (do_seek(dev, drive, + (ccb->cyl_low|(ccb->cyl_high<<8)))) { + do_finish(dev); + return; + } + } + dev->head = ccb->head; + dev->sector = ccb->sector; + + /* Get sector count and size. */ + dev->count = (int)ccb->count; + dev->buf_len = (128 << dev->ssb.sect_size); + + dev->state = STATE_RECV; + /*FALLTHROUGH*/ + + case STATE_RECV: + /* Activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 1); +do_recv: + /* Ready to transfer the data in. */ + dev->state = STATE_RDATA; + dev->buf_idx = 0; + if (no_data) { + /* Delay a bit, no actual transfer. */ + dev->callback = HDC_TIME; + } else { + if (dev->ctrl & ACR_DMA_EN) { + /* DMA enabled. */ + dev->buf_ptr = dev->sector_buf; + dev->callback = HDC_TIME; + } else { + /* No DMA, do PIO. */ + dev->buf_ptr = dev->data; + dev->status |= ASR_DATA_REQ; + } + } + break; + + case STATE_RDATA: + if (! no_data) { + /* Perform DMA. */ + while (dev->buf_idx < dev->buf_len) { + val = dma_channel_read(dev->dma); + if (val == DMA_NODATA) { + ps1_hdc_log("HDC: CMD_WRITE_SECTORS out of data (idx=%d, len=%d)!\n", dev->buf_idx, dev->buf_len); + + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + + dev->intstat |= ISR_EQUIP_CHECK; + dev->ssb.need_reset = 1; + do_finish(dev); + return; + } + dev->buf_ptr[dev->buf_idx] = (val & 0xff); + dev->buf_idx++; + } + } + dev->state = STATE_RDONE; + dev->callback = HDC_TIME; + break; + + case STATE_RDONE: + /* Copy from data to sector if PIO. */ + if (! (dev->ctrl & ACR_DMA_EN)) + memcpy(dev->sector_buf, dev->data, + (128<ssb.sect_size)); + + /* Get address of sector to write. */ + if (get_sector(dev, drive, &addr)) { + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + + do_finish(dev); + return; + } + + /* Write the block to the image. */ + hdd_image_write(drive->hdd_num, addr, 1, + (uint8_t *)dev->sector_buf); + + dev->buf_idx = 0; + if (--dev->count == 0) { + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_XTA, 0); + + if (! (dev->ctrl & ACR_DMA_EN)) + dev->status &= ~ASR_DATA_REQ; + dev->ssb.cmd_syndrome = 0xD4; + do_finish(dev); + return; + } + + /* Advance to next sector. */ + next_sector(dev, drive); + + /* This saves us a LOT of code. */ + dev->state = STATE_RECV; + goto do_recv; + } + break; + + case CMD_FORMAT_DRIVE: + case CMD_FORMAT_TRACK: + do_format(dev, drive, ccb); + break; + + case CMD_SEEK: + if (! drive->present) { + dev->ssb.not_ready = 1; + do_finish(dev); + return; + } + + if (ccb->ec_p == 1) { + /* Park the heads. */ + val = do_seek(dev, drive, drive->tracks-1); + } else { + /* Seek to cylinder. */ + val = do_seek(dev, drive, + (ccb->cyl_low|(ccb->cyl_high<<8))); + } + if (! val) + dev->ssb.seek_end = 1; + do_finish(dev); + break; + + default: + dev->intstat |= ISR_INVALID_CMD; + do_finish(dev); + } +} + + +/* Prepare to send the SSB block. */ +static void +hdc_send_ssb(hdc_t *dev) +{ + drive_t *drive; + + /* We only support one drive, really, but ohwell. */ + drive = &dev->drives[0]; + + if (! dev->ssb.valid) { + /* Create a valid SSB. */ + memset(&dev->ssb, 0x00, sizeof(dev->ssb)); + dev->ssb.sect_size = 0x02; /* 512 bytes */ + dev->ssb.drive_type = drive->type; + } + + /* Update position fields. */ + dev->ssb.track_0 = !!(dev->track == 0); + dev->ssb.last_cyl_low = dev->ssb.curr_cyl_low; + dev->ssb.last_cyl_high = dev->ssb.curr_cyl_high; + dev->ssb.last_head = dev->ssb.curr_head; + dev->ssb.curr_cyl_high = ((dev->track >> 8) & 0x03); + dev->ssb.curr_cyl_low = (dev->track & 0xff); + dev->ssb.curr_head = (dev->head & 0x0f); + + dev->ssb.headsel_state = dev->ssb.curr_head; + dev->ssb.last_sect = dev->sector; + + /* We abuse an unused MBZ bit, so clear it. */ + dev->ssb.valid = 0; + + /* Set up the transfer buffer for the SSB. */ + dev->buf_idx = 0; + dev->buf_len = sizeof(dev->ssb); + dev->buf_ptr = (uint8_t *)&dev->ssb; + + /* Done with the SSB. */ + dev->attn &= ~ATT_SSB; +} + + +/* Read one of the controller registers. */ +static uint8_t +hdc_read(uint16_t port, void *priv) +{ + hdc_t *dev = (hdc_t *)priv; + uint8_t ret = 0xff; + + /* TRM: tell system board we are alive. */ + ps1_set_feedback(dev->sys); + + switch (port & 7) { + case 0: /* DATA register */ + if (dev->state == STATE_SDATA) { + if (dev->buf_idx > dev->buf_len) { + ps1_hdc_log("HDC: read with empty buffer!\n"); + dev->state = STATE_IDLE; + dev->intstat |= ISR_INVALID_CMD; + dev->status &= (ASR_TX_EN|ASR_DATA_REQ|ASR_DIR); + set_intr(dev, 1); + break; + } + + ret = dev->buf_ptr[dev->buf_idx]; + if (++dev->buf_idx == dev->buf_len) { + /* Data block sent OK. */ + dev->status &= ~(ASR_TX_EN|ASR_DATA_REQ|ASR_DIR); + dev->state = STATE_IDLE; + } + } + break; + + case 2: /* ASR */ + ret = dev->status; + break; + + case 4: /* ISR */ + ret = dev->intstat; + dev->intstat = 0x00; + break; + } + + return(ret); +} + + +static void +hdc_write(uint16_t port, uint8_t val, void *priv) +{ + hdc_t *dev = (hdc_t *)priv; + + /* TRM: tell system board we are alive. */ + ps1_set_feedback(dev->sys); + + switch (port & 7) { + case 0: /* DATA register */ + if (dev->state == STATE_RDATA) { + if (dev->buf_idx >= dev->buf_len) { + ps1_hdc_log("HDC: write with full buffer!\n"); + dev->intstat |= ISR_INVALID_CMD; + dev->status &= ~ASR_DATA_REQ; + set_intr(dev, 1); + break; + } + + /* Store the data into the buffer. */ + dev->buf_ptr[dev->buf_idx] = val; + if (++dev->buf_idx == dev->buf_len) { + /* We got all the data we need. */ + dev->status &= ~ASR_DATA_REQ; + dev->state = STATE_IDLE; + + /* If we were receiving a CCB, execute it. */ + if (dev->attn & ATT_CCB) { + /* + * If we were already busy with + * a CCB, then it must have had + * some new data using PIO. + */ + if (dev->status & ASR_BUSY) + dev->state = STATE_RDONE; + else + dev->status |= ASR_BUSY; + + /* Schedule command execution. */ + dev->callback = HDC_TIME; + } + } + } + break; + + case 2: /* ACR */ + dev->ctrl = val; + if (val & ACR_INT_EN) + set_intr(dev, 0); /* clear IRQ */ + + if (dev->reset != 0) { + if (++dev->reset == 3) { + dev->reset = 0; + + set_intr(dev, 1); + } + break; + } + + if (val & ACR_RESET) + dev->reset = 1; + break; + + case 4: /* ATTN */ + dev->status &= ~ASR_INT_REQ; + if (val & ATT_DATA) { + /* Dunno. Start PIO/DMA now? */ + } + + if (val & ATT_SSB) { + if (dev->attn & ATT_CCB) { + /* Hey now, we're still busy for you! */ + dev->intstat |= ISR_INVALID_CMD; + set_intr(dev, 1); + break; + } + + /* OK, prepare for sending an SSB. */ + dev->attn |= ATT_SSB; + + /* Grab or initialize an SSB to send. */ + hdc_send_ssb(dev); + + dev->state = STATE_SDATA; + dev->status |= (ASR_TX_EN|ASR_DATA_REQ|ASR_DIR); + set_intr(dev, 1); + } + + if (val & ATT_CCB) { + dev->attn |= ATT_CCB; + + /* Set up the transfer buffer for a CCB. */ + dev->buf_idx = 0; + dev->buf_len = sizeof(dev->ccb); + dev->buf_ptr = (uint8_t *)&dev->ccb; + + dev->state = STATE_RDATA; + dev->status |= ASR_DATA_REQ; + set_intr(dev, 1); + } + break; + } +} + + +static void * +ps1_hdc_init(const device_t *info) +{ + drive_t *drive; + hdc_t *dev; + int c, i; + + /* Allocate and initialize device block. */ + dev = malloc(sizeof(hdc_t)); + memset(dev, 0x00, sizeof(hdc_t)); + + /* Set up controller parameters for PS/1 2011. */ + dev->base = 0x0320; + dev->irq = 14; + dev->dma = 3; + + ps1_hdc_log("HDC: initializing (I/O=%04X, IRQ=%d, DMA=%d)\n", + dev->base, dev->irq, dev->dma); + + /* Load any disks for this device class. */ + c = 0; + for (i = 0; i < HDD_NUM; i++) { + if ((hdd[i].bus == HDD_BUS_XTA) && (hdd[i].xta_channel < 1)) { + drive = &dev->drives[hdd[i].xta_channel]; + + if (! hdd_image_load(i)) { + drive->present = 0; + continue; + } + drive->id = c; + + /* These are the "hardware" parameters (from the image.) */ + drive->cfg_spt = (uint8_t)(hdd[i].spt & 0xff); + drive->cfg_hpc = (uint8_t)(hdd[i].hpc & 0xff); + drive->cfg_tracks = (uint16_t)hdd[i].tracks; + + /* Use them as "active" parameters until overwritten. */ + drive->spt = drive->cfg_spt; + drive->hpc = drive->cfg_hpc; + drive->tracks = drive->cfg_tracks; + + drive->type = ibm_drive_type(drive); + drive->hdd_num = i; + drive->present = 1; + + ps1_hdc_log("HDC: drive%d (type %d: cyl=%d,hd=%d,spt=%d), disk %d\n", + hdd[i].xta_channel, drive->type, + drive->tracks, drive->hpc, drive->spt, i); + + if (++c > 1) break; + } + } + + /* Sectors are 1-based. */ + dev->sector = 1; + + /* Enable the I/O block. */ + io_sethandler(dev->base, 5, + hdc_read,NULL,NULL, hdc_write,NULL,NULL, dev); + + /* Create a timer for command delays. */ + timer_add(hdc_callback, &dev->callback, &dev->callback, dev); + + return(dev); +} + + +static void +ps1_hdc_close(void *priv) +{ + hdc_t *dev = (hdc_t *)priv; + drive_t *drive; + int d; + + /* Remove the I/O handler. */ + io_removehandler(dev->base, 5, + hdc_read,NULL,NULL, hdc_write,NULL,NULL, dev); + + /* Close all disks and their images. */ + for (d = 0; d < XTA_NUM; d++) { + drive = &dev->drives[d]; + + if (drive->present) + hdd_image_close(drive->hdd_num); + } + + /* Release the device. */ + free(dev); +} + + +const device_t ps1_hdc_device = { + "PS/1 2011 Fixed Disk Controller", + DEVICE_ISA | DEVICE_PS2, + 0, + ps1_hdc_init, ps1_hdc_close, NULL, + NULL, NULL, NULL, + NULL +}; + + +/* + * Very nasty. + * + * The PS/1 systems employ a feedback system where external + * cards let the system know they were 'addressed' by setting + * their Card Selected Flag (CSF) in register 0x0091. Driver + * software can test this register to see if they are talking + * to hardware or not. + * + * This means, that we must somehow do the same, and yes, I + * agree that the current solution is nasty. + */ +void +ps1_hdc_inform(void *priv, void *arg) +{ + hdc_t *dev = (hdc_t *)priv; + + dev->sys = arg; +} diff --git a/src/machine/m_ps2_isa.c b/src/machine/m_ps2_isa.c index 60300adf0..213e06b50 100644 --- a/src/machine/m_ps2_isa.c +++ b/src/machine/m_ps2_isa.c @@ -156,7 +156,7 @@ machine_ps2_m30_286_init(const machine_t *model) pit_set_out_func(&pit, 1, pit_refresh_timer_at); dma16_init(); device_add(&keyboard_ps2_device); - nvr_at_init(8); + device_add(&ps_nvr_device); pic2_init(); ps2board_init(); device_add(&ps1vga_device); diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 0aeed187a..1d594860d 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -1,7 +1,9 @@ -#include +#include #include +#include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../cpu/cpu.h" #include "../cpu/x86.h" @@ -94,9 +96,30 @@ static struct static uint8_t ps2_cache[65536]; static int ps2_cache_valid[65536/8]; + +#ifdef ENABLE_PS2_MCA_LOG +int ps2_mca_do_log = ENABLE_PS2_MCA_LOG; +#endif + + +static void +ps2_mca_log(const char *format, ...) +{ +#ifdef ENABLE_PS2_MCA_LOG + va_list ap; + + if (ps2_mca_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + static uint8_t ps2_read_cache_ram(uint32_t addr, void *priv) { -// pclog("ps2_read_cache_ram: addr=%08x %i %04x:%04x\n", addr, ps2_cache_valid[addr >> 3], CS,cpu_state.pc); + ps2_mca_log("ps2_read_cache_ram: addr=%08x %i %04x:%04x\n", addr, ps2_cache_valid[addr >> 3], CS,cpu_state.pc); if (!ps2_cache_valid[addr >> 3]) { ps2_cache_valid[addr >> 3] = 1; @@ -109,7 +132,7 @@ static uint8_t ps2_read_cache_ram(uint32_t addr, void *priv) } static uint16_t ps2_read_cache_ramw(uint32_t addr, void *priv) { -// pclog("ps2_read_cache_ramw: addr=%08x %i %04x:%04x\n", addr, ps2_cache_valid[addr >> 3], CS,cpu_state.pc); + ps2_mca_log("ps2_read_cache_ramw: addr=%08x %i %04x:%04x\n", addr, ps2_cache_valid[addr >> 3], CS,cpu_state.pc); if (!ps2_cache_valid[addr >> 3]) { ps2_cache_valid[addr >> 3] = 1; @@ -122,7 +145,7 @@ static uint16_t ps2_read_cache_ramw(uint32_t addr, void *priv) } static uint32_t ps2_read_cache_raml(uint32_t addr, void *priv) { -// pclog("ps2_read_cache_raml: addr=%08x %i %04x:%04x\n", addr, ps2_cache_valid[addr >> 3], CS,cpu_state.pc); + ps2_mca_log("ps2_read_cache_raml: addr=%08x %i %04x:%04x\n", addr, ps2_cache_valid[addr >> 3], CS,cpu_state.pc); if (!ps2_cache_valid[addr >> 3]) { ps2_cache_valid[addr >> 3] = 1; @@ -135,7 +158,7 @@ static uint32_t ps2_read_cache_raml(uint32_t addr, void *priv) } static void ps2_write_cache_ram(uint32_t addr, uint8_t val, void *priv) { -// pclog("ps2_write_cache_ram: addr=%08x val=%02x %04x:%04x %i\n", addr, val, CS,cpu_state.pc, ins); + ps2_mca_log("ps2_write_cache_ram: addr=%08x val=%02x %04x:%04x %i\n", addr, val, CS,cpu_state.pc, ins); ps2_cache[addr] = val; } @@ -408,10 +431,10 @@ static void model_55sx_write(uint16_t port, uint8_t val) case 0x104: ps2.memory_bank[ps2.option[3] & 7] &= ~0xf; ps2.memory_bank[ps2.option[3] & 7] |= (val & 0xf); - /* pclog("Write memory bank %i %02x\n", ps2.option[3] & 7, val); */ + ps2_mca_log("Write memory bank %i %02x\n", ps2.option[3] & 7, val); break; case 0x105: - /* pclog("Write POS3 %02x\n", val); */ + ps2_mca_log("Write POS3 %02x\n", val); ps2.option[3] = val; shadowbios = !(val & 0x10); shadowbios_write = val & 0x10; @@ -636,14 +659,14 @@ uint8_t ps2_mca_read(uint16_t port, void *p) break; } - /* pclog("ps2_read: port=%04x temp=%02x\n", port, temp); */ - - return temp; + ps2_mca_log("ps2_read: port=%04x temp=%02x\n", port, temp); + + return temp; } static void ps2_mca_write(uint16_t port, uint8_t val, void *p) { - /* pclog("ps2_write: port=%04x val=%02x %04x:%04x\n", port, val, CS,cpu_state.pc); */ + ps2_mca_log("ps2_write: port=%04x val=%02x %04x:%04x\n", port, val, CS,cpu_state.pc); switch (port) { @@ -893,18 +916,18 @@ static void mem_encoding_update() if (ps2.mem_regs[1] & 2) { mem_set_mem_state(0xe0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - /* pclog("PS/2 Model 80-111: ROM space enabled\n"); */ + ps2_mca_log("PS/2 Model 80-111: ROM space enabled\n"); } else { mem_set_mem_state(0xe0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); - /* pclog("PS/2 Model 80-111: ROM space disabled\n"); */ + ps2_mca_log("PS/2 Model 80-111: ROM space disabled\n"); } if (ps2.mem_regs[1] & 4) { mem_mapping_set_addr(&ram_low_mapping, 0x00000, 0x80000); - /* pclog("PS/2 Model 80-111: 00080000- 0009FFFF disabled\n"); */ + ps2_mca_log("PS/2 Model 80-111: 00080000- 0009FFFF disabled\n"); } else { mem_mapping_set_addr(&ram_low_mapping, 0x00000, 0xa0000); - /* pclog("PS/2 Model 80-111: 00080000- 0009FFFF enabled\n"); */ + ps2_mca_log("PS/2 Model 80-111: 00080000- 0009FFFF enabled\n"); } if (!(ps2.mem_regs[1] & 8)) @@ -920,10 +943,9 @@ static void mem_encoding_update() mem_mapping_set_exec(&ps2.split_mapping, &ram[ps2.split_phys]); mem_mapping_set_addr(&ps2.split_mapping, ps2.split_addr, ps2.split_size << 10); - /* pclog("PS/2 Model 80-111: Split memory block enabled at %08X\n", ps2.split_addr); */ - } /* else { - pclog("PS/2 Model 80-111: Split memory block disabled\n"); - } */ + ps2_mca_log("PS/2 Model 80-111: Split memory block enabled at %08X\n", ps2.split_addr); + } else + ps2_mca_log("PS/2 Model 80-111: Split memory block disabled\n"); } static uint8_t mem_encoding_read(uint16_t addr, void *p) @@ -982,7 +1004,7 @@ static void mem_encoding_write_cached(uint16_t addr, uint8_t val, void *p) ps2.mem_regs[2] = (ps2.mem_regs[2] & 0x80) | (val & ~0x88); if (val & 2) { -// pclog("Clear latch - %i\n", ps2.pending_cache_miss); + ps2_mca_log("Clear latch - %i\n", ps2.pending_cache_miss); if (ps2.pending_cache_miss) ps2.mem_regs[2] |= 0x80; else @@ -1000,7 +1022,7 @@ static void mem_encoding_write_cached(uint16_t addr, uint8_t val, void *p) ram_mid_mapping.flags &= ~MEM_MAPPING_ROM; break; } -// pclog("mem_encoding_write: addr=%02x val=%02x %04x:%04x %02x %02x\n", addr, val, CS,cpu_state.pc, ps2.mem_regs[1],ps2.mem_regs[2]); + ps2_mca_log("mem_encoding_write: addr=%02x val=%02x %04x:%04x %02x %02x\n", addr, val, CS,cpu_state.pc, ps2.mem_regs[1],ps2.mem_regs[2]); mem_encoding_update(); if ((ps2.mem_regs[1] & 0x10) && (ps2.mem_regs[2] & 0x21) == 0x20) { @@ -1172,7 +1194,7 @@ machine_ps2_common_init(const machine_t *model) dma16_init(); ps2_dma_init(); device_add(&keyboard_ps2_mca_device); - nvr_at_init(8); + device_add(&ps_nvr_device); pic2_init(); pit_ps2_init(); diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index 552f23fe9..d159d63c8 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -8,7 +8,7 @@ * * Emulation of Tandy models 1000, 1000HX and 1000SL2. * - * Version: @(#)m_tandy.c 1.0.5 2018/03/19 + * Version: @(#)m_tandy.c 1.0.7 2018/04/29 * * Authors: Sarah Walker, * Miran Grca, @@ -16,12 +16,14 @@ * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 Miran Grca. */ -#include +#include #include +#include #include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../io.h" #include "../pit.h" @@ -397,6 +399,28 @@ static int eep_data_out; static uint8_t vid_in(uint16_t addr, void *priv); static void vid_out(uint16_t addr, uint8_t val, void *priv); + +#ifdef ENABLE_TANDY_LOG +int tandy_do_log = ENABLE_TANDY_LOG; +#endif + + +static void +tandy_log(const char *fmt, ...) +{ +#ifdef ENABLE_TANDY_LOG + va_list ap; + + if (tandy_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + static void recalc_mapping(tandy_t *dev) { @@ -1381,7 +1405,6 @@ static const device_t vid_device = { NULL, vid_speed_changed, NULL, - NULL, vid_config }; @@ -1392,7 +1415,6 @@ static const device_t vid_device_hx = { NULL, vid_speed_changed, NULL, - NULL, vid_config }; @@ -1403,7 +1425,6 @@ static const device_t vid_device_sl = { NULL, vid_speed_changed, NULL, - NULL, NULL }; @@ -1552,7 +1573,7 @@ static const device_t eep_device = { "Tandy 1000 EEPROM", 0, 0, eep_init, eep_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; @@ -1669,7 +1690,7 @@ init_rom(tandy_t *dev) if (! rom_load_interleaved(L"roms/machines/tandy1000sl2/8079047.hu1", L"roms/machines/tandy1000sl2/8079048.hu2", 0x000000, 0x80000, 0, dev->rom)) { - pclog("TANDY: unable to load BIOS for 1000/SL2 !\n"); + tandy_log("TANDY: unable to load BIOS for 1000/SL2 !\n"); free(dev->rom); dev->rom = NULL; return; diff --git a/src/machine/m_xt_t1000.c b/src/machine/m_xt_t1000.c index 02d5e6c48..2b5d33186 100644 --- a/src/machine/m_xt_t1000.c +++ b/src/machine/m_xt_t1000.c @@ -51,7 +51,7 @@ * NOTE: Still need to figure out a way to load/save ConfigSys and * HardRAM stuff. Needs to be linked in to the NVR code. * - * Version: @(#)m_xt_t1000.c 1.0.4 2018/03/19 + * Version: @(#)m_xt_t1000.c 1.0.6 2018/04/29 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -79,12 +79,14 @@ * Boston, MA 02111-1307 * USA. */ -#include +#include #include +#include #include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../cpu/cpu.h" #include "../io.h" @@ -92,8 +94,8 @@ #include "../nmi.h" #include "../mem.h" #include "../rom.h" -#include "../nvr.h" #include "../device.h" +#include "../nvr.h" #include "../keyboard.h" #include "../lpt.h" #include "../mem.h" @@ -176,6 +178,27 @@ typedef struct { static t1000_t t1000; +#ifdef ENABLE_T1000_LOG +int t1000_do_log = ENABLE_T1000_LOG; +#endif + + +static void +t1000_log(const char *fmt, ...) +{ +#ifdef ENABLE_TANDY_LOG + va_list ap; + + if (t1000_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + /* Set the chip time. */ static void tc8521_time_set(uint8_t *regs, struct tm *tm) @@ -225,7 +248,7 @@ tc8521_time_get(uint8_t *regs, struct tm *tm) static void tc8521_tick(nvr_t *nvr) { - pclog("TC8521: ping\n"); + t1000_log("TC8521: ping\n"); } @@ -336,7 +359,7 @@ ems_execaddr(t1000_t *sys, int pg, uint16_t val) val &= 0x7f; #if 0 - pclog("Select EMS page: %d of %d\n", val, sys->ems_pages); + t1000_log("Select EMS page: %d of %d\n", val, sys->ems_pages); #endif if (val < sys->ems_pages) { /* EMS is any memory above 512k, @@ -354,7 +377,7 @@ ems_in(uint16_t addr, void *priv) t1000_t *sys = (t1000_t *)priv; #if 0 - pclog("ems_in(%04x)=%02x\n", addr, sys->ems_reg[(addr >> 14) & 3]); + t1000_log("ems_in(%04x)=%02x\n", addr, sys->ems_reg[(addr >> 14) & 3]); #endif return(sys->ems_reg[(addr >> 14) & 3]); } @@ -367,7 +390,7 @@ ems_out(uint16_t addr, uint8_t val, void *priv) int pg = (addr >> 14) & 3; #if 0 - pclog("ems_out(%04x, %02x) pg=%d\n", addr, val, pg); + t1000_log("ems_out(%04x, %02x) pg=%d\n", addr, val, pg); #endif sys->ems_reg[pg] = val; sys->page_exec[pg] = ems_execaddr(sys, pg, val); @@ -394,7 +417,7 @@ ems_set_hardram(t1000_t *sys, uint8_t val) sys->ems_base = 0; #if 0 - pclog("EMS base set to %02x\n", val); + t1000_log("EMS base set to %02x\n", val); #endif sys->ems_pages = 48 - 4 * sys->ems_base; if (sys->ems_pages < 0) sys->ems_pages = 0; @@ -424,7 +447,7 @@ ems_set_port(t1000_t *sys, uint8_t val) int n; #if 0 - pclog("ems_set_port(%d)", val & 0x0f); + t1000_log("ems_set_port(%d)", val & 0x0f); #endif if (sys->ems_port) { for (n = 0; n <= 0xc000; n += 0x4000) { @@ -449,7 +472,7 @@ ems_set_port(t1000_t *sys, uint8_t val) } #if 0 - pclog(" -> %04x\n", sys->ems_port); + t1000_log(" -> %04x\n", sys->ems_port); #endif } @@ -484,12 +507,12 @@ ems_read_ramw(uint32_t addr, void *priv) if (pg < 0) return(0xff); #if 0 - pclog("ems_read_ramw addr=%05x ", addr); + t1000_log("ems_read_ramw addr=%05x ", addr); #endif addr = sys->page_exec[pg] + (addr & 0x3FFF); #if 0 - pclog("-> %06x val=%04x\n", addr, *(uint16_t *)&ram[addr]); + t1000_log("-> %06x val=%04x\n", addr, *(uint16_t *)&ram[addr]); #endif return(*(uint16_t *)&ram[addr]); @@ -534,12 +557,12 @@ ems_write_ramw(uint32_t addr, uint16_t val, void *priv) if (pg < 0) return; #if 0 - pclog("ems_write_ramw addr=%05x ", addr); + t1000_log("ems_write_ramw addr=%05x ", addr); #endif addr = sys->page_exec[pg] + (addr & 0x3fff); #if 0 - pclog("-> %06x val=%04x\n", addr, val); + t1000_log("-> %06x val=%04x\n", addr, val); #endif if (*(uint16_t *)&ram[addr] != val) nvr_dosave = 1; diff --git a/src/machine/m_xt_t1000_vid.c b/src/machine/m_xt_t1000_vid.c index a1baa8f22..01b184fde 100644 --- a/src/machine/m_xt_t1000_vid.c +++ b/src/machine/m_xt_t1000_vid.c @@ -9,7 +9,7 @@ * Implementation of the Toshiba T1000 plasma display, which * has a fixed resolution of 640x200 pixels. * - * Version: @(#)m_xt_t1000_vid.c 1.0.5 2018/03/18 + * Version: @(#)m_xt_t1000_vid.c 1.0.7 2018/04/29 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -185,7 +185,6 @@ static void t1000_write(uint32_t addr, uint8_t val, void *p) t1000_t *t1000 = (t1000_t *)p; egawrites++; -// pclog("CGA_WRITE %04X %02X\n", addr, val); t1000->vram[addr & 0x3fff] = val; cycles -= 4; } @@ -196,7 +195,6 @@ static uint8_t t1000_read(uint32_t addr, void *p) egareads++; cycles -= 4; -// pclog("CGA_READ %04X\n", addr); return t1000->vram[addr & 0x3fff]; } @@ -736,7 +734,6 @@ const device_t t1000_video_device = { NULL, t1000_speed_changed, NULL, - NULL, t1000_config }; @@ -748,6 +745,5 @@ const device_t t1200_video_device = { NULL, t1000_speed_changed, NULL, - NULL, t1000_config }; diff --git a/src/machine/m_xt_xi8088.c b/src/machine/m_xt_xi8088.c index f4137cfb0..13d1c20b8 100644 --- a/src/machine/m_xt_xi8088.c +++ b/src/machine/m_xt_xi8088.c @@ -112,7 +112,6 @@ const device_t xi8088_device = NULL, NULL, NULL, - NULL, xi8088_config }; @@ -129,7 +128,7 @@ void machine_xt_xi8088_init(const machine_t *model) device_add(&fdc_xt_device); device_add(&keyboard_ps2_device); nmi_init(); - nvr_at_init(8); + device_add(&at_nvr_device); pic2_init(); if (joystick_type != 7) device_add(&gameport_device); diff --git a/src/machine/machine.c b/src/machine/machine.c index b344ddd10..9396de0ba 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -8,7 +8,7 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.c 1.0.32 2018/03/19 + * Version: @(#)machine.c 1.0.34 2018/04/29 * * Authors: Sarah Walker, * Miran Grca, @@ -18,10 +18,12 @@ * Copyright 2016-2018 Miran Grca. * Copyright 2017,2018 Fred N. van Kempen. */ -#include +#include #include +#include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../device.h" #include "../dma.h" @@ -31,8 +33,7 @@ #include "../rom.h" #include "../lpt.h" #include "../serial.h" -#include "../disk/hdc.h" -#include "../disk/hdc_ide.h" +#include "../cpu/cpu.h" #include "machine.h" @@ -41,12 +42,31 @@ int AT, PCI; int romset; +#ifdef ENABLE_MACHINE_LOG +int machine_do_log = ENABLE_MACHINE_LOG; +#endif + + +static void +machine_log(const char *fmt, ...) +{ +#ifdef ENABLE_TANDY_LOG + va_list ap; + + if (machine_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + void machine_init(void) { - pclog("Initializing as \"%s\"\n", machine_getname()); - - ide_set_bus_master(NULL, NULL, NULL); + machine_log("Initializing as \"%s\"\n", machine_getname()); /* Set up the architecture flags. */ AT = IS_ARCH(machine, MACHINE_AT); @@ -68,10 +88,16 @@ void machine_common_init(const machine_t *model) { /* System devices first. */ - dma_init(); pic_init(); + dma_init(); pit_init(); + cpu_set(); + if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286) + setrtcconst(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed); + else + setrtcconst(14318184.0); + if (lpt_enabled) lpt_init(); diff --git a/src/machine/machine.h b/src/machine/machine.h index 7822ffd2f..89228c5eb 100644 --- a/src/machine/machine.h +++ b/src/machine/machine.h @@ -8,7 +8,7 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.h 1.0.22 2018/03/18 + * Version: @(#)machine.h 1.0.24 2018/05/10 * * Authors: Sarah Walker, * Miran Grca, @@ -55,7 +55,7 @@ typedef struct _machine_ { } cpu[5]; int fixed_gfxcard; int flags; - int min_ram, max_ram; + uint32_t min_ram, max_ram; int ram_granularity; int nvrmask; void (*init)(const struct _machine_ *); @@ -64,7 +64,6 @@ typedef struct _machine_ { #else void *get_device; #endif - void (*nvr_close)(void); } machine_t; @@ -114,6 +113,7 @@ extern void machine_at_zappa_init(const machine_t *); extern void machine_at_mb500n_init(const machine_t *); extern void machine_at_president_init(const machine_t *); extern void machine_at_thor_init(const machine_t *); +extern void machine_at_pb640_init(const machine_t *); extern void machine_at_acerm3a_init(const machine_t *); extern void machine_at_acerv35n_init(const machine_t *); @@ -156,6 +156,12 @@ extern void machine_at_4gpv31_init(const machine_t *); extern void machine_pcjr_init(const machine_t *); extern void machine_ps1_m2011_init(const machine_t *); +#ifdef EMU_DEVICE_H +extern void ps1_hdc_inform(void *, void *); +extern void ps1_set_feedback(void *); +extern const device_t ps1_hdc_device; +#endif + extern void machine_ps1_m2121_init(const machine_t *); extern void machine_ps1_m2133_init(const machine_t *); @@ -173,8 +179,7 @@ extern void machine_amstrad_init(const machine_t *); extern void machine_europc_init(const machine_t *); #ifdef EMU_DEVICE_H -extern const device_t europc_device, - europc_hdc_device; +extern const device_t europc_device; #endif extern void machine_olim24_init(const machine_t *); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index eaee5820a..c1f89623b 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11,7 +11,7 @@ * NOTES: OpenAT wip for 286-class machine with open BIOS. * PS2_M80-486 wip, pending receipt of TRM's for machine. * - * Version: @(#)machine_table.c 1.0.27 2018/03/22 + * Version: @(#)machine_table.c 1.0.30 2018/05/26 * * Authors: Sarah Walker, * Miran Grca, @@ -28,155 +28,152 @@ #include "../86box.h" #include "../cpu/cpu.h" #include "../mem.h" -#include "../nvr.h" #include "../rom.h" #include "../device.h" #include "machine.h" const machine_t machines[] = { - { "[8088] AMI XT clone", ROM_AMIXT, "amixt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL, NULL }, - { "[8088] Compaq Portable", ROM_PORTABLE, "portable", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_xt_compaq_init, NULL, NULL }, - { "[8088] DTK XT clone", ROM_DTKXT, "dtk", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL, NULL }, - { "[8088] IBM PC", ROM_IBMPC, "ibmpc", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 32, 0, machine_xt_init, NULL, NULL }, - { "[8088] IBM PCjr", ROM_IBMPCJR, "ibmpcjr", {{"", cpus_pcjr}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_pcjr_init, pcjr_get_device, NULL }, - { "[8088] IBM XT", ROM_IBMXT, "ibmxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL, NULL }, - { "[8088] Generic XT clone", ROM_GENXT, "genxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL, NULL }, - { "[8088] Juko XT clone", ROM_JUKOPC, "jukopc", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL, NULL }, - { "[8088] Phoenix XT clone", ROM_PXXT, "pxxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL, NULL }, - { "[8088] Schneider EuroPC", ROM_EUROPC, "europc", {{"Siemens",cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_HDC | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 15, machine_europc_init, NULL, NULL }, - { "[8088] Tandy 1000", ROM_TANDY, "tandy", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 128, 640, 128, 0, machine_tandy1k_init, tandy1k_get_device, NULL }, - { "[8088] Tandy 1000 HX", ROM_TANDY1000HX, "tandy1000hx", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 256, 640, 128, 0, machine_tandy1k_init, tandy1k_hx_get_device, NULL }, - { "[8088] Toshiba 1000", ROM_T1000, "t1000", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 512, 1280, 768, 63, machine_xt_t1000_init, NULL, NULL }, + { "[8088] AMI XT clone", ROM_AMIXT, "amixt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, + { "[8088] Compaq Portable", ROM_PORTABLE, "portable", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_xt_compaq_init, NULL }, + { "[8088] DTK XT clone", ROM_DTKXT, "dtk", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, + { "[8088] IBM PC", ROM_IBMPC, "ibmpc", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 32, 0, machine_xt_init, NULL }, + { "[8088] IBM PCjr", ROM_IBMPCJR, "ibmpcjr", {{"", cpus_pcjr}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_pcjr_init, pcjr_get_device }, + { "[8088] IBM XT", ROM_IBMXT, "ibmxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, + { "[8088] Generic XT clone", ROM_GENXT, "genxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, + { "[8088] Juko XT clone", ROM_JUKOPC, "jukopc", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, + { "[8088] Phoenix XT clone", ROM_PXXT, "pxxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, + { "[8088] Schneider EuroPC", ROM_EUROPC, "europc", {{"Siemens",cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_HDC | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 15, machine_europc_init, NULL }, + { "[8088] Tandy 1000", ROM_TANDY, "tandy", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 128, 640, 128, 0, machine_tandy1k_init, tandy1k_get_device }, + { "[8088] Tandy 1000 HX", ROM_TANDY1000HX, "tandy1000hx", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 256, 640, 128, 0, machine_tandy1k_init, tandy1k_hx_get_device }, + { "[8088] Toshiba T1000", ROM_T1000, "t1000", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 512, 1280, 768, 63, machine_xt_t1000_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_LASERXT) - { "[8088] VTech Laser Turbo XT", ROM_LTXT, "ltxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 512, 512, 256, 0, machine_xt_laserxt_init, NULL, NULL }, + { "[8088] VTech Laser Turbo XT", ROM_LTXT, "ltxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 512, 512, 256, 0, machine_xt_laserxt_init, NULL }, #endif - { "[8088] Xi8088", ROM_XI8088, "xi8088", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 64, 1024, 128, 127, machine_xt_xi8088_init, NULL, nvr_at_close }, + { "[8088] Xi8088", ROM_XI8088, "xi8088", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 64, 1024, 128, 127, machine_xt_xi8088_init, NULL }, - { "[8086] Amstrad PC1512", ROM_PC1512, "pc1512", {{"", cpus_pc1512}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 63, machine_amstrad_init, NULL, nvr_at_close }, - { "[8086] Amstrad PC1640", ROM_PC1640, "pc1640", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_amstrad_init, NULL, nvr_at_close }, - { "[8086] Amstrad PC2086", ROM_PC2086, "pc2086", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_amstrad_init, NULL, nvr_at_close }, - { "[8086] Amstrad PC3086", ROM_PC3086, "pc3086", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_amstrad_init, NULL, nvr_at_close }, - { "[8086] Amstrad PC20(0)", ROM_PC200, "pc200", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 63, machine_amstrad_init, NULL, nvr_at_close }, - { "[8086] Olivetti M24", ROM_OLIM24, "olivetti_m24", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 128, 640, 128, 0, machine_olim24_init, NULL, NULL }, - { "[8086] Tandy 1000 SL/2", ROM_TANDY1000SL2, "tandy1000sl2", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 512, 768, 128, 0, machine_tandy1k_init, NULL, NULL }, - { "[8086] Toshiba 1200", ROM_T1200, "t1200", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 1024, 2048,1024, 63, machine_xt_t1200_init, NULL, NULL }, + { "[8086] Amstrad PC1512", ROM_PC1512, "pc1512", {{"", cpus_pc1512}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 63, machine_amstrad_init, NULL }, + { "[8086] Amstrad PC1640", ROM_PC1640, "pc1640", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_amstrad_init, NULL }, + { "[8086] Amstrad PC2086", ROM_PC2086, "pc2086", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_amstrad_init, NULL }, + { "[8086] Amstrad PC3086", ROM_PC3086, "pc3086", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_amstrad_init, NULL }, + { "[8086] Amstrad PC20(0)", ROM_PC200, "pc200", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 63, machine_amstrad_init, NULL }, + { "[8086] Olivetti M24", ROM_OLIM24, "olivetti_m24", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 128, 640, 128, 0, machine_olim24_init, NULL }, + { "[8086] Tandy 1000 SL/2", ROM_TANDY1000SL2, "tandy1000sl2", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 512, 768, 128, 0, machine_tandy1k_init, NULL }, + { "[8086] Toshiba T1200", ROM_T1200, "t1200", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 1024, 2048,1024, 63, machine_xt_t1200_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_LASERXT) - { "[8086] VTech Laser XT3", ROM_LXT3, "lxt3", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 256, 512, 256, 0, machine_xt_laserxt_init, NULL, NULL }, + { "[8086] VTech Laser XT3", ROM_LXT3, "lxt3", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 256, 512, 256, 0, machine_xt_laserxt_init, NULL }, #endif - { "[286 ISA] AMI 286 clone", ROM_AMI286, "ami286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_neat_ami_init, NULL, nvr_at_close }, - { "[286 ISA] Award 286 clone", ROM_AWARD286, "award286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_scat_init, NULL, nvr_at_close }, - { "[286 ISA] Commodore PC 30 III", ROM_CMDPC30, "cmdpc30", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 127, machine_at_cmdpc_init, NULL, nvr_at_close }, - { "[286 ISA] Compaq Portable II", ROM_PORTABLEII, "portableii", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 127, machine_at_compaq_init, NULL, nvr_at_close }, + { "[286 ISA] AMI 286 clone", ROM_AMI286, "ami286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_neat_ami_init, NULL }, + { "[286 ISA] Award 286 clone", ROM_AWARD286, "award286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_scat_init, NULL }, + { "[286 ISA] Commodore PC 30 III", ROM_CMDPC30, "cmdpc30", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 127, machine_at_cmdpc_init, NULL }, + { "[286 ISA] Compaq Portable II", ROM_PORTABLEII, "portableii", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 127, machine_at_compaq_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_PORTABLE3) - { "[286 ISA] Compaq Portable III", ROM_PORTABLEIII, "portableiii", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO, 640,16384, 128, 127, machine_at_compaq_init, NULL, nvr_at_close }, + { "[286 ISA] Compaq Portable III", ROM_PORTABLEIII, "portableiii", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO, 640,16384, 128, 127, machine_at_compaq_init, NULL }, #endif - { "[286 ISA] GW-286CT GEAR", ROM_GW286CT, "gw286ct", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_scat_init, NULL, nvr_at_close }, - { "[286 ISA] Hyundai Super-286TR", ROM_SUPER286TR, "super286tr", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_scat_init, NULL, nvr_at_close }, - { "[286 ISA] IBM AT", ROM_IBMAT, "ibmat", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibm_init, NULL, nvr_at_close }, - { "[286 ISA] IBM PS/1 model 2011", ROM_IBMPS1_2011, "ibmps1es", {{"", cpus_ps1_m2011}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 512,16384, 512, 127, machine_ps1_m2011_init, NULL, nvr_at_close }, - { "[286 ISA] IBM PS/2 model 30-286", ROM_IBMPS2_M30_286, "ibmps2_m30_286", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 16, 1, 127, machine_ps2_m30_286_init, NULL, nvr_at_close }, - { "[286 ISA] IBM XT Model 286", ROM_IBMXT286, "ibmxt286", {{"", cpus_ibmxt286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibm_init, NULL, nvr_at_close }, - { "[286 ISA] Samsung SPC-4200P", ROM_SPC4200P, "spc4200p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 512, 2048, 128, 127, machine_at_scat_init, NULL, nvr_at_close }, - { "[286 ISA] Samsung SPC-4216P", ROM_SPC4216P, "spc4216p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 1, 5, 1, 127, machine_at_scat_init, NULL, nvr_at_close }, + { "[286 ISA] GW-286CT GEAR", ROM_GW286CT, "gw286ct", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_scat_init, NULL }, + { "[286 ISA] Hyundai Super-286TR", ROM_SUPER286TR, "super286tr", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_scat_init, NULL }, + { "[286 ISA] IBM AT", ROM_IBMAT, "ibmat", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibm_init, NULL }, + { "[286 ISA] IBM PS/1 model 2011", ROM_IBMPS1_2011, "ibmps1es", {{"", cpus_ps1_m2011}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_PS2 | MACHINE_HDC_PS2, 512,16384, 512, 63, machine_ps1_m2011_init, NULL }, + { "[286 ISA] IBM PS/2 model 30-286", ROM_IBMPS2_M30_286, "ibmps2_m30_286", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 16, 1, 127, machine_ps2_m30_286_init, NULL }, + { "[286 ISA] IBM XT Model 286", ROM_IBMXT286, "ibmxt286", {{"", cpus_ibmxt286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 127, machine_at_ibm_init, NULL }, + { "[286 ISA] Samsung SPC-4200P", ROM_SPC4200P, "spc4200p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 512, 2048, 128, 127, machine_at_scat_init, NULL }, + { "[286 ISA] Samsung SPC-4216P", ROM_SPC4216P, "spc4216p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 1, 5, 1, 127, machine_at_scat_init, NULL }, #ifdef WALTJE - { "[286 ISA] OpenAT 286", ROM_OPENAT, "open_at", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512, 4096, 128, 127, machine_at_init, NULL, nvr_at_close }, + { "[286 ISA] OpenAT 286", ROM_OPENAT, "open_at", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512, 4096, 128, 127, machine_at_init, NULL }, #endif - { "[286 ISA] Toshiba 3100e", ROM_T3100E, "t3100e", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1024, 5120, 256, 63, machine_at_t3100e_init, NULL, nvr_at_close }, + { "[286 ISA] Toshiba T3100e", ROM_T3100E, "t3100e", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1024, 5120, 256, 63, machine_at_t3100e_init, NULL }, - { "[286 MCA] IBM PS/2 model 50", ROM_IBMPS2_M50, "ibmps2_m50", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 10, 1, 63, machine_ps2_model_50_init, NULL, nvr_at_close }, + { "[286 MCA] IBM PS/2 model 50", ROM_IBMPS2_M50, "ibmps2_m50", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 10, 1, 63, machine_ps2_model_50_init, NULL }, - { "[386SX ISA] AMI 386SX clone", ROM_AMI386SX, "ami386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,16384, 128, 127, machine_at_headland_init, NULL, nvr_at_close }, - { "[386SX ISA] Amstrad MegaPC", ROM_MEGAPC, "megapc", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 1, 16, 1, 127, machine_at_wd76c10_init, NULL, nvr_at_close }, - { "[386SX ISA] Award 386SX clone", ROM_AWARD386SX_OPTI495, "award386sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_init, NULL, nvr_at_close }, - { "[386SX ISA] DTK 386SX clone", ROM_DTK386, "dtk386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,16384, 128, 127, machine_at_neat_init, NULL, nvr_at_close }, - { "[386SX ISA] IBM PS/1 model 2121", ROM_IBMPS1_2121, "ibmps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 127, machine_ps1_m2121_init, NULL, nvr_at_close }, - { "[386SX ISA] IBM PS/1 m.2121+ISA", ROM_IBMPS1_2121_ISA, "ibmps1_2121_isa", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 127, machine_ps1_m2121_init, NULL, nvr_at_close }, - { "[386SX ISA] KMX-C-02", ROM_KMXC02, "kmxc02", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 512, 127, machine_at_scatsx_init, NULL, nvr_at_close }, + { "[386SX ISA] AMI 386SX clone", ROM_AMI386SX, "ami386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,16384, 128, 127, machine_at_headland_init, NULL }, + { "[386SX ISA] Amstrad MegaPC", ROM_MEGAPC, "megapc", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 1, 16, 1, 127, machine_at_wd76c10_init, NULL }, + { "[386SX ISA] Award 386SX clone", ROM_AWARD386SX_OPTI495, "award386sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_init, NULL }, + { "[386SX ISA] DTK 386SX clone", ROM_DTK386, "dtk386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,16384, 128, 127, machine_at_neat_init, NULL }, + { "[386SX ISA] IBM PS/1 model 2121", ROM_IBMPS1_2121, "ibmps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 63, machine_ps1_m2121_init, NULL }, + { "[386SX ISA] IBM PS/1 m.2121+ISA", ROM_IBMPS1_2121_ISA, "ibmps1_2121_isa", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 63, machine_ps1_m2121_init, NULL }, + { "[386SX ISA] KMX-C-02", ROM_KMXC02, "kmxc02", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 512, 127, machine_at_scatsx_init, NULL }, - { "[386SX MCA] IBM PS/2 model 55SX", ROM_IBMPS2_M55SX, "ibmps2_m55sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 8, 1, 63, machine_ps2_model_55sx_init, NULL, nvr_at_close }, + { "[386SX MCA] IBM PS/2 model 55SX", ROM_IBMPS2_M55SX, "ibmps2_m55sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 8, 1, 63, machine_ps2_model_55sx_init, NULL }, - { "[386DX ISA] AMI 386DX clone", ROM_AMI386DX_OPTI495, "ami386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_ami_init, NULL, nvr_at_close }, - { "[386DX ISA] Amstrad MegaPC 386DX", ROM_MEGAPCDX, "megapcdx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 32, 1, 127, machine_at_wd76c10_init, NULL, nvr_at_close }, - { "[386DX ISA] Award 386DX clone", ROM_AWARD386DX_OPTI495, "award386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_init, NULL, nvr_at_close }, - { "[386DX ISA] MR 386DX clone", ROM_MR386DX_OPTI495, "mr386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_ami_init, NULL, nvr_at_close }, + { "[386DX ISA] AMI 386DX clone", ROM_AMI386DX_OPTI495, "ami386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_ami_init, NULL }, + { "[386DX ISA] Amstrad MegaPC 386DX", ROM_MEGAPCDX, "megapcdx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 32, 1, 127, machine_at_wd76c10_init, NULL }, + { "[386DX ISA] Award 386DX clone", ROM_AWARD386DX_OPTI495, "award386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_init, NULL }, + { "[386DX ISA] MR 386DX clone", ROM_MR386DX_OPTI495, "mr386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_ami_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_PORTABLE3) - { "[386DX ISA] Compaq Portable III (386)", ROM_PORTABLEIII386, "portableiii386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 1, 14, 1, 127, machine_at_compaq_init, NULL, nvr_at_close }, -#endif - { "[386DX MCA] IBM PS/2 model 70 (type 3)", ROM_IBMPS2_M70_TYPE3, "ibmps2_m70_type3", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 2, 16, 2, 63, machine_ps2_model_70_type3_init, NULL, nvr_at_close }, - - { "[386DX MCA] IBM PS/2 model 80", ROM_IBMPS2_M80, "ibmps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 12, 1, 63, machine_ps2_model_80_init, NULL, nvr_at_close }, - - { "[486 ISA] AMI 486 clone", ROM_AMI486, "ami486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_ali1429_init, NULL, nvr_at_close }, - { "[486 ISA] AMI WinBIOS 486", ROM_WIN486, "win486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_ali1429_init, NULL, nvr_at_close }, - { "[486 ISA] Award 486 clone", ROM_AWARD486_OPTI495, "award486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_init, NULL, nvr_at_close }, - { "[486 ISA] DTK PKM-0038S E-2", ROM_DTK486, "dtk486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 127, machine_at_dtk486_init, NULL, nvr_at_close }, - { "[486 ISA] IBM PS/1 model 2133", ROM_IBMPS1_2133, "ibmps1_2133", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 1, 64, 1, 127, machine_ps1_m2133_init, NULL, nvr_at_close }, - - { "[486 MCA] IBM PS/2 model 70 (type 4)", ROM_IBMPS2_M70_TYPE4, "ibmps2_m70_type4", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 2, 16, 2, 63, machine_ps2_model_70_type4_init, NULL, nvr_at_close }, - -#ifdef WALTJE - { "[486 MCA] IBM PS/2 model 80-486", ROM_IBMPS2_M80_486, "ibmps2_m80-486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 32, 1, 63, machine_ps2_model_80_486_init, NULL, nvr_at_close }, + { "[386DX ISA] Compaq Portable III (386)", ROM_PORTABLEIII386, "portableiii386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 1, 14, 1, 127, machine_at_compaq_init, NULL }, #endif - { "[486 PCI] Rise Computer R418", ROM_R418, "r418", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 127, machine_at_r418_init, NULL, nvr_at_close }, + { "[386DX MCA] IBM PS/2 model 70 (type 3)", ROM_IBMPS2_M70_TYPE3, "ibmps2_m70_type3", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 2, 16, 2, 63, machine_ps2_model_70_type3_init, NULL }, + { "[386DX MCA] IBM PS/2 model 80", ROM_IBMPS2_M80, "ibmps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 12, 1, 63, machine_ps2_model_80_init, NULL }, -#if defined(DEV_BRANCH) && defined(USE_GREENB) - { "[486 VLB] Green-B 4GP V3.1", ROM_4GPV31, "4gpv31", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT, 1, 128, 1, 127, machine_at_4gpv31_init, NULL, nvr_at_close }, -#endif + { "[486 ISA] AMI 486 clone", ROM_AMI486, "ami486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_ali1429_init, NULL }, + { "[486 ISA] AMI WinBIOS 486", ROM_WIN486, "win486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_ali1429_init, NULL }, + { "[486 ISA] Award 486 clone", ROM_AWARD486_OPTI495, "award486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_init, NULL }, + { "[486 ISA] DTK PKM-0038S E-2", ROM_DTK486, "dtk486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 127, machine_at_dtk486_init, NULL }, + { "[486 ISA] IBM PS/1 model 2133", ROM_IBMPS1_2133, "ibmps1_2133", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 1, 64, 1, 127, machine_ps1_m2133_init, NULL }, - { "[Socket 4 LX] Intel Premiere/PCI", ROM_REVENGE, "revenge", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_batman_init, NULL, nvr_at_close }, + { "[486 MCA] IBM PS/2 model 70 (type 4)", ROM_IBMPS2_M70_TYPE4, "ibmps2_m70_type4", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 2, 16, 2, 63, machine_ps2_model_70_type4_init, NULL }, + + { "[486 PCI] Rise Computer R418", ROM_R418, "r418", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 127, machine_at_r418_init, NULL }, + + { "[Socket 4 LX] Intel Premiere/PCI", ROM_REVENGE, "revenge", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_batman_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_AMD_K) - { "[Socket 5 NX] Intel Premiere/PCI II", ROM_PLATO, "plato", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_plato_init, NULL, nvr_at_close }, + { "[Socket 5 NX] Intel Premiere/PCI II", ROM_PLATO, "plato", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_plato_init, NULL }, - { "[Socket 5 FX] ASUS P/I-P54TP4XE", ROM_P54TP4XE, "p54tp4xe", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_p54tp4xe_init, NULL, nvr_at_close }, - { "[Socket 5 FX] Intel Advanced/EV", ROM_ENDEAVOR, "endeavor", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_endeavor_init, at_endeavor_get_device, nvr_at_close }, - { "[Socket 5 FX] Intel Advanced/ZP", ROM_ZAPPA, "zappa", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_zappa_init, NULL, nvr_at_close }, - { "[Socket 5 FX] PC Partner MB500N", ROM_MB500N, "mb500n", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_mb500n_init, NULL, nvr_at_close }, - { "[Socket 5 FX] President Award 430FX PCI",ROM_PRESIDENT, "president", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_president_init, NULL, nvr_at_close }, + { "[Socket 5 FX] ASUS P/I-P54TP4XE", ROM_P54TP4XE, "p54tp4xe", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_p54tp4xe_init, NULL }, + { "[Socket 5 FX] Intel Advanced/ZP", ROM_ZAPPA, "zappa", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_zappa_init, NULL }, + { "[Socket 5 FX] PC Partner MB500N", ROM_MB500N, "mb500n", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_mb500n_init, NULL }, + { "[Socket 5 FX] President Award 430FX PCI",ROM_PRESIDENT, "president", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_president_init, NULL }, - { "[Socket 7 FX] Intel Advanced/ATX", ROM_THOR, "thor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL, nvr_at_close }, - { "[Socket 7 FX] MR Intel Advanced/ATX", ROM_MRTHOR, "mrthor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL, nvr_at_close }, + { "[Socket 7 FX] Intel Advanced/ATX", ROM_THOR, "thor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL }, +#if defined(DEV_BRANCH) && defined(USE_MRTHOR) + { "[Socket 7 FX] MR Intel Advanced/ATX", ROM_MRTHOR, "mrthor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL }, +#endif + { "[Socket 7 FX] Intel Advanced/EV", ROM_ENDEAVOR, "endeavor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_endeavor_init, at_endeavor_get_device }, + { "[Socket 7 FX] Packard Bell PB640", ROM_PB640, "pb640", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_pb640_init, NULL }, - { "[Socket 7 HX] Acer M3a", ROM_ACERM3A, "acerm3a", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerm3a_init, NULL, nvr_at_close }, - { "[Socket 7 HX] Acer V35n", ROM_ACERV35N, "acerv35n", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerv35n_init, NULL, nvr_at_close }, - { "[Socket 7 HX] AOpen AP53", ROM_AP53, "ap53", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_ap53_init, NULL, nvr_at_close }, - { "[Socket 7 HX] ASUS P/I-P55T2P4", ROM_P55T2P4, "p55t2p4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_p55t2p4_init, NULL, nvr_at_close }, - { "[Socket 7 HX] SuperMicro Super P55T2S", ROM_P55T2S, "p55t2s", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 127, machine_at_p55t2s_init, NULL, nvr_at_close }, + { "[Socket 7 HX] Acer M3a", ROM_ACERM3A, "acerm3a", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerm3a_init, NULL }, + { "[Socket 7 HX] Acer V35n", ROM_ACERV35N, "acerv35n", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerv35n_init, NULL }, + { "[Socket 7 HX] AOpen AP53", ROM_AP53, "ap53", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_ap53_init, NULL }, + { "[Socket 7 HX] ASUS P/I-P55T2P4", ROM_P55T2P4, "p55t2p4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_p55t2p4_init, NULL }, + { "[Socket 7 HX] SuperMicro Super P55T2S", ROM_P55T2S, "p55t2s", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 127, machine_at_p55t2s_init, NULL }, - { "[Socket 7 VX] ASUS P/I-P55TVP4", ROM_P55TVP4, "p55tvp4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p55tvp4_init, NULL, nvr_at_close }, - { "[Socket 7 VX] Award 430VX PCI", ROM_430VX, "430vx", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_i430vx_init, NULL, nvr_at_close }, - { "[Socket 7 VX] Epox P55-VA", ROM_P55VA, "p55va", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p55va_init, NULL, nvr_at_close }, + { "[Socket 7 VX] ASUS P/I-P55TVP4", ROM_P55TVP4, "p55tvp4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p55tvp4_init, NULL }, + { "[Socket 7 VX] Award 430VX PCI", ROM_430VX, "430vx", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_i430vx_init, NULL }, + { "[Socket 7 VX] Epox P55-VA", ROM_P55VA, "p55va", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86},{"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p55va_init, NULL }, #else - { "[Socket 5 NX] Intel Premiere/PCI II", ROM_PLATO, "plato", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_plato_init, NULL, nvr_at_close }, + { "[Socket 5 NX] Intel Premiere/PCI II", ROM_PLATO, "plato", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_plato_init, NULL }, - { "[Socket 5 FX] ASUS P/I-P54TP4XE", ROM_P54TP4XE, "p54tp4xe", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_p54tp4xe_init, NULL, nvr_at_close }, - { "[Socket 5 FX] Intel Advanced/EV", ROM_ENDEAVOR, "endeavor", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_endeavor_init, at_endeavor_get_device, nvr_at_close }, - { "[Socket 5 FX] Intel Advanced/ZP", ROM_ZAPPA, "zappa", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_zappa_init, NULL, nvr_at_close }, - { "[Socket 5 FX] PC Partner MB500N", ROM_MB500N, "mb500n", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_mb500n_init, NULL, nvr_at_close }, - { "[Socket 5 FX] President Award 430FX PCI",ROM_PRESIDENT, "president", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_president_init, NULL, nvr_at_close }, + { "[Socket 5 FX] ASUS P/I-P54TP4XE", ROM_P54TP4XE, "p54tp4xe", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_p54tp4xe_init, NULL }, + { "[Socket 5 FX] Intel Advanced/ZP", ROM_ZAPPA, "zappa", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_zappa_init, NULL }, + { "[Socket 5 FX] PC Partner MB500N", ROM_MB500N, "mb500n", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_mb500n_init, NULL }, + { "[Socket 5 FX] President Award 430FX PCI",ROM_PRESIDENT, "president", {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_president_init, NULL }, - { "[Socket 7 FX] Intel Advanced/ATX", ROM_THOR, "thor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL, nvr_at_close }, - { "[Socket 7 FX] MR Intel Advanced/ATX", ROM_MRTHOR, "mrthor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL, nvr_at_close }, + { "[Socket 7 FX] Intel Advanced/ATX", ROM_THOR, "thor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL }, +#if defined(DEV_BRANCH) && defined(USE_MRTHOR) + { "[Socket 7 FX] MR Intel Advanced/ATX", ROM_MRTHOR, "mrthor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL }, +#endif + { "[Socket 7 FX] Intel Advanced/EV", ROM_ENDEAVOR, "endeavor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_endeavor_init, at_endeavor_get_device }, + { "[Socket 7 FX] Packard Bell PB640", ROM_PB640, "pb640", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_pb640_init, NULL }, - { "[Socket 7 HX] Acer M3a", ROM_ACERM3A, "acerm3a", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerm3a_init, NULL, nvr_at_close }, - { "[Socket 7 HX] Acer V35n", ROM_ACERV35N, "acerv35n", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerv35n_init, NULL, nvr_at_close }, - { "[Socket 7 HX] AOpen AP53", ROM_AP53, "ap53", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_ap53_init, NULL, nvr_at_close }, - { "[Socket 7 HX] ASUS P/I-P55T2P4", ROM_P55T2P4, "p55t2p4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_p55t2p4_init, NULL, nvr_at_close }, - { "[Socket 7 HX] SuperMicro Super P55T2S", ROM_P55T2S, "p55t2s", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 127, machine_at_p55t2s_init, NULL, nvr_at_close }, + { "[Socket 7 HX] Acer M3a", ROM_ACERM3A, "acerm3a", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerm3a_init, NULL }, + { "[Socket 7 HX] Acer V35n", ROM_ACERV35N, "acerv35n", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerv35n_init, NULL }, + { "[Socket 7 HX] AOpen AP53", ROM_AP53, "ap53", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_ap53_init, NULL }, + { "[Socket 7 HX] ASUS P/I-P55T2P4", ROM_P55T2P4, "p55t2p4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_p55t2p4_init, NULL }, + { "[Socket 7 HX] SuperMicro Super P55T2S", ROM_P55T2S, "p55t2s", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 127, machine_at_p55t2s_init, NULL }, - { "[Socket 7 VX] ASUS P/I-P55TVP4", ROM_P55TVP4, "p55tvp4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p55tvp4_init, NULL, nvr_at_close }, - { "[Socket 7 VX] Award 430VX PCI", ROM_430VX, "430vx", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_i430vx_init, NULL, nvr_at_close }, - { "[Socket 7 VX] Epox P55-VA", ROM_P55VA, "p55va", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p55va_init, NULL, nvr_at_close }, + { "[Socket 7 VX] ASUS P/I-P55TVP4", ROM_P55TVP4, "p55tvp4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p55tvp4_init, NULL }, + { "[Socket 7 VX] Award 430VX PCI", ROM_430VX, "430vx", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_i430vx_init, NULL }, + { "[Socket 7 VX] Epox P55-VA", ROM_P55VA, "p55va", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p55va_init, NULL }, #endif #if defined(DEV_BRANCH) && defined(USE_I686) - { "[Socket 8 FX] Tyan Titan-Pro AT", ROM_440FX, "440fx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_i440fx_init, NULL, nvr_at_close }, - { "[Socket 8 FX] Tyan Titan-Pro ATX", ROM_S1668, "tpatx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_s1668_init, NULL, nvr_at_close }, + { "[Socket 8 FX] Tyan Titan-Pro AT", ROM_440FX, "440fx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_i440fx_init, NULL }, + { "[Socket 8 FX] Tyan Titan-Pro ATX", ROM_S1668, "tpatx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_s1668_init, NULL }, #endif - { "", -1, "", {{"", 0}, {"", 0}, {"", 0}}, 0,0,0,0, 0 } + { "", -1, "", {{"", 0}, {"", 0}, {"", 0}}, 0,0,0,0, 0 } }; @@ -267,11 +264,3 @@ machine_get_machine_from_internal_name(char *s) return(0); } - - -void -machine_close(void) -{ - if (machines[machine].nvr_close) - machines[machine].nvr_close(); -} diff --git a/src/mcr.c b/src/mcr.c index b2be96640..ddd2dd784 100644 --- a/src/mcr.c +++ b/src/mcr.c @@ -24,7 +24,6 @@ void resetmcr(void) void writemcr(uint16_t addr, uint8_t val) { - pclog("MCR: write %04X %02X %04X:%04X\n",addr,val,CS,cpu_state.pc); switch (addr) { case 0x22: diff --git a/src/mem.c b/src/mem.c index bd19461f7..cad04677b 100644 --- a/src/mem.c +++ b/src/mem.c @@ -12,7 +12,7 @@ * the DYNAMIC_TABLES=1 enables this. Will eventually go * away, either way... * - * Version: @(#)mem.c 1.0.9 2018/03/19 + * Version: @(#)mem.c 1.0.10 2018/04/29 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,11 +40,13 @@ * Boston, MA 02111-1307 * USA. */ +#include #include #include #include #include #include +#define HAVE_STDARG_H #include "86box.h" #include "cpu/cpu.h" #include "cpu/x86_ops.h" @@ -149,6 +151,26 @@ static uint8_t ff_pccache[4] = { 0xff, 0xff, 0xff, 0xff }; static int port_92_reg = 0; +#ifdef ENABLE_MEM_LOG +int mem_do_log = ENABLE_MEM_LOG; +#endif + + +static void +mem_log(const char *format, ...) +{ +#ifdef ENABLE_MEM_LOG + va_list ap; + + if (mem_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + void resetreadlookup(void) { @@ -156,7 +178,7 @@ resetreadlookup(void) /* This is NULL after app startup, when mem_init() has not yet run. */ #if DYNAMIC_TABLES -pclog("MEM: reset_lookup: pages=%08lx, lookup=%08lx, pages_sz=%i\n", pages, page_lookup, pages_sz); +mem_log("MEM: reset_lookup: pages=%08lx, lookup=%08lx, pages_sz=%i\n", pages, page_lookup, pages_sz); #endif /* Initialize the page lookup table. */ @@ -193,11 +215,11 @@ flushmmucache(void) int c; for (c = 0; c < 256; c++) { - if (readlookup[c] != 0xffffffff) { + if (readlookup[c] != (int) 0xffffffff) { readlookup2[readlookup[c]] = -1; readlookup[c] = 0xffffffff; } - if (writelookup[c] != 0xffffffff) { + if (writelookup[c] != (int) 0xffffffff) { page_lookup[writelookup[c]] = NULL; writelookup2[writelookup[c]] = -1; writelookup[c] = 0xffffffff; @@ -220,11 +242,11 @@ flushmmucache_nopc(void) int c; for (c = 0; c < 256; c++) { - if (readlookup[c] != 0xffffffff) { + if (readlookup[c] != (int) 0xffffffff) { readlookup2[readlookup[c]] = -1; readlookup[c] = 0xffffffff; } - if (writelookup[c] != 0xffffffff) { + if (writelookup[c] != (int) 0xffffffff) { page_lookup[writelookup[c]] = NULL; writelookup2[writelookup[c]] = -1; writelookup[c] = 0xffffffff; @@ -239,11 +261,11 @@ flushmmucache_cr3(void) int c; for (c = 0; c < 256; c++) { - if (readlookup[c] != 0xffffffff) { + if (readlookup[c] != (int) 0xffffffff) { readlookup2[readlookup[c]] = -1; readlookup[c] = 0xffffffff; } - if (writelookup[c] != 0xffffffff) { + if (writelookup[c] != (int) 0xffffffff) { page_lookup[writelookup[c]] = NULL; writelookup2[writelookup[c]] = -1; writelookup[c] = 0xffffffff; @@ -259,7 +281,7 @@ mem_flush_write_page(uint32_t addr, uint32_t virt) int c; for (c = 0; c < 256; c++) { - if (writelookup[c] != 0xffffffff) { + if (writelookup[c] != (int) 0xffffffff) { uintptr_t target = (uintptr_t)&ram[(uintptr_t)(addr & ~0xfff) - (virt & ~0xfff)]; if (writelookup2[writelookup[c]] == target || page_lookup[writelookup[c]] == page_target) { @@ -403,9 +425,9 @@ addreadlookup(uint32_t virt, uint32_t phys) { if (virt == 0xffffffff) return; - if (readlookup2[virt>>12] != -1) return; + if (readlookup2[virt>>12] != (uintptr_t) -1) return; - if (readlookup[readlnext] != 0xffffffff) + if (readlookup[readlnext] != (int) 0xffffffff) readlookup2[readlookup[readlnext]] = -1; readlookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; @@ -479,7 +501,7 @@ getpccache(uint32_t a) return &_mem_exec[a >> 14][(uintptr_t)(a & 0x3000) - (uintptr_t)(a2 & ~0xfff)]; } - pclog("Bad getpccache %08X\n", a); + mem_log("Bad getpccache %08X\n", a); #if FIXME return &ff_array[0-(uintptr_t)(a2 & ~0xfff)]; @@ -496,7 +518,7 @@ readmembl(uint32_t addr) if (addr < 0x100000 && ram_mapped_addr[addr >> 14]) { addr = (ram_mapped_addr[addr >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr : (ram_mapped_addr[addr >> 14] & ~0x3fff) + (addr & 0x3fff); - if(addr < mem_size * 1024) return ram[addr]; + if(addr < (uint32_t) (mem_size * 1024)) return ram[addr]; return 0xff; } @@ -520,7 +542,7 @@ writemembl(uint32_t addr, uint8_t val) if (addr < 0x100000 && ram_mapped_addr[addr >> 14]) { addr = (ram_mapped_addr[addr >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr : (ram_mapped_addr[addr >> 14] & ~0x3fff) + (addr & 0x3fff); - if (addr < mem_size * 1024) + if (addr < (uint32_t) (mem_size * 1024)) ram[addr] = val; return; } @@ -545,7 +567,7 @@ writemembl(uint32_t addr, uint8_t val) uint8_t readmemb386l(uint32_t seg, uint32_t addr) { - if (seg == -1) { + if (seg == (uint32_t) -1) { x86gpf("NULL segment", 0); return -1; @@ -554,7 +576,7 @@ readmemb386l(uint32_t seg, uint32_t addr) mem_logical_addr = addr = addr + seg; if (addr < 0x100000 && ram_mapped_addr[addr >> 14]) { addr = (ram_mapped_addr[addr >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr : (ram_mapped_addr[addr >> 14] & ~0x3fff) + (addr & 0x3fff); - if (addr < mem_size * 1024) + if (addr < (uint32_t) (mem_size * 1024)) return ram[addr]; return 0xff; } @@ -577,7 +599,7 @@ readmemb386l(uint32_t seg, uint32_t addr) void writememb386l(uint32_t seg, uint32_t addr, uint8_t val) { - if (seg == -1) { + if (seg == (uint32_t) -1) { x86gpf("NULL segment", 0); return; } @@ -585,7 +607,7 @@ writememb386l(uint32_t seg, uint32_t addr, uint8_t val) mem_logical_addr = addr = addr + seg; if (addr < 0x100000 && ram_mapped_addr[addr >> 14]) { addr = (ram_mapped_addr[addr >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr : (ram_mapped_addr[addr >> 14] & ~0x3fff) + (addr & 0x3fff); - if (addr < mem_size * 1024) + if (addr < (uint32_t) (mem_size * 1024)) ram[addr] = val; return; } @@ -613,7 +635,7 @@ readmemwl(uint32_t seg, uint32_t addr) { uint32_t addr2 = mem_logical_addr = seg + addr; - if (seg == -1) { + if (seg == (uint32_t) -1) { x86gpf("NULL segment", 0); return -1; } @@ -626,16 +648,16 @@ readmemwl(uint32_t seg, uint32_t addr) if (mmutranslate_read(addr2) == 0xffffffff) return 0xffff; if (mmutranslate_read(addr2+1) == 0xffffffff) return 0xffff; } - if (is386) return readmemb386l(seg,addr)|(readmemb386l(seg,addr+1)<<8); - else return readmembl(seg+addr)|(readmembl(seg+addr+1)<<8); + if (is386) return readmemb386l(seg,addr)|(((uint16_t) readmemb386l(seg,addr+1))<<8); + else return readmembl(seg+addr)|(((uint16_t) readmembl(seg+addr+1))<<8); } - else if (readlookup2[addr2 >> 12] != -1) + else if (readlookup2[addr2 >> 12] != (uintptr_t) -1) return *(uint16_t *)(readlookup2[addr2 >> 12] + addr2); } if (addr2 < 0x100000 && ram_mapped_addr[addr2 >> 14]) { addr = (ram_mapped_addr[addr2 >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr2 : (ram_mapped_addr[addr2 >> 14] & ~0x3fff) + (addr2 & 0x3fff); - if (addr < mem_size * 1024) + if (addr < (uint32_t) (mem_size * 1024)) return *((uint16_t *)&ram[addr]); return 0xffff; } @@ -653,9 +675,11 @@ readmemwl(uint32_t seg, uint32_t addr) if (_mem_read_b[addr2 >> 14]) { if (AT) - return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[(addr2 + 1) >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14]) << 8); + return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | + ((uint16_t) (_mem_read_b[(addr2 + 1) >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14])) << 8); else - return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[(seg + ((addr + 1) & 0xffff)) >> 14](seg + ((addr + 1) & 0xffff), _mem_priv_r[addr2 >> 14]) << 8); + return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | + ((uint16_t) (_mem_read_b[(seg + ((addr + 1) & 0xffff)) >> 14](seg + ((addr + 1) & 0xffff), _mem_priv_r[addr2 >> 14])) << 8); } return 0xffff; @@ -667,7 +691,7 @@ writememwl(uint32_t seg, uint32_t addr, uint16_t val) { uint32_t addr2 = mem_logical_addr = seg + addr; - if (seg == -1) { + if (seg == (uint32_t) -1) { x86gpf("NULL segment", 0); return; } @@ -695,7 +719,7 @@ writememwl(uint32_t seg, uint32_t addr, uint16_t val) writemembl(seg+addr+1,val>>8); } return; - } else if (writelookup2[addr2 >> 12] != -1) { + } else if (writelookup2[addr2 >> 12] != (uintptr_t) -1) { *(uint16_t *)(writelookup2[addr2 >> 12] + addr2) = val; return; } @@ -715,7 +739,7 @@ writememwl(uint32_t seg, uint32_t addr, uint16_t val) #if 0 if (addr2 >= 0xa0000 && addr2 < 0xc0000) - pclog("writememwl %08X %02X\n", addr2, val); + mem_log("writememwl %08X %02X\n", addr2, val); #endif if (_mem_write_w[addr2 >> 14]) { @@ -736,7 +760,7 @@ readmemll(uint32_t seg, uint32_t addr) { uint32_t addr2 = mem_logical_addr = seg + addr; - if (seg == -1) { + if (seg == (uint32_t) -1) { x86gpf("NULL segment", 0); return -1; } @@ -757,7 +781,7 @@ readmemll(uint32_t seg, uint32_t addr) if (mmutranslate_read(addr2+3) == 0xffffffff) return 0xffffffff; } return readmemwl(seg,addr)|(readmemwl(seg,addr+2)<<16); - } else if (readlookup2[addr2 >> 12] != -1) + } else if (readlookup2[addr2 >> 12] != (uintptr_t) -1) return *(uint32_t *)(readlookup2[addr2 >> 12] + addr2); } @@ -773,10 +797,14 @@ readmemll(uint32_t seg, uint32_t addr) return _mem_read_l[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]); if (_mem_read_w[addr2 >> 14]) - return _mem_read_w[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_w[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14]) << 16); + return _mem_read_w[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | + ((uint32_t) (_mem_read_w[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14])) << 16); if (_mem_read_b[addr2 >> 14]) - return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[addr2 >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14]) << 8) | (_mem_read_b[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14]) << 16) | (_mem_read_b[addr2 >> 14](addr2 + 3, _mem_priv_r[addr2 >> 14]) << 24); + return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | + ((uint32_t) (_mem_read_b[addr2 >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14])) << 8) | + ((uint32_t) (_mem_read_b[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14])) << 16) | + ((uint32_t) (_mem_read_b[addr2 >> 14](addr2 + 3, _mem_priv_r[addr2 >> 14])) << 24); return 0xffffffff; } @@ -787,7 +815,7 @@ writememll(uint32_t seg, uint32_t addr, uint32_t val) { uint32_t addr2 = mem_logical_addr = seg + addr; - if (seg == -1) { + if (seg == (uint32_t) -1) { x86gpf("NULL segment", 0); return; } @@ -810,7 +838,7 @@ writememll(uint32_t seg, uint32_t addr, uint32_t val) writememwl(seg,addr,val); writememwl(seg,addr+2,val>>16); return; - } else if (writelookup2[addr2 >> 12] != -1) { + } else if (writelookup2[addr2 >> 12] != (uintptr_t) -1) { *(uint32_t *)(writelookup2[addr2 >> 12] + addr2) = val; return; } @@ -852,7 +880,7 @@ readmemql(uint32_t seg, uint32_t addr) { uint32_t addr2 = mem_logical_addr = seg + addr; - if (seg == -1) { + if (seg == (uint32_t) -1) { x86gpf("NULL segment", 0); return -1; } @@ -872,7 +900,7 @@ readmemql(uint32_t seg, uint32_t addr) if (mmutranslate_read(addr2+7) == 0xffffffff) return 0xffffffff; } return readmemll(seg,addr)|((uint64_t)readmemll(seg,addr+4)<<32); - } else if (readlookup2[addr2 >> 12] != -1) + } else if (readlookup2[addr2 >> 12] != (uintptr_t) -1) return *(uint64_t *)(readlookup2[addr2 >> 12] + addr2); } @@ -897,7 +925,7 @@ writememql(uint32_t seg, uint32_t addr, uint64_t val) { uint32_t addr2 = mem_logical_addr = seg + addr; - if (seg == -1) { + if (seg == (uint32_t) -1) { x86gpf("NULL segment", 0); return; } @@ -919,7 +947,7 @@ writememql(uint32_t seg, uint32_t addr, uint64_t val) writememll(seg, addr, val); writememll(seg, addr+4, val >> 32); return; - } else if (writelookup2[addr2 >> 12] != -1) { + } else if (writelookup2[addr2 >> 12] != (uintptr_t) -1) { *(uint64_t *)(writelookup2[addr2 >> 12] + addr2) = val; return; } @@ -1278,6 +1306,7 @@ mem_mapping_recalc(uint64_t base, uint64_t size) _mem_read_b[c >> 14] = NULL; _mem_read_w[c >> 14] = NULL; _mem_read_l[c >> 14] = NULL; + _mem_exec[c >> 14] = NULL; _mem_priv_r[c >> 14] = NULL; _mem_mapping_r[c >> 14] = NULL; _mem_write_b[c >> 14] = NULL; @@ -1611,7 +1640,7 @@ mem_reset(void) * We only do this if the size of the page table has changed. */ #if DYNAMIC_TABLES -pclog("MEM: reset: previous pages=%08lx, pages_sz=%i\n", pages, pages_sz); +mem_log("MEM: reset: previous pages=%08lx, pages_sz=%i\n", pages, pages_sz); #endif if (pages_sz != m) { pages_sz = m; @@ -1621,7 +1650,7 @@ pclog("MEM: reset: previous pages=%08lx, pages_sz=%i\n", pages, pages_sz); } pages = (page_t *)malloc(m*sizeof(page_t)); #if DYNAMIC_TABLES -pclog("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz); +mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz); #endif #if DYNAMIC_TABLES @@ -1760,7 +1789,7 @@ mem_init(void) static void mem_remap_top(int max_size) { - int c; + uint32_t c; if (mem_size > 640) { uint32_t start = (mem_size >= 1024) ? mem_size : 1024; @@ -1799,7 +1828,7 @@ mem_remap_top_384k(void) void mem_reset_page_blocks(void) { - int c; + uint32_t c; if (pages == NULL) return; diff --git a/src/memregs.c b/src/memregs.c index 2c13aadbb..f1aae4ac8 100644 --- a/src/memregs.c +++ b/src/memregs.c @@ -9,16 +9,18 @@ * Emulation of the memory I/O scratch registers on ports 0xE1 * and 0xE2, used by just about any emulated machine. * - * Version: @(#)memregs.c 1.0.5 2017/12/28 + * Version: @(#)memregs.c 1.0.6 2018/04/29 * * Author: Miran Grca, * - * Copyright 2016-2017 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ +#include #include #include #include #include +#define HAVE_STDARG_H #include "86box.h" #include "io.h" #include "memregs.h" @@ -51,15 +53,11 @@ uint8_t memregs_read(uint16_t port, void *priv) void memregs_init(void) { - /* pclog("Memory Registers Init\n"); */ - io_sethandler(0x00e1, 0x0002, memregs_read, NULL, NULL, memregs_write, NULL, NULL, NULL); } void powermate_memregs_init(void) { - /* pclog("Memory Registers Init\n"); */ - io_sethandler(0x00ed, 0x0002, memregs_read, NULL, NULL, memregs_write, NULL, NULL, NULL); io_sethandler(0xffff, 0x0001, memregs_read, NULL, NULL, memregs_write, NULL, NULL, NULL); } diff --git a/src/mouse.c b/src/mouse.c index 89fe585ea..64364b81e 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -11,7 +11,7 @@ * TODO: Add the Genius bus- and serial mouse. * Remove the '3-button' flag from mouse types. * - * Version: @(#)mouse.c 1.0.25 2018/03/19 + * Version: @(#)mouse.c 1.0.27 2018/04/29 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -19,10 +19,12 @@ * Copyright 2016-2018 Miran Grca. * Copyright 2017,2018 Fred N. van Kempen. */ +#include #include #include #include #include +#define HAVE_STDARG_H #include "86box.h" #include "device.h" #include "mouse.h" @@ -45,14 +47,14 @@ static const device_t mouse_none_device = { "None", 0, MOUSE_TYPE_NONE, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; static const device_t mouse_internal_device = { "Internal Mouse", 0, MOUSE_TYPE_INTERNAL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; @@ -78,6 +80,26 @@ static int mouse_nbut; static int (*mouse_dev_poll)(); +#ifdef ENABLE_MOUSE_LOG +int mouse_do_log = ENABLE_MOUSE_LOG; +#endif + + +static void +mouse_log(const char *format, ...) +{ +#ifdef ENABLE_MOUSE_LOG + va_list ap; + + if (mouse_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + /* Initialize the mouse module. */ void mouse_init(void) @@ -112,7 +134,7 @@ mouse_reset(void) if ((mouse_curr != NULL) || (mouse_type == MOUSE_TYPE_INTERNAL)) return; /* Mouse already initialized. */ - pclog("MOUSE: reset(type=%d, '%s')\n", + mouse_log("MOUSE: reset(type=%d, '%s')\n", mouse_type, mouse_devices[mouse_type].device->name); /* Clear local data. */ diff --git a/src/mouse.h b/src/mouse.h index 4d402fa0a..341646178 100644 --- a/src/mouse.h +++ b/src/mouse.h @@ -73,6 +73,8 @@ extern int mouse_get_type(int mouse); extern int mouse_get_ndev(void); extern int mouse_get_buttons(void); +extern void mouse_clear_data(void *priv); + #ifdef __cplusplus } #endif diff --git a/src/mouse_bus.c b/src/mouse_bus.c index ebd81a6df..e60a7063b 100644 --- a/src/mouse_bus.c +++ b/src/mouse_bus.c @@ -14,53 +14,60 @@ * although alike enough to be handled in the same driver, they * are not the same. * - * This code is based on my Minix driver for the Logitech(-mode) - * interface. Although that driver blindly took IRQ5, the board - * seems to be able to tell the driver what IRQ it is set for. - * When testing on MS-DOS (6.22), the 'mouse.exe' driver did not - * want to start, and only after disassembling it and inspecting - * the code it was discovered that driver actually does use the - * IRQ reporting feature. In a really, really weird way, too: it - * sets up the board, and then reads the CTRL register which is - * supposed to return that IRQ value. Depending on whether or - * not the FREEZE bit is set, it has to return either the two's - * complemented (negated) value, or (if clear) just the value. - * The mouse.com driver reads both values 10,000 times, and - * then makes up its mind. Maybe an effort to 'debounce' the - * reading of the DIP switches? Oh-well. + * NOTES: Ported from Bochs with extensive modifications per testing + * of the real hardware, testing of drivers, and the old code. * - * NOTES: Verified with: - * AMI WinBIOS 486 (5A, no IRQ detect, OK, IRQ5 only) - * Microsoft Mouse.com V2.00 (DOS V6.22, 5A, OK) - * Microsoft Mouse.exe V9.1 (DOS V6.22, A5, OK) - * Logitech LMouse.com V6.02 (DOS V6.22) - * Logitech LMouse.com V6.43 (DOS V6.22) - * Microsoft WfW V3.11 on DOS V6.22 - * GEOS V1.0 (OK, IRQ5 only) - * GEOS V2.0 (OK, IRQ5 only) - * Microsoft Windows 95 OSR2 - * Microsoft Windows 98 SE + * Logitech Bus Mouse verified with: + * Logitech LMouse.com 3.12 + * Logitech LMouse.com 3.30 + * Logitech LMouse.com 3.41 + * Logitech LMouse.com 3.42 + * Logitech LMouse.com 4.00 + * Logitech LMouse.com 5.00 + * Logitech LMouse.com 6.00 + * Logitech LMouse.com 6.02 Beta + * Logitech LMouse.com 6.02 + * Logitech LMouse.com 6.12 + * Logitech LMouse.com 6.20 + * Logitech LMouse.com 6.23 + * Logitech LMouse.com 6.30 + * Logitech LMouse.com 6.31E + * Logitech LMouse.com 6.34 + * Logitech Mouse.exe 6.40 + * Logitech Mouse.exe 6.41 + * Logitech Mouse.exe 6.44 + * Logitech Mouse.exe 6.46 + * Logitech Mouse.exe 6.50 + * Microsoft Mouse.com 2.00 + * Microsoft Mouse.sys 3.00 + * Microsoft Windows 1.00 DR5 + * Microsoft Windows 3.10.026 * Microsoft Windows NT 3.1 - * Microsoft Windows NT 3.51 + * Microsoft Windows 95 * - * The polling frequency for InPort controllers has to - * be changed to programmable. Microsoft uses 30Hz, - * but ATIXL ports are programmable 30-200Hz. + * InPort verified with: + * Logitech LMouse.com 6.12 + * Logitech LMouse.com 6.41 + * Microsoft Windows NT 3.1 + * Microsoft Windows 98 SE * - * Based on an early driver for MINIX 1.5. + * Version: @(#)mouse_bus.c 1.0.0 2018/05/23 * - * Version: @(#)mouse_bus.c 1.0.32 2018/03/18 - * - * Authors: Fred N. van Kempen, + * Authors: Miran Grca, + * Fred N. van Kempen, * + * Copyright 200?-2018 Bochs. + * Copyright 2017,2018 Miran Grca. * Copyright 1989-2018 Fred N. van Kempen. */ +#include +#include #include #include #include #include #include -#include +#define HAVE_STDARG_H #include "86box.h" #include "config.h" #include "io.h" @@ -68,369 +75,228 @@ #include "timer.h" #include "device.h" #include "mouse.h" +#include "random.h" +#define IRQ_MASK ((1 << 5) >> dev->irq) -#define MOUSE_PORT 0x023c /* default */ -#define MOUSE_IRQ 5 /* default */ -#define MOUSE_BUTTONS 2 /* default */ -#define MOUSE_DEBUG 0 +/* MS Inport Bus Mouse Adapter */ +#define INP_PORT_CONTROL 0x0000 +#define INP_PORT_DATA 0x0001 +#define INP_PORT_SIGNATURE 0x0002 +#define INP_PORT_CONFIG 0x0003 + +#define INP_CTRL_READ_BUTTONS 0x00 +#define INP_CTRL_READ_X 0x01 +#define INP_CTRL_READ_Y 0x02 +#define INP_CTRL_COMMAND 0x07 +#define INP_CTRL_RAISE_IRQ 0x16 +#define INP_CTRL_RESET 0x80 + +#define INP_HOLD_COUNTER (1 << 5) +#define INP_ENABLE_TIMER_IRQ (1 << 4) +#define INP_ENABLE_DATA_IRQ (1 << 3) +#define INP_PERIOD_MASK 0x07 + +/* MS/Logictech Standard Bus Mouse Adapter */ +#define BUSM_PORT_DATA 0x0000 +#define BUSM_PORT_SIGNATURE 0x0001 +#define BUSM_PORT_CONTROL 0x0002 +#define BUSM_PORT_CONFIG 0x0003 + +#define HOLD_COUNTER (1 << 7) +#define READ_X (0 << 6) +#define READ_Y (1 << 6) +#define READ_LOW (0 << 5) +#define READ_HIGH (1 << 5) +#define DISABLE_IRQ (1 << 4) + +#define DEVICE_ACTIVE (1 << 7) + +#define READ_X_LOW (READ_X | READ_LOW) +#define READ_X_HIGH (READ_X | READ_HIGH) +#define READ_Y_LOW (READ_Y | READ_LOW) +#define READ_Y_HIGH (READ_Y | READ_HIGH) + +#define FLAG_INPORT (1 << 0) +#define FLAG_ENABLED (1 << 1) +#define FLAG_HOLD (1 << 2) +#define FLAG_TIMER_INT (1 << 3) +#define FLAG_DATA_INT (1 << 4) + +static const double periods[4] = { 30.0, 50.0, 100.0, 200.0 }; /* Our mouse device. */ typedef struct mouse { - const char *name; /* name of this device */ - int8_t type; /* type of this device */ - int8_t irq; /* IRQ channel to use */ - uint8_t flags; /* device flags */ + int base, irq, bn, flags, + mouse_delayed_dx, mouse_delayed_dy, + mouse_buttons, + current_x, current_y, + current_b, + control_val, mouse_buttons_last, + config_val, sig_val, + command_val, toggle_counter; - uint8_t r_magic, /* MAGIC register */ - r_ctrl, /* CONTROL register (WR) */ - r_conf, /* CONFIG register */ - r_cmd; /* (MS) current command */ + double period; - uint8_t seq; /* general counter */ - - uint8_t but, /* current mouse status */ - but_last; - uint8_t cur_but; - int8_t x, y; - int x_delay, - y_delay; - uint8_t need_upd; - uint8_t irq_num; - - int64_t timer; /* mouse event timer */ - - uint8_t (*read)(struct mouse *, uint16_t); - void (*write)(struct mouse *, uint16_t, uint8_t); + int64_t timer_enabled, timer; /* mouse event timer */ } mouse_t; -#define FLAG_INPORT 0x80 /* device is MS InPort */ -#define FLAG_3BTN 0x20 /* enable 3-button mode */ -#define FLAG_SCALED 0x10 /* enable delta scaling */ -#define FLAG_INTR 0x04 /* dev can send interrupts */ -#define FLAG_FROZEN 0x02 /* do not update counters */ -#define FLAG_ENABLED 0x01 /* dev is enabled for use */ -/* Definitions for Logitech. */ -#define LTMOUSE_DATA 0 /* DATA register */ -#define LTMOUSE_MAGIC 1 /* signature magic register */ -# define LTMAGIC_BYTE1 0xa5 /* most drivers use this */ -# define LTMAGIC_BYTE2 0x5a /* some drivers use this */ -#define LTMOUSE_CTRL 2 /* CTRL register */ -# define LTCTRL_FREEZE 0x80 /* do not sample when set */ -# define LTCTRL_RD_Y_HI 0x60 -# define LTCTRL_RD_Y_LO 0x40 -# define LTCTRL_RD_X_HI 0x20 -# define LTCTRL_RD_X_LO 0x00 -# define LTCTRL_RD_MASK 0x60 -# define LTCTRL_IDIS 0x10 -# define LTCTRL_IENB 0x00 -#define LTMOUSE_CONFIG 3 /* CONFIG register */ - -/* Definitions for Microsoft. */ -#define MSMOUSE_CTRL 0 /* CTRL register */ -# define MSCTRL_RESET 0x80 /* reset controller */ -# define MSCTRL_FREEZE 0x20 /* HOLD- freeze data */ -# define MSCTRL_IENB_A 0x08 /* ATIXL intr enable */ -# define MSCTRL_IENB_M 0x01 /* MS intr enable */ -# define MSCTRL_COMMAND 0x07 -# define MSCTRL_RD_Y 0x02 -# define MSCTRL_RD_X 0x01 -# define MSCTRL_RD_BUT 0x00 -#define MSMOUSE_DATA 1 /* DATA register */ -# define MSDATA_IRQ 0x16 -# define MSDATA_BASE 0x10 /* MS InPort: 30Hz */ -# define MSDATA_HZ30 0x01 /* ATIXL 30Hz */ -# define MSDATA_HZ50 0x02 /* ATIXL 50Hz */ -# define MSDATA_HZ100 0x03 /* ATIXL 100Hz */ -# define MSDATA_HZ200 0x04 /* ATIXL 200Hz */ -#define MSMOUSE_MAGIC 2 /* MAGIC register */ -# define MAGIC_MSBYTE1 0xde /* indicates MS InPort */ -// # define MAGIC_MSBYTE2 0x12 -# define MAGIC_MSBYTE2 0x22 /* According to the Bochs code, this sould be 0x22, not 0x12. */ -#define MSMOUSE_CONFIG 3 /* CONFIG register */ - - -/* Reset the controller state. */ -static void -ms_reset(mouse_t *dev) -{ - dev->r_ctrl = 0x00; - dev->r_cmd = 0x00; - - dev->seq = 0; - - dev->x = dev->y = 0; - dev->but = 0x00; - - dev->flags &= 0xf0; - dev->flags |= (FLAG_INTR | FLAG_ENABLED); - - dev->x_delay = dev->y_delay = 0; - dev->need_upd = 0; - - dev->cur_but = 0x00; -} +#ifdef ENABLE_MOUSE_BUS_LOG +int bm_do_log = ENABLE_MOUSE_BUS_LOG; +#endif static void -ms_update_data(mouse_t *dev) +bm_log(const char *format, ...) { - int delta_x, delta_y; +#ifdef ENABLE_MOUSE_BUS_LOG + va_list ap; - if (dev->x_delay > 127) { - delta_x = 127; - dev->x_delay -= 127; - } else if (dev->x_delay < -128) { - delta_x = -128; - dev->x_delay += 128; - } else { - delta_x = dev->x_delay; - dev->x_delay = 0; + if (bm_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); } - - if (dev->y_delay > 127) { - delta_y = 127; - dev->y_delay -= 127; - } else if (dev->y_delay < -128) { - delta_y = -128; - dev->x_delay += 128; - } else { - delta_y = dev->y_delay; - dev->y_delay = 0; - } - - if ((dev->x_delay == 0) && (dev->y_delay == 0)) - dev->need_upd = 0; - - dev->x = (int8_t) delta_x; - dev->y = (int8_t) delta_y; - dev->cur_but = dev->but; +#endif } -/* Handle a WRITE to an InPort register. */ -static void -ms_write(mouse_t *dev, uint16_t port, uint8_t val) -{ - switch (port) { - case MSMOUSE_CTRL: - switch (val) { - case MSCTRL_RESET: - ms_reset(dev); - break; - - case MSCTRL_COMMAND: - case MSCTRL_RD_BUT: - case MSCTRL_RD_X: - case MSCTRL_RD_Y: - dev->r_ctrl = val & 0x07; - break; - - case 0x87: - ms_reset(dev); - dev->r_ctrl = MSCTRL_COMMAND; - break; - } - break; - - case MSMOUSE_DATA: - picintc(1 << dev->irq); - if (val == MSDATA_IRQ) { - picint(1<irq); - } else switch (dev->r_ctrl) { - case MSCTRL_COMMAND: - if (val & MSCTRL_FREEZE) { - /* Hold the sampling. */ - ms_update_data(dev); - } else { - /* Reset current state. */ - picintc(1 << dev->irq); - } - - if (val & (MSCTRL_IENB_M | MSCTRL_IENB_A)) - dev->flags |= FLAG_INTR; - else - dev->flags &= ~FLAG_INTR; - - dev->r_cmd = val; - break; - - default: - break; - } - break; - - case MSMOUSE_MAGIC: - break; - - case MSMOUSE_CONFIG: - break; - } -} - - -/* Handle a READ from an InPort register. */ +/* Handle a READ operation from one of our registers. */ static uint8_t -ms_read(mouse_t *dev, uint16_t port) +lt_read(uint16_t port, void *priv) { - uint8_t ret = 0x00; + mouse_t *dev = (mouse_t *)priv; + uint8_t value = 0xff; - switch (port) { - case MSMOUSE_CTRL: - ret = dev->r_ctrl; - break; - - case MSMOUSE_DATA: - switch (dev->r_ctrl) { - case MSCTRL_RD_BUT: - ret = dev->cur_but; + switch (port & 0x03) { + case BUSM_PORT_DATA: + /* Testing and another source confirm that the buttons are + *ALWAYS* present, so I'm going to change this a bit. */ + switch (dev->control_val & 0x60) { + case READ_X_LOW: + value = dev->current_x & 0x0F; break; - - case MSCTRL_RD_X: - ret = dev->x; + case READ_X_HIGH: + value = (dev->current_x >> 4) & 0x0F; break; - - case MSCTRL_RD_Y: - ret = dev->y; + case READ_Y_LOW: + value = dev->current_y & 0x0F; break; - - case MSCTRL_COMMAND: - ret = dev->r_cmd; + case READ_Y_HIGH: + value = (dev->current_y >> 4) & 0x0F; break; + default: + bm_log("ERROR: Reading data port in unsupported mode 0x%02x\n", dev->control_val); } + value |= ((dev->current_b ^ 7) << 5); break; + case BUSM_PORT_SIGNATURE: + value = dev->sig_val; + break; + case BUSM_PORT_CONTROL: + value = dev->control_val; + dev->control_val |= 0x0F; - case MSMOUSE_MAGIC: - if (dev->seq & 0x01) - ret = MAGIC_MSBYTE2; + /* If the conditions are right, simulate the flakiness of the correct IRQ bit. */ + if (dev->flags & FLAG_TIMER_INT) + dev->control_val = (dev->control_val & ~IRQ_MASK) | (random_generate() & IRQ_MASK); + break; + case BUSM_PORT_CONFIG: + /* Read from config port returns control_val in the upper 4 bits when enabled, + possibly solid interrupt readout in the lower 4 bits, 0xff when not (at power-up). */ + if (dev->flags & FLAG_ENABLED) + return (dev->control_val | 0x0F) & ~IRQ_MASK; else - ret = MAGIC_MSBYTE1; - dev->seq ^= 1; - break; - - case MSMOUSE_CONFIG: - /* Not really present in real hardware. */ + return 0xff; break; } - return(ret); + bm_log("DEBUG: read from address 0x%04x, value = 0x%02x\n", port, value); + + return value; } -/* Reset the controller state. */ -static void -lt_reset(mouse_t *dev) +static uint8_t +ms_read(uint16_t port, void *priv) { - dev->r_magic = 0x00; - dev->r_ctrl = (LTCTRL_IENB); - dev->r_conf = 0x00; + mouse_t *dev = (mouse_t *)priv; + uint8_t value = 0xff; - dev->seq = 0; + switch (port & 0x03) { + case INP_PORT_CONTROL: + value = dev->control_val; + break; + case INP_PORT_DATA: + switch (dev->command_val) { + case INP_CTRL_READ_BUTTONS: + value = dev->current_b | 0x80; + break; + case INP_CTRL_READ_X: + value = dev->current_x; + break; + case INP_CTRL_READ_Y: + value = dev->current_y; + break; + case INP_CTRL_COMMAND: + value = dev->control_val; + break; + default: + bm_log("ERROR: Reading data port in unsupported mode 0x%02x\n", dev->control_val); + } + break; + case INP_PORT_SIGNATURE: + if (dev->toggle_counter) + value = 0x12; + else + value = 0xDE; + dev->toggle_counter ^= 1; + break; + case INP_PORT_CONFIG: + bm_log("ERROR: Unsupported read from port 0x%04x\n", port); + break; + } - dev->x = dev->y = 0; - dev->but = 0x00; + bm_log("DEBUG: read from address 0x%04x, value = 0x%02x\n", port, value); - dev->flags &= 0xf0; - dev->flags |= FLAG_INTR; - - dev->irq_num = 0; + return value; } -/* Called at 30hz */ +/* Handle a WRITE operation to one of our registers. */ static void -bm_timer(void *priv) +lt_write(uint16_t port, uint8_t val, void *priv) { mouse_t *dev = (mouse_t *)priv; - if (dev->flags & FLAG_INPORT) { - dev->timer = ((1000000LL * TIMER_USEC) / 30LL); + bm_log("DEBUG: write to address 0x%04x, value = 0x%02x\n", port, val); - if ((dev->flags & FLAG_INTR) && dev->need_upd) { - picint(1 << dev->irq); - /* pclog("IRQ %i raised\n", dev->irq); */ - } - } else { - picint(1 << dev->irq); - - if (dev->irq_num == 5) { - /* pclog("5th IRQ, enabling mouse...\n"); */ - lt_reset(dev); - dev->flags |= FLAG_ENABLED; - } - - if (dev->irq_num == 4) { - /* pclog("4th IRQ, going for the 5th...\n"); */ - dev->irq_num++; - dev->timer = ((1000000LL * TIMER_USEC) / 30LL); - } else { - /* pclog("IRQ before the 4th, disabling timer...\n"); */ - dev->timer = 0; - } - } -} - - -/* Handle a WRITE to a Logitech register. */ -static void -lt_write(mouse_t *dev, uint16_t port, uint8_t val) -{ - uint8_t b; - - switch (port) { - case LTMOUSE_DATA: /* [00] data register */ + switch (port & 0x03) { + case BUSM_PORT_DATA: + bm_log("ERROR: Unsupported write to port 0x%04x (value = 0x%02x)\n", port, val); break; - - case LTMOUSE_MAGIC: /* [01] magic data register */ - switch(val) { - case LTMAGIC_BYTE1: - case LTMAGIC_BYTE2: - lt_reset(dev); - dev->r_magic = val; - dev->flags |= FLAG_ENABLED; - break; - } + case BUSM_PORT_SIGNATURE: + dev->sig_val = val; break; + case BUSM_PORT_CONTROL: + dev->control_val = val | 0x0F; - case LTMOUSE_CTRL: /* [02] control register */ - if (!(dev->flags & FLAG_ENABLED)) { - dev->irq_num++; - dev->timer = ((1000000LL * TIMER_USEC) / 30LL); - break; - } + if (!(val & DISABLE_IRQ)) + dev->flags |= FLAG_TIMER_INT; + else + dev->flags &= ~FLAG_TIMER_INT; - b = (dev->r_ctrl ^ val); - if (b & LTCTRL_FREEZE) { - if (val & LTCTRL_FREEZE) { - /* Hold the sampling while we do something. */ - dev->flags |= FLAG_FROZEN; - } else { - /* Reset current state. */ - dev->flags &= ~FLAG_FROZEN; - dev->x = dev->y = 0; - if (dev->but) - dev->but |= 0x80; - } - } + if (val & HOLD_COUNTER) + dev->flags |= FLAG_HOLD; + else + dev->flags &= ~FLAG_HOLD; - if (b & LTCTRL_IDIS) { - /* Disable or enable interrupts. */ - if (val & LTCTRL_IDIS) - dev->flags &= ~FLAG_INTR; - else - dev->flags |= FLAG_INTR; - } - - /* Save new register value. */ - dev->r_ctrl = val; - - /* Clear any pending interrupts. */ picintc(1 << dev->irq); - break; - case LTMOUSE_CONFIG: /* [03] config register */ + break; + case BUSM_PORT_CONFIG: /* * The original Logitech design was based on using a * 8255 parallel I/O chip. This chip has to be set up @@ -458,128 +324,106 @@ lt_write(mouse_t *dev, uint16_t port, uint8_t val) * being an output port and lower 4 bits an input port, and * enable the sucker. Courtesy Intel 8255 databook. Lars */ - dev->r_conf = val; - break; - - default: - break; - } -} - - -/* Handle a READ from a Logitech register. */ -static uint8_t -lt_read(mouse_t *dev, uint16_t port) -{ - uint8_t ret = 0xff; - - /* The GEOS drivers actually check this. */ - if (! (dev->flags & FLAG_ENABLED)) return(ret); - - switch (port) { - case LTMOUSE_DATA: /* [00] data register */ - ret = 0x07; - if (dev->but & 0x01) /* LEFT */ - ret &= ~0x04; - if (dev->but & 0x02) /* RIGHT */ - ret &= ~0x01; - if (dev->flags & FLAG_3BTN) - if (dev->but & 0x04) /* MIDDLE */ - ret &= ~0x02; - ret <<= 5; - - switch(dev->r_ctrl & LTCTRL_RD_MASK) { - case LTCTRL_RD_X_LO: /* X, low bits */ - ret |= (dev->x & 0x0f); - break; - - case LTCTRL_RD_X_HI: /* X, high bits */ - ret |= (dev->x >> 4) & 0x0f; - break; - - case LTCTRL_RD_Y_LO: /* Y, low bits */ - ret |= (dev->y & 0x0f); - break; - - case LTCTRL_RD_Y_HI: /* Y, high bits */ - ret |= (dev->y >> 4) & 0x0f; - break; + dev->config_val = val; + if (val & DEVICE_ACTIVE) { + dev->flags |= (FLAG_ENABLED | FLAG_TIMER_INT); + dev->control_val = 0x0F & ~IRQ_MASK; + dev->timer = ((int64_t) dev->period) * TIMER_USEC; + dev->timer_enabled = 1LL; + } else { + dev->flags &= ~(FLAG_ENABLED | FLAG_TIMER_INT); + dev->timer = 0LL; + dev->timer_enabled = 0LL; } break; - - case LTMOUSE_MAGIC: /* [01] magic data register */ - /* - * Drivers write a magic byte to this register, usually - * this is either 5A (AMI WinBIOS, MS Mouse 2.0) or - * A5 (MS Mouse 9.1, Windows drivers, UNIX/Linux/Minix.) - */ - ret = dev->r_magic; - break; - - case LTMOUSE_CTRL: /* [02] control register */ - ret = 0x0f; - if (!(dev->r_ctrl & LTCTRL_IDIS) && (dev->seq++ == 0)) { - /* !IDIS, return DIP switch setting. */ - switch(dev->irq) { - case 2: - ret &= ~0x08; - break; - - case 3: - ret &= ~0x04; - break; - - case 4: - ret &= ~0x02; - break; - - case 5: - ret &= ~0x01; - break; - } - } - break; - - case LTMOUSE_CONFIG: /* [03] config register */ - ret = dev->r_conf; - break; - - default: - break; } - - return(ret); } /* Handle a WRITE operation to one of our registers. */ static void -bm_write(uint16_t port, uint8_t val, void *priv) +ms_write(uint16_t port, uint8_t val, void *priv) { mouse_t *dev = (mouse_t *)priv; -#if MOUSE_DEBUG - pclog("%s: write(%d,%02x)\n", dev->name, port-MOUSE_PORT, val); -#endif + bm_log("DEBUG: write to address 0x%04x, value = 0x%02x\n", port, val); - dev->write(dev, port-MOUSE_PORT, val); -} + switch (port & 0x03) { + case INP_PORT_CONTROL: + /* Bit 7 is reset. */ + if (val & INP_CTRL_RESET) + dev->control_val = 0; + /* Bits 0-2 are the internal register index. */ + switch(val & 0x07) { + case INP_CTRL_COMMAND: + case INP_CTRL_READ_BUTTONS: + case INP_CTRL_READ_X: + case INP_CTRL_READ_Y: + dev->command_val = val & 0x07; + break; + default: + bm_log("ERROR: Unsupported command written to port 0x%04x (value = 0x%02x)\n", port, val); + } + break; + case INP_PORT_DATA: + picintc(1 << dev->irq); + switch(dev->command_val) { + case INP_CTRL_COMMAND: + if (val & INP_HOLD_COUNTER) + dev->flags |= FLAG_HOLD; + else + dev->flags &= ~FLAG_HOLD; -/* Handle a READ operation from one of our registers. */ -static uint8_t -bm_read(uint16_t port, void *priv) -{ - mouse_t *dev = (mouse_t *)priv; - uint8_t ret; + if (val & INP_ENABLE_TIMER_IRQ) + dev->flags |= FLAG_TIMER_INT; + else + dev->flags &= ~FLAG_TIMER_INT; - ret = dev->read(dev, port-MOUSE_PORT); + if (val & INP_ENABLE_DATA_IRQ) + dev->flags |= FLAG_DATA_INT; + else + dev->flags &= ~FLAG_DATA_INT; -#if MOUSE_DEBUG > 1 - pclog("%s: read(%d): %02x\n", dev->name, port-MOUSE_PORT, ret); -#endif + switch(val & INP_PERIOD_MASK) { + case 0: + dev->period = 0.0; + dev->timer = 0LL; + dev->timer_enabled = 0LL; + break; - return(ret); + case 1: + case 2: + case 3: + case 4: + dev->period = 1000000.0 / periods[(val & INP_PERIOD_MASK) - 1]; + dev->timer = ((int64_t) dev->period) * TIMER_USEC; + dev->timer_enabled = (val & INP_ENABLE_TIMER_IRQ) ? 1LL : 0LL; + bm_log("DEBUG: Timer is now %sabled at period %i\n", (val & INP_ENABLE_TIMER_IRQ) ? "en" : "dis", (int32_t) dev->period); + break; + + case 6: + if (val & INP_ENABLE_TIMER_IRQ) + picint(1 << dev->irq); + dev->control_val &= INP_PERIOD_MASK; + dev->control_val |= (val & ~INP_PERIOD_MASK); + return; + default: + bm_log("ERROR: Unsupported period written to port 0x%04x (value = 0x%02x)\n", port, val); + } + + dev->control_val = val; + + break; + default: + bm_log("ERROR: Unsupported write to port 0x%04x (value = 0x%02x)\n", port, val); + } + break; + case INP_PORT_SIGNATURE: + case INP_PORT_CONFIG: + bm_log("ERROR: Unsupported write to port 0x%04x (value = 0x%02x)\n", port, val); + break; + } } @@ -588,68 +432,136 @@ static int bm_poll(int x, int y, int z, int b, void *priv) { mouse_t *dev = (mouse_t *)priv; + int xor; - /* Return early if nothing to do. */ - if (!x && !y && !z && (dev->but == b)) - return(1); + if (!(dev->flags & FLAG_ENABLED)) + return(1); /* Mouse is disabled, do nothing. */ - /* If we are not enabled, return. */ - if (! (dev->flags & FLAG_ENABLED)) - pclog("bm_poll(): Mouse not enabled\n"); + if (!x && !y && !((b ^ dev->mouse_buttons_last) & 0x07)) { + dev->mouse_buttons_last = b; + return(1); /* State has not changed, do nothing. */ + } -#if 0 - pclog("%s: poll(%d,%d,%d,%02x) %d\n", - dev->name, x, y, z, b, !!(dev->flags & FLAG_FROZEN)); -#endif + /* Converts button states from MRL to LMR. */ + dev->mouse_buttons = (uint8_t) (((b & 1) << 2) | ((b & 2) >> 1)); + if (dev->bn == 3) + dev->mouse_buttons |= ((b & 4) >> 1); - if (dev->flags & FLAG_SCALED) { - /* Scale down the motion. */ - if ((x < -1) || (x > 1)) x >>= 1; - if ((y < -1) || (y > 1)) y >>= 1; + if ((dev->flags & FLAG_INPORT) && !dev->timer_enabled) { + /* This is an InPort mouse in data interrupt mode, + so update bits 6-3 here. */ + + /* If the mouse has moved, set bit 6. */ + if (x || y) + dev->mouse_buttons |= 0x40; + + /* Set bits 3-5 according to button state changes. */ + xor = ((dev->current_b ^ dev->mouse_buttons) & 0x07) << 3; + dev->mouse_buttons |= xor; + } + + dev->mouse_buttons_last = b; + + /* Clamp x and y to between -128 and 127 (int8_t range). */ + if (x > 127) x = 127; + if (x < -128) x = -128; + + if (y > 127) y = 127; + if (y < -128) y = -128; + + if (dev->timer_enabled) { + /* Update delayed coordinates. */ + dev->mouse_delayed_dx += x; + dev->mouse_delayed_dy += y; + } else { + /* If the counters are not frozen, update them. */ + if (!(dev->flags & FLAG_HOLD)) { + dev->current_x = (int8_t) x; + dev->current_y = (int8_t) y; + + dev->current_b = dev->mouse_buttons; + } + + /* Send interrupt. */ + if (dev->flags & FLAG_DATA_INT) { + picint(1 << dev->irq); + bm_log("DEBUG: Data Interrupt Fired...\n"); + } + } + return(0); +} + + +/* The timer calls us on every tick if the mouse is in timer mode + (InPort mouse is so configured, MS/Logitech Bus mouse always). */ +static void +bm_update_data(mouse_t *dev) +{ + int delta_x, delta_y; + int xor; + + /* Update the deltas and the delays. */ + if (dev->mouse_delayed_dx > 127) { + delta_x = 127; + dev->mouse_delayed_dx -= 127; + } else if (dev->mouse_delayed_dx < -128) { + delta_x = -128; + dev->mouse_delayed_dx += 128; + } else { + delta_x = dev->mouse_delayed_dx; + dev->mouse_delayed_dx = 0; + } + + if (dev->mouse_delayed_dy > 127) { + delta_y = 127; + dev->mouse_delayed_dy -= 127; + } else if (dev->mouse_delayed_dy < -128) { + delta_y = -128; + dev->mouse_delayed_dy += 128; + } else { + delta_y = dev->mouse_delayed_dy; + dev->mouse_delayed_dy = 0; + } + + /* If the counters are not frozen, update them. */ + if (!(dev->flags & FLAG_HOLD)) { + dev->current_x = (uint8_t) delta_x; + dev->current_y = (uint8_t) delta_y; } if (dev->flags & FLAG_INPORT) { - if (x > 127) x = 127; - if (y > 127) y = 127; - if (x < -128) x = -128; - if (y < -128) y = -128; + /* This is an InPort mouse in timer mode, so update current_b always, + and update bits 6-3 (mouse moved and button state changed) here. */ + xor = ((dev->current_b ^ dev->mouse_buttons) & 0x07) << 3; + dev->current_b = (dev->mouse_buttons & 0x87) | xor; + if (delta_x || delta_y) + dev->current_b |= 0x40; + } else if (!(dev->flags & FLAG_HOLD)) { + /* This is a MS/Logitech Bus Mouse, so only update current_b if the + counters are frozen. */ + dev->current_b = dev->mouse_buttons; + } +} - dev->x_delay += x; - dev->y_delay += y; - dev->but = (uint8_t)(0x40 | ((b & 1) << 2) | ((b & 2) >> 1)); - if (dev->flags & FLAG_3BTN) - dev->but |= ((b & 4) >> 1); - dev->need_upd = 1; - } else { - /* If we are frozen, do not update the state. */ - if (! (dev->flags & FLAG_FROZEN)) { - /* Add the delta to our state. */ - x += dev->x; - if (x > 127) - x = 127; - if (x < -128) - x = -128; - dev->x = (int8_t)x; - y += dev->y; - if (y > 127) - y = 127; - if (y < -1287) - y = -1287; - dev->y = (int8_t)y; +/* Called at the configured period (InPort mouse) or 45 times per second (MS/Logitech Bus mouse). */ +static void +bm_timer(void *priv) +{ + mouse_t *dev = (mouse_t *)priv; - dev->x_delay += x; - dev->y_delay += y; + bm_log("DEBUG: Timer Tick (flags=%08X)...\n", dev->flags); - dev->but = b; - } + /* The period is configured either via emulator settings (for MS/Logitech Bus mouse) + or via software (for InPort mouse). */ + dev->timer += ((int64_t) dev->period) * TIMER_USEC; - /* Either way, generate an interrupt. */ - if ((dev->flags & FLAG_INTR) && !(dev->flags & FLAG_INPORT)) - picint(1 << dev->irq); + if (dev->flags & FLAG_TIMER_INT) { + picint(1 << dev->irq); + bm_log("DEBUG: Timer Interrupt Fired...\n"); } - return(0); + bm_update_data(dev); } @@ -659,11 +571,8 @@ bm_close(void *priv) { mouse_t *dev = (mouse_t *)priv; - /* Release our I/O range. */ - io_removehandler(MOUSE_PORT, 4, - bm_read, NULL, NULL, bm_write, NULL, NULL, dev); - - free(dev); + if (dev) + free(dev); } @@ -672,60 +581,84 @@ static void * bm_init(const device_t *info) { mouse_t *dev; - int i; dev = (mouse_t *)malloc(sizeof(mouse_t)); memset(dev, 0x00, sizeof(mouse_t)); - dev->name = info->name; - dev->type = info->local; + + if (info->local == MOUSE_TYPE_INPORT) + dev->flags = FLAG_INPORT; + else + dev->flags = 0; + + dev->base = device_get_config_hex16("base"); dev->irq = device_get_config_int("irq"); - i = device_get_config_int("buttons"); - if (i > 2) - dev->flags |= FLAG_3BTN; + dev->bn = device_get_config_int("buttons"); + mouse_set_buttons(dev->bn); - pclog("%s: I/O=%04x, IRQ=%d, buttons=%d\n", - dev->name, MOUSE_PORT, dev->irq, i); + dev->mouse_delayed_dx = 0; + dev->mouse_delayed_dy = 0; + dev->mouse_buttons = 0; + dev->mouse_buttons_last = 0; + dev->sig_val = 0; /* the signature port value */ + dev->current_x = + dev->current_y = + dev->current_b = 0; + dev->command_val = 0; /* command byte */ + dev->toggle_counter = 0; /* signature byte / IRQ bit toggle */ - switch(dev->type) { - case MOUSE_TYPE_LOGIBUS: - lt_reset(dev); + if (dev->flags & FLAG_INPORT) { + dev->control_val = 0; /* the control port value */ + dev->flags |= FLAG_ENABLED; + dev->period = 0.0; - /* Initialize I/O handlers. */ - dev->read = lt_read; - dev->write = lt_write; + io_sethandler(dev->base, 4, + ms_read, NULL, NULL, ms_write, NULL, NULL, dev); + } else { + dev->control_val = 0x0f; /* the control port value */ + dev->config_val = 0x0e; /* the config port value */ + dev->period = 1000000.0 / ((double) device_get_config_int("hz")); - dev->timer = 0; - timer_add(bm_timer, &dev->timer, &dev->timer, dev); - break; - - case MOUSE_TYPE_INPORT: - dev->flags |= FLAG_INPORT; - ms_reset(dev); - - /* Initialize I/O handlers. */ - dev->read = ms_read; - dev->write = ms_write; - - dev->timer = (33334LL * TIMER_USEC); - timer_add(bm_timer, &dev->timer, TIMER_ALWAYS_ENABLED, dev); - break; + io_sethandler(dev->base, 4, + lt_read, NULL, NULL, lt_write, NULL, NULL, dev); } - /* Request an I/O range. */ - io_sethandler(MOUSE_PORT, 4, - bm_read, NULL, NULL, bm_write, NULL, NULL, dev); + dev->timer = 0LL; + dev->timer_enabled = 0LL; - /* Tell them how many buttons we have. */ - mouse_set_buttons((dev->flags & FLAG_3BTN) ? 3 : 2); + timer_add(bm_timer, &dev->timer, &dev->timer_enabled, dev); - /* Return our private data to the I/O layer. */ - return(dev); + if (dev->flags & FLAG_INPORT) + bm_log("MS Inport BusMouse initialized\n"); + else + bm_log("Standard MS/Logitech BusMouse initialized\n"); + + return dev; } -static const device_config_t bm_config[] = { +static const device_config_t lt_config[] = { { - "irq", "IRQ", CONFIG_SELECTION, "", MOUSE_IRQ, { + "base", "Address", CONFIG_HEX16, "", 0x23c, + { + { + "0x230", 0x230 + }, + { + "0x234", 0x234 + }, + { + "0x238", 0x238 + }, + { + "0x23C", 0x23c + }, + { + "" + } + } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 5, { { "IRQ 2", 2 }, @@ -744,7 +677,82 @@ static const device_config_t bm_config[] = { } }, { - "buttons", "Buttons", CONFIG_SELECTION, "", MOUSE_BUTTONS, { + "hz", "Hz", CONFIG_SELECTION, "", 45, { + { + "30 Hz (JMP2 = 1)", 30 + }, + { + "45 Hz (JMP2 not populated)", 45 + }, + { + "60 Hz (JMP 2 = 2)", 60 + }, + { + "" + } + } + }, + { + "buttons", "Buttons", CONFIG_SELECTION, "", 2, { + { + "Two", 2 + }, + { + "Three", 3 + }, + { + "" + } + } + }, + { + "", "", -1 + } +}; + + +static const device_config_t ms_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x23c, + { + { + "0x230", 0x230 + }, + { + "0x234", 0x234 + }, + { + "0x238", 0x238 + }, + { + "0x23C", 0x23c + }, + { + "" + } + } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 5, { + { + "IRQ 2", 2 + }, + { + "IRQ 3", 3 + }, + { + "IRQ 4", 4 + }, + { + "IRQ 5", 5 + }, + { + "" + } + } + }, + { + "buttons", "Buttons", CONFIG_SELECTION, "", 2, { { "Two", 2 }, @@ -767,8 +775,8 @@ const device_t mouse_logibus_device = { DEVICE_ISA, MOUSE_TYPE_LOGIBUS, bm_init, bm_close, NULL, - bm_poll, NULL, NULL, NULL, - bm_config + bm_poll, NULL, NULL, + lt_config }; const device_t mouse_msinport_device = { @@ -776,6 +784,6 @@ const device_t mouse_msinport_device = { DEVICE_ISA, MOUSE_TYPE_INPORT, bm_init, bm_close, NULL, - bm_poll, NULL, NULL, NULL, - bm_config + bm_poll, NULL, NULL, + ms_config }; diff --git a/src/mouse_ps2.c b/src/mouse_ps2.c index 3cf6ee27e..16ec68b5e 100644 --- a/src/mouse_ps2.c +++ b/src/mouse_ps2.c @@ -8,15 +8,17 @@ * * Implementation of PS/2 series Mouse devices. * - * Version: @(#)mouse_ps2.c 1.0.6 2018/03/18 + * Version: @(#)mouse_ps2.c 1.0.9 2018/05/12 * * Authors: Fred N. van Kempen, */ +#include #include #include #include #include #include +#define HAVE_STDARG_H #include "86box.h" #include "config.h" #include "device.h" @@ -57,6 +59,35 @@ typedef struct { int mouse_scan = 0; +#ifdef ENABLE_MOUSE_PS2_LOG +int mouse_ps2_do_log = ENABLE_MOUSE_PS2_LOG; +#endif + + +static void +mouse_ps2_log(const char *format, ...) +{ +#ifdef ENABLE_MOUSE_PS2_LOG + va_list ap; + + if (mouse_ps2_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + +void +mouse_clear_data(void *priv) +{ + mouse_t *dev = (mouse_t *)priv; + + dev->flags &= ~FLAG_CTRLDAT; +} + + static void ps2_write(uint8_t val, void *priv) { @@ -74,7 +105,7 @@ ps2_write(uint8_t val, void *priv) case 0xf3: /* set sample rate */ dev->sample_rate = val; - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse(0xfa); /* Command response */ break; default: @@ -123,7 +154,7 @@ ps2_write(uint8_t val, void *priv) case 0xf3: /* set command mode */ dev->flags |= FLAG_CTRLDAT; - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse(0xfa); /* ACK for command byte */ break; case 0xf4: /* enable */ @@ -242,7 +273,7 @@ mouse_ps2_init(const device_t *info) /* Hook into the general AT Keyboard driver. */ keyboard_at_set_mouse(ps2_write, dev); - pclog("%s: buttons=%d\n", dev->name, (dev->flags & FLAG_INTELLI)? 3 : 2); + mouse_ps2_log("%s: buttons=%d\n", dev->name, (dev->flags & FLAG_INTELLI)? 3 : 2); /* Tell them how many buttons we have. */ mouse_set_buttons((dev->flags & FLAG_INTELLI) ? 3 : 2); @@ -292,6 +323,6 @@ const device_t mouse_ps2_device = { 0, MOUSE_TYPE_PS2, mouse_ps2_init, ps2_close, NULL, - ps2_poll, NULL, NULL, NULL, + ps2_poll, NULL, NULL, ps2_config }; diff --git a/src/mouse_serial.c b/src/mouse_serial.c index a0a487f9c..cb338a0c5 100644 --- a/src/mouse_serial.c +++ b/src/mouse_serial.c @@ -10,15 +10,17 @@ * * TODO: Add the Genius Serial Mouse. * - * Version: @(#)mouse_serial.c 1.0.21 2018/03/18 + * Version: @(#)mouse_serial.c 1.0.23 2018/04/29 * * Author: Fred N. van Kempen, */ +#include #include #include #include #include #include +#define HAVE_STDARG_H #include "86box.h" #include "config.h" #include "device.h" @@ -50,6 +52,26 @@ typedef struct { #define FLAG_ENABLED 0x01 /* dev is enabled for use */ +#ifdef ENABLE_MOUSE_SERIAL_LOG +int mouse_serial_do_log = ENABLE_MOUSE_SERIAL_LOG; +#endif + + +static void +mouse_serial_log(const char *format, ...) +{ +#ifdef ENABLE_MOUSE_SERIAL_LOG + va_list ap; + + if (mouse_serial_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + /* Callback from serial driver: RTS was toggled. */ static void sermouse_callback(struct SERIAL *serial, void *priv) @@ -98,7 +120,7 @@ sermouse_timer(void *priv) break; default: - pclog("%s: unsupported mouse type %d?\n", dev->type); + mouse_serial_log("%s: unsupported mouse type %d?\n", dev->type); } } @@ -113,7 +135,7 @@ sermouse_poll(int x, int y, int z, int b, void *priv) if (!x && !y && b == dev->oldb) return(1); #if 0 - pclog("%s: poll(%d,%d,%d,%02x)\n", dev->name, x, y, z, b); + mouse_serial_log("%s: poll(%d,%d,%d,%02x)\n", dev->name, x, y, z, b); #endif dev->oldb = b; @@ -164,9 +186,9 @@ sermouse_poll(int x, int y, int z, int b, void *priv) } #if 0 - pclog("%s: [", dev->name); - for (b=0; bname); + for (b=0; bserial->rcr_callback = sermouse_callback; dev->serial->rcr_callback_p = dev; - pclog("%s: port=COM%d\n", dev->name, dev->port+1); + mouse_serial_log("%s: port=COM%d\n", dev->name, dev->port+1); timer_add(sermouse_timer, &dev->delay, &dev->delay, dev); @@ -288,7 +310,7 @@ const device_t mouse_mssystems_device = { 0, MOUSE_TYPE_MSYSTEMS, sermouse_init, sermouse_close, NULL, - sermouse_poll, NULL, NULL, NULL, + sermouse_poll, NULL, NULL, sermouse_config }; @@ -297,6 +319,6 @@ const device_t mouse_msserial_device = { 0, 0, sermouse_init, sermouse_close, NULL, - sermouse_poll, NULL, NULL, NULL, + sermouse_poll, NULL, NULL, sermouse_config }; diff --git a/src/network/net_3c503.c b/src/network/net_3c503.c new file mode 100644 index 000000000..65bea5af7 --- /dev/null +++ b/src/network/net_3c503.c @@ -0,0 +1,1679 @@ +/* + * 86Box An emulator of (mostly) x86-based PC systems and devices, + * using the ISA, EISA, VLB, MCA, and PCI system buses, + * roughly spanning the era between 1981 and 1995. + * + * This file is part of the 86Box Project. + * + * Implementation of the following network controllers: + * - 3Com Etherlink II 3c503 (ISA 8-bit). + * + * Version: @(#)net_3c503.c 1.0.0 2018/06/08 + * + * Based on @(#)3c503.cpp Carl (MAME) + * + * Authors: TheCollector1995, + * Miran Grca, + * Fred N. van Kempen, + * Carl, + * + * Copyright 2018 TheCollector1995. + * Copyright 2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. + * Portions Copyright (C) 2018 MAME Project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include "../86box.h" +#include "../config.h" +#include "../machine/machine.h" +#include "../io.h" +#include "../dma.h" +#include "../pic.h" +#include "../mem.h" +#include "../random.h" +#include "../device.h" +#include "../ui.h" +#include "network.h" +#include "net_dp8390.h" +#include "net_3c503.h" +#include "bswap.h" + +typedef struct { + dp8390_t dp8390; + mem_mapping_t ram_mapping; + uint32_t base_address; + int base_irq; + uint32_t bios_addr; + uint8_t maclocal[6]; /* configured MAC (local) address */ + uint8_t prom[32]; + + struct { + uint8_t pstr; + uint8_t pspr; + uint8_t dqtr; + uint8_t bcfr; + uint8_t pcfr; + uint8_t gacfr; + uint8_t ctrl; + uint8_t streg; + uint8_t idcfr; + uint16_t da; + uint32_t vptr; + uint8_t rfmsb; + uint8_t rflsb; + } regs; + + int dma_channel; +} threec503_t; + +static void threec503_rx(void *, uint8_t *, int); +static void threec503_tx(threec503_t *, uint32_t); + + +#ifdef ENABLE_3COM503_LOG +int threec503_do_log = ENABLE_3COM503_LOG; +#endif + + +static void +threec503_log(const char *fmt, ...) +{ +#ifdef ENABLE_3COM503_LOG + va_list ap; + + if (threec503_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + +static void +threec503_interrupt(threec503_t *dev, int set) +{ + switch (dev->base_irq) { + case 2: + dev->regs.idcfr = 0x10; + break; + + case 3: + dev->regs.idcfr = 0x20; + break; + + case 4: + dev->regs.idcfr = 0x40; + break; + + case 5: + dev->regs.idcfr = 0x80; + break; + } + + if (set) + picint(1 << dev->base_irq); + else + picintc(1 << dev->base_irq); +} + + +static void +threec503_ram_write(uint32_t addr, uint8_t val, void *priv) +{ + threec503_t *dev = (threec503_t *)priv; + + if ((addr & 0x3fff) >= 0x2000) + return; + + dev->dp8390.mem[addr & 0x1fff] = val; +} + + +static uint8_t +threec503_ram_read(uint32_t addr, void *priv) +{ + threec503_t *dev = (threec503_t *)priv; + + if ((addr & 0x3fff) >= 0x2000) + return 0xff; + + return dev->dp8390.mem[addr & 0x1fff]; +} + + +static void +threec503_set_drq(threec503_t *dev) +{ + switch (dev->dma_channel) { + case 1: + dev->regs.idcfr = 1; + break; + + case 2: + dev->regs.idcfr = 2; + break; + + case 3: + dev->regs.idcfr = 4; + break; + } +} + + +/* reset - restore state to power-up, cancelling all i/o */ +static void +threec503_reset(void *priv) +{ + threec503_t *dev = (threec503_t *)priv; + int i; + + threec503_log("3Com503: reset\n"); + + /* Initialize the MAC address area by doubling the physical address */ + dev->prom[0] = dev->dp8390.physaddr[0]; + dev->prom[1] = dev->dp8390.physaddr[1]; + dev->prom[2] = dev->dp8390.physaddr[2]; + dev->prom[3] = dev->dp8390.physaddr[3]; + dev->prom[4] = dev->dp8390.physaddr[4]; + dev->prom[5] = dev->dp8390.physaddr[5]; + + /* ne1k signature */ + for (i=6; i<16; i++) + dev->prom[i] = 0x57; + + /* Zero out registers and memory */ + memset(&dev->dp8390.CR, 0x00, sizeof(dev->dp8390.CR) ); + memset(&dev->dp8390.ISR, 0x00, sizeof(dev->dp8390.ISR)); + memset(&dev->dp8390.IMR, 0x00, sizeof(dev->dp8390.IMR)); + memset(&dev->dp8390.DCR, 0x00, sizeof(dev->dp8390.DCR)); + memset(&dev->dp8390.TCR, 0x00, sizeof(dev->dp8390.TCR)); + memset(&dev->dp8390.TSR, 0x00, sizeof(dev->dp8390.TSR)); + memset(&dev->dp8390.RSR, 0x00, sizeof(dev->dp8390.RSR)); + dev->dp8390.tx_timer_active = 0; + dev->dp8390.local_dma = 0; + dev->dp8390.page_start = 0; + dev->dp8390.page_stop = 0; + dev->dp8390.bound_ptr = 0; + dev->dp8390.tx_page_start = 0; + dev->dp8390.num_coll = 0; + dev->dp8390.tx_bytes = 0; + dev->dp8390.fifo = 0; + dev->dp8390.remote_dma = 0; + dev->dp8390.remote_start = 0; + dev->dp8390.remote_bytes = 0; + dev->dp8390.tallycnt_0 = 0; + dev->dp8390.tallycnt_1 = 0; + dev->dp8390.tallycnt_2 = 0; + + dev->dp8390.curr_page = 0; + + dev->dp8390.rempkt_ptr = 0; + dev->dp8390.localpkt_ptr = 0; + dev->dp8390.address_cnt = 0; + + memset(&dev->dp8390.mem, 0x00, sizeof(dev->dp8390.mem)); + + /* Set power-up conditions */ + dev->dp8390.CR.stop = 1; + dev->dp8390.CR.rdma_cmd = 4; + dev->dp8390.ISR.reset = 1; + dev->dp8390.DCR.longaddr = 1; + + memset(&dev->regs, 0, sizeof(dev->regs)); + + dev->regs.ctrl = 0x0a; + + threec503_interrupt(dev, 0); +} + + +/* + * Access the 32K private RAM. + * + * The NE2000 memory is accessed through the data port of the + * ASIC (offset 0) after setting up a remote-DMA transfer. + * Both byte and word accesses are allowed. + * The first 16 bytes contains the MAC address at even locations, + * and there is 16K of buffer memory starting at 16K. + */ +static uint32_t +threec503_chipmem_read(threec503_t *dev, uint32_t addr, unsigned int len) +{ + uint32_t retval = 0; + + if (addr <= 15) { + retval = dev->prom[addr % 16]; + if (len == 2) + retval |= (dev->prom[(addr + 1) % 16] << 8); + return(retval); + } + + if ((addr >= DP8390_WORD_MEMSTART) && (addr < DP8390_WORD_MEMEND)) { + retval = dev->dp8390.mem[addr - DP8390_WORD_MEMSTART]; + if (len == 2) + retval |= (dev->dp8390.mem[addr - DP8390_WORD_MEMSTART + 1] << 8); + return(retval); + } + + threec503_log("3Com503: out-of-bounds chipmem read, %04X\n", addr); + return(0xff); +} + + +static void +threec503_chipmem_write(threec503_t *dev, uint32_t addr, uint32_t val, unsigned len) +{ + if ((addr >= DP8390_WORD_MEMSTART) && (addr < DP8390_WORD_MEMEND)) { + dev->dp8390.mem[addr-DP8390_WORD_MEMSTART] = val & 0xff; + if (len == 2) + dev->dp8390.mem[addr-DP8390_WORD_MEMSTART+1] = val >> 8; + } else + threec503_log("3Com503: out-of-bounds chipmem write, %04X\n", addr); +} + + +/* Handle reads/writes to the 'zeroth' page of the DS8390 register file. */ +static uint32_t +threec503_page0_read(threec503_t *dev, uint32_t off, unsigned int len) +{ + uint8_t retval = 0; + + if (len > 1) { + /* encountered with win98 hardware probe */ + threec503_log("3Com503: bad length! Page0 read from register 0x%02x, len=%u\n", + off, len); + return(retval); + } + + switch(off) { + case 0x01: /* CLDA0 */ + retval = (dev->dp8390.local_dma & 0xff); + break; + + case 0x02: /* CLDA1 */ + retval = (dev->dp8390.local_dma >> 8); + break; + + case 0x03: /* BNRY */ + retval = dev->dp8390.bound_ptr; + break; + + case 0x04: /* TSR */ + retval = ((dev->dp8390.TSR.ow_coll << 7) | + (dev->dp8390.TSR.cd_hbeat << 6) | + (dev->dp8390.TSR.fifo_ur << 5) | + (dev->dp8390.TSR.no_carrier << 4) | + (dev->dp8390.TSR.aborted << 3) | + (dev->dp8390.TSR.collided << 2) | + (dev->dp8390.TSR.tx_ok)); + break; + + case 0x05: /* NCR */ + retval = dev->dp8390.num_coll; + break; + + case 0x06: /* FIFO */ + /* reading FIFO is only valid in loopback mode */ + threec503_log("3Com503: reading FIFO not supported yet\n"); + retval = dev->dp8390.fifo; + break; + + case 0x07: /* ISR */ + retval = ((dev->dp8390.ISR.reset << 7) | + (dev->dp8390.ISR.rdma_done << 6) | + (dev->dp8390.ISR.cnt_oflow << 5) | + (dev->dp8390.ISR.overwrite << 4) | + (dev->dp8390.ISR.tx_err << 3) | + (dev->dp8390.ISR.rx_err << 2) | + (dev->dp8390.ISR.pkt_tx << 1) | + (dev->dp8390.ISR.pkt_rx)); + break; + + case 0x08: /* CRDA0 */ + retval = (dev->dp8390.remote_dma & 0xff); + break; + + case 0x09: /* CRDA1 */ + retval = (dev->dp8390.remote_dma >> 8); + break; + + case 0x0a: /* reserved / RTL8029ID0 */ + threec503_log("3Com503: reserved Page0 read - 0x0a\n"); + retval = 0xff; + break; + + case 0x0b: /* reserved / RTL8029ID1 */ + threec503_log("3Com503: reserved Page0 read - 0x0b\n"); + retval = 0xff; + break; + + case 0x0c: /* RSR */ + retval = ((dev->dp8390.RSR.deferred << 7) | + (dev->dp8390.RSR.rx_disabled << 6) | + (dev->dp8390.RSR.rx_mbit << 5) | + (dev->dp8390.RSR.rx_missed << 4) | + (dev->dp8390.RSR.fifo_or << 3) | + (dev->dp8390.RSR.bad_falign << 2) | + (dev->dp8390.RSR.bad_crc << 1) | + (dev->dp8390.RSR.rx_ok)); + break; + + case 0x0d: /* CNTR0 */ + retval = dev->dp8390.tallycnt_0; + break; + + case 0x0e: /* CNTR1 */ + retval = dev->dp8390.tallycnt_1; + break; + + case 0x0f: /* CNTR2 */ + retval = dev->dp8390.tallycnt_2; + break; + + default: + threec503_log("3Com503: Page0 register 0x%02x out of range\n", + off); + break; + } + + threec503_log("3Com503: Page0 read from register 0x%02x, value=0x%02x\n", + off, retval); + + return(retval); +} + + +static void +threec503_page0_write(threec503_t *dev, uint32_t off, uint32_t val, unsigned len) +{ + uint8_t val2; + + /* It appears to be a common practice to use outw on page0 regs... */ + + /* break up outw into two outb's */ + if (len == 2) { + threec503_page0_write(dev, off, (val & 0xff), 1); + if (off < 0x0f) + threec503_page0_write(dev, off+1, ((val>>8)&0xff), 1); + return; + } + + threec503_log("3Com503: Page0 write to register 0x%02x, value=0x%02x\n", + off, val); + + switch(off) { + case 0x01: /* PSTART */ + dev->dp8390.page_start = val; + break; + + case 0x02: /* PSTOP */ + dev->dp8390.page_stop = val; + break; + + case 0x03: /* BNRY */ + dev->dp8390.bound_ptr = val; + break; + + case 0x04: /* TPSR */ + dev->dp8390.tx_page_start = val; + break; + + case 0x05: /* TBCR0 */ + /* Clear out low byte and re-insert */ + dev->dp8390.tx_bytes &= 0xff00; + dev->dp8390.tx_bytes |= (val & 0xff); + break; + + case 0x06: /* TBCR1 */ + /* Clear out high byte and re-insert */ + dev->dp8390.tx_bytes &= 0x00ff; + dev->dp8390.tx_bytes |= ((val & 0xff) << 8); + break; + + case 0x07: /* ISR */ + val &= 0x7f; /* clear RST bit - status-only bit */ + /* All other values are cleared iff the ISR bit is 1 */ + dev->dp8390.ISR.pkt_rx &= !((int)((val & 0x01) == 0x01)); + dev->dp8390.ISR.pkt_tx &= !((int)((val & 0x02) == 0x02)); + dev->dp8390.ISR.rx_err &= !((int)((val & 0x04) == 0x04)); + dev->dp8390.ISR.tx_err &= !((int)((val & 0x08) == 0x08)); + dev->dp8390.ISR.overwrite &= !((int)((val & 0x10) == 0x10)); + dev->dp8390.ISR.cnt_oflow &= !((int)((val & 0x20) == 0x20)); + dev->dp8390.ISR.rdma_done &= !((int)((val & 0x40) == 0x40)); + val = ((dev->dp8390.ISR.rdma_done << 6) | + (dev->dp8390.ISR.cnt_oflow << 5) | + (dev->dp8390.ISR.overwrite << 4) | + (dev->dp8390.ISR.tx_err << 3) | + (dev->dp8390.ISR.rx_err << 2) | + (dev->dp8390.ISR.pkt_tx << 1) | + (dev->dp8390.ISR.pkt_rx)); + val &= ((dev->dp8390.IMR.rdma_inte << 6) | + (dev->dp8390.IMR.cofl_inte << 5) | + (dev->dp8390.IMR.overw_inte << 4) | + (dev->dp8390.IMR.txerr_inte << 3) | + (dev->dp8390.IMR.rxerr_inte << 2) | + (dev->dp8390.IMR.tx_inte << 1) | + (dev->dp8390.IMR.rx_inte)); + if (val == 0x00) + threec503_interrupt(dev, 0); + break; + + case 0x08: /* RSAR0 */ + /* Clear out low byte and re-insert */ + dev->dp8390.remote_start &= 0xff00; + dev->dp8390.remote_start |= (val & 0xff); + dev->dp8390.remote_dma = dev->dp8390.remote_start; + break; + + case 0x09: /* RSAR1 */ + /* Clear out high byte and re-insert */ + dev->dp8390.remote_start &= 0x00ff; + dev->dp8390.remote_start |= ((val & 0xff) << 8); + dev->dp8390.remote_dma = dev->dp8390.remote_start; + break; + + case 0x0a: /* RBCR0 */ + /* Clear out low byte and re-insert */ + dev->dp8390.remote_bytes &= 0xff00; + dev->dp8390.remote_bytes |= (val & 0xff); + break; + + case 0x0b: /* RBCR1 */ + /* Clear out high byte and re-insert */ + dev->dp8390.remote_bytes &= 0x00ff; + dev->dp8390.remote_bytes |= ((val & 0xff) << 8); + break; + + case 0x0c: /* RCR */ + /* Check if the reserved bits are set */ + if (val & 0xc0) { + threec503_log("3Com503: RCR write, reserved bits set\n"); + } + + /* Set all other bit-fields */ + dev->dp8390.RCR.errors_ok = ((val & 0x01) == 0x01); + dev->dp8390.RCR.runts_ok = ((val & 0x02) == 0x02); + dev->dp8390.RCR.broadcast = ((val & 0x04) == 0x04); + dev->dp8390.RCR.multicast = ((val & 0x08) == 0x08); + dev->dp8390.RCR.promisc = ((val & 0x10) == 0x10); + dev->dp8390.RCR.monitor = ((val & 0x20) == 0x20); + + /* Monitor bit is a little suspicious... */ + if (val & 0x20) threec503_log("3Com503: RCR write, monitor bit set!\n"); + break; + + case 0x0d: /* TCR */ + /* Check reserved bits */ + if (val & 0xe0) threec503_log("3Com503: TCR write, reserved bits set\n"); + + /* Test loop mode (not supported) */ + if (val & 0x06) { + dev->dp8390.TCR.loop_cntl = (val & 0x6) >> 1; + threec503_log("3Com503: TCR write, loop mode %d not supported\n", + dev->dp8390.TCR.loop_cntl); + } else { + dev->dp8390.TCR.loop_cntl = 0; + } + + /* Inhibit-CRC not supported. */ + if (val & 0x01) threec503_log( + "3Com503: TCR write, inhibit-CRC not supported\n"); + + /* Auto-transmit disable very suspicious */ + if (val & 0x08) threec503_log( + "3Com503: TCR write, auto transmit disable not supported\n"); + + /* Allow collision-offset to be set, although not used */ + dev->dp8390.TCR.coll_prio = ((val & 0x08) == 0x08); + break; + + case 0x0e: /* DCR */ + /* the loopback mode is not suppported yet */ + if (! (val & 0x08)) threec503_log( + "3Com503: DCR write, loopback mode selected\n"); + + /* It is questionable to set longaddr and auto_rx, since + * they are not supported on the NE2000. Print a warning + * and continue. */ + if (val & 0x04) + threec503_log("3Com503: DCR write - LAS set ???\n"); + if (val & 0x10) + threec503_log("3Com503: DCR write - AR set ???\n"); + + /* Set other values. */ + dev->dp8390.DCR.wdsize = ((val & 0x01) == 0x01); + dev->dp8390.DCR.endian = ((val & 0x02) == 0x02); + dev->dp8390.DCR.longaddr = ((val & 0x04) == 0x04); /* illegal ? */ + dev->dp8390.DCR.loop = ((val & 0x08) == 0x08); + dev->dp8390.DCR.auto_rx = ((val & 0x10) == 0x10); /* also illegal ? */ + dev->dp8390.DCR.fifo_size = (val & 0x50) >> 5; + break; + + case 0x0f: /* IMR */ + /* Check for reserved bit */ + if (val & 0x80) + threec503_log("3Com503: IMR write, reserved bit set\n"); + + /* Set other values */ + dev->dp8390.IMR.rx_inte = ((val & 0x01) == 0x01); + dev->dp8390.IMR.tx_inte = ((val & 0x02) == 0x02); + dev->dp8390.IMR.rxerr_inte = ((val & 0x04) == 0x04); + dev->dp8390.IMR.txerr_inte = ((val & 0x08) == 0x08); + dev->dp8390.IMR.overw_inte = ((val & 0x10) == 0x10); + dev->dp8390.IMR.cofl_inte = ((val & 0x20) == 0x20); + dev->dp8390.IMR.rdma_inte = ((val & 0x40) == 0x40); + val2 = ((dev->dp8390.ISR.rdma_done << 6) | + (dev->dp8390.ISR.cnt_oflow << 5) | + (dev->dp8390.ISR.overwrite << 4) | + (dev->dp8390.ISR.tx_err << 3) | + (dev->dp8390.ISR.rx_err << 2) | + (dev->dp8390.ISR.pkt_tx << 1) | + (dev->dp8390.ISR.pkt_rx)); + if (((val & val2) & 0x7f) == 0) + threec503_interrupt(dev, 0); + else + threec503_interrupt(dev, 1); + break; + + default: + threec503_log("3Com503: Page0 write, bad register 0x%02x\n", + off); + break; + } +} + + +/* Handle reads/writes to the first page of the DS8390 register file. */ +static uint32_t +threec503_page1_read(threec503_t *dev, uint32_t off, unsigned int len) +{ + threec503_log("3Com503: Page1 read from register 0x%02x, len=%u\n", + off, len); + + switch(off) { + case 0x01: /* PAR0-5 */ + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + return(dev->dp8390.physaddr[off - 1]); + + case 0x07: /* CURR */ + threec503_log("3Com503: returning current page: 0x%02x\n", + (dev->dp8390.curr_page)); + return(dev->dp8390.curr_page); + + case 0x08: /* MAR0-7 */ + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + return(dev->dp8390.mchash[off - 8]); + + default: + threec503_log("3Com503: Page1 read register 0x%02x out of range\n", + off); + return(0); + } +} + + +static void +threec503_page1_write(threec503_t *dev, uint32_t off, uint32_t val, unsigned len) +{ + threec503_log("3Com503: Page1 write to register 0x%02x, len=%u, value=0x%04x\n", + off, len, val); + + switch(off) { + case 0x01: /* PAR0-5 */ + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + dev->dp8390.physaddr[off - 1] = val; + if (off == 6) threec503_log( + "3Com503: physical address set to %02x:%02x:%02x:%02x:%02x:%02x\n", + dev->dp8390.physaddr[0], dev->dp8390.physaddr[1], + dev->dp8390.physaddr[2], dev->dp8390.physaddr[3], + dev->dp8390.physaddr[4], dev->dp8390.physaddr[5]); + break; + + case 0x07: /* CURR */ + dev->dp8390.curr_page = val; + break; + + case 0x08: /* MAR0-7 */ + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + dev->dp8390.mchash[off - 8] = val; + break; + + default: + threec503_log("3Com503: Page1 write register 0x%02x out of range\n", + off); + break; + } +} + + +/* Handle reads/writes to the second page of the DS8390 register file. */ +static uint32_t +threec503_page2_read(threec503_t *dev, uint32_t off, unsigned int len) +{ + threec503_log("3Com503: Page2 read from register 0x%02x, len=%u\n", + off, len); + + switch(off) { + case 0x01: /* PSTART */ + return(dev->dp8390.page_start); + + case 0x02: /* PSTOP */ + return(dev->dp8390.page_stop); + + case 0x03: /* Remote Next-packet pointer */ + return(dev->dp8390.rempkt_ptr); + + case 0x04: /* TPSR */ + return(dev->dp8390.tx_page_start); + + case 0x05: /* Local Next-packet pointer */ + return(dev->dp8390.localpkt_ptr); + + case 0x06: /* Address counter (upper) */ + return(dev->dp8390.address_cnt >> 8); + + case 0x07: /* Address counter (lower) */ + return(dev->dp8390.address_cnt & 0xff); + + case 0x08: /* Reserved */ + case 0x09: + case 0x0a: + case 0x0b: + threec503_log("3Com503: reserved Page2 read - register 0x%02x\n", + off); + return(0xff); + + case 0x0c: /* RCR */ + return ((dev->dp8390.RCR.monitor << 5) | + (dev->dp8390.RCR.promisc << 4) | + (dev->dp8390.RCR.multicast << 3) | + (dev->dp8390.RCR.broadcast << 2) | + (dev->dp8390.RCR.runts_ok << 1) | + (dev->dp8390.RCR.errors_ok)); + + case 0x0d: /* TCR */ + return ((dev->dp8390.TCR.coll_prio << 4) | + (dev->dp8390.TCR.ext_stoptx << 3) | + ((dev->dp8390.TCR.loop_cntl & 0x3) << 1) | + (dev->dp8390.TCR.crc_disable)); + + case 0x0e: /* DCR */ + return (((dev->dp8390.DCR.fifo_size & 0x3) << 5) | + (dev->dp8390.DCR.auto_rx << 4) | + (dev->dp8390.DCR.loop << 3) | + (dev->dp8390.DCR.longaddr << 2) | + (dev->dp8390.DCR.endian << 1) | + (dev->dp8390.DCR.wdsize)); + + case 0x0f: /* IMR */ + return ((dev->dp8390.IMR.rdma_inte << 6) | + (dev->dp8390.IMR.cofl_inte << 5) | + (dev->dp8390.IMR.overw_inte << 4) | + (dev->dp8390.IMR.txerr_inte << 3) | + (dev->dp8390.IMR.rxerr_inte << 2) | + (dev->dp8390.IMR.tx_inte << 1) | + (dev->dp8390.IMR.rx_inte)); + + default: + threec503_log("3Com503: Page2 register 0x%02x out of range\n", + off); + break; + } + + return(0); +} + + +static void +threec503_page2_write(threec503_t *dev, uint32_t off, uint32_t val, unsigned len) +{ + /* Maybe all writes here should be BX_PANIC()'d, since they + affect internal operation, but let them through for now + and print a warning. */ + threec503_log("3Com503: Page2 write to register 0x%02x, len=%u, value=0x%04x\n", + off, len, val); + switch(off) { + case 0x01: /* CLDA0 */ + /* Clear out low byte and re-insert */ + dev->dp8390.local_dma &= 0xff00; + dev->dp8390.local_dma |= (val & 0xff); + break; + + case 0x02: /* CLDA1 */ + /* Clear out high byte and re-insert */ + dev->dp8390.local_dma &= 0x00ff; + dev->dp8390.local_dma |= ((val & 0xff) << 8); + break; + + case 0x03: /* Remote Next-pkt pointer */ + dev->dp8390.rempkt_ptr = val; + break; + + case 0x04: + threec503_log("page 2 write to reserved register 0x04\n"); + break; + + case 0x05: /* Local Next-packet pointer */ + dev->dp8390.localpkt_ptr = val; + break; + + case 0x06: /* Address counter (upper) */ + /* Clear out high byte and re-insert */ + dev->dp8390.address_cnt &= 0x00ff; + dev->dp8390.address_cnt |= ((val & 0xff) << 8); + break; + + case 0x07: /* Address counter (lower) */ + /* Clear out low byte and re-insert */ + dev->dp8390.address_cnt &= 0xff00; + dev->dp8390.address_cnt |= (val & 0xff); + break; + + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + threec503_log("3Com503: Page2 write to reserved register 0x%02x\n", + off); + break; + + default: + threec503_log("3Com503: Page2 write, illegal register 0x%02x\n", + off); + break; + } +} + + +/* Routines for handling reads/writes to the Command Register. */ +static uint32_t +threec503_read_cr(threec503_t *dev) +{ + uint32_t retval; + + retval = (((dev->dp8390.CR.pgsel & 0x03) << 6) | + ((dev->dp8390.CR.rdma_cmd & 0x07) << 3) | + (dev->dp8390.CR.tx_packet << 2) | + (dev->dp8390.CR.start << 1) | + (dev->dp8390.CR.stop)); + threec503_log("3Com503: read CR returns 0x%02x\n", retval); + + return(retval); +} + + +static void +threec503_write_cr(threec503_t *dev, uint32_t val) +{ + threec503_log("3Com503: wrote 0x%02x to CR\n", val); + + /* Validate remote-DMA */ + if ((val & 0x38) == 0x00) { + threec503_log("3Com503: CR write - invalid rDMA value 0\n"); + val |= 0x20; /* dma_cmd == 4 is a safe default */ + } + + /* Check for s/w reset */ + if (val & 0x01) { + dev->dp8390.ISR.reset = 1; + dev->dp8390.CR.stop = 1; + } else + dev->dp8390.CR.stop = 0; + + dev->dp8390.CR.rdma_cmd = (val & 0x38) >> 3; + + /* If start command issued, the RST bit in the ISR */ + /* must be cleared */ + if ((val & 0x02) && !dev->dp8390.CR.start) + dev->dp8390.ISR.reset = 0; + + dev->dp8390.CR.start = ((val & 0x02) == 0x02); + dev->dp8390.CR.pgsel = (val & 0xc0) >> 6; + + /* Check for send-packet command */ + if (dev->dp8390.CR.rdma_cmd == 3) { + /* Set up DMA read from receive ring */ + dev->dp8390.remote_start = dev->dp8390.remote_dma = dev->dp8390.bound_ptr * 256; + dev->dp8390.remote_bytes = (uint16_t) threec503_chipmem_read(dev, dev->dp8390.bound_ptr * 256 + 2, 2); + threec503_log("3Com503: sending buffer %x length %d\n", + dev->dp8390.remote_start, dev->dp8390.remote_bytes); + } + + /* Check for start-tx */ + if ((val & 0x04) && dev->dp8390.TCR.loop_cntl) { + if (dev->dp8390.TCR.loop_cntl != 1) { + threec503_log("3Com503: loop mode %d not supported\n", + dev->dp8390.TCR.loop_cntl); + } else { + threec503_rx(dev, + &dev->dp8390.mem[dev->dp8390.tx_page_start*256 - DP8390_WORD_MEMSTART], + dev->dp8390.tx_bytes); + } + } else if (val & 0x04) { + if (dev->dp8390.CR.stop || (!dev->dp8390.CR.start)) { + if (dev->dp8390.tx_bytes == 0) /* njh@bandsman.co.uk */ + return; /* Solaris9 probe */ + threec503_log("3Com503: CR write - tx start, dev in reset\n"); + } + + if (dev->dp8390.tx_bytes == 0) + threec503_log("3Com503: CR write - tx start, tx bytes == 0\n"); + + /* Send the packet to the system driver */ + dev->dp8390.CR.tx_packet = 1; + network_tx(&dev->dp8390.mem[dev->dp8390.tx_page_start*256 - DP8390_WORD_MEMSTART], + dev->dp8390.tx_bytes); + + /* some more debug */ + if (dev->dp8390.tx_timer_active) + threec503_log("3Com503: CR write, tx timer still active\n"); + + threec503_tx(dev, val); + } + + /* Linux probes for an interrupt by setting up a remote-DMA read + * of 0 bytes with remote-DMA completion interrupts enabled. + * Detect this here */ + if (dev->dp8390.CR.rdma_cmd == 0x01 && dev->dp8390.CR.start && dev->dp8390.remote_bytes == 0) { + dev->dp8390.ISR.rdma_done = 1; + if (dev->dp8390.IMR.rdma_inte) { + threec503_interrupt(dev, 1); + threec503_interrupt(dev, 0); + } + } +} + + +static uint8_t +threec503_nic_lo_read(uint16_t addr, void *priv) +{ + threec503_t *dev = (threec503_t *)priv; + uint8_t retval = 0; + int off = addr - dev->base_address; + + switch ((dev->regs.ctrl >> 2) & 3) { + case 0x00: + threec503_log("Read offset=%04x\n", off); + if (off == 0x00) + retval = threec503_read_cr(dev); + else switch(dev->dp8390.CR.pgsel) { + case 0x00: + retval = threec503_page0_read(dev, off, 1); + break; + + case 0x01: + retval = threec503_page1_read(dev, off, 1); + break; + + case 0x02: + retval = threec503_page2_read(dev, off, 1); + break; + + case 0x03: + retval = 0xff; + break; + } + break; + + case 0x01: + retval = dev->prom[off]; + break; + + case 0x02: + retval = dev->prom[off + 0x10]; + break; + + case 0x03: + retval = 0xff; + break; + } + + return(retval); +} + + +static void +threec503_nic_lo_write(uint16_t addr, uint8_t val, void *priv) +{ + threec503_t *dev = (threec503_t *)priv; + int off = addr - dev->base_address; + + switch ((dev->regs.ctrl >> 2) & 3) { + case 0x00: + /* The high 16 bytes of i/o space are for the ne2000 asic - + the low 16 bytes are for the DS8390, with the current + page being selected by the PS0,PS1 registers in the + command register */ + if (off == 0x00) + threec503_write_cr(dev, val); + else switch(dev->dp8390.CR.pgsel) { + case 0x00: + threec503_page0_write(dev, off, val, 1); + break; + + case 0x01: + threec503_page1_write(dev, off, val, 1); + break; + + case 0x02: + threec503_page2_write(dev, off, val, 1); + break; + + case 0x03: + break; + } + break; + + case 0x01: + case 0x02: + case 0x03: + break; + } + + threec503_log("3Com503: write addr %x, value %x\n", addr, val); +} + + +static uint8_t +threec503_nic_hi_read(uint16_t addr, void *priv) +{ + threec503_t *dev = (threec503_t *)priv; + + threec503_log("3Com503: Read GA address=%04x\n", addr); + + switch (addr & 0x0f) { + case 0x00: + return dev->regs.pstr; + + case 0x01: + return dev->regs.pspr; + + case 0x02: + return dev->regs.dqtr; + + case 0x03: + switch (dev->base_address) { + default: + case 0x300: + dev->regs.bcfr = 0x80; + break; + + case 0x310: + dev->regs.bcfr = 0x40; + break; + + case 0x330: + dev->regs.bcfr = 0x20; + break; + + case 0x350: + dev->regs.bcfr = 0x10; + break; + + case 0x250: + dev->regs.bcfr = 0x08; + break; + + case 0x280: + dev->regs.bcfr = 0x04; + break; + + case 0x2a0: + dev->regs.bcfr = 0x02; + break; + + case 0x2e0: + dev->regs.bcfr = 0x01; + break; + } + + return dev->regs.bcfr; + break; + + case 0x04: + switch (dev->bios_addr) { + case 0xdc000: + dev->regs.pcfr = 0x80; + break; + + case 0xd8000: + dev->regs.pcfr = 0x40; + break; + + case 0xcc000: + dev->regs.pcfr = 0x20; + break; + + case 0xc8000: + dev->regs.pcfr = 0x10; + break; + } + + return dev->regs.pcfr; + break; + + case 0x05: + return dev->regs.gacfr; + + case 0x06: + return dev->regs.ctrl; + + case 0x07: + return dev->regs.streg; + + case 0x08: + return dev->regs.idcfr; + + case 0x09: + return (dev->regs.da >> 8); + + case 0x0a: + return (dev->regs.da & 0xff); + + case 0x0b: + return (dev->regs.vptr >> 12) & 0xff; + + case 0x0c: + return (dev->regs.vptr >> 4) & 0xff; + + case 0x0d: + return (dev->regs.vptr & 0x0f) << 4; + + case 0x0e: + case 0x0f: + if (!(dev->regs.ctrl & 0x80)) + return 0xff; + + threec503_set_drq(dev); + + return threec503_chipmem_read(dev, dev->regs.da++, 1); + } + + return 0; +} + + +static void +threec503_nic_hi_write(uint16_t addr, uint8_t val, void *priv) +{ + threec503_t *dev = (threec503_t *)priv; + + threec503_log("3Com503: Write GA address=%04x, val=%04x\n", addr, val); + + switch (addr & 0x0f) { + case 0x00: + dev->regs.pstr = val; + break; + + case 0x01: + dev->regs.pspr = val; + break; + + case 0x02: + dev->regs.dqtr = val; + break; + + case 0x05: + if ((dev->regs.gacfr & 0x0f) != (val & 0x0f)) { + mem_mapping_disable(&dev->ram_mapping); + + switch (val & 0x0f) { + case 0: /*ROM mapping*/ + /* FIXME: Implement this when a BIOS is found/generated. */ + break; + + case 9: /*RAM mapping*/ + mem_mapping_enable(&dev->ram_mapping); + break; + + default: /*No ROM mapping*/ + break; + } + } + + if (!(val & 0x80)) + threec503_interrupt(dev, 1); + else + threec503_interrupt(dev, 0); + + dev->regs.gacfr = val; + break; + + case 0x06: + if (val & 1) { + threec503_reset(dev); + dev->dp8390.ISR.reset = 1; + dev->regs.ctrl = 0x0b; + return; + } + + if ((val & 0x80) != (dev->regs.ctrl & 0x80)) { + if (val & 0x80) + dev->regs.streg |= 0x88; + else + dev->regs.streg &= ~0x88; + dev->regs.streg &= ~0x10; + } + dev->regs.ctrl = val; + break; + + case 0x08: + switch (val & 0xf0) { + case 0x00: + case 0x10: + case 0x20: + case 0x40: + case 0x80: + dev->regs.idcfr = (dev->regs.idcfr & 0x0f) | (val & 0xf0); + break; + + default: + threec503_log("Trying to set multiple IRQs: %02x\n", val); + break; + } + + switch (val & 0x0f) { + case 0x00: + case 0x01: + case 0x02: + case 0x04: + dev->regs.idcfr = (dev->regs.idcfr & 0xf0) | (val & 0x0f); + break; + + case 0x08: + break; + + default: + threec503_log("Trying to set multiple DMA channels: %02x\n", val); + break; + } + break; + + case 0x09: + dev->regs.da = (val << 8) | (dev->regs.da & 0xff); + break; + + case 0x0a: + dev->regs.da = (dev->regs.da & 0xff00) | val; + break; + + case 0x0b: + dev->regs.vptr = (val << 12) | (dev->regs.vptr & 0xfff); + break; + + case 0x0c: + dev->regs.vptr = (val << 4) | (dev->regs.vptr & 0xff00f); + break; + + case 0x0d: + dev->regs.vptr = (val << 4) | (dev->regs.vptr & 0xffff0); + break; + + case 0x0e: + case 0x0f: + if (!(dev->regs.ctrl & 0x80)) + return; + + threec503_set_drq(dev); + + threec503_chipmem_write(dev, dev->regs.da++, val, 1); + break; + } +} + + +static void +threec503_nic_ioremove(threec503_t *dev, uint16_t addr) +{ + io_removehandler(addr, 0x10, + threec503_nic_lo_read, NULL, NULL, + threec503_nic_lo_write, NULL, NULL, dev); + + io_removehandler(addr+0x400, 0x10, + threec503_nic_hi_read, NULL, NULL, + threec503_nic_hi_write, NULL, NULL, dev); +} + + +static void +threec503_nic_ioset(threec503_t *dev, uint16_t addr) +{ + io_sethandler(addr, 0x10, + threec503_nic_lo_read, NULL, NULL, + threec503_nic_lo_write, NULL, NULL, dev); + + io_sethandler(addr+0x400, 0x10, + threec503_nic_hi_read, NULL, NULL, + threec503_nic_hi_write, NULL, NULL, dev); +} + + +static void +threec503_tx(threec503_t *dev, uint32_t val) +{ + dev->dp8390.CR.tx_packet = 0; + dev->dp8390.TSR.tx_ok = 1; + dev->dp8390.ISR.pkt_tx = 1; + + /* Generate an interrupt if not masked */ + if (dev->dp8390.IMR.tx_inte) + threec503_interrupt(dev, 1); + dev->dp8390.tx_timer_active = 0; +} + + +/* + * Called by the platform-specific code when an Ethernet frame + * has been received. The destination address is tested to see + * if it should be accepted, and if the RX ring has enough room, + * it is copied into it and the receive process is updated. + */ +static void +threec503_rx(void *priv, uint8_t *buf, int io_len) +{ + static uint8_t bcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; + threec503_t *dev = (threec503_t *)priv; + uint8_t pkthdr[4]; + uint8_t *startptr; + int rx_pages, avail; + int idx, nextpage; + int endbytes; + + /* FIXME: move to upper layer */ + ui_sb_update_icon(SB_NETWORK, 1); + + if (io_len != 60) + threec503_log("3Com503: rx_frame with length %d\n", io_len); + + if ((dev->dp8390.CR.stop != 0) || (dev->dp8390.page_start == 0)) return; + + /* + * Add the pkt header + CRC to the length, and work + * out how many 256-byte pages the frame would occupy. + */ + rx_pages = (io_len + sizeof(pkthdr) + sizeof(uint32_t) + 255)/256; + if (dev->dp8390.curr_page < dev->dp8390.bound_ptr) { + avail = dev->dp8390.bound_ptr - dev->dp8390.curr_page; + } else { + avail = (dev->dp8390.page_stop - dev->dp8390.page_start) - + (dev->dp8390.curr_page - dev->dp8390.bound_ptr); + } + + /* + * Avoid getting into a buffer overflow condition by + * not attempting to do partial receives. The emulation + * to handle this condition seems particularly painful. + */ + if ((avail < rx_pages) +#if NE2K_NEVER_FULL_RING + || (avail == rx_pages) +#endif + ) { + threec503_log("3Com503: no space\n"); + + /* FIXME: move to upper layer */ + ui_sb_update_icon(SB_NETWORK, 0); + return; + } + + if ((io_len < 40/*60*/) && !dev->dp8390.RCR.runts_ok) { + threec503_log("3Com503: rejected small packet, length %d\n", io_len); + + /* FIXME: move to upper layer */ + ui_sb_update_icon(SB_NETWORK, 0); + return; + } + + /* Some computers don't care... */ + if (io_len < 60) + io_len = 60; + + threec503_log("3Com503: RX %x:%x:%x:%x:%x:%x > %x:%x:%x:%x:%x:%x len %d\n", + buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], + io_len); + + /* Do address filtering if not in promiscuous mode. */ + if (! dev->dp8390.RCR.promisc) { + /* If this is a broadcast frame.. */ + if (! memcmp(buf, bcast_addr, 6)) { + /* Broadcast not enabled, we're done. */ + if (! dev->dp8390.RCR.broadcast) { + threec503_log("3Com503: RX BC disabled\n"); + + /* FIXME: move to upper layer */ + ui_sb_update_icon(SB_NETWORK, 0); + return; + } + } + + /* If this is a multicast frame.. */ + else if (buf[0] & 0x01) { + /* Multicast not enabled, we're done. */ + if (! dev->dp8390.RCR.multicast) { +#if 1 + threec503_log("3Com503: RX MC disabled\n"); +#endif + + /* FIXME: move to upper layer */ + ui_sb_update_icon(SB_NETWORK, 0); + return; + } + + /* Are we listening to this multicast address? */ + idx = mcast_index(buf); + if (! (dev->dp8390.mchash[idx>>3] & (1<<(idx&0x7)))) { + threec503_log("3Com503: RX MC not listed\n"); + + /* FIXME: move to upper layer */ + ui_sb_update_icon(SB_NETWORK, 0); + return; + } + } + + /* Unicast, must be for us.. */ + else if (memcmp(buf, dev->dp8390.physaddr, 6)) return; + } else + threec503_log("3Com503: RX promiscuous receive\n"); + + nextpage = dev->dp8390.curr_page + rx_pages; + if (nextpage >= dev->dp8390.page_stop) + nextpage -= (dev->dp8390.page_stop - dev->dp8390.page_start); + + /* Set up packet header. */ + pkthdr[0] = 0x01; /* RXOK - packet is OK */ + if (buf[0] & 0x01) + pkthdr[0] |= 0x20; /* MULTICAST packet */ + pkthdr[1] = nextpage; /* ptr to next packet */ + pkthdr[2] = (io_len + sizeof(pkthdr))&0xff; /* length-low */ + pkthdr[3] = (io_len + sizeof(pkthdr))>>8; /* length-hi */ + threec503_log("3Com503: RX pkthdr [%02x %02x %02x %02x]\n", + pkthdr[0], pkthdr[1], pkthdr[2], pkthdr[3]); + + /* Copy into buffer, update curpage, and signal interrupt if config'd */ + startptr = &dev->dp8390.mem[(dev->dp8390.curr_page * 256) - DP8390_WORD_MEMSTART]; + memcpy(startptr, pkthdr, sizeof(pkthdr)); + if ((nextpage > dev->dp8390.curr_page) || + ((dev->dp8390.curr_page + rx_pages) == dev->dp8390.page_stop)) { + memcpy(startptr+sizeof(pkthdr), buf, io_len); + } else { + endbytes = (dev->dp8390.page_stop - dev->dp8390.curr_page) * 256; + memcpy(startptr+sizeof(pkthdr), buf, endbytes-sizeof(pkthdr)); + startptr = &dev->dp8390.mem[(dev->dp8390.page_start * 256) - DP8390_WORD_MEMSTART]; + memcpy(startptr, buf+endbytes-sizeof(pkthdr), io_len-endbytes+8); + } + dev->dp8390.curr_page = nextpage; + + dev->dp8390.RSR.rx_ok = 1; + dev->dp8390.RSR.rx_mbit = (buf[0] & 0x01) ? 1 : 0; + dev->dp8390.ISR.pkt_rx = 1; + + if (dev->dp8390.IMR.rx_inte) + threec503_interrupt(dev, 1); + + /* FIXME: move to upper layer */ + ui_sb_update_icon(SB_NETWORK, 0); +} + + +static void * +threec503_nic_init(const device_t *info) +{ + uint32_t mac; + threec503_t *dev; + + dev = malloc(sizeof(threec503_t)); + memset(dev, 0x00, sizeof(threec503_t)); + dev->maclocal[0] = 0x02; /* 02:60:8C (3Com OID) */ + dev->maclocal[1] = 0x60; + dev->maclocal[2] = 0x8C; + + dev->base_address = device_get_config_hex16("base"); + dev->base_irq = device_get_config_int("irq"); + dev->dma_channel = device_get_config_int("dma"); + dev->bios_addr = device_get_config_hex20("bios_addr"); + + /* See if we have a local MAC address configured. */ + mac = device_get_config_mac("mac", -1); + + /* + * Make this device known to the I/O system. + * PnP and PCI devices start with address spaces inactive. + */ + threec503_nic_ioset(dev, dev->base_address); + + /* Set up our BIA. */ + if (mac & 0xff000000) { + /* Generate new local MAC. */ + dev->maclocal[3] = random_generate(); + dev->maclocal[4] = random_generate(); + dev->maclocal[5] = random_generate(); + mac = (((int) dev->maclocal[3]) << 16); + mac |= (((int) dev->maclocal[4]) << 8); + mac |= ((int) dev->maclocal[5]); + device_set_config_mac("mac", mac); + } else { + dev->maclocal[3] = (mac>>16) & 0xff; + dev->maclocal[4] = (mac>>8) & 0xff; + dev->maclocal[5] = (mac & 0xff); + } + memcpy(dev->dp8390.physaddr, dev->maclocal, sizeof(dev->maclocal)); + + threec503_log("I/O=%04x, IRQ=%d, MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", + dev->base_address, dev->base_irq, + dev->dp8390.physaddr[0], dev->dp8390.physaddr[1], dev->dp8390.physaddr[2], + dev->dp8390.physaddr[3], dev->dp8390.physaddr[4], dev->dp8390.physaddr[5]); + + /* Reset the board. */ + threec503_reset(dev); + + /* Attach ourselves to the network module. */ + network_attach(dev, dev->dp8390.physaddr, threec503_rx); + + /* Map this system into the memory map. */ + mem_mapping_add(&dev->ram_mapping, dev->bios_addr, 0x4000, + threec503_ram_read, NULL, NULL, + threec503_ram_write, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); + mem_mapping_disable(&dev->ram_mapping); + + return(dev); +} + + +static void +threec503_nic_close(void *priv) +{ + threec503_t *dev = (threec503_t *)priv; + + /* Make sure the platform layer is shut down. */ + network_close(); + + threec503_nic_ioremove(dev, dev->base_address); + + threec503_log("3Com503: closed\n"); + + free(dev); +} + + +static const device_config_t threec503_config[] = +{ + { + "base", "Address", CONFIG_HEX16, "", 0x300, + { + { + "0x250", 0x250 + }, + { + "0x280", 0x280 + }, + { + "0x2a0", 0x2a0 + }, + { + "0x2e0", 0x2e0 + }, + { + "0x300", 0x300 + }, + { + "0x310", 0x310 + }, + { + "0x330", 0x330 + }, + { + "0x350", 0x350 + }, + { + "", 0 + } + }, + { { NULL, { NULL } } }, + { 0, 0, 0 } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 3, + { + { + "IRQ 2", 2 + }, + { + "IRQ 3", 3 + }, + { + "IRQ 4", 4 + }, + { + "IRQ 5", 5 + }, + { + "", 0 + } + }, + { { NULL, { NULL } } }, + { 0, 0, 0 } + }, + { + "dma", "DMA", CONFIG_SELECTION, "", 3, + { + { + "DMA 1", 1 + }, + { + "DMA 2", 2 + }, + { + "DMA 3", 3 + }, + { + "", 0 + } + }, + { { NULL, { NULL } } }, + { 0, 0, 0 } + }, + { + "mac", "MAC Address", CONFIG_MAC, "", -1, + { + { + "", 0 + } + }, + { { NULL, { NULL } } }, + { 0, 0, 0 } + }, + { + "bios_addr", "BIOS address", CONFIG_HEX20, "", 0xCC000, + { + { + "DC00", 0xDC000 + }, + { + "D800", 0xD8000 + }, + { + "C800", 0xC8000 + }, + { + "CC00", 0xCC000 + }, + { + "", 0 + } + }, + { { NULL, { NULL } } }, + { 0, 0, 0 } + }, + { + "", "", -1, "", -1, + { + { + "", 0 + } + }, + { { NULL, { NULL } } }, + { 0, 0, 0 } + } +}; + + +const device_t threec503_device = { + "3Com EtherLink II", + DEVICE_ISA, + 0, + threec503_nic_init, threec503_nic_close, NULL, + NULL, NULL, NULL, + threec503_config +}; diff --git a/src/network/net_3c503.h b/src/network/net_3c503.h new file mode 100644 index 000000000..6cc656b9f --- /dev/null +++ b/src/network/net_3c503.h @@ -0,0 +1,7 @@ +#ifndef NET_3C503_H +# define NET_3C503_H + +extern const device_t threec503_device; + + +#endif /*NET_3C503_H*/ diff --git a/src/network/net_dp8390.c b/src/network/net_dp8390.c new file mode 100644 index 000000000..ee24ecd1e --- /dev/null +++ b/src/network/net_dp8390.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H + +/* + * Return the 6-bit index into the multicast + * table. Stolen unashamedly from FreeBSD's if_ed.c + */ +int +mcast_index(const void *dst) +{ +#define POLYNOMIAL 0x04c11db6 + uint32_t crc = 0xffffffffL; + int carry, i, j; + uint8_t b; + uint8_t *ep = (uint8_t *)dst; + + for (i=6; --i>=0;) { + b = *ep++; + for (j = 8; --j >= 0;) { + carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); + crc <<= 1; + b >>= 1; + if (carry) + crc = ((crc ^ POLYNOMIAL) | carry); + } + } + return(crc >> 26); +#undef POLYNOMIAL +} diff --git a/src/network/net_dp8390.h b/src/network/net_dp8390.h new file mode 100644 index 000000000..16b2d0188 --- /dev/null +++ b/src/network/net_dp8390.h @@ -0,0 +1,158 @@ +#ifndef NET_DP8390_H +# define NET_DP8390_H + +/* Never completely fill the ne2k ring so that we never + hit the unclear completely full buffer condition. */ +#define DP8390_NEVER_FULL_RING (1) + +#define DP8390_DWORD_MEMSIZ (32*1024) +#define DP8390_DWORD_MEMSTART (16*1024) +#define DP8390_DWORD_MEMEND (DP8390_DWORD_MEMSTART+DP8390_DWORD_MEMSIZ) + +#define DP8390_WORD_MEMSIZ (16*1024) +#define DP8390_WORD_MEMSTART (8*1024) +#define DP8390_WORD_MEMEND (DP8390_WORD_MEMSTART+DP8390_WORD_MEMSIZ) + +typedef struct { + /* Page 0 */ + + /* Command Register - 00h read/write */ + struct CR_t { + int stop; /* STP - Software Reset command */ + int start; /* START - start the NIC */ + int tx_packet; /* TXP - initiate packet transmission */ + uint8_t rdma_cmd; /* RD0,RD1,RD2 - Remote DMA command */ + uint8_t pgsel; /* PS0,PS1 - Page select */ + } CR; + + /* Interrupt Status Register - 07h read/write */ + struct ISR_t { + int pkt_rx; /* PRX - packet received with no errors */ + int pkt_tx; /* PTX - packet txed with no errors */ + int rx_err; /* RXE - packet rxed with 1 or more errors */ + int tx_err; /* TXE - packet txed " " " " " */ + int overwrite; /* OVW - rx buffer resources exhausted */ + int cnt_oflow; /* CNT - network tally counter MSB's set */ + int rdma_done; /* RDC - remote DMA complete */ + int reset; /* RST - reset status */ + } ISR; + + /* Interrupt Mask Register - 0fh write */ + struct IMR_t { + int rx_inte; /* PRXE - packet rx interrupt enable */ + int tx_inte; /* PTXE - packet tx interrput enable */ + int rxerr_inte; /* RXEE - rx error interrupt enable */ + int txerr_inte; /* TXEE - tx error interrupt enable */ + int overw_inte; /* OVWE - overwrite warn int enable */ + int cofl_inte; /* CNTE - counter o'flow int enable */ + int rdma_inte; /* RDCE - remote DMA complete int enable */ + int reserved; /* D7 - reserved */ + } IMR; + + /* Data Configuration Register - 0eh write */ + struct DCR_t { + int wdsize; /* WTS - 8/16-bit select */ + int endian; /* BOS - byte-order select */ + int longaddr; /* LAS - long-address select */ + int loop; /* LS - loopback select */ + int auto_rx; /* AR - auto-remove rx pkts with remote DMA */ + uint8_t fifo_size; /* FT0,FT1 - fifo threshold */ + } DCR; + + /* Transmit Configuration Register - 0dh write */ + struct TCR_t { + int crc_disable; /* CRC - inhibit tx CRC */ + uint8_t loop_cntl; /* LB0,LB1 - loopback control */ + int ext_stoptx; /* ATD - allow tx disable by external mcast */ + int coll_prio; /* OFST - backoff algorithm select */ + uint8_t reserved; /* D5,D6,D7 - reserved */ + } TCR; + + /* Transmit Status Register - 04h read */ + struct TSR_t { + int tx_ok; /* PTX - tx complete without error */ + int reserved; /* D1 - reserved */ + int collided; /* COL - tx collided >= 1 times */ + int aborted; /* ABT - aborted due to excessive collisions */ + int no_carrier; /* CRS - carrier-sense lost */ + int fifo_ur; /* FU - FIFO underrun */ + int cd_hbeat; /* CDH - no tx cd-heartbeat from transceiver */ + int ow_coll; /* OWC - out-of-window collision */ + } TSR; + + /* Receive Configuration Register - 0ch write */ + struct RCR_t { + int errors_ok; /* SEP - accept pkts with rx errors */ + int runts_ok; /* AR - accept < 64-byte runts */ + int broadcast; /* AB - accept eth broadcast address */ + int multicast; /* AM - check mcast hash array */ + int promisc; /* PRO - accept all packets */ + int monitor; /* MON - check pkts, but don't rx */ + uint8_t reserved; /* D6,D7 - reserved */ + } RCR; + + /* Receive Status Register - 0ch read */ + struct RSR_t { + int rx_ok; /* PRX - rx complete without error */ + int bad_crc; /* CRC - Bad CRC detected */ + int bad_falign; /* FAE - frame alignment error */ + int fifo_or; /* FO - FIFO overrun */ + int rx_missed; /* MPA - missed packet error */ + int rx_mbit; /* PHY - unicast or mcast/bcast address match */ + int rx_disabled; /* DIS - set when in monitor mode */ + int deferred; /* DFR - collision active */ + } RSR; + + uint16_t local_dma; /* 01,02h read ; current local DMA addr */ + uint8_t page_start; /* 01h write ; page start regr */ + uint8_t page_stop; /* 02h write ; page stop regr */ + uint8_t bound_ptr; /* 03h read/write ; boundary pointer */ + uint8_t tx_page_start; /* 04h write ; transmit page start reg */ + uint8_t num_coll; /* 05h read ; number-of-collisions reg */ + uint16_t tx_bytes; /* 05,06h write ; transmit byte-count reg */ + uint8_t fifo; /* 06h read ; FIFO */ + uint16_t remote_dma; /* 08,09h read ; current remote DMA addr */ + uint16_t remote_start; /* 08,09h write ; remote start address reg */ + uint16_t remote_bytes; /* 0a,0bh write ; remote byte-count reg */ + uint8_t tallycnt_0; /* 0dh read ; tally ctr 0 (frame align errs) */ + uint8_t tallycnt_1; /* 0eh read ; tally ctr 1 (CRC errors) */ + uint8_t tallycnt_2; /* 0fh read ; tally ctr 2 (missed pkt errs) */ + + /* Page 1 */ + + /* Command Register 00h (repeated) */ + + uint8_t physaddr[6]; /* 01-06h read/write ; MAC address */ + uint8_t curr_page; /* 07h read/write ; current page register */ + uint8_t mchash[8]; /* 08-0fh read/write ; multicast hash array */ + + /* Page 2 - diagnostic use only */ + + /* Command Register 00h (repeated) */ + + /* Page Start Register 01h read (repeated) + * Page Stop Register 02h read (repeated) + * Current Local DMA Address 01,02h write (repeated) + * Transmit Page start address 04h read (repeated) + * Receive Configuration Register 0ch read (repeated) + * Transmit Configuration Register 0dh read (repeated) + * Data Configuration Register 0eh read (repeated) + * Interrupt Mask Register 0fh read (repeated) + */ + uint8_t rempkt_ptr; /* 03h read/write ; rmt next-pkt ptr */ + uint8_t localpkt_ptr; /* 05h read/write ; lcl next-pkt ptr */ + uint16_t address_cnt; /* 06,07h read/write ; address cter */ + + /* Page 3 - should never be modified. */ + + /* Novell ASIC state */ + uint8_t mem[DP8390_DWORD_MEMSIZ]; /* on-chip packet memory */ + + int tx_timer_index; + int tx_timer_active; + +} dp8390_t; + +extern int mcast_index(const void *dst); + +#endif /*NET_DP8390_H*/ diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index 97376fce7..43a7b347f 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -12,7 +12,7 @@ * - Realtek RTL8019AS (ISA 16-bit, PnP); * - Realtek RTL8029AS (PCI). * - * Version: @(#)net_ne2000.c 1.0.3 2018/03/15 + * Version: @(#)net_ne2000.c 1.0.4 2018/04/26 * * Based on @(#)ne2k.cc v1.56.2.1 2004/02/02 22:37:22 cbothamy * @@ -63,6 +63,7 @@ #include "../device.h" #include "../ui.h" #include "network.h" +#include "net_dp8390.h" #include "net_ne2000.h" #include "bswap.h" @@ -89,18 +90,6 @@ enum { #define PCI_REGSIZE 256 /* size of PCI space */ -/* Never completely fill the ne2k ring so that we never - hit the unclear completely full buffer condition. */ -#define NE2K_NEVER_FULL_RING (1) - -#define NE2K_MEMSIZ (32*1024) -#define NE2K_MEMSTART (16*1024) -#define NE2K_MEMEND (NE2K_MEMSTART+NE2K_MEMSIZ) - -#define NE1K_MEMSIZ (16*1024) -#define NE1K_MEMSTART (8*1024) -#define NE1K_MEMEND (NE1K_MEMSTART+NE1K_MEMSIZ) - 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, @@ -108,141 +97,8 @@ uint8_t pnp_init_key[32] = { 0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE, typedef struct { - /* Page 0 */ - - /* Command Register - 00h read/write */ - struct CR_t { - int stop; /* STP - Software Reset command */ - int start; /* START - start the NIC */ - int tx_packet; /* TXP - initiate packet transmission */ - uint8_t rdma_cmd; /* RD0,RD1,RD2 - Remote DMA command */ - uint8_t pgsel; /* PS0,PS1 - Page select */ - } CR; - - /* Interrupt Status Register - 07h read/write */ - struct ISR_t { - int pkt_rx; /* PRX - packet received with no errors */ - int pkt_tx; /* PTX - packet txed with no errors */ - int rx_err; /* RXE - packet rxed with 1 or more errors */ - int tx_err; /* TXE - packet txed " " " " " */ - int overwrite; /* OVW - rx buffer resources exhausted */ - int cnt_oflow; /* CNT - network tally counter MSB's set */ - int rdma_done; /* RDC - remote DMA complete */ - int reset; /* RST - reset status */ - } ISR; - - /* Interrupt Mask Register - 0fh write */ - struct IMR_t { - int rx_inte; /* PRXE - packet rx interrupt enable */ - int tx_inte; /* PTXE - packet tx interrput enable */ - int rxerr_inte; /* RXEE - rx error interrupt enable */ - int txerr_inte; /* TXEE - tx error interrupt enable */ - int overw_inte; /* OVWE - overwrite warn int enable */ - int cofl_inte; /* CNTE - counter o'flow int enable */ - int rdma_inte; /* RDCE - remote DMA complete int enable */ - int reserved; /* D7 - reserved */ - } IMR; - - /* Data Configuration Register - 0eh write */ - struct DCR_t { - int wdsize; /* WTS - 8/16-bit select */ - int endian; /* BOS - byte-order select */ - int longaddr; /* LAS - long-address select */ - int loop; /* LS - loopback select */ - int auto_rx; /* AR - auto-remove rx pkts with remote DMA */ - uint8_t fifo_size; /* FT0,FT1 - fifo threshold */ - } DCR; - - /* Transmit Configuration Register - 0dh write */ - struct TCR_t { - int crc_disable; /* CRC - inhibit tx CRC */ - uint8_t loop_cntl; /* LB0,LB1 - loopback control */ - int ext_stoptx; /* ATD - allow tx disable by external mcast */ - int coll_prio; /* OFST - backoff algorithm select */ - uint8_t reserved; /* D5,D6,D7 - reserved */ - } TCR; - - /* Transmit Status Register - 04h read */ - struct TSR_t { - int tx_ok; /* PTX - tx complete without error */ - int reserved; /* D1 - reserved */ - int collided; /* COL - tx collided >= 1 times */ - int aborted; /* ABT - aborted due to excessive collisions */ - int no_carrier; /* CRS - carrier-sense lost */ - int fifo_ur; /* FU - FIFO underrun */ - int cd_hbeat; /* CDH - no tx cd-heartbeat from transceiver */ - int ow_coll; /* OWC - out-of-window collision */ - } TSR; - - /* Receive Configuration Register - 0ch write */ - struct RCR_t { - int errors_ok; /* SEP - accept pkts with rx errors */ - int runts_ok; /* AR - accept < 64-byte runts */ - int broadcast; /* AB - accept eth broadcast address */ - int multicast; /* AM - check mcast hash array */ - int promisc; /* PRO - accept all packets */ - int monitor; /* MON - check pkts, but don't rx */ - uint8_t reserved; /* D6,D7 - reserved */ - } RCR; - - /* Receive Status Register - 0ch read */ - struct RSR_t { - int rx_ok; /* PRX - rx complete without error */ - int bad_crc; /* CRC - Bad CRC detected */ - int bad_falign; /* FAE - frame alignment error */ - int fifo_or; /* FO - FIFO overrun */ - int rx_missed; /* MPA - missed packet error */ - int rx_mbit; /* PHY - unicast or mcast/bcast address match */ - int rx_disabled; /* DIS - set when in monitor mode */ - int deferred; /* DFR - collision active */ - } RSR; - - uint16_t local_dma; /* 01,02h read ; current local DMA addr */ - uint8_t page_start; /* 01h write ; page start regr */ - uint8_t page_stop; /* 02h write ; page stop regr */ - uint8_t bound_ptr; /* 03h read/write ; boundary pointer */ - uint8_t tx_page_start; /* 04h write ; transmit page start reg */ - uint8_t num_coll; /* 05h read ; number-of-collisions reg */ - uint16_t tx_bytes; /* 05,06h write ; transmit byte-count reg */ - uint8_t fifo; /* 06h read ; FIFO */ - uint16_t remote_dma; /* 08,09h read ; current remote DMA addr */ - uint16_t remote_start; /* 08,09h write ; remote start address reg */ - uint16_t remote_bytes; /* 0a,0bh write ; remote byte-count reg */ - uint8_t tallycnt_0; /* 0dh read ; tally ctr 0 (frame align errs) */ - uint8_t tallycnt_1; /* 0eh read ; tally ctr 1 (CRC errors) */ - uint8_t tallycnt_2; /* 0fh read ; tally ctr 2 (missed pkt errs) */ - - /* Page 1 */ - - /* Command Register 00h (repeated) */ - - uint8_t physaddr[6]; /* 01-06h read/write ; MAC address */ - uint8_t curr_page; /* 07h read/write ; current page register */ - uint8_t mchash[8]; /* 08-0fh read/write ; multicast hash array */ - - /* Page 2 - diagnostic use only */ - - /* Command Register 00h (repeated) */ - - /* Page Start Register 01h read (repeated) - * Page Stop Register 02h read (repeated) - * Current Local DMA Address 01,02h write (repeated) - * Transmit Page start address 04h read (repeated) - * Receive Configuration Register 0ch read (repeated) - * Transmit Configuration Register 0dh read (repeated) - * Data Configuration Register 0eh read (repeated) - * Interrupt Mask Register 0fh read (repeated) - */ - uint8_t rempkt_ptr; /* 03h read/write ; rmt next-pkt ptr */ - uint8_t localpkt_ptr; /* 05h read/write ; lcl next-pkt ptr */ - uint16_t address_cnt; /* 06,07h read/write ; address cter */ - - /* Page 3 - should never be modified. */ - - /* Novell ASIC state */ - uint8_t macaddr[32]; /* ASIC ROM'd MAC address, even bytes */ - uint8_t mem[NE2K_MEMSIZ]; /* on-chip packet memory */ - + dp8390_t dp8390; + uint8_t macaddr[32]; /* ASIC ROM'd MAC address, even bytes */ int board; int is_pci, is_8bit; const char *name; @@ -255,8 +111,6 @@ typedef struct { uint8_t pnp_res_data[256]; bar_t pci_bar[2]; uint8_t pci_regs[PCI_REGSIZE]; - int tx_timer_index; - int tx_timer_active; uint8_t maclocal[6]; /* configured MAC (local) address */ uint8_t eeprom[128]; /* for RTL8029AS */ rom_t bios_rom; @@ -330,30 +184,30 @@ nic_reset(void *priv) if (dev->board >= NE2K_NE2000) { /* Initialize the MAC address area by doubling the physical address */ - dev->macaddr[0] = dev->physaddr[0]; - dev->macaddr[1] = dev->physaddr[0]; - dev->macaddr[2] = dev->physaddr[1]; - dev->macaddr[3] = dev->physaddr[1]; - dev->macaddr[4] = dev->physaddr[2]; - dev->macaddr[5] = dev->physaddr[2]; - dev->macaddr[6] = dev->physaddr[3]; - dev->macaddr[7] = dev->physaddr[3]; - dev->macaddr[8] = dev->physaddr[4]; - dev->macaddr[9] = dev->physaddr[4]; - dev->macaddr[10] = dev->physaddr[5]; - dev->macaddr[11] = dev->physaddr[5]; + dev->macaddr[0] = dev->dp8390.physaddr[0]; + dev->macaddr[1] = dev->dp8390.physaddr[0]; + dev->macaddr[2] = dev->dp8390.physaddr[1]; + dev->macaddr[3] = dev->dp8390.physaddr[1]; + dev->macaddr[4] = dev->dp8390.physaddr[2]; + dev->macaddr[5] = dev->dp8390.physaddr[2]; + dev->macaddr[6] = dev->dp8390.physaddr[3]; + dev->macaddr[7] = dev->dp8390.physaddr[3]; + dev->macaddr[8] = dev->dp8390.physaddr[4]; + dev->macaddr[9] = dev->dp8390.physaddr[4]; + dev->macaddr[10] = dev->dp8390.physaddr[5]; + dev->macaddr[11] = dev->dp8390.physaddr[5]; /* ne2k signature */ for (i=12; i<32; i++) dev->macaddr[i] = 0x57; } else { /* Initialize the MAC address area by doubling the physical address */ - dev->macaddr[0] = dev->physaddr[0]; - dev->macaddr[1] = dev->physaddr[1]; - dev->macaddr[2] = dev->physaddr[2]; - dev->macaddr[3] = dev->physaddr[3]; - dev->macaddr[4] = dev->physaddr[4]; - dev->macaddr[5] = dev->physaddr[5]; + dev->macaddr[0] = dev->dp8390.physaddr[0]; + dev->macaddr[1] = dev->dp8390.physaddr[1]; + dev->macaddr[2] = dev->dp8390.physaddr[2]; + dev->macaddr[3] = dev->dp8390.physaddr[3]; + dev->macaddr[4] = dev->dp8390.physaddr[4]; + dev->macaddr[5] = dev->dp8390.physaddr[5]; /* ne1k signature */ for (i=6; i<16; i++) @@ -361,42 +215,42 @@ nic_reset(void *priv) } /* Zero out registers and memory */ - memset(&dev->CR, 0x00, sizeof(dev->CR) ); - memset(&dev->ISR, 0x00, sizeof(dev->ISR)); - memset(&dev->IMR, 0x00, sizeof(dev->IMR)); - memset(&dev->DCR, 0x00, sizeof(dev->DCR)); - memset(&dev->TCR, 0x00, sizeof(dev->TCR)); - memset(&dev->TSR, 0x00, sizeof(dev->TSR)); - memset(&dev->RSR, 0x00, sizeof(dev->RSR)); - dev->tx_timer_active = 0; - dev->local_dma = 0; - dev->page_start = 0; - dev->page_stop = 0; - dev->bound_ptr = 0; - dev->tx_page_start = 0; - dev->num_coll = 0; - dev->tx_bytes = 0; - dev->fifo = 0; - dev->remote_dma = 0; - dev->remote_start = 0; - dev->remote_bytes = 0; - dev->tallycnt_0 = 0; - dev->tallycnt_1 = 0; - dev->tallycnt_2 = 0; + memset(&dev->dp8390.CR, 0x00, sizeof(dev->dp8390.CR) ); + memset(&dev->dp8390.ISR, 0x00, sizeof(dev->dp8390.ISR)); + memset(&dev->dp8390.IMR, 0x00, sizeof(dev->dp8390.IMR)); + memset(&dev->dp8390.DCR, 0x00, sizeof(dev->dp8390.DCR)); + memset(&dev->dp8390.TCR, 0x00, sizeof(dev->dp8390.TCR)); + memset(&dev->dp8390.TSR, 0x00, sizeof(dev->dp8390.TSR)); + memset(&dev->dp8390.RSR, 0x00, sizeof(dev->dp8390.RSR)); + dev->dp8390.tx_timer_active = 0; + dev->dp8390.local_dma = 0; + dev->dp8390.page_start = 0; + dev->dp8390.page_stop = 0; + dev->dp8390.bound_ptr = 0; + dev->dp8390.tx_page_start = 0; + dev->dp8390.num_coll = 0; + dev->dp8390.tx_bytes = 0; + dev->dp8390.fifo = 0; + dev->dp8390.remote_dma = 0; + dev->dp8390.remote_start = 0; + dev->dp8390.remote_bytes = 0; + dev->dp8390.tallycnt_0 = 0; + dev->dp8390.tallycnt_1 = 0; + dev->dp8390.tallycnt_2 = 0; - dev->curr_page = 0; + dev->dp8390.curr_page = 0; - dev->rempkt_ptr = 0; - dev->localpkt_ptr = 0; - dev->address_cnt = 0; + dev->dp8390.rempkt_ptr = 0; + dev->dp8390.localpkt_ptr = 0; + dev->dp8390.address_cnt = 0; - memset(&dev->mem, 0x00, sizeof(dev->mem)); + memset(&dev->dp8390.mem, 0x00, sizeof(dev->dp8390.mem)); /* Set power-up conditions */ - dev->CR.stop = 1; - dev->CR.rdma_cmd = 4; - dev->ISR.reset = 1; - dev->DCR.longaddr = 1; + dev->dp8390.CR.stop = 1; + dev->dp8390.CR.rdma_cmd = 4; + dev->dp8390.ISR.reset = 1; + dev->dp8390.DCR.longaddr = 1; nic_interrupt(dev, 0); } @@ -407,8 +261,8 @@ nic_soft_reset(void *priv) { nic_t *dev = (nic_t *)priv; - memset(&(dev->ISR), 0x00, sizeof(dev->ISR)); - dev->ISR.reset = 1; + memset(&(dev->dp8390.ISR), 0x00, sizeof(dev->dp8390.ISR)); + dev->dp8390.ISR.reset = 1; } @@ -444,14 +298,14 @@ chipmem_read(nic_t *dev, uint32_t addr, unsigned int len) return(retval); } - if ((addr >= NE2K_MEMSTART) && (addr < NE2K_MEMEND)) { - retval = dev->mem[addr - NE2K_MEMSTART]; + if ((addr >= DP8390_DWORD_MEMSTART) && (addr < DP8390_DWORD_MEMEND)) { + retval = dev->dp8390.mem[addr - DP8390_DWORD_MEMSTART]; if ((len == 2) || (len == 4)) { - retval |= (dev->mem[addr - NE2K_MEMSTART + 1] << 8); + retval |= (dev->dp8390.mem[addr - DP8390_DWORD_MEMSTART + 1] << 8); } if (len == 4) { - retval |= (dev->mem[addr - NE2K_MEMSTART + 2] << 16); - retval |= (dev->mem[addr - NE2K_MEMSTART + 3] << 24); + retval |= (dev->dp8390.mem[addr - DP8390_DWORD_MEMSTART + 2] << 16); + retval |= (dev->dp8390.mem[addr - DP8390_DWORD_MEMSTART + 3] << 24); } return(retval); } @@ -464,10 +318,10 @@ chipmem_read(nic_t *dev, uint32_t addr, unsigned int len) return(retval); } - if ((addr >= NE1K_MEMSTART) && (addr < NE1K_MEMEND)) { - retval = dev->mem[addr - NE1K_MEMSTART]; + if ((addr >= DP8390_WORD_MEMSTART) && (addr < DP8390_WORD_MEMEND)) { + retval = dev->dp8390.mem[addr - DP8390_WORD_MEMSTART]; if (len == 2) { - retval |= (dev->mem[addr - NE1K_MEMSTART + 1] << 8); + retval |= (dev->dp8390.mem[addr - DP8390_WORD_MEMSTART + 1] << 8); } return(retval); } @@ -498,23 +352,23 @@ chipmem_write(nic_t *dev, uint32_t addr, uint32_t val, unsigned len) } if (dev->board >= NE2K_NE2000) { - if ((addr >= NE2K_MEMSTART) && (addr < NE2K_MEMEND)) { - dev->mem[addr-NE2K_MEMSTART] = val & 0xff; + if ((addr >= DP8390_DWORD_MEMSTART) && (addr < DP8390_DWORD_MEMEND)) { + dev->dp8390.mem[addr-DP8390_DWORD_MEMSTART] = val & 0xff; if ((len == 2) || (len == 4)) { - dev->mem[addr-NE2K_MEMSTART+1] = val >> 8; + dev->dp8390.mem[addr-DP8390_DWORD_MEMSTART+1] = val >> 8; } if (len == 4) { - dev->mem[addr-NE2K_MEMSTART+2] = val >> 16; - dev->mem[addr-NE2K_MEMSTART+3] = val >> 24; + dev->dp8390.mem[addr-DP8390_DWORD_MEMSTART+2] = val >> 16; + dev->dp8390.mem[addr-DP8390_DWORD_MEMSTART+3] = val >> 24; } } else { nelog(3, "%s: out-of-bounds chipmem write, %04X\n", dev->name, addr); } } else { - if ((addr >= NE1K_MEMSTART) && (addr < NE1K_MEMEND)) { - dev->mem[addr-NE1K_MEMSTART] = val & 0xff; + if ((addr >= DP8390_WORD_MEMSTART) && (addr < DP8390_WORD_MEMEND)) { + dev->dp8390.mem[addr-DP8390_WORD_MEMSTART] = val & 0xff; if (len == 2) { - dev->mem[addr-NE1K_MEMSTART+1] = val >> 8; + dev->dp8390.mem[addr-DP8390_WORD_MEMSTART+1] = val >> 8; } } else { nelog(3, "%s: out-of-bounds chipmem write, %04X\n", dev->name, addr); @@ -546,43 +400,43 @@ asic_read(nic_t *dev, uint32_t off, unsigned int len) /* A read remote-DMA command must have been issued, and the source-address and length registers must have been initialised. */ - if (len > dev->remote_bytes) { + if (len > dev->dp8390.remote_bytes) { nelog(3, "%s: DMA read underrun iolen=%d remote_bytes=%d\n", - dev->name, len, dev->remote_bytes); + dev->name, len, dev->dp8390.remote_bytes); } nelog(3, "%s: DMA read: addr=%4x remote_bytes=%d\n", - dev->name, dev->remote_dma,dev->remote_bytes); - retval = chipmem_read(dev, dev->remote_dma, len); + dev->name, dev->dp8390.remote_dma,dev->dp8390.remote_bytes); + retval = chipmem_read(dev, dev->dp8390.remote_dma, len); /* The 8390 bumps the address and decreases the byte count by the selected word size after every access, not by the amount of data requested by the host (io_len). */ if (len == 4) { - dev->remote_dma += len; + dev->dp8390.remote_dma += len; } else { - dev->remote_dma += (dev->DCR.wdsize + 1); + dev->dp8390.remote_dma += (dev->dp8390.DCR.wdsize + 1); } - if (dev->remote_dma == dev->page_stop << 8) { - dev->remote_dma = dev->page_start << 8; + if (dev->dp8390.remote_dma == dev->dp8390.page_stop << 8) { + dev->dp8390.remote_dma = dev->dp8390.page_start << 8; } /* keep s.remote_bytes from underflowing */ - if (dev->remote_bytes > dev->DCR.wdsize) { + if (dev->dp8390.remote_bytes > dev->dp8390.DCR.wdsize) { if (len == 4) { - dev->remote_bytes -= len; + dev->dp8390.remote_bytes -= len; } else { - dev->remote_bytes -= (dev->DCR.wdsize + 1); + dev->dp8390.remote_bytes -= (dev->dp8390.DCR.wdsize + 1); } } else { - dev->remote_bytes = 0; + dev->dp8390.remote_bytes = 0; } /* If all bytes have been written, signal remote-DMA complete */ - if (dev->remote_bytes == 0) { - dev->ISR.rdma_done = 1; - if (dev->IMR.rdma_inte) + if (dev->dp8390.remote_bytes == 0) { + dev->dp8390.ISR.rdma_done = 1; + if (dev->dp8390.IMR.rdma_inte) nic_interrupt(dev, 1); } break; @@ -609,35 +463,35 @@ asic_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) switch(off) { case 0x00: /* Data register - see asic_read for a description */ - if ((len > 1) && (dev->DCR.wdsize == 0)) { + if ((len > 1) && (dev->dp8390.DCR.wdsize == 0)) { nelog(3, "%s: DMA write length %d on byte mode operation\n", dev->name, len); break; } - if (dev->remote_bytes == 0) + if (dev->dp8390.remote_bytes == 0) nelog(3, "%s: DMA write, byte count 0\n", dev->name); - chipmem_write(dev, dev->remote_dma, val, len); + chipmem_write(dev, dev->dp8390.remote_dma, val, len); if (len == 4) - dev->remote_dma += len; + dev->dp8390.remote_dma += len; else - dev->remote_dma += (dev->DCR.wdsize + 1); + dev->dp8390.remote_dma += (dev->dp8390.DCR.wdsize + 1); - if (dev->remote_dma == dev->page_stop << 8) - dev->remote_dma = dev->page_start << 8; + if (dev->dp8390.remote_dma == dev->dp8390.page_stop << 8) + dev->dp8390.remote_dma = dev->dp8390.page_start << 8; if (len == 4) - dev->remote_bytes -= len; + dev->dp8390.remote_bytes -= len; else - dev->remote_bytes -= (dev->DCR.wdsize + 1); + dev->dp8390.remote_bytes -= (dev->dp8390.DCR.wdsize + 1); - if (dev->remote_bytes > NE2K_MEMSIZ) - dev->remote_bytes = 0; + if (dev->dp8390.remote_bytes > DP8390_DWORD_MEMSIZ) + dev->dp8390.remote_bytes = 0; /* If all bytes have been written, signal remote-DMA complete */ - if (dev->remote_bytes == 0) { - dev->ISR.rdma_done = 1; - if (dev->IMR.rdma_inte) + if (dev->dp8390.remote_bytes == 0) { + dev->dp8390.ISR.rdma_done = 1; + if (dev->dp8390.IMR.rdma_inte) nic_interrupt(dev, 1); } break; @@ -669,54 +523,54 @@ page0_read(nic_t *dev, uint32_t off, unsigned int len) switch(off) { case 0x01: /* CLDA0 */ - retval = (dev->local_dma & 0xff); + retval = (dev->dp8390.local_dma & 0xff); break; case 0x02: /* CLDA1 */ - retval = (dev->local_dma >> 8); + retval = (dev->dp8390.local_dma >> 8); break; case 0x03: /* BNRY */ - retval = dev->bound_ptr; + retval = dev->dp8390.bound_ptr; break; case 0x04: /* TSR */ - retval = ((dev->TSR.ow_coll << 7) | - (dev->TSR.cd_hbeat << 6) | - (dev->TSR.fifo_ur << 5) | - (dev->TSR.no_carrier << 4) | - (dev->TSR.aborted << 3) | - (dev->TSR.collided << 2) | - (dev->TSR.tx_ok)); + retval = ((dev->dp8390.TSR.ow_coll << 7) | + (dev->dp8390.TSR.cd_hbeat << 6) | + (dev->dp8390.TSR.fifo_ur << 5) | + (dev->dp8390.TSR.no_carrier << 4) | + (dev->dp8390.TSR.aborted << 3) | + (dev->dp8390.TSR.collided << 2) | + (dev->dp8390.TSR.tx_ok)); break; case 0x05: /* NCR */ - retval = dev->num_coll; + retval = dev->dp8390.num_coll; break; case 0x06: /* FIFO */ /* reading FIFO is only valid in loopback mode */ nelog(3, "%s: reading FIFO not supported yet\n", dev->name); - retval = dev->fifo; + retval = dev->dp8390.fifo; break; case 0x07: /* ISR */ - retval = ((dev->ISR.reset << 7) | - (dev->ISR.rdma_done << 6) | - (dev->ISR.cnt_oflow << 5) | - (dev->ISR.overwrite << 4) | - (dev->ISR.tx_err << 3) | - (dev->ISR.rx_err << 2) | - (dev->ISR.pkt_tx << 1) | - (dev->ISR.pkt_rx)); + retval = ((dev->dp8390.ISR.reset << 7) | + (dev->dp8390.ISR.rdma_done << 6) | + (dev->dp8390.ISR.cnt_oflow << 5) | + (dev->dp8390.ISR.overwrite << 4) | + (dev->dp8390.ISR.tx_err << 3) | + (dev->dp8390.ISR.rx_err << 2) | + (dev->dp8390.ISR.pkt_tx << 1) | + (dev->dp8390.ISR.pkt_rx)); break; case 0x08: /* CRDA0 */ - retval = (dev->remote_dma & 0xff); + retval = (dev->dp8390.remote_dma & 0xff); break; case 0x09: /* CRDA1 */ - retval = (dev->remote_dma >> 8); + retval = (dev->dp8390.remote_dma >> 8); break; case 0x0a: /* reserved / RTL8029ID0 */ @@ -742,26 +596,26 @@ page0_read(nic_t *dev, uint32_t off, unsigned int len) break; case 0x0c: /* RSR */ - retval = ((dev->RSR.deferred << 7) | - (dev->RSR.rx_disabled << 6) | - (dev->RSR.rx_mbit << 5) | - (dev->RSR.rx_missed << 4) | - (dev->RSR.fifo_or << 3) | - (dev->RSR.bad_falign << 2) | - (dev->RSR.bad_crc << 1) | - (dev->RSR.rx_ok)); + retval = ((dev->dp8390.RSR.deferred << 7) | + (dev->dp8390.RSR.rx_disabled << 6) | + (dev->dp8390.RSR.rx_mbit << 5) | + (dev->dp8390.RSR.rx_missed << 4) | + (dev->dp8390.RSR.fifo_or << 3) | + (dev->dp8390.RSR.bad_falign << 2) | + (dev->dp8390.RSR.bad_crc << 1) | + (dev->dp8390.RSR.rx_ok)); break; case 0x0d: /* CNTR0 */ - retval = dev->tallycnt_0; + retval = dev->dp8390.tallycnt_0; break; case 0x0e: /* CNTR1 */ - retval = dev->tallycnt_1; + retval = dev->dp8390.tallycnt_1; break; case 0x0f: /* CNTR2 */ - retval = dev->tallycnt_2; + retval = dev->dp8390.tallycnt_2; break; default: @@ -797,85 +651,85 @@ page0_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) switch(off) { case 0x01: /* PSTART */ - dev->page_start = val; + dev->dp8390.page_start = val; break; case 0x02: /* PSTOP */ - dev->page_stop = val; + dev->dp8390.page_stop = val; break; case 0x03: /* BNRY */ - dev->bound_ptr = val; + dev->dp8390.bound_ptr = val; break; case 0x04: /* TPSR */ - dev->tx_page_start = val; + dev->dp8390.tx_page_start = val; break; case 0x05: /* TBCR0 */ /* Clear out low byte and re-insert */ - dev->tx_bytes &= 0xff00; - dev->tx_bytes |= (val & 0xff); + dev->dp8390.tx_bytes &= 0xff00; + dev->dp8390.tx_bytes |= (val & 0xff); break; case 0x06: /* TBCR1 */ /* Clear out high byte and re-insert */ - dev->tx_bytes &= 0x00ff; - dev->tx_bytes |= ((val & 0xff) << 8); + dev->dp8390.tx_bytes &= 0x00ff; + dev->dp8390.tx_bytes |= ((val & 0xff) << 8); break; case 0x07: /* ISR */ val &= 0x7f; /* clear RST bit - status-only bit */ /* All other values are cleared iff the ISR bit is 1 */ - dev->ISR.pkt_rx &= !((int)((val & 0x01) == 0x01)); - dev->ISR.pkt_tx &= !((int)((val & 0x02) == 0x02)); - dev->ISR.rx_err &= !((int)((val & 0x04) == 0x04)); - dev->ISR.tx_err &= !((int)((val & 0x08) == 0x08)); - dev->ISR.overwrite &= !((int)((val & 0x10) == 0x10)); - dev->ISR.cnt_oflow &= !((int)((val & 0x20) == 0x20)); - dev->ISR.rdma_done &= !((int)((val & 0x40) == 0x40)); - val = ((dev->ISR.rdma_done << 6) | - (dev->ISR.cnt_oflow << 5) | - (dev->ISR.overwrite << 4) | - (dev->ISR.tx_err << 3) | - (dev->ISR.rx_err << 2) | - (dev->ISR.pkt_tx << 1) | - (dev->ISR.pkt_rx)); - val &= ((dev->IMR.rdma_inte << 6) | - (dev->IMR.cofl_inte << 5) | - (dev->IMR.overw_inte << 4) | - (dev->IMR.txerr_inte << 3) | - (dev->IMR.rxerr_inte << 2) | - (dev->IMR.tx_inte << 1) | - (dev->IMR.rx_inte)); + dev->dp8390.ISR.pkt_rx &= !((int)((val & 0x01) == 0x01)); + dev->dp8390.ISR.pkt_tx &= !((int)((val & 0x02) == 0x02)); + dev->dp8390.ISR.rx_err &= !((int)((val & 0x04) == 0x04)); + dev->dp8390.ISR.tx_err &= !((int)((val & 0x08) == 0x08)); + dev->dp8390.ISR.overwrite &= !((int)((val & 0x10) == 0x10)); + dev->dp8390.ISR.cnt_oflow &= !((int)((val & 0x20) == 0x20)); + dev->dp8390.ISR.rdma_done &= !((int)((val & 0x40) == 0x40)); + val = ((dev->dp8390.ISR.rdma_done << 6) | + (dev->dp8390.ISR.cnt_oflow << 5) | + (dev->dp8390.ISR.overwrite << 4) | + (dev->dp8390.ISR.tx_err << 3) | + (dev->dp8390.ISR.rx_err << 2) | + (dev->dp8390.ISR.pkt_tx << 1) | + (dev->dp8390.ISR.pkt_rx)); + val &= ((dev->dp8390.IMR.rdma_inte << 6) | + (dev->dp8390.IMR.cofl_inte << 5) | + (dev->dp8390.IMR.overw_inte << 4) | + (dev->dp8390.IMR.txerr_inte << 3) | + (dev->dp8390.IMR.rxerr_inte << 2) | + (dev->dp8390.IMR.tx_inte << 1) | + (dev->dp8390.IMR.rx_inte)); if (val == 0x00) nic_interrupt(dev, 0); break; case 0x08: /* RSAR0 */ /* Clear out low byte and re-insert */ - dev->remote_start &= 0xff00; - dev->remote_start |= (val & 0xff); - dev->remote_dma = dev->remote_start; + dev->dp8390.remote_start &= 0xff00; + dev->dp8390.remote_start |= (val & 0xff); + dev->dp8390.remote_dma = dev->dp8390.remote_start; break; case 0x09: /* RSAR1 */ /* Clear out high byte and re-insert */ - dev->remote_start &= 0x00ff; - dev->remote_start |= ((val & 0xff) << 8); - dev->remote_dma = dev->remote_start; + dev->dp8390.remote_start &= 0x00ff; + dev->dp8390.remote_start |= ((val & 0xff) << 8); + dev->dp8390.remote_dma = dev->dp8390.remote_start; break; case 0x0a: /* RBCR0 */ /* Clear out low byte and re-insert */ - dev->remote_bytes &= 0xff00; - dev->remote_bytes |= (val & 0xff); + dev->dp8390.remote_bytes &= 0xff00; + dev->dp8390.remote_bytes |= (val & 0xff); break; case 0x0b: /* RBCR1 */ /* Clear out high byte and re-insert */ - dev->remote_bytes &= 0x00ff; - dev->remote_bytes |= ((val & 0xff) << 8); + dev->dp8390.remote_bytes &= 0x00ff; + dev->dp8390.remote_bytes |= ((val & 0xff) << 8); break; case 0x0c: /* RCR */ @@ -886,12 +740,12 @@ page0_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) } /* Set all other bit-fields */ - dev->RCR.errors_ok = ((val & 0x01) == 0x01); - dev->RCR.runts_ok = ((val & 0x02) == 0x02); - dev->RCR.broadcast = ((val & 0x04) == 0x04); - dev->RCR.multicast = ((val & 0x08) == 0x08); - dev->RCR.promisc = ((val & 0x10) == 0x10); - dev->RCR.monitor = ((val & 0x20) == 0x20); + dev->dp8390.RCR.errors_ok = ((val & 0x01) == 0x01); + dev->dp8390.RCR.runts_ok = ((val & 0x02) == 0x02); + dev->dp8390.RCR.broadcast = ((val & 0x04) == 0x04); + dev->dp8390.RCR.multicast = ((val & 0x08) == 0x08); + dev->dp8390.RCR.promisc = ((val & 0x10) == 0x10); + dev->dp8390.RCR.monitor = ((val & 0x20) == 0x20); /* Monitor bit is a little suspicious... */ if (val & 0x20) nelog(3, "%s: RCR write, monitor bit set!\n", @@ -905,11 +759,11 @@ page0_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) /* Test loop mode (not supported) */ if (val & 0x06) { - dev->TCR.loop_cntl = (val & 0x6) >> 1; + dev->dp8390.TCR.loop_cntl = (val & 0x6) >> 1; nelog(3, "%s: TCR write, loop mode %d not supported\n", - dev->name, dev->TCR.loop_cntl); + dev->name, dev->dp8390.TCR.loop_cntl); } else { - dev->TCR.loop_cntl = 0; + dev->dp8390.TCR.loop_cntl = 0; } /* Inhibit-CRC not supported. */ @@ -922,7 +776,7 @@ page0_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) dev->name); /* Allow collision-offset to be set, although not used */ - dev->TCR.coll_prio = ((val & 0x08) == 0x08); + dev->dp8390.TCR.coll_prio = ((val & 0x08) == 0x08); break; case 0x0e: /* DCR */ @@ -939,12 +793,12 @@ page0_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) nelog(3, "%s: DCR write - AR set ???\n", dev->name); /* Set other values. */ - dev->DCR.wdsize = ((val & 0x01) == 0x01); - dev->DCR.endian = ((val & 0x02) == 0x02); - dev->DCR.longaddr = ((val & 0x04) == 0x04); /* illegal ? */ - dev->DCR.loop = ((val & 0x08) == 0x08); - dev->DCR.auto_rx = ((val & 0x10) == 0x10); /* also illegal ? */ - dev->DCR.fifo_size = (val & 0x50) >> 5; + dev->dp8390.DCR.wdsize = ((val & 0x01) == 0x01); + dev->dp8390.DCR.endian = ((val & 0x02) == 0x02); + dev->dp8390.DCR.longaddr = ((val & 0x04) == 0x04); /* illegal ? */ + dev->dp8390.DCR.loop = ((val & 0x08) == 0x08); + dev->dp8390.DCR.auto_rx = ((val & 0x10) == 0x10); /* also illegal ? */ + dev->dp8390.DCR.fifo_size = (val & 0x50) >> 5; break; case 0x0f: /* IMR */ @@ -953,20 +807,20 @@ page0_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) nelog(3, "%s: IMR write, reserved bit set\n",dev->name); /* Set other values */ - dev->IMR.rx_inte = ((val & 0x01) == 0x01); - dev->IMR.tx_inte = ((val & 0x02) == 0x02); - dev->IMR.rxerr_inte = ((val & 0x04) == 0x04); - dev->IMR.txerr_inte = ((val & 0x08) == 0x08); - dev->IMR.overw_inte = ((val & 0x10) == 0x10); - dev->IMR.cofl_inte = ((val & 0x20) == 0x20); - dev->IMR.rdma_inte = ((val & 0x40) == 0x40); - val2 = ((dev->ISR.rdma_done << 6) | - (dev->ISR.cnt_oflow << 5) | - (dev->ISR.overwrite << 4) | - (dev->ISR.tx_err << 3) | - (dev->ISR.rx_err << 2) | - (dev->ISR.pkt_tx << 1) | - (dev->ISR.pkt_rx)); + dev->dp8390.IMR.rx_inte = ((val & 0x01) == 0x01); + dev->dp8390.IMR.tx_inte = ((val & 0x02) == 0x02); + dev->dp8390.IMR.rxerr_inte = ((val & 0x04) == 0x04); + dev->dp8390.IMR.txerr_inte = ((val & 0x08) == 0x08); + dev->dp8390.IMR.overw_inte = ((val & 0x10) == 0x10); + dev->dp8390.IMR.cofl_inte = ((val & 0x20) == 0x20); + dev->dp8390.IMR.rdma_inte = ((val & 0x40) == 0x40); + val2 = ((dev->dp8390.ISR.rdma_done << 6) | + (dev->dp8390.ISR.cnt_oflow << 5) | + (dev->dp8390.ISR.overwrite << 4) | + (dev->dp8390.ISR.tx_err << 3) | + (dev->dp8390.ISR.rx_err << 2) | + (dev->dp8390.ISR.pkt_tx << 1) | + (dev->dp8390.ISR.pkt_rx)); if (((val & val2) & 0x7f) == 0) nic_interrupt(dev, 0); else @@ -995,12 +849,12 @@ page1_read(nic_t *dev, uint32_t off, unsigned int len) case 0x04: case 0x05: case 0x06: - return(dev->physaddr[off - 1]); + return(dev->dp8390.physaddr[off - 1]); case 0x07: /* CURR */ nelog(3, "%s: returning current page: 0x%02x\n", - dev->name, (dev->curr_page)); - return(dev->curr_page); + dev->name, (dev->dp8390.curr_page)); + return(dev->dp8390.curr_page); case 0x08: /* MAR0-7 */ case 0x09: @@ -1010,7 +864,7 @@ page1_read(nic_t *dev, uint32_t off, unsigned int len) case 0x0d: case 0x0e: case 0x0f: - return(dev->mchash[off - 8]); + return(dev->dp8390.mchash[off - 8]); default: nelog(3, "%s: Page1 read register 0x%02x out of range\n", @@ -1033,17 +887,17 @@ page1_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) case 0x04: case 0x05: case 0x06: - dev->physaddr[off - 1] = val; + dev->dp8390.physaddr[off - 1] = val; if (off == 6) nelog(3, "%s: physical address set to %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, - dev->physaddr[0], dev->physaddr[1], - dev->physaddr[2], dev->physaddr[3], - dev->physaddr[4], dev->physaddr[5]); + dev->dp8390.physaddr[0], dev->dp8390.physaddr[1], + dev->dp8390.physaddr[2], dev->dp8390.physaddr[3], + dev->dp8390.physaddr[4], dev->dp8390.physaddr[5]); break; case 0x07: /* CURR */ - dev->curr_page = val; + dev->dp8390.curr_page = val; break; case 0x08: /* MAR0-7 */ @@ -1054,7 +908,7 @@ page1_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) case 0x0d: case 0x0e: case 0x0f: - dev->mchash[off - 8] = val; + dev->dp8390.mchash[off - 8] = val; break; default: @@ -1074,25 +928,25 @@ page2_read(nic_t *dev, uint32_t off, unsigned int len) switch(off) { case 0x01: /* PSTART */ - return(dev->page_start); + return(dev->dp8390.page_start); case 0x02: /* PSTOP */ - return(dev->page_stop); + return(dev->dp8390.page_stop); case 0x03: /* Remote Next-packet pointer */ - return(dev->rempkt_ptr); + return(dev->dp8390.rempkt_ptr); case 0x04: /* TPSR */ - return(dev->tx_page_start); + return(dev->dp8390.tx_page_start); case 0x05: /* Local Next-packet pointer */ - return(dev->localpkt_ptr); + return(dev->dp8390.localpkt_ptr); case 0x06: /* Address counter (upper) */ - return(dev->address_cnt >> 8); + return(dev->dp8390.address_cnt >> 8); case 0x07: /* Address counter (lower) */ - return(dev->address_cnt & 0xff); + return(dev->dp8390.address_cnt & 0xff); case 0x08: /* Reserved */ case 0x09: @@ -1103,35 +957,35 @@ page2_read(nic_t *dev, uint32_t off, unsigned int len) return(0xff); case 0x0c: /* RCR */ - return ((dev->RCR.monitor << 5) | - (dev->RCR.promisc << 4) | - (dev->RCR.multicast << 3) | - (dev->RCR.broadcast << 2) | - (dev->RCR.runts_ok << 1) | - (dev->RCR.errors_ok)); + return ((dev->dp8390.RCR.monitor << 5) | + (dev->dp8390.RCR.promisc << 4) | + (dev->dp8390.RCR.multicast << 3) | + (dev->dp8390.RCR.broadcast << 2) | + (dev->dp8390.RCR.runts_ok << 1) | + (dev->dp8390.RCR.errors_ok)); case 0x0d: /* TCR */ - return ((dev->TCR.coll_prio << 4) | - (dev->TCR.ext_stoptx << 3) | - ((dev->TCR.loop_cntl & 0x3) << 1) | - (dev->TCR.crc_disable)); + return ((dev->dp8390.TCR.coll_prio << 4) | + (dev->dp8390.TCR.ext_stoptx << 3) | + ((dev->dp8390.TCR.loop_cntl & 0x3) << 1) | + (dev->dp8390.TCR.crc_disable)); case 0x0e: /* DCR */ - return (((dev->DCR.fifo_size & 0x3) << 5) | - (dev->DCR.auto_rx << 4) | - (dev->DCR.loop << 3) | - (dev->DCR.longaddr << 2) | - (dev->DCR.endian << 1) | - (dev->DCR.wdsize)); + return (((dev->dp8390.DCR.fifo_size & 0x3) << 5) | + (dev->dp8390.DCR.auto_rx << 4) | + (dev->dp8390.DCR.loop << 3) | + (dev->dp8390.DCR.longaddr << 2) | + (dev->dp8390.DCR.endian << 1) | + (dev->dp8390.DCR.wdsize)); case 0x0f: /* IMR */ - return ((dev->IMR.rdma_inte << 6) | - (dev->IMR.cofl_inte << 5) | - (dev->IMR.overw_inte << 4) | - (dev->IMR.txerr_inte << 3) | - (dev->IMR.rxerr_inte << 2) | - (dev->IMR.tx_inte << 1) | - (dev->IMR.rx_inte)); + return ((dev->dp8390.IMR.rdma_inte << 6) | + (dev->dp8390.IMR.cofl_inte << 5) | + (dev->dp8390.IMR.overw_inte << 4) | + (dev->dp8390.IMR.txerr_inte << 3) | + (dev->dp8390.IMR.rxerr_inte << 2) | + (dev->dp8390.IMR.tx_inte << 1) | + (dev->dp8390.IMR.rx_inte)); default: nelog(3, "%s: Page2 register 0x%02x out of range\n", @@ -1154,18 +1008,18 @@ page2_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) switch(off) { case 0x01: /* CLDA0 */ /* Clear out low byte and re-insert */ - dev->local_dma &= 0xff00; - dev->local_dma |= (val & 0xff); + dev->dp8390.local_dma &= 0xff00; + dev->dp8390.local_dma |= (val & 0xff); break; case 0x02: /* CLDA1 */ /* Clear out high byte and re-insert */ - dev->local_dma &= 0x00ff; - dev->local_dma |= ((val & 0xff) << 8); + dev->dp8390.local_dma &= 0x00ff; + dev->dp8390.local_dma |= ((val & 0xff) << 8); break; case 0x03: /* Remote Next-pkt pointer */ - dev->rempkt_ptr = val; + dev->dp8390.rempkt_ptr = val; break; case 0x04: @@ -1173,19 +1027,19 @@ page2_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) break; case 0x05: /* Local Next-packet pointer */ - dev->localpkt_ptr = val; + dev->dp8390.localpkt_ptr = val; break; case 0x06: /* Address counter (upper) */ /* Clear out high byte and re-insert */ - dev->address_cnt &= 0x00ff; - dev->address_cnt |= ((val & 0xff) << 8); + dev->dp8390.address_cnt &= 0x00ff; + dev->dp8390.address_cnt |= ((val & 0xff) << 8); break; case 0x07: /* Address counter (lower) */ /* Clear out low byte and re-insert */ - dev->address_cnt &= 0xff00; - dev->address_cnt |= (val & 0xff); + dev->dp8390.address_cnt &= 0xff00; + dev->dp8390.address_cnt |= (val & 0xff); break; case 0x08: @@ -1282,11 +1136,11 @@ read_cr(nic_t *dev) { uint32_t retval; - retval = (((dev->CR.pgsel & 0x03) << 6) | - ((dev->CR.rdma_cmd & 0x07) << 3) | - (dev->CR.tx_packet << 2) | - (dev->CR.start << 1) | - (dev->CR.stop)); + retval = (((dev->dp8390.CR.pgsel & 0x03) << 6) | + ((dev->dp8390.CR.rdma_cmd & 0x07) << 3) | + (dev->dp8390.CR.tx_packet << 2) | + (dev->dp8390.CR.start << 1) | + (dev->dp8390.CR.stop)); nelog(3, "%s: read CR returns 0x%02x\n", dev->name, retval); return(retval); @@ -1306,70 +1160,70 @@ write_cr(nic_t *dev, uint32_t val) /* Check for s/w reset */ if (val & 0x01) { - dev->ISR.reset = 1; - dev->CR.stop = 1; + dev->dp8390.ISR.reset = 1; + dev->dp8390.CR.stop = 1; } else { - dev->CR.stop = 0; + dev->dp8390.CR.stop = 0; } - dev->CR.rdma_cmd = (val & 0x38) >> 3; + dev->dp8390.CR.rdma_cmd = (val & 0x38) >> 3; /* If start command issued, the RST bit in the ISR */ /* must be cleared */ - if ((val & 0x02) && !dev->CR.start) - dev->ISR.reset = 0; + if ((val & 0x02) && !dev->dp8390.CR.start) + dev->dp8390.ISR.reset = 0; - dev->CR.start = ((val & 0x02) == 0x02); - dev->CR.pgsel = (val & 0xc0) >> 6; + dev->dp8390.CR.start = ((val & 0x02) == 0x02); + dev->dp8390.CR.pgsel = (val & 0xc0) >> 6; /* Check for send-packet command */ - if (dev->CR.rdma_cmd == 3) { + if (dev->dp8390.CR.rdma_cmd == 3) { /* Set up DMA read from receive ring */ - dev->remote_start = dev->remote_dma = dev->bound_ptr * 256; - dev->remote_bytes = (uint16_t) chipmem_read(dev, dev->bound_ptr * 256 + 2, 2); + dev->dp8390.remote_start = dev->dp8390.remote_dma = dev->dp8390.bound_ptr * 256; + dev->dp8390.remote_bytes = (uint16_t) chipmem_read(dev, dev->dp8390.bound_ptr * 256 + 2, 2); nelog(3, "%s: sending buffer #x%x length %d\n", - dev->name, dev->remote_start, dev->remote_bytes); + dev->name, dev->dp8390.remote_start, dev->dp8390.remote_bytes); } /* Check for start-tx */ - if ((val & 0x04) && dev->TCR.loop_cntl) { - if (dev->TCR.loop_cntl != 1) { + if ((val & 0x04) && dev->dp8390.TCR.loop_cntl) { + if (dev->dp8390.TCR.loop_cntl != 1) { nelog(3, "%s: loop mode %d not supported\n", - dev->name, dev->TCR.loop_cntl); + dev->name, dev->dp8390.TCR.loop_cntl); } else { if (dev->board >= NE2K_NE2000) { nic_rx(dev, - &dev->mem[dev->tx_page_start*256 - NE2K_MEMSTART], - dev->tx_bytes); + &dev->dp8390.mem[dev->dp8390.tx_page_start*256 - DP8390_DWORD_MEMSTART], + dev->dp8390.tx_bytes); } else { nic_rx(dev, - &dev->mem[dev->tx_page_start*256 - NE1K_MEMSTART], - dev->tx_bytes); + &dev->dp8390.mem[dev->dp8390.tx_page_start*256 - DP8390_WORD_MEMSTART], + dev->dp8390.tx_bytes); } } } else if (val & 0x04) { - if (dev->CR.stop || (!dev->CR.start && (dev->board < NE2K_RTL8019AS))) { - if (dev->tx_bytes == 0) /* njh@bandsman.co.uk */ { + if (dev->dp8390.CR.stop || (!dev->dp8390.CR.start && (dev->board < NE2K_RTL8019AS))) { + if (dev->dp8390.tx_bytes == 0) /* njh@bandsman.co.uk */ { return; /* Solaris9 probe */ } nelog(3, "%s: CR write - tx start, dev in reset\n", dev->name); } - if (dev->tx_bytes == 0) + if (dev->dp8390.tx_bytes == 0) nelog(3, "%s: CR write - tx start, tx bytes == 0\n", dev->name); /* Send the packet to the system driver */ - dev->CR.tx_packet = 1; + dev->dp8390.CR.tx_packet = 1; if (dev->board >= NE2K_NE2000) { - network_tx(&dev->mem[dev->tx_page_start*256 - NE2K_MEMSTART], - dev->tx_bytes); + network_tx(&dev->dp8390.mem[dev->dp8390.tx_page_start*256 - DP8390_DWORD_MEMSTART], + dev->dp8390.tx_bytes); } else { - network_tx(&dev->mem[dev->tx_page_start*256 - NE1K_MEMSTART], - dev->tx_bytes); + network_tx(&dev->dp8390.mem[dev->dp8390.tx_page_start*256 - DP8390_WORD_MEMSTART], + dev->dp8390.tx_bytes); } /* some more debug */ - if (dev->tx_timer_active) + if (dev->dp8390.tx_timer_active) nelog(3, "%s: CR write, tx timer still active\n", dev->name); nic_tx(dev, val); @@ -1378,9 +1232,9 @@ write_cr(nic_t *dev, uint32_t val) /* Linux probes for an interrupt by setting up a remote-DMA read * of 0 bytes with remote-DMA completion interrupts enabled. * Detect this here */ - if (dev->CR.rdma_cmd == 0x01 && dev->CR.start && dev->remote_bytes == 0) { - dev->ISR.rdma_done = 1; - if (dev->IMR.rdma_inte) { + if (dev->dp8390.CR.rdma_cmd == 0x01 && dev->dp8390.CR.start && dev->dp8390.remote_bytes == 0) { + dev->dp8390.ISR.rdma_done = 1; + if (dev->dp8390.IMR.rdma_inte) { nic_interrupt(dev, 1); if (! dev->is_pci) nic_interrupt(dev, 0); @@ -1401,7 +1255,7 @@ nic_read(nic_t *dev, uint32_t addr, unsigned len) retval = asic_read(dev, off - 0x10, len); } else if (off == 0x00) { retval = read_cr(dev); - } else switch(dev->CR.pgsel) { + } else switch(dev->dp8390.CR.pgsel) { case 0x00: retval = page0_read(dev, off, len); break; @@ -1420,7 +1274,7 @@ nic_read(nic_t *dev, uint32_t addr, unsigned len) default: nelog(3, "%s: unknown value of pgsel in read - %d\n", - dev->name, dev->CR.pgsel); + dev->name, dev->dp8390.CR.pgsel); break; } @@ -1440,7 +1294,7 @@ nic_readw(uint16_t addr, void *priv) { nic_t *dev = (nic_t *)priv; - if (dev->DCR.wdsize & 1) + if (dev->dp8390.DCR.wdsize & 1) return(nic_read(dev, addr, 2)); else return(nic_read(dev, addr, 1)); @@ -1469,7 +1323,7 @@ nic_write(nic_t *dev, uint32_t addr, uint32_t val, unsigned len) asic_write(dev, off - 0x10, val, len); } else if (off == 0x00) { write_cr(dev, val); - } else switch(dev->CR.pgsel) { + } else switch(dev->dp8390.CR.pgsel) { case 0x00: page0_write(dev, off, val, len); break; @@ -1488,7 +1342,7 @@ nic_write(nic_t *dev, uint32_t addr, uint32_t val, unsigned len) default: nelog(3, "%s: unknown value of pgsel in write - %d\n", - dev->name, dev->CR.pgsel); + dev->name, dev->dp8390.CR.pgsel); break; } } @@ -1506,7 +1360,7 @@ nic_writew(uint16_t addr, uint16_t val, void *priv) { nic_t *dev = (nic_t *)priv; - if (dev->DCR.wdsize & 1) + if (dev->dp8390.DCR.wdsize & 1) nic_write(dev, addr, val, 2); else nic_write(dev, addr, val, 1); @@ -2134,45 +1988,17 @@ nic_pci_write(int func, int addr, uint8_t val, void *priv) } -/* - * Return the 6-bit index into the multicast - * table. Stolen unashamedly from FreeBSD's if_ed.c - */ -static int -mcast_index(const void *dst) -{ -#define POLYNOMIAL 0x04c11db6 - uint32_t crc = 0xffffffffL; - int carry, i, j; - uint8_t b; - uint8_t *ep = (uint8_t *)dst; - - for (i=6; --i>=0;) { - b = *ep++; - for (j = 8; --j >= 0;) { - carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); - crc <<= 1; - b >>= 1; - if (carry) - crc = ((crc ^ POLYNOMIAL) | carry); - } - } - return(crc >> 26); -#undef POLYNOMIAL -} - - static void nic_tx(nic_t *dev, uint32_t val) { - dev->CR.tx_packet = 0; - dev->TSR.tx_ok = 1; - dev->ISR.pkt_tx = 1; + dev->dp8390.CR.tx_packet = 0; + dev->dp8390.TSR.tx_ok = 1; + dev->dp8390.ISR.pkt_tx = 1; /* Generate an interrupt if not masked */ - if (dev->IMR.tx_inte) + if (dev->dp8390.IMR.tx_inte) nic_interrupt(dev, 1); - dev->tx_timer_active = 0; + dev->dp8390.tx_timer_active = 0; } @@ -2199,18 +2025,18 @@ nic_rx(void *priv, uint8_t *buf, int io_len) if (io_len != 60) nelog(2, "%s: rx_frame with length %d\n", dev->name, io_len); - if ((dev->CR.stop != 0) || (dev->page_start == 0)) return; + if ((dev->dp8390.CR.stop != 0) || (dev->dp8390.page_start == 0)) return; /* * Add the pkt header + CRC to the length, and work * out how many 256-byte pages the frame would occupy. */ pages = (io_len + sizeof(pkthdr) + sizeof(uint32_t) + 255)/256; - if (dev->curr_page < dev->bound_ptr) { - avail = dev->bound_ptr - dev->curr_page; + if (dev->dp8390.curr_page < dev->dp8390.bound_ptr) { + avail = dev->dp8390.bound_ptr - dev->dp8390.curr_page; } else { - avail = (dev->page_stop - dev->page_start) - - (dev->curr_page - dev->bound_ptr); + avail = (dev->dp8390.page_stop - dev->dp8390.page_start) - + (dev->dp8390.curr_page - dev->dp8390.bound_ptr); } /* @@ -2230,7 +2056,7 @@ nic_rx(void *priv, uint8_t *buf, int io_len) return; } - if ((io_len < 40/*60*/) && !dev->RCR.runts_ok) { + if ((io_len < 40/*60*/) && !dev->dp8390.RCR.runts_ok) { nelog(1, "%s: rejected small packet, length %d\n", dev->name, io_len); //FIXME: move to upper layer @@ -2249,11 +2075,11 @@ nic_rx(void *priv, uint8_t *buf, int io_len) io_len); /* Do address filtering if not in promiscuous mode. */ - if (! dev->RCR.promisc) { + if (! dev->dp8390.RCR.promisc) { /* If this is a broadcast frame.. */ if (! memcmp(buf, bcast_addr, 6)) { /* Broadcast not enabled, we're done. */ - if (! dev->RCR.broadcast) { + if (! dev->dp8390.RCR.broadcast) { nelog(2, "%s: RX BC disabled\n", dev->name); //FIXME: move to upper layer @@ -2265,7 +2091,7 @@ nic_rx(void *priv, uint8_t *buf, int io_len) /* If this is a multicast frame.. */ else if (buf[0] & 0x01) { /* Multicast not enabled, we're done. */ - if (! dev->RCR.multicast) { + if (! dev->dp8390.RCR.multicast) { #if 1 nelog(2, "%s: RX MC disabled\n", dev->name); #endif @@ -2277,7 +2103,7 @@ nic_rx(void *priv, uint8_t *buf, int io_len) /* Are we listening to this multicast address? */ idx = mcast_index(buf); - if (! (dev->mchash[idx>>3] & (1<<(idx&0x7)))) { + if (! (dev->dp8390.mchash[idx>>3] & (1<<(idx&0x7)))) { nelog(2, "%s: RX MC not listed\n", dev->name); //FIXME: move to upper layer @@ -2287,14 +2113,14 @@ nic_rx(void *priv, uint8_t *buf, int io_len) } /* Unicast, must be for us.. */ - else if (memcmp(buf, dev->physaddr, 6)) return; + else if (memcmp(buf, dev->dp8390.physaddr, 6)) return; } else { nelog(2, "%s: RX promiscuous receive\n", dev->name); } - nextpage = dev->curr_page + pages; - if (nextpage >= dev->page_stop) - nextpage -= (dev->page_stop - dev->page_start); + nextpage = dev->dp8390.curr_page + pages; + if (nextpage >= dev->dp8390.page_stop) + nextpage -= (dev->dp8390.page_stop - dev->dp8390.page_start); /* Set up packet header. */ pkthdr[0] = 0x01; /* RXOK - packet is OK */ @@ -2308,29 +2134,29 @@ nic_rx(void *priv, uint8_t *buf, int io_len) /* Copy into buffer, update curpage, and signal interrupt if config'd */ if (dev->board >= NE2K_NE2000) - startptr = &dev->mem[(dev->curr_page * 256) - NE2K_MEMSTART]; + startptr = &dev->dp8390.mem[(dev->dp8390.curr_page * 256) - DP8390_DWORD_MEMSTART]; else - startptr = &dev->mem[(dev->curr_page * 256) - NE1K_MEMSTART]; + startptr = &dev->dp8390.mem[(dev->dp8390.curr_page * 256) - DP8390_WORD_MEMSTART]; memcpy(startptr, pkthdr, sizeof(pkthdr)); - if ((nextpage > dev->curr_page) || - ((dev->curr_page + pages) == dev->page_stop)) { + if ((nextpage > dev->dp8390.curr_page) || + ((dev->dp8390.curr_page + pages) == dev->dp8390.page_stop)) { memcpy(startptr+sizeof(pkthdr), buf, io_len); } else { - endbytes = (dev->page_stop - dev->curr_page) * 256; + endbytes = (dev->dp8390.page_stop - dev->dp8390.curr_page) * 256; memcpy(startptr+sizeof(pkthdr), buf, endbytes-sizeof(pkthdr)); if (dev->board >= NE2K_NE2000) - startptr = &dev->mem[(dev->page_start * 256) - NE2K_MEMSTART]; + startptr = &dev->dp8390.mem[(dev->dp8390.page_start * 256) - DP8390_DWORD_MEMSTART]; else - startptr = &dev->mem[(dev->page_start * 256) - NE1K_MEMSTART]; + startptr = &dev->dp8390.mem[(dev->dp8390.page_start * 256) - DP8390_WORD_MEMSTART]; memcpy(startptr, buf+endbytes-sizeof(pkthdr), io_len-endbytes+8); } - dev->curr_page = nextpage; + dev->dp8390.curr_page = nextpage; - dev->RSR.rx_ok = 1; - dev->RSR.rx_mbit = (buf[0] & 0x01) ? 1 : 0; - dev->ISR.pkt_rx = 1; + dev->dp8390.RSR.rx_ok = 1; + dev->dp8390.RSR.rx_mbit = (buf[0] & 0x01) ? 1 : 0; + dev->dp8390.ISR.pkt_rx = 1; - if (dev->IMR.rx_inte) + if (dev->dp8390.IMR.rx_inte) nic_interrupt(dev, 1); //FIXME: move to upper layer @@ -2472,12 +2298,12 @@ nic_init(const device_t *info) dev->maclocal[4] = (mac>>8) & 0xff; dev->maclocal[5] = (mac & 0xff); } - memcpy(dev->physaddr, dev->maclocal, sizeof(dev->maclocal)); + memcpy(dev->dp8390.physaddr, dev->maclocal, sizeof(dev->maclocal)); nelog(0, "%s: I/O=%04x, IRQ=%d, MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, dev->base_address, dev->base_irq, - dev->physaddr[0], dev->physaddr[1], dev->physaddr[2], - dev->physaddr[3], dev->physaddr[4], dev->physaddr[5]); + dev->dp8390.physaddr[0], dev->dp8390.physaddr[1], dev->dp8390.physaddr[2], + dev->dp8390.physaddr[3], dev->dp8390.physaddr[4], dev->dp8390.physaddr[5]); if (dev->board >= NE2K_RTL8019AS) { if (dev->is_pci) { @@ -2616,7 +2442,7 @@ nic_init(const device_t *info) nic_reset(dev); /* Attach ourselves to the network module. */ - network_attach(dev, dev->physaddr, nic_rx); + network_attach(dev, dev->dp8390.physaddr, nic_rx); nelog(1, "%s: %s attached IO=0x%X IRQ=%d\n", dev->name, dev->is_pci?"PCI":"ISA", dev->base_address, dev->base_irq); @@ -2814,7 +2640,7 @@ const device_t ne1000_device = { DEVICE_ISA, NE2K_NE1000, nic_init, nic_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, ne1000_config }; @@ -2823,7 +2649,7 @@ const device_t ne2000_device = { DEVICE_ISA | DEVICE_AT, NE2K_NE2000, nic_init, nic_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, ne2000_config }; @@ -2832,7 +2658,7 @@ const device_t rtl8019as_device = { DEVICE_ISA | DEVICE_AT, NE2K_RTL8019AS, nic_init, nic_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, rtl8019as_config }; @@ -2841,6 +2667,6 @@ const device_t rtl8029as_device = { DEVICE_PCI, NE2K_RTL8029AS, nic_init, nic_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, rtl8029as_config }; diff --git a/src/network/net_pcap.c b/src/network/net_pcap.c index a619868b6..78cf72f91 100644 --- a/src/network/net_pcap.c +++ b/src/network/net_pcap.c @@ -8,7 +8,7 @@ * * Handle WinPcap library processing. * - * Version: @(#)net_pcap.c 1.0.3 2018/03/15 + * Version: @(#)net_pcap.c 1.0.4 2018/04/29 * * Author: Fred N. van Kempen, * @@ -44,12 +44,13 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include #include +#include #include #include #include -#include +#define HAVE_STDARG_H #include "../86box.h" #include "../config.h" #include "../device.h" @@ -58,8 +59,53 @@ #include "network.h" +typedef int bpf_int32; +typedef unsigned int bpf_u_int32; + +/* + * The instruction data structure. + */ +struct bpf_insn { + unsigned short code; + unsigned char jt; + unsigned char jf; + bpf_u_int32 k; +}; + +/* + * Structure for "pcap_compile()", "pcap_setfilter()", etc.. + */ +struct bpf_program { + unsigned int bf_len; + struct bpf_insn *bf_insns; +}; + +typedef struct pcap_if pcap_if_t; + +typedef struct timeval { + long tv_sec; + long tv_usec; +} timeval; + +#define PCAP_ERRBUF_SIZE 256 + +struct pcap_pkthdr { + struct timeval ts; + bpf_u_int32 caplen; + bpf_u_int32 len; +}; + +struct pcap_if { + struct pcap_if *next; + char *name; + char *description; + void *addresses; + unsigned int flags; +}; + + static volatile void *pcap_handle; /* handle to WinPcap DLL */ -static volatile pcap_t *pcap; /* handle to WinPcap library */ +static volatile void *pcap; /* handle to WinPcap library */ static volatile thread_t *poll_tid; static const netcard_t *poll_card; /* netcard linked to us */ static event_t *poll_state; @@ -68,14 +114,15 @@ static event_t *poll_state; /* Pointers to the real functions. */ static const char *(*f_pcap_lib_version)(void); static int (*f_pcap_findalldevs)(pcap_if_t **,char *); -static void (*f_pcap_freealldevs)(pcap_if_t *); -static pcap_t *(*f_pcap_open_live)(const char *,int,int,int,char *); -static int (*f_pcap_compile)(pcap_t *,struct bpf_program *, +static void (*f_pcap_freealldevs)(void *); +static void *(*f_pcap_open_live)(const char *,int,int,int,char *); +static int (*f_pcap_compile)(void *,void *, const char *,int,bpf_u_int32); -static int (*f_pcap_setfilter)(pcap_t *,struct bpf_program *); -static const u_char *(*f_pcap_next)(pcap_t *,struct pcap_pkthdr *); -static int (*f_pcap_sendpacket)(pcap_t *,const u_char *,int); -static void (*f_pcap_close)(pcap_t *); +static int (*f_pcap_setfilter)(void *,void *); +static const unsigned char + *(*f_pcap_next)(void *,void *); +static int (*f_pcap_sendpacket)(void *,const unsigned char *,int); +static void (*f_pcap_close)(void *); static dllimp_t pcap_imports[] = { { "pcap_lib_version", &f_pcap_lib_version }, { "pcap_findalldevs", &f_pcap_findalldevs }, @@ -90,6 +137,26 @@ static dllimp_t pcap_imports[] = { }; +#ifdef ENABLE_PCAP_LOG +int pcap_do_log = ENABLE_PCAP_LOG; +#endif + + +static void +pcap_log(const char *format, ...) +{ +#ifdef ENABLE_PCAP_LOG + va_list ap; + + if (pcap_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + /* Handle the receiving of frames from the channel. */ static void poll_thread(void *arg) @@ -101,7 +168,7 @@ poll_thread(void *arg) uint16_t mac_cmp16[2]; event_t *evt; - pclog("PCAP: polling started.\n"); + pcap_log("PCAP: polling started.\n"); thread_set_event(poll_state); /* Create a waitable event. */ @@ -118,7 +185,7 @@ poll_thread(void *arg) if (pcap == NULL) break; /* Wait for the next packet to arrive. */ - data = (uint8_t *)f_pcap_next((pcap_t *)pcap, &h); + data = (uint8_t *)f_pcap_next((void *)pcap, &h); if (data != NULL) { /* Received MAC. */ mac_cmp32[0] = *(uint32_t *)(data+6); @@ -149,7 +216,7 @@ poll_thread(void *arg) if (evt != NULL) thread_destroy_event(evt); - pclog("PCAP: polling stopped.\n"); + pcap_log("PCAP: polling stopped.\n"); thread_set_event(poll_state); } @@ -181,7 +248,7 @@ net_pcap_prepare(netdev_t *list) /* Retrieve the device list from the local machine */ if (f_pcap_findalldevs(&devlist, errbuf) == -1) { - pclog("PCAP: error in pcap_findalldevs: %s\n", errbuf); + pcap_log("PCAP: error in pcap_findalldevs: %s\n", errbuf); return(-1); } @@ -231,11 +298,11 @@ net_pcap_init(void) strcpy(errbuf, f_pcap_lib_version()); str = strchr(errbuf, '('); if (str != NULL) *(str-1) = '\0'; - pclog("PCAP: initializing, %s\n", errbuf); + pcap_log("PCAP: initializing, %s\n", errbuf); /* Get the value of our capture interface. */ if ((network_host[0] == '\0') || !strcmp(network_host, "none")) { - pclog("PCAP: no interface configured!\n"); + pcap_log("PCAP: no interface configured!\n"); return(-1); } @@ -251,23 +318,23 @@ net_pcap_init(void) void net_pcap_close(void) { - pcap_t *pc; + void *pc; if (pcap == NULL) return; - pclog("PCAP: closing.\n"); + pcap_log("PCAP: closing.\n"); /* Tell the polling thread to shut down. */ - pc = (pcap_t *)pcap; pcap = NULL; + pc = (void *)pcap; pcap = NULL; /* Tell the thread to terminate. */ if (poll_tid != NULL) { network_busy(0); /* Wait for the thread to finish. */ - pclog("PCAP: waiting for thread to end...\n"); + pcap_log("PCAP: waiting for thread to end...\n"); thread_wait_event(poll_state, -1); - pclog("PCAP: thread ended\n"); + pcap_log("PCAP: thread ended\n"); thread_destroy_event(poll_state); poll_tid = NULL; @@ -314,34 +381,34 @@ net_pcap_reset(const netcard_t *card, uint8_t *mac) 1, /* promiscuous mode? */ 10, /* timeout in msec */ errbuf)) == NULL) { /* error buffer */ - pclog(" Unable to open device: %s!\n", network_host); + pcap_log(" Unable to open device: %s!\n", network_host); return(-1); } - pclog("PCAP: interface: %s\n", network_host); + pcap_log("PCAP: interface: %s\n", network_host); /* Create a MAC address based packet filter. */ - pclog("PCAP: installing filter for MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", + pcap_log("PCAP: installing filter for MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); sprintf(filter_exp, "( ((ether dst ff:ff:ff:ff:ff:ff) or (ether dst %02x:%02x:%02x:%02x:%02x:%02x)) and not (ether src %02x:%02x:%02x:%02x:%02x:%02x) )", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - if (f_pcap_compile((pcap_t *)pcap, &fp, filter_exp, 0, 0xffffffff) != -1) { - if (f_pcap_setfilter((pcap_t *)pcap, &fp) != 0) { - pclog("PCAP: error installing filter (%s) !\n", filter_exp); - f_pcap_close((pcap_t *)pcap); + if (f_pcap_compile((void *)pcap, &fp, filter_exp, 0, 0xffffffff) != -1) { + if (f_pcap_setfilter((void *)pcap, &fp) != 0) { + pcap_log("PCAP: error installing filter (%s) !\n", filter_exp); + f_pcap_close((void *)pcap); return(-1); } } else { - pclog("PCAP: could not compile filter (%s) !\n", filter_exp); - f_pcap_close((pcap_t *)pcap); + pcap_log("PCAP: could not compile filter (%s) !\n", filter_exp); + f_pcap_close((void *)pcap); return(-1); } /* Save the callback info. */ poll_card = card; - pclog("PCAP: starting thread..\n"); + pcap_log("PCAP: starting thread..\n"); poll_state = thread_create_event(); poll_tid = thread_create(poll_thread, mac); thread_wait_event(poll_state, -1); @@ -358,7 +425,7 @@ net_pcap_in(uint8_t *bufp, int len) network_busy(1); - f_pcap_sendpacket((pcap_t *)pcap, bufp, len); + f_pcap_sendpacket((void *)pcap, bufp, len); network_busy(0); } diff --git a/src/network/net_slirp.c b/src/network/net_slirp.c index 4fe2d4e98..3285702f4 100644 --- a/src/network/net_slirp.c +++ b/src/network/net_slirp.c @@ -8,7 +8,7 @@ * * Handle SLiRP library processing. * - * Version: @(#)net_slirp.c 1.0.2 2018/03/15 + * Version: @(#)net_slirp.c 1.0.3 2018/04/29 * * Author: Fred N. van Kempen, * @@ -44,11 +44,13 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "slirp/slirp.h" #include "slirp/queue.h" #include "../86box.h" @@ -64,6 +66,26 @@ static const netcard_t *poll_card; /* netcard attached to us */ static event_t *poll_state; +#ifdef ENABLE_SLIRP_LOG +int slirp_do_log = ENABLE_SLIRP_LOG; +#endif + + +static void +slirp_log(const char *format, ...) +{ +#ifdef ENABLE_SLIRP_LOG + va_list ap; + + if (slirp_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + static void slirp_tic(void) { @@ -100,7 +122,7 @@ poll_thread(UNUSED(void *arg)) struct queuepacket *qp; event_t *evt; - pclog("SLiRP: polling started.\n"); + slirp_log("SLiRP: polling started.\n"); thread_set_event(poll_state); /* Create a waitable event. */ @@ -123,10 +145,8 @@ poll_thread(UNUSED(void *arg)) if (QueuePeek(slirpq) != 0) { /* Grab a packet from the queue. */ qp = QueueDelete(slirpq); -#if 0 - pclog("SLiRP: inQ:%d got a %dbyte packet @%08lx\n", + slirp_log("SLiRP: inQ:%d got a %dbyte packet @%08lx\n", QueuePeek(slirpq), qp->len, qp); -#endif poll_card->rx(poll_card->priv, (uint8_t *)qp->data, qp->len); @@ -145,7 +165,7 @@ poll_thread(UNUSED(void *arg)) if (evt != NULL) thread_destroy_event(evt); - pclog("SLiRP: polling stopped.\n"); + slirp_log("SLiRP: polling stopped.\n"); thread_set_event(poll_state); } @@ -154,10 +174,10 @@ poll_thread(UNUSED(void *arg)) int net_slirp_init(void) { - pclog("SLiRP: initializing..\n"); + slirp_log("SLiRP: initializing..\n"); if (slirp_init() != 0) { - pclog("SLiRP could not be initialized!\n"); + slirp_log("SLiRP could not be initialized!\n"); return(-1); } @@ -178,7 +198,7 @@ net_slirp_reset(const netcard_t *card, uint8_t *mac) /* Save the callback info. */ poll_card = card; - pclog("SLiRP: creating thread..\n"); + slirp_log("SLiRP: creating thread..\n"); poll_state = thread_create_event(); poll_tid = thread_create(poll_thread, mac); thread_wait_event(poll_state, -1); @@ -194,7 +214,7 @@ net_slirp_close(void) if (slirpq == NULL) return; - pclog("SLiRP: closing.\n"); + slirp_log("SLiRP: closing.\n"); /* Tell the polling thread to shut down. */ sl = slirpq; slirpq = NULL; @@ -204,9 +224,9 @@ net_slirp_close(void) network_busy(0); /* Wait for the thread to finish. */ - pclog("SLiRP: waiting for thread to end...\n"); + slirp_log("SLiRP: waiting for thread to end...\n"); thread_wait_event(poll_state, -1); - pclog("SLiRP: thread ended\n"); + slirp_log("SLiRP: thread ended\n"); thread_destroy_event(poll_state); poll_tid = NULL; diff --git a/src/network/network.c b/src/network/network.c index 9a4bcd76a..107ffef6c 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -12,7 +12,7 @@ * it should be malloc'ed and then linked to the NETCARD def. * Will be done later. * - * Version: @(#)network.c 1.0.3 2018/03/15 + * Version: @(#)network.c 1.0.5 2018/06/09 * * Author: Fred N. van Kempen, * @@ -48,25 +48,27 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include #include +#include #include #include #include -#ifdef WALTJE -# include -#endif +#define HAVE_STDARG_H #include "../86box.h" #include "../device.h" #include "../plat.h" #include "../ui.h" #include "network.h" +#include "net_3c503.h" #include "net_ne2000.h" static netcard_t net_cards[] = { { "None", "none", NULL, NULL }, + { "[ISA] 3Com EtherLink II (3C503)","3c503", &threec503_device, + NULL }, { "[ISA] Novell NE1000", "ne1k", &ne1000_device, NULL }, { "[ISA] Novell NE2000", "ne2k", &ne2000_device, @@ -103,85 +105,24 @@ static struct { } poll_data; -#ifdef WALTJE -# define is_print(c) (isalnum((int)(c)) || ((c) == ' ')) - - -#if 0 -/* Dump a buffer in hex, standard output. */ -static void -hexdump(uint8_t *bufp, int len) -{ - char asci[20]; - uint8_t c; - int addr; - - addr = 0; - while (len-- > 0) { - c = bufp[addr]; - if ((addr % 16) == 0) { - printf("%06X %02X", addr, c); - } else { - printf(" %02X", c); - } - asci[(addr & 15)] = (char)((is_print(c) ? c : '.') & 0xff); - if ((++addr % 16) == 0) { - asci[16] = '\0'; - printf(" | %s |\n", asci); - } - } - - if (addr % 16) { - while (addr % 16) { - printf(" "); - asci[(addr & 15)] = ' '; - addr++; - } - asci[16] = '\0'; - printf(" | %s |\n", asci); - } -} +#ifdef ENABLE_NETWORK_LOG +int network_do_log = ENABLE_NETWORK_LOG; #endif -/* Dump a buffer in hex to output buffer. */ static void -hexdump_p(char *ptr, uint8_t *bufp, int len) +network_log(const char *format, ...) { - char asci[20]; - uint8_t c; - int addr; +#ifdef ENABLE_NETWORK_LOG + va_list ap; - addr = 0; - while (len-- > 0) { - c = bufp[addr]; - if ((addr % 16) == 0) { - sprintf(ptr, "%06X %02X", addr, c); - } else { - sprintf(ptr, " %02X", c); - } - ptr += strlen(ptr); - asci[(addr & 15)] = (char)((is_print(c) ? c : '.') & 0xff); - if ((++addr % 16) == 0) { - asci[16] = '\0'; - sprintf(ptr, " | %s |\n", asci); - ptr += strlen(ptr); - } + if (network_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); } - - if (addr % 16) { - while (addr % 16) { - sprintf(ptr, " "); - ptr += strlen(ptr); - asci[(addr & 15)] = ' '; - addr++; - } - asci[16] = '\0'; - sprintf(ptr, " | %s |\n", asci); - ptr += strlen(ptr); - } -} #endif +} void @@ -311,7 +252,7 @@ network_close(void) network_mutex = NULL; network_mac = NULL; - pclog("NETWORK: closed.\n"); + network_log("NETWORK: closed.\n"); } @@ -329,10 +270,10 @@ network_reset(void) int i = -1; #ifdef ENABLE_NIC_LOG - pclog("NETWORK: reset (type=%d, card=%d) debug=%d\n", + network_log("NETWORK: reset (type=%d, card=%d) debug=%d\n", network_type, network_card, nic_do_log); #else - pclog("NETWORK: reset (type=%d, card=%d)\n", + network_log("NETWORK: reset (type=%d, card=%d)\n", network_type, network_card); #endif ui_sb_update_icon(SB_NETWORK, 0); @@ -358,7 +299,7 @@ network_reset(void) if (i < 0) { /* Tell user we can't do this (at the moment.) */ - ui_msgbox(MBX_ERROR, (wchar_t *)IDS_2139); + ui_msgbox(MBX_ERROR, (wchar_t *)IDS_2102); // FIXME: we should ask in the dialog if they want to // reconfigure or quit, and throw them into the @@ -370,13 +311,13 @@ network_reset(void) return; } - pclog("NETWORK: set up for %s, card='%s'\n", + network_log("NETWORK: set up for %s, card='%s'\n", (network_type==NET_TYPE_SLIRP)?"SLiRP":"Pcap", net_cards[network_card].name); /* Add the (new?) card to the I/O system. */ if (net_cards[network_card].device) { - pclog("NETWORK: adding device '%s'\n", + network_log("NETWORK: adding device '%s'\n", net_cards[network_card].name); device_add(net_cards[network_card].device); } @@ -389,14 +330,6 @@ network_tx(uint8_t *bufp, int len) { ui_sb_update_icon(SB_NETWORK, 1); -#ifdef WALTJE -{ - char temp[4096]; - hexdump_p(temp, bufp, len); - pclog("NETWORK: >> len=%d\n%s\n", len, temp); -} -#endif - switch(network_type) { case NET_TYPE_PCAP: net_pcap_in(bufp, len); diff --git a/src/nvr.c b/src/nvr.c index fccde1882..2037b68e9 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -8,9 +8,7 @@ * * Implement a generic NVRAM/CMOS/RTC device. * - * NOTE: I should re-do 'intclk' using a TM struct. - * - * Version: @(#)nvr.c 1.0.3 2018/03/19 + * Version: @(#)nvr.c 1.0.10 2018/06/08 * * Author: Fred N. van Kempen, * @@ -46,12 +44,14 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include #include #include #include +#define HAVE_STDARG_H #include "86box.h" #include "device.h" #include "machine/machine.h" @@ -65,26 +65,34 @@ #include "nvr.h" -/* Define the internal clock. */ -typedef struct { - int16_t year; - int8_t sec; - int8_t min; - int8_t hour; - int8_t mday; - int8_t mon; -} intclk_t; - - -int enable_sync; /* configuration variable: enable time sync */ int nvr_dosave; /* NVR is dirty, needs saved */ static int8_t days_in_month[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; -static intclk_t intclk; +static struct tm intclk; static nvr_t *saved_nvr = NULL; +#ifdef ENABLE_NVR_LOG +int nvr_do_log = ENABLE_NVR_LOG; +#endif + + +static void +nvr_log(const char *format, ...) +{ +#ifdef ENABLE_NVR_LOG + va_list ap; + + if (nvr_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + /* Determine whether or not the year is leap. */ int nvr_is_leap(int year) @@ -109,29 +117,27 @@ nvr_get_days(int month, int year) /* One more second has passed, update the internal clock. */ -static void +void rtc_tick(void) { /* Ping the internal clock. */ - if (++intclk.sec == 60) { - intclk.sec = 0; - intclk.min++; - } - if (intclk.min == 60) { - intclk.min = 0; - intclk.hour++; - } - if (intclk.hour == 24) { - intclk.hour = 0; - intclk.mday++; - } - if (intclk.mday == (nvr_get_days(intclk.mon, intclk.year) + 1)) { - intclk.mday = 1; - intclk.mon++; - } - if (intclk.mon == 13) { - intclk.mon = 1; - intclk.year++; + if (++intclk.tm_sec == 60) { + intclk.tm_sec = 0; + if (++intclk.tm_min == 60) { + intclk.tm_min = 0; + if (++intclk.tm_hour == 24) { + intclk.tm_hour = 0; + if (++intclk.tm_mday == (nvr_get_days(intclk.tm_mon, + intclk.tm_year) + 1)) { + intclk.tm_mday = 1; + intclk.tm_mon++; + if (++intclk.tm_mon == 13) { + intclk.tm_mon = 1; + intclk.tm_year++; + } + } + } + } } } @@ -144,7 +150,8 @@ onesec_timer(void *priv) if (++nvr->onesec_cnt >= 100) { /* Update the internal clock. */ - rtc_tick(); + if (!(machines[machine].flags & MACHINE_AT)) + rtc_tick(); /* Update the RTC device if needed. */ if (nvr->tick != NULL) @@ -168,9 +175,9 @@ nvr_init(nvr_t *nvr) /* Set up the NVR file's name. */ sprintf(temp, "%s.nvr", machine_get_internal_name()); - c = strlen(temp)+1; - nvr->fn = (wchar_t *)malloc(c*sizeof(wchar_t)); - mbstowcs(nvr->fn, temp, c); + c = strlen(temp); + nvr->fn = (wchar_t *)malloc((c + 1) * sizeof(wchar_t)); + mbstowcs(nvr->fn, temp, c + 1); /* Initialize the internal clock as needed. */ memset(&intclk, 0x00, sizeof(intclk)); @@ -183,8 +190,8 @@ nvr_init(nvr_t *nvr) nvr_time_set(tm); } else { /* Reset the internal clock to 1980/01/01 00:00. */ - intclk.mon = 1; - intclk.year = 1980; + intclk.tm_mon = 1; + intclk.tm_year = 1980; } /* Set up our timer. */ @@ -201,124 +208,7 @@ nvr_init(nvr_t *nvr) } -/* - * Load an NVR from file. - * - * This function does two things, really. It clears and initializes - * the RTC and NVRAM areas, sets up defaults for the RTC part, and - * then attempts to load data from a saved file. - * - * Either way, after that, it will continue to configure the local - * RTC to operate, so it can update either the local RTC, and/or - * the one supplied by a client. - */ -int -nvr_load(void) -{ - FILE *f; - - /* Make sure we have been initialized. */ - if (saved_nvr == NULL) return(0); - - /* Clear out any old data. */ - memset(saved_nvr->regs, 0xff, sizeof(saved_nvr->regs)); - - /* Set the defaults. */ - if (saved_nvr->reset != NULL) - saved_nvr->reset(saved_nvr); - - /* Load the (relevant) part of the NVR contents. */ - if (saved_nvr->size != 0) { - pclog("NVR: loading from '%ls'\n", nvr_path(saved_nvr->fn)); - f = plat_fopen(nvr_path(saved_nvr->fn), L"rb"); - if (f != NULL) { - /* Read NVR contents from file. */ - (void)fread(saved_nvr->regs, saved_nvr->size, 1, f); - (void)fclose(f); - } - } - - if (romset == ROM_T1000) - t1000_nvr_load(); - else if (romset == ROM_T1200) - t1200_nvr_load(); - - /* Get the local RTC running! */ - if (saved_nvr->start != NULL) - saved_nvr->start(saved_nvr); - - return(1); -} - - -/* Save the current NVR to a file. */ -int -nvr_save(void) -{ - FILE *f; - - /* Make sure we have been initialized. */ - if (saved_nvr == NULL) return(0); - - if (saved_nvr->size != 0) { - pclog("NVR: saving to '%ls'\n", nvr_path(saved_nvr->fn)); - f = plat_fopen(nvr_path(saved_nvr->fn), L"wb"); - if (f != NULL) { - /* Save NVR contents to file. */ - (void)fwrite(saved_nvr->regs, saved_nvr->size, 1, f); - fclose(f); - } - } - - if (romset == ROM_T1000) - t1000_nvr_save(); - else if (romset == ROM_T1200) - t1200_nvr_save(); - - /* Device is clean again. */ - nvr_dosave = 0; - - return(1); -} - - -/* Get current time from internal clock. */ -void -nvr_time_get(struct tm *tm) -{ - int8_t dom, mon, sum, wd; - int16_t cent, yr; - - tm->tm_sec = intclk.sec; - tm->tm_min = intclk.min; - tm->tm_hour = intclk.hour; - dom = intclk.mday; - mon = intclk.mon; - yr = (intclk.year % 100); - cent = ((intclk.year - yr) / 100) % 4; - sum = dom+mon+yr+cent; - wd = ((sum + 6) % 7); - tm->tm_wday = wd; - tm->tm_mday = intclk.mday; - tm->tm_mon = (intclk.mon - 1); - tm->tm_year = (intclk.year - 1900); -} - - -/* Set internal clock time. */ -void -nvr_time_set(struct tm *tm) -{ - intclk.sec = tm->tm_sec; - intclk.min = tm->tm_min; - intclk.hour = tm->tm_hour; - intclk.mday = tm->tm_mday; - intclk.mon = (tm->tm_mon + 1); - intclk.year = (tm->tm_year + 1900); -} - - -/* Get an absolute path to the NVR folder. */ +/* Get path to the NVR folder. */ wchar_t * nvr_path(wchar_t *str) { @@ -341,6 +231,140 @@ nvr_path(wchar_t *str) } +/* + * Load an NVR from file. + * + * This function does two things, really. It clears and initializes + * the RTC and NVRAM areas, sets up defaults for the RTC part, and + * then attempts to load data from a saved file. + * + * Either way, after that, it will continue to configure the local + * RTC to operate, so it can update either the local RTC, and/or + * the one supplied by a client. + */ +int +nvr_load(void) +{ + wchar_t *path; + FILE *fp; + + /* Make sure we have been initialized. */ + if (saved_nvr == NULL) return(0); + + /* Clear out any old data. */ + // memset(saved_nvr->regs, 0x00, sizeof(saved_nvr->regs)); + memset(saved_nvr->regs, 0xff, sizeof(saved_nvr->regs)); + + /* Set the defaults. */ + if (saved_nvr->reset != NULL) + saved_nvr->reset(saved_nvr); + + /* Load the (relevant) part of the NVR contents. */ + if (saved_nvr->size != 0) { + path = nvr_path(saved_nvr->fn); + nvr_log("NVR: loading from '%ls'\n", path); + fp = plat_fopen(path, L"rb"); + if (fp != NULL) { + /* Read NVR contents from file. */ + (void)fread(saved_nvr->regs, saved_nvr->size, 1, fp); + (void)fclose(fp); + } + } + + if (romset == ROM_T1000) + t1000_nvr_load(); + else if (romset == ROM_T1200) + t1200_nvr_load(); + + /* Get the local RTC running! */ + if (saved_nvr->start != NULL) + saved_nvr->start(saved_nvr); + + return(1); +} + + +/* Save the current NVR to a file. */ +int +nvr_save(void) +{ + wchar_t *path; + FILE *fp; + + /* Make sure we have been initialized. */ + if (saved_nvr == NULL) return(0); + + if (saved_nvr->size != 0) { + path = nvr_path(saved_nvr->fn); + nvr_log("NVR: saving to '%ls'\n", path); + fp = plat_fopen(path, L"wb"); + if (fp != NULL) { + /* Save NVR contents to file. */ + (void)fwrite(saved_nvr->regs, saved_nvr->size, 1, fp); + fclose(fp); + } + } + + if (romset == ROM_T1000) + t1000_nvr_save(); + else if (romset == ROM_T1200) + t1200_nvr_save(); + + /* Device is clean again. */ + nvr_dosave = 0; + + return(1); +} + + +void +nvr_period_recalc(void) +{ + /* Make sure we have been initialized. */ + if (saved_nvr == NULL) return; + + if (saved_nvr->size != 0) + saved_nvr->recalc(saved_nvr); +} + + +/* Get current time from internal clock. */ +void +nvr_time_get(struct tm *tm) +{ + uint8_t dom, mon, sum, wd; + uint16_t cent, yr; + + tm->tm_sec = intclk.tm_sec; + tm->tm_min = intclk.tm_min; + tm->tm_hour = intclk.tm_hour; + dom = intclk.tm_mday; + mon = intclk.tm_mon; + yr = (intclk.tm_year % 100); + cent = ((intclk.tm_year - yr) / 100) % 4; + sum = dom+mon+yr+cent; + wd = ((sum + 6) % 7); + tm->tm_wday = wd; + tm->tm_mday = intclk.tm_mday; + tm->tm_mon = (intclk.tm_mon - 1); + tm->tm_year = (intclk.tm_year - 1900); +} + + +/* Set internal clock time. */ +void +nvr_time_set(struct tm *tm) +{ + intclk.tm_sec = tm->tm_sec; + intclk.tm_min = tm->tm_min; + intclk.tm_hour = tm->tm_hour; + intclk.tm_wday = tm->tm_wday; + intclk.tm_mday = tm->tm_mday; + intclk.tm_mon = (tm->tm_mon + 1); + intclk.tm_year = (tm->tm_year + 1900); +} + + /* Open or create a file in the NVR area. */ FILE * nvr_fopen(wchar_t *str, wchar_t *mode) diff --git a/src/nvr.h b/src/nvr.h index 8119948a2..11321fd6a 100644 --- a/src/nvr.h +++ b/src/nvr.h @@ -8,7 +8,7 @@ * * Definitions for the generic NVRAM/CMOS driver. * - * Version: @(#)nvr.h 1.0.2 2018/03/11 + * Version: @(#)nvr.h 1.0.7 2018/06/08 * * Author: Fred N. van Kempen, * @@ -58,29 +58,39 @@ /* Define a generic RTC/NVRAM device. */ typedef struct _nvr_ { - uint8_t regs[NVR_MAXSIZE]; /* these are the registers */ - wchar_t *fn; /* pathname of image file */ - uint16_t size; /* device configuration */ + wchar_t *fn; /* pathname of image file */ + uint16_t size; /* device configuration */ int8_t irq; - int8_t upd_stat, /* FIXME: move to private struct */ - addr; - int64_t upd_ecount, /* FIXME: move to private struct */ - onesec_time, - onesec_cnt, - rtctime; + uint8_t onesec_cnt; + int64_t onesec_time; + + void *data; /* local data */ /* Hooks to device functions. */ void (*reset)(struct _nvr_ *); void (*start)(struct _nvr_ *); void (*tick)(struct _nvr_ *); + void (*recalc)(struct _nvr_ *); + + uint8_t regs[NVR_MAXSIZE]; /* these are the registers */ } nvr_t; extern int nvr_dosave; +#ifdef EMU_DEVICE_H +extern const device_t at_nvr_old_device; +extern const device_t at_nvr_device; +extern const device_t ps_nvr_device; +extern const device_t amstrad_nvr_device; +#endif +extern void rtc_tick(void); + extern void nvr_init(nvr_t *); +extern wchar_t *nvr_path(wchar_t *str); +extern FILE *nvr_fopen(wchar_t *str, wchar_t *mode); extern int nvr_load(void); extern int nvr_save(void); @@ -88,12 +98,7 @@ extern int nvr_is_leap(int year); extern int nvr_get_days(int month, int year); extern void nvr_time_get(struct tm *); extern void nvr_time_set(struct tm *); - -extern wchar_t *nvr_path(wchar_t *str); -extern FILE *nvr_fopen(wchar_t *str, wchar_t *mode); - -extern void nvr_at_init(int irq); -extern void nvr_at_close(void); +extern void nvr_period_recalc(void); #endif /*EMU_NVR_H*/ diff --git a/src/nvr_at.c b/src/nvr_at.c index a982a962f..e6cd8cc71 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -189,7 +189,7 @@ * including the later update (DS12887A) which implemented a * "century" register to be compatible with Y2K. * - * Version: @(#)nvr_at.c 1.0.3 2018/03/11 + * Version: @(#)nvr_at.c 1.0.9 2018/05/10 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -218,6 +218,7 @@ * Boston, MA 02111-1307 * USA. */ +#include #include #include #include @@ -228,19 +229,20 @@ #include "cpu/cpu.h" #include "machine/machine.h" #include "io.h" -#include "pic.h" -#include "pit.h" #include "mem.h" #include "nmi.h" +#include "pic.h" +#include "pit.h" +#include "rom.h" #include "timer.h" #include "device.h" #include "nvr.h" -#include "rom.h" /* RTC registers and bit definitions. */ #define RTC_SECONDS 0 #define RTC_ALSECONDS 1 +# define AL_DONTCARE 0xc0 /* Alarm time is not set */ #define RTC_MINUTES 2 #define RTC_ALMINUTES 3 #define RTC_HOURS 4 @@ -277,43 +279,55 @@ # define REGC_UF 0x10 #define RTC_REGD 13 # define REGD_VRT 0x80 -#define RTC_CENTURY 0x32 /* century register */ +#define RTC_CENTURY_AT 0x32 /* century register for AT etc */ +#define RTC_CENTURY_PS 0x37 /* century register for PS/1 PS/2 */ #define RTC_REGS 14 /* number of registers */ -static nvr_t *nvrp; +typedef struct { + int8_t stat; + uint8_t cent; + + uint16_t addr; + + int64_t ecount, + rtctime; +} local_t; /* Get the current NVR time. */ static void -time_get(uint8_t *regs, struct tm *tm) +time_get(nvr_t *nvr, struct tm *tm) { + local_t *local = (local_t *)nvr->data; int8_t temp; - if (regs[RTC_REGB] & REGB_DM) { + if (nvr->regs[RTC_REGB] & REGB_DM) { /* NVR is in Binary data mode. */ - tm->tm_sec = regs[RTC_SECONDS]; - tm->tm_min = regs[RTC_MINUTES]; - temp = regs[RTC_HOURS]; - tm->tm_wday = (regs[RTC_DOW] - 1); - tm->tm_mday = regs[RTC_DOM]; - tm->tm_mon = (regs[RTC_MONTH] - 1); - tm->tm_year = regs[RTC_YEAR]; - tm->tm_year += (regs[RTC_CENTURY] * 100) - 1900; + tm->tm_sec = nvr->regs[RTC_SECONDS]; + tm->tm_min = nvr->regs[RTC_MINUTES]; + temp = nvr->regs[RTC_HOURS]; + tm->tm_wday = (nvr->regs[RTC_DOW] - 1); + tm->tm_mday = nvr->regs[RTC_DOM]; + tm->tm_mon = (nvr->regs[RTC_MONTH] - 1); + tm->tm_year = nvr->regs[RTC_YEAR]; + if (local->cent != 0xFF) + tm->tm_year += (nvr->regs[local->cent] * 100) - 1900; } else { /* NVR is in BCD data mode. */ - tm->tm_sec = RTC_DCB(regs[RTC_SECONDS]); - tm->tm_min = RTC_DCB(regs[RTC_MINUTES]); - temp = RTC_DCB(regs[RTC_HOURS]); - tm->tm_wday = (RTC_DCB(regs[RTC_DOW]) - 1); - tm->tm_mday = RTC_DCB(regs[RTC_DOM]); - tm->tm_mon = (RTC_DCB(regs[RTC_MONTH]) - 1); - tm->tm_year = RTC_DCB(regs[RTC_YEAR]); - tm->tm_year += (RTC_DCB(regs[RTC_CENTURY]) * 100) - 1900; + tm->tm_sec = RTC_DCB(nvr->regs[RTC_SECONDS]); + tm->tm_min = RTC_DCB(nvr->regs[RTC_MINUTES]); + temp = RTC_DCB(nvr->regs[RTC_HOURS]); + tm->tm_wday = (RTC_DCB(nvr->regs[RTC_DOW]) - 1); + tm->tm_mday = RTC_DCB(nvr->regs[RTC_DOM]); + tm->tm_mon = (RTC_DCB(nvr->regs[RTC_MONTH]) - 1); + tm->tm_year = RTC_DCB(nvr->regs[RTC_YEAR]); + if (local->cent != 0xFF) + tm->tm_year += (RTC_DCB(nvr->regs[local->cent]) * 100) - 1900; } /* Adjust for 12/24 hour mode. */ - if (regs[RTC_REGB] & REGB_2412) + if (nvr->regs[RTC_REGB] & REGB_2412) tm->tm_hour = temp; else tm->tm_hour = ((temp & ~RTC_AMPM)%12) + ((temp&RTC_AMPM) ? 12 : 0); @@ -322,49 +336,52 @@ time_get(uint8_t *regs, struct tm *tm) /* Set the current NVR time. */ static void -time_set(uint8_t *regs, struct tm *tm) +time_set(nvr_t *nvr, struct tm *tm) { + local_t *local = (local_t *)nvr->data; int year = (tm->tm_year + 1900); - if (regs[RTC_REGB] & REGB_DM) { + if (nvr->regs[RTC_REGB] & REGB_DM) { /* NVR is in Binary data mode. */ - regs[RTC_SECONDS] = tm->tm_sec; - regs[RTC_MINUTES] = tm->tm_min; - regs[RTC_DOW] = (tm->tm_wday + 1); - regs[RTC_DOM] = tm->tm_mday; - regs[RTC_MONTH] = (tm->tm_mon + 1); - regs[RTC_YEAR] = (year % 100); - regs[RTC_CENTURY] = (year / 100); + nvr->regs[RTC_SECONDS] = tm->tm_sec; + nvr->regs[RTC_MINUTES] = tm->tm_min; + nvr->regs[RTC_DOW] = (tm->tm_wday + 1); + nvr->regs[RTC_DOM] = tm->tm_mday; + nvr->regs[RTC_MONTH] = (tm->tm_mon + 1); + nvr->regs[RTC_YEAR] = (year % 100); + if (local->cent != 0xFF) + nvr->regs[local->cent] = (year / 100); - if (regs[RTC_REGB] & REGB_2412) { + if (nvr->regs[RTC_REGB] & REGB_2412) { /* NVR is in 24h mode. */ - regs[RTC_HOURS] = tm->tm_hour; + nvr->regs[RTC_HOURS] = tm->tm_hour; } else { /* NVR is in 12h mode. */ - regs[RTC_HOURS] = (tm->tm_hour % 12) ? (tm->tm_hour % 12) : 12; + nvr->regs[RTC_HOURS] = (tm->tm_hour % 12) ? (tm->tm_hour % 12) : 12; if (tm->tm_hour > 11) - regs[RTC_HOURS] |= RTC_AMPM; + nvr->regs[RTC_HOURS] |= RTC_AMPM; } } else { /* NVR is in BCD data mode. */ - regs[RTC_SECONDS] = RTC_BCD(tm->tm_sec); - regs[RTC_MINUTES] = RTC_BCD(tm->tm_min); - regs[RTC_DOW] = (RTC_BCD(tm->tm_wday) + 1); - regs[RTC_DOM] = RTC_BCD(tm->tm_mday); - regs[RTC_MONTH] = (RTC_BCD(tm->tm_mon) + 1); - regs[RTC_YEAR] = RTC_BCD(year % 100); - regs[RTC_CENTURY] = RTC_BCD(year / 100); + nvr->regs[RTC_SECONDS] = RTC_BCD(tm->tm_sec); + nvr->regs[RTC_MINUTES] = RTC_BCD(tm->tm_min); + nvr->regs[RTC_DOW] = RTC_BCD(tm->tm_wday + 1); + nvr->regs[RTC_DOM] = RTC_BCD(tm->tm_mday); + nvr->regs[RTC_MONTH] = RTC_BCD(tm->tm_mon + 1); + nvr->regs[RTC_YEAR] = RTC_BCD(year % 100); + if (local->cent != 0xFF) + nvr->regs[local->cent] = RTC_BCD(year / 100); - if (regs[RTC_REGB] & REGB_2412) { + if (nvr->regs[RTC_REGB] & REGB_2412) { /* NVR is in 24h mode. */ - regs[RTC_HOURS] = RTC_BCD(tm->tm_hour); + nvr->regs[RTC_HOURS] = RTC_BCD(tm->tm_hour); } else { /* NVR is in 12h mode. */ - regs[RTC_HOURS] = (tm->tm_hour % 12) + nvr->regs[RTC_HOURS] = (tm->tm_hour % 12) ? RTC_BCD(tm->tm_hour % 12) : RTC_BCD(12); if (tm->tm_hour > 11) - regs[RTC_HOURS] |= RTC_AMPM; + nvr->regs[RTC_HOURS] |= RTC_AMPM; } } } @@ -372,19 +389,19 @@ time_set(uint8_t *regs, struct tm *tm) /* Check if the current time matches a set alarm time. */ static int8_t -check_alarm(uint8_t *regs, int8_t addr) +check_alarm(nvr_t *nvr, int8_t addr) { -#define ALARM_DONTCARE 0xc0 - return((regs[addr+1] == regs[addr]) || - ((regs[addr+1] & ALARM_DONTCARE) == ALARM_DONTCARE)); + return((nvr->regs[addr+1] == nvr->regs[addr]) || + ((nvr->regs[addr+1] & AL_DONTCARE) == AL_DONTCARE)); } /* Update the NVR registers from the internal clock. */ static void -update_timer(void *priv) +timer_update(void *priv) { nvr_t *nvr = (nvr_t *)priv; + local_t *local = (local_t *)nvr->data; struct tm tm; if (! (nvr->regs[RTC_REGB] & REGB_SET)) { @@ -392,22 +409,22 @@ update_timer(void *priv) nvr_time_get(&tm); /* Update registers with current time. */ - time_set(nvr->regs, &tm); - + time_set(nvr, &tm); + /* Clear update status. */ - nvr->upd_stat = 0x00; + local->stat = 0x00; /* Check for any alarms we need to handle. */ - if (check_alarm(nvr->regs, RTC_SECONDS) && - check_alarm(nvr->regs, RTC_MINUTES) && - check_alarm(nvr->regs, RTC_HOURS)) { + if (check_alarm(nvr, RTC_SECONDS) && + check_alarm(nvr, RTC_MINUTES) && + check_alarm(nvr, RTC_HOURS)) { nvr->regs[RTC_REGC] |= REGC_AF; if (nvr->regs[RTC_REGB] & REGB_AIE) { nvr->regs[RTC_REGC] |= REGC_IRQF; /* Generate an interrupt. */ if (nvr->irq != -1) - picint(1<irq); + picint(1 << nvr->irq); } } @@ -421,41 +438,46 @@ update_timer(void *priv) /* Generate an interrupt. */ if (nvr->irq != -1) - picint(1<irq); + picint(1 << nvr->irq); } } - nvr->upd_ecount = 0; + local->ecount = 0; } /* Re-calculate the timer values. */ static void -rtc_timer_recalc(nvr_t *nvr, int add) +timer_recalc(nvr_t *nvr, int add) { + local_t *local = (local_t *)nvr->data; int64_t c, nt; - c = 1 << ((nvr->regs[RTC_REGA] & REGA_RS) - 1); + c = 1ULL << ((nvr->regs[RTC_REGA] & REGA_RS) - 1); nt = (int64_t)(RTCCONST * c * (1<rtctime += nt; - else if (nvr->rtctime > nt) - nvr->rtctime = nt; + if (add == 2) { + local->rtctime = nt; + return; + } else if (add == 1) + local->rtctime += nt; + else if (local->rtctime > nt) + local->rtctime = nt; } static void -rtc_timer(void *priv) +timer_intr(void *priv) { nvr_t *nvr = (nvr_t *)priv; + local_t *local = (local_t *)nvr->data; if (! (nvr->regs[RTC_REGA] & REGA_RS)) { - nvr->rtctime = 0x7fffffff; + local->rtctime = 0x7fffffff; return; } /* Update our timer interval. */ - rtc_timer_recalc(nvr, 1); + timer_recalc(nvr, 1); nvr->regs[RTC_REGC] |= REGC_PF; if (nvr->regs[RTC_REGB] & REGB_PIE) { @@ -463,20 +485,27 @@ rtc_timer(void *priv) /* Generate an interrupt. */ if (nvr->irq != -1) - picint(1<irq); + picint(1 << nvr->irq); } } /* Callback from internal clock, another second passed. */ static void -tick_timer(nvr_t *nvr) +timer_tick(nvr_t *nvr) { - if (nvr->regs[RTC_REGB] & REGB_SET) return; + local_t *local = (local_t *)nvr->data; - nvr->upd_stat = REGA_UIP; + /* Only update it there is no SET in progress. */ + if (! (nvr->regs[RTC_REGB] & REGB_SET)) { + /* Set the UIP bit, announcing the update. */ + local->stat = REGA_UIP; - nvr->upd_ecount = (int64_t)((244.0 + 1984.0) * TIMER_USEC); + rtc_tick(); + + /* Schedule the actual update. */ + local->ecount = (int64_t)((244.0 + 1984.0) * TIMER_USEC); + } } @@ -485,20 +514,21 @@ static void nvr_write(uint16_t addr, uint8_t val, void *priv) { nvr_t *nvr = (nvr_t *)priv; + local_t *local = (local_t *)nvr->data; struct tm tm; uint8_t old; cycles -= ISA_CYCLES(8); if (addr & 1) { - old = nvr->regs[nvr->addr]; - switch(nvr->addr) { + old = nvr->regs[local->addr]; + switch(local->addr) { case RTC_REGA: nvr->regs[RTC_REGA] = val; if (val & REGA_RS) - rtc_timer_recalc(nvr, 1); + timer_recalc(nvr, 1); else - nvr->rtctime = 0x7fffffff; + local->rtctime = 0x7fffffff; break; case RTC_REGB: @@ -515,25 +545,25 @@ nvr_write(uint16_t addr, uint8_t val, void *priv) break; default: /* non-RTC registers are just NVRAM */ - if (nvr->regs[nvr->addr] != val) { - nvr->regs[nvr->addr] = val; + if (nvr->regs[local->addr] != val) { + nvr->regs[local->addr] = val; nvr_dosave = 1; } break; } - if ((nvr->addr < RTC_REGA) || (nvr->addr == RTC_CENTURY)) { - if ((nvr->addr != 1) && (nvr->addr != 3) && (nvr->addr != 5)) { + if ((local->addr < RTC_REGA) || ((local->cent != 0xff) && (local->addr == local->cent))) { + if ((local->addr != 1) && (local->addr != 3) && (local->addr != 5)) { if ((old != val) && !enable_sync) { /* Update internal clock. */ - time_get(nvr->regs, &tm); + time_get(nvr, &tm); nvr_time_set(&tm); nvr_dosave = 1; } } } } else { - nvr->addr = (val & (nvr->size - 1)); + local->addr = (val & (nvr->size - 1)); if (!(machines[machine].flags & MACHINE_MCA) && (romset != ROM_IBMPS1_2133)) nmi_mask = (~val & 0x80); @@ -546,17 +576,18 @@ static uint8_t nvr_read(uint16_t addr, void *priv) { nvr_t *nvr = (nvr_t *)priv; + local_t *local = (local_t *)nvr->data; uint8_t ret; cycles -= ISA_CYCLES(8); - if (addr & 1) switch(nvr->addr) { + if (addr & 1) switch(local->addr) { case RTC_REGA: - ret = (nvr->regs[RTC_REGA] & 0x7f) | nvr->upd_stat; + ret = (nvr->regs[RTC_REGA] & 0x7f) | local->stat; break; case RTC_REGC: - picintc(1<irq); + picintc(1 << nvr->irq); ret = nvr->regs[RTC_REGC]; nvr->regs[RTC_REGC] = 0x00; break; @@ -567,10 +598,10 @@ nvr_read(uint16_t addr, void *priv) break; default: - ret = nvr->regs[nvr->addr]; + ret = nvr->regs[local->addr]; break; } else { - ret = nvr->addr; + ret = local->addr; } return(ret); @@ -579,19 +610,22 @@ nvr_read(uint16_t addr, void *priv) /* Reset the RTC state to 1980/01/01 00:00. */ static void -nvr_at_reset(nvr_t *nvr) +nvr_reset(nvr_t *nvr) { + local_t *local = (local_t *)nvr->data; + memset(nvr->regs, 0x00, RTC_REGS); nvr->regs[RTC_DOM] = 1; nvr->regs[RTC_MONTH] = 1; nvr->regs[RTC_YEAR] = RTC_BCD(80); - nvr->regs[RTC_CENTURY] = RTC_BCD(19); + if (local->cent != 0xFF) + nvr->regs[local->cent] = RTC_BCD(19); } /* Process after loading from file. */ static void -nvr_at_start(nvr_t *nvr) +nvr_start(nvr_t *nvr) { struct tm tm; @@ -599,63 +633,138 @@ nvr_at_start(nvr_t *nvr) if (enable_sync) { /* Use the internal clock's time. */ nvr_time_get(&tm); - time_set(nvr->regs, &tm); + time_set(nvr, &tm); } else { /* Set the internal clock from the chip time. */ - time_get(nvr->regs, &tm); + time_get(nvr, &tm); nvr_time_set(&tm); } /* Start the RTC. */ nvr->regs[RTC_REGA] = (REGA_RS2|REGA_RS1); nvr->regs[RTC_REGB] = REGB_2412; - rtc_timer_recalc(nvr, 0); + timer_recalc(nvr, 1); } -void -nvr_at_init(int irq) +static void +nvr_recalc(nvr_t *nvr) { + timer_recalc(nvr, 0); +} + + +static void * +nvr_at_init(const device_t *info) +{ + local_t *local; nvr_t *nvr; /* Allocate an NVR for this machine. */ nvr = (nvr_t *)malloc(sizeof(nvr_t)); - if (nvr == NULL) return; - memset(nvr, 0x00, sizeof(nvr_t)); + if (nvr == NULL) return(NULL); + /* FIXME: See which is correct, this or 0xFF. */ + if (info->local == 0) + memset(nvr, 0xff, sizeof(nvr_t)); + else + memset(nvr, 0x00, sizeof(nvr_t)); + + local = (local_t *)malloc(sizeof(local_t)); + memset(local, 0x00, sizeof(local_t)); + nvr->data = local; /* This is machine specific. */ nvr->size = machines[machine].nvrmask + 1; - nvr->irq = irq; + switch(info->local) { + case 0: /* standard AT, no century register */ + nvr->irq = 8; + local->cent = 0xff; + break; + + case 1: /* standard AT */ + nvr->irq = 8; + local->cent = RTC_CENTURY_AT; + break; + + case 2: /* PS/1 or PS/2 */ + nvr->irq = 8; + local->cent = RTC_CENTURY_PS; + break; + + case 3: /* Amstrad PC's */ + nvr->irq = 1; + local->cent = RTC_CENTURY_AT; + break; + } /* Set up any local handlers here. */ - nvr->reset = nvr_at_reset; - nvr->start = nvr_at_start; - nvr->tick = tick_timer; + nvr->reset = nvr_reset; + nvr->start = nvr_start; + nvr->tick = timer_tick; + nvr->recalc = nvr_recalc; /* Initialize the generic NVR. */ nvr_init(nvr); /* Start the timers. */ - timer_add(update_timer, &nvr->upd_ecount, &nvr->upd_ecount, nvr); - timer_add(rtc_timer, &nvr->rtctime, TIMER_ALWAYS_ENABLED, nvr); + timer_add(timer_update, &local->ecount, &local->ecount, nvr); + timer_add(timer_intr, &local->rtctime, TIMER_ALWAYS_ENABLED, nvr); /* Set up the I/O handler for this device. */ io_sethandler(0x0070, 2, nvr_read,NULL,NULL, nvr_write,NULL,NULL, nvr); - nvrp = nvr; + return(nvr); } -void -nvr_at_close(void) +static void +nvr_at_close(void *priv) { - if (nvrp == NULL) return; + nvr_t *nvr = (nvr_t *)priv; - if (nvrp->fn != NULL) - free(nvrp->fn); + if (nvr->fn != NULL) + free(nvr->fn); - free(nvrp); + if (nvr->data != NULL) + free(nvr->data); - nvrp = NULL; + free(nvr); } + + +const device_t at_nvr_old_device = { + "PC/AT NVRAM (No century)", + DEVICE_ISA | DEVICE_AT, + 0, + nvr_at_init, nvr_at_close, NULL, + NULL, NULL, + NULL +}; + +const device_t at_nvr_device = { + "PC/AT NVRAM", + DEVICE_ISA | DEVICE_AT, + 1, + nvr_at_init, nvr_at_close, NULL, + NULL, NULL, + NULL +}; + +const device_t ps_nvr_device = { + "PS/1 or PS/2 NVRAM", + DEVICE_PS2, + 2, + nvr_at_init, nvr_at_close, NULL, + NULL, NULL, + NULL +}; + +const device_t amstrad_nvr_device = { + "Amstrad NVRAM", + MACHINE_ISA | MACHINE_AT, + 3, + nvr_at_init, nvr_at_close, NULL, + NULL, NULL, + NULL +}; diff --git a/src/nvr_ps2.c b/src/nvr_ps2.c index 3c7d68d7d..4431d7a4f 100644 --- a/src/nvr_ps2.c +++ b/src/nvr_ps2.c @@ -8,7 +8,7 @@ * * Handling of the PS/2 series CMOS devices. * - * Version: @(#)nvr_ps2.c 1.0.6 2018/03/20 + * Version: @(#)nvr_ps2.c 1.0.7 2018/04/26 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -169,6 +169,6 @@ const device_t ps2_nvr_device = { "PS/2 Secondary NVRAM", 0, 0, ps2_nvr_init, ps2_nvr_close, NULL, - NULL, NULL, NULL, + NULL, NULL, NULL }; diff --git a/src/pc.c b/src/pc.c index 09268e0c5..88fa42579 100644 --- a/src/pc.c +++ b/src/pc.c @@ -8,7 +8,7 @@ * * Main emulator module where most things are controlled. * - * Version: @(#)pc.c 1.0.68 2018/03/19 + * Version: @(#)pc.c 1.0.73 2018/06/02 * * Authors: Sarah Walker, * Miran Grca, @@ -19,11 +19,11 @@ * Copyright 2017,2018 Fred N. van Kempen. */ #include +#include #include #include #include #include -#include #include #include #define HAVE_STDARG_H @@ -38,6 +38,7 @@ #include "mem.h" #include "rom.h" #include "dma.h" +#include "pci.h" #include "pic.h" #include "pit.h" #include "random.h" @@ -56,22 +57,16 @@ #include "disk/hdd.h" #include "disk/hdc.h" #include "disk/hdc_ide.h" -#include "disk/zip.h" +#include "scsi/scsi.h" #include "cdrom/cdrom.h" +#include "disk/zip.h" +#include "scsi/scsi_disk.h" #include "cdrom/cdrom_image.h" #include "cdrom/cdrom_null.h" -#include "scsi/scsi.h" #include "network/network.h" #include "sound/sound.h" #include "sound/midi.h" -#include "sound/snd_cms.h" -#include "sound/snd_dbopl.h" -#include "sound/snd_mpu401.h" -#include "sound/snd_opl.h" -#include "sound/snd_gus.h" -#include "sound/snd_sb.h" #include "sound/snd_speaker.h" -#include "sound/snd_ssi2001.h" #include "video/video.h" #include "ui.h" #include "plat.h" @@ -109,8 +104,7 @@ int vid_cga_contrast = 0, /* (C) video */ video_fullscreen_scale = 0, /* (C) video */ video_fullscreen_first = 0, /* (C) video */ enable_overscan = 0, /* (C) video */ - force_43 = 0, /* (C) video */ - video_speed = 0; /* (C) video */ + force_43 = 0; /* (C) video */ int serial_enabled[SERIAL_MAX] = {0,0}, /* (C) enable serial ports */ lpt_enabled = 0, /* (C) enable LPT ports */ bugger_enabled = 0; /* (C) enable ISAbugger */ @@ -120,7 +114,7 @@ int sound_is_float = 1, /* (C) sound uses FP values */ GUS = 0, /* (C) sound option */ SSI2001 = 0, /* (C) sound option */ voodoo_enabled = 0; /* (C) video option */ -int mem_size = 0; /* (C) memory size */ +uint32_t mem_size = 0; /* (C) memory size */ int cpu_manufacturer = 0, /* (C) cpu manufacturer */ cpu_use_dynarec = 0, /* (C) cpu uses/needs Dyna */ cpu = 3, /* (C) cpu type */ @@ -133,17 +127,7 @@ extern int readlnum, writelnum; -int sndcount = 0; -int sreadlnum, - swritelnum, - segareads, - segawrites, - scycles_lost; -float mips, flops; -int cycles_lost = 0; /* video */ -int insc = 0; /* cpu */ -int emu_fps = 0, fps; /* video */ -int framecount; +int fps, framecount; /* emulator % */ int CPUID; int output; @@ -283,6 +267,26 @@ fatal(const char *fmt, ...) } +#ifdef ENABLE_PC_LOG +int pc_do_log = ENABLE_PC_LOG; +#endif + + +static void +pc_log(const char *format, ...) +{ +#ifdef ENABLE_PC_LOG + va_list ap; + + if (pc_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + /* * Perform initial startup of the PC. * @@ -299,6 +303,7 @@ pc_init(int argc, wchar_t *argv[]) struct tm *info; time_t now; int c; + uint32_t *uid, *shwnd; /* Grab the executable's full path. */ plat_get_exe_name(exe_path, sizeof(exe_path)-1); @@ -329,12 +334,8 @@ usage: printf("-D or --debug - force debug output logging\n"); #endif printf("-F or --fullscreen - start in fullscreen mode\n"); - printf("-M or --memdump - dump memory on exit\n"); printf("-L or --logfile path - set 'path' to be the logfile\n"); printf("-P or --vmpath path - set 'path' to be root for vm\n"); -#ifdef USE_WX - printf("-R or --fps num - set render speed to 'num' fps\n"); -#endif printf("-S or --settings - show only the settings dialog\n"); #ifdef _WIN32 printf("-H or --hwnd id,hwnd - sends back the main dialog's hwnd\n"); @@ -357,20 +358,11 @@ usage: if ((c+1) == argc) goto usage; wcscpy(log_path, argv[++c]); - } else if (!wcscasecmp(argv[c], L"--memdump") || - !wcscasecmp(argv[c], L"-M")) { } else if (!wcscasecmp(argv[c], L"--vmpath") || !wcscasecmp(argv[c], L"-P")) { if ((c+1) == argc) goto usage; wcscpy(path, argv[++c]); -#ifdef USE_WX - } else if (!wcscasecmp(argv[c], L"--fps") || - !wcscasecmp(argv[c], L"-R")) { - if ((c+1) == argc) goto usage; - - video_fps = wcstol(argv[++c], NULL, 10); -#endif } else if (!wcscasecmp(argv[c], L"--settings") || !wcscasecmp(argv[c], L"-S")) { settings_only = 1; @@ -381,7 +373,9 @@ usage: if ((c+1) == argc) goto usage; wcstombs(temp, argv[++c], 128); - sscanf(temp, "%016" PRIX64 ",%016" PRIX64, &unique_id, &source_hwnd); + uid = (uint32_t *) &unique_id; + shwnd = (uint32_t *) &source_hwnd; + sscanf(temp, "%08X%08X,%08X%08X", uid + 1, uid, shwnd + 1, shwnd); #endif } else if (!wcscasecmp(argv[c], L"--test")) { /* some (undocumented) test function here.. */ @@ -422,6 +416,11 @@ usage: */ wcscpy(usr_path, path); } + + /* If the specified path does not yet exist, + create it. */ + if (! plat_dir_check(path)) + plat_dir_create(path); } /* Make sure we have a trailing backslash. */ @@ -490,6 +489,7 @@ usage: mouse_init(); cdrom_global_init(); zip_global_init(); + scsi_disk_global_init(); /* Load the configuration file. */ config_load(); @@ -505,26 +505,31 @@ pc_full_speed(void) cpuspeed2 = cpuspeed; if (! atfullspeed) { - pclog("Set fullspeed - %i %i %i\n", is386, AT, cpuspeed2); - if (AT) + pc_log("Set fullspeed - %i %i %i\n", is386, AT, cpuspeed2); + if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286) setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed); - else + else setpitclock(14318184.0); } atfullspeed = 1; + + nvr_period_recalc(); } void pc_speed_changed(void) { - if (AT) + if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286) setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed); - else + else setpitclock(14318184.0); + + nvr_period_recalc(); } +#if 0 /* Re-load system configuration and restart. */ /* FIXME: this has to be reviewed! */ void @@ -536,10 +541,8 @@ pc_reload(wchar_t *fn) for (i=0; iexit(i); - cdrom_close(i); - } + + cdrom_close(); pc_reset_hard_close(); @@ -547,24 +550,11 @@ pc_reload(wchar_t *fn) config_load(); - for (i=0; i= 'A') && (cdrom_drives[i].host_drive <= 'Z')) - ioctl_open(i, cdrom_drives[i].host_drive); - else - cdrom_null_open(i, cdrom_drives[i].host_drive); - } + zip_hard_reset(); - for (i=0; i= CPU_286) ? 2 : 1; atfullspeed = 0; random_init(); @@ -653,21 +645,13 @@ again2: codegen_init(); #endif -#ifdef WALTJE_SERIAL - serial_init(); -#endif keyboard_init(); joystick_init(); video_init(); - - ide_init_first(); - device_init(); timer_reset(); - sound_reset(); - fdd_init(); sound_init(); @@ -675,9 +659,10 @@ again2: hdc_init(hdc_name); cdrom_hard_reset(); + zip_hard_reset(); - ide_reset_hard(); + scsi_disk_hard_reset(); scsi_card_init(); @@ -699,16 +684,23 @@ pc_keyboard_send(uint8_t val) } +void +pc_send_ca(uint8_t sc) +{ + pc_keyboard_send(29); /* Ctrl key pressed */ + pc_keyboard_send(56); /* Alt key pressed */ + pc_keyboard_send(sc); + pc_keyboard_send(sc | 0x80); + pc_keyboard_send(184); /* Alt key released */ + pc_keyboard_send(157); /* Ctrl key released */ +} + + /* Send the machine a Control-Alt-DEL sequence. */ void pc_send_cad(void) { - pc_keyboard_send(29); /* Ctrl key pressed */ - pc_keyboard_send(56); /* Alt key pressed */ - pc_keyboard_send(83); /* Delete key pressed */ - pc_keyboard_send(157); /* Ctrl key released */ - pc_keyboard_send(184); /* Alt key released */ - pc_keyboard_send(211); /* Delete key released */ + pc_send_ca(83); } @@ -716,25 +708,7 @@ pc_send_cad(void) void pc_send_cae(void) { - pc_keyboard_send(29); /* Ctrl key pressed */ - pc_keyboard_send(56); /* Alt key pressed */ - pc_keyboard_send(1); /* Esc key pressed */ - pc_keyboard_send(129); /* Esc key released */ - pc_keyboard_send(184); /* Alt key released */ - pc_keyboard_send(157); /* Ctrl key released */ -} - - -/* Send the machine a Control-Alt-Break sequence. */ -void -pc_send_cab(void) -{ - pc_keyboard_send(29); /* Ctrl key pressed */ - pc_keyboard_send(56); /* Alt key pressed */ - pc_keyboard_send(1); /* Esc key pressed */ - pc_keyboard_send(157); /* Ctrl key released */ - pc_keyboard_send(184); /* Alt key released */ - pc_keyboard_send(129); /* Esc key released */ + pc_send_ca(1); } @@ -745,8 +719,6 @@ pc_reset_hard_close(void) nvr_save(); - machine_close(); - mouse_close(); lpt_devices_close(); @@ -755,6 +727,8 @@ pc_reset_hard_close(void) midi_close(); + cdrom_close(); + closeal(); } @@ -773,24 +747,23 @@ pc_reset_hard_init(void) * the actual machine, but which support some of the * modules that are. */ - sound_realloc_buffers(); - sound_cd_thread_reset(); - initalmain(0, NULL); /* Reset the general machine support modules. */ io_init(); - // cpu_set(); timer_reset(); + device_init(); - midi_device_init(); - inital(); sound_reset(); -#ifndef WALTJE_SERIAL /* This is needed to initialize the serial timer. */ serial_init(); -#endif + + cdrom_hard_reset(); + + zip_hard_reset(); + + scsi_disk_hard_reset(); /* Initialize the actual machine and its basic modules. */ machine_init(); @@ -810,11 +783,7 @@ pc_reset_hard_init(void) speaker_init(); serial_reset(); lpt_devices_init(); - - /* Reset keyboard and/or mouse. */ - // FIXME: do we really have to reset the *AT* keyboard?? --FvK shadowbios = 0; - keyboard_at_reset(); /* * This has to be after the serial initialization so that @@ -826,30 +795,18 @@ pc_reset_hard_init(void) /* Reset the video card. */ video_reset(gfxcard); - cdrom_hard_reset(); - zip_hard_reset(); - /* Reset the Hard Disk Controller module. */ hdc_reset(); /* Reset and reconfigure the SCSI layer. */ scsi_card_init(); + /* Reset and reconfigure the Sound Card layer. */ + sound_card_reset(); + /* Reset and reconfigure the Network Card layer. */ network_reset(); - /* Reset and reconfigure the Sound Card layer. */ - // FIXME: should be just one sound_reset() here. --FvK - sound_card_init(); - if (mpu401_standalone_enable) - mpu401_device_add(); - if (GUS) - device_add(&gus_device); - if (GAMEBLASTER) - device_add(&cms_device); - if (SSI2001) - device_add(&ssi2001_device); - if (joystick_type != 7) gameport_update_joystick_type(); @@ -866,13 +823,12 @@ pc_reset_hard_init(void) device_add(&bugger_device); /* Reset the CPU module. */ - cpu_set(); resetx86(); dma_reset(); pic_reset(); cpu_cache_int_enabled = cpu_cache_ext_enabled = 0; - if (AT) + if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286) setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed); else setpitclock(14318184.0); @@ -935,12 +891,6 @@ pc_close(thread_t *ptr) lpt_devices_close(); - for (i=0; iexit(i); - for (i=0; i= CPU_286) { exec386(clockrate/100); } else { execx86(clockrate/100); @@ -1036,50 +980,10 @@ pc_thread(void *param) if (++framecountx >= 100) { framecountx = 0; - /* FIXME: all this should go into a "stats" struct! */ - mips = (float)insc/1000000.0f; - insc = 0; - flops = (float)fpucount/1000000.0f; - fpucount = 0; - sreadlnum = readlnum; - swritelnum = writelnum; - segareads = egareads; - segawrites = egawrites; - scycles_lost = cycles_lost; - -#ifdef USE_DYNAREC - cpu_recomp_blocks_latched = cpu_recomp_blocks; - cpu_recomp_ins_latched = cpu_state.cpu_recomp_ins; - cpu_recomp_full_ins_latched = cpu_recomp_full_ins; - cpu_new_blocks_latched = cpu_new_blocks; - cpu_recomp_flushes_latched = cpu_recomp_flushes; - cpu_recomp_evicted_latched = cpu_recomp_evicted; - cpu_recomp_reuse_latched = cpu_recomp_reuse; - cpu_recomp_removed_latched = cpu_recomp_removed; - cpu_reps_latched = cpu_reps; - cpu_notreps_latched = cpu_notreps; - - cpu_recomp_blocks = 0; - cpu_state.cpu_recomp_ins = 0; - cpu_recomp_full_ins = 0; - cpu_new_blocks = 0; - cpu_recomp_flushes = 0; - cpu_recomp_evicted = 0; - cpu_recomp_reuse = 0; - cpu_recomp_removed = 0; - cpu_reps = 0; - cpu_notreps = 0; -#endif - readlnum = writelnum = 0; egareads = egawrites = 0; - cycles_lost = 0; mmuflush = 0; - emu_fps = frames; frames = 0; - - /* We need a Status window update now. */ - status_update_needed = 1; } if (title_update) { @@ -1122,7 +1026,7 @@ pc_thread(void *param) } } - pclog("PC: main thread done.\n"); + pc_log("PC: main thread done.\n"); } @@ -1148,7 +1052,7 @@ set_screen_size(int x, int y) /* Make sure we keep usable values. */ #if 0 - pclog("SetScreenSize(%d, %d) resize=%d\n", x, y, vid_resize); + pc_log("SetScreenSize(%d, %d) resize=%d\n", x, y, vid_resize); #endif if (x < 320) x = 320; if (y < 200) y = 200; diff --git a/src/pci.c b/src/pci.c index 3ec8e186b..f3b7a9ce1 100644 --- a/src/pci.c +++ b/src/pci.c @@ -12,11 +12,15 @@ #include "mem.h" #include "device.h" #include "pci.h" +#include "piix.h" #include "keyboard.h" +#if 0 +#include "scsi/scsi.h" #include "cdrom/cdrom.h" #include "disk/hdc.h" #include "disk/hdc_ide.h" #include "disk/zip.h" +#endif static uint64_t pci_irq_hold[16]; @@ -52,8 +56,6 @@ int pci_burst_time, pci_nonburst_time; static int trc_reg = 0; -PCI_RESET pci_reset_handler; - #ifdef ENABLE_PCI_LOG int pci_do_log = ENABLE_PCI_LOG; #endif @@ -636,44 +638,11 @@ static uint8_t trc_read(uint16_t port, void *priv) static void trc_reset(uint8_t val) { - int i = 0; - if (val & 2) { - if (pci_reset_handler.pci_master_reset) - { - pci_reset_handler.pci_master_reset(); - } - - if (pci_reset_handler.pci_set_reset) - { - pci_reset_handler.pci_set_reset(); - } - - if (pci_reset_handler.super_io_reset) - { - pci_reset_handler.super_io_reset(); - } - - /* ide_reset(); */ - ide_set_all_signatures(); - for (i = 0; i < CDROM_NUM; i++) - { - if ((cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) || (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA)) - { - cdrom_reset(i); - } - } - for (i = 0; i < ZIP_NUM; i++) - { - if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || (zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA)) - { - zip_reset(i); - } - } + device_reset_all_pci(); port_92_reset(); - keyboard_at_reset(); pci_reset(); } @@ -732,10 +701,6 @@ void pci_init(int type) pci_mirqs[c].enabled = 0; pci_mirqs[c].irq_line = PCI_IRQ_DISABLED; } - - pci_reset_handler.pci_master_reset = NULL; - pci_reset_handler.pci_set_reset = NULL; - pci_reset_handler.super_io_reset = NULL; } void pci_register_slot(int card, int type, int inta, int intb, int intc, int intd) diff --git a/src/pci.h b/src/pci.h index 2bb435f39..8f6d0e619 100644 --- a/src/pci.h +++ b/src/pci.h @@ -15,6 +15,7 @@ void pci_clear_irq(uint8_t card, uint8_t pci_int); void pci_reset(void); void pci_init(int type); void pci_register_slot(int card, int type, int inta, int intb, int intc, int intd); +void pci_close(void); uint8_t pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv); #define PCI_REG_COMMAND 0x04 @@ -53,13 +54,4 @@ typedef union { uint8_t addr_regs[4]; } bar_t; -typedef struct PCI_RESET -{ - void (*pci_master_reset)(void); - void (*pci_set_reset)(void); - void (*super_io_reset)(void); -} PCI_RESET; - -extern PCI_RESET pci_reset_handler; - extern void trc_init(void); diff --git a/src/pci_dummy.c b/src/pci_dummy.c index 7686c33cc..6a790ff14 100644 --- a/src/pci_dummy.c +++ b/src/pci_dummy.c @@ -3,6 +3,7 @@ #include #include #include +#include "86box.h" #include "io.h" #include "pci.h" #include "pci_dummy.h" diff --git a/src/pic.c b/src/pic.c index 1a7ea3d3b..fb107da8b 100644 --- a/src/pic.c +++ b/src/pic.c @@ -1,8 +1,27 @@ +/* + * 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 Intel PIC chip emulation. + * + * Version: @(#)pic.c 1.0.0 2018/04/29 + * + * Author: Miran Grca, + * + * Copyright 2016-2018 Miran Grca. + */ +#include #include #include #include #include +#define HAVE_STDARG_H #include "86box.h" +#include "cpu/cpu.h" #include "machine/machine.h" #include "io.h" #include "pci.h" @@ -18,542 +37,500 @@ PIC pic, pic2; uint16_t pic_current; -void pic_updatepending() +#ifdef ENABLE_PIC_LOG +int pic_do_log = ENABLE_PIC_LOG; +#endif + + +static void +pic_log(const char *format, ...) { - uint16_t temp_pending = 0; - if (AT) - { - if ((pic2.pend&~pic2.mask)&~pic2.mask2) - pic.pend |= pic.icw3; - else - pic.pend &= ~pic.icw3; - } - pic_intpending = (pic.pend & ~pic.mask) & ~pic.mask2; - if (AT) - { - if (!((pic.mask | pic.mask2) & pic.icw3)) - { - temp_pending = ((pic2.pend&~pic2.mask)&~pic2.mask2); - temp_pending <<= 8; - pic_intpending |= temp_pending; - } - } -/* pclog("pic_intpending = %i %02X %02X %02X %02X\n", pic_intpending, pic.ins, pic.pend, pic.mask, pic.mask2); - pclog(" %02X %02X %02X %02X %i %i\n", pic2.ins, pic2.pend, pic2.mask, pic2.mask2, ((pic.mask | pic.mask2) & (1 << 2)), ((pic2.pend&~pic2.mask)&~pic2.mask2)); */ +#ifdef ENABLE_PIC_LOG + va_list ap; + + if (pic_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif } -void pic_reset() +void +pic_updatepending() { - pic.icw=0; - pic.mask=0xFF; - pic.mask2=0; - pic.pend=pic.ins=0; - pic.vector=8; - pic.read=1; - pic2.icw=0; - pic2.mask=0xFF; - pic.mask2=0; - pic2.pend=pic2.ins=0; - pic_intpending = 0; -} - -void pic_update_mask(uint8_t *mask, uint8_t ins) -{ - int c; - *mask = 0; - for (c = 0; c < 8; c++) - { - if (ins & (1 << c)) - { - *mask = 0xff << c; - return; - } - } -} - -static int picint_is_level(uint16_t irq) -{ - if (PCI) - { - return pci_irq_is_level(irq); - } + uint16_t temp_pending = 0; + if (AT) { + if ((pic2.pend&~pic2.mask)&~pic2.mask2) + pic.pend |= pic.icw3; else - { - if (irq < 8) - { - return (pic.icw1 & 8) ? 1 : 0; - } - else - { - return (pic2.icw1 & 8) ? 1 : 0; - } + pic.pend &= ~pic.icw3; + } + pic_intpending = (pic.pend & ~pic.mask) & ~pic.mask2; + if (AT) { + if (!((pic.mask | pic.mask2) & pic.icw3)) { + temp_pending = ((pic2.pend&~pic2.mask)&~pic2.mask2); + temp_pending <<= 8; + pic_intpending |= temp_pending; } -} - -static void pic_autoeoi() -{ - int c; - - for (c=0;c<8;c++) - { - if (pic.ins&(1<0xFF) - { - if (!AT) - { - return; - } - - pic2.pend|=(num>>8); - if ((pic2.pend&~pic2.mask)&~pic2.mask2) - { - pic.pend |= (1 << pic2.icw3); - } - } - else - { - pic.pend|=num; - } - pic_updatepending(); - } -} - -void picint(uint16_t num) -{ - picint_common(num, 0); -} - -void picintlevel(uint16_t num) -{ - picint_common(num, 1); -} - -void picintc(uint16_t num) -{ - int c = 0; - - if (!num) - { - /* pclog("Attempting to lower null IRQ\n"); */ - return; - } - - if (AT && (num == pic.icw3) && (pic.icw3 == 4)) - { - num = 1 << 9; - } - - while (!(num & (1 << c))) c++; - - if (AT && (num == pic.icw3) && (pic.icw3 != 4)) - { - /* pclog("Attempting to lower cascaded IRQ %i\n"); */ - return; - } - - if (pic_current & num) - { - pic_current &= ~num; - } - - /* pclog("Lowering IRQ %i\n", c); */ - - if (num > 0xff) - { - if (!AT) - { - return; - } - - pic2.pend &= ~(num >> 8); - if (!((pic2.pend&~pic2.mask)&~pic2.mask2)) - { - pic.pend &= ~(1 << pic2.icw3); - } - } - else - { - pic.pend&=~num; - } - pic_updatepending(); -} - -/* TODO: Verify this whole level-edge thing... edge/level mode is supposedly handled by bit 3 of ICW1, - but the PIIX spec mandates it being able to be edge/level per IRQ... maybe the PCI-era on-board - PIC ignores bit 3 of ICW1 but instead uses whatever is set in ELCR? - - Edit: Yes, the PIIX (and I suppose also the SIO) disables bit 3 of ICW1 and instead, uses the ELCR. - - Also, shouldn't there be only one picint(), and then edge/level is handled on processing? */ - -static uint8_t pic_process_interrupt(PIC* target_pic, int c) -{ - uint8_t pending = target_pic->pend & ~target_pic->mask; - - int pic_int = c & 7; - int pic_int_num = 1 << pic_int; - - /* int pic_cur_num = 1 << c; */ - - if (pending & pic_int_num) - { - target_pic->pend &= ~pic_int_num; - target_pic->ins |= pic_int_num; - pic_update_mask(&target_pic->mask2, target_pic->ins); - - if (c >= 8) - { - pic.ins |= (1 << pic2.icw3); /*Cascade IRQ*/ - pic_update_mask(&pic.mask2, pic.ins); + if ((pic_current & (1 << c)) && picint_is_level(c)) { + if (((1 << c) != pic.icw3) || !AT) + pic.pend |= 1 << c; } pic_updatepending(); - - if (target_pic->icw4 & 0x02) - { - (c >= 8) ? pic2_autoeoi() : pic_autoeoi(); - } - - if (!c) - { - pit_set_gate(&pit2, 0, 0); - } - - return pic_int + target_pic->vector; - } - else - { - return 0xFF; + return; } + } } -uint8_t picinterrupt() -{ - int c, d; - uint8_t ret; - for (c = 0; c <= 7; c++) - { - if (AT && ((1 << c) == pic.icw3)) - { - for (d = 8; d <= 15; d++) - { - ret = pic_process_interrupt(&pic2, d); - if (ret != 0xFF) return ret; - } +void +pic_write(uint16_t addr, uint8_t val, void *priv) +{ + int c; + if (addr&1) { + switch (pic.icw) { + case 0: /*OCW1*/ + pic.mask=val; + pic_updatepending(); + break; + case 1: /*ICW2*/ + pic.vector=val&0xF8; + if (pic.icw1 & 2) pic.icw=3; + else pic.icw=2; + break; + case 2: /*ICW3*/ + pic.icw3 = val; + pic_log("PIC1 ICW3 now %02X\n", val); + if (pic.icw1 & 1) pic.icw=3; + else pic.icw=0; + break; + case 3: /*ICW4*/ + pic.icw4 = val; + pic.icw=0; + break; + } + } else { + if (val & 16) { /*ICW1*/ + pic.mask = 0; + pic.mask2=0; + pic.icw=1; + pic.icw1=val; + pic.ins = 0; + pic_updatepending(); + } + else if (!(val & 8)) { /*OCW2*/ + if ((val & 0xE0) == 0x60) { + pic.ins &= ~(1 << (val & 7)); + pic_update_mask(&pic.mask2, pic.ins); + if (AT) { + if (((val&7) == pic2.icw3) && (pic2.pend&~pic2.mask)&~pic2.mask2) + pic.pend |= pic.icw3; + } + + if ((pic_current & (1 << (val & 7))) && picint_is_level(val & 7)) { + if ((((1 << (val & 7)) != pic.icw3) || !AT)) + pic.pend |= 1 << (val & 7); + } + + pic_updatepending(); + } else { + for (c = 0; c < 8; c++) { + if (pic.ins & (1 << c)) { + pic.ins &= ~(1 << c); + pic_update_mask(&pic.mask2, pic.ins); + + if (AT) { + if (((1 << c) == pic.icw3) && (pic2.pend&~pic2.mask)&~pic2.mask2) + pic.pend |= pic.icw3; + } + + if ((pic_current & (1 << c)) && picint_is_level(c)) { + if ((((1 << c) != pic.icw3) || !AT)) + pic.pend |= 1 << c; + } + + if (c==1 && keywaiting) + intclear&=~1; + pic_updatepending(); + return; + } + } } - else - { - ret = pic_process_interrupt(&pic, c); + } else { /*OCW3*/ + if (val & 2) + pic.read=(val & 1); + } + } +} + + +uint8_t +pic_read(uint16_t addr, void *priv) +{ + if (addr & 1) { + pic_log("Read PIC mask %02X\n", pic.mask); + return pic.mask; + } + if (pic.read) { + pic_log("Read PIC ins %02X\n", pic.ins); + return pic.ins | (pic2.ins ? 4 : 0); + } + return pic.pend; +} + + +void +pic_init() +{ + io_sethandler(0x0020, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, NULL); +} + + +static void +pic2_autoeoi() +{ + int c; + + for (c = 0; c < 8; c++) { + if (pic2.ins & (1 << c)) { + pic2.ins &= ~(1 << c); + pic_update_mask(&pic2.mask2, pic2.ins); + + if (pic_current & (0x100 << c) && picint_is_level(c + 8)) { + pic2.pend |= (1 << c); + pic.pend |= (1 << pic2.icw3); + } + + pic_updatepending(); + return; + } + } +} + + +void +pic2_write(uint16_t addr, uint8_t val, void *priv) +{ + int c; + if (addr & 1) { + switch (pic2.icw) { + case 0: /*OCW1*/ + pic2.mask=val; + pic_updatepending(); + break; + case 1: /*ICW2*/ + pic2.vector=val & 0xF8; + pic_log("PIC2 vector now: %02X\n", pic2.vector); + if (pic2.icw1 & 2) pic2.icw=3; + else pic2.icw=2; + break; + case 2: /*ICW3*/ + pic2.icw3 = val; + pic_log("PIC2 ICW3 now %02X\n", val); + if (pic2.icw1 & 1) pic2.icw=3; + else pic2.icw=0; + break; + case 3: /*ICW4*/ + pic2.icw4 = val; + pic2.icw=0; + break; + } + } else { + if (val & 16) { /*ICW1*/ + pic2.mask = 0; + pic2.mask2=0; + pic2.icw=1; + pic2.icw1 = val; + pic2.ins = 0; + pic_updatepending(); + } else if (!(val & 8)) { /*OCW2*/ + if ((val & 0xE0) == 0x60) { + pic2.ins &= ~(1 << (val & 7)); + pic_update_mask(&pic2.mask2, pic2.ins); + + if (pic_current & (0x100 << (val & 7)) && picint_is_level((val & 7) + 8)) { + pic2.pend |= (1 << (val & 7)); + pic.pend |= (1 << pic2.icw3); + } + + pic_updatepending(); + } else { + for (c = 0; c < 8; c++) { + if (pic2.ins&(1<0xFF) { + if (!AT) + return; + + pic2.pend|=(num>>8); + if ((pic2.pend&~pic2.mask)&~pic2.mask2) + pic.pend |= (1 << pic2.icw3); + } else + pic.pend|=num; + + pic_updatepending(); + } +} + + +void +picint(uint16_t num) +{ + picint_common(num, 0); +} + + +void +picintlevel(uint16_t num) +{ + picint_common(num, 1); +} + + +void +picintc(uint16_t num) +{ + int c = 0; + + if (!num) { + pic_log("Attempting to lower null IRQ\n"); + return; + } + + if (AT && (num == pic.icw3) && (pic.icw3 == 4)) + num = 1 << 9; + + while (!(num & (1 << c))) + c++; + + if (AT && (num == pic.icw3) && (pic.icw3 != 4)) { + pic_log("Attempting to lower cascaded IRQ %i\n"); + return; + } + + if (pic_current & num) + pic_current &= ~num; + + pic_log("Lowering IRQ %i\n", c); + + if (num > 0xff) { + if (!AT) + return; + + pic2.pend &= ~(num >> 8); + if (!((pic2.pend&~pic2.mask)&~pic2.mask2)) + pic.pend &= ~(1 << pic2.icw3); + } else + pic.pend&=~num; + + pic_updatepending(); +} + + +static uint8_t +pic_process_interrupt(PIC* target_pic, int c) +{ + uint8_t pending = target_pic->pend & ~target_pic->mask; + + int pic_int = c & 7; + int pic_int_num = 1 << pic_int; + + if (pending & pic_int_num) { + target_pic->pend &= ~pic_int_num; + target_pic->ins |= pic_int_num; + pic_update_mask(&target_pic->mask2, target_pic->ins); + + if (c >= 8) { + pic.ins |= (1 << pic2.icw3); /*Cascade IRQ*/ + pic_update_mask(&pic.mask2, pic.ins); + } + + pic_updatepending(); + + if (target_pic->icw4 & 0x02) + (c >= 8) ? pic2_autoeoi() : pic_autoeoi(); + + if (!c) + pit_set_gate(&pit2, 0, 0); + + return pic_int + target_pic->vector; + } else + return 0xFF; +} + + +uint8_t +picinterrupt() +{ + int c, d; + uint8_t ret; + + for (c = 0; c <= 7; c++) { + if (AT && ((1 << c) == pic.icw3)) { + for (d = 8; d <= 15; d++) { + ret = pic_process_interrupt(&pic2, d); if (ret != 0xFF) return ret; - } - } - return 0xFF; -} - -void dumppic() -{ - pclog("PIC1 : MASK %02X PEND %02X INS %02X LEVEL %02X VECTOR %02X CASCADE %02X\n", pic.mask, pic.pend, pic.ins, (pic.icw1 & 8) ? 1 : 0, pic.vector, pic.icw3); - if (AT) - { - pclog("PIC2 : MASK %02X PEND %02X INS %02X LEVEL %02X VECTOR %02X CASCADE %02X\n", pic2.mask, pic2.pend, pic2.ins, (pic2.icw1 & 8) ? 1 : 0, pic2.vector, pic2.icw3); + } + } else { + ret = pic_process_interrupt(&pic, c); + if (ret != 0xFF) return ret; } + } + return 0xFF; } + +void +dumppic() +{ + pic_log("PIC1 : MASK %02X PEND %02X INS %02X LEVEL %02X VECTOR %02X CASCADE %02X\n", pic.mask, pic.pend, pic.ins, (pic.icw1 & 8) ? 1 : 0, pic.vector, pic.icw3); + if (AT) + pic_log("PIC2 : MASK %02X PEND %02X INS %02X LEVEL %02X VECTOR %02X CASCADE %02X\n", pic2.mask, pic2.pend, pic2.ins, (pic2.icw1 & 8) ? 1 : 0, pic2.vector, pic2.icw3); +} diff --git a/src/piix.h b/src/piix.h index c781994df..1cfc22c8a 100644 --- a/src/piix.h +++ b/src/piix.h @@ -8,26 +8,19 @@ * * Emulation core dispatcher. * - * Version: @(#)piix.h 1.0.2 2017/10/25 + * Version: @(#)piix.h 1.0.3 2018/05/11 * * Authors: Sarah Walker, * Miran Grca, - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ -extern void piix_init(int card); +extern const device_t piix_device; +extern const device_t piix_pb640_device; +extern const device_t piix3_device; -extern void piix3_init(int card); +extern int piix_bus_master_dma_read(int channel, uint8_t *data, int transfer_length, void *priv); +extern int piix_bus_master_dma_write(int channel, uint8_t *data, int transfer_length, void *priv); -extern void piix4_init(int card); - -extern uint8_t piix_bus_master_read(uint16_t port, void *priv); -extern void piix_bus_master_write(uint16_t port, uint8_t val, void *priv); - -extern int piix_bus_master_get_count(int channel); - -extern int piix_bus_master_dma_read(int channel, uint8_t *data, int transfer_length); -extern int piix_bus_master_dma_write(int channel, uint8_t *data, int transfer_length); - -extern void piix_bus_master_set_irq(int channel); +extern void piix_bus_master_set_irq(int channel, void *priv); diff --git a/src/pit.c b/src/pit.c index c7dbdc365..3ba096154 100644 --- a/src/pit.c +++ b/src/pit.c @@ -2,6 +2,7 @@ Write B0 Write aa55 Expects aa55 back*/ +#include #include #include #include @@ -39,6 +40,12 @@ float VGACONST1, float RTCCONST; int64_t firsttime=1; +void setrtcconst(float clock) +{ + RTCCONST=clock/32768.0; + TIMER_USEC = (int64_t)((clock / 1000000.0f) * (float)(1 << TIMER_SHIFT)); +} + void setpitclock(float clock) { cpuclock=clock; @@ -52,14 +59,14 @@ void setpitclock(float clock) video_update_timing(); xt_cpu_multi = (int64_t)((14318184.0*(double)(1 << TIMER_SHIFT)) / (double)machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed); - RTCCONST=clock/32768.0; - TIMER_USEC = (int64_t)((clock / 1000000.0f) * (float)(1 << TIMER_SHIFT)); + /* RTCCONST=clock/32768.0; + TIMER_USEC = (int64_t)((clock / 1000000.0f) * (float)(1 << TIMER_SHIFT)); */ device_speed_changed(); } void pit_reset(PIT *pit) { - void (*old_set_out_funcs[3])(int64_t new_out, int64_t old_out); + void (*old_set_out_funcs[3])(int new_out, int old_out); PIT_nr old_pit_nr[3]; memcpy(old_set_out_funcs, pit->set_out_funcs, 3 * sizeof(void *)); @@ -68,9 +75,9 @@ void pit_reset(PIT *pit) memcpy(pit->set_out_funcs, old_set_out_funcs, 3 * sizeof(void *)); memcpy(pit->pit_nr, old_pit_nr, 3 * sizeof(PIT_nr)); - pit->l[0] = 0xFFFF; pit->c[0] = 0xFFFFLL*PITCONST; - pit->l[1] = 0xFFFF; pit->c[1] = 0xFFFFLL*PITCONST; - pit->l[2] = 0xFFFF; pit->c[2] = 0xFFFFLL*PITCONST; + pit->l[0] = 0xFFFF; pit->c[0] = 0xFFFF*PITCONST; + pit->l[1] = 0xFFFF; pit->c[1] = 0xFFFF*PITCONST; + pit->l[2] = 0xFFFF; pit->c[2] = 0xFFFF*PITCONST; pit->m[0] = pit->m[1] = pit->m[2] = 0; pit->ctrls[0] = pit->ctrls[1] = pit->ctrls[2] = 0; pit->thit[0]=1; @@ -92,15 +99,15 @@ float pit_timer0_freq() return (1193181.0 + (2.0 / 3.0))/(float)0x10000; } -static void pit_set_out(PIT *pit, int64_t t, int64_t out) +static void pit_set_out(PIT *pit, int t, int out) { pit->set_out_funcs[t](out, pit->out[t]); pit->out[t] = out; } -static void pit_load(PIT *pit, int64_t t) +static void pit_load(PIT *pit, int t) { - int64_t l = pit->l[t] ? pit->l[t] : 0x10000LL; + int l = pit->l[t] ? pit->l[t] : 0x10000; timer_clock(); pit->newcount[t] = 0; pit->disabled[t] = 0; @@ -108,7 +115,7 @@ static void pit_load(PIT *pit, int64_t t) { case 0: /*Interrupt on terminal count*/ pit->count[t] = l; - pit->c[t] = (int64_t)((l << TIMER_SHIFT) * PITCONST); + pit->c[t] = (int64_t)((((int64_t) l) << TIMER_SHIFT) * PITCONST); pit_set_out(pit, t, 0); pit->thit[t] = 0; pit->enabled[t] = pit->gate[t]; @@ -120,7 +127,7 @@ static void pit_load(PIT *pit, int64_t t) if (pit->initial[t]) { pit->count[t] = l - 1; - pit->c[t] = (int64_t)(((l - 1) << TIMER_SHIFT) * PITCONST); + pit->c[t] = (int64_t)(((((int64_t) l) - 1LL) << TIMER_SHIFT) * PITCONST); pit_set_out(pit, t, 1); pit->thit[t] = 0; } @@ -130,7 +137,7 @@ static void pit_load(PIT *pit, int64_t t) if (pit->initial[t]) { pit->count[t] = l; - pit->c[t] = (int64_t)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); + pit->c[t] = (int64_t)((((((int64_t) l) + 1LL) >> 1) << TIMER_SHIFT) * PITCONST); pit_set_out(pit, t, 1); pit->thit[t] = 0; } @@ -157,9 +164,9 @@ static void pit_load(PIT *pit, int64_t t) timer_update_outstanding(); } -void pit_set_gate_no_timer(PIT *pit, int64_t t, int64_t gate) +void pit_set_gate_no_timer(PIT *pit, int t, int gate) { - int64_t l = pit->l[t] ? pit->l[t] : 0x10000LL; + int64_t l = pit->l[t] ? pit->l[t] : 0x10000; if (pit->disabled[t]) { @@ -178,7 +185,7 @@ void pit_set_gate_no_timer(PIT *pit, int64_t t, int64_t gate) if (gate && !pit->gate[t]) { pit->count[t] = l; - pit->c[t] = (int64_t)((l << TIMER_SHIFT) * PITCONST); + pit->c[t] = (int64_t)((((int64_t) l) << TIMER_SHIFT) * PITCONST); pit_set_out(pit, t, 0); pit->thit[t] = 0; pit->enabled[t] = 1; @@ -188,7 +195,7 @@ void pit_set_gate_no_timer(PIT *pit, int64_t t, int64_t gate) if (gate && !pit->gate[t]) { pit->count[t] = l - 1; - pit->c[t] = (int64_t)(((l - 1) << TIMER_SHIFT) * PITCONST); + pit->c[t] = (int64_t)(((((int64_t) l) - 1LL) << TIMER_SHIFT) * PITCONST); pit_set_out(pit, t, 1); pit->thit[t] = 0; } @@ -198,7 +205,7 @@ void pit_set_gate_no_timer(PIT *pit, int64_t t, int64_t gate) if (gate && !pit->gate[t]) { pit->count[t] = l; - pit->c[t] = (int64_t)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); + pit->c[t] = (int64_t)((((((int64_t) l) + 1LL) >> 1) << TIMER_SHIFT) * PITCONST); pit_set_out(pit, t, 1); pit->thit[t] = 0; } @@ -209,7 +216,7 @@ void pit_set_gate_no_timer(PIT *pit, int64_t t, int64_t gate) pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t]; } -void pit_set_gate(PIT *pit, int64_t t, int64_t gate) +void pit_set_gate(PIT *pit, int t, int gate) { if (pit->disabled[t]) { @@ -224,13 +231,13 @@ void pit_set_gate(PIT *pit, int64_t t, int64_t gate) timer_update_outstanding(); } -static void pit_over(PIT *pit, int64_t t) +static void pit_over(PIT *pit, int t) { - int64_t l = pit->l[t] ? pit->l[t] : 0x10000LL; + int64_t l = pit->l[t] ? pit->l[t] : 0x10000; if (pit->disabled[t]) { pit->count[t] += 0xffff; - pit->c[t] += (int64_t)((0xffff << TIMER_SHIFT) * PITCONST); + pit->c[t] += (int64_t)((0xffffLL << TIMER_SHIFT) * PITCONST); return; } @@ -242,11 +249,11 @@ static void pit_over(PIT *pit, int64_t t) pit_set_out(pit, t, 1); pit->thit[t] = 1; pit->count[t] += 0xffff; - pit->c[t] += (int64_t)((0xffff << TIMER_SHIFT) * PITCONST); + pit->c[t] += (int64_t)((0xffffLL << TIMER_SHIFT) * PITCONST); break; case 2: /*Rate generator*/ pit->count[t] += l; - pit->c[t] += (int64_t)((l << TIMER_SHIFT) * PITCONST); + pit->c[t] += (int64_t)((((int64_t) l) << TIMER_SHIFT) * PITCONST); pit_set_out(pit, t, 0); pit_set_out(pit, t, 1); break; @@ -255,13 +262,13 @@ static void pit_over(PIT *pit, int64_t t) { pit_set_out(pit, t, 0); pit->count[t] += (l >> 1); - pit->c[t] += (int64_t)(((l >> 1) << TIMER_SHIFT) * PITCONST); + pit->c[t] += (int64_t)(((((int64_t) l) >> 1) << TIMER_SHIFT) * PITCONST); } else { pit_set_out(pit, t, 1); pit->count[t] += ((l + 1) >> 1); - pit->c[t] = (int64_t)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST); + pit->c[t] = (int64_t)((((((int64_t) l) + 1LL) >> 1) << TIMER_SHIFT) * PITCONST); } break; case 4: /*Software triggered strove*/ @@ -274,13 +281,13 @@ static void pit_over(PIT *pit, int64_t t) { pit->newcount[t] = 0; pit->count[t] += l; - pit->c[t] += (int64_t)((l << TIMER_SHIFT) * PITCONST); + pit->c[t] += (int64_t)((((int64_t) l) << TIMER_SHIFT) * PITCONST); } else { pit->thit[t] = 1; pit->count[t] += 0xffff; - pit->c[t] += (int64_t)((0xffff << TIMER_SHIFT) * PITCONST); + pit->c[t] += (int64_t)((0xffffLL << TIMER_SHIFT) * PITCONST); } break; case 5: /*Hardware triggered strove*/ @@ -291,52 +298,51 @@ static void pit_over(PIT *pit, int64_t t) } pit->thit[t] = 1; pit->count[t] += 0xffff; - pit->c[t] += (int64_t)((0xffff << TIMER_SHIFT) * PITCONST); + pit->c[t] += (int64_t)((0xffffLL << TIMER_SHIFT) * PITCONST); break; } pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t]; } -int64_t pit_get_timer_0() +int pit_get_timer_0() { - int64_t read = (int64_t)((pit.c[0] + ((1 << TIMER_SHIFT) - 1)) / PITCONST) >> TIMER_SHIFT; + int read = (int)((int64_t)((pit.c[0] + ((1LL << TIMER_SHIFT) - 1)) / PITCONST) >> TIMER_SHIFT); if (pit.m[0] == 2) read++; - if (read < 0LL) - read = 0LL; - if (read > 0x10000LL) - read = 0x10000LL; - if (pit.m[0] == 3LL) - read <<= 1LL; + if (read < 0) + read = 0; + if (read > 0x10000) + read = 0x10000; + if (pit.m[0] == 3) + read <<= 1; return read; } -static int64_t pit_read_timer(PIT *pit, int64_t t) +static int pit_read_timer(PIT *pit, int t) { timer_clock(); if (pit->using_timer[t] && !(pit->m[t] == 3 && !pit->gate[t])) { - int64_t read = (int64_t)((pit->c[t] + ((1 << TIMER_SHIFT) - 1)) / PITCONST) >> TIMER_SHIFT; + int read = (int)((int64_t)((pit->c[t] + ((1LL << TIMER_SHIFT) - 1)) / PITCONST) >> TIMER_SHIFT); if (pit->m[t] == 2) read++; - if (read < 0LL) - read = 0LL; - if (read > 0x10000LL) - read = 0x10000LL; - if (pit->m[t] == 3LL) - read <<= 1LL; + if (read < 0) + read = 0; + if (read > 0x10000) + read = 0x10000; + if (pit->m[t] == 3) + read <<= 1; return read; } - if (pit->m[t] == 2LL) - return pit->count[t] + 1LL; + if (pit->m[t] == 2) + return pit->count[t] + 1; return pit->count[t]; } void pit_write(uint16_t addr, uint8_t val, void *p) { PIT *pit = (PIT *)p; - int64_t t; - cycles -= (int64_t)PITCONST; + int t; switch (addr&3) { @@ -444,7 +450,6 @@ uint8_t pit_read(uint16_t addr, void *p) PIT *pit = (PIT *)p; int64_t t; uint8_t temp = 0xff; - cycles -= (int64_t)PITCONST; switch (addr&3) { case 0: case 1: case 2: /*Timers*/ @@ -503,7 +508,7 @@ void pit_timer_over(void *p) pit_over(pit, timer); } -void pit_clock(PIT *pit, int64_t t) +void pit_clock(PIT *pit, int t) { if (pit->thit[t] || !pit->enabled[t]) return; @@ -516,28 +521,28 @@ void pit_clock(PIT *pit, int64_t t) pit_over(pit, t); } -void pit_set_using_timer(PIT *pit, int64_t t, int64_t using_timer) +void pit_set_using_timer(PIT *pit, int t, int using_timer) { timer_process(); if (pit->using_timer[t] && !using_timer) pit->count[t] = pit_read_timer(pit, t); if (!pit->using_timer[t] && using_timer) - pit->c[t] = (int64_t)((pit->count[t] << TIMER_SHIFT) * PITCONST); + pit->c[t] = (int64_t)((((int64_t) pit->count[t]) << TIMER_SHIFT) * PITCONST); pit->using_timer[t] = using_timer; pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t]; timer_update_outstanding(); } -void pit_set_out_func(PIT *pit, int64_t t, void (*func)(int64_t new_out, int64_t old_out)) +void pit_set_out_func(PIT *pit, int t, void (*func)(int new_out, int old_out)) { pit->set_out_funcs[t] = func; } -void pit_null_timer(int64_t new_out, int64_t old_out) +void pit_null_timer(int new_out, int old_out) { } -void pit_irq0_timer(int64_t new_out, int64_t old_out) +void pit_irq0_timer(int new_out, int old_out) { if (new_out && !old_out) picint(1); @@ -545,7 +550,7 @@ void pit_irq0_timer(int64_t new_out, int64_t old_out) picintc(1); } -void pit_irq0_timer_pcjr(int64_t new_out, int64_t old_out) +void pit_irq0_timer_pcjr(int new_out, int old_out) { if (new_out && !old_out) { @@ -556,7 +561,7 @@ void pit_irq0_timer_pcjr(int64_t new_out, int64_t old_out) picintc(1); } -void pit_irq0_ps2(int64_t new_out, int64_t old_out) +void pit_irq0_ps2(int new_out, int old_out) { if (new_out && !old_out) { @@ -569,19 +574,19 @@ void pit_irq0_ps2(int64_t new_out, int64_t old_out) pit_clock(&pit2, 0); } -void pit_refresh_timer_xt(int64_t new_out, int64_t old_out) +void pit_refresh_timer_xt(int new_out, int old_out) { if (new_out && !old_out) dma_channel_read(0); } -void pit_refresh_timer_at(int64_t new_out, int64_t old_out) +void pit_refresh_timer_at(int new_out, int old_out) { if (new_out && !old_out) ppi.pb ^= 0x10; } -void pit_speaker_timer(int64_t new_out, int64_t old_out) +void pit_speaker_timer(int new_out, int old_out) { int64_t l; @@ -596,7 +601,7 @@ void pit_speaker_timer(int64_t new_out, int64_t old_out) } -void pit_nmi_ps2(int64_t new_out, int64_t old_out) +void pit_nmi_ps2(int new_out, int old_out) { nmi = new_out; if (nmi) diff --git a/src/pit.h b/src/pit.h index 5f48a283a..00297eb26 100644 --- a/src/pit.h +++ b/src/pit.h @@ -13,30 +13,30 @@ typedef struct PIT { uint8_t m[3]; uint8_t ctrl, ctrls[3]; - int64_t wp, + int wp, rm[3], wm[3]; uint16_t rl[3]; - int64_t thit[3]; - int64_t delay[3]; - int64_t rereadlatch[3]; - int64_t gate[3]; - int64_t out[3]; + int thit[3]; + int delay[3]; + int rereadlatch[3]; + int gate[3]; + int out[3]; int64_t running[3]; - int64_t enabled[3]; - int64_t newcount[3]; - int64_t count[3]; - int64_t using_timer[3]; - int64_t initial[3]; - int64_t latched[3]; - int64_t disabled[3]; + int enabled[3]; + int newcount[3]; + int count[3]; + int using_timer[3]; + int initial[3]; + int latched[3]; + int disabled[3]; uint8_t read_status[3]; - int64_t do_read_status[3]; + int do_read_status[3]; PIT_nr pit_nr[3]; - void (*set_out_funcs[3])(int64_t new_out, int64_t old_out); + void (*set_out_funcs[3])(int new_out, int old_out); } PIT; @@ -53,20 +53,22 @@ extern float CGACONST, extern void pit_init(void); extern void pit_ps2_init(void); extern void pit_reset(PIT *pit); -extern void pit_set_gate(PIT *pit, int64_t channel, int64_t gate); -extern void pit_set_using_timer(PIT *pit, int64_t t, int64_t using_timer); -extern void pit_set_out_func(PIT *pit, int64_t t, void (*func)(int64_t new_out, int64_t old_out)); -extern void pit_clock(PIT *pit, int64_t t); +extern void pit_set_gate(PIT *pit, int channel, int gate); +extern void pit_set_using_timer(PIT *pit, int t, int using_timer); +extern void pit_set_out_func(PIT *pit, int t, void (*func)(int new_out, int old_out)); +extern void pit_clock(PIT *pit, int t); + +extern void setrtcconst(float clock); extern void setpitclock(float clock); extern float pit_timer0_freq(void); -extern void pit_null_timer(int64_t new_out, int64_t old_out); -extern void pit_irq0_timer(int64_t new_out, int64_t old_out); -extern void pit_irq0_timer_pcjr(int64_t new_out, int64_t old_out); -extern void pit_refresh_timer_xt(int64_t new_out, int64_t old_out); -extern void pit_refresh_timer_at(int64_t new_out, int64_t old_out); -extern void pit_speaker_timer(int64_t new_out, int64_t old_out); +extern void pit_null_timer(int new_out, int old_out); +extern void pit_irq0_timer(int new_out, int old_out); +extern void pit_irq0_timer_pcjr(int new_out, int old_out); +extern void pit_refresh_timer_xt(int new_out, int old_out); +extern void pit_refresh_timer_at(int new_out, int old_out); +extern void pit_speaker_timer(int new_out, int old_out); #endif /*EMU_PIT_H*/ diff --git a/src/plat.h b/src/plat.h index c8291528a..fc7e5e252 100644 --- a/src/plat.h +++ b/src/plat.h @@ -107,14 +107,13 @@ extern void do_stop(void); extern uint8_t host_cdrom_drive_available[26]; extern uint8_t host_cdrom_drive_available_num; +#ifdef USE_IOCTL extern void cdrom_init_host_drives(void); +#endif extern void cdrom_eject(uint8_t id); extern void cdrom_reload(uint8_t id); extern void zip_eject(uint8_t id); extern void zip_reload(uint8_t id); -extern void removable_disk_unload(uint8_t id); -extern void removable_disk_eject(uint8_t id); -extern void removable_disk_reload(uint8_t id); extern int ioctl_open(uint8_t id, char d); extern void ioctl_reset(uint8_t id); extern void ioctl_close(uint8_t id); diff --git a/src/rom.c b/src/rom.c index 19cf4c762..0fbb102a4 100644 --- a/src/rom.c +++ b/src/rom.c @@ -13,7 +13,7 @@ * - c386sx16 BIOS fails checksum * - the loadfont() calls should be done elsewhere * - * Version: @(#)rom.c 1.0.35 2018/03/16 + * Version: @(#)rom.c 1.0.37 2018/05/20 * * Authors: Sarah Walker, * Miran Grca, @@ -23,11 +23,13 @@ * Copyright 2016-2018 Miran Grca. * Copyright 2018 Fred N. van Kempen. */ +#include #include #include #include #include #include +#define HAVE_STDARG_H #include "86box.h" #include "config.h" #include "cpu/cpu.h" @@ -41,6 +43,26 @@ int romspresent[ROM_MAX]; +#ifdef ENABLE_ROM_LOG +int rom_do_log = ENABLE_ROM_LOG; +#endif + + +static void +rom_log(const char *format, ...) +{ +#ifdef ENABLE_ROM_LOG + va_list ap; + + if (rom_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + FILE * rom_fopen(wchar_t *fn, wchar_t *mode) { @@ -95,7 +117,7 @@ rom_read(uint32_t addr, void *priv) #ifdef ROM_TRACE if (rom->mapping.base==ROM_TRACE) - pclog("ROM: read byte from BIOS at %06lX\n", addr); + rom_log("ROM: read byte from BIOS at %06lX\n", addr); #endif return(rom->rom[addr & rom->mask]); @@ -109,7 +131,7 @@ rom_readw(uint32_t addr, void *priv) #ifdef ROM_TRACE if (rom->mapping.base==ROM_TRACE) - pclog("ROM: read word from BIOS at %06lX\n", addr); + rom_log("ROM: read word from BIOS at %06lX\n", addr); #endif return(*(uint16_t *)&rom->rom[addr & rom->mask]); @@ -123,7 +145,7 @@ rom_readl(uint32_t addr, void *priv) #ifdef ROM_TRACE if (rom->mapping.base==ROM_TRACE) - pclog("ROM: read long from BIOS at %06lX\n", addr); + rom_log("ROM: read long from BIOS at %06lX\n", addr); #endif return(*(uint32_t *)&rom->rom[addr & rom->mask]); @@ -137,7 +159,7 @@ rom_load_linear(wchar_t *fn, uint32_t addr, int sz, int off, uint8_t *ptr) FILE *f = rom_fopen(fn, L"rb"); if (f == NULL) { - pclog("ROM: image '%ls' not found\n", fn); + rom_log("ROM: image '%ls' not found\n", fn); return(0); } @@ -166,7 +188,7 @@ rom_load_linear_inverted(wchar_t *fn, uint32_t addr, int sz, int off, uint8_t *p FILE *f = rom_fopen(fn, L"rb"); if (f == NULL) { - pclog("ROM: image '%ls' not found\n", fn); + rom_log("ROM: image '%ls' not found\n", fn); return(0); } @@ -204,9 +226,9 @@ rom_load_interleaved(wchar_t *fnl, wchar_t *fnh, uint32_t addr, int sz, int off, int c; if (fl == NULL || fh == NULL) { - if (fl == NULL) pclog("ROM: image '%ls' not found\n", fnl); + if (fl == NULL) rom_log("ROM: image '%ls' not found\n", fnl); else (void)fclose(fl); - if (fh == NULL) pclog("ROM: image '%ls' not found\n", fnh); + if (fh == NULL) rom_log("ROM: image '%ls' not found\n", fnh); else (void)fclose(fh); return(0); @@ -296,9 +318,6 @@ rom_load_bios(int rom_id) FILE *f; loadfont(L"roms/video/mda/mda.rom", 0); - loadfont(L"roms/video/wyse700/wy700.rom", 3); - loadfont(L"roms/video/genius/8x12.bin", 4); - loadfont(FONT_ATIKOR_PATH, 6); /* If not done yet, allocate a 128KB buffer for the BIOS ROM. */ if (rom == NULL) @@ -861,12 +880,24 @@ rom_load_bios(int rom_id) biosmask = 0x1ffff; return(1); +#if defined(DEV_BRANCH) && defined(USE_MRTHOR) case ROM_MRTHOR: if (! rom_load_linear( L"roms/machines/mrthor/mr_atx.bio", 0x000000, 131072, 0, rom)) break; biosmask = 0x1ffff; return(1); +#endif + + case ROM_PB640: + if (! rom_load_linear( + L"roms/machines/pb640/1007CP0R.BIO", + 0x010000, 65536, 128, rom)) break; + if (! rom_load_linear( + L"roms/machines/pb640/1007CP0R.BI1", + 0x000000, 0x00d000, 128, rom)) break; + biosmask = 0x1ffff; + return(1); case ROM_ZAPPA: if (! rom_load_linear( @@ -899,9 +930,6 @@ rom_load_bios(int rom_id) return(1); case ROM_IBMPS2_M80: -#ifdef WALTJE - case ROM_IBMPS2_M80_486: -#endif if (! rom_load_interleaved( L"roms/machines/ibmps2_m80/15f6637.bin", L"roms/machines/ibmps2_m80/15f6639.bin", @@ -909,14 +937,6 @@ rom_load_bios(int rom_id) biosmask = 0x1ffff; return(1); -#if defined(DEV_BRANCH) && defined(USE_GREENB) - case ROM_4GPV31: - if (! rom_load_linear( - L"roms/machines/green-b/4gpv31-ami-1993-8273517.bin", - 0x000000, 65536, 0, rom)) break; - return(1); -#endif - case ROM_T1000: loadfont(L"roms/machines/t1000/t1000font.bin", 2); if (!rom_load_linear( @@ -941,7 +961,7 @@ rom_load_bios(int rom_id) break; default: - pclog("ROM: don't know how to handle ROM set %d !\n", rom_id); + rom_log("ROM: don't know how to handle ROM set %d !\n", rom_id); } return(0); diff --git a/src/rom.h b/src/rom.h index ce6e3b2c1..095ddb1d3 100644 --- a/src/rom.h +++ b/src/rom.h @@ -8,7 +8,7 @@ * * Definitions for the ROM image handler. * - * Version: @(#)rom.h 1.0.16 2018/03/02 + * Version: @(#)rom.h 1.0.17 2018/05/10 * * Author: Fred N. van Kempen, * Copyright 2018 Fred N. van Kempen. @@ -122,17 +122,10 @@ enum { #endif ROM_AWARD486_OPTI495, ROM_DTK486, /* DTK PKM-0038S E-2/SiS 471/Award/SiS 85C471 */ -#if defined(DEV_BRANCH) && defined(USE_GREENB) - ROM_4GPV31, /* Green-B 4GPV3.1 ISA/VLB 486/Pentium, AMI */ -#endif ROM_IBMPS1_2133, - ROM_IBMPS2_M70_TYPE3, - ROM_IBMPS2_M70_TYPE4, - -#ifdef WALTJE - ROM_IBMPS2_M80_486, -#endif + ROM_IBMPS2_M70_TYPE3, + ROM_IBMPS2_M70_TYPE4, ROM_R418, /* Rise Computer R418/SiS 496/497/Award/SMC FDC37C665 */ @@ -150,7 +143,10 @@ enum { ROM_PRESIDENT, /* President Award 430FX PCI/430FX/Award/Unknown SIO */ ROM_THOR, /* Intel Advanced_ATX/430FX/AMI/NS PC87306 */ +#if defined(DEV_BRANCH) && defined(USE_MRTHOR) ROM_MRTHOR, /* Intel Advanced_ATX/430FX/MR.BIOS/NS PC87306 */ +#endif + ROM_PB640, /* Packard Bell PB640/430FX/AMI/NS PC87306 */ ROM_ACERM3A, /* Acer M3A/430HX/Acer/SMC FDC37C932FR */ ROM_ACERV35N, /* Acer V35N/430HX/Acer/SMC FDC37C932FR */ diff --git a/src/scsi/scsi.c b/src/scsi/scsi.c index e75993d82..8fc535dc3 100644 --- a/src/scsi/scsi.c +++ b/src/scsi/scsi.c @@ -8,7 +8,7 @@ * * Handling of the SCSI controllers. * - * Version: @(#)scsi.c 1.0.17 2018/03/18 + * Version: @(#)scsi.c 1.0.20 2018/06/02 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -17,21 +17,26 @@ * Copyright 2016-2018 Miran Grca. * Copyright 2017,2018 Fred N. van Kempen. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../mem.h" #include "../rom.h" #include "../timer.h" #include "../device.h" -#include "../cdrom/cdrom.h" #include "../disk/hdc.h" -#include "../disk/zip.h" +#include "../disk/hdd.h" #include "../plat.h" #include "scsi.h" +#include "../cdrom/cdrom.h" +#include "../disk/zip.h" +#include "scsi_disk.h" +#include "scsi_device.h" #include "scsi_aha154x.h" #include "scsi_buslogic.h" #include "scsi_ncr5380.h" @@ -42,11 +47,9 @@ #include "scsi_x54x.h" -scsi_device_t SCSIDevices[SCSI_ID_MAX][SCSI_LUN_MAX]; -// uint8_t SCSIPhase = 0xff; -// uint8_t SCSIStatus = SCSI_STATUS_OK; +scsi_device_t SCSIDevices[SCSI_ID_MAX]; char scsi_fn[SCSI_NUM][512]; -uint16_t scsi_hd_location[SCSI_NUM]; +uint16_t scsi_disk_location[SCSI_NUM]; int scsi_card_current = 0; int scsi_card_last = 0; @@ -60,33 +63,52 @@ typedef const struct { const char *name; const char *internal_name; const device_t *device; - void (*reset)(void *p); } SCSI_CARD; static SCSI_CARD scsi_cards[] = { - { "None", "none", NULL, NULL }, - { "[ISA] Adaptec AHA-1540B","aha1540b", &aha1540b_device, x54x_device_reset }, - { "[ISA] Adaptec AHA-1542C","aha1542c", &aha1542c_device, x54x_device_reset }, - { "[ISA] Adaptec AHA-1542CF","aha1542cf", &aha1542cf_device, x54x_device_reset }, - { "[ISA] BusLogic BT-542BH","bt542bh", &buslogic_device, BuslogicDeviceReset }, - { "[ISA] BusLogic BT-545S", "bt545s", &buslogic_545s_device,BuslogicDeviceReset }, - { "[ISA] Longshine LCS-6821N","lcs6821n", &scsi_lcs6821n_device,NULL }, - { "[ISA] Ranco RT1000B", "rt1000b", &scsi_rt1000b_device, NULL }, - { "[ISA] Trantor T130B", "t130b", &scsi_t130b_device, NULL }, - { "[ISA] Sumo SCSI-AT", "scsiat", &scsi_scsiat_device, NULL }, + { "None", "none", NULL, }, + { "[ISA] Adaptec AHA-1540B","aha1540b", &aha1540b_device, }, + { "[ISA] Adaptec AHA-1542C","aha1542c", &aha1542c_device, }, + { "[ISA] Adaptec AHA-1542CF","aha1542cf", &aha1542cf_device, }, + { "[ISA] BusLogic BT-542BH","bt542bh", &buslogic_device, }, + { "[ISA] BusLogic BT-545S", "bt545s", &buslogic_545s_device,}, + { "[ISA] Longshine LCS-6821N","lcs6821n", &scsi_lcs6821n_device,}, + { "[ISA] Ranco RT1000B", "rt1000b", &scsi_rt1000b_device, }, + { "[ISA] Trantor T130B", "t130b", &scsi_t130b_device, }, + { "[ISA] Sumo SCSI-AT", "scsiat", &scsi_scsiat_device, }, #ifdef WALTJE - { "[ISA] Generic WDC33C93", "wd33c93", &scsi_wd33c93_device, NULL }, + { "[ISA] Generic WDC33C93", "wd33c93", &scsi_wd33c93_device, }, #endif - { "[MCA] Adaptec AHA-1640", "aha1640", &aha1640_device, x54x_device_reset }, - { "[MCA] BusLogic BT-640A", "bt640a", &buslogic_640a_device,BuslogicDeviceReset }, - { "[PCI] BusLogic BT-958D", "bt958d", &buslogic_pci_device, BuslogicDeviceReset }, - { "[PCI] NCR 53C810", "ncr53c810", &ncr53c810_pci_device,NULL }, - { "[VLB] BusLogic BT-445S", "bt445s", &buslogic_445s_device,BuslogicDeviceReset }, - { "", "", NULL, NULL }, + { "[MCA] Adaptec AHA-1640", "aha1640", &aha1640_device, }, + { "[MCA] BusLogic BT-640A", "bt640a", &buslogic_640a_device,}, + { "[PCI] BusLogic BT-958D", "bt958d", &buslogic_pci_device, }, + { "[PCI] NCR 53C810", "ncr53c810", &ncr53c810_pci_device,}, + { "[VLB] BusLogic BT-445S", "bt445s", &buslogic_445s_device,}, + { "", "", NULL, }, }; +#ifdef ENABLE_SCSI_LOG +int scsi_do_log = ENABLE_SCSI_LOG; +#endif + + +static void +scsi_log(const char *fmt, ...) +{ +#ifdef ENABLE_SCSI_LOG + va_list ap; + + if (scsi_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + int scsi_card_available(int card) { if (scsi_cards[card].device) @@ -147,78 +169,59 @@ void scsi_mutex(uint8_t start) void scsi_card_init(void) { - int i, j; + int i; - pclog("Building SCSI hard disk map...\n"); - build_scsi_hd_map(); - pclog("Building SCSI CD-ROM map...\n"); + if (!scsi_cards[scsi_card_current].device) + return; + + scsi_log("Building SCSI hard disk map...\n"); + build_scsi_disk_map(); + scsi_log("Building SCSI CD-ROM map...\n"); build_scsi_cdrom_map(); - pclog("Building SCSI ZIP map...\n"); + scsi_log("Building SCSI ZIP map...\n"); build_scsi_zip_map(); for (i=0; i * Miran Grca, @@ -103,6 +103,13 @@ #define GPMODE_CAPABILITIES_PAGE 0x2a #define GPMODE_ALL_PAGES 0x3f +/* Mode page codes for presence */ +#define GPMODEP_R_W_ERROR_PAGE 0x0000000000000002LL +#define GPMODEP_CDROM_PAGE 0x0000000000002000LL +#define GPMODEP_CDROM_AUDIO_PAGE 0x0000000000004000LL +#define GPMODEP_CAPABILITIES_PAGE 0x0000040000000000LL +#define GPMODEP_ALL_PAGES 0x8000000000000000LL + /* SCSI Status Codes */ #define SCSI_STATUS_OK 0 #define SCSI_STATUS_CHECK_CONDITION 2 @@ -283,9 +290,9 @@ typedef struct { } scsi_device_t; -extern scsi_device_t SCSIDevices[SCSI_ID_MAX][SCSI_LUN_MAX]; +extern scsi_device_t SCSIDevices[SCSI_ID_MAX]; -extern void SCSIReset(uint8_t id, uint8_t lun); +extern void SCSIReset(uint8_t id); extern int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type); extern int cdrom_LBAtoMSF_accurate(void); @@ -306,18 +313,6 @@ extern char *scsi_card_get_internal_name(int card); extern int scsi_card_get_from_internal_name(char *s); extern void scsi_mutex(uint8_t start); extern void scsi_card_init(void); -extern void scsi_card_reset(void); - -extern uint8_t scsi_hard_disks[16][8]; - -extern int scsi_hd_err_stat_to_scsi(uint8_t id); -extern int scsi_hd_phase_to_scsi(uint8_t id); -extern int find_hdc_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun); -extern void build_scsi_hd_map(void); -extern void scsi_hd_reset(uint8_t id); -extern void scsi_hd_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length); -extern void scsi_hd_command(uint8_t id, uint8_t *cdb); -extern void scsi_hd_callback(uint8_t id); #pragma pack(push,1) diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index efb34ebf8..59e48129c 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -10,7 +10,7 @@ * made by Adaptec, Inc. These controllers were designed for * the ISA bus. * - * Version: @(#)scsi_aha154x.c 1.0.40 2018/03/18 + * Version: @(#)scsi_aha154x.c 1.0.42 2018/06/12 * * Authors: Fred N. van Kempen, * Original Buslogic version by SA1988 and Miran Grca. @@ -30,11 +30,11 @@ #include "../mem.h" #include "../mca.h" #include "../rom.h" +#include "../device.h" #include "../nvr.h" #include "../dma.h" #include "../pic.h" #include "../timer.h" -#include "../device.h" #include "../plat.h" #include "../cpu/cpu.h" #include "scsi.h" @@ -573,7 +573,7 @@ aha_mca_write(int port, uint8_t val, void *priv) } /* Say hello. */ - pclog("AHA-1640: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X, HOST ID %i\n", + aha_log("AHA-1640: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X, HOST ID %i\n", dev->Base, dev->Irq, dev->DmaChannel, dev->rom_addr, dev->HostID); } } @@ -1113,7 +1113,7 @@ const device_t aha1540b_device = { DEVICE_ISA | DEVICE_AT, AHA_154xB, aha_init, x54x_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, aha_154xb_config }; @@ -1122,7 +1122,7 @@ const device_t aha1542c_device = { DEVICE_ISA | DEVICE_AT, AHA_154xC, aha_init, x54x_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, aha_154x_config }; @@ -1131,7 +1131,7 @@ const device_t aha1542cf_device = { DEVICE_ISA | DEVICE_AT, AHA_154xCF, aha_init, x54x_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, aha_154x_config }; @@ -1140,6 +1140,6 @@ const device_t aha1640_device = { DEVICE_MCA, AHA_1640, aha_init, x54x_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; diff --git a/src/scsi/scsi_bus.c b/src/scsi/scsi_bus.c index 5d870954d..930c4daff 100644 --- a/src/scsi/scsi_bus.c +++ b/src/scsi/scsi_bus.c @@ -8,7 +8,7 @@ * * The generic SCSI bus operations handler. * - * Version: @(#)scsi_bus.c 1.0.6 2018/01/06 + * Version: @(#)scsi_bus.c 1.0.7 2018/06/18 * * NOTES: For now ported from PCem with some modifications * but at least it's a start. @@ -94,7 +94,6 @@ int scsi_bus_update(scsi_bus_t *bus, int bus_assert) { scsi_device_t *dev; - uint8_t lun = 0; if (bus_assert & BUS_ARB) bus->state = STATE_IDLE; @@ -108,7 +107,7 @@ scsi_bus_update(scsi_bus_t *bus, int bus_assert) bus->dev_id = get_dev_id(sel_data); - if ((bus->dev_id != -1) && scsi_device_present(bus->dev_id, 0)) { + if ((bus->dev_id != -1) && scsi_device_present(bus->dev_id)) { bus->bus_out |= BUS_BSY; bus->state = STATE_PHASESEL; } @@ -122,7 +121,7 @@ scsi_bus_update(scsi_bus_t *bus, int bus_assert) if (! (bus_assert & BUS_SEL)) { if (! (bus_assert & BUS_ATN)) { if ((bus->dev_id != -1) && - scsi_device_present(bus->dev_id, 0)) { + scsi_device_present(bus->dev_id)) { bus->state = STATE_COMMAND; bus->bus_out = BUS_BSY | BUS_REQ; bus->command_pos = 0; @@ -146,20 +145,17 @@ scsi_bus_update(scsi_bus_t *bus, int bus_assert) bus->bus_out &= ~BUS_REQ; if (get_cmd_len(bus->command[0]) == bus->command_pos) { - lun = (bus->command[1] >> 5) & 7; bus->data_pos = 0; - dev = &SCSIDevices[bus->dev_id][lun]; + dev = &SCSIDevices[bus->dev_id]; scsi_bus_log("Command 0x%02X\n", bus->command[0]); dev->BufferLength = -1; - scsi_device_command_phase0(bus->dev_id, lun, - get_cmd_len(bus->command[0]), - bus->command); + scsi_device_command_phase0(bus->dev_id, bus->command); - scsi_bus_log("(%02X:%02X): Command %02X: Buffer Length %i, SCSI Phase %02X\n", bus->dev_id, lun, bus->command[0], dev->BufferLength, dev->Phase); + scsi_bus_log("(ID %02X): Command %02X: Buffer Length %i, SCSI Phase %02X\n", bus->dev_id, bus->command[0], dev->BufferLength, dev->Phase); if ((dev->Phase == SCSI_PHASE_DATA_IN) || (dev->Phase == SCSI_PHASE_DATA_OUT)) { @@ -178,7 +174,7 @@ scsi_bus_update(scsi_bus_t *bus, int bus_assert) /* Other command - execute immediately. */ bus->new_state = dev->Phase; if (dev->Phase == SCSI_PHASE_DATA_IN) { - scsi_device_command_phase1(bus->dev_id, lun); + scsi_device_command_phase1(bus->dev_id); } bus->change_state_delay = 4; @@ -198,12 +194,9 @@ scsi_bus_update(scsi_bus_t *bus, int bus_assert) scsi_bus_log("State Data In\n"); /* This seems to be read, so we first execute the command, then we return the bytes to the host. */ + dev = &SCSIDevices[bus->dev_id]; - lun = (bus->command[1] >> 5) & 7; - - dev = &SCSIDevices[bus->dev_id][lun]; - - if (bus->data_pos >= SCSIDevices[bus->dev_id][lun].BufferLength) { + if (bus->data_pos >= SCSIDevices[bus->dev_id].BufferLength) { free(dev->CmdBuffer); dev->CmdBuffer = NULL; bus->bus_out &= ~BUS_REQ; @@ -224,18 +217,15 @@ scsi_bus_update(scsi_bus_t *bus, int bus_assert) case STATE_DATAOUT: if ((bus_assert & BUS_ACK) && !(bus->bus_in & BUS_ACK)) { scsi_bus_log("State Data Out\n"); - - lun = (bus->command[1] >> 5) & 7; - - dev = &SCSIDevices[bus->dev_id][lun]; + dev = &SCSIDevices[bus->dev_id]; /* This is write, so first get the data from the host, then execute the last phase of the command. */ dev->CmdBuffer[bus->data_pos++] = BUS_GETDATA(bus_assert); - if (bus->data_pos >= SCSIDevices[bus->dev_id][lun].BufferLength) { + if (bus->data_pos >= SCSIDevices[bus->dev_id].BufferLength) { /* scsi_bus_log("%04X bytes written (%02X %02X)\n", bus->data_pos, bus->command[0], bus->command[1]); */ scsi_bus_log("Actually executing write command\n"); - scsi_device_command_phase1(bus->dev_id, lun); + scsi_device_command_phase1(bus->dev_id); free(dev->CmdBuffer); dev->CmdBuffer = NULL; bus->bus_out &= ~BUS_REQ; @@ -281,7 +271,6 @@ int scsi_bus_read(scsi_bus_t *bus) { scsi_device_t *dev; - uint8_t lun = 0; if (bus->clear_req) { bus->clear_req--; @@ -304,8 +293,7 @@ scsi_bus_read(scsi_bus_t *bus) switch (bus->bus_out & SCSI_PHASE_MESSAGE_IN) { case SCSI_PHASE_DATA_IN: - lun = (bus->command[1] >> 5) & 7; - dev = &SCSIDevices[bus->dev_id][lun]; + dev = &SCSIDevices[bus->dev_id]; scsi_bus_log("Phase data in\n"); bus->state = STATE_DATAIN; @@ -324,8 +312,7 @@ scsi_bus_read(scsi_bus_t *bus) break; case SCSI_PHASE_STATUS: - lun = (bus->command[1] >> 5) & 7; - dev = &SCSIDevices[bus->dev_id][lun]; + dev = &SCSIDevices[bus->dev_id]; scsi_bus_log("Phase status\n"); bus->state = STATE_STATUS; diff --git a/src/scsi/scsi_buslogic.c b/src/scsi/scsi_buslogic.c index e796ec23e..bc5eb421c 100644 --- a/src/scsi/scsi_buslogic.c +++ b/src/scsi/scsi_buslogic.c @@ -11,7 +11,7 @@ * 1 - BT-545S ISA; * 2 - BT-958D PCI * - * Version: @(#)scsi_buslogic.c 1.0.36 2018/03/18 + * Version: @(#)scsi_buslogic.c 1.0.39 2018/06/11 * * Authors: TheCollector1995, * Miran Grca, @@ -33,12 +33,12 @@ #include "../mem.h" #include "../mca.h" #include "../rom.h" +#include "../device.h" #include "../nvr.h" #include "../dma.h" #include "../pic.h" #include "../pci.h" #include "../timer.h" -#include "../device.h" #include "../plat.h" #include "scsi.h" #include "scsi_buslogic.h" @@ -480,7 +480,7 @@ buslogic_get_irq(void *p) HALocalRAM *HALR = &bl->LocalRAM; - if (bl->chip == CHIP_BUSLOGIC_PCI) + if ((bl->chip == CHIP_BUSLOGIC_ISA_542) || (bl->chip == CHIP_BUSLOGIC_PCI)) return dev->Irq; else return bl_irq[HALR->structured.autoSCSIData.uIrqChannel]; @@ -499,6 +499,8 @@ buslogic_get_dma(void *p) if (bl->chip == CHIP_BUSLOGIC_PCI) return (dev->Base ? 7 : 0); + else if (bl->chip == CHIP_BUSLOGIC_ISA_542) + return dev->DmaChannel; else return bl_dma[HALR->structured.autoSCSIData.uDMAChannel]; } @@ -529,6 +531,7 @@ buslogic_param_len(void *p) case 0x91: return 2; case 0x94: + case 0xFB: return 3; case 0x93: /* Valid only for VLB */ return (bl->chip == CHIP_BUSLOGIC_VLB) ? 1 : 0; @@ -547,10 +550,10 @@ buslogic_param_len(void *p) static void -BuslogicSCSIBIOSDMATransfer(ESCMD *ESCSICmd, uint8_t TargetID, uint8_t LUN, int dir) +BuslogicSCSIBIOSDMATransfer(ESCMD *ESCSICmd, uint8_t TargetID, int dir) { uint32_t DataPointer = ESCSICmd->DataPointer; - uint32_t DataLength = ESCSICmd->DataLength; + int DataLength = ESCSICmd->DataLength; uint32_t Address; uint32_t TransferLength; @@ -564,16 +567,16 @@ BuslogicSCSIBIOSDMATransfer(ESCMD *ESCSICmd, uint8_t TargetID, uint8_t LUN, int /* If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without checking its length, so do this procedure for both read/write commands. */ - if ((DataLength > 0) && (SCSIDevices[TargetID][LUN].BufferLength > 0)) { + if ((DataLength > 0) && (SCSIDevices[TargetID].BufferLength > 0)) { Address = DataPointer; - TransferLength = MIN(DataLength, SCSIDevices[TargetID][LUN].BufferLength); + TransferLength = MIN(DataLength, SCSIDevices[TargetID].BufferLength); if (dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_OUT) || (ESCSICmd->DataDirection == 0x00))) { buslogic_log("BusLogic BIOS DMA: Reading %i bytes from %08X\n", TransferLength, Address); - DMAPageRead(Address, (uint8_t *)SCSIDevices[TargetID][LUN].CmdBuffer, TransferLength); + DMAPageRead(Address, (uint8_t *)SCSIDevices[TargetID].CmdBuffer, TransferLength); } else if (!dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_IN) || (ESCSICmd->DataDirection == 0x00))) { buslogic_log("BusLogic BIOS DMA: Writing %i bytes at %08X\n", TransferLength, Address); - DMAPageWrite(Address, (uint8_t *)SCSIDevices[TargetID][LUN].CmdBuffer, TransferLength); + DMAPageWrite(Address, (uint8_t *)SCSIDevices[TargetID].CmdBuffer, TransferLength); } } } @@ -599,14 +602,14 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u buslogic_log("Scanning SCSI Target ID %i\n", ESCSICmd->TargetId); - SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].Status = SCSI_STATUS_OK; + SCSIDevices[ESCSICmd->TargetId].Status = SCSI_STATUS_OK; - if (!scsi_device_present(ESCSICmd->TargetId, 0)) { - buslogic_log("SCSI Target ID %i has no device attached\n",ESCSICmd->TargetId,ESCSICmd->LogicalUnit); + if (!scsi_device_present(ESCSICmd->TargetId)) { + buslogic_log("SCSI Target ID %i has no device attached\n", ESCSICmd->TargetId); DataInBuf[2] = CCB_SELECTION_TIMEOUT; DataInBuf[3] = SCSI_STATUS_OK; } else { - buslogic_log("SCSI Target ID %i detected and working\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + buslogic_log("SCSI Target ID %i detected and working\n", ESCSICmd->TargetId); buslogic_log("Transfer Control %02X\n", ESCSICmd->DataDirection); buslogic_log("CDB Length %i\n", ESCSICmd->CDBLength); @@ -616,11 +619,11 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u } } - x54x_buf_alloc(ESCSICmd->TargetId, ESCSICmd->LogicalUnit, ESCSICmd->DataLength); + x54x_buf_alloc(ESCSICmd->TargetId, ESCSICmd->DataLength); - target_cdb_len = scsi_device_cdb_length(ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + target_cdb_len = 12; - if (!scsi_device_valid(ESCSICmd->TargetId, ESCSICmd->LogicalUnit)) fatal("SCSI target on %02i:%02i has disappeared\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + if (!scsi_device_valid(ESCSICmd->TargetId)) fatal("SCSI target on ID %02i has disappeared\n", ESCSICmd->TargetId); buslogic_log("SCSI target command being executed on: SCSI ID %i, SCSI LUN %i, Target %i\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit, target_id); @@ -636,26 +639,26 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u memcpy(temp_cdb, ESCSICmd->CDB, target_cdb_len); } - SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].BufferLength = ESCSICmd->DataLength; - scsi_device_command_phase0(ESCSICmd->TargetId, ESCSICmd->LogicalUnit, ESCSICmd->CDBLength, temp_cdb); + SCSIDevices[ESCSICmd->TargetId].BufferLength = ESCSICmd->DataLength; + scsi_device_command_phase0(ESCSICmd->TargetId, temp_cdb); - phase = SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].Phase; + phase = SCSIDevices[ESCSICmd->TargetId].Phase; if (phase != SCSI_PHASE_STATUS) { if (phase == SCSI_PHASE_DATA_IN) - scsi_device_command_phase1(ESCSICmd->TargetId, ESCSICmd->LogicalUnit); - BuslogicSCSIBIOSDMATransfer(ESCSICmd, ESCSICmd->TargetId, ESCSICmd->LogicalUnit, (phase == SCSI_PHASE_DATA_OUT)); + scsi_device_command_phase1(ESCSICmd->TargetId); + BuslogicSCSIBIOSDMATransfer(ESCSICmd, ESCSICmd->TargetId, (phase == SCSI_PHASE_DATA_OUT)); if (phase == SCSI_PHASE_DATA_OUT) - scsi_device_command_phase1(ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + scsi_device_command_phase1(ESCSICmd->TargetId); } - x54x_buf_free(ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + x54x_buf_free(ESCSICmd->TargetId); buslogic_log("BIOS Request complete\n"); - if (SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].Status == SCSI_STATUS_OK) { + if (SCSIDevices[ESCSICmd->TargetId].Status == SCSI_STATUS_OK) { DataInBuf[2] = CCB_COMPLETE; DataInBuf[3] = SCSI_STATUS_OK; - } else if (SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].Status == SCSI_STATUS_CHECK_CONDITION) { + } else if (SCSIDevices[ESCSICmd->TargetId].Status == SCSI_STATUS_CHECK_CONDITION) { DataInBuf[2] = CCB_COMPLETE; DataInBuf[3] = SCSI_STATUS_CHECK_CONDITION; } @@ -676,7 +679,6 @@ buslogic_cmds(void *p) uint16_t TargetsPresentMask = 0; uint32_t Offset; int i = 0; - int j = 0; MailboxInitExtended_t *MailboxInitE; ReplyInquireExtendedSetupInformation *ReplyIESI; BuslogicPCIInformation_t *ReplyPI; @@ -696,16 +698,14 @@ buslogic_cmds(void *p) memset(dev->DataBuf, 0, 8); for (i = 8; i < 15; i++) { dev->DataBuf[i-8] = 0; - for (j=0; j<8; j++) { - if (scsi_device_present(i, j) && (i != buslogic_get_host_id(dev))) - dev->DataBuf[i-8] |= (1<DataBuf[i-8] |= 1; } dev->DataReplyLeft = 8; break; case 0x24: for (i=0; i<15; i++) { - if (scsi_device_present(i, 0) && (i != buslogic_get_host_id(dev))) + if (scsi_device_present(i) && (i != buslogic_get_host_id(dev))) TargetsPresentMask |= (1 << i); } dev->DataBuf[0] = TargetsPresentMask & 0xFF; @@ -997,6 +997,9 @@ buslogic_cmds(void *p) dev->DataReply = 0; break; + case 0xFB: + dev->DataReplyLeft = dev->CmdBuf[2]; + break; default: dev->DataReplyLeft = 0; dev->Status |= STAT_INVCMD; @@ -1383,6 +1386,7 @@ buslogic_mca_write(int port, uint8_t val, void *priv) * pos[2]=000xxxxx = 0 */ dev->HostID = (dev->pos_regs[4] >> 5) & 0x07; + HALR->structured.autoSCSIData.uSCSIId = dev->HostID; /* * SYNC mode is pos[2]=xxxxxx1x. @@ -1402,6 +1406,45 @@ buslogic_mca_write(int port, uint8_t val, void *priv) HALR->structured.autoSCSIData.uBIOSConfiguration &= ~4; HALR->structured.autoSCSIData.uBIOSConfiguration |= (dev->pos_regs[4] & 8) ? 4 : 0; + switch(dev->DmaChannel) { + case 5: + HALR->structured.autoSCSIData.uDMAChannel = 1; + break; + case 6: + HALR->structured.autoSCSIData.uDMAChannel = 2; + break; + case 7: + HALR->structured.autoSCSIData.uDMAChannel = 3; + break; + default: + HALR->structured.autoSCSIData.uDMAChannel = 0; + break; + } + + switch(dev->Irq) { + case 9: + HALR->structured.autoSCSIData.uIrqChannel = 1; + break; + case 10: + HALR->structured.autoSCSIData.uIrqChannel = 2; + break; + case 11: + HALR->structured.autoSCSIData.uIrqChannel = 3; + break; + case 12: + HALR->structured.autoSCSIData.uIrqChannel = 4; + break; + case 14: + HALR->structured.autoSCSIData.uIrqChannel = 5; + break; + case 15: + HALR->structured.autoSCSIData.uIrqChannel = 6; + break; + default: + HALR->structured.autoSCSIData.uIrqChannel = 0; + break; + } + /* * The PS/2 Model 80 BIOS always enables a card if it finds one, * even if no resources were assigned yet (because we only added @@ -1426,8 +1469,8 @@ buslogic_mca_write(int port, uint8_t val, void *priv) } /* Say hello. */ - pclog("BT-640A: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X, HOST ID %i\n", - dev->Base, dev->Irq, dev->DmaChannel, bl->bios_addr, dev->HostID); + buslogic_log("BT-640A: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X, HOST ID %i\n", + dev->Base, dev->Irq, dev->DmaChannel, bl->bios_addr, dev->HostID); } } @@ -1583,6 +1626,7 @@ buslogic_init(const device_t *info) dev->cdrom_boot = 1; dev->bit32 = 1; dev->ha_bps = 20000000.0; /* ultra SCSI */ + dev->max_id = 15; /* wide SCSI */ break; } @@ -1683,7 +1727,7 @@ static const device_config_t BT_ISA_Config[] = { "0x134", 0x134 }, { - "" + "", 0 } }, }, @@ -1709,7 +1753,7 @@ static const device_config_t BT_ISA_Config[] = { "IRQ 15", 15 }, { - "" + "", 0 } }, }, @@ -1726,7 +1770,7 @@ static const device_config_t BT_ISA_Config[] = { "DMA 7", 7 }, { - "" + "", 0 } }, }, @@ -1746,7 +1790,7 @@ static const device_config_t BT_ISA_Config[] = { "D800H", 0xd8000 }, { - "" + "", 0 } }, }, @@ -1771,7 +1815,7 @@ const device_t buslogic_device = { DEVICE_ISA | DEVICE_AT, CHIP_BUSLOGIC_ISA_542, buslogic_init, x54x_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, BT_ISA_Config }; @@ -1780,7 +1824,7 @@ const device_t buslogic_545s_device = { DEVICE_ISA | DEVICE_AT, CHIP_BUSLOGIC_ISA, buslogic_init, x54x_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, BT_ISA_Config }; @@ -1789,16 +1833,16 @@ const device_t buslogic_640a_device = { DEVICE_MCA, CHIP_BUSLOGIC_MCA, buslogic_init, x54x_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; const device_t buslogic_445s_device = { - "Buslogic BT-445S ISA", + "Buslogic BT-445S VLB", DEVICE_VLB, CHIP_BUSLOGIC_VLB, buslogic_init, x54x_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, BT_ISA_Config }; @@ -1807,6 +1851,6 @@ const device_t buslogic_pci_device = { DEVICE_PCI, CHIP_BUSLOGIC_PCI, buslogic_init, x54x_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, BT958D_Config }; diff --git a/src/scsi/scsi_device.c b/src/scsi/scsi_device.c index aed66bf6c..f5567cb74 100644 --- a/src/scsi/scsi_device.c +++ b/src/scsi/scsi_device.c @@ -8,7 +8,7 @@ * * The generic SCSI device command handler. * - * Version: @(#)scsi_device.c 1.0.15 2018/03/16 + * Version: @(#)scsi_device.c 1.0.17 2018/06/02 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -22,122 +22,87 @@ #include #include "../86box.h" #include "../device.h" -#include "../cdrom/cdrom.h" #include "../disk/hdd.h" -#include "../disk/zip.h" #include "scsi.h" +#include "scsi_device.h" +#include "../cdrom/cdrom.h" +#include "../disk/zip.h" #include "scsi_disk.h" -static uint8_t scsi_null_device_sense[14] = { 0x70,0,SENSE_ILLEGAL_REQUEST,0,0,0,0,0,0,0,0,0,ASC_INV_LUN,0 }; +uint8_t scsi_null_device_sense[18] = { 0x70,0,SENSE_ILLEGAL_REQUEST,0,0,0,0,0,0,0,0,0,ASC_INV_LUN,0,0,0,0,0 }; -static uint8_t scsi_device_target_command(int lun_type, uint8_t id, uint8_t *cdb) +static uint8_t +scsi_device_target_command(int lun_type, uint8_t id, uint8_t *cdb) { - if (lun_type == SCSI_DISK) - { - scsi_hd_command(id, cdb); - return scsi_hd_err_stat_to_scsi(id); - } - else if (lun_type == SCSI_CDROM) - { - cdrom_command(id, cdb); - return cdrom_CDROM_PHASE_to_scsi(id); - } - else if (lun_type == SCSI_ZIP) - { - zip_command(id, cdb); - return zip_ZIP_PHASE_to_scsi(id); - } - else - { + switch(lun_type) { + case SCSI_DISK: + scsi_disk_command(scsi_disk[id], cdb); + return scsi_disk_err_stat_to_scsi(scsi_disk[id]); + case SCSI_CDROM: + cdrom_command(cdrom[id], cdb); + return cdrom_CDROM_PHASE_to_scsi(cdrom[id]); + case SCSI_ZIP: + zip_command(zip[id], cdb); + return zip_ZIP_PHASE_to_scsi(zip[id]); + default: return SCSI_STATUS_CHECK_CONDITION; - } + } } static void scsi_device_target_phase_callback(int lun_type, uint8_t id) { - if (lun_type == SCSI_DISK) - { - scsi_hd_callback(id); - } - else if (lun_type == SCSI_CDROM) - { - cdrom_phase_callback(id); - } - else if (lun_type == SCSI_ZIP) - { - zip_phase_callback(id); - } - else - { - return; - } + switch(lun_type) { + case SCSI_DISK: + scsi_disk_callback(scsi_disk[id]); + break; + case SCSI_CDROM: + cdrom_phase_callback(cdrom[id]); + break; + case SCSI_ZIP: + zip_phase_callback(zip[id]); + break; + } + return; } static int scsi_device_target_err_stat_to_scsi(int lun_type, uint8_t id) { - if (lun_type == SCSI_DISK) - { - return scsi_hd_err_stat_to_scsi(id); - } - else if (lun_type == SCSI_CDROM) - { - return cdrom_CDROM_PHASE_to_scsi(id); - } - else if (lun_type == SCSI_ZIP) - { - return zip_ZIP_PHASE_to_scsi(id); - } - else - { + switch(lun_type) { + case SCSI_DISK: + return scsi_disk_err_stat_to_scsi(scsi_disk[id]); + case SCSI_CDROM: + return cdrom_CDROM_PHASE_to_scsi(cdrom[id]); + case SCSI_ZIP: + return zip_ZIP_PHASE_to_scsi(zip[id]); + default: return SCSI_STATUS_CHECK_CONDITION; - } + } } -static void scsi_device_target_save_cdb_byte(int lun_type, uint8_t id, uint8_t cdb_byte) +int64_t scsi_device_get_callback(uint8_t scsi_id) { - if (lun_type == SCSI_DISK) - { - shdc[id].request_length = cdb_byte; - } - else if (lun_type == SCSI_CDROM) - { - cdrom[id]->request_length = cdb_byte; - } - else if (lun_type == SCSI_ZIP) - { - zip[id].request_length = cdb_byte; - } - else - { - return; - } -} - - -int64_t scsi_device_get_callback(uint8_t scsi_id, uint8_t scsi_lun) -{ - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; + uint8_t lun_type = SCSIDevices[scsi_id].LunType; uint8_t id = 0; switch (lun_type) { case SCSI_DISK: - id = scsi_hard_disks[scsi_id][scsi_lun]; - return shdc[id].callback; + id = scsi_disks[scsi_id]; + return scsi_disk[id]->callback; break; case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id][scsi_lun]; + id = scsi_cdrom_drives[scsi_id]; return cdrom[id]->callback; break; case SCSI_ZIP: - id = scsi_zip_drives[scsi_id][scsi_lun]; - return zip[id].callback; + id = scsi_zip_drives[scsi_id]; + return zip[id]->callback; break; default: return -1LL; @@ -146,25 +111,25 @@ int64_t scsi_device_get_callback(uint8_t scsi_id, uint8_t scsi_lun) } -uint8_t *scsi_device_sense(uint8_t scsi_id, uint8_t scsi_lun) +uint8_t *scsi_device_sense(uint8_t scsi_id) { - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; + uint8_t lun_type = SCSIDevices[scsi_id].LunType; uint8_t id = 0; switch (lun_type) { case SCSI_DISK: - id = scsi_hard_disks[scsi_id][scsi_lun]; - return shdc[id].sense; + id = scsi_disks[scsi_id]; + return scsi_disk[id]->sense; break; case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id][scsi_lun]; + id = scsi_cdrom_drives[scsi_id]; return cdrom[id]->sense; break; case SCSI_ZIP: - id = scsi_zip_drives[scsi_id][scsi_lun]; - return zip[id].sense; + id = scsi_zip_drives[scsi_id]; + return zip[id]->sense; break; default: return scsi_null_device_sense; @@ -173,25 +138,25 @@ uint8_t *scsi_device_sense(uint8_t scsi_id, uint8_t scsi_lun) } -void scsi_device_request_sense(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *buffer, uint8_t alloc_length) +void scsi_device_request_sense(uint8_t scsi_id, uint8_t *buffer, uint8_t alloc_length) { - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; + uint8_t lun_type = SCSIDevices[scsi_id].LunType; uint8_t id = 0; switch (lun_type) { case SCSI_DISK: - id = scsi_hard_disks[scsi_id][scsi_lun]; - scsi_hd_request_sense_for_scsi(id, buffer, alloc_length); + id = scsi_disks[scsi_id]; + scsi_disk_request_sense_for_scsi(scsi_disk[id], buffer, alloc_length); break; case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id][scsi_lun]; - cdrom_request_sense_for_scsi(id, buffer, alloc_length); + id = scsi_cdrom_drives[scsi_id]; + cdrom_request_sense_for_scsi(cdrom[id], buffer, alloc_length); break; case SCSI_ZIP: - id = scsi_zip_drives[scsi_id][scsi_lun]; - zip_request_sense_for_scsi(id, buffer, alloc_length); + id = scsi_zip_drives[scsi_id]; + zip_request_sense_for_scsi(zip[id], buffer, alloc_length); break; default: memcpy(buffer, scsi_null_device_sense, alloc_length); @@ -200,18 +165,38 @@ void scsi_device_request_sense(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *buffe } -void scsi_device_type_data(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *type, uint8_t *rmb) +void scsi_device_reset(uint8_t scsi_id) { - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; + uint8_t lun_type = SCSIDevices[scsi_id].LunType; uint8_t id = 0; switch (lun_type) { case SCSI_DISK: - id = scsi_hard_disks[scsi_id][scsi_lun]; - *type = 0x00; - *rmb = (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? 0x80 : 0x00; + id = scsi_disks[scsi_id]; + scsi_disk_reset(scsi_disk[id]); + break; + case SCSI_CDROM: + id = scsi_cdrom_drives[scsi_id]; + cdrom_reset(cdrom[id]); + break; + case SCSI_ZIP: + id = scsi_zip_drives[scsi_id]; + zip_reset(zip[id]); + break; + } +} + + +void scsi_device_type_data(uint8_t scsi_id, uint8_t *type, uint8_t *rmb) +{ + uint8_t lun_type = SCSIDevices[scsi_id].LunType; + + switch (lun_type) + { + case SCSI_DISK: + *type = *rmb = 0x00; break; case SCSI_CDROM: *type = 0x05; @@ -222,38 +207,38 @@ void scsi_device_type_data(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *type, uin *rmb = 0x80; break; default: - *type = *rmb = 0xFF; + *type = *rmb = 0xff; break; } } -int scsi_device_read_capacity(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *cdb, uint8_t *buffer, uint32_t *len) +int scsi_device_read_capacity(uint8_t scsi_id, uint8_t *cdb, uint8_t *buffer, uint32_t *len) { - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; + uint8_t lun_type = SCSIDevices[scsi_id].LunType; uint8_t id = 0; switch (lun_type) { case SCSI_DISK: - id = scsi_hard_disks[scsi_id][scsi_lun]; - return scsi_hd_read_capacity(id, cdb, buffer, len); + id = scsi_disks[scsi_id]; + return scsi_disk_read_capacity(scsi_disk[id], cdb, buffer, len); case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id][scsi_lun]; - return cdrom_read_capacity(id, cdb, buffer, len); + id = scsi_cdrom_drives[scsi_id]; + return cdrom_read_capacity(cdrom[id], cdb, buffer, len); case SCSI_ZIP: - id = scsi_zip_drives[scsi_id][scsi_lun]; - return zip_read_capacity(id, cdb, buffer, len); + id = scsi_zip_drives[scsi_id]; + return zip_read_capacity(zip[id], cdb, buffer, len); default: return 0; } } -int scsi_device_present(uint8_t scsi_id, uint8_t scsi_lun) +int scsi_device_present(uint8_t scsi_id) { - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; + uint8_t lun_type = SCSIDevices[scsi_id].LunType; switch (lun_type) { @@ -265,22 +250,22 @@ int scsi_device_present(uint8_t scsi_id, uint8_t scsi_lun) } -int scsi_device_valid(uint8_t scsi_id, uint8_t scsi_lun) +int scsi_device_valid(uint8_t scsi_id) { - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; + uint8_t lun_type = SCSIDevices[scsi_id].LunType; uint8_t id = 0; switch (lun_type) { case SCSI_DISK: - id = scsi_hard_disks[scsi_id][scsi_lun]; + id = scsi_disks[scsi_id]; break; case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id][scsi_lun]; + id = scsi_cdrom_drives[scsi_id]; break; case SCSI_ZIP: - id = scsi_zip_drives[scsi_id][scsi_lun]; + id = scsi_zip_drives[scsi_id]; break; default: id = 0; @@ -291,106 +276,74 @@ int scsi_device_valid(uint8_t scsi_id, uint8_t scsi_lun) } -int scsi_device_cdb_length(uint8_t scsi_id, uint8_t scsi_lun) +int scsi_device_cdb_length(uint8_t scsi_id) { - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; - - uint8_t id = 0; - - switch (lun_type) - { - case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id][scsi_lun]; - return cdrom[id]->cdb_len; - case SCSI_ZIP: - id = scsi_zip_drives[scsi_id][scsi_lun]; - return zip[id].cdb_len; - default: - return 12; - } + /* Right now, it's 12 for all devices. */ + return 12; } -void scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len, uint8_t *cdb) +void scsi_device_command_phase0(uint8_t scsi_id, uint8_t *cdb) { - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; - uint8_t id = 0; + uint8_t lun_type = SCSIDevices[scsi_id].LunType; - switch (lun_type) - { + switch (lun_type) { case SCSI_DISK: - id = scsi_hard_disks[scsi_id][scsi_lun]; + id = scsi_disks[scsi_id]; break; case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id][scsi_lun]; + id = scsi_cdrom_drives[scsi_id]; break; case SCSI_ZIP: - id = scsi_zip_drives[scsi_id][scsi_lun]; + id = scsi_zip_drives[scsi_id]; break; default: id = 0; - SCSIDevices[scsi_id][scsi_lun].Phase = SCSI_PHASE_STATUS; - SCSIDevices[scsi_id][scsi_lun].Status = SCSI_STATUS_CHECK_CONDITION; + SCSIDevices[scsi_id].Phase = SCSI_PHASE_STATUS; + SCSIDevices[scsi_id].Status = SCSI_STATUS_CHECK_CONDITION; return; } - /* - * Since that field in the target struct is never used when - * the bus type is SCSI, let's use it for this scope. - */ - scsi_device_target_save_cdb_byte(lun_type, id, cdb[1]); - - if (cdb_len != 12) { - /* - * Make sure the LUN field of the temporary CDB is always 0, - * otherwise Daemon Tools drives will misbehave when a command - * is passed through to them. - */ - cdb[1] &= 0x1f; - } - /* Finally, execute the SCSI command immediately and get the transfer length. */ - SCSIDevices[scsi_id][scsi_lun].Phase = SCSI_PHASE_COMMAND; - SCSIDevices[scsi_id][scsi_lun].Status = scsi_device_target_command(lun_type, id, cdb); + SCSIDevices[scsi_id].Phase = SCSI_PHASE_COMMAND; + SCSIDevices[scsi_id].Status = scsi_device_target_command(lun_type, id, cdb); - if (SCSIDevices[scsi_id][scsi_lun].Phase == SCSI_PHASE_STATUS) { + if (SCSIDevices[scsi_id].Phase == SCSI_PHASE_STATUS) { /* Command completed (either OK or error) - call the phase callback to complete the command. */ scsi_device_target_phase_callback(lun_type, id); } /* If the phase is DATA IN or DATA OUT, finish this here. */ } -void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun) +void scsi_device_command_phase1(uint8_t scsi_id) { - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; + uint8_t id = 0; + uint8_t lun_type = SCSIDevices[scsi_id].LunType; - uint8_t id = 0; + switch (lun_type) { + case SCSI_DISK: + id = scsi_disks[scsi_id]; + break; + case SCSI_CDROM: + id = scsi_cdrom_drives[scsi_id]; + break; + case SCSI_ZIP: + id = scsi_zip_drives[scsi_id]; + break; + default: + id = 0; + return; + } - switch (lun_type) - { - case SCSI_DISK: - id = scsi_hard_disks[scsi_id][scsi_lun]; - break; - case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id][scsi_lun]; - break; - case SCSI_ZIP: - id = scsi_zip_drives[scsi_id][scsi_lun]; - break; - default: - id = 0; - return; - } - - /* Call the second phase. */ - scsi_device_target_phase_callback(lun_type, id); - SCSIDevices[scsi_id][scsi_lun].Status = scsi_device_target_err_stat_to_scsi(lun_type, id); - /* Command second phase complete - call the callback to complete the command. */ - scsi_device_target_phase_callback(lun_type, id); + /* Call the second phase. */ + scsi_device_target_phase_callback(lun_type, id); + SCSIDevices[scsi_id].Status = scsi_device_target_err_stat_to_scsi(lun_type, id); + /* Command second phase complete - call the callback to complete the command. */ + scsi_device_target_phase_callback(lun_type, id); } -int32_t *scsi_device_get_buf_len(uint8_t scsi_id, uint8_t scsi_lun) +int32_t *scsi_device_get_buf_len(uint8_t scsi_id) { - return &SCSIDevices[scsi_id][scsi_lun].BufferLength; + return &SCSIDevices[scsi_id].BufferLength; } diff --git a/src/scsi/scsi_device.h b/src/scsi/scsi_device.h index 9d7267528..d0da9a19b 100644 --- a/src/scsi/scsi_device.h +++ b/src/scsi/scsi_device.h @@ -8,7 +8,7 @@ * * Definitions for the generic SCSI device command handler. * - * Version: @(#)scsi_device.h 1.0.6 2018/03/07 + * Version: @(#)scsi_device.h 1.0.8 2018/06/12 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -32,25 +32,21 @@ typedef struct int new_req_delay; } scsi_bus_t; -extern uint8_t *scsi_device_sense(uint8_t id, uint8_t lun); -extern void scsi_device_type_data(uint8_t id, uint8_t lun, - uint8_t *type, uint8_t *rmb); -extern int64_t scsi_device_get_callback(uint8_t scsi_id, uint8_t scsi_lun); -extern void scsi_device_request_sense(uint8_t scsi_id, uint8_t scsi_lun, - uint8_t *buffer, +extern uint8_t *scsi_device_sense(uint8_t id); +extern void scsi_device_type_data(uint8_t id, uint8_t *type, uint8_t *rmb); +extern int64_t scsi_device_get_callback(uint8_t scsi_id); +extern void scsi_device_request_sense(uint8_t scsi_id, uint8_t *buffer, uint8_t alloc_length); -extern int scsi_device_read_capacity(uint8_t id, uint8_t lun, - uint8_t *cdb, uint8_t *buffer, - uint32_t *len); -extern int scsi_device_present(uint8_t id, uint8_t lun); -extern int scsi_device_valid(uint8_t id, uint8_t lun); -extern int scsi_device_cdb_length(uint8_t id, uint8_t lun); -extern void scsi_device_command(uint8_t id, uint8_t lun, int cdb_len, - uint8_t *cdb); -extern void scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, - int cdb_len, uint8_t *cdb); -extern void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun); -extern int32_t *scsi_device_get_buf_len(uint8_t scsi_id, uint8_t scsi_lun); +extern void scsi_device_reset(uint8_t scsi_id); +extern int scsi_device_read_capacity(uint8_t id, uint8_t *cdb, + uint8_t *buffer, uint32_t *len); +extern int scsi_device_present(uint8_t id); +extern int scsi_device_valid(uint8_t id); +extern int scsi_device_cdb_length(uint8_t id); +extern void scsi_device_command(uint8_t id, int cdb_len, uint8_t *cdb); +extern void scsi_device_command_phase0(uint8_t scsi_id, uint8_t *cdb); +extern void scsi_device_command_phase1(uint8_t scsi_id); +extern int32_t *scsi_device_get_buf_len(uint8_t scsi_id); extern int scsi_bus_update(scsi_bus_t *bus, int bus_assert); extern int scsi_bus_read(scsi_bus_t *bus); diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index b4121ed36..22d7f117b 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -4,9 +4,9 @@ * PC systems and compatibles from 1981 through fairly recent * system designs based on the PCI bus. * - * Emulation of SCSI fixed and removable disks. + * Emulation of SCSI fixed disks. * - * Version: @(#)scsi_disk.c 1.0.18 2018/03/18 + * Version: @(#)scsi_disk.c 1.0.20 2018/05/28 * * Author: Miran Grca, * @@ -24,13 +24,13 @@ #include "../device.h" #include "../nvr.h" #include "../piix.h" -#include "../cdrom/cdrom.h" #include "../disk/hdd.h" #include "../disk/hdc.h" #include "../disk/hdc_ide.h" #include "../plat.h" #include "../ui.h" #include "scsi.h" +#include "../cdrom/cdrom.h" #include "scsi_disk.h" @@ -48,37 +48,22 @@ #define MAX_BLOCKS_AT_ONCE 340 -#define scsi_hd_sense_error shdc[id].sense[0] -#define scsi_hd_sense_key shdc[id].sense[2] -#define scsi_hd_asc shdc[id].sense[12] -#define scsi_hd_ascq shdc[id].sense[13] +#define scsi_disk_sense_error dev->sense[0] +#define scsi_disk_sense_key dev->sense[2] +#define scsi_disk_asc dev->sense[12] +#define scsi_disk_ascq dev->sense[13] -scsi_hard_disk_t shdc[HDD_NUM]; -FILE *shdf[HDD_NUM]; +scsi_disk_t *scsi_disk[HDD_NUM]; -uint8_t scsi_hard_disks[16][8] = { - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } +uint8_t scsi_disks[16] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ -const uint8_t scsi_hd_command_flags[0x100] = { +const uint8_t scsi_disk_command_flags[0x100] = { IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ 0, @@ -88,7 +73,8 @@ const uint8_t scsi_hd_command_flags[0x100] = { IMPLEMENTED | CHECK_READY, /* 0x08 */ 0, IMPLEMENTED | CHECK_READY, /* 0x0A */ - 0, 0, 0, 0, 0, 0, 0, + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ + 0, 0, 0, 0, 0, 0, IMPLEMENTED | ALLOW_UA, /* 0x12 */ IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ 0, @@ -96,9 +82,8 @@ const uint8_t scsi_hd_command_flags[0x100] = { IMPLEMENTED | SCSI_ONLY, /* 0x16 */ IMPLEMENTED | SCSI_ONLY, /* 0x17 */ 0, 0, - IMPLEMENTED, - IMPLEMENTED | CHECK_READY, /* 0x1B */ - 0, + IMPLEMENTED, /* 0x1A */ + 0, 0, IMPLEMENTED, /* 0x1D */ IMPLEMENTED | CHECK_READY, /* 0x1E */ 0, 0, 0, 0, 0, 0, @@ -107,7 +92,8 @@ const uint8_t scsi_hd_command_flags[0x100] = { IMPLEMENTED | CHECK_READY, /* 0x28 */ 0, IMPLEMENTED | CHECK_READY, /* 0x2A */ - 0, 0, 0, + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ + 0, 0, IMPLEMENTED | CHECK_READY, /* 0x2E */ IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -140,36 +126,34 @@ const uint8_t scsi_hd_command_flags[0x100] = { }; -uint64_t scsi_hd_mode_sense_page_flags = (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F); +uint64_t scsi_disk_mode_sense_page_flags = (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F); /* This should be done in a better way but for time being, it's been done this way so it's not as huge and more readable. */ -static const mode_sense_pages_t scsi_hd_mode_sense_pages_default = +static const mode_sense_pages_t scsi_disk_mode_sense_pages_default = { { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } } }; -static const mode_sense_pages_t scsi_hd_mode_sense_pages_changeable = +static const mode_sense_pages_t scsi_disk_mode_sense_pages_changeable = { { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } } }; -static mode_sense_pages_t scsi_hd_mode_sense_pages_saved[HDD_NUM]; - #ifdef ENABLE_SCSI_DISK_LOG -int scsi_hd_do_log = ENABLE_SCSI_DISK_LOG; +int scsi_disk_do_log = ENABLE_SCSI_DISK_LOG; #endif static void -scsi_hd_log(const char *fmt, ...) +scsi_disk_log(const char *fmt, ...) { #ifdef ENABLE_SCSI_DISK_LOG va_list ap; - if (scsi_hd_do_log) { + if (scsi_disk_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); @@ -179,1523 +163,1151 @@ scsi_hd_log(const char *fmt, ...) /* Translates ATAPI status (ERR_STAT flag) to SCSI status. */ -int scsi_hd_err_stat_to_scsi(uint8_t id) +int +scsi_disk_err_stat_to_scsi(scsi_disk_t *dev) { - if (shdc[id].status & ERR_STAT) - { - return SCSI_STATUS_CHECK_CONDITION; - } - else - { - return SCSI_STATUS_OK; - } - + if (dev->status & ERR_STAT) + return SCSI_STATUS_CHECK_CONDITION; + else return SCSI_STATUS_OK; } -int find_hdd_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun) +int +find_hdd_for_scsi_id(uint8_t scsi_id) { - uint8_t i = 0; + uint8_t i = 0; - for (i = 0; i < HDD_NUM; i++) - { - if ((wcslen(hdd[i].fn) == 0) && (hdd[i].bus != HDD_BUS_SCSI_REMOVABLE)) - { - continue; - } - if (((hdd[i].spt == 0) || (hdd[i].hpc == 0) || (hdd[i].tracks == 0)) && (hdd[i].bus != HDD_BUS_SCSI_REMOVABLE)) - { - continue; - } - if (((hdd[i].bus == HDD_BUS_SCSI) || (hdd[i].bus == HDD_BUS_SCSI_REMOVABLE)) && (hdd[i].scsi_id == scsi_id) && (hdd[i].scsi_lun == scsi_lun)) - { - return i; - } - } - return 0xff; + for (i = 0; i < HDD_NUM; i++) { + if (wcslen(hdd[i].fn) == 0) + continue; + if ((hdd[i].spt == 0) || (hdd[i].hpc == 0) || (hdd[i].tracks == 0)) + continue; + if ((hdd[i].bus == HDD_BUS_SCSI) && (hdd[i].scsi_id == scsi_id)) + return i; + } + return 0xff; } -void scsi_disk_insert(uint8_t id) +void +scsi_loadhd(int scsi_id, int id) { - shdc[id].unit_attention = (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0; + if (! hdd_image_load(id)) + scsi_disks[scsi_id] = 0xff; } -void scsi_loadhd(int scsi_id, int scsi_lun, int id) +void +build_scsi_disk_map(void) { - if (! hdd_image_load(id)) { - if (hdd[id].bus != HDD_BUS_SCSI_REMOVABLE) - { - scsi_hard_disks[scsi_id][scsi_lun] = 0xff; - } - } - else - { - scsi_disk_insert(id); + uint8_t i = 0; + + memset(scsi_disks, 0xff, 16); + + for (i = 0; i < 16; i++) { + scsi_disks[i] = find_hdd_for_scsi_id(i); + if (scsi_disks[i] != 0xff) { + if (wcslen(hdd[scsi_disks[i]].fn) > 0) + scsi_loadhd(i, scsi_disks[i]); } + } } -void scsi_reloadhd(int id) +void +scsi_disk_mode_sense_load(scsi_disk_t *dev) { - int ret = 0; - - if (wcslen(hdd[id].prev_fn) == 0) - { - return; - } - else - { - wcscpy(hdd[id].fn, hdd[id].prev_fn); - memset(hdd[id].prev_fn, 0, sizeof(hdd[id].prev_fn)); - } - - ret = hdd_image_load(id); - - if (ret) - { - scsi_disk_insert(id); + FILE *f; + wchar_t file_name[512]; + int i; + memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); + for (i = 0; i < 0x3f; i++) { + if (scsi_disk_mode_sense_pages_default.pages[i][1] != 0) { + memcpy(dev->ms_pages_saved.pages[i], scsi_disk_mode_sense_pages_default.pages[i], + scsi_disk_mode_sense_pages_default.pages[i][1] + 2); } + } + swprintf(file_name, 512, L"scsi_disk_%02i_mode_sense.bin", dev->id); + memset(file_name, 0, 512 * sizeof(wchar_t)); + f = plat_fopen(nvr_path(file_name), L"rb"); + if (f) { + fread(dev->ms_pages_saved.pages[0x30], 1, 0x18, f); + fclose(f); + } } -void scsi_unloadhd(int scsi_id, int scsi_lun, int id) +void +scsi_disk_mode_sense_save(scsi_disk_t *dev) { - hdd_image_unload(id, 1); + FILE *f; + wchar_t file_name[512]; + memset(file_name, 0, 512 * sizeof(wchar_t)); + swprintf(file_name, 512, L"scsi_disk_%02i_mode_sense.bin", dev->id); + f = plat_fopen(nvr_path(file_name), L"wb"); + if (f) { + fwrite(dev->ms_pages_saved.pages[0x30], 1, 0x18, f); + fclose(f); + } } -void build_scsi_hd_map(void) +int +scsi_disk_read_capacity(scsi_disk_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len) { - uint8_t i = 0; - uint8_t j = 0; + int size = 0; - for (i = 0; i < 16; i++) - { - memset(scsi_hard_disks[i], 0xff, 8); - } + size = hdd_image_get_last_sector(dev->id); + memset(buffer, 0, 8); + buffer[0] = (size >> 24) & 0xff; + buffer[1] = (size >> 16) & 0xff; + buffer[2] = (size >> 8) & 0xff; + buffer[3] = size & 0xff; + buffer[6] = 2; /* 512 = 0x0200 */ + *len = 8; - for (i = 0; i < 16; i++) - { - for (j = 0; j < 8; j++) - { - scsi_hard_disks[i][j] = find_hdd_for_scsi_id(i, j); - if (scsi_hard_disks[i][j] != 0xff) - { - memset(&(shdc[scsi_hard_disks[i][j]]), 0, sizeof(shdc[scsi_hard_disks[i][j]])); - if (wcslen(hdd[scsi_hard_disks[i][j]].fn) > 0) - { - scsi_loadhd(i, j, scsi_hard_disks[i][j]); - } - } - } - } -} - -void scsi_hd_mode_sense_load(uint8_t id) -{ - FILE *f; - wchar_t file_name[512]; - int i; - memset(&scsi_hd_mode_sense_pages_saved[id], 0, sizeof(mode_sense_pages_t)); - for (i = 0; i < 0x3f; i++) { - if (scsi_hd_mode_sense_pages_default.pages[i][1] != 0) - memcpy(scsi_hd_mode_sense_pages_saved[id].pages[i], scsi_hd_mode_sense_pages_default.pages[i], scsi_hd_mode_sense_pages_default.pages[i][1] + 2); - } - swprintf(file_name, 512, L"scsi_hd_%02i_mode_sense.bin", id); - memset(file_name, 0, 512 * sizeof(wchar_t)); - f = plat_fopen(nvr_path(file_name), L"rb"); - if (f) { - fread(scsi_hd_mode_sense_pages_saved[id].pages[0x30], 1, 0x18, f); - fclose(f); - } -} - -void scsi_hd_mode_sense_save(uint8_t id) -{ - FILE *f; - wchar_t file_name[512]; - memset(file_name, 0, 512 * sizeof(wchar_t)); - swprintf(file_name, 512, L"scsi_hd_%02i_mode_sense.bin", id); - f = plat_fopen(nvr_path(file_name), L"wb"); - if (f) { - fwrite(scsi_hd_mode_sense_pages_saved[id].pages[0x30], 1, 0x18, f); - fclose(f); - } -} - -int scsi_hd_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len) -{ - int size = 0; - - size = hdd_image_get_last_sector(id); - memset(buffer, 0, 8); - buffer[0] = (size >> 24) & 0xff; - buffer[1] = (size >> 16) & 0xff; - buffer[2] = (size >> 8) & 0xff; - buffer[3] = size & 0xff; - buffer[6] = 2; /* 512 = 0x0200 */ - *len = 8; - - return 1; + return 1; } /*SCSI Mode Sense 6/10*/ -uint8_t scsi_hd_mode_sense_read(uint8_t id, uint8_t page_control, uint8_t page, uint8_t pos) +uint8_t +scsi_disk_mode_sense_read(scsi_disk_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) { - switch (page_control) - { - case 0: - case 3: - return scsi_hd_mode_sense_pages_saved[id].pages[page][pos]; - break; - case 1: - return scsi_hd_mode_sense_pages_changeable.pages[page][pos]; - break; - case 2: - return scsi_hd_mode_sense_pages_default.pages[page][pos]; - break; - } + switch (page_control) { + case 0: + case 3: + return dev->ms_pages_saved.pages[page][pos]; + break; + case 1: + return scsi_disk_mode_sense_pages_changeable.pages[page][pos]; + break; + case 2: + return scsi_disk_mode_sense_pages_default.pages[page][pos]; + break; + } - return 0; + return 0; } -uint32_t scsi_hd_mode_sense(uint8_t id, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len) + +uint32_t +scsi_disk_mode_sense(scsi_disk_t *dev, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len) { - uint8_t page_control = (type >> 6) & 3; + uint8_t msplen, page_control = (type >> 6) & 3; - int i = 0; - int j = 0; + int i = 0, j = 0; + int size = 0; - uint8_t msplen; - int size = 0; + type &= 0x3f; - type &= 0x3f; + size = hdd_image_get_last_sector(dev->id); - size = hdd_image_get_last_sector(id); + if (block_descriptor_len) { + buf[pos++] = 1; /* Density code. */ + buf[pos++] = (size >> 16) & 0xff; /* Number of blocks (0 = all). */ + buf[pos++] = (size >> 8) & 0xff; + buf[pos++] = size & 0xff; + buf[pos++] = 0; /* Reserved. */ + buf[pos++] = 0; /* Block length (0x200 = 512 bytes). */ + buf[pos++] = 2; + buf[pos++] = 0; + } - if (block_descriptor_len) - { - buf[pos++] = 1; /* Density code. */ - buf[pos++] = (size >> 16) & 0xff; /* Number of blocks (0 = all). */ - buf[pos++] = (size >> 8) & 0xff; - buf[pos++] = size & 0xff; - buf[pos++] = 0; /* Reserved. */ - buf[pos++] = 0; /* Block length (0x200 = 512 bytes). */ - buf[pos++] = 2; - buf[pos++] = 0; - } - - for (i = 0; i < 0x40; i++) - { - if ((type == GPMODE_ALL_PAGES) || (type == i)) - { - if (scsi_hd_mode_sense_page_flags & (1LL << shdc[id].current_page_code)) - { - buf[pos++] = scsi_hd_mode_sense_read(id, page_control, i, 0); - msplen = scsi_hd_mode_sense_read(id, page_control, i, 1); - buf[pos++] = msplen; - scsi_hd_log("SCSI HDD %i: MODE SENSE: Page [%02X] length %i\n", id, i, msplen); - for (j = 0; j < msplen; j++) - { - buf[pos++] = scsi_hd_mode_sense_read(id, page_control, i, 2 + j); - } - } + for (i = 0; i < 0x40; i++) { + if ((type == GPMODE_ALL_PAGES) || (type == i)) { + if (scsi_disk_mode_sense_page_flags & (1LL << dev->current_page_code)) { + buf[pos++] = scsi_disk_mode_sense_read(dev, page_control, i, 0); + msplen = scsi_disk_mode_sense_read(dev, page_control, i, 1); + buf[pos++] = msplen; + scsi_disk_log("SCSI HDD %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); + for (j = 0; j < msplen; j++) + buf[pos++] = scsi_disk_mode_sense_read(dev, page_control, i, 2 + j); } } + } - return pos; + return pos; } -void scsi_hd_update_request_length(uint8_t id, int len, int block_len) + +static void +scsi_disk_command_common(scsi_disk_t *dev) { - /* For media access commands, make sure the requested DRQ length matches the block length. */ - switch (shdc[id].current_cdb[0]) - { - case 0x08: - case 0x0a: - case 0x28: - case 0x2a: - case 0xa8: - case 0xaa: - if (shdc[id].request_length < block_len) - { - shdc[id].request_length = block_len; - } - /* Make sure we respect the limit of how many blocks we can transfer at once. */ - if (shdc[id].requested_blocks > shdc[id].max_blocks_at_once) - { - shdc[id].requested_blocks = shdc[id].max_blocks_at_once; - } - shdc[id].block_total = (shdc[id].requested_blocks * block_len); - if (len > shdc[id].block_total) - { - len = shdc[id].block_total; - } - break; - default: - shdc[id].packet_len = len; - break; - } - /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ - if ((shdc[id].request_length & 1) && (shdc[id].request_length < len)) - { - shdc[id].request_length &= 0xfffe; - } - /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ - if (len <= shdc[id].request_length) - { - shdc[id].request_length = len; - } + dev->status = BUSY_STAT; + dev->phase = 1; + if (dev->packet_status == CDROM_PHASE_COMPLETE) { + scsi_disk_callback(dev); + dev->callback = 0LL; + } else + dev->callback = -1LL; /* Speed depends on SCSI controller */ +} + + +static void +scsi_disk_command_complete(scsi_disk_t *dev) +{ + dev->packet_status = CDROM_PHASE_COMPLETE; + scsi_disk_command_common(dev); +} + + +static void +scsi_disk_command_read_dma(scsi_disk_t *dev) +{ + dev->packet_status = CDROM_PHASE_DATA_IN_DMA; + scsi_disk_command_common(dev); +} + + +static void +scsi_disk_command_write_dma(scsi_disk_t *dev) +{ + dev->packet_status = CDROM_PHASE_DATA_OUT_DMA; + scsi_disk_command_common(dev); +} + + +static void +scsi_disk_data_command_finish(scsi_disk_t *dev, int len, int block_len, int alloc_len, int direction) +{ + scsi_disk_log("SCSI HD %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", dev->id, + dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length); + if (alloc_len >= 0) { + if (alloc_len < len) + len = alloc_len; + } + if (len == 0) + scsi_disk_command_complete(dev); + else { + if (direction == 0) + scsi_disk_command_read_dma(dev); + else + scsi_disk_command_write_dma(dev); + } +} + + +static void +scsi_disk_sense_clear(scsi_disk_t *dev, int command) +{ + scsi_disk_sense_key = scsi_disk_asc = scsi_disk_ascq = 0; +} + + +static void +scsi_disk_set_phase(scsi_disk_t *dev, uint8_t phase) +{ + uint8_t scsi_id = dev->drv->scsi_id; + + if (dev->drv->bus != HDD_BUS_SCSI) return; + + SCSIDevices[scsi_id].Phase = phase; } -static void scsi_hd_command_common(uint8_t id) +static void +scsi_disk_cmd_error(scsi_disk_t *dev) { - shdc[id].status = BUSY_STAT; - shdc[id].phase = 1; - shdc[id].pos = 0; - if (shdc[id].packet_status == CDROM_PHASE_COMPLETE) { - scsi_hd_callback(id); - shdc[id].callback = 0LL; - } else - shdc[id].callback = -1LL; /* Speed depends on SCSI controller */ + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + dev->error = ((scsi_disk_sense_key & 0xf) << 4) | ABRT_ERR; + dev->status = READY_STAT | ERR_STAT; + dev->phase = 3; + dev->packet_status = 0x80; + dev->callback = 50 * SCSI_TIME; + scsi_disk_log("SCSI HD %i: ERROR: %02X/%02X/%02X\n", dev->id, scsi_disk_sense_key, scsi_disk_asc, scsi_disk_ascq); } -void scsi_hd_command_complete(uint8_t id) +static void +scsi_disk_invalid_lun(scsi_disk_t *dev) { - shdc[id].packet_status = CDROM_PHASE_COMPLETE; - scsi_hd_command_common(id); + scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_disk_asc = ASC_INV_LUN; + scsi_disk_ascq = 0; + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_cmd_error(dev); } -static void scsi_hd_command_read_dma(uint8_t id) +static void +scsi_disk_illegal_opcode(scsi_disk_t *dev) { - shdc[id].packet_status = CDROM_PHASE_DATA_IN_DMA; - scsi_hd_command_common(id); - shdc[id].total_read = 0; + scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_disk_asc = ASC_ILLEGAL_OPCODE; + scsi_disk_ascq = 0; + scsi_disk_cmd_error(dev); } -static void scsi_hd_command_write_dma(uint8_t id) +static void +scsi_disk_lba_out_of_range(scsi_disk_t *dev) { - shdc[id].packet_status = CDROM_PHASE_DATA_OUT_DMA; - scsi_hd_command_common(id); + scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_disk_asc = ASC_LBA_OUT_OF_RANGE; + scsi_disk_ascq = 0; + scsi_disk_cmd_error(dev); } -void scsi_hd_data_command_finish(uint8_t id, int len, int block_len, int alloc_len, int direction) +static void +scsi_disk_invalid_field(scsi_disk_t *dev) { - scsi_hd_log("SCSI HD %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", id, shdc[id].current_cdb[0], len, block_len, alloc_len, direction, shdc[id].request_length); - shdc[id].pos=0; - if (alloc_len >= 0) - { - if (alloc_len < len) - { - len = alloc_len; - } - } - if (len == 0) - { - scsi_hd_command_complete(id); - } - else - { - if (direction == 0) - { - scsi_hd_command_read_dma(id); - } - else - { - scsi_hd_command_write_dma(id); - } - } - - scsi_hd_log("SCSI HD %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", id, shdc[id].packet_status, shdc[id].request_length, shdc[id].packet_len, shdc[id].pos, shdc[id].phase); + scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_disk_asc = ASC_INV_FIELD_IN_CMD_PACKET; + scsi_disk_ascq = 0; + scsi_disk_cmd_error(dev); + dev->status = 0x53; } -static void scsi_hd_sense_clear(int id, int command) +static void +scsi_disk_invalid_field_pl(scsi_disk_t *dev) { - shdc[id].previous_command = command; - scsi_hd_sense_key = scsi_hd_asc = scsi_hd_ascq = 0; + scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_disk_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; + scsi_disk_ascq = 0; + scsi_disk_cmd_error(dev); + dev->status = 0x53; } -static void scsi_hd_set_phase(uint8_t id, uint8_t phase) +static void +scsi_disk_data_phase_error(scsi_disk_t *dev) { - uint8_t scsi_id = hdd[id].scsi_id; - uint8_t scsi_lun = hdd[id].scsi_lun; - - if ((hdd[id].bus != HDD_BUS_SCSI) && (hdd[id].bus != HDD_BUS_SCSI_REMOVABLE)) - return; - - SCSIDevices[scsi_id][scsi_lun].Phase = phase; + scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_disk_asc = ASC_DATA_PHASE_ERROR; + scsi_disk_ascq = 0; + scsi_disk_cmd_error(dev); } -static void scsi_hd_cmd_error(uint8_t id) +static int +scsi_disk_pre_execution_check(scsi_disk_t *dev, uint8_t *cdb) { - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - shdc[id].error = ((scsi_hd_sense_key & 0xf) << 4) | ABRT_ERR; - if (shdc[id].unit_attention & 3) - { - shdc[id].error |= MCR_ERR; - } - shdc[id].status = READY_STAT | ERR_STAT; - shdc[id].phase = 3; - shdc[id].packet_status = 0x80; - shdc[id].callback = 50 * SCSI_TIME; - scsi_hd_log("SCSI HD %i: ERROR: %02X/%02X/%02X\n", id, scsi_hd_sense_key, scsi_hd_asc, scsi_hd_ascq); + if ((cdb[0] != GPCMD_REQUEST_SENSE) && (cdb[1] & 0xe0)) { + scsi_disk_log("SCSI HD %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", + dev->id, ((dev->request_length >> 5) & 7)); + scsi_disk_invalid_lun(dev); + return 0; + } + + if (!(scsi_disk_command_flags[cdb[0]] & IMPLEMENTED)) { + scsi_disk_log("SCSI HD %i: Attempting to execute unknown command %02X\n", dev->id, cdb[0]); + scsi_disk_illegal_opcode(dev); + return 0; + } + + /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* + the UNIT ATTENTION condition if it's set. */ + if (cdb[0] != GPCMD_REQUEST_SENSE) + scsi_disk_sense_clear(dev, cdb[0]); + + scsi_disk_log("SCSI HD %i: Continuing with command\n", dev->id); + + return 1; } -static void scsi_hd_unit_attention(uint8_t id) +static void +scsi_disk_seek(scsi_disk_t *dev, uint32_t pos) { - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - shdc[id].error = (SENSE_NOT_READY << 4) | ABRT_ERR; - if (shdc[id].unit_attention & 3) - { - shdc[id].error |= MCR_ERR; - } - shdc[id].status = READY_STAT | ERR_STAT; - shdc[id].phase = 3; - shdc[id].packet_status = 0x80; - shdc[id].callback = 50 * CDROM_TIME; - scsi_hd_log("SCSI HD %i: UNIT ATTENTION\n", id); + /* scsi_disk_log("SCSI HD %i: Seek %08X\n", dev->id, pos); */ + hdd_image_seek(dev->id, pos); } -static void scsi_hd_not_ready(uint8_t id) +static void +scsi_disk_rezero(scsi_disk_t *dev) { - scsi_hd_sense_key = SENSE_NOT_READY; - scsi_hd_asc = ASC_MEDIUM_NOT_PRESENT; - scsi_hd_ascq = 0; - scsi_hd_cmd_error(id); + if (dev->id == 0xff) + return; + + dev->sector_pos = dev->sector_len = 0; + scsi_disk_seek(dev, 0); } -static void scsi_hd_write_protected(uint8_t id) +void +scsi_disk_reset(scsi_disk_t *dev) { - scsi_hd_sense_key = SENSE_UNIT_ATTENTION; - scsi_hd_asc = ASC_WRITE_PROTECTED; - scsi_hd_ascq = 0; - scsi_hd_cmd_error(id); + scsi_disk_rezero(dev); + dev->status = 0; + dev->callback = 0; + dev->packet_status = 0xff; } -static void scsi_hd_invalid_lun(uint8_t id) -{ - scsi_hd_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_hd_asc = ASC_INV_LUN; - scsi_hd_ascq = 0; - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - scsi_hd_cmd_error(id); -} - - -static void scsi_hd_illegal_opcode(uint8_t id) -{ - scsi_hd_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_hd_asc = ASC_ILLEGAL_OPCODE; - scsi_hd_ascq = 0; - scsi_hd_cmd_error(id); -} - - -void scsi_hd_lba_out_of_range(uint8_t id) -{ - scsi_hd_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_hd_asc = ASC_LBA_OUT_OF_RANGE; - scsi_hd_ascq = 0; - scsi_hd_cmd_error(id); -} - - -static void scsi_hd_invalid_field(uint8_t id) -{ - scsi_hd_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_hd_asc = ASC_INV_FIELD_IN_CMD_PACKET; - scsi_hd_ascq = 0; - scsi_hd_cmd_error(id); - shdc[id].status = 0x53; -} - - -static void scsi_hd_invalid_field_pl(uint8_t id) -{ - scsi_hd_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_hd_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; - scsi_hd_ascq = 0; - scsi_hd_cmd_error(id); - shdc[id].status = 0x53; -} - - -static void scsi_hd_data_phase_error(uint8_t id) -{ - scsi_hd_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_hd_asc = ASC_DATA_PHASE_ERROR; - scsi_hd_ascq = 0; - scsi_hd_cmd_error(id); -} - - -/*SCSI Sense Initialization*/ -void scsi_hd_sense_code_ok(uint8_t id) -{ - scsi_hd_sense_key = SENSE_NONE; - scsi_hd_asc = 0; - scsi_hd_ascq = 0; -} - - -int scsi_hd_pre_execution_check(uint8_t id, uint8_t *cdb) -{ - int ready = 1; - - if (((shdc[id].request_length >> 5) & 7) != hdd[id].scsi_lun) - { - scsi_hd_log("SCSI HD %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", id, ((shdc[id].request_length >> 5) & 7)); - scsi_hd_invalid_lun(id); - return 0; - } - - if (!(scsi_hd_command_flags[cdb[0]] & IMPLEMENTED)) - { - scsi_hd_log("SCSI HD %i: Attempting to execute unknown command %02X\n", id, cdb[0]); - scsi_hd_illegal_opcode(id); - return 0; - } - - if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) - { - /* Removable disk, set ready state. */ - if (wcslen(hdd[id].fn) > 0) - { - ready = 1; - } - else - { - ready = 0; - } - } - else - { - /* Fixed disk, clear UNIT ATTENTION, just in case it might have been set when the disk was removable). */ - shdc[id].unit_attention = 0; - } - - if (!ready && shdc[id].unit_attention) - { - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - shdc[id].unit_attention = 0; - } - - /* If the UNIT ATTENTION condition is set and the command does not allow - execution under it, error out and report the condition. */ - if (shdc[id].unit_attention == 1) - { - /* Only increment the unit attention phase if the command can not pass through it. */ - if (!(scsi_hd_command_flags[cdb[0]] & ALLOW_UA)) - { - /* scsi_hd_log("SCSI HD %i: Unit attention now 2\n", id); */ - shdc[id].unit_attention = 2; - scsi_hd_log("SCSI HD %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", id, cdb[0]); - scsi_hd_unit_attention(id); - return 0; - } - } - else if (shdc[id].unit_attention == 2) - { - if (cdb[0] != GPCMD_REQUEST_SENSE) - { - /* scsi_hd_log("SCSI HD %i: Unit attention now 0\n", id); */ - shdc[id].unit_attention = 0; - } - } - - /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* - the UNIT ATTENTION condition if it's set. */ - if (cdb[0] != GPCMD_REQUEST_SENSE) - { - scsi_hd_sense_clear(id, cdb[0]); - } - - /* Next it's time for NOT READY. */ - if ((scsi_hd_command_flags[cdb[0]] & CHECK_READY) && !ready) - { - scsi_hd_log("SCSI HD %i: Not ready (%02X)\n", id, cdb[0]); - scsi_hd_not_ready(id); - return 0; - } - - scsi_hd_log("SCSI HD %i: Continuing with command\n", id); - - return 1; -} - - -static void scsi_hd_seek(uint8_t id, uint32_t pos) -{ - /* scsi_hd_log("SCSI HD %i: Seek %08X\n", id, pos); */ - hdd_image_seek(id, pos); -} - - -static void scsi_hd_rezero(uint8_t id) -{ - if (id == 255) - { - return; - } - - shdc[id].sector_pos = shdc[id].sector_len = 0; - scsi_hd_seek(id, 0); -} - - -void scsi_hd_reset(uint8_t id) -{ - scsi_hd_rezero(id); - shdc[id].status = 0; - shdc[id].callback = 0; - shdc[id].packet_status = 0xff; -} - - -void scsi_hd_request_sense(uint8_t id, uint8_t *buffer, uint8_t alloc_length, int desc) +void +scsi_disk_request_sense(scsi_disk_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc) { - /*Will return 18 bytes of 0*/ - if (alloc_length != 0) - { - memset(buffer, 0, alloc_length); - if (!desc) - memcpy(buffer, shdc[id].sense, alloc_length); - else { - buffer[1] = scsi_hd_sense_key; - buffer[2] = scsi_hd_asc; - buffer[3] = scsi_hd_ascq; - } - } - else - { - return; + /*Will return 18 bytes of 0*/ + if (alloc_length != 0) { + memset(buffer, 0, alloc_length); + if (!desc) + memcpy(buffer, dev->sense, alloc_length); + else { + buffer[1] = scsi_disk_sense_key; + buffer[2] = scsi_disk_asc; + buffer[3] = scsi_disk_ascq; } + } else + return; - buffer[0] = 0x70; + buffer[0] = 0x70; - if (shdc[id].unit_attention && (scsi_hd_sense_key == 0)) - { - buffer[desc ? 1 : 2]=SENSE_UNIT_ATTENTION; - buffer[desc ? 2 : 12]=ASC_MEDIUM_MAY_HAVE_CHANGED; - buffer[desc ? 3 : 13]=0x00; - } + scsi_disk_log("SCSI HD %i: Reporting sense: %02X %02X %02X\n", dev->id, buffer[2], buffer[12], buffer[13]); - scsi_hd_log("SCSI HD %i: Reporting sense: %02X %02X %02X\n", id, buffer[2], buffer[12], buffer[13]); - - if (buffer[desc ? 1: 2] == SENSE_UNIT_ATTENTION) - { - /* If the last remaining sense is unit attention, clear - that condition. */ - shdc[id].unit_attention = 0; - } - - /* Clear the sense stuff as per the spec. */ - scsi_hd_sense_clear(id, GPCMD_REQUEST_SENSE); + /* Clear the sense stuff as per the spec. */ + scsi_disk_sense_clear(dev, GPCMD_REQUEST_SENSE); } -void scsi_hd_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length) +void +scsi_disk_request_sense_for_scsi(scsi_disk_t *dev, uint8_t *buffer, uint8_t alloc_length) { - int ready = 1; + scsi_disk_request_sense(dev, buffer, alloc_length, 0); +} - if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) - { - /* Removable disk, set ready state. */ - if (wcslen(hdd[id].fn) > 0) - { - ready = 1; + +void +scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb) +{ + uint8_t *hdbufferb; + int32_t *BufLen; + uint32_t len; + int max_len, pos = 0; + unsigned idx = 0; + unsigned size_idx, preamble_len; + uint32_t alloc_length, last_sector = 0; + char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; + char device_identify_ex[15] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; + int block_desc = 0; + + hdbufferb = SCSIDevices[dev->drv->scsi_id].CmdBuffer; + BufLen = &SCSIDevices[dev->drv->scsi_id].BufferLength; + + last_sector = hdd_image_get_last_sector(dev->id); + + dev->status &= ~ERR_STAT; + dev->packet_len = 0; + + device_identify[6] = (dev->id / 10) + 0x30; + device_identify[7] = (dev->id % 10) + 0x30; + + device_identify_ex[6] = (dev->id / 10) + 0x30; + device_identify_ex[7] = (dev->id % 10) + 0x30; + device_identify_ex[10] = EMU_VERSION[0]; + device_identify_ex[12] = EMU_VERSION[2]; + device_identify_ex[13] = EMU_VERSION[3]; + + memcpy(dev->current_cdb, cdb, 12); + + if (cdb[0] != 0) { + scsi_disk_log("SCSI HD %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X\n", + dev->id, cdb[0], scsi_disk_sense_key, scsi_disk_asc, scsi_disk_ascq); + scsi_disk_log("SCSI HD %i: Request length: %04X\n", dev->id, dev->request_length); + + scsi_disk_log("SCSI HD %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, + cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], + cdb[8], cdb[9], cdb[10], cdb[11]); + } + + dev->sector_len = 0; + + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + + /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ + if (scsi_disk_pre_execution_check(dev, cdb) == 0) + return; + + switch (cdb[0]) { + case GPCMD_SEND_DIAGNOSTIC: + if (!(cdb[1] & (1 << 2))) { + scsi_disk_invalid_field(dev); + return; } + case GPCMD_SCSI_RESERVE: + case GPCMD_SCSI_RELEASE: + case GPCMD_TEST_UNIT_READY: + case GPCMD_FORMAT_UNIT: + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_command_complete(dev); + break; + + case GPCMD_REZERO_UNIT: + dev->sector_pos = dev->sector_len = 0; + scsi_disk_seek(dev, 0); + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + break; + + case GPCMD_REQUEST_SENSE: + /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE + should forget about the not ready, and report unit attention straight away. */ + if ((*BufLen == -1) || (cdb[4] < *BufLen)) + *BufLen = cdb[4]; + + if (*BufLen < cdb[4]) + cdb[4] = *BufLen; + + len = (cdb[1] & 1) ? 8 : 18; + + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); + scsi_disk_data_command_finish(dev, len, len, cdb[4], 0); + break; + + case GPCMD_MECHANISM_STATUS: + len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; + + if ((*BufLen == -1) || (len < *BufLen)) + *BufLen = len; + + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); + scsi_disk_data_command_finish(dev, 8, 8, len, 0); + break; + + case GPCMD_READ_6: + case GPCMD_READ_10: + case GPCMD_READ_12: + switch(cdb[0]) { + case GPCMD_READ_6: + dev->sector_len = cdb[4]; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + break; + case GPCMD_READ_10: + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + break; + case GPCMD_READ_12: + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + break; + } + + if ((dev->sector_pos > last_sector) || ((dev->sector_pos + dev->sector_len - 1) > last_sector)) { + scsi_disk_lba_out_of_range(dev); + return; + } + + if ((!dev->sector_len) || (*BufLen == 0)) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_log("SCSI HD %i: All done - callback set\n", dev); + dev->packet_status = CDROM_PHASE_COMPLETE; + dev->callback = 20 * SCSI_TIME; + break; + } + + max_len = dev->sector_len; + dev->requested_blocks = max_len; + + alloc_length = dev->packet_len = max_len << 9; + + if ((*BufLen == -1) || (alloc_length < *BufLen)) + *BufLen = alloc_length; + + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); + + if (dev->requested_blocks > 1) + scsi_disk_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, alloc_length, 0); else - { - ready = 0; - } - } - else - { - /* Fixed disk, clear UNIT ATTENTION, just in case it might have been set when the disk was removable). */ - shdc[id].unit_attention = 0; - } - - if (!ready && shdc[id].unit_attention) - { - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - shdc[id].unit_attention = 0; - } - - /* Do *NOT* advance the unit attention phase. */ - - scsi_hd_request_sense(id, buffer, alloc_length, 0); -} - - -void scsi_hd_command(uint8_t id, uint8_t *cdb) -{ - /* uint8_t *hdbufferb = (uint8_t *) shdc[id].buffer; */ - uint8_t *hdbufferb = SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].CmdBuffer; - uint32_t len; - int pos=0; - int max_len; - unsigned idx = 0; - unsigned size_idx; - unsigned preamble_len; - uint32_t alloc_length; - char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; - char device_identify_ex[15] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; - uint32_t last_sector = 0; - int block_desc = 0; - int32_t *BufLen = &SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].BufferLength; - -#if 0 - int CdbLength; -#endif - last_sector = hdd_image_get_last_sector(id); - - shdc[id].status &= ~ERR_STAT; - - shdc[id].packet_len = 0; - shdc[id].request_pos = 0; - - device_identify[6] = (id / 10) + 0x30; - device_identify[7] = (id % 10) + 0x30; - - device_identify_ex[6] = (id / 10) + 0x30; - device_identify_ex[7] = (id % 10) + 0x30; - device_identify_ex[10] = EMU_VERSION[0]; - device_identify_ex[12] = EMU_VERSION[2]; - device_identify_ex[13] = EMU_VERSION[3]; - - if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) - { - device_identify[4] = 'R'; - - device_identify_ex[4] = 'R'; - } - - shdc[id].data_pos = 0; - - memcpy(shdc[id].current_cdb, cdb, 12); - - if (cdb[0] != 0) - { - scsi_hd_log("SCSI HD %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X\n", id, cdb[0], scsi_hd_sense_key, scsi_hd_asc, scsi_hd_ascq); - scsi_hd_log("SCSI HD %i: Request length: %04X\n", id, shdc[id].request_length); - -#if 0 - for (CdbLength = 1; CdbLength < 12; CdbLength++) - { - scsi_hd_log("SCSI HD %i: CDB[%d] = %d\n", id, CdbLength, cdb[CdbLength]); - } -#endif - } - - shdc[id].sector_len = 0; - - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - - /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ - if (scsi_hd_pre_execution_check(id, cdb) == 0) - { + scsi_disk_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 0); return; - } - switch (cdb[0]) - { - case GPCMD_SEND_DIAGNOSTIC: - if (!(cdb[1] & (1 << 2))) { - scsi_hd_invalid_field(id); - return; - } - case GPCMD_SCSI_RESERVE: - case GPCMD_SCSI_RELEASE: - case GPCMD_TEST_UNIT_READY: - case GPCMD_FORMAT_UNIT: - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - scsi_hd_command_complete(id); + case GPCMD_VERIFY_6: + case GPCMD_VERIFY_10: + case GPCMD_VERIFY_12: + if (!(cdb[1] & 2)) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_command_complete(dev); break; - - case GPCMD_REZERO_UNIT: - shdc[id].sector_pos = shdc[id].sector_len = 0; - scsi_hd_seek(id, 0); - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - break; - - case GPCMD_REQUEST_SENSE: - /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE - should forget about the not ready, and report unit attention straight away. */ - if ((*BufLen == -1) || (cdb[4] < *BufLen)) - { - *BufLen = cdb[4]; - } - - if (*BufLen < cdb[4]) - { - cdb[4] = *BufLen; - } - - len = (cdb[1] & 1) ? 8 : 18; - - scsi_hd_set_phase(id, SCSI_PHASE_DATA_IN); - scsi_hd_data_command_finish(id, len, len, cdb[4], 0); - break; - - case GPCMD_MECHANISM_STATUS: - len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - - if ((*BufLen == -1) || (len < *BufLen)) - { - *BufLen = len; - } - - scsi_hd_set_phase(id, SCSI_PHASE_DATA_IN); - scsi_hd_data_command_finish(id, 8, 8, len, 0); - break; - - case GPCMD_READ_6: - case GPCMD_READ_10: - case GPCMD_READ_12: - switch(cdb[0]) - { - case GPCMD_READ_6: - shdc[id].sector_len = cdb[4]; - shdc[id].sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - break; - case GPCMD_READ_10: - shdc[id].sector_len = (cdb[7] << 8) | cdb[8]; - shdc[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - break; - case GPCMD_READ_12: - shdc[id].sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - shdc[id].sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - break; - } - - if ((shdc[id].sector_pos > last_sector) || ((shdc[id].sector_pos + shdc[id].sector_len - 1) > last_sector)) - { - scsi_hd_lba_out_of_range(id); - return; - } - - if ((!shdc[id].sector_len) || (*BufLen == 0)) - { - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); - scsi_hd_log("SCSI HD %i: All done - callback set\n", id); - shdc[id].packet_status = CDROM_PHASE_COMPLETE; - shdc[id].callback = 20 * SCSI_TIME; + } + case GPCMD_WRITE_6: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + switch(cdb[0]) + { + case GPCMD_VERIFY_6: + case GPCMD_WRITE_6: + dev->sector_len = cdb[4]; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + scsi_disk_log("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); break; - } + case GPCMD_VERIFY_10: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + scsi_disk_log("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + break; + case GPCMD_VERIFY_12: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + break; + } - max_len = shdc[id].sector_len; - shdc[id].requested_blocks = max_len; - - alloc_length = shdc[id].packet_len = max_len << 9; - - if ((*BufLen == -1) || (alloc_length < *BufLen)) - { - *BufLen = alloc_length; - } - - scsi_hd_set_phase(id, SCSI_PHASE_DATA_IN); - - if (shdc[id].requested_blocks > 1) - { - scsi_hd_data_command_finish(id, alloc_length, alloc_length / shdc[id].requested_blocks, alloc_length, 0); - } - else - { - scsi_hd_data_command_finish(id, alloc_length, alloc_length, alloc_length, 0); - } - shdc[id].all_blocks_total = shdc[id].block_total; - ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 1); + if ((dev->sector_pos > last_sector) || + ((dev->sector_pos + dev->sector_len - 1) > last_sector)) { + scsi_disk_lba_out_of_range(dev); return; + } - case GPCMD_VERIFY_6: - case GPCMD_VERIFY_10: - case GPCMD_VERIFY_12: - if (!(cdb[1] & 2)) { - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - scsi_hd_command_complete(id); - break; - } - case GPCMD_WRITE_6: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - if ((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) && hdd[id].wp) - { - scsi_hd_write_protected(id); - return; - } + if ((!dev->sector_len) || (*BufLen == 0)) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); + dev->packet_status = CDROM_PHASE_COMPLETE; + dev->callback = 20 * SCSI_TIME; + break; + } - switch(cdb[0]) - { - case GPCMD_VERIFY_6: - case GPCMD_WRITE_6: - shdc[id].sector_len = cdb[4]; - shdc[id].sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - scsi_hd_log("SCSI HD %i: Length: %i, LBA: %i\n", id, shdc[id].sector_len, shdc[id].sector_pos); - break; - case GPCMD_VERIFY_10: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - shdc[id].sector_len = (cdb[7] << 8) | cdb[8]; - shdc[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - scsi_hd_log("SCSI HD %i: Length: %i, LBA: %i\n", id, shdc[id].sector_len, shdc[id].sector_pos); - break; - case GPCMD_VERIFY_12: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - shdc[id].sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - shdc[id].sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - break; - } + max_len = dev->sector_len; + dev->requested_blocks = max_len; - if ((shdc[id].sector_pos > last_sector) || ((shdc[id].sector_pos + shdc[id].sector_len - 1) > last_sector)) - { - scsi_hd_lba_out_of_range(id); - return; - } + alloc_length = dev->packet_len = max_len << 9; - if ((!shdc[id].sector_len) || (*BufLen == 0)) - { - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); - scsi_hd_log("SCSI HD %i: All done - callback set\n", id); - shdc[id].packet_status = CDROM_PHASE_COMPLETE; - shdc[id].callback = 20 * SCSI_TIME; - break; - } + if ((*BufLen == -1) || (alloc_length < *BufLen)) + *BufLen = alloc_length; - max_len = shdc[id].sector_len; - shdc[id].requested_blocks = max_len; - - alloc_length = shdc[id].packet_len = max_len << 9; + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); - if ((*BufLen == -1) || (alloc_length < *BufLen)) - { - *BufLen = alloc_length; - } + if (dev->requested_blocks > 1) + scsi_disk_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, alloc_length, 1); + else + scsi_disk_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 1); + return; - scsi_hd_set_phase(id, SCSI_PHASE_DATA_OUT); - - if (shdc[id].requested_blocks > 1) - { - scsi_hd_data_command_finish(id, alloc_length, alloc_length / shdc[id].requested_blocks, alloc_length, 1); - } - else - { - scsi_hd_data_command_finish(id, alloc_length, alloc_length, alloc_length, 1); - } - shdc[id].all_blocks_total = shdc[id].block_total; - ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 1); + case GPCMD_WRITE_SAME_10: + if ((cdb[1] & 6) == 6) { + scsi_disk_invalid_field(dev); return; + } - case GPCMD_WRITE_SAME_10: - if ((cdb[1] & 6) == 6) - { - scsi_hd_invalid_field(id); - return; - } + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + scsi_disk_log("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); - if ((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) && hdd[id].wp) - { - scsi_hd_write_protected(id); - return; - } - - shdc[id].sector_len = (cdb[7] << 8) | cdb[8]; - shdc[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - scsi_hd_log("SCSI HD %i: Length: %i, LBA: %i\n", id, shdc[id].sector_len, shdc[id].sector_pos); - - if ((shdc[id].sector_pos > last_sector) || ((shdc[id].sector_pos + shdc[id].sector_len - 1) > last_sector)) - { - scsi_hd_lba_out_of_range(id); - return; - } - - if ((!shdc[id].sector_len) || (*BufLen == 0)) - { - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); - scsi_hd_log("SCSI HD %i: All done - callback set\n", id); - shdc[id].packet_status = CDROM_PHASE_COMPLETE; - shdc[id].callback = 20 * SCSI_TIME; - break; - } - - max_len = 1; - shdc[id].requested_blocks = max_len; - - alloc_length = shdc[id].packet_len = max_len << 9; - - if ((*BufLen == -1) || (alloc_length < *BufLen)) - { - *BufLen = alloc_length; - } - - scsi_hd_set_phase(id, SCSI_PHASE_DATA_OUT); - - if (shdc[id].requested_blocks > 1) - { - scsi_hd_data_command_finish(id, alloc_length, alloc_length / shdc[id].requested_blocks, alloc_length, 1); - } - else - { - scsi_hd_data_command_finish(id, alloc_length, alloc_length, alloc_length, 1); - } - shdc[id].all_blocks_total = shdc[id].block_total; - ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 1); + if ((dev->sector_pos > last_sector) || + ((dev->sector_pos + dev->sector_len - 1) > last_sector)) { + scsi_disk_lba_out_of_range(dev); return; + } - case GPCMD_MODE_SENSE_6: - case GPCMD_MODE_SENSE_10: - scsi_hd_set_phase(id, SCSI_PHASE_DATA_IN); - - block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; + if ((!dev->sector_len) || (*BufLen == 0)) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); + dev->packet_status = CDROM_PHASE_COMPLETE; + dev->callback = 20 * SCSI_TIME; + break; + } - if (cdb[0] == GPCMD_MODE_SENSE_6) - len = cdb[4]; - else - len = (cdb[8] | (cdb[7] << 8)); + max_len = 1; + dev->requested_blocks = max_len; - shdc[id].current_page_code = cdb[2] & 0x3F; + alloc_length = dev->packet_len = max_len << 9; - alloc_length = len; + if ((*BufLen == -1) || (alloc_length < *BufLen)) + *BufLen = alloc_length; - shdc[id].temp_buffer = (uint8_t *) malloc(65536); - memset(shdc[id].temp_buffer, 0, 65536); + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = scsi_hd_mode_sense(id, shdc[id].temp_buffer, 4, cdb[2], block_desc); - if (len > alloc_length) - len = alloc_length; - shdc[id].temp_buffer[0] = len - 1; - shdc[id].temp_buffer[1] = 0; - if (block_desc) - shdc[id].temp_buffer[3] = 8; - } - else - { - len = scsi_hd_mode_sense(id, shdc[id].temp_buffer, 8, cdb[2], block_desc); - if (len > alloc_length) - len = alloc_length; - shdc[id].temp_buffer[0]=(len - 2) >> 8; - shdc[id].temp_buffer[1]=(len - 2) & 255; - shdc[id].temp_buffer[2] = 0; - if (block_desc) { - shdc[id].temp_buffer[6] = 0; - shdc[id].temp_buffer[7] = 8; - } - } + if (dev->requested_blocks > 1) + scsi_disk_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, alloc_length, 1); + else + scsi_disk_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 1); + return; + case GPCMD_MODE_SENSE_6: + case GPCMD_MODE_SENSE_10: + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); + + block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; + + if (cdb[0] == GPCMD_MODE_SENSE_6) + len = cdb[4]; + else + len = (cdb[8] | (cdb[7] << 8)); + + dev->current_page_code = cdb[2] & 0x3F; + + alloc_length = len; + + dev->temp_buffer = (uint8_t *) malloc(65536); + memset(dev->temp_buffer, 0, 65536); + + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = scsi_disk_mode_sense(dev, dev->temp_buffer, 4, cdb[2], block_desc); if (len > alloc_length) len = alloc_length; - else if (len < alloc_length) - alloc_length = len; - - if ((*BufLen == -1) || (alloc_length < *BufLen)) - *BufLen = alloc_length; - - scsi_hd_log("SCSI HDD %i: Reading mode page: %02X...\n", id, cdb[2]); - - scsi_hd_data_command_finish(id, len, len, alloc_length, 0); - return; - - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - scsi_hd_set_phase(id, SCSI_PHASE_DATA_OUT); - - if (cdb[0] == GPCMD_MODE_SELECT_6) - len = cdb[4]; - else - len = (cdb[7] << 8) | cdb[8]; - - if ((*BufLen == -1) || (len < *BufLen)) - *BufLen = len; - - shdc[id].total_length = len; - shdc[id].do_page_save = cdb[1] & 1; - - shdc[id].current_page_pos = 0; - - scsi_hd_data_command_finish(id, len, len, len, 1); - return; - - case GPCMD_START_STOP_UNIT: - if (hdd[id].bus != HDD_BUS_SCSI_REMOVABLE) - { - scsi_hd_illegal_opcode(id); - break; + dev->temp_buffer[0] = len - 1; + dev->temp_buffer[1] = 0; + if (block_desc) + dev->temp_buffer[3] = 8; + } else { + len = scsi_disk_mode_sense(dev, dev->temp_buffer, 8, cdb[2], block_desc); + if (len > alloc_length) + len = alloc_length; + dev->temp_buffer[0]=(len - 2) >> 8; + dev->temp_buffer[1]=(len - 2) & 255; + dev->temp_buffer[2] = 0; + if (block_desc) { + dev->temp_buffer[6] = 0; + dev->temp_buffer[7] = 8; } + } - switch(cdb[4] & 3) - { - case 0: /* Stop the disc. */ - case 1: /* Start the disc and read the TOC. */ - break; - case 2: /* Eject the disc if possible. */ - removable_disk_eject(id); - break; - case 3: /* Load the disc (close tray). */ - removable_disk_reload(id); - break; - } + if (len > alloc_length) + len = alloc_length; + else if (len < alloc_length) + alloc_length = len; - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - scsi_hd_command_complete(id); + if ((*BufLen == -1) || (alloc_length < *BufLen)) + *BufLen = alloc_length; + + scsi_disk_log("SCSI HDD %i: Reading mode page: %02X...\n", dev->id, cdb[2]); + + scsi_disk_data_command_finish(dev, len, len, alloc_length, 0); + return; + + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); + + if (cdb[0] == GPCMD_MODE_SELECT_6) + len = cdb[4]; + else + len = (cdb[7] << 8) | cdb[8]; + + if ((*BufLen == -1) || (len < *BufLen)) + *BufLen = len; + + dev->total_length = len; + dev->do_page_save = cdb[1] & 1; + + scsi_disk_data_command_finish(dev, len, len, len, 1); + return; + + case GPCMD_INQUIRY: + max_len = cdb[3]; + max_len <<= 8; + max_len |= cdb[4]; + + if ((!max_len) || (*BufLen == 0)) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + /* scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); */ + dev->packet_status = CDROM_PHASE_COMPLETE; + dev->callback = 20 * SCSI_TIME; break; + } - case GPCMD_INQUIRY: - max_len = cdb[3]; - max_len <<= 8; - max_len |= cdb[4]; + dev->temp_buffer = malloc(1024); - if ((!max_len) || (*BufLen == 0)) - { - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - /* scsi_hd_log("SCSI HD %i: All done - callback set\n", id); */ - shdc[id].packet_status = CDROM_PHASE_COMPLETE; - shdc[id].callback = 20 * SCSI_TIME; - break; - } - - shdc[id].temp_buffer = malloc(1024); + if (cdb[1] & 1) { + preamble_len = 4; + size_idx = 3; - if (cdb[1] & 1) - { - preamble_len = 4; - size_idx = 3; - - shdc[id].temp_buffer[idx++] = 05; - shdc[id].temp_buffer[idx++] = cdb[2]; - shdc[id].temp_buffer[idx++] = 0; + dev->temp_buffer[idx++] = 05; + dev->temp_buffer[idx++] = cdb[2]; + dev->temp_buffer[idx++] = 0; - idx++; + idx++; - switch (cdb[2]) - { - case 0x00: - shdc[id].temp_buffer[idx++] = 0x00; - shdc[id].temp_buffer[idx++] = 0x83; - break; - case 0x83: - if (idx + 24 > max_len) - { - free(shdc[id].temp_buffer); - shdc[id].temp_buffer = NULL; - scsi_hd_data_phase_error(id); - return; - } - - shdc[id].temp_buffer[idx++] = 0x02; - shdc[id].temp_buffer[idx++] = 0x00; - shdc[id].temp_buffer[idx++] = 0x00; - shdc[id].temp_buffer[idx++] = 20; - ide_padstr8(shdc[id].temp_buffer + idx, 20, "53R141"); /* Serial */ - idx += 20; - - if (idx + 72 > cdb[4]) - { - goto atapi_out; - } - shdc[id].temp_buffer[idx++] = 0x02; - shdc[id].temp_buffer[idx++] = 0x01; - shdc[id].temp_buffer[idx++] = 0x00; - shdc[id].temp_buffer[idx++] = 68; - ide_padstr8(shdc[id].temp_buffer + idx, 8, EMU_NAME); /* Vendor */ - idx += 8; - ide_padstr8(shdc[id].temp_buffer + idx, 40, device_identify_ex); /* Product */ - idx += 40; - ide_padstr8(shdc[id].temp_buffer + idx, 20, "53R141"); /* Product */ - idx += 20; - break; - default: - scsi_hd_log("INQUIRY: Invalid page: %02X\n", cdb[2]); - free(shdc[id].temp_buffer); - shdc[id].temp_buffer = NULL; - scsi_hd_invalid_field(id); + switch (cdb[2]) { + case 0x00: + dev->temp_buffer[idx++] = 0x00; + dev->temp_buffer[idx++] = 0x83; + break; + case 0x83: + if (idx + 24 > max_len) { + free(dev->temp_buffer); + dev->temp_buffer = NULL; + scsi_disk_data_phase_error(dev); return; - } + } + + dev->temp_buffer[idx++] = 0x02; + dev->temp_buffer[idx++] = 0x00; + dev->temp_buffer[idx++] = 0x00; + dev->temp_buffer[idx++] = 20; + ide_padstr8(dev->temp_buffer + idx, 20, "53R141"); /* Serial */ + idx += 20; + + if (idx + 72 > cdb[4]) + goto atapi_out; + dev->temp_buffer[idx++] = 0x02; + dev->temp_buffer[idx++] = 0x01; + dev->temp_buffer[idx++] = 0x00; + dev->temp_buffer[idx++] = 68; + ide_padstr8(dev->temp_buffer + idx, 8, EMU_NAME); /* Vendor */ + idx += 8; + ide_padstr8(dev->temp_buffer + idx, 40, device_identify_ex); /* Product */ + idx += 40; + ide_padstr8(dev->temp_buffer + idx, 20, "53R141"); /* Product */ + idx += 20; + break; + default: + scsi_disk_log("INQUIRY: Invalid page: %02X\n", cdb[2]); + free(dev->temp_buffer); + dev->temp_buffer = NULL; + scsi_disk_invalid_field(dev); + return; } - else - { - preamble_len = 5; - size_idx = 4; + } else { + preamble_len = 5; + size_idx = 4; - memset(shdc[id].temp_buffer, 0, 8); - shdc[id].temp_buffer[0] = 0; /*SCSI HD*/ - if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) - { - shdc[id].temp_buffer[1] = 0x80; /*Removable*/ - } - else - { - shdc[id].temp_buffer[1] = 0; /*Fixed*/ - } - shdc[id].temp_buffer[2] = 0x02; /*SCSI-2 compliant*/ - shdc[id].temp_buffer[3] = 0x02; - shdc[id].temp_buffer[4] = 31; - shdc[id].temp_buffer[6] = 1; /* 16-bit transfers supported */ - shdc[id].temp_buffer[7] = 0x20; /* Wide bus supported */ + memset(dev->temp_buffer, 0, 8); + dev->temp_buffer[0] = 0; /*SCSI HD*/ + dev->temp_buffer[1] = 0; /*Fixed*/ + dev->temp_buffer[2] = 0x02; /*SCSI-2 compliant*/ + dev->temp_buffer[3] = 0x02; + dev->temp_buffer[4] = 31; + dev->temp_buffer[6] = 1; /* 16-bit transfers supported */ + dev->temp_buffer[7] = 0x20; /* Wide bus supported */ - ide_padstr8(shdc[id].temp_buffer + 8, 8, EMU_NAME); /* Vendor */ - ide_padstr8(shdc[id].temp_buffer + 16, 16, device_identify); /* Product */ - ide_padstr8(shdc[id].temp_buffer + 32, 4, EMU_VERSION); /* Revision */ - idx = 36; + ide_padstr8(dev->temp_buffer + 8, 8, EMU_NAME); /* Vendor */ + ide_padstr8(dev->temp_buffer + 16, 16, device_identify); /* Product */ + ide_padstr8(dev->temp_buffer + 32, 4, EMU_VERSION); /* Revision */ + idx = 36; - if (max_len == 96) { - shdc[id].temp_buffer[4] = 91; - idx = 96; - } + if (max_len == 96) { + dev->temp_buffer[4] = 91; + idx = 96; } + } atapi_out: - shdc[id].temp_buffer[size_idx] = idx - preamble_len; - len=idx; + dev->temp_buffer[size_idx] = idx - preamble_len; + len=idx; - scsi_hd_log("scsi_hd_command(): Inquiry (%08X, %08X)\n", hdbufferb, shdc[id].temp_buffer); - - if (len > max_len) - { - len = max_len; - } - - if ((*BufLen == -1) || (len < *BufLen)) - { - *BufLen = len; - } + scsi_disk_log("scsi_disk_command(): Inquiry (%08X, %08X)\n", hdbufferb, dev->temp_buffer); + + if (len > max_len) + len = max_len; - if (len > *BufLen) - { - len = *BufLen; - } + if ((*BufLen == -1) || (len < *BufLen)) + *BufLen = len; - scsi_hd_set_phase(id, SCSI_PHASE_DATA_IN); - scsi_hd_data_command_finish(id, len, len, max_len, 0); - break; + if (len > *BufLen) + len = *BufLen; - case GPCMD_PREVENT_REMOVAL: - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - scsi_hd_command_complete(id); - break; + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); + scsi_disk_data_command_finish(dev, len, len, max_len, 0); + break; - case GPCMD_SEEK_6: - case GPCMD_SEEK_10: - switch(cdb[0]) - { - case GPCMD_SEEK_6: - pos = (cdb[2] << 8) | cdb[3]; - break; - case GPCMD_SEEK_10: - pos = (cdb[2] << 24) | (cdb[3]<<16) | (cdb[4]<<8) | cdb[5]; - break; - } - scsi_hd_seek(id, pos); - - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - scsi_hd_command_complete(id); - break; + case GPCMD_PREVENT_REMOVAL: + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_command_complete(dev); + break; - case GPCMD_READ_CDROM_CAPACITY: - shdc[id].temp_buffer = (uint8_t *) malloc(8); + case GPCMD_SEEK_6: + case GPCMD_SEEK_10: + switch(cdb[0]) { + case GPCMD_SEEK_6: + pos = (cdb[2] << 8) | cdb[3]; + break; + case GPCMD_SEEK_10: + pos = (cdb[2] << 24) | (cdb[3]<<16) | (cdb[4]<<8) | cdb[5]; + break; + } + scsi_disk_seek(dev, pos); - if (scsi_hd_read_capacity(id, shdc[id].current_cdb, shdc[id].temp_buffer, &len) == 0) - { - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - return; - } - - if ((*BufLen == -1) || (len < *BufLen)) - { - *BufLen = len; - } + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_command_complete(dev); + break; - scsi_hd_set_phase(id, SCSI_PHASE_DATA_IN); - scsi_hd_data_command_finish(id, len, len, len, 0); - break; + case GPCMD_READ_CDROM_CAPACITY: + dev->temp_buffer = (uint8_t *) malloc(8); - default: - scsi_hd_illegal_opcode(id); - break; - } - - /* scsi_hd_log("SCSI HD %i: Phase: %02X, request length: %i\n", shdc[id].phase, shdc[id].request_length); */ + if (scsi_disk_read_capacity(dev, dev->current_cdb, dev->temp_buffer, &len) == 0) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + return; + } + + if ((*BufLen == -1) || (len < *BufLen)) + *BufLen = len; + + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); + scsi_disk_data_command_finish(dev, len, len, len, 0); + break; + + default: + scsi_disk_illegal_opcode(dev); + break; + } + + /* scsi_disk_log("SCSI HD %i: Phase: %02X, request length: %i\n", dev->id, dev->phase, dev->request_length); */ } -void scsi_hd_phase_data_in(uint8_t id) +static void +scsi_disk_phase_data_in(scsi_disk_t *dev) { - uint8_t *hdbufferb = SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].CmdBuffer; - int32_t *BufLen = &SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].BufferLength; + uint8_t *hdbufferb = SCSIDevices[dev->drv->scsi_id].CmdBuffer; + int32_t *BufLen = &SCSIDevices[dev->drv->scsi_id].BufferLength; - if (!*BufLen) - { - scsi_hd_log("scsi_hd_phase_data_in(): Buffer length is 0\n"); - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); + if (!*BufLen) { + scsi_disk_log("scsi_disk_phase_data_in(): Buffer length is 0\n"); + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - return; - } + return; + } - switch (shdc[id].current_cdb[0]) - { - case GPCMD_REQUEST_SENSE: - scsi_hd_log("SCSI HDD %i: %08X, %08X\n", id, hdbufferb, *BufLen); - scsi_hd_request_sense(id, hdbufferb, *BufLen, shdc[id].current_cdb[1] & 1); - break; - case GPCMD_MECHANISM_STATUS: - memset(hdbufferb, 0, *BufLen); - hdbufferb[5] = 1; - break; - case GPCMD_READ_6: - case GPCMD_READ_10: - case GPCMD_READ_12: - if ((shdc[id].requested_blocks > 0) && (*BufLen > 0)) - { - if (shdc[id].packet_len > *BufLen) - { - hdd_image_read(id, shdc[id].sector_pos, *BufLen >> 9, hdbufferb); - } - else - { - hdd_image_read(id, shdc[id].sector_pos, shdc[id].requested_blocks, hdbufferb); - } - } - break; - case GPCMD_MODE_SENSE_6: - case GPCMD_MODE_SENSE_10: - case GPCMD_INQUIRY: - case GPCMD_READ_CDROM_CAPACITY: - scsi_hd_log("scsi_hd_phase_data_in(): Filling buffer (%08X, %08X)\n", hdbufferb, shdc[id].temp_buffer); - memcpy(hdbufferb, shdc[id].temp_buffer, *BufLen); - free(shdc[id].temp_buffer); - shdc[id].temp_buffer = NULL; - scsi_hd_log("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", - hdbufferb[0], hdbufferb[1], hdbufferb[2], hdbufferb[3], hdbufferb[4], hdbufferb[5], hdbufferb[6], hdbufferb[7], - hdbufferb[8], hdbufferb[9], hdbufferb[10], hdbufferb[11], hdbufferb[12], hdbufferb[13], hdbufferb[14], hdbufferb[15]); - break; - default: - fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", shdc[id].current_cdb[0]); - break; - } + switch (dev->current_cdb[0]) { + case GPCMD_REQUEST_SENSE: + scsi_disk_log("SCSI HDD %i: %08X, %08X\n", dev->id, hdbufferb, *BufLen); + scsi_disk_request_sense(dev, hdbufferb, *BufLen, dev->current_cdb[1] & 1); + break; + case GPCMD_MECHANISM_STATUS: + memset(hdbufferb, 0, *BufLen); + hdbufferb[5] = 1; + break; + case GPCMD_READ_6: + case GPCMD_READ_10: + case GPCMD_READ_12: + if ((dev->requested_blocks > 0) && (*BufLen > 0)) { + if (dev->packet_len > *BufLen) + hdd_image_read(dev->id, dev->sector_pos, *BufLen >> 9, hdbufferb); + else + hdd_image_read(dev->id, dev->sector_pos, dev->requested_blocks, hdbufferb); + } + break; + case GPCMD_MODE_SENSE_6: + case GPCMD_MODE_SENSE_10: + case GPCMD_INQUIRY: + case GPCMD_READ_CDROM_CAPACITY: + scsi_disk_log("scsi_disk_phase_data_in(): Filling buffer (%08X, %08X)\n", hdbufferb, dev->temp_buffer); + memcpy(hdbufferb, dev->temp_buffer, *BufLen); + free(dev->temp_buffer); + dev->temp_buffer = NULL; + scsi_disk_log("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", + hdbufferb[0], hdbufferb[1], hdbufferb[2], hdbufferb[3], hdbufferb[4], hdbufferb[5], hdbufferb[6], hdbufferb[7], + hdbufferb[8], hdbufferb[9], hdbufferb[10], hdbufferb[11], hdbufferb[12], hdbufferb[13], hdbufferb[14], hdbufferb[15]); + break; + default: + fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", dev->id, dev->current_cdb[0]); + break; + } - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); } -void scsi_hd_phase_data_out(uint8_t id) + +static void +scsi_disk_phase_data_out(scsi_disk_t *dev) { - uint8_t *hdbufferb = SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].CmdBuffer; + uint8_t *hdbufferb = SCSIDevices[dev->drv->scsi_id].CmdBuffer; + int i; + int32_t *BufLen = &SCSIDevices[dev->drv->scsi_id].BufferLength; + uint32_t last_sector = hdd_image_get_last_sector(dev->id); + uint32_t c, h, s, last_to_write = 0; + uint16_t block_desc_len, pos; + uint8_t hdr_len, val, old_val, ch, error = 0; + uint8_t page, page_len; - int i; + if (!*BufLen) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - int32_t *BufLen = &SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].BufferLength; + return; + } - uint32_t last_sector = hdd_image_get_last_sector(id); - uint32_t last_to_write = 0; - - uint32_t c, h, s; - - uint16_t block_desc_len; - uint16_t pos; - - uint8_t error = 0; - uint8_t page, page_len; - - uint8_t hdr_len, val, old_val, ch; - - if (!*BufLen) - { - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); - - return; - } - - switch (shdc[id].current_cdb[0]) - { - case GPCMD_VERIFY_6: - case GPCMD_VERIFY_10: - case GPCMD_VERIFY_12: - break; - case GPCMD_WRITE_6: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - if ((shdc[id].requested_blocks > 0) && (*BufLen > 0)) - { - if (shdc[id].packet_len > *BufLen) - { - hdd_image_write(id, shdc[id].sector_pos, *BufLen >> 9, hdbufferb); - } - else - { - hdd_image_write(id, shdc[id].sector_pos, shdc[id].requested_blocks, hdbufferb); - } - } - break; - case GPCMD_WRITE_SAME_10: - if (!shdc[id].current_cdb[7] && !shdc[id].current_cdb[8]) - last_to_write = last_sector; + switch (dev->current_cdb[0]) { + case GPCMD_VERIFY_6: + case GPCMD_VERIFY_10: + case GPCMD_VERIFY_12: + break; + case GPCMD_WRITE_6: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + if ((dev->requested_blocks > 0) && (*BufLen > 0)) { + if (dev->packet_len > *BufLen) + hdd_image_write(dev->id, dev->sector_pos, *BufLen >> 9, hdbufferb); else - last_to_write = shdc[id].sector_pos + shdc[id].sector_len - 1; + hdd_image_write(dev->id, dev->sector_pos, dev->requested_blocks, hdbufferb); + } + break; + case GPCMD_WRITE_SAME_10: + if (!dev->current_cdb[7] && !dev->current_cdb[8]) + last_to_write = last_sector; + else + last_to_write = dev->sector_pos + dev->sector_len - 1; - for (i = shdc[id].sector_pos; i <= last_to_write; i++) { - if (shdc[id].current_cdb[1] & 2) { - hdbufferb[0] = (i >> 24) & 0xff; - hdbufferb[1] = (i >> 16) & 0xff; - hdbufferb[2] = (i >> 8) & 0xff; - hdbufferb[3] = i & 0xff; - } else if (shdc[id].current_cdb[1] & 4) { - s = (i % hdd[id].spt); - h = ((i - s) / hdd[id].spt) % hdd[id].hpc; - c = ((i - s) / hdd[id].spt) / hdd[id].hpc; - hdbufferb[0] = (c >> 16) & 0xff; - hdbufferb[1] = (c >> 8) & 0xff; - hdbufferb[2] = c & 0xff; - hdbufferb[3] = h & 0xff; - hdbufferb[4] = (s >> 24) & 0xff; - hdbufferb[5] = (s >> 16) & 0xff; - hdbufferb[6] = (s >> 8) & 0xff; - hdbufferb[7] = s & 0xff; - } - hdd_image_write(id, i, 1, hdbufferb); + for (i = dev->sector_pos; i <= last_to_write; i++) { + if (dev->current_cdb[1] & 2) { + hdbufferb[0] = (i >> 24) & 0xff; + hdbufferb[1] = (i >> 16) & 0xff; + hdbufferb[2] = (i >> 8) & 0xff; + hdbufferb[3] = i & 0xff; + } else if (dev->current_cdb[1] & 4) { + s = (i % dev->drv->spt); + h = ((i - s) / dev->drv->spt) % dev->drv->hpc; + c = ((i - s) / dev->drv->spt) / dev->drv->hpc; + hdbufferb[0] = (c >> 16) & 0xff; + hdbufferb[1] = (c >> 8) & 0xff; + hdbufferb[2] = c & 0xff; + hdbufferb[3] = h & 0xff; + hdbufferb[4] = (s >> 24) & 0xff; + hdbufferb[5] = (s >> 16) & 0xff; + hdbufferb[6] = (s >> 8) & 0xff; + hdbufferb[7] = s & 0xff; } - break; - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - if (shdc[id].current_cdb[0] == GPCMD_MODE_SELECT_10) - hdr_len = 8; - else - hdr_len = 4; + hdd_image_write(dev->id, i, 1, hdbufferb); + } + break; + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) + hdr_len = 8; + else + hdr_len = 4; - if (shdc[id].current_cdb[0] == GPCMD_MODE_SELECT_6) { - block_desc_len = hdbufferb[2]; - block_desc_len <<= 8; - block_desc_len |= hdbufferb[3]; - } else { - block_desc_len = hdbufferb[6]; - block_desc_len <<= 8; - block_desc_len |= hdbufferb[7]; - } + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { + block_desc_len = hdbufferb[2]; + block_desc_len <<= 8; + block_desc_len |= hdbufferb[3]; + } else { + block_desc_len = hdbufferb[6]; + block_desc_len <<= 8; + block_desc_len |= hdbufferb[7]; + } - pos = hdr_len + block_desc_len; + pos = hdr_len + block_desc_len; - while(1) { - page = hdbufferb[pos] & 0x3F; - page_len = hdbufferb[pos + 1]; + while(1) { + page = hdbufferb[pos] & 0x3F; + page_len = hdbufferb[pos + 1]; - pos += 2; + pos += 2; - if (!(scsi_hd_mode_sense_page_flags & (1LL << ((uint64_t) page)))) - error |= 1; - else { - for (i = 0; i < page_len; i++) { - ch = scsi_hd_mode_sense_pages_changeable.pages[page][i + 2]; - val = hdbufferb[pos + i]; - old_val = scsi_hd_mode_sense_pages_saved[id].pages[page][i + 2]; - if (val != old_val) { - if (ch) - scsi_hd_mode_sense_pages_saved[id].pages[page][i + 2] = val; - else - error |= 1; - } + if (!(scsi_disk_mode_sense_page_flags & (1LL << ((uint64_t) page)))) + error |= 1; + else { + for (i = 0; i < page_len; i++) { + ch = scsi_disk_mode_sense_pages_changeable.pages[page][i + 2]; + val = hdbufferb[pos + i]; + old_val = dev->ms_pages_saved.pages[page][i + 2]; + if (val != old_val) { + if (ch) + dev->ms_pages_saved.pages[page][i + 2] = val; + else + error |= 1; } } - - pos += page_len; - - val = scsi_hd_mode_sense_pages_default.pages[page][0] & 0x80; - if (shdc[id].do_page_save && val) - scsi_hd_mode_sense_save(id); - - if (pos >= shdc[id].total_length) - break; } - if (error) - scsi_hd_invalid_field_pl(id); - break; - default: - fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", shdc[id].current_cdb[0]); - break; - } + pos += page_len; - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); + val = scsi_disk_mode_sense_pages_default.pages[page][0] & 0x80; + if (dev->do_page_save && val) + scsi_disk_mode_sense_save(dev); + + if (pos >= dev->total_length) + break; + } + + if (error) + scsi_disk_invalid_field_pl(dev); + break; + default: + fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", dev->id, dev->current_cdb[0]); + break; + } + + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); } + /* If the result is 1, issue an IRQ, otherwise not. */ -void scsi_hd_callback(uint8_t id) +void +scsi_disk_callback(scsi_disk_t *dev) { - switch(shdc[id].packet_status) - { - case CDROM_PHASE_IDLE: - scsi_hd_log("SCSI HD %i: PHASE_IDLE\n", id); - shdc[id].pos=0; - shdc[id].phase = 1; - shdc[id].status = READY_STAT | DRQ_STAT | (shdc[id].status & ERR_STAT); - return; - case CDROM_PHASE_COMPLETE: - scsi_hd_log("SCSI HD %i: PHASE_COMPLETE\n", id); - shdc[id].status = READY_STAT; - shdc[id].phase = 3; - shdc[id].packet_status = 0xFF; - ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); - return; - case CDROM_PHASE_DATA_OUT: - scsi_hd_log("SCSI HD %i: PHASE_DATA_OUT\n", id); - shdc[id].status = READY_STAT | DRQ_STAT | (shdc[id].status & ERR_STAT); - shdc[id].phase = 0; - return; - case CDROM_PHASE_DATA_OUT_DMA: - scsi_hd_log("SCSI HD %i: PHASE_DATA_OUT_DMA\n", id); - scsi_hd_phase_data_out(id); - shdc[id].packet_status = CDROM_PHASE_COMPLETE; - shdc[id].status = READY_STAT; - shdc[id].phase = 3; - ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); - return; - case CDROM_PHASE_DATA_IN: - scsi_hd_log("SCSI HD %i: PHASE_DATA_IN\n", id); - shdc[id].status = READY_STAT | DRQ_STAT | (shdc[id].status & ERR_STAT); - shdc[id].phase = 2; - return; - case CDROM_PHASE_DATA_IN_DMA: - scsi_hd_log("SCSI HD %i: PHASE_DATA_IN_DMA\n", id); - scsi_hd_phase_data_in(id); - shdc[id].packet_status = CDROM_PHASE_COMPLETE; - shdc[id].status = READY_STAT; - shdc[id].phase = 3; - ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); - return; - case CDROM_PHASE_ERROR: - scsi_hd_log("SCSI HD %i: PHASE_ERROR\n", id); - shdc[id].status = READY_STAT | ERR_STAT; - shdc[id].phase = 3; - return; - } + switch(dev->packet_status) { + case CDROM_PHASE_IDLE: + scsi_disk_log("SCSI HD %i: PHASE_IDLE\n", dev->id); + dev->phase = 1; + dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); + return; + case CDROM_PHASE_COMPLETE: + scsi_disk_log("SCSI HD %i: PHASE_COMPLETE\n", dev->id); + dev->status = READY_STAT; + dev->phase = 3; + dev->packet_status = 0xFF; + return; + case CDROM_PHASE_DATA_OUT_DMA: + scsi_disk_log("SCSI HD %i: PHASE_DATA_OUT_DMA\n", dev->id); + scsi_disk_phase_data_out(dev); + dev->packet_status = CDROM_PHASE_COMPLETE; + dev->status = READY_STAT; + dev->phase = 3; + return; + case CDROM_PHASE_DATA_IN_DMA: + scsi_disk_log("SCSI HD %i: PHASE_DATA_IN_DMA\n", dev->id); + scsi_disk_phase_data_in(dev); + dev->packet_status = CDROM_PHASE_COMPLETE; + dev->status = READY_STAT; + dev->phase = 3; + return; + case CDROM_PHASE_ERROR: + scsi_disk_log("SCSI HD %i: PHASE_ERROR\n", dev->id); + dev->status = READY_STAT | ERR_STAT; + dev->phase = 3; + return; + } +} + + +/* Peform a master init on the entire module. */ +void +scsi_disk_global_init(void) +{ + /* Clear the global data. */ + memset(scsi_disk, 0x00, sizeof(scsi_disk)); +} + + +void +scsi_disk_hard_reset(void) +{ + int c; + + for (c = 0; c < HDD_NUM; c++) { + if (hdd[c].bus == HDD_BUS_SCSI) { + scsi_disk_log("SCSI disk hard_reset drive=%d\n", c); + + if (!scsi_disk[c]) { + scsi_disk[c] = (scsi_disk_t *) malloc(sizeof(scsi_disk_t)); + memset(scsi_disk[c], 0, sizeof(scsi_disk_t)); + } + + scsi_disk[c]->id = c; + scsi_disk[c]->drv = &hdd[c]; + + scsi_disk_mode_sense_load(scsi_disk[c]); + } + } +} + + +void +scsi_disk_close(void) +{ + scsi_disk_t *dev; + int c; + + for (c = 0; c < HDD_NUM; c++) { + dev = scsi_disk[c]; + + if (dev) { + hdd_image_close(c); + + free(scsi_disk[c]); + scsi_disk[c] = NULL; + } + } } diff --git a/src/scsi/scsi_disk.h b/src/scsi/scsi_disk.h index 5a1a48c4f..36898f266 100644 --- a/src/scsi/scsi_disk.h +++ b/src/scsi/scsi_disk.h @@ -6,66 +6,55 @@ * * Emulation of SCSI fixed and removable disks. * - * Version: @(#)scsi_disk.h 1.0.3 2017/10/14 + * Version: @(#)scsi_disk.h 1.0.5 2018/06/02 * * Author: Miran Grca, - * Copyright 2017 Miran Grca. + * Copyright 2017,2018 Miran Grca. */ typedef struct { - /* Stuff for SCSI hard disks. */ - uint8_t cdb[16]; - uint8_t current_cdb[16]; - uint8_t max_cdb_len; - int requested_blocks; - int max_blocks_at_once; - uint16_t request_length; - int block_total; - int all_blocks_total; - uint32_t packet_len; - int packet_status; - uint8_t status; - uint8_t phase; - uint32_t pos; - int callback; - int total_read; - int unit_attention; - uint8_t sense[256]; - uint8_t previous_command; - uint8_t error; - uint32_t sector_pos; - uint32_t sector_len; - uint32_t seek_pos; - int data_pos; - int old_len; - int request_pos; - uint8_t hd_cdb[16]; + mode_sense_pages_t ms_pages_saved; - uint64_t current_page_code; - int current_page_len; + hard_disk_t *drv; - int current_page_pos; + /* Stuff for SCSI hard disks. */ + uint8_t status, phase, + error, id, + current_cdb[16], + sense[256]; - int mode_select_phase; + uint16_t request_length; - int total_length; - int written_length; + int requested_blocks, block_total, + packet_status, callback, + block_descriptor_len, + total_length, do_page_save; - int do_page_save; - int block_descriptor_len; + uint32_t sector_pos, sector_len, + packet_len; - uint8_t *temp_buffer; -} scsi_hard_disk_t; + uint64_t current_page_code; + + uint8_t *temp_buffer; +} scsi_disk_t; -extern scsi_hard_disk_t shdc[HDD_NUM]; -extern FILE *shdf[HDD_NUM]; +extern scsi_disk_t *scsi_disk[HDD_NUM]; +extern uint8_t scsi_disks[16]; -extern void scsi_disk_insert(uint8_t id); -extern void scsi_loadhd(int scsi_id, int scsi_lun, int id); -extern void scsi_reloadhd(int id); -extern void scsi_unloadhd(int scsi_id, int scsi_lun, int id); +extern void scsi_loadhd(int scsi_id, int id); +extern void scsi_disk_global_init(void); +extern void scsi_disk_hard_reset(void); +extern void scsi_disk_close(void); -int scsi_hd_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len); +extern int scsi_disk_read_capacity(scsi_disk_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len); +extern int scsi_disk_err_stat_to_scsi(scsi_disk_t *dev); +extern int scsi_disk_phase_to_scsi(scsi_disk_t *dev); +extern int find_hdd_for_scsi_id(uint8_t scsi_id); +extern void build_scsi_disk_map(void); +extern void scsi_disk_reset(scsi_disk_t *dev); +extern void scsi_disk_request_sense_for_scsi(scsi_disk_t *dev, uint8_t *buffer, uint8_t alloc_length); +extern void scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb); +extern void scsi_disk_callback(scsi_disk_t *dev); diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index fd88997c4..e67407cd9 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -9,7 +9,7 @@ * Implementation of the NCR 5380 series of SCSI Host Adapters * made by NCR. These controllers were designed for the ISA bus. * - * Version: @(#)scsi_ncr5380.c 1.0.12 2018/03/18 + * Version: @(#)scsi_ncr5380.c 1.0.15 2018/06/13 * * Authors: Sarah Walker, * TheCollector1995, @@ -34,8 +34,8 @@ #include "../mca.h" #include "../mem.h" #include "../rom.h" -#include "../nvr.h" #include "../device.h" +#include "../nvr.h" #include "../timer.h" #include "../plat.h" #include "scsi.h" @@ -290,7 +290,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv) default: #if 1 - pclog("NCR5380: bad write %04x %02x\n", port, val); + ncr_log("NCR5380: bad write %04x %02x\n", port, val); #endif break; } @@ -496,7 +496,7 @@ dma_callback(void *priv) default: #if 1 - pclog("DMA callback bad mode %i\n", scsi->ncr.dma_mode); + ncr_log("DMA callback bad mode %i\n", scsi->ncr.dma_mode); #endif break; } @@ -668,9 +668,12 @@ t130b_read(uint32_t addr, void *priv) uint8_t ret = 0xff; addr &= 0x3fff; - if (addr < 0x1800) + if ((addr < 0x1800) && scsi->rom_addr) ret = scsi->bios_rom.rom[addr & 0x1fff]; else + if ((addr < 0x1800) && !scsi->rom_addr) + ret = 0xff; + else if (addr < 0x1880) ret = scsi->ext_ram[addr & 0x7f]; @@ -849,47 +852,79 @@ ncr_init(const device_t *info) break; case 1: /* Ranco RT1000B */ - scsi->rom_addr = 0xDC000; - rom_init(&scsi->bios_rom, RT1000B_ROM, - scsi->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + scsi->base = device_get_config_hex16("base"); + scsi->rom_addr = device_get_config_hex20("bios_addr"); - mem_mapping_disable(&scsi->bios_rom.mapping); + if (scsi->rom_addr) { + rom_init(&scsi->bios_rom, RT1000B_ROM, + scsi->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + mem_mapping_disable(&scsi->bios_rom.mapping); + } else { + scsi->bios_rom.rom = (uint8_t *) malloc(0x4000); + memset(scsi->bios_rom.rom, 0xff, 0x4000); + } mem_mapping_add(&scsi->mapping, scsi->rom_addr, 0x4000, memio_read, NULL, NULL, memio_write, NULL, NULL, scsi->bios_rom.rom, 0, scsi); + + if (scsi->base) { + io_sethandler(scsi->base, 16, + t130b_in,NULL,NULL, t130b_out,NULL,NULL, scsi); + } break; case 2: /* Trantor T130B */ - scsi->rom_addr = 0xDC000; - scsi->base = 0x0350; - rom_init(&scsi->bios_rom, T130B_ROM, - scsi->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + scsi->base = device_get_config_hex16("base"); + scsi->rom_addr = device_get_config_hex20("bios_addr"); + + if (scsi->rom_addr) { + rom_init(&scsi->bios_rom, T130B_ROM, + scsi->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + mem_mapping_disable(&scsi->bios_rom.mapping); + } else { + scsi->bios_rom.rom = (uint8_t *) malloc(0x4000); + memset(scsi->bios_rom.rom, 0xff, 0x4000); + } mem_mapping_add(&scsi->mapping, scsi->rom_addr, 0x4000, t130b_read, NULL, NULL, t130b_write, NULL, NULL, scsi->bios_rom.rom, 0, scsi); - io_sethandler(scsi->base, 16, - t130b_in,NULL,NULL, t130b_out,NULL,NULL, scsi); + if (scsi->base) { + io_sethandler(scsi->base, 16, + t130b_in,NULL,NULL, t130b_out,NULL,NULL, scsi); + } break; case 3: /* Sumo SCSI-AT */ scsi->base = device_get_config_hex16("base"); scsi->irq = device_get_config_int("irq"); scsi->rom_addr = device_get_config_hex20("bios_addr"); - rom_init(&scsi->bios_rom, SCSIAT_ROM, - scsi->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + if (scsi->rom_addr) { + rom_init(&scsi->bios_rom, SCSIAT_ROM, + scsi->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + + mem_mapping_disable(&scsi->bios_rom.mapping); + } else { + scsi->bios_rom.rom = (uint8_t *) malloc(0x4000); + memset(scsi->bios_rom.rom, 0xff, 0x4000); + } mem_mapping_add(&scsi->mapping, scsi->rom_addr, 0x4000, t130b_read, NULL, NULL, t130b_write, NULL, NULL, scsi->bios_rom.rom, 0, scsi); - io_sethandler(scsi->base, 16, - scsiat_in,NULL,NULL, scsiat_out,NULL,NULL, scsi); + if (scsi->base) { + io_sethandler(scsi->base, 16, + scsiat_in,NULL,NULL, scsiat_out,NULL,NULL, scsi); + } break; } @@ -898,7 +933,7 @@ ncr_init(const device_t *info) sprintf(&temp[strlen(temp)], " I/O=%04x", scsi->base); if (scsi->irq != 0) sprintf(&temp[strlen(temp)], " IRQ=%d", scsi->irq); - pclog("%s\n", temp); + ncr_log("%s\n", temp); ncr5380_reset(&scsi->ncr); @@ -948,6 +983,59 @@ scsiat_available(void) } +static const device_config_t ncr5380_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x0350, + { + { + "None", 0 + }, + { + "240H", 0x0240 + }, + { + "250H", 0x0250 + }, + { + "340H", 0x0340 + }, + { + "350H", 0x0350 + }, + { + "" + } + }, + }, + { + "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xDC000, + { + { + "Disabled", 0 + }, + { + "C800H", 0xc8000 + }, + { + "CC00H", 0xcc000 + }, + { + "D800H", 0xd8000 + }, + { + "DC00H", 0xdc000 + }, + { + "" + } + }, + }, + { + "", "", -1 + } +}; + + static const device_config_t scsiat_config[] = { { "base", "Address", CONFIG_HEX16, "", 0x0310, @@ -1052,7 +1140,7 @@ const device_t scsi_lcs6821n_device = 0, ncr_init, ncr_close, NULL, lcs6821n_available, - NULL, NULL, NULL, + NULL, NULL, NULL }; @@ -1063,8 +1151,8 @@ const device_t scsi_rt1000b_device = 1, ncr_init, ncr_close, NULL, rt1000b_available, - NULL, NULL, NULL, - NULL + NULL, NULL, + ncr5380_config }; const device_t scsi_t130b_device = @@ -1074,8 +1162,8 @@ const device_t scsi_t130b_device = 2, ncr_init, ncr_close, NULL, t130b_available, - NULL, NULL, NULL, - NULL + NULL, NULL, + ncr5380_config }; const device_t scsi_scsiat_device = @@ -1085,6 +1173,6 @@ const device_t scsi_scsiat_device = 3, ncr_init, ncr_close, NULL, scsiat_available, - NULL, NULL, NULL, + NULL, NULL, scsiat_config }; diff --git a/src/scsi/scsi_ncr53c810.c b/src/scsi/scsi_ncr53c810.c index 0dcb1fced..459ca28fd 100644 --- a/src/scsi/scsi_ncr53c810.c +++ b/src/scsi/scsi_ncr53c810.c @@ -10,7 +10,7 @@ * NCR and later Symbios and LSI. This controller was designed * for the PCI bus. * - * Version: @(#)scsi_ncr53c810.c 1.0.10 2018/03/18 + * Version: @(#)scsi_ncr53c810.c 1.0.14 2018/05/28 * * Authors: Paul Brook (QEMU) * Artyom Tarasenko (QEMU) @@ -22,11 +22,12 @@ * Copyright 2017,2018 Miran Grca. */ #include +#include #include #include -#include #include -#include +#include +#define HAVE_STDARG_H #include #include "../86box.h" #include "../io.h" @@ -35,14 +36,16 @@ #include "../mem.h" #include "../rom.h" #include "../pci.h" -#include "../nvr.h" #include "../device.h" +#include "../nvr.h" #include "../timer.h" #include "../plat.h" #include "scsi.h" #include "scsi_device.h" #include "scsi_ncr53c810.h" +#define NCR53C810_ROM L"roms/scsi/ncr53c810/NCR307.BIN" + #define NCR_SCNTL0_TRG 0x01 #define NCR_SCNTL0_AAP 0x02 #define NCR_SCNTL0_EPC 0x08 @@ -187,6 +190,8 @@ typedef enum typedef struct { uint8_t pci_slot; + int has_bios; + rom_t bios; int PCIBase; int MMIOBase; mem_mapping_t mmio_mapping; @@ -329,6 +334,8 @@ ncr53c810_irq_on_rsl(ncr53c810_t *dev) static void ncr53c810_soft_reset(ncr53c810_t *dev) { + int i; + ncr53c810_log("LSI Reset\n"); dev->timer_period = dev->timer_enabled = 0; @@ -383,13 +390,16 @@ ncr53c810_soft_reset(ncr53c810_t *dev) dev->last_level = 0; dev->gpreg0 = 0; dev->sstop = 1; + + for (i = 0; i < 16; i++) + scsi_device_reset(i); } static void ncr53c810_read(ncr53c810_t *dev, uint32_t addr, uint8_t *buf, uint32_t len) { - int i = 0; + uint32_t i = 0; ncr53c810_log("ncr53c810_read(): %08X-%08X, length %i\n", addr, (addr + len - 1), len); @@ -407,7 +417,7 @@ ncr53c810_read(ncr53c810_t *dev, uint32_t addr, uint8_t *buf, uint32_t len) static void ncr53c810_write(ncr53c810_t *dev, uint32_t addr, uint8_t *buf, uint32_t len) { - int i = 0; + uint32_t i = 0; ncr53c810_log("ncr53c810_write(): %08X-%08X, length %i\n", addr, (addr + len - 1), len); @@ -582,13 +592,14 @@ ncr53c810_command_complete(void *priv, uint32_t status) static void ncr53c810_do_dma(ncr53c810_t *dev, int out, uint8_t id) { - uint32_t addr, count, tdbc; + uint32_t addr, tdbc; + int count; scsi_device_t *sd; - sd = &SCSIDevices[id][dev->current_lun]; + sd = &SCSIDevices[id]; - if ((((id) == -1) && !scsi_device_present(id, dev->current_lun))) { + if ((!scsi_device_present(id))) { ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Device not present when attempting to do DMA\n", id, dev->current_lun, dev->last_command); return; } @@ -615,7 +626,7 @@ ncr53c810_do_dma(ncr53c810_t *dev, int out, uint8_t id) else { if (!dev->buffer_pos) { ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DI\n", id, dev->current_lun, dev->last_command); - scsi_device_command_phase1(dev->current->tag, dev->current_lun); + scsi_device_command_phase1(dev->current->tag); } ncr53c810_write(dev, addr, sd->CmdBuffer+dev->buffer_pos, count); } @@ -626,7 +637,7 @@ ncr53c810_do_dma(ncr53c810_t *dev, int out, uint8_t id) if (dev->temp_buf_len <= 0) { if (out) { ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DO\n", id, dev->current_lun, dev->last_command); - scsi_device_command_phase1(id, dev->current_lun); + scsi_device_command_phase1(id); } if (sd->CmdBuffer != NULL) { free(sd->CmdBuffer); @@ -672,8 +683,8 @@ ncr53c810_do_command(ncr53c810_t *dev, uint8_t id) dev->sfbr = buf[0]; dev->command_complete = 0; - sd = &SCSIDevices[id][dev->current_lun]; - if (((id == -1) || !scsi_device_present(id, dev->current_lun))) { + sd = &SCSIDevices[id]; + if (!scsi_device_present(id)) { ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Bad Selection\n", id, dev->current_lun, buf[0]); ncr53c810_bad_selection(dev, id); return 0; @@ -687,7 +698,7 @@ ncr53c810_do_command(ncr53c810_t *dev, uint8_t id) ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DBC=%i\n", id, dev->current_lun, buf[0], dev->dbc); dev->last_command = buf[0]; - scsi_device_command_phase0(dev->current->tag, dev->current_lun, dev->dbc, buf); + scsi_device_command_phase0(dev->current->tag, buf); dev->hba_private = (void *)dev->current; dev->waiting = 0; @@ -703,7 +714,7 @@ ncr53c810_do_command(ncr53c810_t *dev, uint8_t id) if ((sd->Phase == SCSI_PHASE_DATA_IN) && (sd->BufferLength > 0)) { ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DI\n", id, dev->current_lun, buf[0]); ncr53c810_set_phase(dev, PHASE_DI); - p = scsi_device_get_callback(dev->current->tag, dev->current_lun); + p = scsi_device_get_callback(dev->current->tag); if (p <= 0LL) { period = ((double) sd->BufferLength) * 0.1 * ((double) TIMER_USEC); /* Fast SCSI: 10000000 bytes per second */ dev->timer_period += (int64_t) period; @@ -711,9 +722,9 @@ ncr53c810_do_command(ncr53c810_t *dev, uint8_t id) dev->timer_period += p; return 1; } else if ((sd->Phase == SCSI_PHASE_DATA_OUT) && (sd->BufferLength > 0)) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DO\n", id, dev->current_lun, buf[0]); + ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DO\n", id, buf[0]); ncr53c810_set_phase(dev, PHASE_DO); - p = scsi_device_get_callback(dev->current->tag, dev->current_lun); + p = scsi_device_get_callback(dev->current->tag); if (p <= 0LL) { period = ((double) sd->BufferLength) * 0.1 * ((double) TIMER_USEC); /* Fast SCSI: 10000000 bytes per second */ dev->timer_period += (int64_t) period; @@ -747,7 +758,7 @@ ncr53c810_do_status(ncr53c810_t *dev) static void ncr53c810_do_msgin(ncr53c810_t *dev) { - int len; + uint32_t len; ncr53c810_log("Message in len=%d/%d\n", dev->dbc, dev->msg_len); dev->sfbr = dev->msg[0]; len = dev->msg_len; @@ -821,7 +832,7 @@ ncr53c810_do_msgout(ncr53c810_t *dev, uint8_t id) uint32_t current_tag; scsi_device_t *sd; - sd = &SCSIDevices[id][dev->current_lun]; + sd = &SCSIDevices[id]; current_tag = id; @@ -1067,7 +1078,7 @@ again: } dev->sstat0 |= NCR_SSTAT0_WOA; dev->scntl1 &= ~NCR_SCNTL1_IARB; - if (((id == -1) || !scsi_device_present(id, 0))) { + if (!scsi_device_present(id)) { ncr53c810_bad_selection(dev, id); break; } @@ -1086,8 +1097,12 @@ again: break; case 2: /* Wait Reselect */ ncr53c810_log("Wait Reselect\n"); - if (!ncr53c810_irq_on_rsl(dev)) - dev->waiting = 1; + if (dev->istat & NCR_ISTAT_SIGP) + dev->dsp = dev->dnad; /* If SIGP is set, this command causes an immediate jump to DNAD. */ + else { + if (!ncr53c810_irq_on_rsl(dev)) + dev->waiting = 1; + } break; case 3: /* Set */ ncr53c810_log("Set%s%s%s%s\n", insn & (1 << 3) ? " ATN" : "", @@ -1450,7 +1465,7 @@ ncr53c810_reg_writeb(ncr53c810_t *dev, uint32_t offset, uint8_t val) ncr53c810_update_irq(dev); } - if (dev->waiting == 1 && val & NCR_ISTAT_SIGP) { + if ((dev->waiting == 1) && (val & NCR_ISTAT_SIGP)) { ncr53c810_log("Woken by SIGP\n"); dev->waiting = 0; dev->dsp = dev->dnad; @@ -1656,7 +1671,8 @@ ncr53c810_reg_readb(ncr53c810_t *dev, uint32_t offset) CASE_GET_REG32(dsa, 0x10) case 0x14: /* ISTAT */ ncr53c810_log("NCR 810: Read ISTAT %02X\n", dev->istat); - return dev->istat; + tmp = dev->istat; + return tmp; case 0x16: /* MBOX0 */ ncr53c810_log("NCR 810: Read MBOX0 %02X\n", dev->mbox0); return dev->mbox0; @@ -1977,9 +1993,8 @@ ncr53c810_pci_read(int func, int addr, void *p) ncr53c810_log("NCR53c810: Reading register %02X\n", addr & 0xff); - if ((addr >= 0x80) && (addr <= 0xDF)) { + if ((addr >= 0x80) && (addr <= 0xDF)) return ncr53c810_reg_readb(dev, addr & 0x7F); - } switch (addr) { case 0x00: @@ -2155,6 +2170,12 @@ ncr53c810_init(const device_t *info) timer_add(ncr53c810_callback, &dev->timer_period, &dev->timer_enabled, dev); + dev->has_bios = device_get_config_int("bios"); + + /* Enable our BIOS space in PCI, if needed. */ + if (dev->has_bios) + rom_init(&dev->bios, NCR53C810_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + return(dev); } @@ -2171,13 +2192,22 @@ ncr53c810_close(void *priv) } +static const device_config_t ncr53c810_pci_config[] = { + { + "bios", "Enable BIOS", CONFIG_BINARY, "", 0 + }, + { + "", "", -1 + } +}; + + const device_t ncr53c810_pci_device = { "NCR 53c810 (SCSI)", DEVICE_PCI, 0, ncr53c810_init, ncr53c810_close, NULL, - NULL, NULL, NULL, NULL, - NULL + ncr53c810_pci_config }; diff --git a/src/scsi/scsi_x54x.c b/src/scsi/scsi_x54x.c index 10f27249f..e8c334eab 100644 --- a/src/scsi/scsi_x54x.c +++ b/src/scsi/scsi_x54x.c @@ -11,7 +11,7 @@ * series of SCSI Host Adapters made by Mylex. * These controllers were designed for various buses. * - * Version: @(#)scsi_x54x.c 1.0.20 2018/03/18 + * Version: @(#)scsi_x54x.c 1.0.21 2018/06/12 * * Authors: TheCollector1995, * Miran Grca, @@ -36,8 +36,8 @@ #include "../mca.h" #include "../mem.h" #include "../rom.h" -#include "../nvr.h" #include "../device.h" +#include "../nvr.h" #include "../timer.h" #include "../plat.h" #include "../cpu/cpu.h" @@ -90,24 +90,21 @@ x54x_irq(x54x_t *dev, int set) if (dev->bus & DEVICE_PCI) { x54x_log("PCI IRQ: %02X, PCI_INTA\n", dev->pci_slot); - if (set) { + if (set) pci_set_irq(dev->pci_slot, PCI_INTA); - } else { + else pci_clear_irq(dev->pci_slot, PCI_INTA); - } } else { if (set) { if (dev->interrupt_type) int_type = dev->interrupt_type(dev); - if (int_type) { + if (int_type) picintlevel(1 << irq); - } else { + else picint(1 << irq); - } - } else { + } else picintc(1 << irq); - } } } @@ -157,10 +154,10 @@ clear_irq(x54x_t *dev) static void -target_check(uint8_t id, uint8_t lun) +target_check(uint8_t id) { - if (! scsi_device_valid(id, lun)) { - fatal("BIOS INT13 device on %02i:%02i has disappeared\n", id, lun); + if (! scsi_device_valid(id)) { + fatal("BIOS INT13 device on ID %02i has disappeared\n", id); } } @@ -235,15 +232,15 @@ completion_code(uint8_t *sense) static uint8_t -x54x_bios_command_08(uint8_t id, uint8_t lun, uint8_t *buffer) +x54x_bios_command_08(uint8_t id, uint8_t *buffer) { uint8_t cdb[12] = { GPCMD_READ_CDROM_CAPACITY, 0,0,0,0,0,0,0,0,0,0,0 }; uint8_t rcbuf[8] = { 0,0,0,0,0,0,0,0 }; uint32_t len = 0; int i, ret, sc; - ret = scsi_device_read_capacity(id, lun, cdb, rcbuf, &len); - sc = completion_code(scsi_device_sense(id, lun)); + ret = scsi_device_read_capacity(id, cdb, rcbuf, &len); + sc = completion_code(scsi_device_sense(id)); if (ret == 0) return(sc); memset(buffer, 0x00, 6); @@ -259,21 +256,21 @@ x54x_bios_command_08(uint8_t id, uint8_t lun, uint8_t *buffer) static int -x54x_bios_command_15(uint8_t id, uint8_t lun, uint8_t *buffer) +x54x_bios_command_15(uint8_t id, uint8_t *buffer) { uint8_t cdb[12] = { GPCMD_READ_CDROM_CAPACITY, 0,0,0,0,0,0,0,0,0,0,0 }; uint8_t rcbuf[8] = { 0,0,0,0,0,0,0,0 }; uint32_t len = 0; int i, ret, sc; - ret = scsi_device_read_capacity(id, lun, cdb, rcbuf, &len); - sc = completion_code(scsi_device_sense(id, lun)); + ret = scsi_device_read_capacity(id, cdb, rcbuf, &len); + sc = completion_code(scsi_device_sense(id)); memset(buffer, 0x00, 6); for (i=0; i<4; i++) buffer[i] = (ret == 0) ? 0 : rcbuf[i]; - scsi_device_type_data(id, lun, &(buffer[4]), &(buffer[5])); + scsi_device_type_data(id, &(buffer[4]), &(buffer[5])); x54x_log("BIOS Command 0x15: %02X %02X %02X %02X %02X %02X\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); @@ -306,19 +303,22 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) return(0x80); } + if (cmd->lun) { + x54x_log("BIOS Target LUN is not 0\n"); + return(0x80); + } + /* Get pointer to selected device. */ - dev = &SCSIDevices[cmd->id][cmd->lun]; + dev = &SCSIDevices[cmd->id]; dev->BufferLength = 0; - if (! scsi_device_present(cmd->id, cmd->lun)) { - x54x_log("BIOS Target ID %i and LUN %i have no device attached\n", - cmd->id, cmd->lun); + if (! scsi_device_present(cmd->id)) { + x54x_log("BIOS Target ID %i has no device attached\n", cmd->id); return(0x80); } if ((dev->LunType == SCSI_CDROM) && !x54x->cdrom_boot) { - x54x_log("BIOS Target ID %i and LUN %i is CD-ROM on unsupported BIOS\n", - cmd->id, cmd->lun); + x54x_log("BIOS Target ID %i is CD-ROM on unsupported BIOS\n", cmd->id); return(0x80); } @@ -337,7 +337,7 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) return(0); case 0x01: /* Read Status of Last Operation */ - target_check(cmd->id, cmd->lun); + target_check(cmd->id); /* * Assuming 14 bytes because that is the default @@ -352,7 +352,7 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) x54x_log("BIOS DMA: Reading 14 bytes at %08X\n", dma_address); DMAPageWrite(dma_address, - scsi_device_sense(cmd->id, cmd->lun), 14); + scsi_device_sense(cmd->id), 14); } if (dev->CmdBuffer != NULL) { @@ -363,7 +363,7 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) return(0); case 0x02: /* Read Desired Sectors to Memory */ - target_check(cmd->id, cmd->lun); + target_check(cmd->id); dev->BufferLength = -1; @@ -379,14 +379,14 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) x54x_log("BIOS CMD(READ, %08lx, %d)\n", lba, cmd->secount); #endif - scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + scsi_device_command_phase0(cmd->id, cdb); if (dev->Phase == SCSI_PHASE_STATUS) goto skip_read_phase1; dev->CmdBuffer = (uint8_t *)malloc(dev->BufferLength); - scsi_device_command_phase1(cmd->id, cmd->lun); + scsi_device_command_phase1(cmd->id); if (sector_len > 0) { x54x_log("BIOS DMA: Reading %i bytes at %08X\n", dev->BufferLength, dma_address); @@ -400,10 +400,10 @@ skip_read_phase1: dev->CmdBuffer = NULL; } - return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); + return(completion_code(scsi_device_sense(cmd->id))); case 0x03: /* Write Desired Sectors from Memory */ - target_check(cmd->id, cmd->lun); + target_check(cmd->id); dev->BufferLength = -1; @@ -419,7 +419,7 @@ skip_read_phase1: x54x_log("BIOS CMD(WRITE, %08lx, %d)\n", lba, cmd->secount); #endif - scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + scsi_device_command_phase0(cmd->id, cdb); if (dev->Phase == SCSI_PHASE_STATUS) goto skip_write_phase1; @@ -433,7 +433,7 @@ skip_read_phase1: dev->CmdBuffer, dev->BufferLength); } - scsi_device_command_phase1(cmd->id, cmd->lun); + scsi_device_command_phase1(cmd->id); skip_write_phase1: if (dev->CmdBuffer != NULL) { @@ -441,10 +441,10 @@ skip_write_phase1: dev->CmdBuffer = NULL; } - return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); + return(completion_code(scsi_device_sense(cmd->id))); case 0x04: /* Verify Desired Sectors */ - target_check(cmd->id, cmd->lun); + target_check(cmd->id); cdb[0] = GPCMD_VERIFY_10; cdb[1] = (cmd->lun & 7) << 5; @@ -455,9 +455,9 @@ skip_write_phase1: cdb[7] = 0; cdb[8] = sector_len; - scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + scsi_device_command_phase0(cmd->id, cdb); - return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); + return(completion_code(scsi_device_sense(cmd->id))); case 0x05: /* Format Track, invalid since SCSI has no tracks */ //FIXME: add a longer delay here --FvK @@ -468,23 +468,23 @@ skip_write_phase1: return(0); case 0x07: /* Format Unit */ - target_check(cmd->id, cmd->lun); + target_check(cmd->id); cdb[0] = GPCMD_FORMAT_UNIT; cdb[1] = (cmd->lun & 7) << 5; - scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + scsi_device_command_phase0(cmd->id, cdb); - return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); + return(completion_code(scsi_device_sense(cmd->id))); case 0x08: /* Read Drive Parameters */ - target_check(cmd->id, cmd->lun); + target_check(cmd->id); dev->BufferLength = 6; dev->CmdBuffer = (uint8_t *)malloc(dev->BufferLength); memset(dev->CmdBuffer, 0x00, dev->BufferLength); - ret = x54x_bios_command_08(cmd->id, cmd->lun, dev->CmdBuffer); + ret = x54x_bios_command_08(cmd->id, dev->CmdBuffer); x54x_log("BIOS DMA: Reading 6 bytes at %08X\n", dma_address); DMAPageWrite(dma_address, @@ -502,7 +502,7 @@ skip_write_phase1: return(0); case 0x0c: /* Seek */ - target_check(cmd->id, cmd->lun); + target_check(cmd->id); cdb[0] = GPCMD_SEEK_10; cdb[1] = (cmd->lun & 7) << 5; @@ -511,7 +511,7 @@ skip_write_phase1: cdb[4] = (lba >> 8) & 0xff; cdb[5] = lba & 0xff; - scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + scsi_device_command_phase0(cmd->id, cdb); return((dev->Status == SCSI_STATUS_OK) ? 1 : 0); @@ -520,37 +520,37 @@ skip_write_phase1: return(0); case 0x10: /* Test Drive Ready */ - target_check(cmd->id, cmd->lun); + target_check(cmd->id); cdb[0] = GPCMD_TEST_UNIT_READY; cdb[1] = (cmd->lun & 7) << 5; - scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + scsi_device_command_phase0(cmd->id, cdb); - return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); + return(completion_code(scsi_device_sense(cmd->id))); case 0x11: /* Recalibrate */ - target_check(cmd->id, cmd->lun); + target_check(cmd->id); cdb[0] = GPCMD_REZERO_UNIT; cdb[1] = (cmd->lun & 7) << 5; - scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + scsi_device_command_phase0(cmd->id, cdb); - return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); + return(completion_code(scsi_device_sense(cmd->id))); case 0x14: /* Controller Diagnostic */ //FIXME: add a longer delay here --FvK return(0); case 0x15: /* Read DASD Type */ - target_check(cmd->id, cmd->lun); + target_check(cmd->id); dev->BufferLength = 6; dev->CmdBuffer = (uint8_t *)malloc(dev->BufferLength); memset(dev->CmdBuffer, 0x00, dev->BufferLength); - ret = x54x_bios_command_15(cmd->id, cmd->lun, dev->CmdBuffer); + ret = x54x_bios_command_15(cmd->id, dev->CmdBuffer); x54x_log("BIOS DMA: Reading 6 bytes at %08X\n", dma_address); DMAPageWrite(dma_address, @@ -720,8 +720,7 @@ x54x_get_length(Req_t *req, int Is24bit) uint32_t DataPointer, DataLength; uint32_t SGEntryLength = (Is24bit ? sizeof(SGE) : sizeof(SGE32)); SGE32 SGBuffer; - uint32_t DataToTransfer = 0; - int i = 0; + uint32_t DataToTransfer = 0, i = 0; if (Is24bit) { DataPointer = ADDR_TO_U32(req->CmdBlock.old.DataPointer); @@ -763,7 +762,7 @@ x54x_set_residue(Req_t *req, int32_t TransferLength) { uint32_t Residue = 0; addr24 Residue24; - int32_t BufLen = SCSIDevices[req->TargetID][req->LUN].BufferLength; + int32_t BufLen = SCSIDevices[req->TargetID].BufferLength; if ((req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) || (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) { @@ -793,9 +792,8 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir) { uint32_t DataPointer, DataLength; uint32_t SGEntryLength = (Is24bit ? sizeof(SGE) : sizeof(SGE32)); - uint32_t Address; - int i = 0; - int32_t BufLen = SCSIDevices[req->TargetID][req->LUN].BufferLength; + uint32_t Address, i; + int32_t BufLen = SCSIDevices[req->TargetID].BufferLength; uint8_t read_from_host = (dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) || (req->CmdBlock.common.ControlByte == 0x00))); uint8_t write_to_host = (!dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) || (req->CmdBlock.common.ControlByte == 0x00))); int sg_pos = 0; @@ -809,8 +807,8 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir) DataPointer = req->CmdBlock.new.DataPointer; DataLength = req->CmdBlock.new.DataLength; } - x54x_log("Data Buffer %s: length %d, pointer 0x%04X\n", - dir ? "write" : "read", BufLen, DataPointer); + x54x_log("Data Buffer %s: length %d (%u), pointer 0x%04X\n", + dir ? "write" : "read", BufLen, DataLength, DataPointer); if ((req->CmdBlock.common.ControlByte != 0x03) && TransferLength && BufLen) { if ((req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND) || @@ -823,15 +821,15 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir) x54x_rd_sge(Is24bit, DataPointer + i, &SGBuffer); Address = SGBuffer.SegmentPointer; - DataToTransfer = MIN(SGBuffer.Segment, BufLen); + DataToTransfer = MIN((int) SGBuffer.Segment, BufLen); if (read_from_host && DataToTransfer) { x54x_log("Reading S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); - DMAPageRead(Address, &(SCSIDevices[req->TargetID][req->LUN].CmdBuffer[sg_pos]), DataToTransfer); + DMAPageRead(Address, &(SCSIDevices[req->TargetID].CmdBuffer[sg_pos]), DataToTransfer); } else if (write_to_host && DataToTransfer) { x54x_log("Writing S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); - DMAPageWrite(Address, &(SCSIDevices[req->TargetID][req->LUN].CmdBuffer[sg_pos]), DataToTransfer); + DMAPageWrite(Address, &(SCSIDevices[req->TargetID].CmdBuffer[sg_pos]), DataToTransfer); } else x54x_log("No action on S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); @@ -851,9 +849,9 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir) if ((DataLength > 0) && (BufLen > 0) && (req->CmdBlock.common.ControlByte < 0x03)) { if (read_from_host) - DMAPageRead(Address, SCSIDevices[req->TargetID][req->LUN].CmdBuffer, MIN(BufLen, DataLength)); + DMAPageRead(Address, SCSIDevices[req->TargetID].CmdBuffer, MIN(BufLen, (int) DataLength)); else if (write_to_host) - DMAPageWrite(Address, SCSIDevices[req->TargetID][req->LUN].CmdBuffer, MIN(BufLen, DataLength)); + DMAPageWrite(Address, SCSIDevices[req->TargetID].CmdBuffer, MIN(BufLen, (int) DataLength)); } } } @@ -861,25 +859,25 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir) void -x54x_buf_alloc(uint8_t id, uint8_t lun, int length) +x54x_buf_alloc(uint8_t id, int length) { - if (SCSIDevices[id][lun].CmdBuffer != NULL) { - free(SCSIDevices[id][lun].CmdBuffer); - SCSIDevices[id][lun].CmdBuffer = NULL; + if (SCSIDevices[id].CmdBuffer != NULL) { + free(SCSIDevices[id].CmdBuffer); + SCSIDevices[id].CmdBuffer = NULL; } x54x_log("Allocating data buffer (%i bytes)\n", length); - SCSIDevices[id][lun].CmdBuffer = (uint8_t *) malloc(length); - memset(SCSIDevices[id][lun].CmdBuffer, 0, length); + SCSIDevices[id].CmdBuffer = (uint8_t *) malloc(length); + memset(SCSIDevices[id].CmdBuffer, 0, length); } void -x54x_buf_free(uint8_t id, uint8_t lun) +x54x_buf_free(uint8_t id) { - if (SCSIDevices[id][lun].CmdBuffer != NULL) { - free(SCSIDevices[id][lun].CmdBuffer); - SCSIDevices[id][lun].CmdBuffer = NULL; + if (SCSIDevices[id].CmdBuffer != NULL) { + free(SCSIDevices[id].CmdBuffer); + SCSIDevices[id].CmdBuffer = NULL; } } @@ -923,7 +921,7 @@ SenseBufferFree(Req_t *req, int Copy) uint8_t temp_sense[256]; if (SenseLength && Copy) { - scsi_device_request_sense(req->TargetID, req->LUN, temp_sense, SenseLength); + scsi_device_request_sense(req->TargetID, temp_sense, SenseLength); /* * The sense address, in 32-bit mode, is located in the @@ -962,11 +960,11 @@ x54x_scsi_cmd(x54x_t *dev) id = req->TargetID; lun = req->LUN; - target_cdb_len = scsi_device_cdb_length(id, lun); + target_cdb_len = 12; target_data_len = x54x_get_length(req, bit24); - if (!scsi_device_valid(id, lun)) - fatal("SCSI target on %02i:%02i has disappeared\n", id, lun); + if (!scsi_device_valid(id)) + fatal("SCSI target on %02i has disappeared\n", id); x54x_log("target_data_len = %i\n", target_data_len); @@ -988,14 +986,14 @@ x54x_scsi_cmd(x54x_t *dev) dev->Residue = 0; - BufLen = scsi_device_get_buf_len(id, lun); + BufLen = scsi_device_get_buf_len(id); *BufLen = target_data_len; - x54x_log("Command buffer: %08X\n", SCSIDevices[id][lun].CmdBuffer); + x54x_log("Command buffer: %08X\n", SCSIDevices[id].CmdBuffer); - scsi_device_command_phase0(id, lun, req->CmdBlock.common.CdbLength, temp_cdb); + scsi_device_command_phase0(id, temp_cdb); - phase = SCSIDevices[id][lun].Phase; + phase = SCSIDevices[id].Phase; x54x_log("Control byte: %02X\n", (req->CmdBlock.common.ControlByte == 0x03)); @@ -1003,46 +1001,46 @@ x54x_scsi_cmd(x54x_t *dev) if ((temp_cdb[0] == 0x03) && (req->CmdBlock.common.ControlByte == 0x03)) { /* Request sense in non-data mode - sense goes to sense buffer. */ *BufLen = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength); - x54x_buf_alloc(id, lun, *BufLen); - scsi_device_command_phase1(id, lun); - if ((SCSIDevices[id][lun].Status != SCSI_STATUS_OK) && (*BufLen > 0)) { + x54x_buf_alloc(id, *BufLen); + scsi_device_command_phase1(id); + if ((SCSIDevices[id].Status != SCSI_STATUS_OK) && (*BufLen > 0)) { SenseBufferAddress = SenseBufferPointer(req); - DMAPageWrite(SenseBufferAddress, SCSIDevices[id][lun].CmdBuffer, *BufLen); + DMAPageWrite(SenseBufferAddress, SCSIDevices[id].CmdBuffer, *BufLen); x54x_add_to_period(*BufLen); } } else { - p = scsi_device_get_callback(id, lun); + p = scsi_device_get_callback(id); if (p <= 0LL) x54x_add_to_period(*BufLen); else dev->media_period += p; - x54x_buf_alloc(id, lun, MIN(target_data_len, *BufLen)); + x54x_buf_alloc(id, MIN(target_data_len, *BufLen)); if (phase == SCSI_PHASE_DATA_OUT) x54x_buf_dma_transfer(req, bit24, target_data_len, 1); - scsi_device_command_phase1(id, lun); + scsi_device_command_phase1(id); if (phase == SCSI_PHASE_DATA_IN) x54x_buf_dma_transfer(req, bit24, target_data_len, 0); - SenseBufferFree(req, (SCSIDevices[id][lun].Status != SCSI_STATUS_OK)); + SenseBufferFree(req, (SCSIDevices[id].Status != SCSI_STATUS_OK)); } } else - SenseBufferFree(req, (SCSIDevices[id][lun].Status != SCSI_STATUS_OK)); + SenseBufferFree(req, (SCSIDevices[id].Status != SCSI_STATUS_OK)); x54x_set_residue(req, target_data_len); - x54x_buf_free(id, lun); + x54x_buf_free(id); x54x_log("Request complete\n"); - if (SCSIDevices[id][lun].Status == SCSI_STATUS_OK) { + if (SCSIDevices[id].Status == SCSI_STATUS_OK) { x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS); - } else if (SCSIDevices[id][lun].Status == SCSI_STATUS_CHECK_CONDITION) { + } else if (SCSIDevices[id].Status == SCSI_STATUS_CHECK_CONDITION) { x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR); } - x54x_log("SCSIDevices[%02i][%02i].Status = %02X\n", id, lun, SCSIDevices[id][lun].Status); + x54x_log("SCSIDevices[%02i].Status = %02X\n", id, SCSIDevices[id].Status); } @@ -1061,7 +1059,6 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32) { Req_t *req = &dev->Req; uint8_t id, lun; - uint8_t max_id = SCSI_ID_MAX-1; /* Fetch data from the Command Control Block. */ DMAPageRead(CCBPointer, (uint8_t *)&req->CmdBlock, sizeof(CCB32)); @@ -1074,7 +1071,7 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32) id = req->TargetID; lun = req->LUN; - if ((id > max_id) || (lun > 7)) { + if ((id > dev->max_id) || (lun > 7)) { x54x_log("SCSI Target ID %i or LUN %i is not valid\n",id,lun); x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR); @@ -1085,10 +1082,10 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32) x54x_log("Scanning SCSI Target ID %i\n", id); - SCSIDevices[id][lun].Status = SCSI_STATUS_OK; + SCSIDevices[id].Status = SCSI_STATUS_OK; /* If there is no device at ID:0, timeout the selection - the LUN is then checked later. */ - if (! scsi_device_present(id, 0)) { + if (! scsi_device_present(id)) { x54x_log("SCSI Target ID %i and LUN %i have no device attached\n",id,lun); x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR); @@ -1110,12 +1107,14 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32) } if (req->CmdBlock.common.Opcode == 0x81) { x54x_log("Bus reset opcode\n"); + scsi_device_reset(id); x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS); x54x_log("%s: Callback: Send incoming mailbox\n", dev->name); x54x_notify(dev); return; } + if (req->CmdBlock.common.ControlByte > 0x03) { x54x_log("Invalid control byte: %02X\n", req->CmdBlock.common.ControlByte); @@ -1276,7 +1275,12 @@ x54x_cmd_callback(void *priv) double period; x54x_t *dev = (x54x_t *) x54x_dev; - if ((dev->Status & STAT_INIT) || (!dev->MailboxInit && !dev->BIOSMailboxInit) || (!dev->MailboxReq && !dev->BIOSMailboxReq)) { + int mailboxes_present, bios_mailboxes_present; + + mailboxes_present = (!(dev->Status & STAT_INIT) && dev->MailboxInit && dev->MailboxReq); + bios_mailboxes_present = (dev->ven_callback && dev->BIOSMailboxInit && dev->BIOSMailboxReq); + + if (!mailboxes_present && !bios_mailboxes_present) { /* If we did not get anything, do nothing and wait 10 us. */ dev->timer_period = 10LL * TIMER_USEC; return; @@ -1284,11 +1288,21 @@ x54x_cmd_callback(void *priv) dev->temp_period = dev->media_period = 0LL; - if (!(x54x_dev->Status & STAT_INIT) && x54x_dev->MailboxInit && dev->MailboxReq) - x54x_do_mail(dev); - - if (dev->ven_callback) + if (!mailboxes_present) { + /* Do only BIOS mailboxes. */ dev->ven_callback(dev); + } else if (!bios_mailboxes_present) { + /* Do only normal mailboxes. */ + x54x_do_mail(dev); + } else { + /* Do both kinds of mailboxes. */ + if (dev->callback_phase) + dev->ven_callback(dev); + else + x54x_do_mail(dev); + + dev->callback_phase = (dev->callback_phase + 1) & 0x01; + } period = (1000000.0 / x54x_dev->ha_bps) * ((double) TIMER_USEC) * ((double) dev->temp_period); dev->timer_period = dev->media_period + ((int64_t) period) + (40LL * TIMER_USEC); @@ -1319,7 +1333,10 @@ x54x_in(uint16_t port, void *priv) break; case 2: - ret = dev->Interrupt; + if (dev->int_geom_writable) + ret = dev->Interrupt; + else + ret = dev->Interrupt & ~0x70; break; case 3: @@ -1406,11 +1423,14 @@ x54x_reset_poll(void *priv) static void x54x_reset(x54x_t *dev) { + int i; + clear_irq(dev); if (dev->int_geom_writable) dev->Geometry = 0x80; else dev->Geometry = 0x00; + dev->callback_phase = 0; dev->Command = 0xFF; dev->CmdParam = 0; dev->CmdParamLeft = 0; @@ -1422,9 +1442,12 @@ x54x_reset(x54x_t *dev) dev->MailboxCount = 0; dev->MailboxOutPosCur = 0; - if (dev->ven_reset) { + /* Reset all devices on controller reset. */ + for (i = 0; i < 16; i++) + scsi_device_reset(i); + + if (dev->ven_reset) dev->ven_reset(dev); - } } @@ -1454,7 +1477,6 @@ x54x_out(uint16_t port, uint8_t val, void *priv) x54x_t *dev = (x54x_t *)priv; MailboxInit_t *mbi; int i = 0; - uint8_t j = 0; BIOSCMD *cmd; uint16_t cyl = 0; int suppress = 0; @@ -1476,6 +1498,12 @@ x54x_out(uint16_t port, uint8_t val, void *priv) break; } + if (val & CTRL_SCRST) { + /* Reset all devices on SCSI bus reset. */ + for (i = 0; i < 16; i++) + scsi_device_reset(i); + } + if (val & CTRL_IRST) { clear_irq(dev); x54x_log("Interrupt reset: "); @@ -1643,16 +1671,15 @@ x54x_out(uint16_t port, uint8_t val, void *priv) if (dev->ven_get_host_id) host_id = dev->ven_get_host_id(dev); - for (i=0; iDataBuf[i] = 0x00; /* Skip the HA .. */ if (i == host_id) continue; - for (j=0; jDataBuf[i] |= (1<DataBuf[i] |= 1; } dev->DataReplyLeft = i; break; @@ -1902,6 +1929,7 @@ x54x_init(const device_t *info) dev->type = info->local; dev->bus = info->flags; + dev->callback_phase = 0; timer_add(x54x_reset_poll, &dev->ResetCB, &dev->ResetCB, dev); dev->timer_period = 10LL * TIMER_USEC; diff --git a/src/scsi/scsi_x54x.h b/src/scsi/scsi_x54x.h index a35932169..13699a181 100644 --- a/src/scsi/scsi_x54x.h +++ b/src/scsi/scsi_x54x.h @@ -11,7 +11,7 @@ * of SCSI Host Adapters made by Mylex. * These controllers were designed for various buses. * - * Version: @(#)scsi_x54x.h 1.0.6 2018/03/18 + * Version: @(#)scsi_x54x.h 1.0.7 2018/04/06 * * Authors: TheCollector1995, * Miran Grca, @@ -333,6 +333,7 @@ typedef struct { char name[16]; /* name of device */ int64_t timer_period, temp_period; + uint8_t callback_phase; int64_t media_period; double ha_bps; /* bytes per second */ @@ -491,8 +492,8 @@ typedef struct extern void x54x_reset_ctrl(x54x_t *dev, uint8_t Reset); -extern void x54x_buf_alloc(uint8_t id, uint8_t lun, int length); -extern void x54x_buf_free(uint8_t id, uint8_t lun); +extern void x54x_buf_alloc(uint8_t id, int length); +extern void x54x_buf_free(uint8_t id); extern uint8_t x54x_mbo_process(x54x_t *dev); extern void x54x_wait_for_poll(void); extern void x54x_io_set(x54x_t *dev, uint32_t base, uint8_t len); diff --git a/src/serial.c b/src/serial.c index 988eb7946..920f381c3 100644 --- a/src/serial.c +++ b/src/serial.c @@ -1,8 +1,10 @@ +#include #include #include #include #include #include +#define HAVE_STDARG_H #include "86box.h" #include "machine/machine.h" #include "io.h" @@ -26,6 +28,26 @@ SERIAL serial1, serial2; int serial_do_log = 0; +#ifdef ENABLE_SERIAL_LOG +int serial_do_log = ENABLE_SERIAL_LOG; +#endif + + +static void +serial_log(const char *format, ...) +{ +#ifdef ENABLE_SERIAL_LOG + va_list ap; + + if (serial_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + void serial_reset() { serial1.iir = serial1.ier = serial1.lcr = 0; @@ -279,7 +301,7 @@ void serial_remove(int port) return; } - /* pclog("Removing serial port %i at %04X...\n", port, base_address[port - 1]); */ + serial_log("Removing serial port %i at %04X...\n", port, base_address[port - 1]); switch(port) { @@ -296,7 +318,7 @@ void serial_remove(int port) void serial_setup(int port, uint16_t addr, int irq) { - /* pclog("Adding serial port %i at %04X...\n", port, addr); */ + serial_log("Adding serial port %i at %04X...\n", port, addr); switch(port) { @@ -345,7 +367,7 @@ void serial_init(void) if (serial_enabled[0]) { - /* pclog("Adding serial port 1...\n"); */ + serial_log("Adding serial port 1...\n"); memset(&serial1, 0, sizeof(serial1)); io_sethandler(0x3f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1); serial1.irq = 4; @@ -354,7 +376,7 @@ void serial_init(void) } if (serial_enabled[1]) { - /* pclog("Adding serial port 2...\n"); */ + serial_log("Adding serial port 2...\n"); memset(&serial2, 0, sizeof(serial2)); io_sethandler(0x2f8, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2); serial2.irq = 3; diff --git a/src/sio_fdc37c669.c b/src/sio_fdc37c669.c index ea5398020..58547c55c 100644 --- a/src/sio_fdc37c669.c +++ b/src/sio_fdc37c669.c @@ -8,7 +8,7 @@ * * Implementation of the SMC FDC37C669 Super I/O Chip. * - * Version: @(#)sio_fdc37c669.c 1.0.7 2018/01/16 + * Version: @(#)sio_fdc37c669.c 1.0.9 2018/04/29 * * Author: Miran Grca, * Copyright 2016-2018 Miran Grca. @@ -73,7 +73,6 @@ void fdc37c669_write(uint16_t port, uint8_t val, void *priv) uint8_t index = (port & 1) ? 0 : 1; uint8_t valxor = 0; uint8_t max = 42; - /* pclog("fdc37c669_write : port=%04x reg %02X = %02X locked=%i\n", port, fdc37c669_curreg, val, fdc37c669_locked); */ if (index) { @@ -125,7 +124,7 @@ process_value: if (valxor & 3) { ide_pri_disable(); - if ((fdc37c669_regs[0] & 3) == 2) ide_pri_enable_ex(); + if ((fdc37c669_regs[0] & 3) == 2) ide_pri_enable(); break; } #endif @@ -138,11 +137,9 @@ process_value: case 1: if (valxor & 4) { - /* pclog("Removing LPT1\n"); */ lpt1_remove(); if ((fdc37c669_regs[1] & 4) && (fdc37c669_regs[0x23] >= 0x40)) { - /* pclog("LPT1 init (%02X)\n", make_port(0x23)); */ lpt1_init(make_port(0x23)); } } @@ -154,21 +151,17 @@ process_value: case 2: if (valxor & 8) { - /* pclog("Removing UART1\n"); */ serial_remove(1); if ((fdc37c669_regs[2] & 8) && (fdc37c669_regs[0x24] >= 0x40)) { - /* pclog("UART1 init (%02X, %i)\n", make_port(0x24), (fdc37c669_regs[0x28] & 0xF0) >> 4); */ serial_setup(1, make_port(0x24), (fdc37c669_regs[0x28] & 0xF0) >> 4); } } if (valxor & 0x80) { - /* pclog("Removing UART2\n"); */ serial_remove(2); if ((fdc37c669_regs[2] & 0x80) && (fdc37c669_regs[0x25] >= 0x40)) { - /* pclog("UART2 init (%02X, %i)\n", make_port(0x25), fdc37c669_regs[0x28] & 0x0F); */ serial_setup(2, make_port(0x25), fdc37c669_regs[0x28] & 0x0F); } } @@ -206,18 +199,16 @@ process_value: ide_set_side(0, make_port(0x22)); break; } - if ((fdc37c669_regs[0] & 3) == 2) ide_pri_enable_ex(); + if ((fdc37c669_regs[0] & 3) == 2) ide_pri_enable(); } #endif break; case 0x23: if (valxor) { - /* pclog("Removing LPT1\n"); */ lpt1_remove(); if ((fdc37c669_regs[1] & 4) && (fdc37c669_regs[0x23] >= 0x40)) { - /* pclog("LPT1 init (%02X)\n", make_port(0x23)); */ lpt1_init(make_port(0x23)); } } @@ -225,11 +216,9 @@ process_value: case 0x24: if (valxor & 0xfe) { - /* pclog("Removing UART1\n"); */ serial_remove(1); if ((fdc37c669_regs[2] & 8) && (fdc37c669_regs[0x24] >= 0x40)) { - /* pclog("UART1 init (%02X, %i)\n", make_port(0x24), (fdc37c669_regs[0x28] & 0xF0) >> 4); */ serial_setup(1, make_port(0x24), (fdc37c669_regs[0x28] & 0xF0) >> 4); } } @@ -237,11 +226,9 @@ process_value: case 0x25: if (valxor & 0xfe) { - /* pclog("Removing UART2\n"); */ serial_remove(2); if ((fdc37c669_regs[2] & 0x80) && (fdc37c669_regs[0x25] >= 0x40)) { - /* pclog("UART2 init (%02X, %i)\n", make_port(0x25), fdc37c669_regs[0x28] & 0x0F); */ serial_setup(2, make_port(0x25), fdc37c669_regs[0x28] & 0x0F); } } @@ -249,21 +236,17 @@ process_value: case 0x28: if (valxor & 0xf) { - /* pclog("Removing UART2\n"); */ serial_remove(2); if ((fdc37c669_regs[2] & 0x80) && (fdc37c669_regs[0x25] >= 0x40)) { - /* pclog("UART2 init (%02X, %i)\n", make_port(0x25), fdc37c669_regs[0x28] & 0x0F); */ serial_setup(2, make_port(0x25), fdc37c669_regs[0x28] & 0x0F); } } if (valxor & 0xf0) { - /* pclog("Removing UART1\n"); */ serial_remove(1); if ((fdc37c669_regs[2] & 8) && (fdc37c669_regs[0x24] >= 0x40)) { - /* pclog("UART1 init (%02X, %i)\n", make_port(0x24), (fdc37c669_regs[0x28] & 0xF0) >> 4); */ serial_setup(1, make_port(0x24), (fdc37c669_regs[0x28] & 0xF0) >> 4); } } @@ -275,8 +258,6 @@ uint8_t fdc37c669_read(uint16_t port, void *priv) { uint8_t index = (port & 1) ? 0 : 1; - /* pclog("fdc37c669_read : port=%04x reg %02X locked=%i\n", port, fdc37c669_curreg, fdc37c669_locked); */ - if (!fdc37c669_locked) { return 0xFF; @@ -286,7 +267,6 @@ uint8_t fdc37c669_read(uint16_t port, void *priv) return fdc37c669_curreg; else { - /* pclog("0x03F1: %02X\n", fdc37c669_regs[fdc37c669_curreg]); */ if ((fdc37c669_curreg < 0x18) && (fdc37c669_rw_locked)) return 0xff; return fdc37c669_regs[fdc37c669_curreg]; } @@ -345,6 +325,4 @@ void fdc37c669_init() io_sethandler(0x3f0, 0x0002, fdc37c669_read, NULL, NULL, fdc37c669_write, NULL, NULL, NULL); fdc37c669_reset(); - - pci_reset_handler.super_io_reset = fdc37c669_reset; } diff --git a/src/sio_fdc37c66x.c b/src/sio_fdc37c66x.c index 222233db4..a97ee26e9 100644 --- a/src/sio_fdc37c66x.c +++ b/src/sio_fdc37c66x.c @@ -9,7 +9,7 @@ * Implementation of the SMC FDC37C663 and FDC37C665 Super * I/O Chips. * - * Version: @(#)sio_fdc37c66x.c 1.0.10 2018/01/16 + * Version: @(#)sio_fdc37c66x.c 1.0.11 2018/04/04 * * Authors: Sarah Walker, * Miran Grca, @@ -73,7 +73,7 @@ static void ide_handler() } ide_set_base(0, 0x170 | or_value); ide_set_side(0, 0x376 | or_value); - ide_pri_enable_ex(); + ide_pri_enable(); } #endif } @@ -319,8 +319,6 @@ void fdc37c663_init() io_sethandler(0x03f0, 0x0002, fdc37c66x_read, NULL, NULL, fdc37c66x_write, NULL, NULL, NULL); fdc37c663_reset(); - - pci_reset_handler.super_io_reset = fdc37c663_reset; } void fdc37c665_init() @@ -330,6 +328,4 @@ void fdc37c665_init() io_sethandler(0x03f0, 0x0002, fdc37c66x_read, NULL, NULL, fdc37c66x_write, NULL, NULL, NULL); fdc37c665_reset(); - - pci_reset_handler.super_io_reset = fdc37c665_reset; } diff --git a/src/sio_fdc37c93x.c b/src/sio_fdc37c93x.c index 0d4076ade..5d2f7816d 100644 --- a/src/sio_fdc37c93x.c +++ b/src/sio_fdc37c93x.c @@ -9,7 +9,7 @@ * Implementation of the SMC FDC37C932FR and FDC37C935 Super * I/O Chips. * - * Version: @(#)sio_fdc37c93x.c 1.0.11 2018/03/14 + * Version: @(#)sio_fdc37c93x.c 1.0.13 2018/04/29 * * Author: Miran Grca, * Copyright 2016-2018 Miran Grca. @@ -53,13 +53,11 @@ static uint16_t make_port(uint8_t ld) static uint8_t fdc37c93x_gpio_read(uint16_t port, void *priv) { - /* pclog("fdc37c93x: GPIO read: %02X\n", fdc37c93x_gpio_reg); */ return fdc37c93x_gpio_reg; } static void fdc37c93x_gpio_write(uint16_t port, uint8_t val, void *priv) { - /* pclog("fdc37c93x: GPIO write: %02X\n", val); */ fdc37c93x_gpio_reg = val; } @@ -71,11 +69,9 @@ static void fdc37c93x_fdc_handler(void) uint8_t local_enable = !!fdc37c93x_ld_regs[0][0x30]; fdc_remove(fdc37c93x_fdc); - /* pclog("fdc37c93x: Removing FDC (%i, %i)\n", global_enable, local_enable); */ if (global_enable && local_enable) { ld_port = make_port(0); - /* pclog("fdc37c93x: Setting FDC port to %04X\n", ld_port); */ if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) { fdc_set_base(fdc37c93x_fdc, ld_port); } @@ -93,7 +89,6 @@ static void fdc37c93x_lpt_handler(void) if (global_enable && local_enable) { ld_port = make_port(3); - /* pclog("fdc37c93x: Setting LPT1 port to %04X\n", ld_port); */ if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) lpt1_init(ld_port); } @@ -112,7 +107,6 @@ static void fdc37c93x_serial_handler(int uart) if (global_enable && local_enable) { ld_port = make_port(uart_no); - /* pclog("fdc37c93x: Setting COM%i port to %04X\n", uart, ld_port); */ if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) serial_setup(uart, ld_port, fdc37c93x_ld_regs[uart_no][0x70]); } @@ -128,7 +122,6 @@ static void fdc37c93x_auxio_handler(void) if (local_enable) { fdc37c93x_gpio_base = ld_port = make_port(8); - /* pclog("fdc37c93x: Setting Auxiliary I/O port to %04X\n", ld_port); */ if ((ld_port >= 0x0100) && (ld_port <= 0x0FFF)) io_sethandler(fdc37c93x_gpio_base, 0x0001, fdc37c93x_gpio_read, NULL, NULL, fdc37c93x_gpio_write, NULL, NULL, NULL); } @@ -198,7 +191,6 @@ static void fdc37c932fr_access_bus_handler(void) if (global_enable && local_enable) { access_bus.base = ld_port = make_port(9); - /* pclog("fdc37c93x: Setting Auxiliary I/O port to %04X\n", ld_port); */ if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) io_sethandler(access_bus.base, 0x0004, fdc37c932fr_access_bus_read, NULL, NULL, fdc37c932fr_access_bus_write, NULL, NULL, NULL); } @@ -566,14 +558,10 @@ void fdc37c932fr_init(void) { fdc37c93x_init(); fdc37c932fr_reset(); - - pci_reset_handler.super_io_reset = fdc37c932fr_reset; } void fdc37c935_init(void) { fdc37c93x_init(); fdc37c935_reset(); - - pci_reset_handler.super_io_reset = fdc37c935_reset; } diff --git a/src/sio_pc87306.c b/src/sio_pc87306.c index 9dfe881b1..3761d53d5 100644 --- a/src/sio_pc87306.c +++ b/src/sio_pc87306.c @@ -8,7 +8,7 @@ * * Emulation of the NatSemi PC87306 Super I/O chip. * - * Version: @(#)sio_pc87306.c 1.0.9 2018/01/17 + * Version: @(#)sio_pc87306.c 1.0.12 2018/05/11 * * Author: Miran Grca, * Copyright 2016-2018 Miran Grca. @@ -20,13 +20,16 @@ #include "86box.h" #include "io.h" #include "device.h" -#include "pci.h" #include "lpt.h" +#include "mem.h" +#include "pci.h" +#include "rom.h" #include "serial.h" #include "disk/hdc.h" #include "disk/hdc_ide.h" #include "floppy/fdd.h" #include "floppy/fdc.h" +#include "machine/machine.h" #include "sio.h" @@ -84,7 +87,6 @@ void lpt1_handler() lpt_port = 0x278; break; case 3: - // pclog("PNP0 Bits 4,5 = 00, FAR Bits 1,0 = 3 - reserved\n"); lpt_port = 0x000; break; } @@ -153,11 +155,7 @@ void serial2_handler() void pc87306_write(uint16_t port, uint8_t val, void *priv) { - uint8_t index; - uint8_t valxor; -#if 0 - uint16_t or_value; -#endif + uint8_t index, valxor; index = (port & 1) ? 0 : 1; @@ -240,27 +238,6 @@ process_value: fdc_set_base(pc87306_fdc, (val & 0x20) ? 0x370 : 0x3f0); } } - if (valxor & 0xc0) - { -#if 0 - ide_pri_disable(); - if (val & 0x80) - { - or_value = 0; - } - else - { - or_value = 0x80; - } - ide_set_base(0, 0x170 | or_value); - ide_set_side(0, 0x376 | or_value); - if (val & 0x40) - { - ide_pri_enable_ex(); - } -#endif - } - break; case 1: if (valxor & 3) @@ -441,7 +418,6 @@ void pc87306_reset(void) { memset(pc87306_regs, 0, 29); - /* pc87306_regs[0] = 0x4B; */ pc87306_regs[0] = 0x0B; pc87306_regs[1] = 0x01; pc87306_regs[3] = 0x01; @@ -476,6 +452,4 @@ void pc87306_init() pc87306_reset(); io_sethandler(0x02e, 0x0002, pc87306_read, NULL, NULL, pc87306_write, NULL, NULL, NULL); - - pci_reset_handler.super_io_reset = pc87306_reset; } diff --git a/src/sio_um8669f.c b/src/sio_um8669f.c index 1f2dccf11..fb991fede 100644 --- a/src/sio_um8669f.c +++ b/src/sio_um8669f.c @@ -88,7 +88,6 @@ void um8669f_pnp_write(uint16_t port, uint8_t val, void *p) um8669f->cur_device = val & 7; else { -/* pclog("Write UM8669F %02x [%02x] %02x\n", um8669f->cur_reg, um8669f->cur_device, val); */ switch (um8669f->cur_reg) { case REG_ENABLE: @@ -116,8 +115,6 @@ void um8669f_pnp_write(uint16_t port, uint8_t val, void *p) break; } - /* pclog("UM8669F: Write %02X to [%02X][%02X]...\n", val, um8669f->cur_device, um8669f->cur_reg); */ - switch (um8669f->cur_device) { case DEV_FDC: @@ -161,8 +158,6 @@ void um8669f_pnp_write(uint16_t port, uint8_t val, void *p) uint8_t um8669f_pnp_read(uint16_t port, void *p) { um8669f_t *um8669f = (um8669f_t *)p; - -/* pclog("Read UM8669F %02x\n", um8669f->cur_reg); */ switch (um8669f->cur_reg) { @@ -205,7 +200,6 @@ void um8669f_write(uint16_t port, uint8_t val, void *p) } else { -/* pclog("Write UM8669f register %02x %02x %04x:%04x %i\n", um8669f_curreg, val, CS,cpu_state.pc, ins); */ um8669f->regs_108[um8669f->cur_reg_108] = val; if (um8669f->cur_reg_108 == 0xc1) { @@ -231,8 +225,7 @@ void um8669f_write(uint16_t port, uint8_t val, void *p) uint8_t um8669f_read(uint16_t port, void *p) { um8669f_t *um8669f = (um8669f_t *)p; - -/* pclog("um8669f_read : port=%04x reg %02X locked=%i %02x\n", port, um8669f_curreg, um8669f_locked, um8669f_regs[um8669f_curreg]); */ + if (um8669f->locked) return 0xff; @@ -299,6 +292,4 @@ void um8669f_init(void) io_sethandler(0x0108, 0x0002, um8669f_read, NULL, NULL, um8669f_write, NULL, NULL, &um8669f_global); um8669f_reset(); - - pci_reset_handler.super_io_reset = um8669f_reset; } diff --git a/src/sio_w83877f.c b/src/sio_w83877f.c index fe6edc20d..775beccfe 100644 --- a/src/sio_w83877f.c +++ b/src/sio_w83877f.c @@ -11,7 +11,7 @@ * Winbond W83877F Super I/O Chip * Used by the Award 430HX * - * Version: @(#)sio_w83877f.c 1.0.9 2018/01/20 + * Version: @(#)sio_w83877f.c 1.0.11 2018/04/29 * * Author: Miran Grca, * Copyright 2016-2018 Miran Grca. @@ -224,7 +224,6 @@ static void w83877f_remap(void) winbond_port = (HEFRAS ? 0x3f0 : 0x250); winbond_key_times = HEFRAS + 1; winbond_key = (HEFRAS ? 0x86 : 0x88) | HEFERE; - /* pclog("W83877F: Remapped to port %04X, key %02X\n", winbond_port, winbond_key); */ } @@ -300,8 +299,6 @@ void w83877f_serial_handler(int id) int reg_id = (id - 1) ? 0x24 : 0x25; int irq_mask = (id - 1) ? 0xF : 0xF0; - /* pclog("Registers (%i): %02X %02X %02X\n", id, w83877f_regs[4], w83877f_regs[reg_id], w83877f_regs[0x28]); */ - if ((w83877f_regs[4] & reg_mask) || !(w83877f_regs[reg_id] & 0xc0)) { serial_remove(id); @@ -538,6 +535,4 @@ void w83877f_init(void) lpt2_remove(); w83877f_reset(); - - pci_reset_handler.super_io_reset = w83877f_reset; } diff --git a/src/sound/midi_fluidsynth.c b/src/sound/midi_fluidsynth.c index 6fff49a1f..22d318fbf 100644 --- a/src/sound/midi_fluidsynth.c +++ b/src/sound/midi_fluidsynth.c @@ -42,7 +42,6 @@ enum fluid_interp { extern void givealbuffer_midi(void *buf, uint32_t size); -extern void pclog(const char *format, ...); extern void al_set_midi(int freq, int buf_size); extern int soundon; @@ -224,7 +223,6 @@ void fluidsynth_msg(uint8_t *msg) case 0xF0: /* SysEx */ break; default: - /* pclog("fluidsynth: unknown send() command 0x%02X", cmd); */ break; } } @@ -243,13 +241,13 @@ void* fluidsynth_init(const device_t *info) /* Try loading the DLL. */ #ifdef _WIN32 - fluidsynth_handle = dynld_module("libfluidsynth.dll", fluidsynth_imports); + fluidsynth_handle = dynld_module("libfluidsynth-1.dll", fluidsynth_imports); #else fluidsynth_handle = dynld_module("libfluidsynth.so", fluidsynth_imports); #endif if (fluidsynth_handle == NULL) { - ui_msgbox(MBX_ERROR, (wchar_t *)IDS_2171); + ui_msgbox(MBX_ERROR, (wchar_t *)IDS_2081); return NULL; } @@ -331,8 +329,6 @@ void* fluidsynth_init(const device_t *info) al_set_midi(data->samplerate, data->buf_size); - /* pclog("fluidsynth (%s) initialized, samplerate %d, buf_size %d\n", f_fluid_version_str(), data->samplerate, data->buf_size); */ - midi_device_t* dev = malloc(sizeof(midi_device_t)); memset(dev, 0, sizeof(midi_device_t)); @@ -386,8 +382,6 @@ void fluidsynth_close(void* p) dynld_close(fluidsynth_handle); fluidsynth_handle = NULL; } - - /* pclog("fluidsynth closed\n"); */ } static const device_config_t fluidsynth_config[] = @@ -577,7 +571,6 @@ const device_t fluidsynth_device = fluidsynth_available, NULL, NULL, - NULL, fluidsynth_config }; diff --git a/src/sound/midi_mt32.c b/src/sound/midi_mt32.c index 2687c5e10..7903b2b05 100644 --- a/src/sound/midi_mt32.c +++ b/src/sound/midi_mt32.c @@ -15,7 +15,6 @@ extern void givealbuffer_midi(void *buf, uint32_t size); -extern void pclog(const char *format, ...); extern void al_set_midi(int freq, int buf_size); static const mt32emu_report_handler_i_v0 handler_v0 = { @@ -63,7 +62,6 @@ mt32emu_return_code mt32_check(const char* func, mt32emu_return_code ret, mt32em { if (ret != expected) { - /* pclog("%s() failed, expected %d but returned %d\n", func, expected, ret); */ return 0; } return 1; @@ -201,15 +199,8 @@ void* mt32emu_init(wchar_t *control_rom, wchar_t *pcm_rom) mt32emu_set_reversed_stereo_enabled(context, device_get_config_int("reversed_stereo")); mt32emu_set_nice_amp_ramp_enabled(context, device_get_config_int("nice_ramp")); - /* pclog("mt32 output gain: %f\n", mt32emu_get_output_gain(context)); - pclog("mt32 reverb output gain: %f\n", mt32emu_get_reverb_output_gain(context)); - pclog("mt32 reverb: %d\n", mt32emu_is_reverb_enabled(context)); - pclog("mt32 reversed stereo: %d\n", mt32emu_is_reversed_stereo_enabled(context)); */ - al_set_midi(samplerate, buf_size); - /* pclog("mt32 (Munt %s) initialized, samplerate %d, buf_size %d\n", mt32emu_get_library_version_string(), samplerate, buf_size); */ - midi_device_t* dev = malloc(sizeof(midi_device_t)); memset(dev, 0, sizeof(midi_device_t)); @@ -261,8 +252,6 @@ void mt32_close(void* p) midi_close(); free((midi_device_t*)p); - - /* pclog("mt32 closed\n"); */ } static const device_config_t mt32_config[] = @@ -323,7 +312,6 @@ const device_t mt32_device = mt32_available, NULL, NULL, - NULL, mt32_config }; @@ -338,6 +326,5 @@ const device_t cm32l_device = cm32l_available, NULL, NULL, - NULL, mt32_config }; diff --git a/src/sound/midi_system.c b/src/sound/midi_system.c index cbf1a469a..d9a15c6a9 100644 --- a/src/sound/midi_system.c +++ b/src/sound/midi_system.c @@ -62,6 +62,5 @@ const device_t system_midi_device = system_midi_available, NULL, NULL, - NULL, system_midi_config }; diff --git a/src/sound/nukedopl.cpp b/src/sound/nukedopl.cpp index 538a4411b..0039a63bc 100644 --- a/src/sound/nukedopl.cpp +++ b/src/sound/nukedopl.cpp @@ -1,7 +1,16 @@ -/* Copyright holders: Alexey Khokholov (Nuke.YKT) - see COPYING for more details -*/ - +// +// Copyright (C) 2013-2018 Alexey Khokholov (Nuke.YKT) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// // // Nuked OPL3 emulator. // Thanks: @@ -11,8 +20,10 @@ // Tremolo and phase generator calculation information. // OPLx decapsulated(Matthew Gambrell, Olli Niemitalo): // OPL2 ROMs. +// siliconpr0n.org(John McMaster, digshadow): +// YMF262 and VRC VII decaps and die shots. // -// version: 1.7.4 +// version: 1.8 // #include @@ -83,38 +94,38 @@ static const Bit16u logsinrom[256] = { // static const Bit16u exprom[256] = { - 0x000, 0x003, 0x006, 0x008, 0x00b, 0x00e, 0x011, 0x014, - 0x016, 0x019, 0x01c, 0x01f, 0x022, 0x025, 0x028, 0x02a, - 0x02d, 0x030, 0x033, 0x036, 0x039, 0x03c, 0x03f, 0x042, - 0x045, 0x048, 0x04b, 0x04e, 0x051, 0x054, 0x057, 0x05a, - 0x05d, 0x060, 0x063, 0x066, 0x069, 0x06c, 0x06f, 0x072, - 0x075, 0x078, 0x07b, 0x07e, 0x082, 0x085, 0x088, 0x08b, - 0x08e, 0x091, 0x094, 0x098, 0x09b, 0x09e, 0x0a1, 0x0a4, - 0x0a8, 0x0ab, 0x0ae, 0x0b1, 0x0b5, 0x0b8, 0x0bb, 0x0be, - 0x0c2, 0x0c5, 0x0c8, 0x0cc, 0x0cf, 0x0d2, 0x0d6, 0x0d9, - 0x0dc, 0x0e0, 0x0e3, 0x0e7, 0x0ea, 0x0ed, 0x0f1, 0x0f4, - 0x0f8, 0x0fb, 0x0ff, 0x102, 0x106, 0x109, 0x10c, 0x110, - 0x114, 0x117, 0x11b, 0x11e, 0x122, 0x125, 0x129, 0x12c, - 0x130, 0x134, 0x137, 0x13b, 0x13e, 0x142, 0x146, 0x149, - 0x14d, 0x151, 0x154, 0x158, 0x15c, 0x160, 0x163, 0x167, - 0x16b, 0x16f, 0x172, 0x176, 0x17a, 0x17e, 0x181, 0x185, - 0x189, 0x18d, 0x191, 0x195, 0x199, 0x19c, 0x1a0, 0x1a4, - 0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc, 0x1c0, 0x1c4, - 0x1c8, 0x1cc, 0x1d0, 0x1d4, 0x1d8, 0x1dc, 0x1e0, 0x1e4, - 0x1e8, 0x1ec, 0x1f0, 0x1f5, 0x1f9, 0x1fd, 0x201, 0x205, - 0x209, 0x20e, 0x212, 0x216, 0x21a, 0x21e, 0x223, 0x227, - 0x22b, 0x230, 0x234, 0x238, 0x23c, 0x241, 0x245, 0x249, - 0x24e, 0x252, 0x257, 0x25b, 0x25f, 0x264, 0x268, 0x26d, - 0x271, 0x276, 0x27a, 0x27f, 0x283, 0x288, 0x28c, 0x291, - 0x295, 0x29a, 0x29e, 0x2a3, 0x2a8, 0x2ac, 0x2b1, 0x2b5, - 0x2ba, 0x2bf, 0x2c4, 0x2c8, 0x2cd, 0x2d2, 0x2d6, 0x2db, - 0x2e0, 0x2e5, 0x2e9, 0x2ee, 0x2f3, 0x2f8, 0x2fd, 0x302, - 0x306, 0x30b, 0x310, 0x315, 0x31a, 0x31f, 0x324, 0x329, - 0x32e, 0x333, 0x338, 0x33d, 0x342, 0x347, 0x34c, 0x351, - 0x356, 0x35b, 0x360, 0x365, 0x36a, 0x370, 0x375, 0x37a, - 0x37f, 0x384, 0x38a, 0x38f, 0x394, 0x399, 0x39f, 0x3a4, - 0x3a9, 0x3ae, 0x3b4, 0x3b9, 0x3bf, 0x3c4, 0x3c9, 0x3cf, - 0x3d4, 0x3da, 0x3df, 0x3e4, 0x3ea, 0x3ef, 0x3f5, 0x3fa + 0x7fa, 0x7f5, 0x7ef, 0x7ea, 0x7e4, 0x7df, 0x7da, 0x7d4, + 0x7cf, 0x7c9, 0x7c4, 0x7bf, 0x7b9, 0x7b4, 0x7ae, 0x7a9, + 0x7a4, 0x79f, 0x799, 0x794, 0x78f, 0x78a, 0x784, 0x77f, + 0x77a, 0x775, 0x770, 0x76a, 0x765, 0x760, 0x75b, 0x756, + 0x751, 0x74c, 0x747, 0x742, 0x73d, 0x738, 0x733, 0x72e, + 0x729, 0x724, 0x71f, 0x71a, 0x715, 0x710, 0x70b, 0x706, + 0x702, 0x6fd, 0x6f8, 0x6f3, 0x6ee, 0x6e9, 0x6e5, 0x6e0, + 0x6db, 0x6d6, 0x6d2, 0x6cd, 0x6c8, 0x6c4, 0x6bf, 0x6ba, + 0x6b5, 0x6b1, 0x6ac, 0x6a8, 0x6a3, 0x69e, 0x69a, 0x695, + 0x691, 0x68c, 0x688, 0x683, 0x67f, 0x67a, 0x676, 0x671, + 0x66d, 0x668, 0x664, 0x65f, 0x65b, 0x657, 0x652, 0x64e, + 0x649, 0x645, 0x641, 0x63c, 0x638, 0x634, 0x630, 0x62b, + 0x627, 0x623, 0x61e, 0x61a, 0x616, 0x612, 0x60e, 0x609, + 0x605, 0x601, 0x5fd, 0x5f9, 0x5f5, 0x5f0, 0x5ec, 0x5e8, + 0x5e4, 0x5e0, 0x5dc, 0x5d8, 0x5d4, 0x5d0, 0x5cc, 0x5c8, + 0x5c4, 0x5c0, 0x5bc, 0x5b8, 0x5b4, 0x5b0, 0x5ac, 0x5a8, + 0x5a4, 0x5a0, 0x59c, 0x599, 0x595, 0x591, 0x58d, 0x589, + 0x585, 0x581, 0x57e, 0x57a, 0x576, 0x572, 0x56f, 0x56b, + 0x567, 0x563, 0x560, 0x55c, 0x558, 0x554, 0x551, 0x54d, + 0x549, 0x546, 0x542, 0x53e, 0x53b, 0x537, 0x534, 0x530, + 0x52c, 0x529, 0x525, 0x522, 0x51e, 0x51b, 0x517, 0x514, + 0x510, 0x50c, 0x509, 0x506, 0x502, 0x4ff, 0x4fb, 0x4f8, + 0x4f4, 0x4f1, 0x4ed, 0x4ea, 0x4e7, 0x4e3, 0x4e0, 0x4dc, + 0x4d9, 0x4d6, 0x4d2, 0x4cf, 0x4cc, 0x4c8, 0x4c5, 0x4c2, + 0x4be, 0x4bb, 0x4b8, 0x4b5, 0x4b1, 0x4ae, 0x4ab, 0x4a8, + 0x4a4, 0x4a1, 0x49e, 0x49b, 0x498, 0x494, 0x491, 0x48e, + 0x48b, 0x488, 0x485, 0x482, 0x47e, 0x47b, 0x478, 0x475, + 0x472, 0x46f, 0x46c, 0x469, 0x466, 0x463, 0x460, 0x45d, + 0x45a, 0x457, 0x454, 0x451, 0x44e, 0x44b, 0x448, 0x445, + 0x442, 0x43f, 0x43c, 0x439, 0x436, 0x433, 0x430, 0x42d, + 0x42a, 0x428, 0x425, 0x422, 0x41f, 0x41c, 0x419, 0x416, + 0x414, 0x411, 0x40e, 0x40b, 0x408, 0x406, 0x403, 0x400 }; // @@ -143,33 +154,11 @@ static const Bit8u kslshift[4] = { // envelope generator constants // -static const Bit8u eg_incstep[3][4][8] = { - { - { 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0 } - }, - { - { 0, 1, 0, 1, 0, 1, 0, 1 }, - { 0, 1, 0, 1, 1, 1, 0, 1 }, - { 0, 1, 1, 1, 0, 1, 1, 1 }, - { 0, 1, 1, 1, 1, 1, 1, 1 } - }, - { - { 1, 1, 1, 1, 1, 1, 1, 1 }, - { 2, 2, 1, 1, 1, 1, 1, 1 }, - { 2, 2, 1, 1, 2, 2, 1, 1 }, - { 2, 2, 2, 2, 2, 2, 1, 1 } - } -}; - -static const Bit8u eg_incdesc[16] = { - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2 -}; - -static const Bit8s eg_incsh[16] = { - 0, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, -1, -2 +static const Bit8u eg_incstep[4][4] = { + { 0, 0, 0, 0 }, + { 1, 0, 0, 0 }, + { 1, 0, 1, 0 }, + { 1, 1, 1, 0 } }; // @@ -198,7 +187,7 @@ static Bit16s OPL3_EnvelopeCalcExp(Bit32u level) { level = 0x1fff; } - return ((exprom[(level & 0xff) ^ 0xff] | 0x400) << 1) >> (level >> 8); + return (exprom[level & 0xff] << 1) >> (level >> 8); } static Bit16s OPL3_EnvelopeCalcSin0(Bit16u phase, Bit16u envelope) @@ -208,7 +197,7 @@ static Bit16s OPL3_EnvelopeCalcSin0(Bit16u phase, Bit16u envelope) phase &= 0x3ff; if (phase & 0x200) { - neg = ~0; + neg = 0xffff; } if (phase & 0x100) { @@ -277,7 +266,7 @@ static Bit16s OPL3_EnvelopeCalcSin4(Bit16u phase, Bit16u envelope) phase &= 0x3ff; if ((phase & 0x300) == 0x100) { - neg = ~0; + neg = 0xffff; } if (phase & 0x200) { @@ -319,7 +308,7 @@ static Bit16s OPL3_EnvelopeCalcSin6(Bit16u phase, Bit16u envelope) phase &= 0x3ff; if (phase & 0x200) { - neg = ~0; + neg = 0xffff; } return OPL3_EnvelopeCalcExp(envelope << 3) ^ neg; } @@ -331,7 +320,7 @@ static Bit16s OPL3_EnvelopeCalcSin7(Bit16u phase, Bit16u envelope) phase &= 0x3ff; if (phase & 0x200) { - neg = ~0; + neg = 0xffff; phase = (phase & 0x1ff) ^ 0x1ff; } out = phase << 3; @@ -349,45 +338,14 @@ static const envelope_sinfunc envelope_sin[8] = { OPL3_EnvelopeCalcSin7 }; -static void OPL3_EnvelopeGenOff(opl3_slot *slot); -static void OPL3_EnvelopeGenAttack(opl3_slot *slot); -static void OPL3_EnvelopeGenDecay(opl3_slot *slot); -static void OPL3_EnvelopeGenSustain(opl3_slot *slot); -static void OPL3_EnvelopeGenRelease(opl3_slot *slot); - -envelope_genfunc envelope_gen[5] = { - OPL3_EnvelopeGenOff, - OPL3_EnvelopeGenAttack, - OPL3_EnvelopeGenDecay, - OPL3_EnvelopeGenSustain, - OPL3_EnvelopeGenRelease -}; - enum envelope_gen_num { - envelope_gen_num_off = 0, - envelope_gen_num_attack = 1, - envelope_gen_num_decay = 2, - envelope_gen_num_sustain = 3, - envelope_gen_num_release = 4 + envelope_gen_num_attack = 0, + envelope_gen_num_decay = 1, + envelope_gen_num_sustain = 2, + envelope_gen_num_release = 3 }; -static Bit8u OPL3_EnvelopeCalcRate(opl3_slot *slot, Bit8u reg_rate) -{ - Bit8u rate; - if (reg_rate == 0x00) - { - return 0x00; - } - rate = (reg_rate << 2) - + (slot->reg_ksr ? slot->channel->ksv : (slot->channel->ksv >> 2)); - if (rate > 0x3c) - { - rate = 0x3c; - } - return rate; -} - static void OPL3_EnvelopeUpdateKSL(opl3_slot *slot) { Bit16s ksl = (kslrom[slot->channel->f_num >> 6] << 2) @@ -399,128 +357,161 @@ static void OPL3_EnvelopeUpdateKSL(opl3_slot *slot) slot->eg_ksl = (Bit8u)ksl; } -static void OPL3_EnvelopeUpdateRate(opl3_slot *slot) -{ - switch (slot->eg_gen) - { - case envelope_gen_num_off: - case envelope_gen_num_attack: - slot->eg_rate = OPL3_EnvelopeCalcRate(slot, slot->reg_ar); - break; - case envelope_gen_num_decay: - slot->eg_rate = OPL3_EnvelopeCalcRate(slot, slot->reg_dr); - break; - case envelope_gen_num_sustain: - case envelope_gen_num_release: - slot->eg_rate = OPL3_EnvelopeCalcRate(slot, slot->reg_rr); - break; - } -} - -static void OPL3_EnvelopeGenOff(opl3_slot *slot) -{ - slot->eg_rout = 0x1ff; -} - -static void OPL3_EnvelopeGenAttack(opl3_slot *slot) -{ - if (slot->eg_rout == 0x00) - { - slot->eg_gen = envelope_gen_num_decay; - OPL3_EnvelopeUpdateRate(slot); - return; - } - slot->eg_rout += ((~slot->eg_rout) * slot->eg_inc) >> 3; - if (slot->eg_rout < 0x00) - { - slot->eg_rout = 0x00; - } -} - -static void OPL3_EnvelopeGenDecay(opl3_slot *slot) -{ - if (slot->eg_rout >= slot->reg_sl << 4) - { - slot->eg_gen = envelope_gen_num_sustain; - OPL3_EnvelopeUpdateRate(slot); - return; - } - slot->eg_rout += slot->eg_inc; -} - -static void OPL3_EnvelopeGenSustain(opl3_slot *slot) -{ - if (!slot->reg_type) - { - OPL3_EnvelopeGenRelease(slot); - } -} - -static void OPL3_EnvelopeGenRelease(opl3_slot *slot) -{ - if (slot->eg_rout >= 0x1ff) - { - slot->eg_gen = envelope_gen_num_off; - slot->eg_rout = 0x1ff; - OPL3_EnvelopeUpdateRate(slot); - return; - } - slot->eg_rout += slot->eg_inc; -} - static void OPL3_EnvelopeCalc(opl3_slot *slot) { - Bit8u rate_h, rate_l; - Bit8u inc = 0; - rate_h = slot->eg_rate >> 2; - rate_l = slot->eg_rate & 3; - if (eg_incsh[rate_h] > 0) + Bit8u nonzero; + Bit8u rate; + Bit8u rate_hi; + Bit8u rate_lo; + Bit8u reg_rate = 0; + Bit8u ks; + Bit8u eg_shift, shift; + Bit16u eg_rout; + Bit16s eg_inc; + Bit8u eg_off; + Bit8u reset = 0; + slot->eg_out = slot->eg_rout + (slot->reg_tl << 2) + + (slot->eg_ksl >> kslshift[slot->reg_ksl]) + *slot->trem; + if (slot->key && slot->eg_gen == envelope_gen_num_release) { - if ((slot->chip->timer & ((1 << eg_incsh[rate_h]) - 1)) == 0) - { - inc = eg_incstep[eg_incdesc[rate_h]][rate_l] - [((slot->chip->timer)>> eg_incsh[rate_h]) & 0x07]; - } + reset = 1; + reg_rate = slot->reg_ar; } else { - inc = eg_incstep[eg_incdesc[rate_h]][rate_l] - [slot->chip->timer & 0x07] << (-eg_incsh[rate_h]); + switch (slot->eg_gen) + { + case envelope_gen_num_attack: + reg_rate = slot->reg_ar; + break; + case envelope_gen_num_decay: + reg_rate = slot->reg_dr; + break; + case envelope_gen_num_sustain: + if (!slot->reg_type) + { + reg_rate = slot->reg_rr; + } + break; + case envelope_gen_num_release: + reg_rate = slot->reg_rr; + break; + } + } + slot->pg_reset = reset; + ks = slot->channel->ksv >> ((slot->reg_ksr ^ 1) << 1); + nonzero = (reg_rate != 0); + rate = ks + (reg_rate << 2); + rate_hi = rate >> 2; + rate_lo = rate & 0x03; + if (rate_hi & 0x10) + { + rate_hi = 0x0f; + } + eg_shift = rate_hi + slot->chip->eg_add; + shift = 0; + if (nonzero) + { + if (rate_hi < 12) + { + if (slot->chip->eg_state) + { + switch (eg_shift) + { + case 12: + shift = 1; + break; + case 13: + shift = (rate_lo >> 1) & 0x01; + break; + case 14: + shift = rate_lo & 0x01; + break; + default: + break; + } + } + } + else + { + shift = (rate_hi & 0x03) + eg_incstep[rate_lo][slot->chip->timer & 0x03]; + if (shift & 0x04) + { + shift = 0x03; + } + if (!shift) + { + shift = slot->chip->eg_state; + } + } + } + eg_rout = slot->eg_rout; + eg_inc = 0; + eg_off = 0; + // Instant attack + if (reset && rate_hi == 0x0f) + { + eg_rout = 0x00; + } + // Envelope off + if ((slot->eg_rout & 0x1f8) == 0x1f8) + { + eg_off = 1; + } + if (slot->eg_gen != envelope_gen_num_attack && !reset && eg_off) + { + eg_rout = 0x1ff; + } + switch (slot->eg_gen) + { + case envelope_gen_num_attack: + if (!slot->eg_rout) + { + slot->eg_gen = envelope_gen_num_decay; + } + else if (slot->key && shift > 0 && rate_hi != 0x0f) + { + eg_inc = ((~slot->eg_rout) << shift) >> 4; + } + break; + case envelope_gen_num_decay: + if ((slot->eg_rout >> 4) == slot->reg_sl) + { + slot->eg_gen = envelope_gen_num_sustain; + } + else if (!eg_off && !reset && shift > 0) + { + eg_inc = 1 << (shift - 1); + } + break; + case envelope_gen_num_sustain: + case envelope_gen_num_release: + if (!eg_off && !reset && shift > 0) + { + eg_inc = 1 << (shift - 1); + } + break; + } + slot->eg_rout = (eg_rout + eg_inc) & 0x1ff; + // Key off + if (reset) + { + slot->eg_gen = envelope_gen_num_attack; + } + if (!slot->key) + { + slot->eg_gen = envelope_gen_num_release; } - slot->eg_inc = inc; - slot->eg_out = slot->eg_rout + (slot->reg_tl << 2) - + (slot->eg_ksl >> kslshift[slot->reg_ksl]) + *slot->trem; - envelope_gen[slot->eg_gen](slot); } static void OPL3_EnvelopeKeyOn(opl3_slot *slot, Bit8u type) { - if (!slot->key) - { - slot->eg_gen = envelope_gen_num_attack; - OPL3_EnvelopeUpdateRate(slot); - if ((slot->eg_rate >> 2) == 0x0f) - { - slot->eg_gen = envelope_gen_num_decay; - OPL3_EnvelopeUpdateRate(slot); - slot->eg_rout = 0x00; - } - slot->pg_phase = 0x00; - } slot->key |= type; } static void OPL3_EnvelopeKeyOff(opl3_slot *slot, Bit8u type) { - if (slot->key) - { - slot->key &= (~type); - if (!slot->key) - { - slot->eg_gen = envelope_gen_num_release; - OPL3_EnvelopeUpdateRate(slot); - } - } + slot->key &= ~type; } // @@ -529,9 +520,14 @@ static void OPL3_EnvelopeKeyOff(opl3_slot *slot, Bit8u type) static void OPL3_PhaseGenerate(opl3_slot *slot) { + opl3_chip *chip; Bit16u f_num; Bit32u basefreq; + Bit8u rm_xor, n_bit; + Bit32u noise; + Bit16u phase; + chip = slot->chip; f_num = slot->channel->f_num; if (slot->reg_vib) { @@ -558,20 +554,58 @@ static void OPL3_PhaseGenerate(opl3_slot *slot) f_num += range; } basefreq = (f_num << slot->channel->block) >> 1; - slot->pg_phase += (basefreq * mt[slot->reg_mult]) >> 1; -} - -// -// Noise Generator -// - -static void OPL3_NoiseGenerate(opl3_chip *chip) -{ - if (chip->noise & 0x01) + phase = (Bit16u)(slot->pg_phase >> 9); + if (slot->pg_reset) { - chip->noise ^= 0x800302; + slot->pg_phase = 0; } - chip->noise >>= 1; + slot->pg_phase += (basefreq * mt[slot->reg_mult]) >> 1; + // Rhythm mode + noise = chip->noise; + slot->pg_phase_out = phase; + if (slot->slot_num == 13) // hh + { + chip->rm_hh_bit2 = (phase >> 2) & 1; + chip->rm_hh_bit3 = (phase >> 3) & 1; + chip->rm_hh_bit7 = (phase >> 7) & 1; + chip->rm_hh_bit8 = (phase >> 8) & 1; + } + if (slot->slot_num == 17 && (chip->rhy & 0x20)) // tc + { + chip->rm_tc_bit3 = (phase >> 3) & 1; + chip->rm_tc_bit5 = (phase >> 5) & 1; + } + if (chip->rhy & 0x20) + { + rm_xor = (chip->rm_hh_bit2 ^ chip->rm_hh_bit7) + | (chip->rm_hh_bit3 ^ chip->rm_tc_bit5) + | (chip->rm_tc_bit3 ^ chip->rm_tc_bit5); + switch (slot->slot_num) + { + case 13: // hh + slot->pg_phase_out = rm_xor << 9; + if (rm_xor ^ (noise & 1)) + { + slot->pg_phase_out |= 0xd0; + } + else + { + slot->pg_phase_out |= 0x34; + } + break; + case 16: // sd + slot->pg_phase_out = (chip->rm_hh_bit8 << 9) + | ((chip->rm_hh_bit8 ^ (noise & 1)) << 8); + break; + case 17: // tc + slot->pg_phase_out = (rm_xor << 9) | 0x80; + break; + default: + break; + } + } + n_bit = ((noise >> 14) ^ noise) & 0x01; + chip->noise = (noise >> 1) | (n_bit << 22); } // @@ -592,7 +626,6 @@ static void OPL3_SlotWrite20(opl3_slot *slot, Bit8u data) slot->reg_type = (data >> 5) & 0x01; slot->reg_ksr = (data >> 4) & 0x01; slot->reg_mult = data & 0x0f; - OPL3_EnvelopeUpdateRate(slot); } static void OPL3_SlotWrite40(opl3_slot *slot, Bit8u data) @@ -606,7 +639,6 @@ static void OPL3_SlotWrite60(opl3_slot *slot, Bit8u data) { slot->reg_ar = (data >> 4) & 0x0f; slot->reg_dr = data & 0x0f; - OPL3_EnvelopeUpdateRate(slot); } static void OPL3_SlotWrite80(opl3_slot *slot, Bit8u data) @@ -617,7 +649,6 @@ static void OPL3_SlotWrite80(opl3_slot *slot, Bit8u data) slot->reg_sl = 0x1f; } slot->reg_rr = data & 0x0f; - OPL3_EnvelopeUpdateRate(slot); } static void OPL3_SlotWriteE0(opl3_slot *slot, Bit8u data) @@ -629,19 +660,9 @@ static void OPL3_SlotWriteE0(opl3_slot *slot, Bit8u data) } } -static void OPL3_SlotGeneratePhase(opl3_slot *slot, Bit16u phase) -{ - slot->out = envelope_sin[slot->reg_wf](phase, slot->eg_out); -} - static void OPL3_SlotGenerate(opl3_slot *slot) { - OPL3_SlotGeneratePhase(slot, (Bit16u)(slot->pg_phase >> 9) + *slot->mod); -} - -static void OPL3_SlotGenerateZM(opl3_slot *slot) -{ - OPL3_SlotGeneratePhase(slot, (Bit16u)(slot->pg_phase >> 9)); + slot->out = envelope_sin[slot->reg_wf](slot->pg_phase_out + *slot->mod, slot->eg_out); } static void OPL3_SlotCalcFB(opl3_slot *slot) @@ -693,6 +714,8 @@ static void OPL3_ChannelUpdateRhythm(opl3_chip *chip, Bit8u data) chip->channel[chnum].chtype = ch_drum; } OPL3_ChannelSetupAlg(channel6); + OPL3_ChannelSetupAlg(channel7); + OPL3_ChannelSetupAlg(channel8); //hh if (chip->rhy & 0x01) { @@ -764,16 +787,12 @@ static void OPL3_ChannelWriteA0(opl3_channel *channel, Bit8u data) | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01); OPL3_EnvelopeUpdateKSL(channel->slots[0]); OPL3_EnvelopeUpdateKSL(channel->slots[1]); - OPL3_EnvelopeUpdateRate(channel->slots[0]); - OPL3_EnvelopeUpdateRate(channel->slots[1]); if (channel->chip->newm && channel->chtype == ch_4op) { channel->pair->f_num = channel->f_num; channel->pair->ksv = channel->ksv; OPL3_EnvelopeUpdateKSL(channel->pair->slots[0]); OPL3_EnvelopeUpdateKSL(channel->pair->slots[1]); - OPL3_EnvelopeUpdateRate(channel->pair->slots[0]); - OPL3_EnvelopeUpdateRate(channel->pair->slots[1]); } } @@ -789,8 +808,6 @@ static void OPL3_ChannelWriteB0(opl3_channel *channel, Bit8u data) | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01); OPL3_EnvelopeUpdateKSL(channel->slots[0]); OPL3_EnvelopeUpdateKSL(channel->slots[1]); - OPL3_EnvelopeUpdateRate(channel->slots[0]); - OPL3_EnvelopeUpdateRate(channel->slots[1]); if (channel->chip->newm && channel->chtype == ch_4op) { channel->pair->f_num = channel->f_num; @@ -798,8 +815,6 @@ static void OPL3_ChannelWriteB0(opl3_channel *channel, Bit8u data) channel->pair->ksv = channel->ksv; OPL3_EnvelopeUpdateKSL(channel->pair->slots[0]); OPL3_EnvelopeUpdateKSL(channel->pair->slots[1]); - OPL3_EnvelopeUpdateRate(channel->pair->slots[0]); - OPL3_EnvelopeUpdateRate(channel->pair->slots[1]); } } @@ -807,6 +822,12 @@ static void OPL3_ChannelSetupAlg(opl3_channel *channel) { if (channel->chtype == ch_drum) { + if (channel->ch_num == 7 || channel->ch_num == 8) + { + channel->slots[0]->mod = &channel->chip->zeromod; + channel->slots[1]->mod = &channel->chip->zeromod; + return; + } switch (channel->alg & 0x01) { case 0x00: @@ -933,7 +954,7 @@ static void OPL3_ChannelWriteC0(opl3_channel *channel, Bit8u data) } else { - channel->cha = channel->chb = ~0; + channel->cha = channel->chb = (Bit16u)~0; } } @@ -1022,96 +1043,23 @@ static Bit16s OPL3_ClipSample(Bit32s sample) return (Bit16s)sample; } -static void OPL3_GenerateRhythm1(opl3_chip *chip) -{ - opl3_channel *channel6; - opl3_channel *channel7; - opl3_channel *channel8; - Bit16u phase14; - Bit16u phase17; - Bit16u phase; - Bit16u phasebit; - - channel6 = &chip->channel[6]; - channel7 = &chip->channel[7]; - channel8 = &chip->channel[8]; - OPL3_SlotGenerate(channel6->slots[0]); - phase14 = (channel7->slots[0]->pg_phase >> 9) & 0x3ff; - phase17 = (channel8->slots[1]->pg_phase >> 9) & 0x3ff; - phase = 0x00; - //hh tc phase bit - phasebit = ((phase14 & 0x08) | (((phase14 >> 5) ^ phase14) & 0x04) - | (((phase17 >> 2) ^ phase17) & 0x08)) ? 0x01 : 0x00; - //hh - phase = (phasebit << 9) - | (0x34 << ((phasebit ^ (chip->noise & 0x01)) << 1)); - OPL3_SlotGeneratePhase(channel7->slots[0], phase); - //tt - OPL3_SlotGenerateZM(channel8->slots[0]); -} - -static void OPL3_GenerateRhythm2(opl3_chip *chip) -{ - opl3_channel *channel6; - opl3_channel *channel7; - opl3_channel *channel8; - Bit16u phase14; - Bit16u phase17; - Bit16u phase; - Bit16u phasebit; - - channel6 = &chip->channel[6]; - channel7 = &chip->channel[7]; - channel8 = &chip->channel[8]; - OPL3_SlotGenerate(channel6->slots[1]); - phase14 = (channel7->slots[0]->pg_phase >> 9) & 0x3ff; - phase17 = (channel8->slots[1]->pg_phase >> 9) & 0x3ff; - phase = 0x00; - //hh tc phase bit - phasebit = ((phase14 & 0x08) | (((phase14 >> 5) ^ phase14) & 0x04) - | (((phase17 >> 2) ^ phase17) & 0x08)) ? 0x01 : 0x00; - //sd - phase = (0x100 << ((phase14 >> 8) & 0x01)) ^ ((chip->noise & 0x01) << 8); - OPL3_SlotGeneratePhase(channel7->slots[1], phase); - //tc - phase = 0x100 | (phasebit << 9); - OPL3_SlotGeneratePhase(channel8->slots[1], phase); -} - void OPL3_Generate(opl3_chip *chip, Bit16s *buf) { Bit8u ii; Bit8u jj; Bit16s accm; + Bit8u shift = 0; buf[1] = OPL3_ClipSample(chip->mixbuff[1]); - for (ii = 0; ii < 12; ii++) + for (ii = 0; ii < 15; ii++) { OPL3_SlotCalcFB(&chip->slot[ii]); - OPL3_PhaseGenerate(&chip->slot[ii]); OPL3_EnvelopeCalc(&chip->slot[ii]); + OPL3_PhaseGenerate(&chip->slot[ii]); OPL3_SlotGenerate(&chip->slot[ii]); } - for (ii = 12; ii < 15; ii++) - { - OPL3_SlotCalcFB(&chip->slot[ii]); - OPL3_PhaseGenerate(&chip->slot[ii]); - OPL3_EnvelopeCalc(&chip->slot[ii]); - } - - if (chip->rhy & 0x20) - { - OPL3_GenerateRhythm1(chip); - } - else - { - OPL3_SlotGenerate(&chip->slot[12]); - OPL3_SlotGenerate(&chip->slot[13]); - OPL3_SlotGenerate(&chip->slot[14]); - } - chip->mixbuff[0] = 0; for (ii = 0; ii < 18; ii++) { @@ -1126,19 +1074,9 @@ void OPL3_Generate(opl3_chip *chip, Bit16s *buf) for (ii = 15; ii < 18; ii++) { OPL3_SlotCalcFB(&chip->slot[ii]); - OPL3_PhaseGenerate(&chip->slot[ii]); OPL3_EnvelopeCalc(&chip->slot[ii]); - } - - if (chip->rhy & 0x20) - { - OPL3_GenerateRhythm2(chip); - } - else - { - OPL3_SlotGenerate(&chip->slot[15]); - OPL3_SlotGenerate(&chip->slot[16]); - OPL3_SlotGenerate(&chip->slot[17]); + OPL3_PhaseGenerate(&chip->slot[ii]); + OPL3_SlotGenerate(&chip->slot[ii]); } buf[0] = OPL3_ClipSample(chip->mixbuff[0]); @@ -1146,8 +1084,8 @@ void OPL3_Generate(opl3_chip *chip, Bit16s *buf) for (ii = 18; ii < 33; ii++) { OPL3_SlotCalcFB(&chip->slot[ii]); - OPL3_PhaseGenerate(&chip->slot[ii]); OPL3_EnvelopeCalc(&chip->slot[ii]); + OPL3_PhaseGenerate(&chip->slot[ii]); OPL3_SlotGenerate(&chip->slot[ii]); } @@ -1165,13 +1103,11 @@ void OPL3_Generate(opl3_chip *chip, Bit16s *buf) for (ii = 33; ii < 36; ii++) { OPL3_SlotCalcFB(&chip->slot[ii]); - OPL3_PhaseGenerate(&chip->slot[ii]); OPL3_EnvelopeCalc(&chip->slot[ii]); + OPL3_PhaseGenerate(&chip->slot[ii]); OPL3_SlotGenerate(&chip->slot[ii]); } - OPL3_NoiseGenerate(chip); - if ((chip->timer & 0x3f) == 0x3f) { chip->tremolopos = (chip->tremolopos + 1) % 210; @@ -1191,6 +1127,52 @@ void OPL3_Generate(opl3_chip *chip, Bit16s *buf) } chip->timer++; + + chip->eg_add = 0; + if (chip->eg_timer) + { + while (shift < 36 && ((chip->eg_timer >> shift) & 1) == 0) + { + shift++; + } + if (shift > 12) + { + chip->eg_add = 0; + } + else + { + chip->eg_add = shift + 1; + } + } + + if (chip->eg_timerrem || chip->eg_state) + { + if (chip->eg_timer == 0xfffffffff) + { + chip->eg_timer = 0; + chip->eg_timerrem = 1; + } + else + { + chip->eg_timer++; + chip->eg_timerrem = 0; + } + } + + chip->eg_state ^= 1; + + while (chip->writebuf[chip->writebuf_cur].time <= chip->writebuf_samplecnt) + { + if (!(chip->writebuf[chip->writebuf_cur].reg & 0x200)) + { + break; + } + chip->writebuf[chip->writebuf_cur].reg &= 0x1ff; + OPL3_WriteReg(chip, chip->writebuf[chip->writebuf_cur].reg, + chip->writebuf[chip->writebuf_cur].data); + chip->writebuf_cur = (chip->writebuf_cur + 1) % OPL_WRITEBUF_SIZE; + } + chip->writebuf_samplecnt++; } void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf) @@ -1221,8 +1203,9 @@ void OPL3_Reset(opl3_chip *chip, Bit32u samplerate) chip->slot[slotnum].mod = &chip->zeromod; chip->slot[slotnum].eg_rout = 0x1ff; chip->slot[slotnum].eg_out = 0x1ff; - chip->slot[slotnum].eg_gen = envelope_gen_num_off; + chip->slot[slotnum].eg_gen = envelope_gen_num_release; chip->slot[slotnum].trem = (Bit8u*)&chip->zeromod; + chip->slot[slotnum].slot_num = slotnum; } for (channum = 0; channum < 18; channum++) { @@ -1244,11 +1227,12 @@ void OPL3_Reset(opl3_chip *chip, Bit32u samplerate) chip->channel[channum].out[2] = &chip->zeromod; chip->channel[channum].out[3] = &chip->zeromod; chip->channel[channum].chtype = ch_2op; - chip->channel[channum].cha = ~0; - chip->channel[channum].chb = ~0; + chip->channel[channum].cha = 0xffff; + chip->channel[channum].chb = 0xffff; + chip->channel[channum].ch_num = channum; OPL3_ChannelSetupAlg(&chip->channel[channum]); } - chip->noise = 0x306600; + chip->noise = 1; chip->rateratio = (samplerate << RSM_FRAC) / 49716; chip->tremoloshift = 4; chip->vibshift = 1; @@ -1363,6 +1347,34 @@ void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v) } } +void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v) +{ + Bit64u time1, time2; + + if (chip->writebuf[chip->writebuf_last].reg & 0x200) + { + OPL3_WriteReg(chip, chip->writebuf[chip->writebuf_last].reg & 0x1ff, + chip->writebuf[chip->writebuf_last].data); + + chip->writebuf_cur = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE; + chip->writebuf_samplecnt = chip->writebuf[chip->writebuf_last].time; + } + + chip->writebuf[chip->writebuf_last].reg = reg | 0x200; + chip->writebuf[chip->writebuf_last].data = v; + time1 = chip->writebuf_lasttime + OPL_WRITEBUF_DELAY; + time2 = chip->writebuf_samplecnt; + + if (time1 < time2) + { + time1 = time2; + } + + chip->writebuf[chip->writebuf_last].time = time1; + chip->writebuf_lasttime = time1; + chip->writebuf_last = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE; +} + void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples) { Bit32u i; diff --git a/src/sound/nukedopl.h b/src/sound/nukedopl.h index aa389feb0..9570298fb 100644 --- a/src/sound/nukedopl.h +++ b/src/sound/nukedopl.h @@ -1,7 +1,16 @@ -/* Copyright holders: Alexey Khokholov (Nuke.YKT) - see COPYING for more details -*/ - +// +// Copyright (C) 2013-2018 Alexey Khokholov (Nuke.YKT) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// // // Nuked OPL3 emulator. // Thanks: @@ -11,10 +20,16 @@ // Tremolo and phase generator calculation information. // OPLx decapsulated(Matthew Gambrell, Olli Niemitalo): // OPL2 ROMs. +// siliconpr0n.org(John McMaster, digshadow): +// YMF262 and VRC VII decaps and die shots. +// +// version: 1.8 // #ifndef NUKEDOPL_H #define NUKEDOPL_H +#define OPL_WRITEBUF_SIZE 1024 +#define OPL_WRITEBUF_DELAY 1 //#include "dosbox.h" #include @@ -26,10 +41,12 @@ typedef int16_t Bit16s; typedef uint16_t Bit16u; typedef int32_t Bit32s; typedef uint32_t Bit32u; +typedef int64_t Bit64s; +typedef uint64_t Bit64u; -struct opl3_chip; struct opl3_slot; struct opl3_channel; +struct opl3_chip; struct opl3_slot { opl3_channel *channel; @@ -57,8 +74,10 @@ struct opl3_slot { Bit8u reg_rr; Bit8u reg_wf; Bit8u key; + Bit32u pg_reset; Bit32u pg_phase; - Bit32u timer; + Bit16u pg_phase_out; + Bit8u slot_num; }; struct opl3_channel { @@ -74,12 +93,23 @@ struct opl3_channel { Bit8u alg; Bit8u ksv; Bit16u cha, chb; + Bit8u ch_num; +}; + +struct opl3_writebuf { + Bit64u time; + Bit16u reg; + Bit8u data; }; struct opl3_chip { opl3_channel channel[18]; opl3_slot slot[36]; Bit16u timer; + Bit64u eg_timer; + Bit8u eg_timerrem; + Bit8u eg_state; + Bit8u eg_add; Bit8u newm; Bit8u nts; Bit8u rhy; @@ -91,11 +121,23 @@ struct opl3_chip { Bit32u noise; Bit16s zeromod; Bit32s mixbuff[2]; - + Bit8u rm_hh_bit2; + Bit8u rm_hh_bit3; + Bit8u rm_hh_bit7; + Bit8u rm_hh_bit8; + Bit8u rm_tc_bit3; + Bit8u rm_tc_bit5; + //OPL3L Bit32s rateratio; Bit32s samplecnt; Bit16s oldsamples[2]; Bit16s samples[2]; + + Bit64u writebuf_samplecnt; + Bit32u writebuf_cur; + Bit32u writebuf_last; + Bit64u writebuf_lasttime; + opl3_writebuf writebuf[OPL_WRITEBUF_SIZE]; }; void OPL3_Generate(opl3_chip *chip, Bit16s *buf); @@ -103,5 +145,6 @@ void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf); void OPL3_Reset(opl3_chip *chip, Bit32u samplerate); Bit32u OPL3_WriteAddr(opl3_chip *chip, Bit32u port, Bit8u val); void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v); +void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v); void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples); #endif diff --git a/src/sound/openal.c b/src/sound/openal.c index 9483d1648..319623816 100644 --- a/src/sound/openal.c +++ b/src/sound/openal.c @@ -8,7 +8,7 @@ * * Interface to the OpenAL sound processing library. * - * Version: @(#)openal.c 1.0.5 2018/02/19 + * Version: @(#)openal.c 1.0.6 2018/04/23 * * Authors: Sarah Walker, * Miran Grca, @@ -22,7 +22,6 @@ #include #include #include -#ifdef USE_OPENAL # undef AL_API # undef ALC_API # define AL_LIBTYPE_STATIC @@ -30,7 +29,6 @@ # include # include # include -#endif #include "../86box.h" #include "sound.h" #include "midi.h" @@ -40,12 +38,10 @@ #define BUFLEN SOUNDBUFLEN -#ifdef USE_OPENAL ALuint buffers[4]; /* front and back buffers */ ALuint buffers_cd[4]; /* front and back buffers */ ALuint buffers_midi[4]; /* front and back buffers */ static ALuint source[3]; /* audio source */ -#endif static int midi_freq = 44100; @@ -61,7 +57,6 @@ al_set_midi(int freq, int buf_size) } -#ifdef USE_OPENAL void closeal(void); ALvoid alutInit(ALint *argc,ALbyte **argv) { @@ -104,27 +99,15 @@ alutExit(ALvoid) alcDestroyContext(Context); } } -#endif void closeal(void) { -#ifdef USE_OPENAL + if (!initialized) return; + alutExit(); -#endif -} - -void -initalmain(int argc, char *argv[]) -{ - if (! initialized) return; - -#ifdef USE_OPENAL - alutInit(0,0); - atexit(closeal); -#endif initialized = 0; } @@ -141,13 +124,14 @@ inital(void) if (initialized) return; + alutInit(0, 0); + atexit(closeal); + mdn = midi_device_get_internal_name(midi_device_current); if (strcmp(mdn, "none") && strcmp(mdn, SYSTEM_MIDI_INTERNAL_NAME)) init_midi = 1; /* If the device is neither none, nor system MIDI, initialize the MIDI buffer and source, otherwise, do not. */ -#ifdef USE_OPENAL - if (sound_is_float) { buf = (float *) malloc((BUFLEN << 1) * sizeof(float)); cd_buf = (float *) malloc((CD_BUFLEN << 1) * sizeof(float)); @@ -236,14 +220,12 @@ inital(void) } initialized = 1; -#endif } void givealbuffer_common(void *buf, uint8_t src, int size, int freq) { -#ifdef USE_OPENAL int processed; int state; ALuint buffer; @@ -270,7 +252,6 @@ givealbuffer_common(void *buf, uint8_t src, int size, int freq) alSourceQueueBuffers(source[src], 1, &buffer); } -#endif } diff --git a/src/sound/snd_adlib.c b/src/sound/snd_adlib.c index cc9733bc5..0628ec932 100644 --- a/src/sound/snd_adlib.c +++ b/src/sound/snd_adlib.c @@ -1,8 +1,10 @@ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../io.h" #include "../mca.h" @@ -12,6 +14,26 @@ #include "snd_opl.h" +#ifdef ENABLE_ADLIB_LOG +int adlib_do_log = ENABLE_ADLIB_LOG; +#endif + + +static void +adlib_log(const char *fmt, ...) +{ +#ifdef ENABLE_ADLIB_LOG + va_list ap; + + if (adlib_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + typedef struct adlib_t { opl_t opl; @@ -37,7 +59,7 @@ uint8_t adlib_mca_read(int port, void *p) { adlib_t *adlib = (adlib_t *)p; - pclog("adlib_mca_read: port=%04x\n", port); + adlib_log("adlib_mca_read: port=%04x\n", port); return adlib->pos_regs[port & 7]; } @@ -49,7 +71,7 @@ void adlib_mca_write(int port, uint8_t val, void *p) if (port < 0x102) return; - pclog("adlib_mca_write: port=%04x val=%02x\n", port, val); + adlib_log("adlib_mca_write: port=%04x val=%02x\n", port, val); switch (port) { @@ -68,7 +90,7 @@ void *adlib_init(const device_t *info) adlib_t *adlib = malloc(sizeof(adlib_t)); memset(adlib, 0, sizeof(adlib_t)); - pclog("adlib_init\n"); + adlib_log("adlib_init\n"); opl2_init(&adlib->opl); io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl); sound_add_handler(adlib_get_buffer, adlib); @@ -100,7 +122,7 @@ const device_t adlib_device = DEVICE_ISA, 0, adlib_init, adlib_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; @@ -110,6 +132,6 @@ const device_t adlib_mca_device = DEVICE_MCA, 0, adlib_init, adlib_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; diff --git a/src/sound/snd_adlibgold.c b/src/sound/snd_adlibgold.c index 02e692491..178095702 100644 --- a/src/sound/snd_adlibgold.c +++ b/src/sound/snd_adlibgold.c @@ -10,9 +10,9 @@ #include "../pit.h" #include "../mem.h" #include "../rom.h" +#include "../device.h" #include "../nvr.h" #include "../timer.h" -#include "../device.h" #include "sound.h" #include "filters.h" #include "snd_opl.h" @@ -847,6 +847,5 @@ const device_t adgold_device = NULL, NULL, NULL, - NULL, adgold_config }; diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index a7e0257a9..999c91d4e 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -1217,6 +1217,8 @@ static void generate_es1371_filter() for (n = 0; n < ES1371_NCoef; n++) gain += low_fir_es1371_coef[n] / (float)N; + gain /= 0.95; + /*Normalise filter, to produce unity gain*/ for (n = 0; n < ES1371_NCoef; n++) low_fir_es1371_coef[n] /= gain; @@ -1292,14 +1294,6 @@ void es1371_add_status_info_dac(es1371_t *es1371, char *s, int max_len, int dac_ } } -void es1371_add_status_info(char *s, int max_len, void *p) -{ - es1371_t *es1371 = (es1371_t *)p; - - es1371_add_status_info_dac(es1371, s, max_len, 0); - es1371_add_status_info_dac(es1371, s, max_len, 1); -} - const device_t es1371_device = { "Ensoniq AudioPCI (ES1371)", @@ -1311,6 +1305,5 @@ const device_t es1371_device = NULL, es1371_speed_changed, NULL, - es1371_add_status_info, NULL }; diff --git a/src/sound/snd_cms.c b/src/sound/snd_cms.c index ce416650a..5d3e73c8d 100644 --- a/src/sound/snd_cms.c +++ b/src/sound/snd_cms.c @@ -1,8 +1,10 @@ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../io.h" #include "../device.h" @@ -180,7 +182,6 @@ void *cms_init(const device_t *info) cms_t *cms = malloc(sizeof(cms_t)); memset(cms, 0, sizeof(cms_t)); - pclog("cms_init\n"); io_sethandler(0x0220, 0x0010, cms_read, NULL, NULL, cms_write, NULL, NULL, cms); sound_add_handler(cms_get_buffer, cms); return cms; @@ -198,6 +199,6 @@ const device_t cms_device = "Creative Music System / Game Blaster", 0, 0, cms_init, cms_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; diff --git a/src/sound/snd_dbopl.cc b/src/sound/snd_dbopl.cc index 94480ad4f..78840f4a6 100644 --- a/src/sound/snd_dbopl.cc +++ b/src/sound/snd_dbopl.cc @@ -3,23 +3,24 @@ */ #include "dbopl.h" #include "nukedopl.h" +#include "sound.h" #include "snd_dbopl.h" -int opl3_type = 0; +int opl_type = 0; static struct { DBOPL::Chip chip; - struct opl3_chip opl3chip; + opl3_chip opl3chip; int addr; int timer[2]; uint8_t timer_ctrl; uint8_t status_mask; uint8_t status; int is_opl3; - + void (*timer_callback)(void *param, int timer, int64_t period); void *timer_param; } opl[2]; @@ -42,20 +43,19 @@ enum void opl_init(void (*timer_callback)(void *param, int timer, int64_t period), void *timer_param, int nr, int is_opl3) { - if (!is_opl3 || !opl3_type) + opl[nr].timer_callback = timer_callback; + opl[nr].timer_param = timer_param; + opl[nr].is_opl3 = is_opl3; + + if (!opl_type) { - DBOPL::InitTables(); - opl[nr].chip.Setup(48000, is_opl3); - opl[nr].timer_callback = timer_callback; - opl[nr].timer_param = timer_param; - opl[nr].is_opl3 = is_opl3; + DBOPL::InitTables(); + opl[nr].chip.Setup(48000, is_opl3); } else { - OPL3_Reset(&opl[nr].opl3chip, 48000); - opl[nr].timer_callback = timer_callback; - opl[nr].timer_param = timer_param; - opl[nr].is_opl3 = is_opl3; + opl[nr].opl3chip.newm = 0; + OPL3_Reset(&opl[nr].opl3chip, 48000); } } @@ -87,17 +87,22 @@ void opl_write(int nr, uint16_t addr, uint8_t val) { if (!(addr & 1)) { - if (!opl[nr].is_opl3 || !opl3_type) - opl[nr].addr = (int)opl[nr].chip.WriteAddr(addr, val) & (opl[nr].is_opl3 ? 0x1ff : 0xff); + if (!opl_type) + opl[nr].addr = (int)opl[nr].chip.WriteAddr(addr, val) & 0x1ff; else opl[nr].addr = (int)OPL3_WriteAddr(&opl[nr].opl3chip, addr, val) & 0x1ff; + if (!opl[nr].is_opl3) + opl[nr].addr &= 0xff; } else { - if (!opl[nr].is_opl3 || !opl3_type) + if (!opl_type) opl[nr].chip.WriteReg(opl[nr].addr, val); - else - OPL3_WriteReg(&opl[nr].opl3chip, opl[nr].addr, val); + else { + OPL3_WriteRegBuffered(&opl[nr].opl3chip, (uint16_t) opl[nr].addr, val); + if (opl[nr].addr == 0x105) + opl[nr].opl3chip.newm = opl[nr].addr & 0x01; + } switch (opl[nr].addr) { @@ -148,20 +153,27 @@ uint8_t opl_read(int nr, uint16_t addr) void opl2_update(int nr, int16_t *buffer, int samples) { int c; - Bit32s buffer_32[samples]; - - opl[nr].chip.GenerateBlock2(samples, buffer_32); - - for (c = 0; c < samples; c++) - buffer[c*2] = (int16_t)buffer_32[c]; + Bit32s buffer_32[SOUNDBUFLEN]; + + if (opl_type) + { + OPL3_GenerateStream(&opl[nr].opl3chip, buffer, samples); + } + else + { + opl[nr].chip.GenerateBlock2(samples, buffer_32); + + for (c = 0; c < samples; c++) + buffer[c*2] = (int16_t)buffer_32[c]; + } } void opl3_update(int nr, int16_t *buffer, int samples) { int c; - Bit32s buffer_32[samples*2]; + Bit32s buffer_32[SOUNDBUFLEN*2]; - if (opl3_type) + if (opl_type) { OPL3_GenerateStream(&opl[nr].opl3chip, buffer, samples); } diff --git a/src/sound/snd_dbopl.h b/src/sound/snd_dbopl.h index 6fd536f39..ca6299724 100644 --- a/src/sound/snd_dbopl.h +++ b/src/sound/snd_dbopl.h @@ -11,7 +11,7 @@ extern "C" { void opl2_update(int nr, int16_t *buffer, int samples); void opl3_update(int nr, int16_t *buffer, int samples); - extern int opl3_type; + extern int opl_type; #ifdef __cplusplus } #endif diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index d08b01da8..3bd367e63 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -1,8 +1,10 @@ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../io.h" #include "../nmi.h" @@ -1006,8 +1008,6 @@ void *gus_init(const device_t *info) gus->ram = malloc(1 << 20); memset(gus->ram, 0, 1 << 20); - pclog("gus_init\n"); - for (c=0;c<32;c++) { gus->ctrl[c]=1; @@ -1020,7 +1020,6 @@ void *gus_init(const device_t *info) out/=1.002709201; /* 0.0235 dB Steps */ } - pclog("GUS: top volume %f %f %f %f\n",vol16bit[4095],vol16bit[3800],vol16bit[3000],vol16bit[2048]); gus->voices=14; gus->samp_timer = gus->samp_latch = (int64_t)(TIMER_USEC * (1000000.0 / 44100.0)); @@ -1063,6 +1062,6 @@ const device_t gus_device = "Gravis UltraSound", 0, 0, gus_init, gus_close, NULL, NULL, - gus_speed_changed, NULL, NULL, + gus_speed_changed, NULL, NULL }; diff --git a/src/sound/snd_mpu401.c b/src/sound/snd_mpu401.c index a885d72d3..4bc619d90 100644 --- a/src/sound/snd_mpu401.c +++ b/src/sound/snd_mpu401.c @@ -8,7 +8,7 @@ * * Roland MPU-401 emulation. * - * Version: @(#)snd_mpu401.c 1.0.8 2018/03/18 + * Version: @(#)snd_mpu401.c 1.0.10 2018/04/29 * * Authors: Sarah Walker, * DOSBox Team, @@ -19,12 +19,14 @@ * Copyright 2008-2018 DOSBox Team. * Copyright 2016-2018 Miran Grca. */ -#include +#include #include +#include #include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../device.h" #include "../io.h" @@ -47,33 +49,29 @@ static int64_t mpu401_event_callback = 0LL; static int64_t mpu401_eoi_callback = 0LL; static int64_t mpu401_reset_callback = 0LL; -#ifdef ENABLE_MPU401_LOG -static int mpu401_do_log = ENABLE_MPU401_LOG; -static char logfmt[512]; -#endif - static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val); static void MPU401_EOIHandlerDispatch(void *p); +#ifdef ENABLE_MPU401_LOG +int mpu401_do_log = ENABLE_MPU401_LOG; +#endif + + static void -mpulog(const char *fmt, ...) +mpu401_log(const char *fmt, ...) { #ifdef ENABLE_MPU401_LOG va_list ap; if (mpu401_do_log) { va_start(ap, fmt); - memset(logfmt, 0, 512); - strcpy(logfmt, "MPU-401: "); - strcpy(logfmt + strlen(logfmt), fmt); - vprintf(logfmt, ap); + pclog_ex(fmt, ap); va_end(ap); } #endif } -#define pclog mpulog static void @@ -100,7 +98,7 @@ QueueByte(mpu_t *mpu, uint8_t data) mpu->queue_used++; mpu->queue[pos]=data; } else - pclog("MPU401:Data queue full\n"); + mpu401_log("MPU401:Data queue full\n"); } @@ -161,7 +159,7 @@ MPU401_ResetDone(void *priv) { mpu_t *mpu = (mpu_t *)priv; - pclog("MPU-401 reset callback\n"); + mpu401_log("MPU-401 reset callback\n"); mpu401_reset_callback = 0LL; @@ -197,10 +195,6 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) break; } -#if 0 - if (val&0x20) - pclog("MPU-401:Unhandled Recording Command %x",(int)val); -#endif switch (val & 0xc) { case 0x4: /* Stop */ mpu->state.playing = 0; @@ -215,7 +209,6 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) break; case 0x8: /* Play */ -// pclog("MPU-401:Intelligent mode playback started"); mpu->state.playing = 1; mpu401_event_callback = (MPU401_TIMECONSTANT / (mpu->clock.tempo*mpu->clock.timebase)) * 1000LL * TIMER_USEC; ClrQueue(mpu); @@ -332,7 +325,7 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) break; case 0xff: /* Reset MPU-401 */ - pclog("MPU-401:Reset %X\n",val); + mpu401_log("MPU-401:Reset %X\n",val); mpu401_reset_callback = MPU401_RESETBUSY * 33LL * TIMER_USEC; mpu->state.reset=1; MPU401_Reset(mpu); @@ -342,12 +335,12 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) break; case 0x3f: /* UART mode */ - pclog("MPU-401:Set UART mode %X\n",val); + mpu401_log("MPU-401:Set UART mode %X\n",val); mpu->mode=M_UART; break; default:; - //pclog("MPU-401:Unhandled command %X",val); + //mpu401_log("MPU-401:Unhandled command %X",val); } QueueByte(mpu, MSG_MPU_ACK); @@ -371,7 +364,7 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) case 0xe1: /* Set relative tempo */ mpu->state.command_byte=0; if (val!=0x40) //default value - pclog("MPU-401:Relative tempo change not implemented\n"); + mpu401_log("MPU-401:Relative tempo change not implemented\n"); return; case 0xe7: /* Set internal clock to host interval */ @@ -428,7 +421,7 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) break; case 0xf0: - //pclog("MPU-401:Illegal WSD byte\n"); + //mpu401_log("MPU-401:Illegal WSD byte\n"); mpu->state.wsd=0; mpu->state.channel=mpu->state.old_chan; return; @@ -656,7 +649,7 @@ MPU401_EOIHandler(void *priv) mpu_t *mpu = (mpu_t *)priv; uint8_t i; - pclog("MPU-401 end of input callback\n"); + mpu401_log("MPU-401 end of input callback\n"); mpu401_eoi_callback = 0LL; mpu->state.eoi_scheduled=0; @@ -697,7 +690,7 @@ MPU401_EOIHandlerDispatch(void *priv) static void imf_write(uint16_t addr, uint8_t val, void *priv) { - pclog("IMF:Wr %4X,%X\n", addr, val); + mpu401_log("IMF:Wr %4X,%X\n", addr, val); } @@ -750,16 +743,16 @@ mpu401_write(uint16_t addr, uint8_t val, void *priv) { mpu_t *mpu = (mpu_t *)priv; - /* pclog("MPU401 Write Port %04X, val %x\n", addr, val); */ + /* mpu401_log("MPU401 Write Port %04X, val %x\n", addr, val); */ switch (addr & 1) { case 0: /*Data*/ MPU401_WriteData(mpu, val); - pclog("Write Data (0x330) %X\n", val); + mpu401_log("Write Data (0x330) %X\n", val); break; case 1: /*Command*/ MPU401_WriteCommand(mpu, val); - pclog("Write Command (0x331) %x\n", val); + mpu401_log("Write Command (0x331) %x\n", val); break; } } @@ -774,7 +767,7 @@ mpu401_read(uint16_t addr, void *priv) switch (addr & 1) { case 0: //Read Data ret = MPU401_ReadData(mpu); - pclog("Read Data (0x330) %X\n", ret); + mpu401_log("Read Data (0x330) %X\n", ret); break; case 1: //Read Status @@ -782,11 +775,11 @@ mpu401_read(uint16_t addr, void *priv) if (!mpu->queue_used) ret=STATUS_INPUT_NOT_READY; ret |= 0x3f; //FIXME: check with MPU401 TechRef - pclog("Read Status (0x331) %x\n", ret); + mpu401_log("Read Status (0x331) %x\n", ret); break; } - /* pclog("MPU401 Read Port %04X, ret %x\n", addr, ret); */ + /* mpu401_log("MPU401 Read Port %04X, ret %x\n", addr, ret); */ return(ret); } @@ -798,7 +791,7 @@ MPU401_Event(void *priv) int new_time; uint8_t i; - pclog("MPU-401 event callback\n"); + mpu401_log("MPU-401 event callback\n"); if (mpu->mode==M_UART) { mpu401_event_callback = 0LL; @@ -838,7 +831,7 @@ next_event: return; } else { mpu401_event_callback += (MPU401_TIMECONSTANT/new_time) * 1000LL * TIMER_USEC; - pclog("Next event after %i us (time constant: %i)\n", (int) ((MPU401_TIMECONSTANT/new_time) * 1000 * TIMER_USEC), (int) MPU401_TIMECONSTANT); + mpu401_log("Next event after %i us (time constant: %i)\n", (int) ((MPU401_TIMECONSTANT/new_time) * 1000 * TIMER_USEC), (int) MPU401_TIMECONSTANT); } } @@ -860,7 +853,7 @@ mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode) mpu->mode = M_UART; mpu->intelligent = (mode == M_INTELLIGENT) ? 1 : 0; - pclog("Starting as %s (mode is %s)\n", mpu->intelligent ? "INTELLIGENT" : "UART", (mode == M_INTELLIGENT) ? "INTELLIGENT" : "UART"); + mpu401_log("Starting as %s (mode is %s)\n", mpu->intelligent ? "INTELLIGENT" : "UART", (mode == M_INTELLIGENT) ? "INTELLIGENT" : "UART"); mpu401_event_callback = 0LL; mpu401_eoi_callback = 0LL; @@ -902,7 +895,7 @@ mpu401_standalone_init(const device_t *info) mpu = malloc(sizeof(mpu_t)); memset(mpu, 0, sizeof(mpu_t)); - pclog("mpu_init\n"); + mpu401_log("mpu_init\n"); mpu401_init(mpu, device_get_config_hex16("base"), device_get_config_int("irq"), device_get_config_int("mode")); return(mpu); @@ -987,6 +980,5 @@ const device_t mpu401_device = { NULL, NULL, NULL, - NULL, mpu401_standalone_config }; diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index 5a0c4738d..e93bdfcb6 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -1,8 +1,10 @@ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../cpu/cpu.h" #include "../io.h" @@ -176,6 +178,27 @@ enum PAS16_FILT_MUTE = 0x20 }; + +#ifdef ENABLE_PAS16_LOG +int pas16_do_log = ENABLE_PAS16_LOG; +#endif + + +static void +pas16_log(const char *fmt, ...) +{ +#ifdef ENABLE_PAS16_LOG + va_list ap; + + if (pas16_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + static uint8_t pas16_in(uint16_t port, void *p) { pas16_t *pas16 = (pas16_t *)p; @@ -272,7 +295,7 @@ static uint8_t pas16_in(uint16_t port, void *p) temp = 0xff; break; } -/* if (port != 0x388 && port != 0x389 && port != 0xb8b) */pclog("pas16_in : port %04X return %02X %04X:%04X\n", port, temp, CS,cpu_state.pc); +/* if (port != 0x388 && port != 0x389 && port != 0xb8b) */pas16_log("pas16_in : port %04X return %02X %04X:%04X\n", port, temp, CS,cpu_state.pc); /* if (CS == 0x1FF4 && pc == 0x0585) { if (output) @@ -285,7 +308,7 @@ static uint8_t pas16_in(uint16_t port, void *p) static void pas16_out(uint16_t port, uint8_t val, void *p) { pas16_t *pas16 = (pas16_t *)p; -/* if (port != 0x388 && port != 0x389) */pclog("pas16_out : port %04X val %02X %04X:%04X\n", port, val, CS,cpu_state.pc); +/* if (port != 0x388 && port != 0x389) */pas16_log("pas16_out : port %04X val %02X %04X:%04X\n", port, val, CS,cpu_state.pc); /* if (CS == 0x369 && pc == 0x2AC5) fatal("here\n");*/ switch ((port - pas16->base) + 0x388) @@ -352,12 +375,12 @@ static void pas16_out(uint16_t port, uint8_t val, void *p) case 0xf389: pas16->io_conf_2 = val; pas16->dma = pas16_dmas[val & 0x7]; - pclog("pas16_out : set PAS DMA %i\n", pas16->dma); + pas16_log("pas16_out : set PAS DMA %i\n", pas16->dma); break; case 0xf38a: pas16->io_conf_3 = val; pas16->irq = pas16_irqs[val & 0xf]; - pclog("pas16_out : set PAS IRQ %i\n", pas16->irq); + pas16_log("pas16_out : set PAS IRQ %i\n", pas16->irq); break; case 0xf38b: pas16->io_conf_4 = val; @@ -380,11 +403,11 @@ static void pas16_out(uint16_t port, uint8_t val, void *p) pas16->sb_irqdma = val; sb_dsp_setirq(&pas16->dsp, pas16_sb_irqs[(val >> 3) & 7]); sb_dsp_setdma8(&pas16->dsp, pas16_sb_dmas[(val >> 6) & 3]); - pclog("pas16_out : set SB IRQ %i DMA %i\n", pas16_sb_irqs[(val >> 3) & 7], pas16_sb_dmas[(val >> 6) & 3]); + pas16_log("pas16_out : set SB IRQ %i DMA %i\n", pas16_sb_irqs[(val >> 3) & 7], pas16_sb_dmas[(val >> 6) & 3]); break; default: - pclog("pas16_out : unknown %04X\n", port); + pas16_log("pas16_out : unknown %04X\n", port); } if (cpu_state.pc == 0x80048CF3) { @@ -417,7 +440,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p) pas16->pit.ctrls[t] = pas16->pit.ctrl = val; if (t == 3) { - pclog("PAS16: bad PIT reg select\n"); + pas16_log("PAS16: bad PIT reg select\n"); return; } if (!(pas16->pit.ctrl & 0x30)) @@ -627,7 +650,7 @@ static void pas16_pcm_poll(void *p) pas16->irq_stat |= PAS16_INT_PCM; if (pas16->irq_ena & PAS16_INT_PCM) { - pclog("pas16_pcm_poll : cause IRQ %i %02X\n", pas16->irq, 1 << pas16->irq); + pas16_log("pas16_pcm_poll : cause IRQ %i %02X\n", pas16->irq, 1 << pas16->irq); picint(1 << pas16->irq); } } @@ -658,7 +681,7 @@ static void pas16_out_base(uint16_t port, uint8_t val, void *p) io_removehandler((pas16->base - 0x388) + 0xff88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); pas16->base = val << 2; - pclog("pas16_write_base : PAS16 base now at %04X\n", pas16->base); + pas16_log("pas16_write_base : PAS16 base now at %04X\n", pas16->base); io_sethandler((pas16->base - 0x388) + 0x0388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); io_sethandler((pas16->base - 0x388) + 0x0788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); @@ -752,6 +775,6 @@ const device_t pas16_device = DEVICE_ISA | DEVICE_NOT_WORKING, 0, pas16_init, pas16_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; diff --git a/src/sound/snd_pssj.c b/src/sound/snd_pssj.c index 2e200c589..1b6af8caf 100644 --- a/src/sound/snd_pssj.c +++ b/src/sound/snd_pssj.c @@ -214,6 +214,5 @@ const device_t pssj_device = NULL, NULL, NULL, - NULL, NULL }; diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index c4c4ff255..c2831ece9 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -8,7 +8,7 @@ * * Sound Blaster emulation. * - * Version: @(#)sound_sb.c 1.0.6 2018/03/18 + * Version: @(#)sound_sb.c 1.0.9 2018/04/29 * * Authors: Sarah Walker, * Miran Grca, @@ -17,11 +17,13 @@ * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../io.h" #include "../mca.h" @@ -134,6 +136,9 @@ typedef struct sb_t }; mpu_t mpu; emu8k_t emu8k; +#if 0 + sb_ct1745_mixer_t temp_mixer_sb16; +#endif int pos; @@ -165,6 +170,27 @@ const int32_t sb_att_7dbstep_2bits[]= 164,6537,14637,32767 }; + +#ifdef ENABLE_SB_LOG +int sb_do_log = ENABLE_SB_LOG; +#endif + + +static void +sb_log(const char *fmt, ...) +{ +#ifdef ENABLE_SB_LOG + va_list ap; + + if (sb_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + /* sb 1, 1.5, 2, 2 mvc do not have a mixer, so signal is hardwired */ static void sb_get_buffer_sb2(int32_t *buffer, int len, void *p) { @@ -272,10 +298,12 @@ static void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p) sb->dsp.pos = 0; } +// FIXME: See why this causes weird audio glitches in some situations. +#if 0 static void sb_process_buffer_sb16(int32_t *buffer, int len, void *p) { sb_t *sb = (sb_t *)p; - sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; + sb_ct1745_mixer_t *mixer = &sb->temp_mixer_sb16; int c; @@ -283,8 +311,8 @@ static void sb_process_buffer_sb16(int32_t *buffer, int len, void *p) { int32_t out_l = 0, out_r = 0; - out_l = ((int32_t)(buffer[c] * mixer->cd_l) / 3) >> 15; - out_r = ((int32_t)(buffer[c + 1] * mixer->cd_r) / 3) >> 15; + out_l = ((int32_t)(low_fir_sb16(0, (float)buffer[c]) * mixer->cd_l) / 3) >> 15; + out_r = ((int32_t)(low_fir_sb16(1, (float)buffer[c + 1]) * mixer->cd_r) / 3) >> 15; out_l = (out_l * mixer->master_l) >> 15; out_r = (out_r * mixer->master_r) >> 15; @@ -306,6 +334,7 @@ static void sb_process_buffer_sb16(int32_t *buffer, int len, void *p) buffer[c + 1] = (out_r << mixer->output_gain_R); } } +#endif static void sb_get_buffer_sb16(int32_t *buffer, int len, void *p) { @@ -378,6 +407,9 @@ static void sb_get_buffer_sb16(int32_t *buffer, int len, void *p) sb->pos = 0; sb->opl.pos = 0; sb->dsp.pos = 0; +#if 0 + memcpy(&sb->temp_mixer_sb16, &sb->mixer_sb16, sizeof(sb_ct1745_mixer_t)); +#endif } #ifdef SB_DSP_RECORD_DEBUG int old_dsp_rec_pos=0; @@ -488,6 +520,9 @@ static void sb_get_buffer_emu8k(int32_t *buffer, int len, void *p) sb->opl.pos = 0; sb->dsp.pos = 0; sb->emu8k.pos = 0; +#if 0 + memcpy(&sb->temp_mixer_sb16, &sb->mixer_sb16, sizeof(sb_ct1745_mixer_t)); +#endif } @@ -521,7 +556,7 @@ void sb_ct1335_mixer_write(uint16_t addr, uint8_t val, void *p) break; default: - /* pclog("sb_ct1335: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); */ + sb_log("sb_ct1335: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); break; } } @@ -548,7 +583,7 @@ uint8_t sb_ct1335_mixer_read(uint16_t addr, void *p) case 0x00: case 0x02: case 0x06: case 0x08: case 0x0A: return mixer->regs[mixer->index]; default: - /* pclog("sb_ct1335: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); */ + sb_log("sb_ct1335: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); break; } @@ -612,7 +647,7 @@ void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p) default: - /* pclog("sb_ct1345: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); */ + sb_log("sb_ct1345: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); break; } } @@ -672,7 +707,7 @@ uint8_t sb_ct1345_mixer_read(uint16_t addr, void *p) return mixer->regs[mixer->index]; default: - /* pclog("sb_ct1345: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); */ + sb_log("sb_ct1345: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); break; } @@ -819,7 +854,7 @@ void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p) /*TODO: pcspeaker volume, with "output_selector" check? or better not? */ sound_set_cd_volume(((uint32_t)mixer->master_l * (uint32_t)mixer->cd_l) / 65535, ((uint32_t)mixer->master_r * (uint32_t)mixer->cd_r) / 65535); -// pclog("sb_ct1745: Received register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + sb_log("sb_ct1745: Received register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); } } @@ -831,7 +866,7 @@ uint8_t sb_ct1745_mixer_read(uint16_t addr, void *p) if (!(addr & 1)) return mixer->index; -// pclog("sb_ct1745: received register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + sb_log("sb_ct1745: received register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); if (mixer->index>=0x30 && mixer->index<=0x47) { @@ -913,7 +948,7 @@ uint8_t sb_ct1745_mixer_read(uint16_t addr, void *p) default: - /* pclog("sb_ct1745: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); */ + sb_log("sb_ct1745: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); break; } @@ -933,8 +968,8 @@ uint8_t sb_mcv_read(int port, void *p) { sb_t *sb = (sb_t *)p; - /* pclog("sb_mcv_read: port=%04x\n", port); */ - + sb_log("sb_mcv_read: port=%04x\n", port); + return sb->pos_regs[port & 7]; } @@ -946,7 +981,7 @@ void sb_mcv_write(int port, uint8_t val, void *p) if (port < 0x102) return; - /* pclog("sb_mcv_write: port=%04x val=%02x\n", port, val); */ + sb_log("sb_mcv_write: port=%04x val=%02x\n", port, val); addr = sb_mcv_addr[sb->pos_regs[4] & 7]; if (sb->opl_enabled) { @@ -977,8 +1012,8 @@ uint8_t sb_pro_mcv_read(int port, void *p) { sb_t *sb = (sb_t *)p; - /* pclog("sb_pro_mcv_read: port=%04x\n", port); */ - + sb_log("sb_pro_mcv_read: port=%04x\n", port); + return sb->pos_regs[port & 7]; } @@ -990,7 +1025,7 @@ void sb_pro_mcv_write(int port, uint8_t val, void *p) if (port < 0x102) return; - /* pclog("sb_pro_mcv_write: port=%04x val=%02x\n", port, val); */ + sb_log("sb_pro_mcv_write: port=%04x val=%02x\n", port, val); addr = (sb->pos_regs[2] & 0x20) ? 0x220 : 0x240; io_removehandler(addr+0, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); @@ -1103,6 +1138,12 @@ void *sb_2_init() "CD version" also uses 250h or 260h for 2x0 to 2x3 -> CDROM interface 2x4 to 2x5 -> Mixer interface*/ + /*My SB 2.0 mirrors the OPL2 at ports 2x0/2x1. Presumably this mirror is + disabled when the CMS chips are present. + This mirror may also exist on SB 1.5 & MCV, however I am unable to + test this. It shouldn't exist on SB 1.0 as the CMS chips are always + present there. + Syndicate requires this mirror for music to play.*/ sb_t *sb = malloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); memset(sb, 0, sizeof(sb_t)); @@ -1119,6 +1160,8 @@ void *sb_2_init() /* CMS I/O handler is activated on the dedicated sound_cms module DSP I/O handler is activated in sb_dsp_setaddr */ if (sb->opl_enabled) { + if (!GAMEBLASTER) + io_sethandler(addr, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); } @@ -1249,9 +1292,14 @@ void *sb_16_init() } io_sethandler(addr+4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb); sound_add_handler(sb_get_buffer_sb16, sb); +#if 0 sound_add_process_handler(sb_process_buffer_sb16, sb); +#endif mpu401_init(&sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq401"), device_get_config_int("mode401")); sb_dsp_set_mpu(&sb->mpu); +#if 0 + memcpy(&sb->temp_mixer_sb16, &sb->mixer_sb16, sizeof(sb_ct1745_mixer_t)); +#endif return sb; } @@ -1288,10 +1336,15 @@ void *sb_awe32_init() } io_sethandler(addr+4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb); sound_add_handler(sb_get_buffer_emu8k, sb); +#if 0 sound_add_process_handler(sb_process_buffer_sb16, sb); +#endif mpu401_init(&sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq401"), device_get_config_int("mode401")); sb_dsp_set_mpu(&sb->mpu); emu8k_init(&sb->emu8k, emu_addr, onboard_ram); +#if 0 + memcpy(&sb->temp_mixer_sb16, &sb->mixer_sb16, sizeof(sb_ct1745_mixer_t)); +#endif return sb; } @@ -1332,13 +1385,6 @@ void sb_speed_changed(void *p) sb_dsp_speed_changed(&sb->dsp); } -void sb_add_status_info(char *s, int max_len, void *p) -{ - sb_t *sb = (sb_t *)p; - - sb_dsp_add_status_info(s, max_len, &sb->dsp); -} - static const device_config_t sb_config[] = { { @@ -1823,7 +1869,6 @@ const device_t sb_1_device = sb_1_init, sb_close, NULL, NULL, sb_speed_changed, NULL, - sb_add_status_info, sb_config }; const device_t sb_15_device = @@ -1834,7 +1879,6 @@ const device_t sb_15_device = sb_15_init, sb_close, NULL, NULL, sb_speed_changed, NULL, - sb_add_status_info, sb_config }; const device_t sb_mcv_device = @@ -1845,7 +1889,6 @@ const device_t sb_mcv_device = sb_mcv_init, sb_close, NULL, NULL, sb_speed_changed, NULL, - sb_add_status_info, sb_mcv_config }; const device_t sb_2_device = @@ -1856,7 +1899,6 @@ const device_t sb_2_device = sb_2_init, sb_close, NULL, NULL, sb_speed_changed, NULL, - sb_add_status_info, sb_config }; const device_t sb_pro_v1_device = @@ -1867,7 +1909,6 @@ const device_t sb_pro_v1_device = sb_pro_v1_init, sb_close, NULL, NULL, sb_speed_changed, NULL, - sb_add_status_info, sb_pro_config }; const device_t sb_pro_v2_device = @@ -1878,7 +1919,6 @@ const device_t sb_pro_v2_device = sb_pro_v2_init, sb_close, NULL, NULL, sb_speed_changed, NULL, - sb_add_status_info, sb_pro_config }; const device_t sb_pro_mcv_device = @@ -1889,7 +1929,6 @@ const device_t sb_pro_mcv_device = sb_pro_mcv_init, sb_close, NULL, NULL, sb_speed_changed, NULL, - sb_add_status_info, NULL }; const device_t sb_16_device = @@ -1900,7 +1939,6 @@ const device_t sb_16_device = sb_16_init, sb_close, NULL, NULL, sb_speed_changed, NULL, - sb_add_status_info, sb_16_config }; const device_t sb_awe32_device = @@ -1912,6 +1950,5 @@ const device_t sb_awe32_device = sb_awe32_available, sb_speed_changed, NULL, - sb_add_status_info, sb_awe32_config }; diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index fd71a697d..d4dbf15e1 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -5,11 +5,13 @@ Pentium - 45kHz*/ #include -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../io.h" #include "../pic.h" @@ -29,17 +31,6 @@ void pollsb(void *p); void sb_poll_i(void *p); -//#define SB_DSP_RECORD_DEBUG -//#define SB_TEST_RECORDING_SAW - -#ifdef SB_DSP_RECORD_DEBUG -FILE* soundf = 0/*NULL*/; -#endif - -#ifdef SB_TEST_RECORDING_SAW -int counttest; -#endif - static int sbe2dat[4][9] = { { 0x01, -0x02, -0x04, 0x08, -0x10, 0x20, 0x40, -0x80, -106 }, { -0x01, 0x02, -0x04, 0x08, 0x10, -0x20, 0x40, -0x80, 165 }, @@ -119,6 +110,27 @@ uint16_t sb_dsp_versions[] = {0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x float low_fir_sb16_coef[SB16_NCoef]; + +#ifdef ENABLE_SB_DSP_LOG +int sb_dsp_do_log = ENABLE_SB_DSP_LOG; +#endif + + +static void +sb_dsp_log(const char *fmt, ...) +{ +#ifdef ENABLE_SB_DSP_LOG + va_list ap; + + if (sb_dsp_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + static inline double sinc(double x) { return sin(M_PI * x) / (M_PI * x); @@ -156,7 +168,7 @@ static void recalc_sb16_filter(int playback_freq) void sb_irq(sb_dsp_t *dsp, int irq8) { -// pclog("IRQ %i %02X\n",irq8,pic.mask); + sb_dsp_log("IRQ %i %02X\n",irq8,pic.mask); if (irq8) dsp->sb_irq8 = 1; else dsp->sb_irq16 = 1; picint(1 << dsp->sb_irqnum); @@ -195,14 +207,6 @@ void sb_dsp_reset(sb_dsp_t *dsp) picintc(1 << dsp->sb_irqnum); dsp->asp_data_len = 0; - - #ifdef SB_DSP_RECORD_DEBUG - if (soundf != 0) - { - fclose(soundf); - soundf=0; - } - #endif } void sb_doreset(sb_dsp_t *dsp) @@ -260,7 +264,6 @@ void sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len timer_update_outstanding(); dsp->sbleftright = 0; dsp->sbdacpos = 0; -// pclog("Start 8-bit DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len); } else { @@ -274,7 +277,6 @@ void sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len timer_process(); dsp->sbenable = dsp->sb_16_enable; timer_update_outstanding(); -// pclog("Start 16-bit DMA addr %06X len %04X\n",dma16.ac[1]+(dma16.page[1]<<16),len); } } @@ -282,13 +284,6 @@ void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int l { if (dma8) { -#ifdef SB_TEST_RECORDING_SAW - switch (dsp->sb_8_format) - { - case 00:case 20:counttest=0x80;break; - case 10:case 30:counttest=0;break; - } -#endif dsp->sb_8_length = len; dsp->sb_8_format = format; dsp->sb_8_autoinit = autoinit; @@ -299,17 +294,9 @@ void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int l timer_process(); dsp->sb_enable_i = dsp->sb_8_enable; timer_update_outstanding(); -// pclog("Start 8-bit input DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len); } else { -#ifdef SB_TEST_RECORDING_SAW - switch (dsp->sb_16_format) - { - case 00:case 20:counttest=0x8000;break; - case 10:case 30:counttest=0;break; - } -#endif dsp->sb_16_length = len; dsp->sb_16_format = format; dsp->sb_16_autoinit = autoinit; @@ -320,18 +307,8 @@ void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int l timer_process(); dsp->sb_enable_i = dsp->sb_16_enable; timer_update_outstanding(); -// pclog("Start 16-bit input DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len); } memset(dsp->record_buffer,0,sizeof(dsp->record_buffer)); - - #ifdef SB_DSP_RECORD_DEBUG - if (soundf != 0) - { - fclose(soundf); - soundf=0; - } - #endif - } int sb_8_read_dma(sb_dsp_t *dsp) @@ -341,22 +318,14 @@ int sb_8_read_dma(sb_dsp_t *dsp) void sb_8_write_dma(sb_dsp_t *dsp, uint8_t val) { dma_channel_write(dsp->sb_8_dmanum, val); -#ifdef SB_DSP_RECORD_DEBUG - if (!soundf) soundf=fopen("sound_dsp.pcm","wb"); - fwrite(&val,1,1,soundf); -#endif } -uint16_t sb_16_read_dma(sb_dsp_t *dsp) +int sb_16_read_dma(sb_dsp_t *dsp) { return dma_channel_read(dsp->sb_16_dmanum); } int sb_16_write_dma(sb_dsp_t *dsp, uint16_t val) { int ret = dma_channel_write(dsp->sb_16_dmanum, val); -#ifdef SB_DSP_RECORD_DEBUG - if (!soundf) soundf=fopen("sound_dsp.pcm","wb"); - fwrite(&val,2,1,soundf); -#endif return (ret == DMA_NODATA); } @@ -377,7 +346,7 @@ void sb_dsp_setdma16(sb_dsp_t *dsp, int dma) void sb_exec_command(sb_dsp_t *dsp) { int temp,c; -// pclog("sb_exec_command : SB command %02X\n", dsp->sb_command); + sb_dsp_log("sb_exec_command : SB command %02X\n", dsp->sb_command); switch (dsp->sb_command) { case 0x01: /*???*/ @@ -397,7 +366,6 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x17: /*2-bit ADPCM output with reference*/ dsp->sbref = sb_8_read_dma(dsp); dsp->sbstep = 0; -// pclog("Ref byte 2 %02X\n",sbref); case 0x16: /*2-bit ADPCM output*/ sb_start_dma(dsp, 1, 0, ADPCM_2, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); dsp->sbdat2 = sb_8_read_dma(dsp); @@ -459,7 +427,7 @@ void sb_exec_command(sb_dsp_t *dsp) dsp->sblatcho = dsp->sblatchi = TIMER_USEC * (256 - dsp->sb_data[0]); temp = 256 - dsp->sb_data[0]; temp = 1000000 / temp; -// pclog("Sample rate - %ihz (%i)\n",temp, dsp->sblatcho); + sb_dsp_log("Sample rate - %ihz (%i)\n",temp, dsp->sblatcho); if (dsp->sb_freq != temp && dsp->sb_type >= SB16) recalc_sb16_filter(temp); dsp->sb_freq = temp; @@ -468,7 +436,7 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x42: /*Set input sampling rate*/ if (dsp->sb_type < SB16) break; dsp->sblatcho = (int)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_data[1] + (dsp->sb_data[0] << 8)))); -// pclog("Sample rate - %ihz (%i)\n",dsp->sb_data[1]+(dsp->sb_data[0]<<8), dsp->sblatcho); + sb_dsp_log("Sample rate - %ihz (%i)\n",dsp->sb_data[1]+(dsp->sb_data[0]<<8), dsp->sblatcho); temp = dsp->sb_freq; dsp->sb_freq = dsp->sb_data[1] + (dsp->sb_data[0] << 8); dsp->sb_timeo = 256LL + dsp->sb_freq; @@ -483,7 +451,6 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x75: /*4-bit ADPCM output with reference*/ dsp->sbref = sb_8_read_dma(dsp); dsp->sbstep = 0; -// pclog("Ref byte 4 %02X\n",sbref); case 0x74: /*4-bit ADPCM output*/ sb_start_dma(dsp, 1, 0, ADPCM_4, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); dsp->sbdat2 = sb_8_read_dma(dsp); @@ -494,7 +461,6 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x77: /*2.6-bit ADPCM output with reference*/ dsp->sbref = sb_8_read_dma(dsp); dsp->sbstep = 0; -// pclog("Ref byte 26 %02X\n",sbref); case 0x76: /*2.6-bit ADPCM output*/ sb_start_dma(dsp, 1, 0, ADPCM_26, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); dsp->sbdat2 = sb_8_read_dma(dsp); @@ -516,31 +482,30 @@ void sb_exec_command(sb_dsp_t *dsp) break; case 0x80: /*Pause DAC*/ dsp->sb_pausetime = dsp->sb_data[0] + (dsp->sb_data[1] << 8); -// pclog("SB pause %04X\n",sb_pausetime); timer_process(); dsp->sbenable = 1; timer_update_outstanding(); break; case 0x90: /*High speed 8-bit autoinit DMA output*/ - if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break; + if (dsp->sb_type < SB2) break; sb_start_dma(dsp, 1, 1, 0, dsp->sb_8_autolen); break; case 0x91: /*High speed 8-bit single cycle DMA output*/ - if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break; + if (dsp->sb_type < SB2) break; sb_start_dma(dsp, 1, 0, 0, dsp->sb_8_autolen); break; case 0x98: /*High speed 8-bit autoinit DMA input*/ - if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break; + if (dsp->sb_type < SB2) break; sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_8_autolen); break; case 0x99: /*High speed 8-bit single cycle DMA input*/ - if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break; + if (dsp->sb_type < SB2) break; sb_start_dma_i(dsp, 1, 0, 0, dsp->sb_8_autolen); break; case 0xA0: /*Set input mode to mono*/ case 0xA8: /*Set input mode to stereo*/ if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break; - //TODO: Implement. 3.xx-only command. + /* TODO: Implement. 3.xx-only command. */ break; case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7: /*16-bit DMA output*/ @@ -632,11 +597,11 @@ void sb_exec_command(sb_dsp_t *dsp) sb_add_data(dsp, dsp->sb_test); break; case 0xF2: /*Trigger 8-bit IRQ*/ -// pclog("Trigger IRQ\n"); + sb_dsp_log("Trigger IRQ\n"); sb_irq(dsp, 1); break; case 0xF3: /*Trigger 16-bit IRQ*/ -// pclog("Trigger IRQ\n"); + sb_dsp_log("Trigger IRQ\n"); sb_irq(dsp, 0); break; case 0xE7: /*???*/ @@ -652,13 +617,10 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x0E: /*ASP set register*/ if (dsp->sb_type < SB16) break; dsp->sb_asp_regs[dsp->sb_data[0]] = dsp->sb_data[1]; -// pclog("ASP write reg %02X %02X\n", sb_data[0], sb_data[1]); break; case 0x0F: /*ASP get register*/ if (dsp->sb_type < SB16) break; -// sb_add_data(0); sb_add_data(dsp, dsp->sb_asp_regs[dsp->sb_data[0]]); -// pclog("ASP read reg %02X %02X\n", sb_data[0], sb_asp_regs[sb_data[0]]); break; case 0xF8: if (dsp->sb_type >= SB16) break; @@ -673,10 +635,7 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x04: case 0x05: break; -// default: -// fatal("Exec bad SB command %02X\n",sb_command); - - + /*TODO: Some more data about the DSP registeres * http://the.earth.li/~tfm/oldpage/sb_dsp.html * http://www.synchrondata.com/pheaven/www/area19.htm @@ -697,7 +656,6 @@ void sb_exec_command(sb_dsp_t *dsp) void sb_write(uint16_t a, uint8_t v, void *priv) { sb_dsp_t *dsp = (sb_dsp_t *)priv; -// pclog("sb_write : Write soundblaster %04X %02X %04X:%04X %02X\n",a,v,CS,pc,dsp->sb_command); switch (a&0xF) { case 6: /*Reset*/ @@ -721,7 +679,7 @@ void sb_write(uint16_t a, uint8_t v, void *priv) timer_update_outstanding(); if (dsp->asp_data_len) { -// pclog("ASP data %i\n", dsp->asp_data_len); + sb_dsp_log("ASP data %i\n", dsp->asp_data_len); dsp->asp_data_len--; if (!dsp->asp_data_len) sb_add_data(dsp, 0); @@ -732,8 +690,6 @@ void sb_write(uint16_t a, uint8_t v, void *priv) dsp->sb_command = v; if (v == 0x01) sb_add_data(dsp, 0); -// if (sb_commands[v]==-1) -// fatal("Bad SB command %02X\n",v); dsp->sb_data_stat++; } else @@ -750,7 +706,6 @@ void sb_write(uint16_t a, uint8_t v, void *priv) uint8_t sb_read(uint16_t a, void *priv) { sb_dsp_t *dsp = (sb_dsp_t *)priv; -// pclog("sb_read : Read soundblaster %04X %04X:%04X\n",a,CS,pc); switch (a & 0xf) { case 0xA: /*Read data*/ @@ -764,14 +719,13 @@ uint8_t sb_read(uint16_t a, void *priv) dsp->sb_read_rp++; dsp->sb_read_rp &= 0xFF; } -// pclog("SB read %02X\n",sbreaddat); return dsp->sbreaddat; case 0xC: /*Write data ready*/ - if (dsp->sb_8_enable || dsp->sb_type >= SB16 ) - dsp->busy_count = (dsp->busy_count + 1) & 15; + if (dsp->sb_8_enable || dsp->sb_type >= SB16) + dsp->busy_count = (dsp->busy_count + 1) & 3; else dsp->busy_count = 0; - if (dsp->wb_full || (dsp->busy_count & 8)) + if (dsp->wb_full || (dsp->busy_count & 2)) { dsp->wb_full = dsp->wb_time; return 0xff; @@ -823,7 +777,7 @@ void sb_dsp_init(sb_dsp_t *dsp, int type) void sb_dsp_setaddr(sb_dsp_t *dsp, uint16_t addr) { -// pclog("sb_dsp_setaddr : %04X\n", addr); + sb_dsp_log("sb_dsp_setaddr : %04X\n", addr); if (dsp->sb_addr != 0) { io_removehandler(dsp->sb_addr + 6, 0x0002, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); io_removehandler(dsp->sb_addr + 0xa, 0x0006, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); @@ -846,13 +800,11 @@ void pollsb(void *p) int tempi,ref; dsp->sbcount += dsp->sblatcho; -// pclog("PollSB %i %i %i %i\n",sb_8_enable,sb_8_pause,sb_pausetime,sb_8_output); if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && dsp->sb_8_output) { int data[2]; sb_dsp_update(dsp); -// pclog("Dopoll %i %02X %i\n", sb_8_length, sb_8_format, sblatcho); switch (dsp->sb_8_format) { case 0x00: /*Mono unsigned*/ @@ -1016,35 +968,49 @@ void pollsb(void *p) } if (dsp->sb_16_enable && !dsp->sb_16_pause && dsp->sb_pausetime < 0LL && dsp->sb_16_output) { + int data[2]; + sb_dsp_update(dsp); switch (dsp->sb_16_format) { case 0x00: /*Mono unsigned*/ - dsp->sbdatl = dsp->sbdatr = sb_16_read_dma(dsp) ^ 0x8000; + data[0] = sb_16_read_dma(dsp); + if (data[0] == DMA_NODATA) + break; + dsp->sbdatl = dsp->sbdatr = data[0] ^ 0x8000; dsp->sb_16_length--; break; case 0x10: /*Mono signed*/ - dsp->sbdatl = dsp->sbdatr = sb_16_read_dma(dsp); + data[0] = sb_16_read_dma(dsp); + if (data[0] == DMA_NODATA) + break; + dsp->sbdatl = dsp->sbdatr = data[0]; dsp->sb_16_length--; break; case 0x20: /*Stereo unsigned*/ - dsp->sbdatl = sb_16_read_dma(dsp) ^ 0x8000; - dsp->sbdatr = sb_16_read_dma(dsp) ^ 0x8000; + data[0] = sb_16_read_dma(dsp); + data[1] = sb_16_read_dma(dsp); + if (data[0] == DMA_NODATA || data[1] == DMA_NODATA) + break; + dsp->sbdatl = data[0] ^ 0x8000; + dsp->sbdatr = data[1] ^ 0x8000; dsp->sb_16_length -= 2; break; case 0x30: /*Stereo signed*/ - dsp->sbdatl = sb_16_read_dma(dsp); - dsp->sbdatr = sb_16_read_dma(dsp); + data[0] = sb_16_read_dma(dsp); + data[1] = sb_16_read_dma(dsp); + if (data[0] == DMA_NODATA || data[1] == DMA_NODATA) + break; + dsp->sbdatl = data[0]; + dsp->sbdatr = data[1]; dsp->sb_16_length -= 2; break; -// default: -// fatal("Unrecognised SB 16-bit format %02X\n",sb_16_format); } if (dsp->sb_16_length < 0) { -// pclog("16DMA over %i\n",dsp->sb_16_autoinit); + sb_dsp_log("16DMA over %i\n",dsp->sb_16_autoinit); if (dsp->sb_16_autoinit) dsp->sb_16_length = dsp->sb_16_autolen; else dsp->sb_16_enable = dsp->sbenable = 0; sb_irq(dsp, 0); @@ -1057,7 +1023,7 @@ void pollsb(void *p) { sb_irq(dsp, 1); dsp->sbenable = dsp->sb_8_enable; -// pclog("SB pause over\n"); + sb_dsp_log("SB pause over\n"); } } } @@ -1067,28 +1033,10 @@ void sb_poll_i(void *p) sb_dsp_t *dsp = (sb_dsp_t *)p; int processed=0; dsp->sb_count_i += dsp->sblatchi; -// pclog("PollSBi %i %i %i %i\n",sb_8_enable,sb_8_pause,sb_pausetime,sb_8_output); if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && !dsp->sb_8_output) { switch (dsp->sb_8_format) { -#ifdef SB_TEST_RECORDING_SAW - case 0x00: /*Unsigned mono. As the manual says, only the left channel is recorded*/ - case 0x10: /*Signed mono. As the manual says, only the left channel is recorded*/ - sb_8_write_dma(dsp, counttest); - counttest+=0x10; - counttest&=0xFF; - dsp->sb_8_length--; - break; - case 0x20: /*Unsigned stereo*/ - case 0x30: /*Signed stereo*/ - sb_8_write_dma(dsp, counttest); - sb_8_write_dma(dsp, counttest); - counttest+=0x10; - counttest&=0xFF; - dsp->sb_8_length -= 2; - break; -#else case 0x00: /*Mono unsigned As the manual says, only the left channel is recorded*/ sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8) ^0x80); dsp->sb_8_length--; @@ -1115,14 +1063,10 @@ void sb_poll_i(void *p) dsp->record_pos_read+=2; dsp->record_pos_read&=0xFFFF; break; -#endif -// default: -// fatal("Unrecognised SB 8-bit input format %02X\n",sb_8_format); } if (dsp->sb_8_length < 0) { -// pclog("Input DMA over %i\n",sb_8_autoinit); if (dsp->sb_8_autoinit) dsp->sb_8_length = dsp->sb_8_autolen; else dsp->sb_8_enable = dsp->sb_enable_i = 0; sb_irq(dsp, 1); @@ -1133,25 +1077,6 @@ void sb_poll_i(void *p) { switch (dsp->sb_16_format) { -#ifdef SB_TEST_RECORDING_SAW - case 0x00: /*Unsigned mono. As the manual says, only the left channel is recorded*/ - case 0x10: /*Signed mono. As the manual says, only the left channel is recorded*/ - if (sb_16_write_dma(dsp, counttest)) - return; - counttest+=0x1000; - counttest&=0xFFFF; - dsp->sb_16_length--; - break; - case 0x20: /*Unsigned stereo*/ - case 0x30: /*Signed stereo*/ - if (sb_16_write_dma(dsp, counttest)) - return; - sb_16_write_dma(dsp, counttest); - counttest+=0x1000; - counttest&=0xFFFF; - dsp->sb_16_length -= 2; - break; -#else case 0x00: /*Unsigned mono. As the manual says, only the left channel is recorded*/ if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read]^0x8000)) return; @@ -1182,21 +1107,17 @@ void sb_poll_i(void *p) dsp->record_pos_read+=2; dsp->record_pos_read&=0xFFFF; break; -#endif -// default: -// fatal("Unrecognised SB 16-bit input format %02X\n",sb_16_format); } if (dsp->sb_16_length < 0) { -// pclog("16iDMA over %i\n",sb_16_autoinit); if (dsp->sb_16_autoinit) dsp->sb_16_length = dsp->sb_16_autolen; else dsp->sb_16_enable = dsp->sb_enable_i = 0; sb_irq(dsp, 0); } processed=1; } - //Assume this is direct mode + /* Assume this is direct mode */ if (!processed) { dsp->record_pos_read+=2; @@ -1217,77 +1138,7 @@ void sb_dsp_update(sb_dsp_t *dsp) dsp->buffer[dsp->pos*2 + 1] = dsp->sbdatr; } } + void sb_dsp_close(sb_dsp_t *dsp) { - #ifdef SB_DSP_RECORD_DEBUG - if (soundf != 0) - { - fclose(soundf); - soundf=0; - } - #endif -} - -void sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp) -{ - char temps[128]; - int freq; - - if (dsp->sb_timeo < 256LL) - freq = 1000000 / (256LL - dsp->sb_timeo); - else - freq = dsp->sb_timeo - 256LL; - - if (dsp->sb_8_enable && dsp->sb_8_output) - { - switch (dsp->sb_8_format) - { - case 0x00: /*Mono unsigned*/ - case 0x10: /*Mono signed*/ - if (dsp->sb_type >= SBPRO && dsp->sb_type < SB16 && dsp->stereo) - { - strcpy(temps, "SB playback format : 8-bit stereo\n"); - freq /= 2; - } - else - strcpy(temps, "SB playback format : 8-bit mono\n"); - break; - case 0x20: /*Stereo unsigned*/ - case 0x30: /*Stereo signed*/ - strcpy(temps, "SB playback format : 8-bit stereo\n"); - break; - case ADPCM_4: - strcpy(temps, "SB playback format : 4-bit ADPCM\n"); - break; - case ADPCM_26: - strcpy(temps, "SB playback format : 2.6-bit ADPCM\n"); - break; - case ADPCM_2: - strcpy(temps, "SB playback format : 2-bit ADPCM\n"); - break; - } - } - else if (dsp->sb_16_enable && dsp->sb_16_output) - { - switch (dsp->sb_16_format) - { - case 0x00: /*Mono unsigned*/ - case 0x10: /*Mono signed*/ - strcpy(temps, "SB playback format : 16-bit mono\n"); - break; - case 0x20: /*Stereo unsigned*/ - case 0x30: /*Stereo signed*/ - strcpy(temps, "SB playback format : 16-bit stereo\n"); - break; - } - } - else - strcpy(temps, "SB playback stopped\n"); - strncat(s, temps, max_len); - - if ((dsp->sb_8_enable && dsp->sb_8_output) || (dsp->sb_16_enable && dsp->sb_16_output)) - { - sprintf(temps, "SB playback frequency : %iHz\n", freq); - strncat(s, temps, max_len); - } } diff --git a/src/sound/snd_sb_dsp.h b/src/sound/snd_sb_dsp.h index 0aac5650c..e4587c529 100644 --- a/src/sound/snd_sb_dsp.h +++ b/src/sound/snd_sb_dsp.h @@ -87,6 +87,4 @@ void sb_dsp_poll(sb_dsp_t *dsp, int16_t *l, int16_t *r); void sb_dsp_set_stereo(sb_dsp_t *dsp, int stereo); -void sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp); - void sb_dsp_update(sb_dsp_t *dsp); diff --git a/src/sound/snd_sn76489.c b/src/sound/snd_sn76489.c index c9dea8937..0f1b64ac1 100644 --- a/src/sound/snd_sn76489.c +++ b/src/sound/snd_sn76489.c @@ -238,7 +238,7 @@ const device_t sn76489_device = 0, sn76489_device_init, sn76489_device_close, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; const device_t ncr8496_device = @@ -248,6 +248,6 @@ const device_t ncr8496_device = 0, ncr8496_device_init, sn76489_device_close, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; diff --git a/src/sound/snd_ssi2001.c b/src/sound/snd_ssi2001.c index 5408a652d..e20a08333 100644 --- a/src/sound/snd_ssi2001.c +++ b/src/sound/snd_ssi2001.c @@ -1,8 +1,10 @@ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../io.h" #include "../device.h" @@ -61,8 +63,7 @@ void *ssi2001_init(const device_t *info) { ssi2001_t *ssi2001 = malloc(sizeof(ssi2001_t)); memset(ssi2001, 0, sizeof(ssi2001_t)); - - pclog("ssi2001_init\n"); + ssi2001->psid = sid_init(); sid_reset(ssi2001->psid); io_sethandler(0x0280, 0x0020, ssi2001_read, NULL, NULL, ssi2001_write, NULL, NULL, ssi2001); @@ -84,6 +85,6 @@ const device_t ssi2001_device = "Innovation SSI-2001", 0, 0, ssi2001_init, ssi2001_close, NULL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; diff --git a/src/sound/snd_wss.c b/src/sound/snd_wss.c index 8a6c82369..14725b5af 100644 --- a/src/sound/snd_wss.c +++ b/src/sound/snd_wss.c @@ -119,6 +119,6 @@ const device_t wss_device = wss_init, wss_close, NULL, NULL, wss_speed_changed, - NULL, NULL, + NULL, NULL }; diff --git a/src/sound/sound.c b/src/sound/sound.c index 66f8a0c87..75145468e 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -8,7 +8,7 @@ * * Sound emulation core. * - * Version: @(#)sound.c 1.0.15 2018/03/18 + * Version: @(#)sound.c 1.0.17 2018/04/29 * * Authors: Sarah Walker, * Miran Grca, @@ -16,28 +16,34 @@ * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 Miran Grca. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../device.h" #include "../timer.h" +#include "../scsi/scsi.h" #include "../cdrom/cdrom.h" #include "../plat.h" #include "sound.h" #include "midi.h" #include "snd_opl.h" +#include "snd_cms.h" #include "snd_adlib.h" #include "snd_adlibgold.h" #include "snd_audiopci.h" +#include "snd_gus.h" #include "snd_mpu401.h" #if defined(DEV_BRANCH) && defined(USE_PAS16) # include "snd_pas16.h" #endif #include "snd_sb.h" #include "snd_sb_dsp.h" +#include "snd_ssi2001.h" #include "snd_wss.h" #include "filters.h" @@ -102,6 +108,26 @@ static const SOUND_CARD sound_cards[] = }; +#ifdef ENABLE_SOUND_LOG +int sound_do_log = ENABLE_SOUND_LOG; +#endif + + +static void +sound_log(const char *fmt, ...) +{ +#ifdef ENABLE_SOUND_LOG + va_list ap; + + if (sound_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + int sound_card_available(int card) { if (sound_cards[card].device) @@ -169,7 +195,7 @@ static void sound_cd_thread(void *param) int32_t cd_buffer_temp4[2] = {0, 0}; int c, has_audio; - int d; + int d, r; thread_set_event(sound_cd_start_event); @@ -195,22 +221,40 @@ static void sound_cd_thread(void *param) for (i = 0; i < CDROM_NUM; i++) { has_audio = 0; - if (cdrom_drives[i].bus_type == CDROM_BUS_DISABLED) + if ((cdrom_drives[i].bus_type == CDROM_BUS_DISABLED) || !cdrom[i] || !cdrom[i]->handler) continue; - if (cdrom_drives[i].handler->audio_callback) + if (cdrom[i]->handler->audio_callback) { - cdrom_drives[i].handler->audio_callback(i, cd_buffer[i], CD_BUFLEN*2); - has_audio = (cdrom_drives[i].bus_type && cdrom_drives[i].sound_on); + r = cdrom[i]->handler->audio_callback(i, cd_buffer[i], CD_BUFLEN*2); + has_audio = (cdrom_drives[i].bus_type && cdrom_drives[i].sound_on/* && r*/); } else continue; if (soundon && has_audio) { - int32_t audio_vol_l = cdrom_mode_sense_get_volume(i, 0); - int32_t audio_vol_r = cdrom_mode_sense_get_volume(i, 1); + int32_t audio_vol_l = cdrom_mode_sense_get_volume(cdrom[i], 0); + int32_t audio_vol_r = cdrom_mode_sense_get_volume(cdrom[i], 1); int channel_select[2]; - channel_select[0] = cdrom_mode_sense_get_channel(i, 0); - channel_select[1] = cdrom_mode_sense_get_channel(i, 1); + channel_select[0] = cdrom_mode_sense_get_channel(cdrom[i], 0); + channel_select[1] = cdrom_mode_sense_get_channel(cdrom[i], 1); + + if (!r) + { + for (c = 0; c < CD_BUFLEN*2; c += 2) + { + if (sound_is_float) + { + cd_out_buffer[c] += 0.0; + cd_out_buffer[c+1] += 0.0; + } + else + { + cd_out_buffer_int16[c] += 0; + cd_out_buffer_int16[c+1] += 0; + } + } + continue; + } for (c = 0; c < CD_BUFLEN*2; c += 2) { @@ -299,7 +343,7 @@ static int16_t *outbuffer_ex_int16; static int cd_thread_enable = 0; -void sound_realloc_buffers(void) +static void sound_realloc_buffers(void) { if (outbuffer_ex != NULL) { @@ -326,15 +370,10 @@ void sound_init(void) int i = 0; int available_cdrom_drives = 0; - initalmain(0,NULL); - inital(); - outbuffer_ex = NULL; outbuffer_ex_int16 = NULL; - outbuffer = malloc(SOUNDBUFLEN * 2 * sizeof(int32_t)); - - sound_realloc_buffers(); + outbuffer = malloc(SOUNDBUFLEN * 2 * sizeof(int32_t)); for (i = 0; i < CDROM_NUM; i++) { @@ -353,10 +392,10 @@ void sound_init(void) sound_cd_event = thread_create_event(); sound_cd_thread_h = thread_create(sound_cd_thread, NULL); - /* pclog("Waiting for CD start event...\n"); */ + sound_log("Waiting for CD start event...\n"); thread_wait_event(sound_cd_start_event, -1); thread_reset_event(sound_cd_start_event); - /* pclog("Done!\n"); */ + sound_log("Done!\n"); } else cdaudioon = 0; @@ -445,7 +484,10 @@ void sound_speed_changed(void) void sound_reset(void) { - int i = 0; + sound_realloc_buffers(); + + midi_device_init(); + inital(); timer_add(sound_poll, &sound_poll_time, TIMER_ALWAYS_ENABLED, NULL); @@ -453,14 +495,19 @@ void sound_reset(void) sound_process_handlers_num = 0; sound_set_cd_volume(65535, 65535); +} - for (i = 0; i < CDROM_NUM; i++) - { - if (cdrom_drives[i].handler->audio_stop) - { - cdrom_drives[i].handler->audio_stop(i); - } - } +void sound_card_reset(void) +{ + sound_card_init(); + if (mpu401_standalone_enable) + mpu401_device_add(); + if (GUS) + device_add(&gus_device); + if (GAMEBLASTER) + device_add(&cms_device); + if (SSI2001) + device_add(&ssi2001_device); } void sound_cd_thread_end(void) @@ -468,10 +515,10 @@ void sound_cd_thread_end(void) if (cdaudioon) { cdaudioon = 0; - /* pclog("Waiting for CD Audio thread to terminate...\n"); */ + sound_log("Waiting for CD Audio thread to terminate...\n"); thread_set_event(sound_cd_event); thread_wait(sound_cd_thread_h, -1); - /* pclog("CD Audio thread terminated...\n"); */ + sound_log("CD Audio thread terminated...\n"); if (sound_cd_event) { thread_destroy_event(sound_cd_event); @@ -494,7 +541,12 @@ void sound_cd_thread_reset(void) for (i = 0; i < CDROM_NUM; i++) { - if (cdrom_drives[i].bus_type != CDROM_BUS_DISABLED) + if (cdrom[i] && cdrom[i]->handler && cdrom[i]->handler->audio_stop) + { + cdrom[i]->handler->audio_stop(i); + } + + if ((cdrom_drives[i].bus_type != CDROM_BUS_DISABLED) && cdrom[i]) { available_cdrom_drives++; } diff --git a/src/sound/sound.h b/src/sound/sound.h index 05bfe4959..cf49dbf1c 100644 --- a/src/sound/sound.h +++ b/src/sound/sound.h @@ -8,7 +8,7 @@ * * Sound emulation core. * - * Version: @(#)sound.h 1.0.6 2018/03/18 + * Version: @(#)sound.h 1.0.7 2018/04/23 * * Authors: Sarah Walker, * Miran Grca, @@ -55,16 +55,15 @@ extern void sound_set_cd_volume(unsigned int vol_l, unsigned int vol_r); extern void sound_speed_changed(void); -extern void sound_realloc_buffers(void); - extern void sound_init(void); extern void sound_reset(void); +extern void sound_card_reset(void); + extern void sound_cd_thread_end(void); extern void sound_cd_thread_reset(void); extern void closeal(void); -extern void initalmain(int argc, char *argv[]); extern void inital(void); extern void givealbuffer(void *buf); extern void givealbuffer_cd(void *buf); diff --git a/src/timer.c b/src/timer.c index bb40b2342..02d5a1bd2 100644 --- a/src/timer.c +++ b/src/timer.c @@ -96,7 +96,6 @@ void timer_update_outstanding(void) void timer_reset(void) { - /* pclog("timer_reset\n"); */ timers_present = 0; timer_latch = timer_count = 0; } diff --git a/src/ui.h b/src/ui.h index fd2f83abc..1e9077cdf 100644 --- a/src/ui.h +++ b/src/ui.h @@ -8,7 +8,7 @@ * * Define the various UI functions. * - * Version: @(#)ui.h 1.0.13 2018/02/06 + * Version: @(#)ui.h 1.0.14 2018/04/24 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -45,11 +45,10 @@ extern void ui_check_menu_item(int id, int checked); #define SB_FLOPPY 0x00 #define SB_CDROM 0x10 #define SB_ZIP 0x20 -#define SB_RDISK 0x30 -#define SB_HDD 0x50 -#define SB_NETWORK 0x60 -#define SB_SOUND 0x70 -#define SB_TEXT 0x80 +#define SB_HDD 0x40 +#define SB_NETWORK 0x50 +#define SB_SOUND 0x60 +#define SB_TEXT 0x70 extern wchar_t *ui_window_title(wchar_t *s); extern void ui_status_update(void); diff --git a/src/video/vid_ati18800.c b/src/video/vid_ati18800.c index d31561816..01614c299 100644 --- a/src/video/vid_ati18800.c +++ b/src/video/vid_ati18800.c @@ -8,7 +8,7 @@ * * ATI 18800 emulation (VGA Edge-16) * - * Version: @(#)vid_ati18800.c 1.0.8 2018/03/18 + * Version: @(#)vid_ati18800.c 1.0.12 2018/04/29 * * Authors: Sarah Walker, * Miran Grca, @@ -34,14 +34,21 @@ #include "vid_svga_render.h" +#if defined(DEV_BRANCH) && defined(USE_VGAWONDER) #define BIOS_ROM_PATH_WONDER L"roms/video/ati18800/VGA_Wonder_V3-1.02.bin" +#endif #define BIOS_ROM_PATH_VGA88 L"roms/video/ati18800/vga88.bin" #define BIOS_ROM_PATH_EDGE16 L"roms/video/ati18800/vgaedge16.vbi" enum { +#if defined(DEV_BRANCH) && defined(USE_VGAWONDER) ATI18800_WONDER = 0, ATI18800_VGA88, ATI18800_EDGE16 +#else + ATI18800_VGA88 = 0, + ATI18800_EDGE16 +#endif }; @@ -73,7 +80,6 @@ static void ati18800_out(uint16_t addr, uint8_t val, void *p) break; case 0x1cf: ati18800->regs[ati18800->index] = val; - pclog("ATI 18800 ATI register write %02x %02x\n", ati18800->index, val); switch (ati18800->index) { case 0xb0: @@ -150,46 +156,10 @@ static uint8_t ati18800_in(uint16_t addr, void *p) case 0x3D5: temp = svga->crtc[svga->crtcreg]; break; - case 0x3DA: - svga->attrff = 0; - svga->attrff = 0; - svga->cgastat &= ~0x30; - /* copy color diagnostic info from the overscan color register */ - switch (svga->attrregs[0x12] & 0x30) - { - case 0x00: /* P0 and P2 */ - if (svga->attrregs[0x11] & 0x01) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x04) - svga->cgastat |= 0x20; - break; - case 0x10: /* P4 and P5 */ - if (svga->attrregs[0x11] & 0x10) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x20) - svga->cgastat |= 0x20; - break; - case 0x20: /* P1 and P3 */ - if (svga->attrregs[0x11] & 0x02) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x08) - svga->cgastat |= 0x20; - break; - case 0x30: /* P6 and P7 */ - if (svga->attrregs[0x11] & 0x40) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x80) - svga->cgastat |= 0x20; - break; - } - return svga->cgastat; default: temp = svga_in(addr, svga); break; } -#ifndef RELEASE_BUILD - if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,cpu_state.pc); -#endif return temp; } @@ -221,10 +191,14 @@ static void *ati18800_init(const device_t *info) memset(ati18800, 0, sizeof(ati18800_t)); switch (info->local) { +#if defined(DEV_BRANCH) && defined(USE_VGAWONDER) case ATI18800_WONDER: +#endif default: +#if defined(DEV_BRANCH) && defined(USE_VGAWONDER) rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_WONDER, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); break; +#endif case ATI18800_VGA88: rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_VGA88, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); break; @@ -249,10 +223,12 @@ static void *ati18800_init(const device_t *info) return ati18800; } +#if defined(DEV_BRANCH) && defined(USE_VGAWONDER) static int ati18800_wonder_available(void) { return rom_present(BIOS_ROM_PATH_WONDER); } +#endif static int ati18800_vga88_available(void) { @@ -287,13 +263,7 @@ static void ati18800_force_redraw(void *p) ati18800->svga.fullchange = changeframecount; } -static void ati18800_add_status_info(char *s, int max_len, void *p) -{ - ati18800_t *ati18800 = (ati18800_t *)p; - - svga_add_status_info(s, max_len, &ati18800->svga); -} - +#if defined(DEV_BRANCH) && defined(USE_VGAWONDER) const device_t ati18800_wonder_device = { "ATI-18800", @@ -304,9 +274,9 @@ const device_t ati18800_wonder_device = ati18800_wonder_available, ati18800_speed_changed, ati18800_force_redraw, - ati18800_add_status_info, NULL }; +#endif const device_t ati18800_vga88_device = { @@ -318,7 +288,6 @@ const device_t ati18800_vga88_device = ati18800_vga88_available, ati18800_speed_changed, ati18800_force_redraw, - ati18800_add_status_info, NULL }; @@ -332,6 +301,5 @@ const device_t ati18800_device = ati18800_available, ati18800_speed_changed, ati18800_force_redraw, - ati18800_add_status_info, NULL }; diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index a85acab9f..e8fda8302 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -8,7 +8,7 @@ * * ATI 28800 emulation (VGA Charger and Korean VGA) * - * Version: @(#)vid_ati28800.c 1.0.15 2018/03/20 + * Version: @(#)vid_ati28800.c 1.0.19 2018/05/20 * * Authors: Sarah Walker, * Miran Grca, @@ -18,11 +18,13 @@ * Copyright 2016-2018 Miran Grca. * Copyright 2018 greatpsycho. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../cpu/cpu.h" #include "../io.h" @@ -39,6 +41,7 @@ #define BIOS_ATIKOR_PATH L"roms/video/ati28800/atikorvga.bin" +#define FONT_ATIKOR_PATH L"roms/video/ati28800/ati_ksc5601.rom" #define BIOS_VGAXL_EVEN_PATH L"roms/video/ati28800/xleven.bin" #define BIOS_VGAXL_ODD_PATH L"roms/video/ati28800/xlodd.bin" @@ -73,14 +76,34 @@ typedef struct ati28800_t } ati28800_t; +#ifdef ENABLE_ATI28800_LOG +int ati28800_do_log = ENABLE_ATI28800_LOG; +#endif + + +static void +ati28800_log(const char *fmt, ...) +{ +#ifdef ENABLE_ATI28800_LOG + va_list ap; + + if (ati28800_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + static void ati28800_out(uint16_t addr, uint8_t val, void *p) { ati28800_t *ati28800 = (ati28800_t *)p; svga_t *svga = &ati28800->svga; uint8_t old; -/* pclog("ati28800_out : %04X %02X %04X:%04X\n", addr, val, CS,pc); */ - + ati28800_log("ati28800_out : %04X %02X %04X:%04X\n", addr, val, CS, cpu_state.pc); + if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) addr ^= 0x60; @@ -212,7 +235,7 @@ static uint8_t ati28800_in(uint16_t addr, void *p) svga_t *svga = &ati28800->svga; uint8_t temp; -/* if (addr != 0x3da) pclog("ati28800_in : %04X ", addr); */ + if (addr != 0x3da) ati28800_log("ati28800_in : %04X ", addr); if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) addr ^= 0x60; @@ -257,44 +280,11 @@ static uint8_t ati28800_in(uint16_t addr, void *p) case 0x3D5: temp = svga->crtc[svga->crtcreg]; break; - case 0x3DA: - svga->attrff = 0; - svga->attrff = 0; - svga->cgastat &= ~0x30; - /* copy color diagnostic info from the overscan color register */ - switch (svga->attrregs[0x12] & 0x30) - { - case 0x00: /* P0 and P2 */ - if (svga->attrregs[0x11] & 0x01) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x04) - svga->cgastat |= 0x20; - break; - case 0x10: /* P4 and P5 */ - if (svga->attrregs[0x11] & 0x10) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x20) - svga->cgastat |= 0x20; - break; - case 0x20: /* P1 and P3 */ - if (svga->attrregs[0x11] & 0x02) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x08) - svga->cgastat |= 0x20; - break; - case 0x30: /* P6 and P7 */ - if (svga->attrregs[0x11] & 0x40) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x80) - svga->cgastat |= 0x20; - break; - } - return svga->cgastat; default: temp = svga_in(addr, svga); break; } - /* if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,cpu_state.pc); */ + if (addr != 0x3da) ati28800_log("%02X %04X:%04X\n", temp, CS,cpu_state.pc); return temp; } @@ -305,8 +295,8 @@ uint8_t ati28800k_in(uint16_t addr, void *p) uint16_t oldaddr = addr; uint8_t temp = 0xFF; -// if (addr != 0x3da) pclog("ati28800_in : %04X ", addr); - + if (addr != 0x3da) ati28800_log("ati28800k_in : %04X ", addr); + if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) addr ^= 0x60; switch (addr) @@ -336,7 +326,7 @@ uint8_t ati28800k_in(uint16_t addr, void *p) temp = ati28800_in(oldaddr, p); break; } - if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,cpu_state.pc); + if (addr != 0x3da) ati28800_log("%02X %04X:%04X\n", temp, CS,cpu_state.pc); return temp; } @@ -420,7 +410,7 @@ ati28800k_init(const device_t *info) ati28800->ksc5601_mode_enabled = 0; rom_init(&ati28800->bios_rom, BIOS_ATIKOR_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - loadfont(FONT_ATIKOR_PATH, 6); + loadfont(FONT_ATIKOR_PATH, 6); svga_init(&ati28800->svga, ati28800, ati28800->memory << 10, /*Memory size, default 512KB*/ ati28800k_recalctimings, @@ -553,24 +543,6 @@ ati28800_force_redraw(void *priv) ati->svga.fullchange = changeframecount; } -static void ati28800_add_status_info(char *s, int max_len, void *priv) -{ - ati28800_t *ati = (ati28800_t *)priv; - - svga_add_status_info(s, max_len, &ati->svga); -} - -void ati28800k_add_status_info(char *s, int max_len, void *p) -{ - ati28800_t *ati28800 = (ati28800_t *)p; - char temps[128]; - - ati28800_add_status_info(s, max_len, p); - - sprintf(temps, "Korean SVGA mode enabled : %s\n\n", ati28800->ksc5601_mode_enabled ? "Yes" : "No"); - strncat(s, temps, max_len); -} - static const device_config_t ati28800_config[] = { @@ -631,7 +603,6 @@ const device_t ati28800_device = ati28800_available, ati28800_speed_changed, ati28800_force_redraw, - ati28800_add_status_info, ati28800_config }; @@ -644,7 +615,6 @@ const device_t ati28800k_device = ati28800k_available, ati28800_speed_changed, ati28800_force_redraw, - ati28800k_add_status_info, ati28800_config }; @@ -657,7 +627,6 @@ const device_t compaq_ati28800_device = compaq_ati28800_available, ati28800_speed_changed, ati28800_force_redraw, - ati28800_add_status_info, ati28800_config }; @@ -671,7 +640,6 @@ const device_t ati28800_wonderxl24_device = ati28800_wonderxl24_available, ati28800_speed_changed, ati28800_force_redraw, - ati28800_add_status_info, ati28800_wonderxl_config }; #endif diff --git a/src/video/vid_ati_eeprom.c b/src/video/vid_ati_eeprom.c index 6ce2ac238..4bcd9d702 100644 --- a/src/video/vid_ati_eeprom.c +++ b/src/video/vid_ati_eeprom.c @@ -8,19 +8,20 @@ * * Emulation of the EEPROM on select ATI cards. * - * Version: @(#)vid_ati_eeprom.c 1.0.2 2017/11/04 + * Version: @(#)vid_ati_eeprom.c 1.0.2 2018/04/11 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include #include #include #include "../86box.h" +#include "../device.h" #include "../mem.h" #include "../nvr.h" #include "vid_ati_eeprom.h" diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index b8f414ad3..cac55a2e8 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -8,7 +8,7 @@ * * ATi Mach64 graphics card emulation. * - * Version: @(#)vid_ati_mach64.c 1.0.17 2018/03/18 + * Version: @(#)vid_ati_mach64.c 1.0.22 2018/07/16 * * Authors: Sarah Walker, * Miran Grca, @@ -16,12 +16,15 @@ * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 Miran Grca. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" +#include "../cpu/cpu.h" #include "../machine/machine.h" #include "../device.h" #include "../io.h" @@ -94,7 +97,7 @@ typedef struct mach64_t uint8_t regs[256]; int index; - int type; + int type, pci; uint8_t pci_regs[256]; uint8_t int_line; @@ -339,6 +342,27 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv); void mach64_ext_writew(uint32_t addr, uint16_t val, void *priv); void mach64_ext_writel(uint32_t addr, uint32_t val, void *priv); + +#ifdef ENABLE_MACH64_LOG +int mach64_do_log = ENABLE_MACH64_LOG; +#endif + + +static void +mach64_log(const char *fmt, ...) +{ +#ifdef ENABLE_MACH64_LOG + va_list ap; + + if (mach64_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + void mach64_out(uint16_t addr, uint8_t val, void *p) { mach64_t *mach64 = p; @@ -429,39 +453,6 @@ uint8_t mach64_in(uint16_t addr, void *p) if (svga->crtcreg > 0x18) return 0xff; return svga->crtc[svga->crtcreg]; - case 0x3DA: - svga->attrff = 0; - svga->attrff = 0; - svga->cgastat &= ~0x30; - /* copy color diagnostic info from the overscan color register */ - switch (svga->attrregs[0x12] & 0x30) - { - case 0x00: /* P0 and P2 */ - if (svga->attrregs[0x11] & 0x01) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x04) - svga->cgastat |= 0x20; - break; - case 0x10: /* P4 and P5 */ - if (svga->attrregs[0x11] & 0x10) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x20) - svga->cgastat |= 0x20; - break; - case 0x20: /* P1 and P3 */ - if (svga->attrregs[0x11] & 0x02) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x08) - svga->cgastat |= 0x20; - break; - case 0x30: /* P6 and P7 */ - if (svga->attrregs[0x11] & 0x40) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x80) - svga->cgastat |= 0x20; - break; - } - return svga->cgastat; } return svga_in(addr, svga); } @@ -538,7 +529,7 @@ void mach64_updatemapping(mach64_t *mach64) if (!(mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { - /* pclog("Update mapping - PCI disabled\n"); */ + mach64_log("Update mapping - PCI disabled\n"); mem_mapping_disable(&svga->mapping); mem_mapping_disable(&mach64->linear_mapping); mem_mapping_disable(&mach64->mmio_mapping); @@ -600,7 +591,6 @@ void mach64_updatemapping(mach64_t *mach64) mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((8 << 20) - 0x4000), 0x4000); mem_mapping_set_addr(&mach64->mmio_linear_mapping_2, mach64->linear_base + ((16 << 20) - 0x4000), 0x4000); } - svga->linear_base = mach64->linear_base; } else { @@ -612,6 +602,11 @@ void mach64_updatemapping(mach64_t *mach64) static void mach64_update_irqs(mach64_t *mach64) { + if (!mach64->pci) + { + return; + } + if ((mach64->crtc_int_cntl & 0xaa0024) & ((mach64->crtc_int_cntl << 1) & 0xaa0024)) pci_set_irq(mach64->card, PCI_INTA); else @@ -676,11 +671,9 @@ static void mach64_accel_write_fifo(mach64_t *mach64, uint32_t addr, uint8_t val (addr & 0x3ff) == 0x113) && !(val & 0x80)) { mach64_start_fill(mach64); -#ifdef MACH64_DEBUG - pclog("%i %i %i %i %i %08x\n", (mach64->dst_height_width & 0x7ff), (mach64->dst_height_width & 0x7ff0000), + mach64_log("%i %i %i %i %i %08x\n", (mach64->dst_height_width & 0x7ff), (mach64->dst_height_width & 0x7ff0000), ((mach64->dp_src & 7) != SRC_HOST), (((mach64->dp_src >> 8) & 7) != SRC_HOST), (((mach64->dp_src >> 16) & 3) != MONO_SRC_HOST), mach64->dp_src); -#endif if ((mach64->dst_height_width & 0x7ff) && (mach64->dst_height_width & 0x7ff0000) && ((mach64->dp_src & 7) != SRC_HOST) && (((mach64->dp_src >> 8) & 7) != SRC_HOST) && (((mach64->dp_src >> 16) & 3) != MONO_SRC_HOST)) @@ -868,13 +861,7 @@ static void mach64_accel_write_fifo_w(mach64_t *mach64, uint32_t addr, uint16_t break; default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif mach64_accel_write_fifo(mach64, addr, val); -#ifdef MACH64_DEBUG - pclog(" "); -#endif mach64_accel_write_fifo(mach64, addr + 1, val >> 8); break; } @@ -900,13 +887,7 @@ static void mach64_accel_write_fifo_l(mach64_t *mach64, uint32_t addr, uint32_t break; default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif mach64_accel_write_fifo_w(mach64, addr, val); -#ifdef MACH64_DEBUG - pclog(" "); -#endif mach64_accel_write_fifo_w(mach64, addr + 2, val >> 16); break; } @@ -1019,14 +1000,12 @@ void mach64_start_fill(mach64_t *mach64) mach64->accel.src_width2 = (mach64->src_height2_width2 >> 16) & 0x7fff; mach64->accel.src_height2 = mach64->src_height2_width2 & 0x1fff; -#ifdef MACH64_DEBUG - pclog("src %i %i %i %i %08X %08X\n", mach64->accel.src_x_count, + mach64_log("src %i %i %i %i %08X %08X\n", mach64->accel.src_x_count, mach64->accel.src_y_count, mach64->accel.src_width1, mach64->accel.src_height1, mach64->src_height1_width1, mach64->src_height2_width2); -#endif mach64->accel.src_pitch = (mach64->src_off_pitch >> 22) * 8; mach64->accel.src_offset = (mach64->src_off_pitch & 0xfffff) * 8; @@ -1079,9 +1058,6 @@ void mach64_start_fill(mach64_t *mach64) mach64->accel.sc_top = mach64->sc_top_bottom & 0x7fff; mach64->accel.sc_bottom = (mach64->sc_top_bottom >> 16) & 0x7fff; -/* mach64->accel.sc_left *= mach64_inc[mach64->accel.dst_pix_width]; - mach64->accel.sc_right *= mach64_inc[mach64->accel.dst_pix_width];*/ - mach64->accel.dp_frgd_clr = mach64->dp_frgd_clr; mach64->accel.dp_bkgd_clr = mach64->dp_bkgd_clr; @@ -1093,9 +1069,8 @@ void mach64_start_fill(mach64_t *mach64) mach64->accel.poly_draw = 0; mach64->accel.busy = 1; -#ifdef MACH64_DEBUG - pclog("mach64_start_fill : dst %i, %i src %i, %i size %i, %i src pitch %i offset %X dst pitch %i offset %X scissor %i %i %i %i src_fg %i mix %02X %02X\n", mach64->accel.dst_x_start, mach64->accel.dst_y_start, mach64->accel.src_x_start, mach64->accel.src_y_start, mach64->accel.dst_width, mach64->accel.dst_height, mach64->accel.src_pitch, mach64->accel.src_offset, mach64->accel.dst_pitch, mach64->accel.dst_offset, mach64->accel.sc_left, mach64->accel.sc_right, mach64->accel.sc_top, mach64->accel.sc_bottom, mach64->accel.source_fg, mach64->accel.mix_fg, mach64->accel.mix_bg); -#endif + mach64_log("mach64_start_fill : dst %i, %i src %i, %i size %i, %i src pitch %i offset %X dst pitch %i offset %X scissor %i %i %i %i src_fg %i mix %02X %02X\n", mach64->accel.dst_x_start, mach64->accel.dst_y_start, mach64->accel.src_x_start, mach64->accel.src_y_start, mach64->accel.dst_width, mach64->accel.dst_height, mach64->accel.src_pitch, mach64->accel.src_offset, mach64->accel.dst_pitch, mach64->accel.dst_offset, mach64->accel.sc_left, mach64->accel.sc_right, mach64->accel.sc_top, mach64->accel.sc_bottom, mach64->accel.source_fg, mach64->accel.mix_fg, mach64->accel.mix_bg); + mach64->accel.op = OP_RECT; } @@ -1171,9 +1146,8 @@ void mach64_start_line(mach64_t *mach64) mach64->accel.clr_cmp_src = mach64->clr_cmp_cntl & (1 << 24); mach64->accel.busy = 1; -#ifdef MACH64_DEBUG - pclog("mach64_start_line\n"); -#endif + mach64_log("mach64_start_line\n"); + mach64->accel.op = OP_LINE; } @@ -1241,9 +1215,7 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) if (!mach64->accel.busy) { -#ifdef MACH64_DEBUG - pclog("mach64_blit : return as not busy\n"); -#endif + mach64_log("mach64_blit : return as not busy\n"); return; } switch (mach64->accel.op) @@ -1428,9 +1400,7 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) if (mach64->accel.dst_height <= 0) { /*Blit finished*/ -#ifdef MACH64_DEBUG - pclog("mach64 blit finished\n"); -#endif + mach64_log("mach64 blit finished\n"); mach64->accel.busy = 0; if (mach64->dst_cntl & DST_X_TILE) mach64->dst_y_x = (mach64->dst_y_x & 0xfff) | ((mach64->dst_y_x + (mach64->accel.dst_width << 16)) & 0xfff0000); @@ -1557,9 +1527,7 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) if (mach64->accel.x_count <= 0) { /*Blit finished*/ -#ifdef MACH64_DEBUG - pclog("mach64 blit finished\n"); -#endif + mach64_log("mach64 blit finished\n"); mach64->accel.busy = 0; return; } @@ -1583,9 +1551,7 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) mach64->accel.dst_y++; break; } -#ifdef MACH64_DEBUG - pclog("x %i y %i err %i inc %i dec %i\n", mach64->accel.dst_x, mach64->accel.dst_y, mach64->accel.err, mach64->dst_bres_inc, mach64->dst_bres_dec); -#endif + mach64_log("x %i y %i err %i inc %i dec %i\n", mach64->accel.dst_x, mach64->accel.dst_y, mach64->accel.err, mach64->dst_bres_inc, mach64->dst_bres_dec); if (mach64->accel.err >= 0) { mach64->accel.err += mach64->dst_bres_dec; @@ -1626,10 +1592,8 @@ void mach64_load_context(mach64_t *mach64) { addr = ((0x3fff - (mach64->context_load_cntl & 0x3fff)) * 256) & mach64->vram_mask; mach64->context_mask = *(uint32_t *)&svga->vram[addr]; -#ifdef MACH64_DEBUG - pclog("mach64_load_context %08X from %08X : mask %08X\n", mach64->context_load_cntl, addr, mach64->context_mask); -#endif - + mach64_log("mach64_load_context %08X from %08X : mask %08X\n", mach64->context_load_cntl, addr, mach64->context_mask); + if (mach64->context_mask & (1 << 2)) mach64_accel_write_fifo_l(mach64, 0x100, *(uint32_t *)&svga->vram[addr + 0x08]); if (mach64->context_mask & (1 << 3)) @@ -1704,8 +1668,8 @@ static void pll_write(mach64_t *mach64, uint32_t addr, uint8_t val) break; case 2: /*Data*/ mach64->pll_regs[mach64->pll_addr] = val; - /* pclog("pll_write %02x,%02x\n", mach64->pll_addr, val); */ - + mach64_log("pll_write %02x,%02x\n", mach64->pll_addr, val); + for (c = 0; c < 4; c++) { double m = (double)mach64->pll_regs[PLL_REF_DIV]; @@ -1713,9 +1677,9 @@ static void pll_write(mach64_t *mach64, uint32_t addr, uint8_t val) double r = 14318184.0; double p = (double)(1 << ((mach64->pll_regs[VCLK_POST_DIV] >> (c*2)) & 3)); - /* pclog("PLLfreq %i = %g %g m=%02x n=%02x p=%02x\n", c, (2.0 * r * n) / (m * p), p, mach64->pll_regs[PLL_REF_DIV], mach64->pll_regs[VCLK0_FB_DIV+c], mach64->pll_regs[VCLK_POST_DIV]); */ + mach64_log("PLLfreq %i = %g %g m=%02x n=%02x p=%02x\n", c, (2.0 * r * n) / (m * p), p, mach64->pll_regs[PLL_REF_DIV], mach64->pll_regs[VCLK0_FB_DIV+c], mach64->pll_regs[VCLK_POST_DIV]); mach64->pll_freq[c] = (2.0 * r * n) / (m * p); - /* pclog(" %g\n", mach64->pll_freq[c]); */ + mach64_log(" %g\n", mach64->pll_freq[c]); } break; } @@ -1751,9 +1715,7 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p) uint8_t ret; if (!(addr & 0x400)) { -#ifdef MACH64_DEBUG - pclog("nmach64_ext_readb: addr=%04x %04x(%08x):%08x\n", addr, CS, cs, cpu_state.pc); -#endif + mach64_log("nmach64_ext_readb: addr=%04x %04x(%08x):%08x\n", addr, CS, cs, cpu_state.pc); switch (addr & 0x3ff) { case 0x00: case 0x01: case 0x02: case 0x03: @@ -2105,8 +2067,6 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p) break; case 0x338: -/* if (!FIFO_EMPTY) - wake_fifo_thread(mach64);*/ ret = FIFO_EMPTY ? 0 : 1; break; @@ -2114,9 +2074,7 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p) ret = 0; break; } -#ifdef MACH64_DEBUG - if ((addr & 0x3fc) != 0x018) pclog("mach64_ext_readb : addr %08X ret %02X\n", addr, ret); -#endif + if ((addr & 0x3fc) != 0x018) mach64_log("mach64_ext_readb : addr %08X ret %02X\n", addr, ret); return ret; } uint16_t mach64_ext_readw(uint32_t addr, void *p) @@ -2124,27 +2082,17 @@ uint16_t mach64_ext_readw(uint32_t addr, void *p) uint16_t ret; if (!(addr & 0x400)) { -#ifdef MACH64_DEBUG - pclog("nmach64_ext_readw: addr=%04x %04x(%08x):%08x\n", addr, CS, cs, cpu_state.pc); -#endif + mach64_log("nmach64_ext_readw: addr=%04x %04x(%08x):%08x\n", addr, CS, cs, cpu_state.pc); ret = 0xffff; } else switch (addr & 0x3ff) { default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif ret = mach64_ext_readb(addr, p); -#ifdef MACH64_DEBUG - pclog(" "); -#endif ret |= mach64_ext_readb(addr + 1, p) << 8; break; } -#ifdef MACH64_DEBUG - if ((addr & 0x3fc) != 0x018) pclog("mach64_ext_readw : addr %08X ret %04X\n", addr, ret); -#endif + if ((addr & 0x3fc) != 0x018) mach64_log("mach64_ext_readw : addr %08X ret %04X\n", addr, ret); return ret; } uint32_t mach64_ext_readl(uint32_t addr, void *p) @@ -2153,9 +2101,7 @@ uint32_t mach64_ext_readl(uint32_t addr, void *p) uint32_t ret; if (!(addr & 0x400)) { -#ifdef MACH64_DEBUG - pclog("nmach64_ext_readl: addr=%04x %04x(%08x):%08x\n", addr, CS, cs, cpu_state.pc); -#endif + mach64_log("nmach64_ext_readl: addr=%04x %04x(%08x):%08x\n", addr, CS, cs, cpu_state.pc); ret = 0xffffffff; } else switch (addr & 0x3ff) @@ -2174,19 +2120,11 @@ uint32_t mach64_ext_readl(uint32_t addr, void *p) break; default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif ret = mach64_ext_readw(addr, p); -#ifdef MACH64_DEBUG - pclog(" "); -#endif ret |= mach64_ext_readw(addr + 2, p) << 16; break; } -#ifdef MACH64_DEBUG - if ((addr & 0x3fc) != 0x018) pclog("mach64_ext_readl : addr %08X ret %08X\n", addr, ret); -#endif + if ((addr & 0x3fc) != 0x018) mach64_log("mach64_ext_readl : addr %08X ret %08X\n", addr, ret); return ret; } @@ -2194,9 +2132,9 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) { mach64_t *mach64 = (mach64_t *)p; svga_t *svga = &mach64->svga; -#ifdef MACH64_DEBUG - pclog("mach64_ext_writeb : addr %08X val %02X %04x(%08x):%08x\n", addr, val, CS,cs,cpu_state.pc); -#endif + + mach64_log("mach64_ext_writeb : addr %08X val %02X %04x(%08x):%08x\n", addr, val, CS,cs,cpu_state.pc); + if (!(addr & 0x400)) { switch (addr & 0x3ff) @@ -2253,9 +2191,8 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) WRITE8(addr, mach64->buf_pitch[1], val); break; } -#ifdef MACH64_DEBUG - pclog("nmach64_ext_writeb: addr=%04x val=%02x\n", addr, val); -#endif + + mach64_log("nmach64_ext_writeb: addr=%04x val=%02x\n", addr, val); } else if (addr & 0x300) { @@ -2361,27 +2298,19 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) case 0xb4: mach64->bank_w[0] = val * 32768; -#ifdef MACH64_DEBUG - pclog("mach64 : write bank A0000-A7FFF set to %08X\n", mach64->bank_w[0]); -#endif + mach64_log("mach64 : write bank A0000-A7FFF set to %08X\n", mach64->bank_w[0]); break; case 0xb5: case 0xb6: mach64->bank_w[1] = val * 32768; -#ifdef MACH64_DEBUG - pclog("mach64 : write bank A8000-AFFFF set to %08X\n", mach64->bank_w[1]); -#endif + mach64_log("mach64 : write bank A8000-AFFFF set to %08X\n", mach64->bank_w[1]); break; case 0xb8: mach64->bank_r[0] = val * 32768; -#ifdef MACH64_DEBUG - pclog("mach64 : read bank A0000-A7FFF set to %08X\n", mach64->bank_r[0]); -#endif + mach64_log("mach64 : read bank A0000-A7FFF set to %08X\n", mach64->bank_r[0]); break; case 0xb9: case 0xba: mach64->bank_r[1] = val * 32768; -#ifdef MACH64_DEBUG - pclog("mach64 : read bank A8000-AFFFF set to %08X\n", mach64->bank_r[1]); -#endif + mach64_log("mach64 : read bank A8000-AFFFF set to %08X\n", mach64->bank_r[1]); break; case 0xc0: case 0xc1: case 0xc2: case 0xc3: @@ -2418,14 +2347,11 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) void mach64_ext_writew(uint32_t addr, uint16_t val, void *p) { mach64_t *mach64 = (mach64_t *)p; -#ifdef MACH64_DEBUG - pclog("mach64_ext_writew : addr %08X val %04X\n", addr, val); -#endif + mach64_log("mach64_ext_writew : addr %08X val %04X\n", addr, val); if (!(addr & 0x400)) { -#ifdef MACH64_DEBUG - pclog("nmach64_ext_writew: addr=%04x val=%04x %04x(%08x):%08x\n", addr, val, CS, cs, cpu_state.pc); -#endif + mach64_log("nmach64_ext_writew: addr=%04x val=%04x %04x(%08x):%08x\n", addr, val, CS, cs, cpu_state.pc); + mach64_ext_writeb(addr, val, p); mach64_ext_writeb(addr + 1, val >> 8, p); } @@ -2436,13 +2362,7 @@ void mach64_ext_writew(uint32_t addr, uint16_t val, void *p) else switch (addr & 0x3fe) { default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif mach64_ext_writeb(addr, val, p); -#ifdef MACH64_DEBUG - pclog(" "); -#endif mach64_ext_writeb(addr + 1, val >> 8, p); break; } @@ -2450,15 +2370,12 @@ void mach64_ext_writew(uint32_t addr, uint16_t val, void *p) void mach64_ext_writel(uint32_t addr, uint32_t val, void *p) { mach64_t *mach64 = (mach64_t *)p; -#ifdef MACH64_DEBUG if ((addr & 0x3c0) != 0x200) - pclog("mach64_ext_writel : addr %08X val %08X\n", addr, val); -#endif + mach64_log("mach64_ext_writel : addr %08X val %08X\n", addr, val); if (!(addr & 0x400)) { -#ifdef MACH64_DEBUG - pclog("nmach64_ext_writel: addr=%04x val=%08x %04x(%08x):%08x\n", addr, val, CS, cs, cpu_state.pc); -#endif + mach64_log("nmach64_ext_writel: addr=%04x val=%08x %04x(%08x):%08x\n", addr, val, CS, cs, cpu_state.pc); + mach64_ext_writew(addr, val, p); mach64_ext_writew(addr + 2, val >> 16, p); } @@ -2469,13 +2386,7 @@ void mach64_ext_writel(uint32_t addr, uint32_t val, void *p) else switch (addr & 0x3fc) { default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif mach64_ext_writew(addr, val, p); -#ifdef MACH64_DEBUG - pclog(" "); -#endif mach64_ext_writew(addr + 2, val >> 16, p); break; } @@ -2599,9 +2510,7 @@ uint8_t mach64_ext_inb(uint16_t port, void *p) ret = 0; break; } -#ifdef MACH64_DEBUG - pclog("mach64_ext_inb : port %04X ret %02X %04X:%04X\n", port, ret, CS,cpu_state.pc); -#endif + mach64_log("mach64_ext_inb : port %04X ret %02X %04X:%04X\n", port, ret, CS,cpu_state.pc); return ret; } uint16_t mach64_ext_inw(uint16_t port, void *p) @@ -2610,19 +2519,11 @@ uint16_t mach64_ext_inw(uint16_t port, void *p) switch (port) { default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif ret = mach64_ext_inb(port, p); -#ifdef MACH64_DEBUG - pclog(" "); -#endif ret |= (mach64_ext_inb(port + 1, p) << 8); break; } -#ifdef MACH64_DEBUG - pclog("mach64_ext_inw : port %04X ret %04X\n", port, ret); -#endif + mach64_log("mach64_ext_inw : port %04X ret %04X\n", port, ret); return ret; } uint32_t mach64_ext_inl(uint16_t port, void *p) @@ -2638,28 +2539,18 @@ uint32_t mach64_ext_inl(uint16_t port, void *p) break; default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif ret = mach64_ext_inw(port, p); -#ifdef MACH64_DEBUG - pclog(" "); -#endif ret |= (mach64_ext_inw(port + 2, p) << 16); break; } -#ifdef MACH64_DEBUG - pclog("mach64_ext_inl : port %04X ret %08X\n", port, ret); -#endif + mach64_log("mach64_ext_inl : port %04X ret %08X\n", port, ret); return ret; } void mach64_ext_outb(uint16_t port, uint8_t val, void *p) { mach64_t *mach64 = (mach64_t *)p; -#ifdef MACH64_DEBUG - pclog("mach64_ext_outb : port %04X val %02X %04X:%04X\n", port, val, CS,cpu_state.pc); -#endif + mach64_log("mach64_ext_outb : port %04X val %02X %04X:%04X\n", port, val, CS,cpu_state.pc); switch (port) { case 0x02ec: case 0x02ed: case 0x02ee: case 0x02ef: @@ -2761,36 +2652,22 @@ void mach64_ext_outb(uint16_t port, uint8_t val, void *p) } void mach64_ext_outw(uint16_t port, uint16_t val, void *p) { -#ifdef MACH64_DEBUG - pclog("mach64_ext_outw : port %04X val %04X\n", port, val); -#endif + mach64_log("mach64_ext_outw : port %04X val %04X\n", port, val); switch (port) { default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif mach64_ext_outb(port, val, p); -#ifdef MACH64_DEBUG - pclog(" "); -#endif mach64_ext_outb(port + 1, val >> 8, p); break; } } void mach64_ext_outl(uint16_t port, uint32_t val, void *p) { - /* pclog("mach64_ext_outl : port %04X val %08X\n", port, val); */ + mach64_log("mach64_ext_outl : port %04X val %08X\n", port, val); switch (port) { default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif mach64_ext_outw(port, val, p); -#ifdef MACH64_DEBUG - pclog(" "); -#endif mach64_ext_outw(port + 2, val >> 16, p); break; } @@ -2802,9 +2679,7 @@ static uint8_t mach64_block_inb(uint16_t port, void *p) uint8_t ret; ret = mach64_ext_readb(0x400 | (port & 0x3ff), mach64); -#ifdef MACH64_DEBUG - pclog("mach64_block_inb : port %04X ret %02X %04x:%04x\n", port, ret, CS,cpu_state.pc); -#endif + mach64_log("mach64_block_inb : port %04X ret %02X %04x:%04x\n", port, ret, CS,cpu_state.pc); return ret; } static uint16_t mach64_block_inw(uint16_t port, void *p) @@ -2813,9 +2688,7 @@ static uint16_t mach64_block_inw(uint16_t port, void *p) uint16_t ret; ret = mach64_ext_readw(0x400 | (port & 0x3ff), mach64); -#ifdef MACH64_DEBUG - pclog("mach64_block_inw : port %04X ret %04X\n", port, ret); -#endif + mach64_log("mach64_block_inw : port %04X ret %04X\n", port, ret); return ret; } static uint32_t mach64_block_inl(uint16_t port, void *p) @@ -2824,9 +2697,7 @@ static uint32_t mach64_block_inl(uint16_t port, void *p) uint32_t ret; ret = mach64_ext_readl(0x400 | (port & 0x3ff), mach64); -#ifdef MACH64_DEBUG - pclog("mach64_block_inl : port %04X ret %08X\n", port, ret); -#endif + mach64_log("mach64_block_inl : port %04X ret %08X\n", port, ret); return ret; } @@ -2834,27 +2705,21 @@ static void mach64_block_outb(uint16_t port, uint8_t val, void *p) { mach64_t *mach64 = (mach64_t *)p; -#ifdef MACH64_DEBUG - pclog("mach64_block_outb : port %04X val %02X\n ", port, val); -#endif + mach64_log("mach64_block_outb : port %04X val %02X\n ", port, val); mach64_ext_writeb(0x400 | (port & 0x3ff), val, mach64); } static void mach64_block_outw(uint16_t port, uint16_t val, void *p) { mach64_t *mach64 = (mach64_t *)p; -#ifdef MACH64_DEBUG - pclog("mach64_block_outw : port %04X val %04X\n ", port, val); -#endif + mach64_log("mach64_block_outw : port %04X val %04X\n ", port, val); mach64_ext_writew(0x400 | (port & 0x3ff), val, mach64); } static void mach64_block_outl(uint16_t port, uint32_t val, void *p) { mach64_t *mach64 = (mach64_t *)p; -#ifdef MACH64_DEBUG - pclog("mach64_block_outl : port %04X val %08X\n ", port, val); -#endif + mach64_log("mach64_block_outl : port %04X val %08X\n ", port, val); mach64_ext_writel(0x400 | (port & 0x3ff), val, mach64); } @@ -2915,8 +2780,10 @@ void mach64_hwcursor_draw(svga_t *svga, int displine) uint8_t dat; uint32_t col0 = mach64->ramdac.pallook[0]; uint32_t col1 = mach64->ramdac.pallook[1]; - int y_add = (enable_overscan && !suppress_overscan) ? 16 : 0; - int x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; + int y_add, x_add; + + y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; + x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; offset = svga->hwcursor_latch.xoff; for (x = 0; x < 64 - svga->hwcursor_latch.xoff; x += 4) @@ -3114,7 +2981,7 @@ void mach64_overlay_draw(svga_t *svga, int displine) break; default: - /* pclog("Unknown Mach64 scaler format %x\n", mach64->scaler_format); */ + mach64_log("Unknown Mach64 scaler format %x\n", mach64->scaler_format); /*Fill buffer with something recognisably wrong*/ for (x = 0; x < mach64->svga.overlay_latch.xsize; x++) mach64->overlay_dat[x] = 0xff00ff; @@ -3390,12 +3257,12 @@ void mach64_pci_write(int func, int addr, uint8_t val, void *p) if (mach64->pci_regs[0x30] & 0x01) { uint32_t addr = (mach64->pci_regs[0x32] << 16) | (mach64->pci_regs[0x33] << 24); - /* pclog("Mach64 bios_rom enabled at %08x\n", addr); */ + mach64_log("Mach64 bios_rom enabled at %08x\n", addr); mem_mapping_set_addr(&mach64->bios_rom.mapping, addr, 0x8000); } else { - /* pclog("Mach64 bios_rom disabled\n"); */ + mach64_log("Mach64 bios_rom disabled\n"); mem_mapping_disable(&mach64->bios_rom.mapping); } return; @@ -3467,6 +3334,7 @@ static void *mach64gx_init(const device_t *info) mach64_t *mach64 = mach64_common_init(info); mach64->type = MACH64_GX; + mach64->pci = !!(info->flags & DEVICE_PCI); mach64->pci_id = (int)'X' | ((int)'G' << 8); mach64->config_chip_id = 0x020000d7; mach64->dac_cntl = 5 << 16; /*ATI 68860 RAMDAC*/ @@ -3493,6 +3361,7 @@ static void *mach64vt2_init(const device_t *info) svga_t *svga = &mach64->svga; mach64->type = MACH64_VT2; + mach64->pci = 1; mach64->pci_id = 0x5654; mach64->config_chip_id = 0x40005654; mach64->dac_cntl = 1 << 16; /*Internal 24-bit DAC*/ @@ -3552,54 +3421,6 @@ void mach64_force_redraw(void *p) mach64->svga.fullchange = changeframecount; } -void mach64_add_status_info(char *s, int max_len, void *p) -{ - mach64_t *mach64 = (mach64_t *)p; - char temps[256]; - uint64_t new_time = plat_timer_read(); - uint64_t status_diff = new_time - mach64->status_time; - mach64->status_time = new_time; - - if (((mach64->crtc_gen_cntl >> 24) & 3) == 3) - { - svga_t *svga = &mach64->svga; - char temps[128]; - int bpp = 4; - - strncat(s, "Mach64 in native mode\n", max_len); - - switch ((mach64->crtc_gen_cntl >> 8) & 7) - { - case 1: bpp = 4; break; - case 2: bpp = 8; break; - case 3: bpp = 15; break; - case 4: bpp = 16; break; - case 5: bpp = 24; break; - case 6: bpp = 32; break; - } - - sprintf(temps, "Mach64 colour depth : %i bpp\n", bpp); - strncat(s, temps, max_len); - - sprintf(temps, "Mach64 resolution : %i x %i\n", svga->hdisp, svga->dispend); - strncat(s, temps, max_len); - - sprintf(temps, "Mach64 refresh rate : %i Hz\n\n", svga->frames); - svga->frames = 0; - strncat(s, temps, max_len); - } - else - { - strncat(s, "Mach64 in SVGA mode\n", max_len); - svga_add_status_info(s, max_len, &mach64->svga); - } - - sprintf(temps, "%f%% CPU\n%f%% CPU (real)\n\n", ((double)mach64->blitter_time * 100.0) / timer_freq, ((double)mach64->blitter_time * 100.0) / status_diff); - strncat(s, temps, max_len); - - mach64->blitter_time = 0; -} - static const device_config_t mach64gx_config[] = { { @@ -3654,7 +3475,6 @@ const device_t mach64gx_isa_device = mach64gx_isa_available, mach64_speed_changed, mach64_force_redraw, - mach64_add_status_info, mach64gx_config }; @@ -3667,7 +3487,6 @@ const device_t mach64gx_vlb_device = mach64gx_vlb_available, mach64_speed_changed, mach64_force_redraw, - mach64_add_status_info, mach64gx_config }; @@ -3680,7 +3499,6 @@ const device_t mach64gx_pci_device = mach64gx_available, mach64_speed_changed, mach64_force_redraw, - mach64_add_status_info, mach64gx_config }; @@ -3693,6 +3511,5 @@ const device_t mach64vt2_device = mach64vt2_available, mach64_speed_changed, mach64_force_redraw, - mach64_add_status_info, mach64vt2_config }; diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index 4f94e7e20..6f12a01a5 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -8,7 +8,7 @@ * * Emulation of the old and new IBM CGA graphics cards. * - * Version: @(#)vid_cga.c 1.0.14 2018/03/18 + * Version: @(#)vid_cga.c 1.0.16 2018/04/29 * * Authors: Sarah Walker, * Miran Grca, @@ -151,7 +151,6 @@ void cga_recalctimings(cga_t *cga) { double disptime; double _dispontime, _dispofftime; - /* pclog("Recalc - %i %i %i\n", cga->crtc[0], cga->crtc[1], cga->cgamode & 1); */ if (cga->cgamode & 1) { disptime = (double) (cga->crtc[0] + 1); @@ -595,6 +594,5 @@ const device_t cga_device = NULL, cga_speed_changed, NULL, - NULL, cga_config }; diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 81960c350..6e501e4ae 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -9,7 +9,7 @@ * Emulation of select Cirrus Logic cards (CL-GD 5428, * CL-GD 5429, CL-GD 5430, CL-GD 5434 and CL-GD 5436 are supported). * - * Version: @(#)vid_cl_54xx.c 1.0.16 2018/03/23 + * Version: @(#)vid_cl_54xx.c 1.0.20 2018/07/16 * * Authors: Sarah Walker, * Barry Rodewald, @@ -47,6 +47,7 @@ #define BIOS_GD5430_PCI_PATH L"roms/video/cirruslogic/pci.bin" #define BIOS_GD5434_PATH L"roms/video/cirruslogic/gd5434.bin" #define BIOS_GD5436_PATH L"roms/video/cirruslogic/5436.vbi" +#define BIOS_GD5440_PATH L"roms/video/cirruslogic/BIOS.BIN" #define BIOS_GD5446_PATH L"roms/video/cirruslogic/5446BV.VBI" #define BIOS_GD5446_STB_PATH L"roms/video/cirruslogic/stb nitro64v.BIN" #define BIOS_GD5480_PATH L"roms/video/cirruslogic/clgd5480.rom" @@ -57,6 +58,7 @@ #define CIRRUS_ID_CLGD5430 0xa0 #define CIRRUS_ID_CLGD5434 0xa8 #define CIRRUS_ID_CLGD5436 0xac +#define CIRRUS_ID_CLGD5440 0xa0 /* Yes, the 5440 has the same ID as the 5430. */ #define CIRRUS_ID_CLGD5446 0xb8 #define CIRRUS_ID_CLGD5480 0xbc @@ -128,7 +130,7 @@ typedef struct gd54xx_t svga_t svga; - int has_bios; + int has_bios, rev; rom_t bios_rom; uint32_t vram_size; @@ -201,6 +203,18 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx); static void gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga); + +/* Returns 1 if the card is a 5434, 5436/46, or 5480. */ +static int +gd54xx_is_5434(svga_t *svga) +{ + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + return 1; + else + return 0; +} + + static void gd54xx_out(uint16_t addr, uint8_t val, void *p) { @@ -622,8 +636,8 @@ gd54xx_in(uint16_t addr, void *p) case 0x27: /*ID*/ return svga->crtc[0x27]; /*GD542x/GD543x*/ case 0x28: /*Class ID*/ - if (svga->crtc[0x27] == CIRRUS_ID_CLGD5430) - return 0xff; /*Standard CL-GD5430*/ + if ((svga->crtc[0x27] == CIRRUS_ID_CLGD5430) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5440)) + return 0xff; /*Standard CL-GD5430/40*/ break; } return svga->crtc[svga->crtcreg]; @@ -718,7 +732,6 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) mem_mapping_disable(&svga->mapping); mem_mapping_set_addr(&gd54xx->linear_mapping, base, size); - svga->linear_base = base; if (svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) { if (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR) { if (size >= (4 * 1024 * 1024)) @@ -745,85 +758,72 @@ gd54xx_recalctimings(svga_t *svga) svga->interlace = (svga->crtc[0x1a] & 0x01); + if (svga->seqregs[7] & CIRRUS_SR7_BPP_SVGA) + svga->render = svga_render_8bpp_highres; + else if (svga->gdcreg[5] & 0x40) + svga->render = svga_render_8bpp_lowres; + svga->ma_latch |= ((svga->crtc[0x1b] & 0x01) << 16) | ((svga->crtc[0x1b] & 0xc) << 15); - if (svga->seqregs[7] & CIRRUS_SR7_BPP_SVGA) - { - svga->bpp = 8; - svga->render = svga_render_8bpp_highres; - } - else if (svga->gdcreg[5] & 0x40) - { - svga->bpp = 8; - svga->render = svga_render_8bpp_lowres; - } - - if (gd54xx->ramdac.ctrl & 0x80) - { - if (gd54xx->ramdac.ctrl & 0x40) - { - switch (gd54xx->ramdac.ctrl & 0xf) - { - case 0: - svga->bpp = 15; - svga->render = svga_render_15bpp_highres; - break; - - case 1: - svga->bpp = 16; - svga->render = svga_render_16bpp_highres; - break; - - case 5: - if ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) && (svga->seqregs[7] & CIRRUS_SR7_BPP_32)) - { + svga->bpp = 8; + + if (gd54xx->ramdac.ctrl & 0x80) { + if (gd54xx->ramdac.ctrl & 0x40) { + switch (gd54xx->ramdac.ctrl & 0xf) { + case 0: + svga->bpp = 15; + svga->render = svga_render_15bpp_highres; + break; + + case 1: + svga->bpp = 16; + svga->render = svga_render_16bpp_highres; + break; + + case 5: + if (gd54xx_is_5434(svga) && (svga->seqregs[7] & CIRRUS_SR7_BPP_32)) { + svga->bpp = 32; + svga->render = svga_render_32bpp_highres; + if (svga->crtc[0x27] < CIRRUS_ID_CLGD5436) + svga->rowoffset *= 2; + } else { + svga->bpp = 24; + svga->render = svga_render_24bpp_highres; + } + break; + + case 0xf: + switch (svga->seqregs[7] & CIRRUS_SR7_BPP_MASK) { + case CIRRUS_SR7_BPP_32: svga->bpp = 32; svga->render = svga_render_32bpp_highres; - if (svga->crtc[0x27] < CIRRUS_ID_CLGD5436) - svga->rowoffset *= 2; - } - else - { + svga->rowoffset *= 2; + break; + + case CIRRUS_SR7_BPP_24: svga->bpp = 24; svga->render = svga_render_24bpp_highres; - } - break; - - case 0xf: - switch (svga->seqregs[7] & CIRRUS_SR7_BPP_MASK) - { - case CIRRUS_SR7_BPP_32: - svga->bpp = 32; - svga->render = svga_render_32bpp_highres; - svga->rowoffset *= 2; - break; - - case CIRRUS_SR7_BPP_24: - svga->bpp = 24; - svga->render = svga_render_24bpp_highres; - break; - - case CIRRUS_SR7_BPP_16: - case CIRRUS_SR7_BPP_16_DOUBLEVCLK: - svga->bpp = 16; - svga->render = svga_render_16bpp_highres; - break; - - case CIRRUS_SR7_BPP_8: - svga->bpp = 8; - svga->render = svga_render_8bpp_highres; - break; - } - break; - } - } - else - { - svga->bpp = 15; - svga->render = svga_render_15bpp_highres; + break; + + case CIRRUS_SR7_BPP_16: + case CIRRUS_SR7_BPP_16_DOUBLEVCLK: + svga->bpp = 16; + svga->render = svga_render_16bpp_highres; + break; + + case CIRRUS_SR7_BPP_8: + svga->bpp = 8; + svga->render = svga_render_8bpp_highres; + break; + } + break; } + } else { + svga->bpp = 15; + svga->render = svga_render_15bpp_highres; } - + } + clocksel = (svga->miscout >> 2) & 3; if (!gd54xx->vclk_n[clocksel] || !gd54xx->vclk_d[clocksel]) @@ -833,19 +833,18 @@ gd54xx_recalctimings(svga_t *svga) int d = (gd54xx->vclk_d[clocksel] & 0x3e) >> 1; int m = gd54xx->vclk_d[clocksel] & 0x01 ? 2 : 1; float freq = (14318184.0 * ((float)n / ((float)d * m))); - switch (svga->seqregs[7] & ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) ? 0xe : 6)) - { - case 2: - freq /= 2.0; - break; - case 4: - if (svga->crtc[0x27] <= CIRRUS_ID_CLGD5434) + switch (svga->seqregs[7] & (gd54xx_is_5434(svga) ? 0xe : 6)) { + case 2: + freq /= 2.0; + break; + case 4: + if (!gd54xx_is_5434(svga)) freq /= 3.0; - break; + break; } svga->clock = cpuclock / freq; } - + svga->vram_display_mask = (svga->crtc[0x1b] & 2) ? gd54xx->vram_mask : 0x3ffff; } @@ -856,12 +855,14 @@ void gd54xx_hwcursor_draw(svga_t *svga, int displine) int x, xx, comb, b0, b1; uint8_t dat[2]; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; - int y_add = (enable_overscan && !suppress_overscan) ? 16 : 0; - int x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; + int y_add, x_add; int pitch = (svga->hwcursor.xsize == 64) ? 16 : 4; uint32_t bgcol = gd54xx->extpallook[0x00]; uint32_t fgcol = gd54xx->extpallook[0x0f]; + y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; + x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; + if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += pitch; @@ -994,9 +995,6 @@ gd54xx_blt_write_l(uint32_t addr, uint32_t val, void *p) } -static void gd54xx_write_linear(uint32_t addr, uint8_t val, gd54xx_t *gd54xx); - - static void gd54xx_write(uint32_t addr, uint8_t val, void *p) { @@ -1018,7 +1016,8 @@ gd54xx_write(uint32_t addr, uint8_t val, void *p) addr &= svga->banked_mask; addr = (addr & 0x7fff) + gd54xx->bank[(addr >> 15) & 1]; - gd54xx_write_linear(addr, val, gd54xx); + + svga_write_linear(addr, val, svga); } @@ -1037,12 +1036,12 @@ gd54xx_writew(uint32_t addr, uint16_t val, void *p) addr &= svga->banked_mask; addr = (addr & 0x7fff) + gd54xx->bank[(addr >> 15) & 1]; - - if (svga->writemode < 4) - svga_writew_linear(addr, val, svga); + + if (svga->writemode < 4) + svga_writew_linear(addr, val, svga); else { - gd54xx_write_linear(addr, val, gd54xx); - gd54xx_write_linear(addr+1, val >> 8, gd54xx); + svga_write_linear(addr, val, svga); + svga_write_linear(addr + 1, val >> 8, svga); } } @@ -1068,52 +1067,24 @@ gd54xx_writel(uint32_t addr, uint32_t val, void *p) if (svga->writemode < 4) svga_writel_linear(addr, val, svga); else { - gd54xx_write_linear(addr, val, gd54xx); - gd54xx_write_linear(addr+1, val >> 8, gd54xx); - gd54xx_write_linear(addr+2, val >> 16, gd54xx); - gd54xx_write_linear(addr+3, val >> 24, gd54xx); + svga_write_linear(addr, val, svga); + svga_write_linear(addr+1, val >> 8, svga); + svga_write_linear(addr+2, val >> 16, svga); + svga_write_linear(addr+3, val >> 24, svga); } } +/* This adds write modes 4 and 5 to SVGA. */ static void -gd54xx_write_linear(uint32_t addr, uint8_t val, gd54xx_t *gd54xx) +gd54xx_write_modes45(svga_t *svga, uint8_t val, uint32_t addr) { - svga_t *svga = &gd54xx->svga; - uint8_t vala, valb, valc, vald, wm = svga->writemask; - int writemask2 = svga->writemask; - int i; - uint8_t j; - - cycles -= video_timing_write_b; - cycles_lost += video_timing_write_b; - - egawrites++; - - if (!(svga->gdcreg[6] & 1)) - svga->fullchange = 2; - if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4)) { - writemask2 = 1 << (addr & 3); - addr &= ~3; - } else if (svga->chain2_write) { - writemask2 &= ~0xa; - if (addr & 1) - writemask2 <<= 1; - addr &= ~1; - addr <<= 2; - } else - addr <<= 2; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - svga->changedvram[addr >> 12]=changeframecount; + uint32_t i, j; switch (svga->writemode) { case 4: if (svga->gdcreg[0xb] & 0x10) { addr <<= 2; - svga->changedvram[addr >> 12] = changeframecount; for (i = 0; i < 8; i++) { if (val & svga->seqregs[2] & (0x80 >> i)) { @@ -1122,173 +1093,41 @@ gd54xx_write_linear(uint32_t addr, uint8_t val, gd54xx_t *gd54xx) } } } else { - addr <<= 1; - svga->changedvram[addr >> 12] = changeframecount; + addr <<= 1; for (i = 0; i < 8; i++) { - if (val & svga->seqregs[2] & (0x80 >> i)) - svga->vram[addr + i] = svga->gdcreg[1]; + if (val & svga->seqregs[2] & (0x80 >> i)) + svga->vram[addr + i] = svga->gdcreg[1]; } - } - break; - - case 5: - if (svga->gdcreg[0xb] & 0x10) - { - addr <<= 2; - svga->changedvram[addr >> 12] = changeframecount; + } + break; + + case 5: + if (svga->gdcreg[0xb] & 0x10) { + addr <<= 2; for (i = 0; i < 8; i++) { j = (0x80 >> i); if (svga->seqregs[2] & j) { - svga->vram[addr + (i << 1)] = (val & j) ? svga->gdcreg[1] : svga->gdcreg[0]; - svga->vram[addr + (i << 1) + 1] = (val & j) ? svga->gdcreg[0x11] : svga->gdcreg[0x10]; + svga->vram[addr + (i << 1)] = (val & j) ? + svga->gdcreg[1] : svga->gdcreg[0]; + svga->vram[addr + (i << 1) + 1] = (val & j) ? + svga->gdcreg[0x11] : svga->gdcreg[0x10]; } } - } - else - { - addr <<= 1; - svga->changedvram[addr >> 12] = changeframecount; + } else { + addr <<= 1; for (i = 0; i < 8; i++) { j = (0x80 >> i); if (svga->seqregs[2] & j) svga->vram[addr + i] = (val & j) ? svga->gdcreg[1] : svga->gdcreg[0]; } - } - break; - - case 1: - if (writemask2 & 1) svga->vram[addr] = svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld; - break; - case 0: - if (svga->gdcreg[3] & 7) - val = svga_rotate[svga->gdcreg[3] & 7][val]; - if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { - if (writemask2 & 1) svga->vram[addr] = val; - if (writemask2 & 2) svga->vram[addr | 0x1] = val; - if (writemask2 & 4) svga->vram[addr | 0x2] = val; - if (writemask2 & 8) svga->vram[addr | 0x3] = val; - } else { - if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0; - else vala = val; - if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0; - else valb = val; - if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0; - else valc = val; - if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0; - else vald = val; - - switch (svga->gdcreg[3] & 0x18) { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } } break; - case 2: - if (!(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) { - if (writemask2 & 1) svga->vram[addr] = (((val & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - } else { - vala = ((val & 1) ? 0xff : 0); - valb = ((val & 2) ? 0xff : 0); - valc = ((val & 4) ? 0xff : 0); - vald = ((val & 8) ? 0xff : 0); - switch (svga->gdcreg[3] & 0x18) { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } - } - break; - case 3: - if (svga->gdcreg[3] & 7) - val = svga_rotate[svga->gdcreg[3] & 7][val]; - wm = svga->gdcreg[8]; - svga->gdcreg[8] &= val; - - vala = (svga->gdcreg[0] & 1) ? 0xff : 0; - valb = (svga->gdcreg[0] & 2) ? 0xff : 0; - valc = (svga->gdcreg[0] & 4) ? 0xff : 0; - vald = (svga->gdcreg[0] & 8) ? 0xff : 0; - switch (svga->gdcreg[3] & 0x18) { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } - svga->gdcreg[8] = wm; - break; } + + svga->changedvram[addr >> 12] = changeframecount; } @@ -1378,10 +1217,8 @@ gd54xx_readw_linear(uint32_t addr, void *p) temp = svga_readb_linear(addr + 1, p); temp |= (svga_readb_linear(addr, p) << 8); - if (svga->fast) { + if (svga->fast) cycles -= video_timing_read_w; - cycles_lost += video_timing_read_w; - } return temp; case 3: @@ -1439,10 +1276,8 @@ gd54xx_readl_linear(uint32_t addr, void *p) temp |= (svga_readb_linear(addr + 3, p) << 16); temp |= (svga_readb_linear(addr + 2, p) << 24); - if (svga->fast) { + if (svga->fast) cycles -= video_timing_read_l; - cycles_lost += video_timing_read_l; - } return temp; case 2: @@ -1451,10 +1286,8 @@ gd54xx_readl_linear(uint32_t addr, void *p) temp |= (svga_readb_linear(addr + 1, p) << 16); temp |= (svga_readb_linear(addr, p) << 24); - if (svga->fast) { + if (svga->fast) cycles -= video_timing_read_l; - cycles_lost += video_timing_read_l; - } return temp; case 3: @@ -1506,10 +1339,7 @@ gd54xx_writeb_linear(uint32_t addr, uint8_t val, void *p) return; } - if (svga->writemode < 4) - svga_write_linear(addr, val, svga); - else - gd54xx_write_linear(addr, val & 0xff, gd54xx); + svga_write_linear(addr, val, svga); } @@ -1561,10 +1391,8 @@ gd54xx_writew_linear(uint32_t addr, uint16_t val, void *p) svga_writeb_linear(addr + 1, val & 0xff, svga); svga_writeb_linear(addr, val >> 8, svga); - if (svga->fast) { + if (svga->fast) cycles -= video_timing_write_w; - cycles_lost += video_timing_write_w; - } case 3: return; } @@ -1572,14 +1400,14 @@ gd54xx_writew_linear(uint32_t addr, uint16_t val, void *p) switch(ap) { case 0: default: - gd54xx_write_linear(addr, val & 0xff, gd54xx); - gd54xx_write_linear(addr + 1, val >> 8, gd54xx); + svga_write_linear(addr, val & 0xff, svga); + svga_write_linear(addr + 1, val >> 8, svga); return; case 2: addr ^= 0x00000002; case 1: - gd54xx_write_linear(addr + 1, val & 0xff, gd54xx); - gd54xx_write_linear(addr, val >> 8, gd54xx); + svga_write_linear(addr + 1, val & 0xff, svga); + svga_write_linear(addr, val >> 8, svga); case 3: return; } @@ -1654,30 +1482,28 @@ gd54xx_writel_linear(uint32_t addr, uint32_t val, void *p) return; } - if (svga->fast) { + if (svga->fast) cycles -= video_timing_write_l; - cycles_lost += video_timing_write_l; - } } else { switch(ap) { case 0: default: - gd54xx_write_linear(addr, val & 0xff, gd54xx); - gd54xx_write_linear(addr+1, val >> 8, gd54xx); - gd54xx_write_linear(addr+2, val >> 16, gd54xx); - gd54xx_write_linear(addr+3, val >> 24, gd54xx); + svga_write_linear(addr, val & 0xff, svga); + svga_write_linear(addr+1, val >> 8, svga); + svga_write_linear(addr+2, val >> 16, svga); + svga_write_linear(addr+3, val >> 24, svga); return; case 1: - gd54xx_write_linear(addr + 1, val & 0xff, gd54xx); - gd54xx_write_linear(addr, val >> 8, gd54xx); - gd54xx_write_linear(addr + 3, val >> 16, gd54xx); - gd54xx_write_linear(addr + 2, val >> 24, gd54xx); + svga_write_linear(addr + 1, val & 0xff, svga); + svga_write_linear(addr, val >> 8, svga); + svga_write_linear(addr + 3, val >> 16, svga); + svga_write_linear(addr + 2, val >> 24, svga); return; case 2: - gd54xx_write_linear(addr + 3, val & 0xff, gd54xx); - gd54xx_write_linear(addr + 2, val >> 8, gd54xx); - gd54xx_write_linear(addr + 1, val >> 16, gd54xx); - gd54xx_write_linear(addr, val >> 24, gd54xx); + svga_write_linear(addr + 3, val & 0xff, svga); + svga_write_linear(addr + 2, val >> 8, svga); + svga_write_linear(addr + 1, val >> 16, svga); + svga_write_linear(addr, val >> 24, svga); case 3: return; } @@ -1739,44 +1565,44 @@ gd543x_mmio_write(uint32_t addr, uint8_t val, void *p) if (gd543x_do_mmio(svga, addr)) { switch (addr & 0xff) { case 0x00: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0xffffff00) | val; else gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0xff00) | val; break; case 0x01: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0xffff00ff) | (val << 8); else gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0x00ff) | (val << 8); break; case 0x02: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0xff00ffff) | (val << 16); break; case 0x03: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0x00ffffff) | (val << 24); break; case 0x04: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0xffffff00) | val; else gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0xff00) | val; break; case 0x05: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0xffff00ff) | (val << 8); else gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0x00ff) | (val << 8); break; case 0x06: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0xff00ffff) | (val << 16); break; case 0x07: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0x00ffffff) | (val << 24); break; @@ -1785,7 +1611,7 @@ gd543x_mmio_write(uint32_t addr, uint8_t val, void *p) break; case 0x09: gd54xx->blt.width = (gd54xx->blt.width & 0x00ff) | (val << 8); - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.width &= 0x1fff; else gd54xx->blt.width &= 0x07ff; @@ -1818,7 +1644,7 @@ gd543x_mmio_write(uint32_t addr, uint8_t val, void *p) break; case 0x12: gd54xx->blt.dst_addr = (gd54xx->blt.dst_addr & 0x00ffff) | (val << 16); - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.dst_addr &= 0x3fffff; else gd54xx->blt.dst_addr &= 0x1fffff; @@ -1844,7 +1670,7 @@ gd543x_mmio_write(uint32_t addr, uint8_t val, void *p) break; case 0x16: gd54xx->blt.src_addr = (gd54xx->blt.src_addr & 0x00ffff) | (val << 16); - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.src_addr &= 0x3fffff; else gd54xx->blt.src_addr &= 0x1fffff; @@ -2027,7 +1853,7 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga) else gd54xx->blt.y_count = 0; - if ((gd54xx->blt.mode & (CIRRUS_BLTMODE_MEMSYSSRC|CIRRUS_BLTMODE_COLOREXPAND)) == (CIRRUS_BLTMODE_MEMSYSSRC|CIRRUS_BLTMODE_COLOREXPAND)) { + if (gd54xx->blt.mode & CIRRUS_BLTMODE_MEMSYSSRC) { if (!(svga->seqregs[7] & 0xf0)) { mem_mapping_set_handler(&svga->mapping, NULL, NULL, NULL, NULL, gd54xx_blt_write_w, gd54xx_blt_write_l); mem_mapping_set_p(&svga->mapping, gd54xx); @@ -2037,7 +1863,7 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga) } gd543x_recalc_mapping(gd54xx); return; - } else if (gd54xx->blt.mode != CIRRUS_BLTMODE_MEMSYSSRC) { + } else { if (!(svga->seqregs[7] & 0xf0)) { mem_mapping_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, gd54xx_readl, gd54xx_write, gd54xx_writew, gd54xx_writel); mem_mapping_set_p(&gd54xx->svga.mapping, gd54xx); @@ -2083,6 +1909,12 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga) cpu_dat <<= 1; count--; } + } else { + /*This must stay for general purpose Cirrus drivers to render fine in WinNT 3.5x*/ + src = cpu_dat & 0xff; + cpu_dat >>= 8; + count -= 8; + mask = 1; } } else { switch (gd54xx->blt.mode & (CIRRUS_BLTMODE_PATTERNCOPY|CIRRUS_BLTMODE_COLOREXPAND)) { @@ -2265,6 +2097,9 @@ cl_pci_read(int func, int addr, void *p) gd54xx_t *gd54xx = (gd54xx_t *)p; svga_t *svga = &gd54xx->svga; + if ((addr >= 0x30) && (addr <= 0x33) && (!gd54xx->has_bios)) + return 0; + switch (addr) { case 0x00: return 0x13; /*Cirrus Logic*/ case 0x01: return 0x10; @@ -2276,10 +2111,11 @@ cl_pci_read(int func, int addr, void *p) case PCI_REG_COMMAND: return gd54xx->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ - case 0x07: return 0 << 1; /*Fast DEVSEL timing*/ + // case 0x07: return 0 << 1; /*Fast DEVSEL timing*/ + case 0x07: return 0x02; /*Fast DEVSEL timing*/ - case 0x08: return 0; /*Revision ID*/ - case 0x09: return 0; /*Programming interface*/ + case 0x08: return gd54xx->rev; /*Revision ID*/ + case 0x09: return 0x00; /*Programming interface*/ case 0x0a: return 0x00; /*Supports VGA interface*/ case 0x0b: return 0x03; @@ -2306,6 +2142,9 @@ cl_pci_write(int func, int addr, uint8_t val, void *p) { gd54xx_t *gd54xx = (gd54xx_t *)p; + if ((addr >= 0x30) && (addr <= 0x33) && (!gd54xx->has_bios)) + return; + switch (addr) { case PCI_REG_COMMAND: gd54xx->pci_regs[PCI_REG_COMMAND] = val & 0x23; @@ -2348,6 +2187,8 @@ static void gd54xx->pci = !!(info->flags & DEVICE_PCI); gd54xx->vlb = !!(info->flags & DEVICE_VLB); + gd54xx->rev = 0; + gd54xx->has_bios = 1; switch (id) { case CIRRUS_ID_CLGD5426: romfn = BIOS_GD5426_PATH; @@ -2364,13 +2205,6 @@ static void romfn = BIOS_GD5429_PATH; break; - case CIRRUS_ID_CLGD5430: - if (gd54xx->pci) - romfn = BIOS_GD5430_PCI_PATH; - else - romfn = BIOS_GD5430_VLB_PATH; - break; - case CIRRUS_ID_CLGD5434: romfn = BIOS_GD5434_PATH; break; @@ -2379,6 +2213,24 @@ static void romfn = BIOS_GD5436_PATH; break; + case CIRRUS_ID_CLGD5430: + if (info->local & 0x400) { + /* CL-GD 5440 */ + gd54xx->rev = 0x47; + if (info->local & 0x200) { + romfn = NULL; + gd54xx->has_bios = 0; + } else + romfn = BIOS_GD5440_PATH; + } else { + /* CL-GD 5430 */ + if (gd54xx->pci) + romfn = BIOS_GD5430_PCI_PATH; + else + romfn = BIOS_GD5430_VLB_PATH; + } + break; + case CIRRUS_ID_CLGD5446: if (info->local & 0x100) romfn = BIOS_GD5446_STB_PATH; @@ -2394,11 +2246,13 @@ static void gd54xx->vram_size = device_get_config_int("memory"); gd54xx->vram_mask = (gd54xx->vram_size << 20) - 1; - rom_init(&gd54xx->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (romfn) + rom_init(&gd54xx->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); svga_init(&gd54xx->svga, gd54xx, gd54xx->vram_size << 20, gd54xx_recalctimings, gd54xx_in, gd54xx_out, gd54xx_hwcursor_draw, NULL); + svga_set_ven_write(&gd54xx->svga, gd54xx_write_modes45); mem_mapping_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, gd54xx_readl, gd54xx_write, gd54xx_writew, gd54xx_writel); mem_mapping_set_p(&svga->mapping, gd54xx); @@ -2480,6 +2334,12 @@ gd5436_available(void) return rom_present(BIOS_GD5436_PATH); } +static int +gd5440_available(void) +{ + return rom_present(BIOS_GD5440_PATH); +} + static int gd5446_available(void) { @@ -2527,15 +2387,6 @@ gd54xx_force_redraw(void *p) } -void -gd54xx_add_status_info(char *s, int max_len, void *p) -{ - gd54xx_t *gd54xx = (gd54xx_t *)p; - - svga_add_status_info(s, max_len, &gd54xx->svga); -} - - static const device_config_t gd5428_config[] = { { @@ -2563,6 +2414,33 @@ static const device_config_t gd5428_config[] = } }; +static const device_config_t gd5440_onboard_config[] = +{ + { + .name = "memory", + .description = "Video memory size", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "1 MB", + .value = 1 + }, + { + .description = "2 MB", + .value = 2 + }, + { + .description = "" + } + }, + .default_int = 2 + }, + { + .type = -1 + } +}; + static const device_config_t gd5434_config[] = { { @@ -2601,7 +2479,6 @@ const device_t gd5426_vlb_device = gd5426_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, gd5428_config }; @@ -2616,7 +2493,6 @@ const device_t gd5428_isa_device = gd5428_isa_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, gd5428_config }; @@ -2631,7 +2507,6 @@ const device_t gd5428_vlb_device = gd5428_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, gd5428_config }; @@ -2646,7 +2521,6 @@ const device_t gd5429_isa_device = gd5429_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, gd5428_config }; @@ -2661,7 +2535,6 @@ const device_t gd5429_vlb_device = gd5429_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, gd5428_config }; @@ -2676,7 +2549,6 @@ const device_t gd5430_vlb_device = gd5430_vlb_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, gd5428_config }; @@ -2691,7 +2563,6 @@ const device_t gd5430_pci_device = gd5430_pci_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, gd5428_config }; @@ -2706,7 +2577,6 @@ const device_t gd5434_isa_device = gd5434_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, gd5434_config }; @@ -2721,7 +2591,6 @@ const device_t gd5434_vlb_device = gd5434_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, gd5434_config }; @@ -2736,7 +2605,6 @@ const device_t gd5434_pci_device = gd5434_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, gd5434_config }; @@ -2751,10 +2619,37 @@ const device_t gd5436_pci_device = gd5436_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, gd5434_config }; +const device_t gd5440_onboard_pci_device = +{ + "Cirrus Logic CL-GD 5440 (On-Board PCI)", + DEVICE_PCI, + CIRRUS_ID_CLGD5440 | 0x600, + gd54xx_init, + gd54xx_close, + NULL, + NULL, + gd54xx_speed_changed, + gd54xx_force_redraw, + gd5440_onboard_config +}; + +const device_t gd5440_pci_device = +{ + "Cirrus Logic CL-GD 5440 (PCI)", + DEVICE_PCI, + CIRRUS_ID_CLGD5440 | 0x400, + gd54xx_init, + gd54xx_close, + NULL, + gd5440_available, + gd54xx_speed_changed, + gd54xx_force_redraw, + gd5428_config +}; + const device_t gd5446_pci_device = { "Cirrus Logic CL-GD 5446 (PCI)", @@ -2766,7 +2661,6 @@ const device_t gd5446_pci_device = gd5446_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, gd5434_config }; @@ -2774,14 +2668,13 @@ const device_t gd5446_stb_pci_device = { "STB Nitro 64V (PCI)", DEVICE_PCI, - CIRRUS_ID_CLGD5446, + CIRRUS_ID_CLGD5446 | 0x100, gd54xx_init, gd54xx_close, NULL, gd5446_stb_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, gd5434_config }; @@ -2796,6 +2689,5 @@ const device_t gd5480_pci_device = gd5480_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, gd5434_config }; diff --git a/src/video/vid_cl54xx.h b/src/video/vid_cl54xx.h index 91bfa44aa..654a6326e 100644 --- a/src/video/vid_cl54xx.h +++ b/src/video/vid_cl54xx.h @@ -12,6 +12,8 @@ extern const device_t gd5434_isa_device; extern const device_t gd5434_vlb_device; extern const device_t gd5434_pci_device; extern const device_t gd5436_pci_device; +extern const device_t gd5440_onboard_pci_device; +extern const device_t gd5440_pci_device; extern const device_t gd5446_pci_device; extern const device_t gd5446_stb_pci_device; extern const device_t gd5480_pci_device; \ No newline at end of file diff --git a/src/video/vid_colorplus.c b/src/video/vid_colorplus.c index d03c7d94d..95d82c70f 100644 --- a/src/video/vid_colorplus.c +++ b/src/video/vid_colorplus.c @@ -8,7 +8,7 @@ * * Plantronics ColorPlus emulation. * - * Version: @(#)vid_colorplus.c 1.0.8 2018/03/18 + * Version: @(#)vid_colorplus.c 1.0.9 2018/04/26 * * Authors: Sarah Walker, * Miran Grca, @@ -473,6 +473,5 @@ const device_t colorplus_device = NULL, NULL, colorplus_speed_changed, NULL, - NULL, colorplus_config }; diff --git a/src/video/vid_compaq_cga.c b/src/video/vid_compaq_cga.c index 10c518403..c502aa6dd 100644 --- a/src/video/vid_compaq_cga.c +++ b/src/video/vid_compaq_cga.c @@ -444,7 +444,6 @@ const device_t compaq_cga_device = NULL, compaq_cga_speed_changed, NULL, - NULL, cga_config }; @@ -458,6 +457,5 @@ const device_t compaq_cga_2_device = NULL, compaq_cga_speed_changed, NULL, - NULL, cga_config }; diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 2d73d46df..426d23957 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -9,7 +9,7 @@ * Emulation of the EGA, Chips & Technologies SuperEGA, and * AX JEGA graphics cards. * - * Version: @(#)vid_ega.c 1.0.16 2018/03/18 + * Version: @(#)vid_ega.c 1.0.17 2018/04/26 * * Authors: Sarah Walker, * Miran Grca, @@ -683,7 +683,6 @@ void ega_write(uint32_t addr, uint8_t val, void *p) egawrites++; cycles -= video_timing_write_b; - cycles_lost += video_timing_write_b; if (addr >= 0xB0000) addr &= 0x7fff; else addr &= 0xffff; @@ -820,7 +819,6 @@ uint8_t ega_read(uint32_t addr, void *p) egareads++; cycles -= video_timing_read_b; - cycles_lost += video_timing_read_b; if (addr >= 0xb0000) addr &= 0x7fff; else addr &= 0xffff; @@ -1253,7 +1251,6 @@ const device_t ega_device = ega_standalone_available, ega_speed_changed, NULL, - NULL, ega_config }; @@ -1266,7 +1263,6 @@ const device_t cpqega_device = cpqega_standalone_available, ega_speed_changed, NULL, - NULL, ega_config }; @@ -1279,7 +1275,6 @@ const device_t sega_device = sega_standalone_available, ega_speed_changed, NULL, - NULL, ega_config }; @@ -1293,7 +1288,6 @@ const device_t jega_device = sega_standalone_available, ega_speed_changed, NULL, - NULL, ega_config }; #endif diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index 1dd4abb31..5db6c55d9 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -8,7 +8,7 @@ * * Emulation of the Tseng Labs ET4000. * - * Version: @(#)vid_et4000.c 1.0.5 2018/03/18 + * Version: @(#)vid_et4000.c 1.0.6 2018/04/26 * * Authors: Sarah Walker, * Miran Grca, @@ -206,13 +206,6 @@ void et4000_force_redraw(void *p) et4000->svga.fullchange = changeframecount; } -void et4000_add_status_info(char *s, int max_len, void *p) -{ - et4000_t *et4000 = (et4000_t *)p; - - svga_add_status_info(s, max_len, &et4000->svga); -} - const device_t et4000_device = { "Tseng Labs ET4000AX", @@ -221,6 +214,5 @@ const device_t et4000_device = et4000_available, et4000_speed_changed, et4000_force_redraw, - et4000_add_status_info, NULL }; diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 19bb5c0a8..2ed8837bf 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -10,7 +10,7 @@ * * Known bugs: Accelerator doesn't work in planar modes * - * Version: @(#)vid_et4000w32.c 1.0.7 2018/03/18 + * Version: @(#)vid_et4000w32.c 1.0.11 2018/07/16 * * Authors: Sarah Walker, * Miran Grca, @@ -18,11 +18,13 @@ * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 Miran Grca. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../cpu/cpu.h" #include "../io.h" @@ -155,6 +157,27 @@ void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p); void et4000w32_blit_start(et4000w32p_t *et4000); void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32p_t *et4000); + +#ifdef ENABLE_ET4000W32_LOG +int et4000w32_do_log = ENABLE_ET4000W32_LOG; +#endif + + +static void +et4000w32_log(const char *format, ...) +{ +#ifdef ENABLE_ET4000W32_LOG + va_list ap; + + if (et4000w32_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + void et4000w32p_out(uint16_t addr, uint8_t val, void *p) { et4000w32p_t *et4000 = (et4000w32p_t *)p; @@ -285,6 +308,15 @@ uint8_t et4000w32p_in(uint16_t addr, void *p) case 0x214B: case 0x215B: case 0x216B: case 0x217B: if (et4000->index==0xec) return (et4000->regs[0xec] & 0xf) | 0x60; /*ET4000/W32p rev D*/ + if (et4000->index == 0xee) /*Preliminary implementation*/ + { + if (svga->bpp == 8) + return 3; + else if (svga->bpp == 16) + return 4; + else + break; + } if (et4000->index == 0xef) { if (et4000->pci) return et4000->regs[0xef] | 0xe0; /*PCI*/ @@ -351,7 +383,6 @@ void et4000w32p_recalcmapping(et4000w32p_t *et4000) if (svga->crtc[0x36] & 0x10) /*Linear frame buffer*/ { mem_mapping_set_addr(&et4000->linear_mapping, et4000->linearbase, 0x200000); - svga->linear_base = et4000->linearbase; mem_mapping_disable(&svga->mapping); mem_mapping_disable(&et4000->mmu_mapping); } @@ -839,10 +870,10 @@ void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et400 { while (count--) { - /* if (bltout) pclog("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y); */ + et4000w32_log("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y); pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & 0x1fffff]; source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & 0x1fffff]; - /* if (bltout) pclog("%06X %06X ", (et4000->acl.pattern_addr + et4000->acl.pattern_x) & 0x1fffff, (et4000->acl.source_addr + et4000->acl.source_x) & 0x1fffff); */ + et4000w32_log("%06X %06X ", (et4000->acl.pattern_addr + et4000->acl.pattern_x) & 0x1fffff, (et4000->acl.source_addr + et4000->acl.source_x) & 0x1fffff); if (cpu_input == 2) { source = sdat & 0xff; @@ -850,11 +881,11 @@ void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et400 } dest = svga->vram[et4000->acl.dest_addr & 0x1fffff]; out = 0; - /* if (bltout) pclog("%06X ", et4000->acl.dest_addr); */ + et4000w32_log("%06X ", et4000->acl.dest_addr); if ((et4000->acl.internal.ctrl_routing & 0xa) == 8) { mixdat = svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff] & (1 << (et4000->acl.mix_addr & 7)); - /* if (bltout) pclog("%06X %02X ", et4000->acl.mix_addr, svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff]); */ + et4000w32_log("%06X %02X ", et4000->acl.mix_addr, svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff]); } else { @@ -871,7 +902,7 @@ void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et400 if (pattern & (1 << c)) d |= 4; if (rop & (1 << d)) out |= (1 << c); } - /* if (bltout) pclog("%06X = %02X\n", et4000->acl.dest_addr & 0x1fffff, out); */ + et4000w32_log("%06X = %02X\n", et4000->acl.dest_addr & 0x1fffff, out); if (!(et4000->acl.internal.ctrl_routing & 0x40)) { svga->vram[et4000->acl.dest_addr & 0x1fffff] = out; @@ -954,11 +985,11 @@ void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et400 { while (count--) { - /* if (bltout) pclog("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y); */ - + et4000w32_log("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y); + pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & 0x1fffff]; source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & 0x1fffff]; - /* if (bltout) pclog("%i %06X %06X %02X %02X ", et4000->acl.pattern_y, (et4000->acl.pattern_addr + et4000->acl.pattern_x) & 0x1fffff, (et4000->acl.source_addr + et4000->acl.source_x) & 0x1fffff, pattern, source); */ + et4000w32_log("%i %06X %06X %02X %02X ", et4000->acl.pattern_y, (et4000->acl.pattern_addr + et4000->acl.pattern_x) & 0x1fffff, (et4000->acl.source_addr + et4000->acl.source_x) & 0x1fffff, pattern, source); if (cpu_input == 2) { @@ -967,11 +998,11 @@ void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et400 } dest = svga->vram[et4000->acl.dest_addr & 0x1fffff]; out = 0; - /* if (bltout) pclog("%06X %02X %i %08X %08X ", dest, et4000->acl.dest_addr, mix & 1, mix, et4000->acl.mix_addr); */ + et4000w32_log("%06X %02X %i %08X %08X ", dest, et4000->acl.dest_addr, mix & 1, mix, et4000->acl.mix_addr); if ((et4000->acl.internal.ctrl_routing & 0xa) == 8) { mixdat = svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff] & (1 << (et4000->acl.mix_addr & 7)); - /* if (bltout) pclog("%06X %02X ", et4000->acl.mix_addr, svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff]); */ + et4000w32_log("%06X %02X ", et4000->acl.mix_addr, svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff]); } else { @@ -988,7 +1019,7 @@ void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et400 if (pattern & (1 << c)) d |= 4; if (rop & (1 << d)) out |= (1 << c); } - /* if (bltout) pclog("%06X = %02X\n", et4000->acl.dest_addr & 0x1fffff, out); */ + et4000w32_log("%06X = %02X\n", et4000->acl.dest_addr & 0x1fffff, out); if (!(et4000->acl.internal.ctrl_routing & 0x40)) { svga->vram[et4000->acl.dest_addr & 0x1fffff] = out; @@ -1046,10 +1077,12 @@ void et4000w32p_hwcursor_draw(svga_t *svga, int displine) { int x, offset; uint8_t dat; - int y_add = (enable_overscan && !suppress_overscan) ? 16 : 0; - int x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; + int y_add, x_add; offset = svga->hwcursor_latch.xoff; + y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; + x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; + for (x = 0; x < 64 - svga->hwcursor_latch.xoff; x += 4) { dat = svga->vram[svga->hwcursor_latch.addr + (offset >> 2)]; @@ -1178,12 +1211,12 @@ void et4000w32p_pci_write(int func, int addr, uint8_t val, void *p) { addr = 0xC0000; } - /* pclog("ET4000 bios_rom enabled at %08x\n", addr); */ + et4000w32_log("ET4000 bios_rom enabled at %08x\n", addr); mem_mapping_set_addr(&et4000->bios_rom.mapping, addr, 0x8000); } else { - /* pclog("ET4000 bios_rom disabled\n"); */ + et4000w32_log("ET4000 bios_rom disabled\n"); mem_mapping_disable(&et4000->bios_rom.mapping); } return; @@ -1293,22 +1326,6 @@ void et4000w32p_force_redraw(void *p) et4000w32p->svga.fullchange = changeframecount; } -void et4000w32p_add_status_info(char *s, int max_len, void *p) -{ - et4000w32p_t *et4000 = (et4000w32p_t *)p; - char temps[256]; - uint64_t new_time = plat_timer_read(); - uint64_t status_diff = new_time - et4000->status_time; - et4000->status_time = new_time; - - svga_add_status_info(s, max_len, &et4000->svga); - - sprintf(temps, "%f%% CPU\n%f%% CPU (real)\n\n", ((double)et4000->blitter_time * 100.0) / timer_freq, ((double)et4000->blitter_time * 100.0) / status_diff); - strncat(s, temps, max_len); - - et4000->blitter_time = 0; -} - static const device_config_t et4000w32p_config[] = { { @@ -1338,7 +1355,6 @@ const device_t et4000w32p_cardex_vlb_device = et4000w32p_cardex_available, et4000w32p_speed_changed, et4000w32p_force_redraw, - et4000w32p_add_status_info, et4000w32p_config }; @@ -1350,7 +1366,6 @@ const device_t et4000w32p_cardex_pci_device = et4000w32p_cardex_available, et4000w32p_speed_changed, et4000w32p_force_redraw, - et4000w32p_add_status_info, et4000w32p_config }; @@ -1363,7 +1378,6 @@ const device_t et4000w32p_vlb_device = et4000w32p_available, et4000w32p_speed_changed, et4000w32p_force_redraw, - et4000w32p_add_status_info, et4000w32p_config }; @@ -1375,7 +1389,6 @@ const device_t et4000w32p_pci_device = et4000w32p_available, et4000w32p_speed_changed, et4000w32p_force_redraw, - et4000w32p_add_status_info, et4000w32p_config }; #endif diff --git a/src/video/vid_genius.c b/src/video/vid_genius.c index a205628ce..91d1bce61 100644 --- a/src/video/vid_genius.c +++ b/src/video/vid_genius.c @@ -8,7 +8,7 @@ * * MDSI Genius VHR emulation. * - * Version: @(#)vid_genius.c 1.0.8 2018/03/18 + * Version: @(#)vid_genius.c 1.0.10 2018/05/20 * * Authors: Sarah Walker, * Miran Grca, @@ -93,6 +93,7 @@ extern uint8_t fontdat8x12[256][16]; * in an 8x12 cell if necessary. */ + typedef struct genius_t { @@ -134,6 +135,8 @@ typedef struct genius_t uint8_t *vram; } genius_t; +static uint32_t genius_pal[4]; + /* Mapping of attributes to colours, in MDA emulation mode */ static int mdacols[256][2][2]; @@ -219,8 +222,6 @@ uint8_t genius_in(uint16_t addr, void *p) return 0xff; } - - void genius_write(uint32_t addr, uint8_t val, void *p) { genius_t *genius = (genius_t *)p; @@ -257,8 +258,6 @@ uint8_t genius_read(uint32_t addr, void *p) return genius->vram[addr]; } - - void genius_recalctimings(genius_t *genius) { double disptime; @@ -269,8 +268,8 @@ void genius_recalctimings(genius_t *genius) _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - genius->dispontime = (int64_t)(_dispontime * (1LL << TIMER_SHIFT)); - genius->dispofftime = (int64_t)(_dispofftime * (1LL << TIMER_SHIFT)); + genius->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); + genius->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); } @@ -290,7 +289,7 @@ void genius_textline(genius_t *genius, uint8_t background) uint16_t ma = (genius->mda_crtc[13] | (genius->mda_crtc[12] << 8)) & 0x3fff; uint16_t ca = (genius->mda_crtc[15] | (genius->mda_crtc[14] << 8)) & 0x3fff; unsigned char *framebuf = genius->vram + 0x10000; - uint8_t col; + uint32_t col; /* Character height is 12-15 */ charh = 15 - (genius->genius_charh & 3); @@ -342,13 +341,13 @@ void genius_textline(genius_t *genius, uint8_t background) if (genius->genius_control & 0x20) { - col ^= 15; + col ^= 0xffffff; } for (c = 0; c < cw; c++) { if (col != background) - buffer->line[genius->displine][(x * cw) + c] = col; + ((uint32_t *)buffer32->line[genius->displine])[(x * cw) + c] = col; } } else /* Draw 8 pixels of character */ @@ -362,49 +361,50 @@ void genius_textline(genius_t *genius, uint8_t background) if (genius->genius_control & 0x20) { - col ^= 15; + col ^= 0xffffff; } if (col != background) { - buffer->line[genius->displine][(x * cw) + c] = col; + ((uint32_t *)buffer32->line[genius->displine])[(x * cw) + c] = col; } } /* The ninth pixel column... */ if ((chr & ~0x1f) == 0xc0) { /* Echo column 8 for the graphics chars */ - col = buffer->line[genius->displine][(x * cw) + 7]; - if (col != background) buffer->line[genius->displine][(x * cw) + 8] = col; + col = ((uint32_t *)buffer32->line[genius->displine])[(x * cw) + 7]; + if (col != background) + ((uint32_t *)buffer32->line[genius->displine])[(x * cw) + 8] = col; } else /* Otherwise fill with background */ { col = mdacols[attr][blink][0]; if (genius->genius_control & 0x20) { - col ^= 15; + col ^= 0xffffff; } - if (col != background) buffer->line[genius->displine][(x * cw) + 8] = col; + if (col != background) + ((uint32_t *)buffer32->line[genius->displine])[(x * cw) + 8] = col; } if (drawcursor) { for (c = 0; c < cw; c++) - buffer->line[genius->displine][(x * cw) + c] ^= mdacols[attr][0][1]; + ((uint32_t *)buffer32->line[genius->displine])[(x * cw) + c] ^= mdacols[attr][0][1]; } ++ma; } } } - /* Draw a line in the CGA 640x200 mode */ void genius_cgaline(genius_t *genius) { int x, c; uint32_t dat; - uint8_t ink; + uint32_t ink; uint32_t addr; - ink = (genius->genius_control & 0x20) ? 16 : 16+15; + ink = (genius->genius_control & 0x20) ? genius_pal[0] : genius_pal[3]; /* We draw the CGA at row 600 */ if (genius->displine < 600) { @@ -425,23 +425,22 @@ void genius_cgaline(genius_t *genius) { if (dat & 0x80) { - buffer->line[genius->displine][x*8 + c] = ink; + ((uint32_t *)buffer32->line[genius->displine])[x*8 + c] = ink; } dat = dat << 1; } } } - /* Draw a line in the native high-resolution mode */ void genius_hiresline(genius_t *genius) { int x, c; uint32_t dat; - uint8_t ink; + uint32_t ink; uint32_t addr; - ink = (genius->genius_control & 0x20) ? 16 : 16+15; + ink = (genius->genius_control & 0x20) ? genius_pal[0] : genius_pal[3]; /* The first 512 lines live at A0000 */ if (genius->displine < 512) { @@ -461,14 +460,13 @@ void genius_hiresline(genius_t *genius) { if (dat & 0x80) { - buffer->line[genius->displine][x*8 + c] = ink; + ((uint32_t *)buffer32->line[genius->displine])[x*8 + c] = ink; } dat = dat << 1; } } } - void genius_poll(void *p) { genius_t *genius = (genius_t *)p; @@ -485,11 +483,11 @@ void genius_poll(void *p) { if (genius->genius_control & 0x20) { - background = 16 + 15; + background = genius_pal[3]; } else { - background = 16; + background = genius_pal[0]; } if (genius->displine == 0) { @@ -498,7 +496,7 @@ void genius_poll(void *p) /* Start off with a blank line */ for (x = 0; x < GENIUS_XSIZE; x++) { - buffer->line[genius->displine][x] = background; + ((uint32_t *)buffer32->line[genius->displine])[x] = background; } /* If graphics display enabled, draw graphics on top * of the blanked line */ @@ -547,7 +545,7 @@ void genius_poll(void *p) if (genius->displine == 1008) { /* Hardcode GENIUS_XSIZE * GENIUS_YSIZE window size */ - if ((GENIUS_XSIZE != xsize) || (GENIUS_YSIZE != ysize) || video_force_resize_get()) + if (GENIUS_XSIZE != xsize || GENIUS_YSIZE != ysize) { xsize = GENIUS_XSIZE; ysize = GENIUS_YSIZE; @@ -558,7 +556,7 @@ void genius_poll(void *p) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen_8(0, 0, 0, ysize, xsize, ysize); + video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize); frames++; /* Fixed 728x1008 resolution */ @@ -579,6 +577,8 @@ void *genius_init(const device_t *info) /* 160k video RAM */ genius->vram = malloc(0x28000); + loadfont(BIOS_ROM_PATH, 4); + timer_add(genius_poll, &genius->vidtime, TIMER_ALWAYS_ENABLED, genius); /* Occupy memory between 0xB0000 and 0xBFFFF (moves to 0xA0000 in @@ -588,27 +588,32 @@ void *genius_init(const device_t *info) io_sethandler(0x03b0, 0x000C, genius_in, NULL, NULL, genius_out, NULL, NULL, genius); io_sethandler(0x03d0, 0x0010, genius_in, NULL, NULL, genius_out, NULL, NULL, genius); + genius_pal[0] = makecol(0x00, 0x00, 0x00); + genius_pal[1] = makecol(0x55, 0x55, 0x55); + genius_pal[2] = makecol(0xaa, 0xaa, 0xaa); + genius_pal[3] = makecol(0xff, 0xff, 0xff); + /* MDA attributes */ /* I don't know if the Genius's MDA emulation actually does * emulate bright / non-bright. For the time being pretend it does. */ for (c = 0; c < 256; c++) { - mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16; - if (c & 8) mdacols[c][0][1] = 15 + 16; - else mdacols[c][0][1] = 7 + 16; + mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = genius_pal[0]; + if (c & 8) mdacols[c][0][1] = genius_pal[3]; + else mdacols[c][0][1] = genius_pal[2]; } - mdacols[0x70][0][1] = 16; - mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15; - mdacols[0xF0][0][1] = 16; - mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15; - mdacols[0x78][0][1] = 16 + 7; - mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15; - mdacols[0xF8][0][1] = 16 + 7; - mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15; - mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16; - mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16; - mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16; - mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16; + mdacols[0x70][0][1] = genius_pal[0]; + mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = genius_pal[3]; + mdacols[0xF0][0][1] = genius_pal[0]; + mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = genius_pal[3]; + mdacols[0x78][0][1] = genius_pal[2]; + mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = genius_pal[3]; + mdacols[0xF8][0][1] = genius_pal[2]; + mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = genius_pal[3]; + mdacols[0x00][0][1] = mdacols[0x00][1][1] = genius_pal[0]; + mdacols[0x08][0][1] = mdacols[0x08][1][1] = genius_pal[0]; + mdacols[0x80][0][1] = mdacols[0x80][1][1] = genius_pal[0]; + mdacols[0x88][0][1] = mdacols[0x88][1][1] = genius_pal[0]; /* Start off in 80x25 text mode */ genius->cga_stat = 0xF4; @@ -626,7 +631,7 @@ void genius_close(void *p) free(genius); } -static int genius_available(void) +static int genius_available() { return rom_present(BIOS_ROM_PATH); } @@ -646,6 +651,5 @@ const device_t genius_device = genius_available, genius_speed_changed, NULL, - NULL, NULL }; diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index d4ab49af4..0724fb433 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -8,7 +8,7 @@ * * Hercules emulation. * - * Version: @(#)vid_hercules.c 1.0.9 2018/03/18 + * Version: @(#)vid_hercules.c 1.0.11 2018/04/29 * * Authors: Sarah Walker, * Miran Grca, @@ -68,7 +68,6 @@ uint8_t hercules_read(uint32_t addr, void *p); void hercules_out(uint16_t addr, uint8_t val, void *p) { hercules_t *hercules = (hercules_t *)p; -// pclog("Herc out %04X %02X\n",addr,val); switch (addr) { case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: @@ -99,7 +98,6 @@ void hercules_out(uint16_t addr, uint8_t val, void *p) uint8_t hercules_in(uint16_t addr, void *p) { hercules_t *hercules = (hercules_t *)p; - // pclog("Herc in %04X %02X %04X:%04X %04X\n",addr,(hercules_stat & 0xF) | ((hercules_stat & 8) << 4),CS,pc,CX); switch (addr) { case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: @@ -116,7 +114,6 @@ void hercules_write(uint32_t addr, uint8_t val, void *p) { hercules_t *hercules = (hercules_t *)p; egawrites++; -// pclog("Herc write %08X %02X\n",addr,val); hercules->vram[addr & 0xffff] = val; } @@ -153,7 +150,6 @@ void hercules_poll(void *p) int blink; if (!hercules->linepos) { - //pclog("Poll %i %i\n",vc,sc); hercules->vidtime += hercules->dispofftime; hercules->stat |= 1; hercules->linepos = 1; @@ -427,6 +423,5 @@ const device_t hercules_device = NULL, hercules_speed_changed, NULL, - NULL, hercules_config }; diff --git a/src/video/vid_herculesplus.c b/src/video/vid_herculesplus.c index 6a657bff7..1bf4118fc 100644 --- a/src/video/vid_herculesplus.c +++ b/src/video/vid_herculesplus.c @@ -8,7 +8,7 @@ * * Hercules InColor emulation. * - * Version: @(#)vid_herculesplus.c 1.0.7 2018/03/18 + * Version: @(#)vid_herculesplus.c 1.0.9 2018/04/29 * * Authors: Sarah Walker, * Miran Grca, @@ -97,7 +97,6 @@ static int mdacols[256][2][2]; void herculesplus_out(uint16_t addr, uint8_t val, void *p) { herculesplus_t *herculesplus = (herculesplus_t *)p; -/* pclog("InColor out %04X %02X\n",addr,val); */ switch (addr) { case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: @@ -129,7 +128,6 @@ void herculesplus_out(uint16_t addr, uint8_t val, void *p) uint8_t herculesplus_in(uint16_t addr, void *p) { herculesplus_t *herculesplus = (herculesplus_t *)p; -/* pclog("InColor in %04X %02X %04X:%04X %04X\n",addr,(herculesplus->stat & 0xF) | ((herculesplus->stat & 8) << 4),CS,pc,CX); */ switch (addr) { case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: @@ -737,6 +735,5 @@ const device_t herculesplus_device = NULL, herculesplus_speed_changed, NULL, - NULL, NULL }; diff --git a/src/video/vid_incolor.c b/src/video/vid_incolor.c index 1a456f3b5..f1cf1c1a1 100644 --- a/src/video/vid_incolor.c +++ b/src/video/vid_incolor.c @@ -8,7 +8,7 @@ * * Hercules InColor emulation. * - * Version: @(#)vid_incolor.c 1.0.8 2018/03/18 + * Version: @(#)vid_incolor.c 1.0.10 2018/04/29 * * Authors: Sarah Walker, * Miran Grca, @@ -197,7 +197,6 @@ uint8_t incolor_read(uint32_t addr, void *p); void incolor_out(uint16_t addr, uint8_t val, void *p) { incolor_t *incolor = (incolor_t *)p; -/* pclog("InColor out %04X %02X\n",addr,val); */ switch (addr) { case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: @@ -235,7 +234,6 @@ void incolor_out(uint16_t addr, uint8_t val, void *p) uint8_t incolor_in(uint16_t addr, void *p) { incolor_t *incolor = (incolor_t *)p; -/* pclog("InColor in %04X %02X %04X:%04X %04X\n",addr,(incolor->stat & 0xF) | ((incolor->stat & 8) << 4),CS,pc,CX); */ switch (addr) { case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: @@ -1081,6 +1079,5 @@ const device_t incolor_device = NULL, incolor_speed_changed, NULL, - NULL, NULL }; diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 9f792207a..51921bd78 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -8,7 +8,7 @@ * * MDA emulation. * - * Version: @(#)vid_mda.c 1.0.10 2018/03/18 + * Version: @(#)vid_mda.c 1.0.11 2018/04/26 * * Authors: Sarah Walker, * Miran Grca, @@ -376,6 +376,5 @@ const device_t mda_device = NULL, mda_speed_changed, NULL, - NULL, mda_config }; diff --git a/src/video/vid_nv_riva128.c b/src/video/vid_nv_riva128.c index 9abc94cc0..a74569153 100644 --- a/src/video/vid_nv_riva128.c +++ b/src/video/vid_nv_riva128.c @@ -8,7 +8,7 @@ * * nVidia RIVA 128 emulation. * - * Version: @(#)vid_nv_riva128.c 1.0.5 2018/03/18 + * Version: @(#)vid_nv_riva128.c 1.0.7 2018/04/29 * * Author: Melissa Goad * Miran Grca, @@ -16,11 +16,13 @@ * Copyright 2015-2018 Melissa Goad. * Copyright 2015-2018 Miran Grca. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../cpu/cpu.h" #include "../machine/machine.h" @@ -103,6 +105,8 @@ typedef struct riva128_t uint16_t chan_dma; uint16_t chan_size; //0 = 1024, 1 = 512 + uint32_t runout_put, runout_get; + struct { uint32_t dmaput; @@ -113,6 +117,9 @@ typedef struct riva128_t { int chanid; int push_enabled; + int runout; + uint32_t get, put; + uint32_t ctx; } caches[2]; struct @@ -297,6 +304,26 @@ const char* riva128_pfifo_interrupts[32] = void riva128_mmio_write_l(uint32_t addr, uint32_t val, void *p); +#ifdef ENABLE_NV_RIVA_LOG +int nv_riva_do_log = ENABLE_NV_RIVA_LOG; +#endif + + +static void +nv_riva_log(const char *fmt, ...) +{ +#ifdef ENABLE_NV_RIVA_LOG + va_list ap; + + if (nv_riva_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + /* riva128_color_t riva128_pgraph_expand_color(uint32_t ctx, uint32_t color) { riva128_color_t ret; @@ -306,7 +333,7 @@ const char* riva128_pfifo_interrupts[32] = switch(format) { default: - pclog("RIVA 128 Unknown color format %i found!\n", format); + nv_riva_log("RIVA 128 Unknown color format %i found!\n", format); ret.a = 0x0; break; case 0: @@ -371,7 +398,7 @@ const char* riva128_pfifo_interrupts[32] = riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; - //pclog("RIVA 128 PMC read %08X %04X:%08X\n", addr, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 PMC read %08X %04X:%08X\n", addr, CS, cpu_state.pc); if(riva128->card_id == 0x03) switch(addr) { @@ -476,7 +503,7 @@ const char* riva128_pfifo_interrupts[32] = void riva128_pmc_write(uint32_t addr, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; - //pclog("RIVA 128 PMC write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 PMC write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); switch(addr) { @@ -498,7 +525,7 @@ const char* riva128_pfifo_interrupts[32] = void riva128_pmc_interrupt(int num, void *p) { - //pclog("RIVA 128 PMC interrupt #%d fired!\n", num); + //nv_riva_log("RIVA 128 PMC interrupt #%d fired!\n", num); riva128_t *riva128 = (riva128_t *)p; riva128->pmc.intr |= (1 << num); @@ -514,7 +541,7 @@ const char* riva128_pfifo_interrupts[32] = riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; - //pclog("RIVA 128 PBUS read %08X %04X:%08X\n", addr, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 PBUS read %08X %04X:%08X\n", addr, CS, cpu_state.pc); switch(addr) { @@ -552,7 +579,7 @@ const char* riva128_pfifo_interrupts[32] = void riva128_pbus_write(uint32_t addr, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; - //pclog("RIVA 128 PBUS write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 PBUS write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); switch(addr) { @@ -584,12 +611,65 @@ void riva128_pfifo_interrupt(int num, void *p) riva128_pmc_interrupt(8, riva128); } +uint32_t riva128_pfifo_runout_next(void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + uint32_t next = (riva128->pfifo.runout_put + 8) & ((riva128->pfifo.ramro_size) - 1); + return next; +} + +uint32_t riva128_pfifo_cache1_next(uint32_t ptr) +{ + //Apparently, PFIFO's CACHE1 uses some sort of Gray code... oh well + int bits = 5; + uint32_t tmp = ptr >> 2; + if(tmp == (1 << (bits - 1))) return 0; + for(int bit = bits - 1;bit > 0;bit--) + { + if(tmp == (1 << (bit - 1))) return ptr ^ (1 << (2 + bit)); + if(tmp & (1 << bit)) tmp ^= 3 << (bit - 1); + } + return ptr ^ 4; +} + +uint32_t riva128_pfifo_cache1_lin(uint32_t ptr) +{ + int bits = 5; + uint32_t res = 0; + uint32_t tmp = ptr >> 2; + for(int bit = bits = 1; bit > 0; bit--) + { + if(tmp & (1 << bit)) + { + tmp ^= 3 << (bit - 1); + res ^= 4 << bit; + } + } + if(tmp & 1) res ^= 4; + return res; +} + +uint32_t riva128_pfifo_cache1_free(uint32_t chid, void* p) +{ + riva128_t *riva128 = (riva128_t *)p; + uint32_t get = riva128_pfifo_cache1_lin(riva128->pfifo.caches[1].get); + uint32_t put = riva128_pfifo_cache1_lin(riva128->pfifo.caches[1].put); + + if(riva128->pfifo.caches[1].runout) return 0; + if(chid != riva128->pfifo.caches[1].chanid || !riva128->pfifo.caches[1].push_enabled) + { + if(riva128->pfifo.caches[1].get != riva128->pfifo.caches[1].put) return 0; + return 0x7c; + } + return (get - put - 4) & 0x7c; +} + uint8_t riva128_pfifo_read(uint32_t addr, void *p) { riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; - // pclog("RIVA 128 PFIFO read %08X %04X:%08X\n", addr, CS, cpu_state.pc); + // nv_riva_log("RIVA 128 PFIFO read %08X %04X:%08X\n", addr, CS, cpu_state.pc); switch(addr) { @@ -728,7 +808,7 @@ void riva128_pfifo_interrupt(int num, void *p) void riva128_pfifo_write(uint32_t addr, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; - // pclog("RIVA 128 PFIFO write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); + // nv_riva_log("RIVA 128 PFIFO write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); switch(addr) { @@ -794,7 +874,7 @@ void riva128_pfifo_interrupt(int num, void *p) riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; - //pclog("RIVA 128 PTIMER read %08X %04X:%08X\n", addr, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 PTIMER read %08X %04X:%08X\n", addr, CS, cpu_state.pc); switch(addr) { @@ -893,7 +973,7 @@ void riva128_pfifo_interrupt(int num, void *p) void riva128_ptimer_write(uint32_t addr, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; - pclog("RIVA 128 PTIMER write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); + nv_riva_log("RIVA 128 PTIMER write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); switch(addr) { @@ -927,7 +1007,7 @@ void riva128_pfifo_interrupt(int num, void *p) void riva128_ptimer_interrupt(int num, void *p) { - //pclog("RIVA 128 PTIMER interrupt #%d fired!\n", num); + //nv_riva_log("RIVA 128 PTIMER interrupt #%d fired!\n", num); riva128_t *riva128 = (riva128_t *)p; riva128->ptimer.intr |= (1 << num); @@ -940,7 +1020,7 @@ void riva128_pfifo_interrupt(int num, void *p) riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; - //pclog("RIVA 128 PFB read %08X %04X:%08X\n", addr, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 PFB read %08X %04X:%08X\n", addr, CS, cpu_state.pc); switch(addr) { @@ -1007,7 +1087,7 @@ void riva128_pfifo_interrupt(int num, void *p) void riva128_pfb_write(uint32_t addr, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; - //pclog("RIVA 128 PFB write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 PFB write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); switch(addr) { @@ -1035,7 +1115,7 @@ uint8_t riva128_pextdev_read(uint32_t addr, void *p) riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; - //pclog("RIVA 128 PEXTDEV read %08X %04X:%08X\n", addr, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 PEXTDEV read %08X %04X:%08X\n", addr, CS, cpu_state.pc); //For NV3, we give it PCI 66MHz, card mode, PCI bus type, 13.5MHz crystal, no TV encoder, and PCI 2.1. //For NV4, we give it normal PCI line polarity, card mode, 13.5 MHz crystal, no TV encoder, and PCI bus type @@ -1074,7 +1154,7 @@ uint8_t riva128_pextdev_read(uint32_t addr, void *p) void riva128_pextdev_write(uint32_t addr, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; - //pclog("RIVA 128 PEXTDEV write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 PEXTDEV write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); switch(addr) { @@ -1140,7 +1220,7 @@ void rivatnt_pgraph_ctx_switch(void *p) riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; - pclog("RIVA 128 PGRAPH read %08X %04X:%08X\n", addr, CS, cpu_state.pc); + nv_riva_log("RIVA 128 PGRAPH read %08X %04X:%08X\n", addr, CS, cpu_state.pc); switch(addr) { @@ -1537,7 +1617,7 @@ void rivatnt_pgraph_ctx_switch(void *p) void riva128_pgraph_write(uint32_t addr, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; - pclog("RIVA 128 PGRAPH write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); + nv_riva_log("RIVA 128 PGRAPH write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); switch(addr) { @@ -1736,7 +1816,7 @@ void riva128_pgraph_vblank_interrupt(void *p) riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; - //pclog("RIVA 128 PRAMDAC read %08X %04X:%08X\n", addr, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 PRAMDAC read %08X %04X:%08X\n", addr, CS, cpu_state.pc); switch(addr) { @@ -1809,7 +1889,7 @@ void riva128_pgraph_vblank_interrupt(void *p) { riva128_t *riva128 = (riva128_t *)p; svga_t* svga = &riva128->svga; - //pclog("RIVA 128 PRAMDAC write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 PRAMDAC write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); switch(addr) { @@ -1876,7 +1956,7 @@ void riva128_pgraph_vblank_interrupt(void *p) ret = riva128->pramin[ramht_base + (hash * 8)]; - pclog("RIVA 128 RAMHT lookup with handle %08X returned %08X %04X:%08X\n", handle, ret, CS, cpu_state.pc); + nv_riva_log("RIVA 128 RAMHT lookup with handle %08X returned %08X %04X:%08X\n", handle, ret, CS, cpu_state.pc); return ret; } @@ -1884,7 +1964,7 @@ void riva128_pgraph_vblank_interrupt(void *p) void riva128_puller_exec_method(int chanid, int subchanid, int offset, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; - pclog("RIVA 128 Puller executing method %04X on channel %01X[%01X] param %08X %04X:%08X\n", offset, chanid, subchanid, val, CS, cpu_state.pc); + nv_riva_log("RIVA 128 Puller executing method %04X on channel %01X[%01X] param %08X %04X:%08X\n", offset, chanid, subchanid, val, CS, cpu_state.pc); if(riva128->card_id == 0x03) { @@ -1962,7 +2042,7 @@ void riva128_pgraph_vblank_interrupt(void *p) } else { - pclog("RIVA 128 PFIFO Invalid DMA pusher command %08x!\n", cmd); + nv_riva_log("RIVA 128 PFIFO Invalid DMA pusher command %08x!\n", cmd); riva128_pfifo_interrupt(12, riva128); } riva128->pfifo.channels[chanid].dmaget += 4; @@ -1977,7 +2057,7 @@ uint8_t riva128_user_read(uint32_t addr, void *p) int offset = addr & 0x1fff; uint8_t ret = 0; - pclog("RIVA 128 USER read %08X %04X:%08X\n", addr, CS, cpu_state.pc); + nv_riva_log("RIVA 128 USER read %08X %04X:%08X\n", addr, CS, cpu_state.pc); addr -= 0x800000; @@ -1990,9 +2070,8 @@ uint8_t riva128_user_read(uint32_t addr, void *p) //PIO mode switch(offset) { - //HACK - case 0x10: ret = 0xff; break; - case 0x11: ret = 0x7f; break; + case 0x10: ret = riva128_pfifo_cache1_free(chanid, riva128) & 0xfc; break; + case 0x11: ret = riva128_pfifo_cache1_free(chanid, riva128) >> 8; break; } } @@ -2006,7 +2085,7 @@ uint8_t riva128_user_read(uint32_t addr, void *p) int subchanid = (addr >> 13) & 0x7; int offset = addr & 0x1fff; - pclog("RIVA 128 USER write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); + nv_riva_log("RIVA 128 USER write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); addr -= 0x800000; @@ -2056,7 +2135,7 @@ uint8_t riva128_user_read(uint32_t addr, void *p) //This logging condition is necessary to prevent A CATASTROPHIC LOG BLOWUP when polling PTIMER or PFIFO. DO NOT REMOVE. if(/*!((addr >= 0x009000) && (addr <= 0x009fff)) && !((addr >= 0x002000) && (addr <= 0x003fff)) && !((addr >= 0x000000) && (addr <= 0x000003)) && !((addr <= 0x680fff) && (addr >= 0x680000)) && !((addr >= 0x0c0000) && (addr <= 0x0cffff)) - && !((addr >= 0x110000) && (addr <= 0x11ffff)) && !(addr <= 0x000fff) && (addr >= 0x000000)*/1) pclog("RIVA 128 MMIO read %08X %04X:%08X\n", addr, CS, cpu_state.pc); + && !((addr >= 0x110000) && (addr <= 0x11ffff)) && !(addr <= 0x000fff) && (addr >= 0x000000)*/1) nv_riva_log("RIVA 128 MMIO read %08X %04X:%08X\n", addr, CS, cpu_state.pc); if((addr >= 0x000000) && (addr <= 0x000fff)) ret = riva128_pmc_read(addr, riva128); if((addr >= 0x001000) && (addr <= 0x001fff)) ret = riva128_pbus_read(addr, riva128); @@ -2086,21 +2165,21 @@ uint8_t riva128_user_read(uint32_t addr, void *p) uint16_t riva128_mmio_read_w(uint32_t addr, void *p) { addr &= 0xffffff; - //pclog("RIVA 128 MMIO read %08X %04X:%08X\n", addr, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 MMIO read %08X %04X:%08X\n", addr, CS, cpu_state.pc); return (riva128_mmio_read(addr+0,p) << 0) | (riva128_mmio_read(addr+1,p) << 8); } uint32_t riva128_mmio_read_l(uint32_t addr, void *p) { addr &= 0xffffff; - //pclog("RIVA 128 MMIO read %08X %04X:%08X\n", addr, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 MMIO read %08X %04X:%08X\n", addr, CS, cpu_state.pc); return (riva128_mmio_read(addr+0,p) << 0) | (riva128_mmio_read(addr+1,p) << 8) | (riva128_mmio_read(addr+2,p) << 16) | (riva128_mmio_read(addr+3,p) << 24); } void riva128_mmio_write(uint32_t addr, uint8_t val, void *p) { addr &= 0xffffff; - //pclog("RIVA 128 MMIO write %08X %02X %04X:%08X\n", addr, val, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 MMIO write %08X %02X %04X:%08X\n", addr, val, CS, cpu_state.pc); if(addr != 0x6013d4 && addr != 0x6013d5 && addr != 0x6013b4 && addr != 0x6013b5 && addr != 0x6013da && !((addr >= 0x6813c6) && (addr <= 0x6813cc))) { uint32_t tmp = riva128_mmio_read_l(addr,p); @@ -2118,7 +2197,7 @@ uint8_t riva128_user_read(uint32_t addr, void *p) { uint32_t tmp; addr &= 0xffffff; - //pclog("RIVA 128 MMIO write %08X %04X %04X:%08X\n", addr, val, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 MMIO write %08X %04X %04X:%08X\n", addr, val, CS, cpu_state.pc); tmp = riva128_mmio_read_l(addr,p); tmp &= ~(0xffff << ((addr & 2) << 4)); tmp |= val << ((addr & 2) << 4); @@ -2132,7 +2211,7 @@ uint8_t riva128_user_read(uint32_t addr, void *p) addr &= 0xffffff; //DO NOT REMOVE. This fixes a monstrous log blowup in win9x's drivers when accessing PFIFO. - if(/*!((addr >= 0x002000) && (addr <= 0x003fff)) && !((addr >= 0xc0000) && (addr <= 0xcffff)) && (addr != 0x000140)*/1) pclog("RIVA 128 MMIO write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); + if(/*!((addr >= 0x002000) && (addr <= 0x003fff)) && !((addr >= 0xc0000) && (addr <= 0xcffff)) && (addr != 0x000140)*/1) nv_riva_log("RIVA 128 MMIO write %08X %08X %04X:%08X\n", addr, val, CS, cpu_state.pc); if((addr >= 0x000000) && (addr <= 0x000fff)) riva128_pmc_write(addr, val, riva128); @@ -2163,13 +2242,13 @@ uint8_t riva128_user_read(uint32_t addr, void *p) void riva128_ptimer_tick(void *p) { riva128_t *riva128 = (riva128_t *)p; - //pclog("RIVA 128 PTIMER tick!\n"); + //nv_riva_log("RIVA 128 PTIMER tick!\n"); double time = ((double)riva128->ptimer.clock_mul * 10000000.0f) / (double)riva128->ptimer.clock_div; uint32_t tmp; int alarm_check; - //if(cs == 0x0008 && !riva128->pgraph.beta) pclog("RIVA 128 PTIMER time elapsed %f alarm %08x, time_low %08x\n", time, riva128->ptimer.alarm, riva128->ptimer.time & 0xffffffff); + //if(cs == 0x0008 && !riva128->pgraph.beta) nv_riva_log("RIVA 128 PTIMER time elapsed %f alarm %08x, time_low %08x\n", time, riva128->ptimer.alarm, riva128->ptimer.time & 0xffffffff); tmp = riva128->ptimer.time; riva128->ptimer.time += (uint64_t)time; @@ -2178,7 +2257,7 @@ void riva128_ptimer_tick(void *p) if(alarm_check && (riva128->ptimer.intr_en & 1)) { - //pclog("RIVA 128 PTIMER ALARM interrupt fired!\n"); + //nv_riva_log("RIVA 128 PTIMER ALARM interrupt fired!\n"); riva128_ptimer_interrupt(0, riva128); } } @@ -2187,7 +2266,7 @@ void riva128_ptimer_tick(void *p) { riva128_t *riva128 = (riva128_t *)p; - //if(!riva128->pgraph.beta) pclog("RIVA 128 MCLK poll PMC enable %08x\n", riva128->pmc.enable); + //if(!riva128->pgraph.beta) nv_riva_log("RIVA 128 MCLK poll PMC enable %08x\n", riva128->pmc.enable); if((riva128->pmc.enable & 0x00010000) && (riva128->card_id == 0x03)) riva128_ptimer_tick(riva128); @@ -2218,7 +2297,7 @@ void riva128_ptimer_tick(void *p) addr &= 0xff; - //pclog("RIVA 128 RMA read %04X %04X:%08X\n", addr, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 RMA read %04X %04X:%08X\n", addr, CS, cpu_state.pc); switch(addr) { @@ -2253,7 +2332,7 @@ void riva128_ptimer_tick(void *p) addr &= 0xff; - //pclog("RIVA 128 RMA write %04X %02X %04X:%08X\n", addr, val, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 RMA write %04X %02X %04X:%08X\n", addr, val, CS, cpu_state.pc); switch(addr) { @@ -2316,7 +2395,7 @@ void riva128_ptimer_tick(void *p) if((addr >= 0x3d0) && (addr <= 0x3d3)) { - //pclog("RIVA 128 RMA BAR Register read %04X %04X:%08X\n", addr, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 RMA BAR Register read %04X %04X:%08X\n", addr, CS, cpu_state.pc); if(!(riva128->rma.mode & 1)) return ret; ret = riva128_rma_in(riva128->rma_addr + ((riva128->rma.mode & 0xe) << 1) + (addr & 3), riva128); return ret; @@ -2325,7 +2404,7 @@ void riva128_ptimer_tick(void *p) if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; - // if (addr != 0x3da) pclog("S3 in %04X %04X:%08X ", addr, CS, cpu_state.pc); + // if (addr != 0x3da) nv_riva_log("S3 in %04X %04X:%08X ", addr, CS, cpu_state.pc); switch (addr) { case 0x3D4: @@ -2374,13 +2453,13 @@ void riva128_ptimer_tick(void *p) break; } if(svga->crtcreg > 0x18) - pclog("RIVA 128 Extended CRTC read %02X %04X:%08X\n", svga->crtcreg, CS, cpu_state.pc); + nv_riva_log("RIVA 128 Extended CRTC read %02X %04X:%08X\n", svga->crtcreg, CS, cpu_state.pc); break; default: ret = svga_in(addr, svga); break; } - // if (addr != 0x3da) pclog("%02X\n", ret); + // if (addr != 0x3da) nv_riva_log("%02X\n", ret); return ret; } @@ -2393,7 +2472,7 @@ void riva128_ptimer_tick(void *p) if((addr >= 0x3d0) && (addr <= 0x3d3)) { - //pclog("RIVA 128 RMA BAR Register write %04X %02x %04X:%08X\n", addr, val, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 RMA BAR Register write %04X %02x %04X:%08X\n", addr, val, CS, cpu_state.pc); riva128->rma.access_reg[addr & 3] = val; if(!(riva128->rma.mode & 1)) return; riva128_rma_out(riva128->rma_addr + ((riva128->rma.mode & 0xe) << 1) + (addr & 3), riva128->rma.access_reg[addr & 3], riva128); @@ -2487,7 +2566,7 @@ void riva128_ptimer_tick(void *p) break; } //if(svga->crtcreg > 0x18) - // pclog("RIVA 128 Extended CRTC write %02X %02x %04X:%08X\n", svga->crtcreg, val, CS, cpu_state.pc); + // nv_riva_log("RIVA 128 Extended CRTC write %02X %02x %04X:%08X\n", svga->crtcreg, val, CS, cpu_state.pc); if (old != val) { if (svga->crtcreg < 0xE || svga->crtcreg > 0x10) @@ -2551,7 +2630,7 @@ void riva128_ptimer_tick(void *p) { riva128_t *riva128 = (riva128_t *)p; uint8_t ret = 0; - //pclog("RIVA 128 PCI read %02X %04X:%08X\n", addr, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 PCI read %02X %04X:%08X\n", addr, CS, cpu_state.pc); switch (addr) { case 0x00: @@ -2641,7 +2720,7 @@ void riva128_ptimer_tick(void *p) break; } - // pclog("%02X\n", ret); + // nv_riva_log("%02X\n", ret); return ret; } @@ -2670,7 +2749,7 @@ void riva128_ptimer_tick(void *p) void riva128_pci_write(int func, int addr, uint8_t val, void *p) { - //pclog("RIVA 128 PCI write %02X %02X %04X:%08X\n", addr, val, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 PCI write %02X %02X %04X:%08X\n", addr, val, CS, cpu_state.pc); riva128_t *riva128 = (riva128_t *)p; svga_t* svga = &riva128->svga; switch (addr) @@ -2690,15 +2769,16 @@ void riva128_ptimer_tick(void *p) case PCI_REG_COMMAND: riva128->pci_regs[PCI_REG_COMMAND] = val & 0x27; - io_removehandler(0x03c0, 0x0020, riva128_in, NULL, NULL, riva128_out, NULL, NULL, riva128); mem_mapping_disable(&svga->mapping); mem_mapping_disable(&riva128->mmio_mapping); mem_mapping_disable(&riva128->linear_mapping); mem_mapping_disable(&riva128->ramin_mapping); if (val & PCI_COMMAND_IO) { + io_removehandler(0x03c0, 0x0020, riva128_in, NULL, NULL, riva128_out, NULL, NULL, riva128); io_sethandler(0x03c0, 0x0020, riva128_in, NULL, NULL, riva128_out, NULL, NULL, riva128); } + else io_removehandler(0x03c0, 0x0020, riva128_in, NULL, NULL, riva128_out, NULL, NULL, riva128); if (val & PCI_COMMAND_MEM) { uint32_t mmio_addr = riva128->pci_regs[0x13] << 24; @@ -2713,9 +2793,8 @@ void riva128_ptimer_tick(void *p) } if (linear_addr) { - mem_mapping_set_addr(&riva128->linear_mapping, linear_addr, 0xc00000); + mem_mapping_set_addr(&riva128->linear_mapping, linear_addr, 0x1000000); mem_mapping_set_addr(&riva128->ramin_mapping, linear_addr + 0xc00000, 0x200000); - svga->linear_base = linear_addr; } } return; @@ -2752,7 +2831,6 @@ void riva128_ptimer_tick(void *p) { mem_mapping_set_addr(&riva128->linear_mapping, linear_addr, 0xc00000); mem_mapping_set_addr(&riva128->ramin_mapping, linear_addr + 0xc00000, 0x200000); - svga->linear_base = linear_addr; } return; } @@ -2765,7 +2843,7 @@ void riva128_ptimer_tick(void *p) if (riva128->pci_regs[0x30] & 0x01) { uint32_t addr = (riva128->pci_regs[0x32] << 16) | (riva128->pci_regs[0x33] << 24); - // pclog("RIVA 128 bios_rom enabled at %08x\n", addr); + // nv_riva_log("RIVA 128 bios_rom enabled at %08x\n", addr); mem_mapping_set_addr(&riva128->bios_rom.mapping, addr, 0x8000); } return; @@ -2785,7 +2863,7 @@ void riva128_ptimer_tick(void *p) void rivatnt_pci_write(int func, int addr, uint8_t val, void *p) { - //pclog("RIVA 128 PCI write %02X %02X %04X:%08X\n", addr, val, CS, cpu_state.pc); + //nv_riva_log("RIVA 128 PCI write %02X %02X %04X:%08X\n", addr, val, CS, cpu_state.pc); riva128_t *riva128 = (riva128_t *)p; svga_t *svga = &riva128->svga; switch (addr) @@ -2805,14 +2883,15 @@ void riva128_ptimer_tick(void *p) case PCI_REG_COMMAND: riva128->pci_regs[PCI_REG_COMMAND] = val & 0x27; - io_removehandler(0x03c0, 0x0020, riva128_in, NULL, NULL, riva128_out, NULL, NULL, riva128); mem_mapping_disable(&svga->mapping); mem_mapping_disable(&riva128->mmio_mapping); mem_mapping_disable(&riva128->linear_mapping); if (val & PCI_COMMAND_IO) { + io_removehandler(0x03c0, 0x0020, riva128_in, NULL, NULL, riva128_out, NULL, NULL, riva128); io_sethandler(0x03c0, 0x0020, riva128_in, NULL, NULL, riva128_out, NULL, NULL, riva128); } + else io_removehandler(0x03c0, 0x0020, riva128_in, NULL, NULL, riva128_out, NULL, NULL, riva128); if (val & PCI_COMMAND_MEM) { uint32_t mmio_addr = riva128->pci_regs[0x13] << 24; @@ -2828,7 +2907,6 @@ void riva128_ptimer_tick(void *p) if (linear_addr) { mem_mapping_set_addr(&riva128->linear_mapping, linear_addr, 0x1000000); - svga->linear_base = linear_addr; } } return; @@ -2863,7 +2941,6 @@ void riva128_ptimer_tick(void *p) if (linear_addr) { mem_mapping_set_addr(&riva128->linear_mapping, linear_addr, 0x1000000); - svga->linear_base = linear_addr; } return; } @@ -2876,7 +2953,7 @@ void riva128_ptimer_tick(void *p) if (riva128->pci_regs[0x30] & 0x01) { uint32_t addr = (riva128->pci_regs[0x32] << 16) | (riva128->pci_regs[0x33] << 24); - // pclog("RIVA TNT bios_rom enabled at %08x\n", addr); + // nv_riva_log("RIVA TNT bios_rom enabled at %08x\n", addr); mem_mapping_set_addr(&riva128->bios_rom.mapping, addr, 0x10000); } return; @@ -2945,7 +3022,7 @@ void riva128_ptimer_tick(void *p) else { freq = (freq * riva128->pramdac.v_n) / (1 << riva128->pramdac.v_p) / riva128->pramdac.v_m; - //pclog("RIVA 128 Pixel clock is %f Hz\n", freq); + //nv_riva_log("RIVA 128 Pixel clock is %f Hz\n", freq); } svga->clock = cpuclock / freq; @@ -2959,7 +3036,7 @@ void riva128_ptimer_tick(void *p) else { freq = (freq * riva128->pramdac.m_n) / (1 << riva128->pramdac.m_p) / riva128->pramdac.m_m; - //pclog("RIVA 128 Memory clock is %f Hz\n", freq); + //nv_riva_log("RIVA 128 Memory clock is %f Hz\n", freq); } riva128->mfreq = freq; @@ -2975,7 +3052,7 @@ void riva128_ptimer_tick(void *p) else { freq = (freq * riva128->pramdac.nv_n) / (1 << riva128->pramdac.nv_p) / riva128->pramdac.nv_m; - //pclog("RIVA 128 Core clock is %f Hz\n", freq); + //nv_riva_log("RIVA 128 Core clock is %f Hz\n", freq); } riva128->nvfreq = freq; @@ -3003,7 +3080,7 @@ void *riva128_init(const device_t *info) riva128_in, riva128_out, NULL, NULL); - riva128->svga.decode_mask = 0x1fffff; + riva128->svga.decode_mask = (riva128->memory_size << 20) - 1; rom_init(&riva128->bios_rom, L"roms/video/nv_riva128/Diamond_V330_rev-e.vbi", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); if (PCI) @@ -3153,13 +3230,6 @@ void riva128_force_redraw(void *p) riva128->svga.fullchange = changeframecount; } -void riva128_add_status_info(char *s, int max_len, void *p) -{ - riva128_t *riva128 = (riva128_t *)p; - - svga_add_status_info(s, max_len, &riva128->svga); -} - const device_config_t riva128_config[] = { { @@ -3232,7 +3302,6 @@ const device_t riva128_device = riva128_available, riva128_speed_changed, riva128_force_redraw, - riva128_add_status_info, riva128_config }; @@ -3255,7 +3324,7 @@ void *rivatnt_init(const device_t *info) riva128_in, riva128_out, NULL, NULL); - riva128->svga.decode_mask = 0x1fffff; + riva128->svga.decode_mask = (riva128->memory_size << 20) - 1; rom_init(&riva128->bios_rom, L"roms/video/nv_riva128/NV4_diamond_revB.rom", 0xc0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); if (PCI) @@ -3386,13 +3455,6 @@ void rivatnt_force_redraw(void *p) riva128->svga.fullchange = changeframecount; } -void rivatnt_add_status_info(char *s, int max_len, void *p) -{ - riva128_t *riva128 = (riva128_t *)p; - - svga_add_status_info(s, max_len, &riva128->svga); -} - const device_config_t rivatnt_config[] = { { @@ -3428,7 +3490,6 @@ const device_t rivatnt_device = rivatnt_available, rivatnt_speed_changed, rivatnt_force_redraw, - rivatnt_add_status_info, rivatnt_config }; @@ -3452,7 +3513,7 @@ void *rivatnt2_init(const device_t *info) riva128_in, riva128_out, NULL, NULL); - riva128->svga.decode_mask = 0x1fffff; + riva128->svga.decode_mask = 0x3fffff; switch(model) { @@ -3594,13 +3655,6 @@ void rivatnt2_force_redraw(void *p) riva128->svga.fullchange = changeframecount; } -void rivatnt2_add_status_info(char *s, int max_len, void *p) -{ - riva128_t *riva128 = (riva128_t *)p; - - svga_add_status_info(s, max_len, &riva128->svga); -} - const device_config_t rivatnt2_config[] = { { @@ -3653,6 +3707,5 @@ const device_t rivatnt2_device = rivatnt2_available, rivatnt2_speed_changed, rivatnt2_force_redraw, - rivatnt2_add_status_info, rivatnt2_config }; diff --git a/src/video/vid_nvidia.c b/src/video/vid_nvidia.c new file mode 100644 index 000000000..2c210e0ac --- /dev/null +++ b/src/video/vid_nvidia.c @@ -0,0 +1,965 @@ +/* + * 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. + * + * nVidia RIVA 128 emulation. + * + * Version: @(#)vid_nv_riva128.c 1.0.7 2018/04/29 + * + * Author: Melissa Goad + * Miran Grca, + * + * Copyright 2015-2018 Melissa Goad. + * Copyright 2015-2018 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include "../86box.h" +#include "../cpu/cpu.h" +#include "../machine/machine.h" +#include "../io.h" +#include "../mem.h" +#include "../pci.h" +#include "../pic.h" +#include "../rom.h" +#include "../timer.h" +#include "../device.h" +#include "../plat.h" +#include "video.h" +#include "vid_nv_riva128.h" +#include "vid_svga.h" +#include "vid_svga_render.h" + +typedef struct riva128_t +{ + mem_mapping_t linear_mapping; + mem_mapping_t mmio_mapping; + + rom_t bios_rom; + + svga_t svga; + + uint8_t card_id; + int pci_card; + int is_nv3t; + + uint16_t vendor_id; + uint16_t device_id; + + uint32_t linear_base, linear_size; + + uint16_t rma_addr; + + uint8_t pci_regs[256]; + + int memory_size; + + uint8_t ext_regs_locked; + + uint8_t read_bank; + uint8_t write_bank; + + struct + { + uint32_t intr; + uint32_t intr_en; + uint32_t intr_line; + uint32_t enable; + } pmc; + + struct + { + uint32_t intr; + uint32_t intr_en; + } pbus; + + struct + { + uint32_t cache_error; + uint32_t intr; + uint32_t intr_en; + + uint32_t ramht; + uint32_t ramht_addr; + uint32_t ramht_size; + + uint32_t ramfc; + uint32_t ramfc_addr; + + uint32_t ramro; + uint32_t ramro_addr; + uint32_t ramro_size; + + uint16_t chan_mode; + uint16_t chan_dma; + uint16_t chan_size; //0 = 1024, 1 = 512 + + uint32_t runout_put, runout_get; + + struct + { + uint32_t dmaput; + uint32_t dmaget; + } channels[16]; + + struct + { + int chanid; + int push_enabled; + int runout; + uint32_t get, put; + uint32_t ctx; + } caches[2]; + + struct + { + int subchan; + uint16_t method; + uint32_t param; + } cache0, cache1[64]; + } pfifo; + + struct + { + uint32_t addr; + uint32_t data; + uint8_t access_reg[4]; + uint8_t mode; + } rma; + + struct + { + uint32_t intr, intr_en; + + uint64_t time; + uint32_t alarm; + + uint16_t clock_mul, clock_div; + } ptimer; + + struct + { + int width; + int bpp; + uint32_t config_0; + } pfb; + + struct + { + uint32_t boot_0; + } pextdev; + + struct + { + int pgraph_speedhack; + + uint32_t obj_handle[8]; + uint16_t obj_class[8]; + + uint32_t debug[5]; + + uint32_t intr; + uint32_t intr_en; + + uint32_t invalid; + uint32_t invalid_en; + + uint32_t ctx_switch[5]; + uint32_t ctx_control; + uint32_t ctx_user; + uint32_t ctx_cache[8][5]; + + uint32_t fifo_enable; + + uint32_t fifo_st2_addr; + uint32_t fifo_st2_data; + + uint32_t uclip_xmin, uclip_ymin, uclip_xmax, uclip_ymax; + uint32_t oclip_xmin, oclip_ymin, oclip_xmax, oclip_ymax; + + uint32_t src_canvas_min, src_canvas_max; + uint32_t dst_canvas_min, dst_canvas_max; + + uint8_t rop; + + uint32_t chroma; + + uint32_t beta; + + uint32_t notify; + + //NV3 + uint32_t surf_offset[4]; + uint32_t surf_pitch[4]; + + uint32_t cliprect_min[2]; + uint32_t cliprect_max[2]; + uint32_t cliprect_ctrl; + + uint32_t instance; + + uint32_t dma_intr, dma_intr_en; + + uint32_t status; + } pgraph; + + struct + { + uint32_t nvpll; + uint32_t nv_m,nv_n,nv_p; + + uint32_t mpll; + uint32_t m_m,m_n,m_p; + + uint32_t vpll; + uint32_t v_m,v_n,v_p; + + uint32_t pll_ctrl; + + uint32_t gen_ctrl; + } pramdac; + + uint32_t channels[16][8][0x2000]; + + struct + { + int scl; + int sda; + } i2c; + + int64_t mtime, mfreq; +} riva128_t; + + +#ifdef ENABLE_NVIDIA_LOG +int nvidia_do_log = ENABLE_NVIDIA_LOG; +#endif + + +static void +nvidia_log(const char *fmt, ...) +{ +#ifdef ENABLE_NVIDIA_LOG + va_list ap; + + if (nvidia_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + +uint8_t riva128_rma_in(uint16_t addr, void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + svga_t* svga = &riva128->svga; + uint8_t ret = 0; + + addr &= 0xff; + + //nvidia_log("RIVA 128 RMA read %04X %04X:%08X\n", addr, CS, cpu_state.pc); + + switch(addr) + { + case 0x00: + ret = 0x65; + break; + case 0x01: + ret = 0xd0; + break; + case 0x02: + ret = 0x16; + break; + case 0x03: + ret = 0x2b; + break; + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + if(riva128->rma.addr < 0x1000000) /*ret = riva128_mmio_read((riva128->rma.addr + (addr & 3)) & 0xffffff, riva128);*/nvidia_log("RIVA 128 MMIO write %08x %08x\n", riva128->rma.addr & 0xffffff, riva128->rma.data); + else ret = svga_read_linear((riva128->rma.addr - 0x1000000), svga); + break; + } + + return ret; +} + +void riva128_rma_out(uint16_t addr, uint8_t val, void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + svga_t* svga = &riva128->svga; + + addr &= 0xff; + + //nvidia_log("RIVA 128 RMA write %04X %02X %04X:%08X\n", addr, val, CS, cpu_state.pc); + + switch(addr) + { + case 0x04: + riva128->rma.addr &= ~0xff; + riva128->rma.addr |= val; + break; + case 0x05: + riva128->rma.addr &= ~0xff00; + riva128->rma.addr |= (val << 8); + break; + case 0x06: + riva128->rma.addr &= ~0xff0000; + riva128->rma.addr |= (val << 16); + break; + case 0x07: + riva128->rma.addr &= ~0xff000000; + riva128->rma.addr |= (val << 24); + break; + case 0x08: + case 0x0c: + case 0x10: + case 0x14: + riva128->rma.data &= ~0xff; + riva128->rma.data |= val; + break; + case 0x09: + case 0x0d: + case 0x11: + case 0x15: + riva128->rma.data &= ~0xff00; + riva128->rma.data |= (val << 8); + break; + case 0x0a: + case 0x0e: + case 0x12: + case 0x16: + riva128->rma.data &= ~0xff0000; + riva128->rma.data |= (val << 16); + break; + case 0x0b: + case 0x0f: + case 0x13: + case 0x17: + riva128->rma.data &= ~0xff000000; + riva128->rma.data |= (val << 24); + if(riva128->rma.addr < 0x1000000) /*riva128_mmio_write_l(riva128->rma.addr & 0xffffff, riva128->rma.data, riva128);*/nvidia_log("RIVA 128 MMIO write %08x %08x\n", riva128->rma.addr & 0xffffff, riva128->rma.data); + else svga_writel_linear((riva128->rma.addr - 0x1000000), riva128->rma.data, svga); + break; + } + + if(addr & 0x10) riva128->rma.addr+=4; +} + +uint8_t riva128_in(uint16_t addr, void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + svga_t* svga = &riva128->svga; + uint8_t ret = 0; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + // if (addr != 0x3da) nvidia_log("S3 in %04X %04X:%08X ", addr, CS, cpu_state.pc); + switch (addr) + { + case 0x3D4: + ret = svga->crtcreg; + break; + case 0x3D5: + switch(svga->crtcreg) + { + case 0x28: + ret = svga->crtc[0x28] & 0x3f; + break; + case 0x34: + ret = svga->displine & 0xff; + break; + case 0x35: + ret = (svga->displine >> 8) & 7; + break; + case 0x3e: + //DDC status register + ret = (riva128->i2c.sda << 3) | (riva128->i2c.scl << 2); + break; + default: + ret = svga->crtc[svga->crtcreg]; + break; + } + //if(svga->crtcreg > 0x18) + // nvidia_log("RIVA 128 Extended CRTC read %02X %04X:%08X\n", svga->crtcreg, CS, cpu_state.pc); + break; + default: + ret = svga_in(addr, svga); + break; + } + // if (addr != 0x3da) nvidia_log("%02X\n", ret); + return ret; +} + +void riva128_out(uint16_t addr, uint8_t val, void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + svga_t *svga = &riva128->svga; + + uint8_t old; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch(addr) + { + case 0x3D4: + svga->crtcreg = val; + return; + case 0x3D5: + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + old = svga->crtc[svga->crtcreg]; + svga->crtc[svga->crtcreg] = val; + switch(svga->crtcreg) + { + case 0x1e: + riva128->read_bank = val; + if (svga->chain4) svga->read_bank = riva128->read_bank << 15; + else svga->read_bank = riva128->read_bank << 13; + break; + case 0x1d: + riva128->write_bank = val; + if (svga->chain4) svga->write_bank = riva128->write_bank << 15; + else svga->write_bank = riva128->write_bank << 13; + break; + case 0x19: + case 0x1a: + case 0x25: + case 0x28: + case 0x2d: + svga_recalctimings(svga); + break; + case 0x38: + riva128->rma.mode = val & 0xf; + break; + case 0x3f: + riva128->i2c.sda = (val >> 4) & 1; + riva128->i2c.scl = (val >> 5) & 1; + break; + } + //if(svga->crtcreg > 0x18) + // nvidia_log("RIVA 128 Extended CRTC write %02X %02x %04X:%08X\n", svga->crtcreg, val, CS, cpu_state.pc); + if (old != val) + { + if (svga->crtcreg < 0xE || svga->crtcreg > 0x10) + { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + return; + } + + svga_out(addr, val, svga); +} + +uint8_t riva128_pci_read(int func, int addr, void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + uint8_t ret = 0; + //nvidia_log("RIVA 128 PCI read %02X %04X:%08X\n", addr, CS, cpu_state.pc); + switch (addr) + { + case 0x00: + ret = riva128->vendor_id & 0xff; + break; + case 0x01: + ret = riva128->vendor_id >> 8; + break; + + case 0x02: + ret = riva128->device_id & 0xff; + break; + case 0x03: + ret = riva128->device_id >> 8; + break; + + case 0x04: + ret = riva128->pci_regs[0x04] & 0x37; + break; + case 0x05: + ret = riva128->pci_regs[0x05] & 0x01; + break; + + case 0x06: + ret = 0x20; + break; + case 0x07: + ret = riva128->pci_regs[0x07] & 0x73; + break; + + case 0x08: + ret = 0x00; + break; /*Revision ID*/ + case 0x09: + ret = 0; + break; /*Programming interface*/ + + case 0x0a: + ret = 0x00; + break; /*Supports VGA interface*/ + case 0x0b: + ret = 0x03; /*output = 3; */break; + + case 0x0e: + ret = 0x00; + break; /*Header type*/ + + case 0x13: + case 0x17: + ret = riva128->pci_regs[addr]; + break; + + case 0x2c: + case 0x2d: + case 0x2e: + case 0x2f: + ret = riva128->pci_regs[addr]; + //if(CS == 0x0028) output = 3; + break; + + case 0x30: + return riva128->pci_regs[0x30] & 0x01; /*BIOS ROM address*/ + case 0x31: + return 0x00; + case 0x32: + return riva128->pci_regs[0x32]; + case 0x33: + return riva128->pci_regs[0x33]; + + case 0x34: + ret = 0x00; + break; + + case 0x3c: + ret = riva128->pci_regs[0x3c]; + break; + + case 0x3d: + ret = 0x01; + break; /*INTA*/ + + case 0x3e: + ret = 0x03; + break; + case 0x3f: + ret = 0x01; + break; + + } + // nvidia_log("%02X\n", ret); + return ret; +} + +void riva128_reenable_svga_mappings(svga_t *svga) +{ + switch (svga->gdcreg[6] & 0xc) /*Banked framebuffer*/ + { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + svga->banked_mask = 0xffff; + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; + break; + } +} + +void riva128_pci_write(int func, int addr, uint8_t val, void *p) +{ + //nvidia_log("RIVA 128 PCI write %02X %02X %04X:%08X\n", addr, val, CS, cpu_state.pc); + riva128_t *riva128 = (riva128_t *)p; + svga_t* svga = &riva128->svga; + switch (addr) + { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x3d: + case 0x3e: + case 0x3f: + return; + + case PCI_REG_COMMAND: + riva128->pci_regs[PCI_REG_COMMAND] = val & 0x27; + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&riva128->mmio_mapping); + mem_mapping_disable(&riva128->linear_mapping); + if (val & PCI_COMMAND_IO) + { + io_removehandler(0x03c0, 0x0020, riva128_in, NULL, NULL, riva128_out, NULL, NULL, riva128); + io_sethandler(0x03c0, 0x0020, riva128_in, NULL, NULL, riva128_out, NULL, NULL, riva128); + } + else io_removehandler(0x03c0, 0x0020, riva128_in, NULL, NULL, riva128_out, NULL, NULL, riva128); + if (val & PCI_COMMAND_MEM) + { + uint32_t mmio_addr = riva128->pci_regs[0x13] << 24; + uint32_t linear_addr = riva128->pci_regs[0x17] << 24; + if (!mmio_addr && !linear_addr) + { + riva128_reenable_svga_mappings(svga); + } + if (mmio_addr) + { + mem_mapping_set_addr(&riva128->mmio_mapping, mmio_addr, 0x1000000); + } + if (linear_addr) + { + mem_mapping_set_addr(&riva128->linear_mapping, linear_addr, 0x1000000); + } + } + return; + + case 0x05: + riva128->pci_regs[0x05] = val & 0x01; + return; + + case 0x07: + riva128->pci_regs[0x07] = (riva128->pci_regs[0x07] & 0x8f) | (val & 0x70); + return; + + case 0x13: + { + uint32_t mmio_addr; + riva128->pci_regs[addr] = val; + mmio_addr = riva128->pci_regs[0x13] << 24; + mem_mapping_disable(&riva128->mmio_mapping); + if (mmio_addr) + { + mem_mapping_set_addr(&riva128->mmio_mapping, mmio_addr, 0x1000000); + } + return; + } + + case 0x17: + { + uint32_t linear_addr; + riva128->pci_regs[addr] = val; + linear_addr = riva128->pci_regs[0x17] << 24; + mem_mapping_disable(&riva128->linear_mapping); + if (linear_addr) + { + mem_mapping_set_addr(&riva128->linear_mapping, linear_addr, 0x1000000); + } + return; + } + + case 0x30: + case 0x32: + case 0x33: + riva128->pci_regs[addr] = val; + mem_mapping_disable(&riva128->bios_rom.mapping); + if (riva128->pci_regs[0x30] & 0x01) + { + uint32_t addr = (riva128->pci_regs[0x32] << 16) | (riva128->pci_regs[0x33] << 24); + // nvidia_log("RIVA 128 bios_rom enabled at %08x\n", addr); + mem_mapping_set_addr(&riva128->bios_rom.mapping, addr, 0x8000); + } + return; + + case 0x3c: + riva128->pci_regs[0x3c] = val & 0x0f; + return; + + case 0x40: + case 0x41: + case 0x42: + case 0x43: + riva128->pci_regs[addr - 0x14] = val; //0x40-0x43 are ways to write to 0x2c-0x2f + return; + } +} + +void riva128_recalctimings(svga_t *svga) +{ + riva128_t *riva128 = (riva128_t *)svga->p; + + svga->ma_latch += (svga->crtc[0x19] & 0x1f) << 16; + svga->rowoffset += (svga->crtc[0x19] & 0xe0) << 3; + if (svga->crtc[0x25] & 0x01) svga->vtotal += 0x400; + if (svga->crtc[0x25] & 0x02) svga->dispend += 0x400; + if (svga->crtc[0x25] & 0x04) svga->vblankstart += 0x400; + if (svga->crtc[0x25] & 0x08) svga->vsyncstart += 0x400; + if (svga->crtc[0x25] & 0x10) svga->htotal += 0x100; + if (svga->crtc[0x2d] & 0x01) svga->hdisp += 0x100; + //The effects of the large screen bit seem to just be doubling the row offset. + //However, these large modes still don't work. Possibly core SVGA bug? It does report 640x2 res after all. + //if (!(svga->crtc[0x1a] & 0x04)) svga->rowoffset <<= 1; + switch(svga->crtc[0x28] & 3) + { + case 1: + svga->bpp = 8; + svga->lowres = 0; + svga->render = svga_render_8bpp_highres; + break; + case 2: + svga->bpp = 16; + svga->lowres = 0; + svga->render = svga_render_16bpp_highres; + break; + case 3: + svga->bpp = 32; + svga->lowres = 0; + svga->render = svga_render_32bpp_highres; + break; + } + + /*if((svga->crtc[0x28] & 3) != 0) + { + if(svga->crtc[0x1a] & 2) svga_set_ramdac_type(svga, RAMDAC_6BIT); + else svga_set_ramdac_type(svga, RAMDAC_8BIT); + } + else svga_set_ramdac_type(svga, RAMDAC_6BIT);*/ + + double freq; + + if (((svga->miscout >> 2) & 2) == 2) + { + freq = 13500000.0; + + if(riva128->pramdac.v_m == 0) riva128->pramdac.v_m = 1; + else + { + freq = (freq * riva128->pramdac.v_n) / (1 << riva128->pramdac.v_p) / riva128->pramdac.v_m; + //nvidia_log("RIVA 128 Pixel clock is %f Hz\n", freq); + } + + svga->clock = cpuclock / freq; + } + + if(riva128->card_id == 0x03) + { + freq = 13500000.0; + + if(riva128->pramdac.m_m == 0) riva128->pramdac.m_m = 1; + else + { + freq = (freq * riva128->pramdac.m_n) / (1 << riva128->pramdac.m_p) / riva128->pramdac.m_m; + //nvidia_log("RIVA 128 Memory clock is %f Hz\n", freq); + } + + riva128->mfreq = freq; + riva128->mtime = (int64_t)((TIMER_USEC * 100000000.0) / riva128->mfreq); + } +} + + +void *riva128_init(const device_t *info) +{ + riva128_t *riva128 = malloc(sizeof(riva128_t)); + memset(riva128, 0, sizeof(riva128_t)); + + riva128->card_id = 0x03; + riva128->is_nv3t = 0; + + riva128->vendor_id = 0x12d2; + riva128->device_id = 0x0018; + + riva128->memory_size = device_get_config_int("memory"); + + svga_init(&riva128->svga, riva128, riva128->memory_size << 20, + riva128_recalctimings, + riva128_in, riva128_out, + NULL, NULL); + + riva128->svga.decode_mask = (riva128->memory_size << 20) - 1; + + rom_init(&riva128->bios_rom, L"roms/video/nv_riva128/Diamond_V330_rev-e.vbi", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (PCI) + mem_mapping_disable(&riva128->bios_rom.mapping); + + /*mem_mapping_add(&riva128->mmio_mapping, 0, 0, + riva128_mmio_read, + riva128_mmio_read_w, + riva128_mmio_read_l, + riva128_mmio_write, + riva128_mmio_write_w, + riva128_mmio_write_l, + NULL, + 0, + riva128);*/ + + mem_mapping_add(&riva128->linear_mapping, 0, 0, + svga_read_linear, + svga_readw_linear, + svga_readl_linear, + svga_write_linear, + svga_writew_linear, + svga_writel_linear, + NULL, + 0, + &riva128->svga); + + io_sethandler(0x03c0, 0x0020, riva128_in, NULL, NULL, riva128_out, NULL, NULL, riva128); + + // riva128->pci_regs[4] = 3; + riva128->pci_regs[4] = 7; + riva128->pci_regs[5] = 0; + riva128->pci_regs[6] = 0; + riva128->pci_regs[7] = 2; + + riva128->pci_regs[0x2c] = 0xd2; + riva128->pci_regs[0x2d] = 0x12; + riva128->pci_regs[0x2e] = 0x00; + riva128->pci_regs[0x2f] = 0x03; + + riva128->pci_regs[0x30] = 0x00; + riva128->pci_regs[0x32] = 0x0c; + riva128->pci_regs[0x33] = 0x00; + + riva128->pmc.intr = 0; + riva128->pbus.intr = 0; + riva128->pfifo.intr = 0; + riva128->pgraph.intr = 0; + riva128->ptimer.intr = 0; + + riva128->pci_card = pci_add_card(PCI_ADD_VIDEO, riva128_pci_read, riva128_pci_write, riva128); + + riva128->ptimer.clock_mul = 1; + riva128->ptimer.clock_div = 1; + + //default values so that the emulator can boot. These'll be overwritten by the video BIOS anyway. + riva128->pramdac.m_m = 0x03; + riva128->pramdac.m_n = 0xc2; + riva128->pramdac.m_p = 0x0d; + + //timer_add(riva128_mclk_poll, &riva128->mtime, &timer_one, riva128); + + return riva128; +} + +void riva128_close(void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + FILE *f = fopen("vram.dmp", "wb"); + fwrite(riva128->svga.vram, 4 << 20, 1, f); + fclose(f); + + svga_close(&riva128->svga); + + free(riva128); +} + +int riva128_available(void) +{ + return rom_present(L"roms/video/nv_riva128/Diamond_V330_rev-e.vbi"); +} + +void riva128_speed_changed(void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + + svga_recalctimings(&riva128->svga); +} + +void riva128_force_redraw(void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + + riva128->svga.fullchange = changeframecount; +} + +const device_config_t riva128_config[] = +{ + { + "memory", "Memory size", CONFIG_SELECTION, "", 4, + { + { + "1 MB", 1 + }, + { + "2 MB", 2 + }, + { + "4 MB", 4 + }, + { + "" + } + }, + }, + { + "", "", -1 + } +}; + +#if 0 +const device_config_t riva128zx_config[] = +{ + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "1 MB", + .value = 1 + }, + { + .description = "2 MB", + .value = 2 + }, + { + .description = "4 MB", + .value = 4 + }, + { + .description = "8 MB", + .value = 8 + }, + { + .description = "" + } + }, + .default_int = 4 + }, + { + .type = -1 + } +}; +#endif + +const device_t riva128_device = +{ + "nVidia RIVA 128", + DEVICE_PCI, + 0, + riva128_init, + riva128_close, + NULL, + riva128_available, + riva128_speed_changed, + riva128_force_redraw, + riva128_config +}; \ No newline at end of file diff --git a/src/video/vid_nvidia.h b/src/video/vid_nvidia.h new file mode 100644 index 000000000..c55533d2c --- /dev/null +++ b/src/video/vid_nvidia.h @@ -0,0 +1 @@ +extern const device_t riva128_device; diff --git a/src/video/vid_oak_oti.c b/src/video/vid_oak_oti.c index 15781aa32..9d166d6e0 100644 --- a/src/video/vid_oak_oti.c +++ b/src/video/vid_oak_oti.c @@ -8,7 +8,7 @@ * * Oak OTI037C/67/077 emulation. * - * Version: @(#)vid_oak_oti.c 1.0.9 2018/03/18 + * Version: @(#)vid_oak_oti.c 1.0.12 2018/04/26 * * Authors: Sarah Walker, * Miran Grca, @@ -77,6 +77,8 @@ oti_out(uint16_t addr, uint8_t val, void *p) return; case 0x3D5: + if (svga->crtcreg & 0x20) + return; if (((svga->crtcreg & 31) < 7) && (svga->crtc[0x11] & 0x80)) return; if (((svga->crtcreg & 31) == 7) && (svga->crtc[0x11] & 0x80)) @@ -154,9 +156,46 @@ oti_in(uint16_t addr, void *p) break; case 0x3D5: - temp = svga->crtc[svga->crtcreg & 31]; + if (svga->crtcreg & 0x20) + temp = 0xff; + else + temp = svga->crtc[svga->crtcreg & 31]; break; - + + case 0x3DA: + svga->attrff = 0; + svga->attrff = 0; + svga->cgastat &= ~0x30; + /* copy color diagnostic info from the overscan color register */ + switch (svga->attrregs[0x12] & 0x30) + { + case 0x00: /* P0 and P2 */ + if (svga->attrregs[0x11] & 0x01) + svga->cgastat |= 0x10; + if (svga->attrregs[0x11] & 0x04) + svga->cgastat |= 0x20; + break; + case 0x10: /* P4 and P5 */ + if (svga->attrregs[0x11] & 0x10) + svga->cgastat |= 0x10; + if (svga->attrregs[0x11] & 0x20) + svga->cgastat |= 0x20; + break; + case 0x20: /* P1 and P3 */ + if (svga->attrregs[0x11] & 0x02) + svga->cgastat |= 0x10; + if (svga->attrregs[0x11] & 0x08) + svga->cgastat |= 0x20; + break; + case 0x30: /* P6 and P7 */ + if (svga->attrregs[0x11] & 0x40) + svga->cgastat |= 0x10; + if (svga->attrregs[0x11] & 0x80) + svga->cgastat |= 0x20; + break; + } + return svga->cgastat; + case 0x3DE: temp = oti->index | (oti->chip_id << 5); break; @@ -287,14 +326,6 @@ oti_force_redraw(void *p) } -static void -oti_add_status_info(char *s, int max_len, void *p) -{ - oti_t *oti = (oti_t *)p; - - svga_add_status_info(s, max_len, &oti->svga); -} - static int oti037c_available(void) { @@ -364,7 +395,6 @@ const device_t oti037c_device = oti037c_available, oti_speed_changed, oti_force_redraw, - oti_add_status_info, oti067_config }; @@ -377,7 +407,6 @@ const device_t oti067_device = oti067_077_available, oti_speed_changed, oti_force_redraw, - oti_add_status_info, oti067_config }; @@ -390,6 +419,5 @@ const device_t oti077_device = oti067_077_available, oti_speed_changed, oti_force_redraw, - oti_add_status_info, oti077_config }; diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index dda19b26d..2342c353a 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -10,7 +10,7 @@ * PC2086, PC3086 use PVGA1A * MegaPC uses W90C11A * - * Version: @(#)vid_paradise.c 1.0.5 2018/03/18 + * Version: @(#)vid_paradise.c 1.0.7 2018/04/26 * * Authors: Sarah Walker, * Miran Grca, @@ -124,12 +124,11 @@ void paradise_out(uint16_t addr, uint8_t val, void *p) break; case 0x3D4: - if (paradise->type == PVGA1A) - svga->crtcreg = val & 0x1f; - else - svga->crtcreg = val & 0x3f; + svga->crtcreg = val & 0x3f; return; case 0x3D5: + if ((paradise->type == PVGA1A) && (svga->crtcreg & 0x20)) + return; if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) return; if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) @@ -194,6 +193,8 @@ uint8_t paradise_in(uint16_t addr, void *p) case 0x3D4: return svga->crtcreg; case 0x3D5: + if ((paradise->type == PVGA1A) && (svga->crtcreg & 0x20)) + return 0xff; if (svga->crtcreg > 0x29 && svga->crtcreg < 0x30 && (svga->crtc[0x29] & 0x88) != 0x80) return 0xff; return svga->crtc[svga->crtcreg]; @@ -305,8 +306,6 @@ void *paradise_pvga1a_init(const device_t *info, uint32_t memsize) svga->bpp = 8; svga->miscout = 1; - svga->linear_base = 0; - paradise->type = PVGA1A; return paradise; @@ -339,9 +338,7 @@ void *paradise_wd90c11_init(const device_t *info) svga->bpp = 8; svga->miscout = 1; - - svga->linear_base = 0; - + paradise->type = WD90C11; return paradise; @@ -374,9 +371,7 @@ void *paradise_wd90c30_init(const device_t *info, uint32_t memsize) svga->bpp = 8; svga->miscout = 1; - - svga->linear_base = 0; - + paradise->type = WD90C11; return paradise; @@ -494,13 +489,6 @@ void paradise_force_redraw(void *p) paradise->svga.fullchange = changeframecount; } -void paradise_add_status_info(char *s, int max_len, void *p) -{ - paradise_t *paradise = (paradise_t *)p; - - svga_add_status_info(s, max_len, ¶dise->svga); -} - const device_t paradise_pvga1a_pc2086_device = { @@ -513,7 +501,7 @@ const device_t paradise_pvga1a_pc2086_device = NULL, paradise_speed_changed, paradise_force_redraw, - paradise_add_status_info + NULL }; const device_t paradise_pvga1a_pc3086_device = { @@ -526,7 +514,7 @@ const device_t paradise_pvga1a_pc3086_device = NULL, paradise_speed_changed, paradise_force_redraw, - paradise_add_status_info + NULL }; static const device_config_t paradise_pvga1a_config[] = @@ -564,7 +552,6 @@ const device_t paradise_pvga1a_device = paradise_pvga1a_standalone_available, paradise_speed_changed, paradise_force_redraw, - paradise_add_status_info, paradise_pvga1a_config }; const device_t paradise_wd90c11_megapc_device = @@ -578,7 +565,7 @@ const device_t paradise_wd90c11_megapc_device = NULL, paradise_speed_changed, paradise_force_redraw, - paradise_add_status_info + NULL }; const device_t paradise_wd90c11_device = { @@ -591,7 +578,7 @@ const device_t paradise_wd90c11_device = paradise_wd90c11_standalone_available, paradise_speed_changed, paradise_force_redraw, - paradise_add_status_info + NULL }; static const device_config_t paradise_wd90c30_config[] = @@ -626,6 +613,5 @@ const device_t paradise_wd90c30_device = paradise_wd90c30_standalone_available, paradise_speed_changed, paradise_force_redraw, - paradise_add_status_info, paradise_wd90c30_config }; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 1df6e8eb3..164220c96 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -8,7 +8,7 @@ * * S3 emulation. * - * Version: @(#)vid_s3.c 1.0.8 2018/03/21 + * Version: @(#)vid_s3.c 1.0.11 2018/07/16 * * Authors: Sarah Walker, * Miran Grca, @@ -94,7 +94,7 @@ typedef struct s3_t int width; int bpp; - int chip; + int chip, pci; uint8_t id, id_ext, id_ext_pci; @@ -118,12 +118,13 @@ typedef struct s3_t uint16_t subsys_cntl; uint16_t setup_md; uint8_t advfunc_cntl; - uint16_t cur_y; - uint16_t cur_x; - int16_t desty_axstp; + uint16_t cur_y, cur_y2; + uint16_t cur_x, cur_x2; + uint16_t x2; + int16_t desty_axstp, desty_axstp2; int16_t destx_distp; - int16_t err_term; - int16_t maj_axis_pcnt; + int16_t err_term, err_term2; + int16_t maj_axis_pcnt, maj_axis_pcnt2; uint16_t cmd; uint16_t short_stroke; uint32_t bkgd_color; @@ -142,7 +143,13 @@ typedef struct s3_t int dx, dy; uint32_t src, dest, pattern; int pix_trans_count; - + + int poly_cx, poly_cx2; + int poly_cy, poly_cy2; + int point_1_updated, point_2_updated; + int poly_dx1, poly_dx2; + int poly_x; + uint32_t dat_buf; int dat_count; } accel; @@ -193,6 +200,11 @@ static void s3_wait_fifo_idle(s3_t *s3) static void s3_update_irqs(s3_t *s3) { + if (!s3->pci) + { + return; + } + if (s3->subsys_cntl & s3->subsys_stat & INT_MASK) pci_set_irq(s3->card, PCI_INTA); else @@ -215,34 +227,78 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) { case 0x82e8: s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val; + s3->accel.poly_cy = s3->accel.cur_y; break; case 0x82e9: s3->accel.cur_y = (s3->accel.cur_y & 0xff) | ((val & 0x1f) << 8); + s3->accel.poly_cy = s3->accel.cur_y; + break; + case 0x82ea: + s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xf00) | val; + s3->accel.poly_cy2 = s3->accel.cur_y2; + break; + case 0x82eb: + s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xff) | ((val & 0x1f) << 8); + s3->accel.poly_cy2 = s3->accel.cur_y2; break; case 0x86e8: s3->accel.cur_x = (s3->accel.cur_x & 0xf00) | val; + s3->accel.poly_cx = s3->accel.cur_x << 20; + s3->accel.poly_x = s3->accel.poly_cx >> 20; break; case 0x86e9: s3->accel.cur_x = (s3->accel.cur_x & 0xff) | ((val & 0x1f) << 8); + s3->accel.poly_cx = s3->accel.poly_x = s3->accel.cur_x << 20; + s3->accel.poly_x = s3->accel.poly_cx >> 20; + break; + case 0x86ea: + s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xf00) | val; + s3->accel.poly_cx2 = s3->accel.cur_x2 << 20; + break; + case 0x86eb: + s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xff) | ((val & 0x1f) << 8); + s3->accel.poly_cx2 = s3->accel.cur_x2 << 20; break; case 0x8ae8: s3->accel.desty_axstp = (s3->accel.desty_axstp & 0x3f00) | val; + s3->accel.point_1_updated = 1; break; case 0x8ae9: s3->accel.desty_axstp = (s3->accel.desty_axstp & 0xff) | ((val & 0x3f) << 8); if (val & 0x20) - s3->accel.desty_axstp |= ~0x3fff; + s3->accel.desty_axstp |= ~0x3fff; + s3->accel.point_1_updated = 1; + break; + case 0x8aea: + s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0x3f00) | val; + s3->accel.point_2_updated = 1; + break; + case 0x8aeb: + s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + s3->accel.desty_axstp2 |= ~0x3fff; + s3->accel.point_2_updated = 1; break; case 0x8ee8: s3->accel.destx_distp = (s3->accel.destx_distp & 0x3f00) | val; + s3->accel.point_1_updated = 1; break; case 0x8ee9: s3->accel.destx_distp = (s3->accel.destx_distp & 0xff) | ((val & 0x3f) << 8); if (val & 0x20) - s3->accel.destx_distp |= ~0x3fff; + s3->accel.destx_distp |= ~0x3fff; + s3->accel.point_1_updated = 1; + break; + case 0x8eea: + s3->accel.x2 = (s3->accel.x2 & 0xf00) | val; + s3->accel.point_2_updated = 1; + break; + case 0x8eeb: + s3->accel.x2 = (s3->accel.x2 & 0xff) | ((val & 0xf) << 8); + s3->accel.point_2_updated = 1; break; case 0x92e8: @@ -253,6 +309,14 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) if (val & 0x20) s3->accel.err_term |= ~0x3fff; break; + case 0x92ea: + s3->accel.err_term2 = (s3->accel.err_term2 & 0x3f00) | val; + break; + case 0x92eb: + s3->accel.err_term2 = (s3->accel.err_term2 & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + s3->accel.err_term2 |= ~0x3fff; + break; case 0x96e8: s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0x3f00) | val; @@ -262,6 +326,14 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) if (val & 0x08) s3->accel.maj_axis_pcnt |= ~0x0fff; break; + case 0x96ea: + s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xf00) | val; + break; + case 0x96eb: + s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xff) | ((val & 0x0f) << 8); + if (val & 0x08) + s3->accel.maj_axis_pcnt2 |= ~0x0fff; + break; case 0x9ae8: s3->accel.cmd = (s3->accel.cmd & 0xff00) | val; @@ -297,10 +369,25 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xa2ea: if (s3->accel.multifunc[0xe] & 0x200) s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; + } break; case 0xa2eb: if (s3->accel.multifunc[0xe] & 0x200) s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } break; case 0xa6e8: @@ -320,10 +407,25 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xa6ea: if (s3->accel.multifunc[0xe] & 0x200) s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; + } break; case 0xa6eb: if (s3->accel.multifunc[0xe] & 0x200) s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } break; case 0xaae8: @@ -343,10 +445,25 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xaaea: if (s3->accel.multifunc[0xe] & 0x200) s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; + } break; case 0xaaeb: if (s3->accel.multifunc[0xe] & 0x200) s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } break; case 0xaee8: @@ -366,10 +483,25 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xaeea: if (s3->accel.multifunc[0xe] & 0x200) s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; + } break; case 0xaeeb: if (s3->accel.multifunc[0xe] & 0x200) s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } break; case 0xb2e8: @@ -389,10 +521,25 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xb2ea: if (s3->accel.multifunc[0xe] & 0x200) s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; + } break; case 0xb2eb: if (s3->accel.multifunc[0xe] & 0x200) s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } break; case 0xb6e8: @@ -436,7 +583,14 @@ static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xe2eb: s3->accel.pix_trans[3] = val; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x400 && (s3->accel.cmd & 0x100)) + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x600 && (s3->accel.cmd & 0x100) && s3->chip == S3_TRIO32) + { + s3_accel_start(8, 1, s3->accel.pix_trans[3], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[2], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + } + else if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x400) == 0x400 && (s3->accel.cmd & 0x100)) s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); else if ((s3->accel.cmd & 0x600) == 0x400 && (s3->accel.cmd & 0x100)) s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); @@ -452,6 +606,11 @@ static void s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) { if (s3->accel.cmd & 0x1000) val = (val >> 8) | (val << 8); + if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32) + { + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } if ((s3->accel.cmd & 0x600) == 0x000) s3_accel_start(8, 1, val | (val << 16), 0, s3); else @@ -473,7 +632,16 @@ static void s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val) { if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) { - if (s3->accel.cmd & 0x400) + if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32) + { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } + else if (s3->accel.cmd & 0x400) { if (s3->accel.cmd & 0x1000) val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); @@ -632,7 +800,12 @@ static void s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) { if (s3->accel.cmd & 0x1000) val = (val >> 8) | (val << 8); - if ((s3->accel.cmd & 0x600) == 0x000) + if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32) + { + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } + else if ((s3->accel.cmd & 0x600) == 0x000) s3_accel_start(8, 1, val | (val << 16), 0, s3); else s3_accel_start(16, 1, val | (val << 16), 0, s3); @@ -663,7 +836,16 @@ static void s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) { if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) { - if (s3->accel.cmd & 0x400) + if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32) + { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } + else if (s3->accel.cmd & 0x400) { if (s3->accel.cmd & 0x1000) val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); @@ -1137,7 +1319,6 @@ void s3_updatemapping(s3_t *s3) break; } s3->linear_base &= ~(s3->linear_size - 1); - svga->linear_base = s3->linear_base; if (s3->linear_base == 0xa0000) { mem_mapping_disable(&s3->linear_mapping); @@ -1428,29 +1609,80 @@ uint8_t s3_accel_read(uint32_t addr, void *p) return 0; } -#define READ(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \ - else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \ - else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; +static void polygon_setup(s3_t *s3) +{ + if (s3->accel.point_1_updated) + { + int start_x = s3->accel.poly_cx; + int start_y = s3->accel.poly_cy; + int end_x = s3->accel.destx_distp << 20; + int end_y = s3->accel.desty_axstp; + + if (end_y - start_y) + s3->accel.poly_dx1 = (end_x - start_x) / (end_y - start_y); + else + s3->accel.poly_dx1 = 0; + + s3->accel.point_1_updated = 0; -#define MIX switch ((mix_dat & mix_mask) ? (s3->accel.frgd_mix & 0xf) : (s3->accel.bkgd_mix & 0xf)) \ - { \ - case 0x0: dest_dat = ~dest_dat; break; \ - case 0x1: dest_dat = 0; break; \ - case 0x2: dest_dat = ~0; break; \ - case 0x3: dest_dat = dest_dat; break; \ - case 0x4: dest_dat = ~src_dat; break; \ - case 0x5: dest_dat = src_dat ^ dest_dat; break; \ - case 0x6: dest_dat = ~(src_dat ^ dest_dat); break; \ - case 0x7: dest_dat = src_dat; break; \ - case 0x8: dest_dat = ~(src_dat & dest_dat); break; \ - case 0x9: dest_dat = ~src_dat | dest_dat; break; \ - case 0xa: dest_dat = src_dat | ~dest_dat; break; \ - case 0xb: dest_dat = src_dat | dest_dat; break; \ - case 0xc: dest_dat = src_dat & dest_dat; break; \ - case 0xd: dest_dat = src_dat & ~dest_dat; break; \ - case 0xe: dest_dat = ~src_dat & dest_dat; break; \ - case 0xf: dest_dat = ~(src_dat | dest_dat); break; \ + if (end_y == s3->accel.poly_cy) + { + s3->accel.poly_cx = end_x; + s3->accel.poly_x = end_x >> 20; } + } + if (s3->accel.point_2_updated) + { + int start_x = s3->accel.poly_cx2; + int start_y = s3->accel.poly_cy2; + int end_x = s3->accel.x2 << 20; + int end_y = s3->accel.desty_axstp2; + + if (end_y - start_y) + s3->accel.poly_dx2 = (end_x - start_x) / (end_y - start_y); + else + s3->accel.poly_dx2 = 0; + + s3->accel.point_2_updated = 0; + + if (end_y == s3->accel.poly_cy) + s3->accel.poly_cx2 = end_x; + } +} + +#define READ_SRC(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \ + else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \ + else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; \ + if (vram_mask) \ + dat = ((dat & rd_mask) == rd_mask); + +#define READ_DST(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \ + else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \ + else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; + +#define MIX { \ + uint32_t old_dest_dat = dest_dat; \ + switch ((mix_dat & mix_mask) ? (s3->accel.frgd_mix & 0xf) : (s3->accel.bkgd_mix & 0xf)) \ + { \ + case 0x0: dest_dat = ~dest_dat; break; \ + case 0x1: dest_dat = 0; break; \ + case 0x2: dest_dat = ~0; break; \ + case 0x3: dest_dat = dest_dat; break; \ + case 0x4: dest_dat = ~src_dat; break; \ + case 0x5: dest_dat = src_dat ^ dest_dat; break; \ + case 0x6: dest_dat = ~(src_dat ^ dest_dat); break; \ + case 0x7: dest_dat = src_dat; break; \ + case 0x8: dest_dat = ~(src_dat & dest_dat); break; \ + case 0x9: dest_dat = ~src_dat | dest_dat; break; \ + case 0xa: dest_dat = src_dat | ~dest_dat; break; \ + case 0xb: dest_dat = src_dat | dest_dat; break; \ + case 0xc: dest_dat = src_dat & dest_dat; break; \ + case 0xd: dest_dat = src_dat & ~dest_dat; break; \ + case 0xe: dest_dat = ~src_dat & dest_dat; break; \ + case 0xf: dest_dat = ~(src_dat | dest_dat); break; \ + } \ + dest_dat = (dest_dat & s3->accel.wrt_mask) | (old_dest_dat & ~s3->accel.wrt_mask); \ + } #define WRITE(addr) if (s3->bpp == 0) \ @@ -1484,6 +1716,11 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat uint32_t *vram_l = (uint32_t *)svga->vram; uint32_t compare = s3->accel.color_cmp; int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3; + uint32_t rd_mask = s3->accel.rd_mask; + int cmd = s3->accel.cmd >> 13; + + if ((s3->chip == S3_TRIO64) && (s3->accel.cmd & (1 << 11))) + cmd |= 8; if (!cpu_input) s3->accel.dat_count = 0; if (cpu_input && (s3->accel.multifunc[0xa] & 0xc0) != 0x80) @@ -1505,18 +1742,23 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (s3->bpp == 1) count >>= 1; if (s3->bpp == 3) count >>= 2; } - + + if (s3->bpp == 0) + rd_mask &= 0xff; + else if (s3->bpp == 1) + rd_mask &= 0xffff; + switch (s3->accel.cmd & 0x600) { case 0x000: mix_mask = 0x80; break; case 0x200: mix_mask = 0x8000; break; case 0x400: mix_mask = 0x80000000; break; - case 0x600: mix_mask = 0x80000000; break; + case 0x600: mix_mask = (s3->chip == S3_TRIO32) ? 0x80 : 0x80000000; break; } if (s3->bpp == 0) compare &= 0xff; if (s3->bpp == 1) compare &= 0xffff; - switch (s3->accel.cmd >> 13) + switch (cmd) { case 1: /*Draw line*/ if (!cpu_input) /*!cpu_input is trigger to start operation*/ @@ -1528,6 +1770,15 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat s3->accel.sy = s3->accel.maj_axis_pcnt; } + + s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ + + if ((s3->accel.cmd & 0x100) && !cpu_input) + { + s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/ + return; /*Wait for data from CPU*/ + } + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ frgd_mix = (s3->accel.frgd_mix >> 5) & 3; @@ -1552,7 +1803,7 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { - READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + READ_DST((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); MIX @@ -1602,7 +1853,7 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { - READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + READ_DST((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); MIX @@ -1669,14 +1920,14 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat s3->accel.dest = s3->accel.cy * s3->width; } - s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ + s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ + + if ((s3->accel.cmd & 0x100) && !cpu_input) + { + s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/ + return; /*Wait for data from CPU*/ + } - if ((s3->accel.cmd & 0x100) && !cpu_input) - { - s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/ - return; /*Wait for data from CPU*/ - } - if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ frgd_mix = (s3->accel.frgd_mix >> 5) & 3; @@ -1699,7 +1950,7 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { - READ(s3->accel.dest + s3->accel.cx, dest_dat); + READ_DST(s3->accel.dest + s3->accel.cx, dest_dat); MIX @@ -1730,8 +1981,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return; if (s3->accel.sy < 0) { - s3->accel.cur_x = s3->accel.cx; - s3->accel.cur_y = s3->accel.cy; + s3->accel.cur_x = s3->accel.cx; + s3->accel.cur_y = s3->accel.cy; return; } } @@ -1757,6 +2008,15 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat s3->accel.src = s3->accel.cy * s3->width; s3->accel.dest = s3->accel.dy * s3->width; } + + s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ + + if ((s3->accel.cmd & 0x100) && !cpu_input) + { + s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/ + return; /*Wait for data from CPU*/ + } + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ if (s3->accel.sy < 0) @@ -1774,10 +2034,11 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r && s3->accel.dy >= clip_t && s3->accel.dy <= clip_b) { - READ(s3->accel.src + s3->accel.cx, src_dat); - - dest_dat = src_dat; - + READ_SRC(s3->accel.src + s3->accel.cx, src_dat); + READ_DST(s3->accel.dest + s3->accel.dx, dest_dat); + + dest_dat = (src_dat & s3->accel.wrt_mask) | (dest_dat & ~s3->accel.wrt_mask); + WRITE(s3->accel.dest + s3->accel.dx); } @@ -1814,7 +2075,7 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat { if (vram_mask) { - READ(s3->accel.src + s3->accel.cx, mix_dat) + READ_SRC(s3->accel.src + s3->accel.cx, mix_dat) mix_dat = mix_dat ? mix_mask : 0; } switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) @@ -1822,14 +2083,14 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat case 0: src_dat = s3->accel.bkgd_color; break; case 1: src_dat = s3->accel.frgd_color; break; case 2: src_dat = cpu_dat; break; - case 3: READ(s3->accel.src + s3->accel.cx, src_dat); break; + case 3: READ_SRC(s3->accel.src + s3->accel.cx, src_dat); break; } if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { - READ(s3->accel.dest + s3->accel.dx, dest_dat); + READ_DST(s3->accel.dest + s3->accel.dx, dest_dat); MIX @@ -1918,6 +2179,15 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width); } + + s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ + + if ((s3->accel.cmd & 0x100) && !cpu_input) + { + s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/ + return; /*Wait for data from CPU*/ + } + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ frgd_mix = (s3->accel.frgd_mix >> 5) & 3; @@ -1930,7 +2200,7 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat { if (vram_mask) { - READ(s3->accel.src + s3->accel.cx, mix_dat) + READ_SRC(s3->accel.src + s3->accel.cx, mix_dat) mix_dat = mix_dat ? mix_mask : 0; } switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) @@ -1938,14 +2208,14 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat case 0: src_dat = s3->accel.bkgd_color; break; case 1: src_dat = s3->accel.frgd_color; break; case 2: src_dat = cpu_dat; break; - case 3: READ(s3->accel.src + s3->accel.cx, src_dat); break; + case 3: READ_SRC(s3->accel.src + s3->accel.cx, src_dat); break; } if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { - READ(s3->accel.dest + s3->accel.dx, dest_dat); + READ_DST(s3->accel.dest + s3->accel.dx, dest_dat); MIX @@ -2005,6 +2275,182 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat } } break; + + case 3: /*Polygon Fill Solid (Trio64 only)*/ + { + int end_y1, end_y2; + + if (s3->chip != S3_TRIO64) + break; + + polygon_setup(s3); + + s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ + + if ((s3->accel.cmd & 0x100) && !cpu_input) + { + s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/ + return; /*Wait for data from CPU*/ + } + + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + + end_y1 = s3->accel.desty_axstp; + end_y2 = s3->accel.desty_axstp2; + + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + + while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2)) + { + int y = s3->accel.poly_cy; + int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1; + + s3->accel.dest = y * s3->width; + + while (x_count-- && count--) + { + if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r && + s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b) + { + switch (frgd_mix) + { + case 0: src_dat = s3->accel.bkgd_color; break; + case 1: src_dat = s3->accel.frgd_color; break; + case 2: src_dat = cpu_dat; break; + case 3: src_dat = 0; /*Nor supported?*/ break; + } + + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ_DST(s3->accel.dest + s3->accel.poly_x, dest_dat); + + MIX + + WRITE(s3->accel.dest + s3->accel.poly_x); + } + } + if (s3->bpp == 0) cpu_dat >>= 8; + else cpu_dat >>= 16; + + if (s3->accel.poly_x < (s3->accel.poly_cx2 >> 20)) + s3->accel.poly_x++; + else + s3->accel.poly_x--; + } + + s3->accel.poly_cx += s3->accel.poly_dx1; + s3->accel.poly_cx2 += s3->accel.poly_dx2; + s3->accel.poly_x = s3->accel.poly_cx >> 20; + + s3->accel.poly_cy++; + s3->accel.poly_cy2++; + + if (!count) + break; + } + + s3->accel.cur_x = s3->accel.poly_cx & 0xfff; + s3->accel.cur_y = s3->accel.poly_cy & 0xfff; + s3->accel.cur_x2 = s3->accel.poly_cx2 & 0xfff; + s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff; + } + break; + + case 11: /*Polygon Fill Pattern (Trio64 only)*/ + { + int end_y1, end_y2; + + if (s3->chip != S3_TRIO64) + break; + + polygon_setup(s3); + + s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ + + if ((s3->accel.cmd & 0x100) && !cpu_input) + { + s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/ + return; /*Wait for data from CPU*/ + } + + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + + end_y1 = s3->accel.desty_axstp; + end_y2 = s3->accel.desty_axstp2; + + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + + while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2)) + { + int y = s3->accel.poly_cy; + int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1; + + s3->accel.src = s3->accel.pattern + ((y & 7) * s3->width); + s3->accel.dest = y * s3->width; + + while (x_count-- && count--) + { + int pat_x = s3->accel.poly_x & 7; + + if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r && + s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b) + { + if (vram_mask) + { + READ_SRC(s3->accel.src + pat_x, mix_dat) + mix_dat = mix_dat ? mix_mask : 0; + } + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: src_dat = s3->accel.bkgd_color; break; + case 1: src_dat = s3->accel.frgd_color; break; + case 2: src_dat = cpu_dat; break; + case 3: READ_SRC(s3->accel.src + pat_x, src_dat); break; + } + + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ_DST(s3->accel.dest + s3->accel.poly_x, dest_dat); + + MIX + + WRITE(s3->accel.dest + s3->accel.poly_x); + } + } + if (s3->bpp == 0) cpu_dat >>= 8; + else cpu_dat >>= 16; + + mix_dat <<= 1; + mix_dat |= 1; + + if (s3->accel.poly_x < (s3->accel.poly_cx2 >> 20)) + s3->accel.poly_x++; + else + s3->accel.poly_x--; + } + + s3->accel.poly_cx += s3->accel.poly_dx1; + s3->accel.poly_cx2 += s3->accel.poly_dx2; + s3->accel.poly_x = s3->accel.poly_cx >> 20; + + s3->accel.poly_cy++; + s3->accel.poly_cy2++; + + if (!count) + break; + } + + s3->accel.cur_x = s3->accel.poly_cx & 0xfff; + s3->accel.cur_y = s3->accel.poly_cy & 0xfff; + s3->accel.cur_x2 = s3->accel.poly_cx2 & 0xfff; + s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff; + } + break; } } @@ -2015,10 +2461,11 @@ void s3_hwcursor_draw(svga_t *svga, int displine) uint16_t dat[2]; int xx; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; - int y_add = (enable_overscan && !suppress_overscan) ? 16 : 0; - int x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; - + int y_add, x_add; uint32_t fg = 0, bg = 0; + + y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; + x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; switch (svga->bpp) { @@ -2086,12 +2533,24 @@ static void s3_io_remove(s3_t *s3) io_removehandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + if (s3->chip == S3_TRIO64) + { + io_sethandler(0x82e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x86e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x92e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x96e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + } + else + { + io_sethandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + } io_removehandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2254,6 +2713,8 @@ static void *s3_init(const device_t *info, wchar_t *bios_fn, int chip) mem_mapping_disable(&s3->bios_rom.mapping); } + s3->pci = !!(info->flags & DEVICE_PCI); + mem_mapping_add(&s3->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, MEM_MAPPING_EXTERNAL, &s3->svga); mem_mapping_add(&s3->mmio_mapping, 0xa0000, 0x10000, s3_accel_read, NULL, NULL, s3_accel_write, s3_accel_write_w, s3_accel_write_l, NULL, MEM_MAPPING_EXTERNAL, s3); mem_mapping_disable(&s3->mmio_mapping); @@ -2469,24 +2930,6 @@ static void s3_force_redraw(void *p) s3->svga.fullchange = changeframecount; } -static void s3_add_status_info(char *s, int max_len, void *p) -{ - s3_t *s3 = (s3_t *)p; - char temps[256]; - uint64_t new_time = plat_timer_read(); - uint64_t status_diff = new_time - s3->status_time; - s3->status_time = new_time; - - if (!status_diff) - status_diff = 1; - - svga_add_status_info(s, max_len, &s3->svga); - sprintf(temps, "%f%% CPU\n%f%% CPU (real)\n\n", ((double)s3->blitter_time * 100.0) / timer_freq, ((double)s3->blitter_time * 100.0) / status_diff); - strncat(s, temps, max_len); - - s3->blitter_time = 0; -} - static const device_config_t s3_bahamas64_config[] = { { @@ -2631,7 +3074,6 @@ const device_t s3_bahamas64_vlb_device = s3_bahamas64_available, s3_speed_changed, s3_force_redraw, - s3_add_status_info, s3_bahamas64_config }; @@ -2646,7 +3088,6 @@ const device_t s3_bahamas64_pci_device = s3_bahamas64_available, s3_speed_changed, s3_force_redraw, - s3_add_status_info, s3_bahamas64_config }; @@ -2661,7 +3102,6 @@ const device_t s3_9fx_vlb_device = s3_9fx_available, s3_speed_changed, s3_force_redraw, - s3_add_status_info, s3_9fx_config }; @@ -2676,7 +3116,6 @@ const device_t s3_9fx_pci_device = s3_9fx_available, s3_speed_changed, s3_force_redraw, - s3_add_status_info, s3_9fx_config }; @@ -2691,7 +3130,6 @@ const device_t s3_phoenix_trio32_vlb_device = s3_phoenix_trio32_available, s3_speed_changed, s3_force_redraw, - s3_add_status_info, s3_phoenix_trio32_config }; @@ -2706,7 +3144,6 @@ const device_t s3_phoenix_trio32_pci_device = s3_phoenix_trio32_available, s3_speed_changed, s3_force_redraw, - s3_add_status_info, s3_phoenix_trio32_config }; @@ -2721,7 +3158,6 @@ const device_t s3_phoenix_trio64_vlb_device = s3_phoenix_trio64_available, s3_speed_changed, s3_force_redraw, - s3_add_status_info, s3_phoenix_trio64_config }; @@ -2736,7 +3172,6 @@ const device_t s3_phoenix_trio64_onboard_pci_device = NULL, s3_speed_changed, s3_force_redraw, - s3_add_status_info, s3_phoenix_trio64_onboard_config }; @@ -2751,7 +3186,6 @@ const device_t s3_phoenix_trio64_pci_device = s3_phoenix_trio64_available, s3_speed_changed, s3_force_redraw, - s3_add_status_info, s3_phoenix_trio64_config }; @@ -2766,7 +3200,6 @@ const device_t s3_phoenix_vision864_vlb_device = s3_phoenix_vision864_available, s3_speed_changed, s3_force_redraw, - s3_add_status_info, s3_bahamas64_config }; @@ -2781,7 +3214,6 @@ const device_t s3_phoenix_vision864_pci_device = s3_phoenix_vision864_available, s3_speed_changed, s3_force_redraw, - s3_add_status_info, s3_bahamas64_config }; @@ -2796,7 +3228,6 @@ const device_t s3_diamond_stealth64_vlb_device = s3_diamond_stealth64_available, s3_speed_changed, s3_force_redraw, - s3_add_status_info, s3_phoenix_trio64_config }; @@ -2811,6 +3242,5 @@ const device_t s3_diamond_stealth64_pci_device = s3_diamond_stealth64_available, s3_speed_changed, s3_force_redraw, - s3_add_status_info, s3_phoenix_trio64_config }; diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index bb104c921..59a20b2bf 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -8,7 +8,7 @@ * * S3 ViRGE emulation. * - * Version: @(#)vid_s3_virge.c 1.0.8 2018/03/22 + * Version: @(#)vid_s3_virge.c 1.0.12 2018/07/16 * * Authors: Sarah Walker, * Miran Grca, @@ -16,11 +16,13 @@ * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 Miran Grca. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../io.h" #include "../mem.h" @@ -35,7 +37,6 @@ static uint64_t virge_time = 0; -static uint64_t status_time = 0; static int reg_writes = 0, reg_reads = 0; static int dither[4][4] = @@ -319,6 +320,27 @@ enum #define INT_3DF_EMP (1 << 6) #define INT_MASK 0xff + +#ifdef ENABLE_S3_VIRGE_LOG +int s3_virge_do_log = ENABLE_S3_VIRGE_LOG; +#endif + + +static void +s3_virge_log(const char *format, ...) +{ +#ifdef ENABLE_S3_VIRGE_LOG + va_list ap; + + if (s3_virge_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + static void s3_virge_update_irqs(virge_t *virge) { if (!virge->pci) @@ -659,7 +681,7 @@ static void s3_virge_updatemapping(virge_t *virge) return; } - //pclog("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc); + s3_virge_log("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc); switch (svga->gdcreg[6] & 0xc) /*Banked framebuffer*/ { case 0x0: /*128k at A0000*/ @@ -682,7 +704,7 @@ static void s3_virge_updatemapping(virge_t *virge) virge->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); - //pclog("Linear framebuffer %02X ", svga->crtc[0x58] & 0x10); + s3_virge_log("Linear framebuffer %02X ", svga->crtc[0x58] & 0x10); if (svga->crtc[0x58] & 0x10) /*Linear framebuffer*/ { switch (svga->crtc[0x58] & 3) @@ -701,8 +723,7 @@ static void s3_virge_updatemapping(virge_t *virge) break; } virge->linear_base &= ~(virge->linear_size - 1); - svga->linear_base = virge->linear_base; - //pclog("Linear framebuffer at %08X size %08X\n", virge->linear_base, virge->linear_size); + s3_virge_log("Linear framebuffer at %08X size %08X\n", virge->linear_base, virge->linear_size); if (virge->linear_base == 0xa0000) { mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); @@ -718,7 +739,7 @@ static void s3_virge_updatemapping(virge_t *virge) svga->fb_only = 0; } - //pclog("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x18); + s3_virge_log("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x18); if (svga->crtc[0x53] & 0x10) /*Old MMIO*/ { if (svga->crtc[0x53] & 0x20) @@ -1998,7 +2019,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; virge->s3d.data_left_count = 0; -/* pclog("BitBlt start %i,%i %i,%i %i,%i %02X %x %x\n", + s3_virge_log("BitBlt start %i,%i %i,%i %i,%i %02X %x %x\n", virge->s3d.src_x, virge->s3d.src_y, virge->s3d.dest_x, @@ -2007,7 +2028,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) virge->s3d.h, virge->s3d.rop, virge->s3d.src_base, - virge->s3d.dest_base);*/ + virge->s3d.dest_base); if (virge->s3d.cmd_set & CMD_SET_IDS) return; @@ -2129,11 +2150,11 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) virge->s3d.h = virge->s3d.r_height; virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; -/* pclog("RctFll start %i,%i %i,%i %02X %08x\n", virge->s3d.dest_x, + s3_virge_log("RctFll start %i,%i %i,%i %02X %08x\n", virge->s3d.dest_x, virge->s3d.dest_y, virge->s3d.w, virge->s3d.h, - virge->s3d.rop, virge->s3d.dest_base);*/ + virge->s3d.rop, virge->s3d.dest_base); } while (count && virge->s3d.h) @@ -3228,7 +3249,7 @@ static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) dest_pixel = dest_pixel_lit_texture_decal; break; default: - /* pclog("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf); */ + s3_virge_log("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf); return; } break; @@ -3237,7 +3258,7 @@ static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) dest_pixel = dest_pixel_unlit_texture_triangle; break; default: - /* pclog("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf); */ + s3_virge_log("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf); return; } @@ -3293,7 +3314,7 @@ static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap; break; default: - /* pclog("bad texture type %i\n", (s3d_tri->cmd_set >> 5) & 7); */ + s3_virge_log("bad texture type %i\n", (s3d_tri->cmd_set >> 5) & 7); tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap; break; } @@ -3356,9 +3377,11 @@ static void s3_virge_hwcursor_draw(svga_t *svga, int displine) uint16_t dat[2]; int xx; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + int y_add, x_add; uint32_t fg, bg; - int y_add = (enable_overscan && !suppress_overscan) ? 16 : 0; - int x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; + + y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; + x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 16; @@ -4167,27 +4190,6 @@ static void s3_virge_force_redraw(void *p) virge->svga.fullchange = changeframecount; } -static void s3_virge_add_status_info(char *s, int max_len, void *p) -{ - virge_t *virge = (virge_t *)p; - char temps[256]; - uint64_t new_time = plat_timer_read(); - uint64_t status_diff = new_time - status_time; - status_time = new_time; - - if (!status_diff) - status_diff = 1; - - svga_add_status_info(s, max_len, &virge->svga); - sprintf(temps, "%f Mpixels/sec\n%f ktris/sec\n%f%% CPU\n%f%% CPU (real)\n%d writes %i reads\n\n", (double)virge->pixel_count/1000000.0, (double)virge->tri_count/1000.0, ((double)virge_time * 100.0) / timer_freq, ((double)virge_time * 100.0) / status_diff, reg_writes, reg_reads); - strncat(s, temps, max_len); - - virge->pixel_count = virge->tri_count = 0; - virge_time = 0; - reg_reads = 0; - reg_writes = 0; -} - static const device_config_t s3_virge_config[] = { { @@ -4226,7 +4228,6 @@ const device_t s3_virge_vlb_device = s3_virge_available, s3_virge_speed_changed, s3_virge_force_redraw, - s3_virge_add_status_info, s3_virge_config }; @@ -4241,7 +4242,6 @@ const device_t s3_virge_pci_device = s3_virge_available, s3_virge_speed_changed, s3_virge_force_redraw, - s3_virge_add_status_info, s3_virge_config }; @@ -4256,7 +4256,6 @@ const device_t s3_virge_988_vlb_device = s3_virge_988_available, s3_virge_speed_changed, s3_virge_force_redraw, - s3_virge_add_status_info, s3_virge_config }; @@ -4271,7 +4270,6 @@ const device_t s3_virge_988_pci_device = s3_virge_988_available, s3_virge_speed_changed, s3_virge_force_redraw, - s3_virge_add_status_info, s3_virge_config }; @@ -4286,7 +4284,6 @@ const device_t s3_virge_375_vlb_device = s3_virge_375_1_available, s3_virge_speed_changed, s3_virge_force_redraw, - s3_virge_add_status_info, s3_virge_config }; @@ -4301,7 +4298,6 @@ const device_t s3_virge_375_pci_device = s3_virge_375_1_available, s3_virge_speed_changed, s3_virge_force_redraw, - s3_virge_add_status_info, s3_virge_config }; @@ -4316,7 +4312,6 @@ const device_t s3_virge_375_4_vlb_device = s3_virge_375_4_available, s3_virge_speed_changed, s3_virge_force_redraw, - s3_virge_add_status_info, s3_virge_config }; @@ -4331,6 +4326,5 @@ const device_t s3_virge_375_4_pci_device = s3_virge_375_4_available, s3_virge_speed_changed, s3_virge_force_redraw, - s3_virge_add_status_info, s3_virge_config }; diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index cb03307a2..cfb5e6d99 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -11,7 +11,7 @@ * This is intended to be used by another SVGA driver, * and not as a card in it's own right. * - * Version: @(#)vid_svga.c 1.0.27 2018/03/23 + * Version: @(#)vid_svga.c 1.0.31 2018/05/26 * * Authors: Sarah Walker, * Miran Grca, @@ -42,1512 +42,1312 @@ void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga); -extern uint8_t edatlookup[4][4]; +extern int cyc_total; +extern uint8_t edatlookup[4][4]; -uint8_t svga_rotate[8][256]; +uint8_t svga_rotate[8][256]; + +static const uint32_t mask16[16] = { + 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff, + 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff, + 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff, + 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff +}; /*Primary SVGA device. As multiple video cards are not yet supported this is the only SVGA device.*/ -static svga_t *svga_pri; +static svga_t *svga_pri; -svga_t *svga_get_pri() + +svga_t +*svga_get_pri() { - return svga_pri; -} -void svga_set_override(svga_t *svga, int val) -{ - if (svga->override && !val) - svga->fullchange = changeframecount; - svga->override = val; + return svga_pri; } -void svga_out(uint16_t addr, uint8_t val, void *p) + +void +svga_set_override(svga_t *svga, int val) { - svga_t *svga = (svga_t *)p; - int c; - uint8_t o; - switch (addr) - { - case 0x3C0: - case 0x3C1: - if (!svga->attrff) - { - svga->attraddr = val & 31; - if ((val & 0x20) != svga->attr_palette_enable) - { - svga->fullchange = 3; - svga->attr_palette_enable = val & 0x20; - svga_recalctimings(svga); - } - } - else - { + if (svga->override && !val) + svga->fullchange = changeframecount; + svga->override = val; +} + + +/* Used to add custom write modes, eg. by the CL-GD 54xx to add write modes 4 and 5. */ +void +svga_set_ven_write(svga_t *svga, void (*ven_write)(struct svga_t *svga, uint8_t val, uint32_t addr)) +{ + svga->ven_write = ven_write; +} + + +void +svga_out(uint16_t addr, uint8_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + int c; + uint8_t o; + + switch (addr) { + case 0x3c0: + case 0x3c1: + if (!svga->attrff) { + svga->attraddr = val & 31; + if ((val & 0x20) != svga->attr_palette_enable) { + svga->fullchange = 3; + svga->attr_palette_enable = val & 0x20; + svga_recalctimings(svga); + } + } else { o = svga->attrregs[svga->attraddr & 31]; - svga->attrregs[svga->attraddr & 31] = val; - if (svga->attraddr < 16) - svga->fullchange = changeframecount; - if (svga->attraddr == 0x10 || svga->attraddr == 0x14 || svga->attraddr < 0x10) - { - for (c = 0; c < 16; c++) - { - if (svga->attrregs[0x10] & 0x80) svga->egapal[c] = (svga->attrregs[c] & 0xf) | ((svga->attrregs[0x14] & 0xf) << 4); - else svga->egapal[c] = (svga->attrregs[c] & 0x3f) | ((svga->attrregs[0x14] & 0xc) << 4); - } - } - /* Recalculate timings on change of attribute register 0x11 (overscan border color) too. */ - if (svga->attraddr == 0x10) - { - if (o != val) svga_recalctimings(svga); - } - else if (svga->attraddr == 0x11) - { - svga->overscan_color = svga->pallook[svga->overscan_color]; - if (o != val) svga_recalctimings(svga); - } - else if (svga->attraddr == 0x12) - { - if ((val & 0xf) != svga->plane_mask) - svga->fullchange = changeframecount; - svga->plane_mask = val & 0xf; - } - } - svga->attrff ^= 1; - break; - case 0x3C2: - svga->miscout = val; - svga->vidclock = val & 4; - io_removehandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->p); - if (!(val & 1)) - io_sethandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->p); - svga_recalctimings(svga); - break; - case 0x3C4: - svga->seqaddr = val; - break; - case 0x3C5: - if (svga->seqaddr > 0xf) return; - o = svga->seqregs[svga->seqaddr & 0xf]; - svga->seqregs[svga->seqaddr & 0xf] = val; - if (o != val && (svga->seqaddr & 0xf) == 1) - svga_recalctimings(svga); - switch (svga->seqaddr & 0xf) - { - case 1: - if (svga->scrblank && !(val & 0x20)) - svga->fullchange = 3; - svga->scrblank = (svga->scrblank & ~0x20) | (val & 0x20); - svga_recalctimings(svga); - break; - case 2: - svga->writemask = val & 0xf; - break; - case 3: - svga->charsetb = (((val >> 2) & 3) * 0x10000) + 2; - svga->charseta = ((val & 3) * 0x10000) + 2; - if (val & 0x10) - svga->charseta += 0x8000; - if (val & 0x20) - svga->charsetb += 0x8000; - break; - case 4: - svga->chain2_write = !(val & 4); - svga->chain4 = val & 8; - svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4; - break; - } - break; - case 0x3c6: - svga->dac_mask = val; - break; - case 0x3C7: - svga->dac_read = val; - svga->dac_pos = 0; - break; - case 0x3C8: - svga->dac_write = val; - svga->dac_read = val - 1; - svga->dac_pos = 0; - break; - case 0x3C9: - svga->dac_status = 0; - svga->fullchange = changeframecount; - switch (svga->dac_pos) - { - case 0: - svga->dac_r = val; - svga->dac_pos++; - break; - case 1: - svga->dac_g = val; - svga->dac_pos++; - break; - case 2: - svga->vgapal[svga->dac_write].r = svga->dac_r; - svga->vgapal[svga->dac_write].g = svga->dac_g; - svga->vgapal[svga->dac_write].b = val; - if (svga->ramdac_type == RAMDAC_8BIT) - svga->pallook[svga->dac_write] = makecol32(svga->vgapal[svga->dac_write].r, svga->vgapal[svga->dac_write].g, svga->vgapal[svga->dac_write].b); - else - svga->pallook[svga->dac_write] = makecol32(video_6to8[svga->vgapal[svga->dac_write].r & 0x3f], video_6to8[svga->vgapal[svga->dac_write].g & 0x3f], video_6to8[svga->vgapal[svga->dac_write].b & 0x3f]); - svga->dac_pos = 0; - svga->dac_write = (svga->dac_write + 1) & 255; - break; - } - break; - case 0x3CE: - svga->gdcaddr = val; - break; - case 0x3CF: - o = svga->gdcreg[svga->gdcaddr & 15]; - switch (svga->gdcaddr & 15) - { - case 2: svga->colourcompare=val; break; - case 4: svga->readplane=val&3; break; - case 5: - svga->writemode = val & 3; - svga->readmode = val & 8; - svga->chain2_read = val & 0x10; - break; - case 6: - if ((svga->gdcreg[6] & 0xc) != (val & 0xc)) - { - switch (val&0xC) - { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); - svga->banked_mask = 0xffff; - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0xffff; - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - svga->banked_mask = 0x7fff; - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - svga->banked_mask = 0x7fff; - break; - } - } - break; - case 7: svga->colournocare=val; break; - } - svga->gdcreg[svga->gdcaddr & 15] = val; - svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4; - if (((svga->gdcaddr & 15) == 5 && (val ^ o) & 0x70) || ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1)) - svga_recalctimings(svga); - break; - } -} - -uint8_t svga_in(uint16_t addr, void *p) -{ - svga_t *svga = (svga_t *)p; - uint8_t temp; - switch (addr) - { - case 0x3C0: - return svga->attraddr | svga->attr_palette_enable; - case 0x3C1: - return svga->attrregs[svga->attraddr]; - case 0x3c2: - if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) - temp = 0; - else - temp = 0x10; - return temp; - case 0x3C4: - return svga->seqaddr; - case 0x3C5: - return svga->seqregs[svga->seqaddr & 0xF]; - case 0x3c6: return svga->dac_mask; - case 0x3c7: return svga->dac_status; - case 0x3c8: return svga->dac_write; - case 0x3c9: - svga->dac_status = 3; - switch (svga->dac_pos) - { - case 0: - svga->dac_pos++; - if (svga->ramdac_type == RAMDAC_8BIT) - return svga->vgapal[svga->dac_read].r; - return svga->vgapal[svga->dac_read].r & 0x3f; - case 1: - svga->dac_pos++; - if (svga->ramdac_type == RAMDAC_8BIT) - return svga->vgapal[svga->dac_read].g; - return svga->vgapal[svga->dac_read].g & 0x3f; - case 2: - svga->dac_pos=0; - svga->dac_read = (svga->dac_read + 1) & 255; - if (svga->ramdac_type == RAMDAC_8BIT) - return svga->vgapal[(svga->dac_read - 1) & 255].b; - return svga->vgapal[(svga->dac_read - 1) & 255].b & 0x3f; - } - break; - case 0x3CC: - return svga->miscout; - case 0x3CE: - return svga->gdcaddr; - case 0x3CF: - /* The spec says GDC addresses 0xF8 to 0xFB return the latch. */ - if (svga->gdcaddr == 0xF8) return svga->la; - if (svga->gdcaddr == 0xF9) return svga->lb; - if (svga->gdcaddr == 0xFA) return svga->lc; - if (svga->gdcaddr == 0xFB) return svga->ld; - return svga->gdcreg[svga->gdcaddr & 0xf]; - case 0x3DA: - svga->attrff = 0; - svga->attrff = 0; - - if (svga->cgastat & 0x01) - svga->cgastat &= ~0x30; - else - svga->cgastat ^= 0x30; - return svga->cgastat; - } - return 0xFF; -} - -void svga_set_ramdac_type(svga_t *svga, int type) -{ - int c; - - if (svga->ramdac_type != type) - { - svga->ramdac_type = type; - - for (c = 0; c < 256; c++) - { - if (svga->ramdac_type == RAMDAC_8BIT) - svga->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b); - else - svga->pallook[c] = makecol32((svga->vgapal[c].r & 0x3f) * 4, (svga->vgapal[c].g & 0x3f) * 4, (svga->vgapal[c].b & 0x3f) * 4); - } - } -} - -void svga_recalctimings(svga_t *svga) -{ - double crtcconst; - double _dispontime, _dispofftime, disptime; - - svga->vtotal = svga->crtc[6]; - svga->dispend = svga->crtc[0x12]; - svga->vsyncstart = svga->crtc[0x10]; - svga->split = svga->crtc[0x18]; - svga->vblankstart = svga->crtc[0x15]; - - if (svga->crtc[7] & 1) svga->vtotal |= 0x100; - if (svga->crtc[7] & 32) svga->vtotal |= 0x200; - svga->vtotal += 2; - - if (svga->crtc[7] & 2) svga->dispend |= 0x100; - if (svga->crtc[7] & 64) svga->dispend |= 0x200; - svga->dispend++; - - if (svga->crtc[7] & 4) svga->vsyncstart |= 0x100; - if (svga->crtc[7] & 128) svga->vsyncstart |= 0x200; - svga->vsyncstart++; - - if (svga->crtc[7] & 0x10) svga->split|=0x100; - if (svga->crtc[9] & 0x40) svga->split|=0x200; - svga->split++; - - if (svga->crtc[7] & 0x08) svga->vblankstart |= 0x100; - if (svga->crtc[9] & 0x20) svga->vblankstart |= 0x200; - svga->vblankstart++; - - svga->hdisp = svga->crtc[1]; - svga->hdisp++; - - svga->htotal = svga->crtc[0]; - svga->htotal += 6; /*+6 is required for Tyrian*/ - - svga->rowoffset = svga->crtc[0x13]; - - svga->clock = (svga->vidclock) ? VGACONST2 : VGACONST1; - - svga->lowres = svga->attrregs[0x10] & 0x40; - - svga->interlace = 0; - - svga->ma_latch = (svga->crtc[0xc] << 8) | svga->crtc[0xd]; - - svga->hdisp_time = svga->hdisp; - svga->render = svga_render_blank; - if (!svga->scrblank && svga->attr_palette_enable) { - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - if (svga->seqregs[1] & 8) /*40 column*/ { - svga->render = svga_render_text_40; - svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; - } else { - svga->render = svga_render_text_80; - svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; - } - svga->hdisp_old = svga->hdisp; - } else { - svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; - svga->hdisp_old = svga->hdisp; - - switch (svga->gdcreg[5] & 0x60) { - case 0x00: - if (svga->seqregs[1] & 8) /*Low res (320)*/ - svga->render = svga_render_4bpp_lowres; - else - svga->render = svga_render_4bpp_highres; - break; - case 0x20: /*4 colours*/ - if (svga->seqregs[1] & 8) /*Low res (320)*/ - svga->render = svga_render_2bpp_lowres; - else - svga->render = svga_render_2bpp_highres; - break; - case 0x40: case 0x60: /*256+ colours*/ - switch (svga->bpp) { - case 8: - if (svga->lowres) - svga->render = svga_render_8bpp_lowres; - else - svga->render = svga_render_8bpp_highres; - break; - case 15: - if (svga->lowres) - svga->render = svga_render_15bpp_lowres; - else - svga->render = svga_render_15bpp_highres; - break; - case 16: - if (svga->lowres) - svga->render = svga_render_16bpp_lowres; - else - svga->render = svga_render_16bpp_highres; - break; - case 24: - if (svga->lowres) - svga->render = svga_render_24bpp_lowres; - else - svga->render = svga_render_24bpp_highres; - break; - case 32: - if (svga->lowres) - svga->render = svga_render_32bpp_lowres; - else - svga->render = svga_render_32bpp_highres; - break; - } - break; - } - } - } - - svga->linedbl = svga->crtc[9] & 0x80; - svga->rowcount = svga->crtc[9] & 31; - if (enable_overscan) { - overscan_y = (svga->rowcount + 1) << 1; - if (svga->seqregs[1] & 8) /*Low res (320)*/ - overscan_y <<= 1; - if (overscan_y < 16) - overscan_y = 16; - } - if (svga->recalctimings_ex) - svga->recalctimings_ex(svga); - - if (svga->vblankstart < svga->dispend) - svga->dispend = svga->vblankstart; - - crtcconst = (svga->seqregs[1] & 1) ? (svga->clock * 8.0) : (svga->clock * 9.0); - - disptime = svga->htotal; - _dispontime = svga->hdisp_time; - - if (svga->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; } - _dispofftime = disptime - _dispontime; - _dispontime *= crtcconst; - _dispofftime *= crtcconst; - - svga->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - svga->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); -} - -extern int cyc_total; -void svga_poll(void *p) -{ - svga_t *svga = (svga_t *)p; - int x; - - if (!svga->linepos) { - if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena) { - svga->hwcursor_on = 64 - svga->hwcursor_latch.yoff; - svga->hwcursor_oddeven = 0; - } - - if (svga->displine == svga->hwcursor_latch.y+1 && svga->hwcursor_latch.ena && svga->interlace) { - svga->hwcursor_on = 64 - (svga->hwcursor_latch.yoff + 1); - svga->hwcursor_oddeven = 1; - } - - if (svga->displine == svga->overlay_latch.y && svga->overlay_latch.ena) { - svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff; - svga->overlay_oddeven = 0; - } - if (svga->displine == svga->overlay_latch.y+1 && svga->overlay_latch.ena && svga->interlace) { - svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff; - svga->overlay_oddeven = 1; - } - - svga->vidtime += svga->dispofftime; - svga->cgastat |= 1; - svga->linepos = 1; - - if (svga->dispon) { - svga->hdisp_on=1; - - svga->ma &= svga->vram_display_mask; - if (svga->firstline == 2000) { - svga->firstline = svga->displine; - video_wait_for_buffer(); - } - - if (svga->hwcursor_on || svga->overlay_on) - svga->changedvram[svga->ma >> 12] = svga->changedvram[(svga->ma >> 12) + 1] = svga->interlace ? 3 : 2; - - if (!svga->override) - svga->render(svga); - - if (svga->overlay_on) { - if (!svga->override) - svga->overlay_draw(svga, svga->displine); - svga->overlay_on--; - if (svga->overlay_on && svga->interlace) - svga->overlay_on--; - } - - if (svga->hwcursor_on) { - if (!svga->override) - svga->hwcursor_draw(svga, svga->displine); - svga->hwcursor_on--; - if (svga->hwcursor_on && svga->interlace) - svga->hwcursor_on--; - } - - if (svga->lastline < svga->displine) - svga->lastline = svga->displine; - } - - svga->displine++; - if (svga->interlace) - svga->displine++; - if ((svga->cgastat & 8) && ((svga->displine & 15) == (svga->crtc[0x11] & 15)) && svga->vslines) - svga->cgastat &= ~8; - svga->vslines++; - if (svga->displine > 1500) - svga->displine = 0; - } else { - svga->vidtime += svga->dispontime; - - if (svga->dispon) - svga->cgastat &= ~1; - svga->hdisp_on = 0; - - svga->linepos = 0; - if (svga->sc == (svga->crtc[11] & 31)) - svga->con = 0; - if (svga->dispon) { - if (svga->linedbl && !svga->linecountff) { - svga->linecountff = 1; - svga->ma = svga->maback; - } else if (svga->sc == svga->rowcount) { - svga->linecountff = 0; - svga->sc = 0; - - svga->maback += (svga->rowoffset << 3); - if (svga->interlace) - svga->maback += (svga->rowoffset << 3); - svga->maback &= svga->vram_display_mask; - svga->ma = svga->maback; - } else { - svga->linecountff = 0; - svga->sc++; - svga->sc &= 31; - svga->ma = svga->maback; - } - } - svga->vc++; - svga->vc &= 2047; - - if (svga->vc == svga->split) { - svga->ma = svga->maback = 0; - if (svga->attrregs[0x10] & 0x20) - svga->scrollcache = 0; - } - if (svga->vc == svga->dispend) { - if (svga->vblank_start) - svga->vblank_start(svga); - svga->dispon=0; - if (svga->crtc[10] & 0x20) svga->cursoron = 0; - else svga->cursoron = svga->blink & 16; - if (!(svga->gdcreg[6] & 1) && !(svga->blink & 15)) - svga->fullchange = 2; - svga->blink++; - - for (x = 0; x < ((svga->vram_mask+1) >> 12); x++) { - if (svga->changedvram[x]) - svga->changedvram[x]--; - } - if (svga->fullchange) - svga->fullchange--; - } - if (svga->vc == svga->vsyncstart) { - int wx, wy; - svga->dispon=0; - svga->cgastat |= 8; - x = svga->hdisp; - - if (svga->interlace && !svga->oddeven) svga->lastline++; - if (svga->interlace && svga->oddeven) svga->firstline--; - - wx = x; - wy = svga->lastline - svga->firstline; - - if (!svga->override) - svga_doblit(svga->firstline_draw, svga->lastline_draw + 1, wx, wy, svga); - - svga->firstline = 2000; - svga->lastline = 0; - - svga->firstline_draw = 2000; - svga->lastline_draw = 0; - - svga->oddeven ^= 1; - - changeframecount = svga->interlace ? 3 : 2; - svga->vslines = 0; - - if (svga->interlace && svga->oddeven) svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1); - else svga->ma = svga->maback = svga->ma_latch; - svga->ca = (svga->crtc[0xe] << 8) | svga->crtc[0xf]; - - svga->ma <<= 2; - svga->maback <<= 2; - svga->ca <<= 2; - - svga->video_res_x = wx; - svga->video_res_y = wy + 1; - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - svga->video_res_x /= (svga->seqregs[1] & 1) ? 8 : 9; - svga->video_res_y /= (svga->crtc[9] & 31) + 1; - svga->video_bpp = 0; - } else { - if (svga->crtc[9] & 0x80) - svga->video_res_y /= 2; - if (!(svga->crtc[0x17] & 2)) - svga->video_res_y *= 4; - else if (!(svga->crtc[0x17] & 1)) - svga->video_res_y *= 2; - svga->video_res_y /= (svga->crtc[9] & 31) + 1; - if (svga->lowres) - svga->video_res_x /= 2; - - svga->video_bpp = svga->bpp; - } - } - if (svga->vc == svga->vtotal) { - svga->vc = 0; - svga->sc = svga->crtc[8] & 0x1f; - svga->dispon = 1; - svga->displine = (svga->interlace && svga->oddeven) ? 1 : 0; - svga->scrollcache = svga->attrregs[0x13] & 7; - svga->linecountff = 0; - - svga->hwcursor_on = 0; - svga->hwcursor_latch = svga->hwcursor; - - svga->overlay_on = 0; - svga->overlay_latch = svga->overlay; - } - if (svga->sc == (svga->crtc[10] & 31)) - svga->con = 1; - } -} - -int svga_init(svga_t *svga, void *p, int memsize, - void (*recalctimings_ex)(struct svga_t *svga), - uint8_t (*video_in) (uint16_t addr, void *p), - void (*video_out)(uint16_t addr, uint8_t val, void *p), - void (*hwcursor_draw)(struct svga_t *svga, int displine), - void (*overlay_draw)(struct svga_t *svga, int displine)) -{ - int c, d, e; - - svga->p = p; - - for (c = 0; c < 256; c++) { - e = c; - for (d = 0; d < 8; d++) { - svga_rotate[d][c] = e; - e = (e >> 1) | ((e & 1) ? 0x80 : 0); - } - } - svga->readmode = 0; - - svga->attrregs[0x11] = 0; - svga->overscan_color = 0x000000; - - overscan_x = 16; - overscan_y = 32; - - svga->crtc[0] = 63; - svga->crtc[6] = 255; - svga->dispontime = 1000 * (1 << TIMER_SHIFT); - svga->dispofftime = 1000 * (1 << TIMER_SHIFT); - svga->bpp = 8; - svga->vram = malloc(memsize); - svga->vram_max = memsize; - svga->vram_display_mask = memsize - 1; - svga->vram_mask = memsize - 1; - svga->decode_mask = 0x7fffff; - svga->changedvram = malloc(/*(memsize >> 12) << 1*/0x800000 >> 12); - svga->recalctimings_ex = recalctimings_ex; - svga->video_in = video_in; - svga->video_out = video_out; - svga->hwcursor_draw = hwcursor_draw; - svga->overlay_draw = overlay_draw; - - mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL, MEM_MAPPING_EXTERNAL, svga); - - timer_add(svga_poll, &svga->vidtime, TIMER_ALWAYS_ENABLED, svga); - - svga_pri = svga; - - svga->ramdac_type = RAMDAC_6BIT; - - return 0; -} - -void svga_close(svga_t *svga) -{ - free(svga->changedvram); - free(svga->vram); - - svga_pri = NULL; -} - -void svga_write(uint32_t addr, uint8_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - uint8_t vala, valb, valc, vald, wm = svga->writemask; - int writemask2 = svga->writemask; - - egawrites++; - - cycles -= video_timing_write_b; - cycles_lost += video_timing_write_b; - - if (svga_output) pclog("Writeega %06X ",addr); - addr &= svga->banked_mask; - addr += svga->write_bank; - - if (!(svga->gdcreg[6] & 1)) svga->fullchange=2; - if (svga->chain4 || svga->fb_only) - { - writemask2=1<<(addr&3); - addr&=~3; - } - else if (svga->chain2_write) - { - writemask2 &= ~0xa; - if (addr & 1) - writemask2 <<= 1; - addr &= ~1; - addr <<= 2; - } - else - { - addr<<=2; - } - addr &= svga->decode_mask; - - if (addr >= svga->vram_max) - return; - - addr &= svga->vram_mask; - - if (svga_output) pclog("%08X (%i, %i) %02X %i %i %i %02X\n", addr, addr & 1023, addr >> 10, val, writemask2, svga->writemode, svga->chain4, svga->gdcreg[8]); - svga->changedvram[addr >> 12] = changeframecount; - - switch (svga->writemode) - { - case 1: - if (writemask2 & 1) svga->vram[addr] = svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld; - break; - case 0: - if (svga->gdcreg[3] & 7) - val = svga_rotate[svga->gdcreg[3] & 7][val]; - if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) - { - if (writemask2 & 1) svga->vram[addr] = val; - if (writemask2 & 2) svga->vram[addr | 0x1] = val; - if (writemask2 & 4) svga->vram[addr | 0x2] = val; - if (writemask2 & 8) svga->vram[addr | 0x3] = val; - } - else - { - if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0; - else vala = val; - if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0; - else valb = val; - if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0; - else valc = val; - if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0; - else vald = val; - - switch (svga->gdcreg[3] & 0x18) - { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } -// pclog("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); - } - break; - case 2: - if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) - { - if (writemask2 & 1) svga->vram[addr] = (((val & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - } - else - { - vala = ((val & 1) ? 0xff : 0); - valb = ((val & 2) ? 0xff : 0); - valc = ((val & 4) ? 0xff : 0); - vald = ((val & 8) ? 0xff : 0); - switch (svga->gdcreg[3] & 0x18) - { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } - } - break; - case 3: - if (svga->gdcreg[3] & 7) - val = svga_rotate[svga->gdcreg[3] & 7][val]; - wm = svga->gdcreg[8]; - svga->gdcreg[8] &= val; - - vala = (svga->gdcreg[0] & 1) ? 0xff : 0; - valb = (svga->gdcreg[0] & 2) ? 0xff : 0; - valc = (svga->gdcreg[0] & 4) ? 0xff : 0; - vald = (svga->gdcreg[0] & 8) ? 0xff : 0; - switch (svga->gdcreg[3] & 0x18) - { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } - svga->gdcreg[8] = wm; - break; - } -} - -uint8_t svga_read(uint32_t addr, void *p) -{ - svga_t *svga = (svga_t *)p; - uint8_t temp, temp2, temp3, temp4; - uint32_t latch_addr; - int readplane = svga->readplane; - - cycles -= video_timing_read_b; - cycles_lost += video_timing_read_b; - - egareads++; -// pclog("Readega %06X ",addr); - - addr &= svga->banked_mask; - addr += svga->read_bank; - - latch_addr = (addr << 2) & svga->decode_mask; - -// pclog("%05X %i %04X:%04X %02X %02X %i\n",addr,svga->chain4,CS,pc, vram[addr & 0x7fffff], vram[(addr << 2) & 0x7fffff], svga->readmode); -// pclog("%i\n", svga->readmode); - if (svga->chain4 || svga->fb_only) - { - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xff; - return svga->vram[addr & svga->vram_mask]; - } - else if (svga->chain2_read) - { - readplane = (readplane & 2) | (addr & 1); - addr &= ~1; - addr <<= 2; - } - else - addr<<=2; - - addr &= svga->decode_mask; - - if (latch_addr >= svga->vram_max) - { - svga->la = svga->lb = svga->lc = svga->ld = 0xff; - } - else - { - latch_addr &= svga->vram_mask; - svga->la = svga->vram[latch_addr]; - svga->lb = svga->vram[latch_addr | 0x1]; - svga->lc = svga->vram[latch_addr | 0x2]; - svga->ld = svga->vram[latch_addr | 0x3]; - } - - if (addr >= svga->vram_max) - return 0xff; - - addr &= svga->vram_mask; - - if (svga->readmode) - { - temp = svga->la; - temp ^= (svga->colourcompare & 1) ? 0xff : 0; - temp &= (svga->colournocare & 1) ? 0xff : 0; - temp2 = svga->lb; - temp2 ^= (svga->colourcompare & 2) ? 0xff : 0; - temp2 &= (svga->colournocare & 2) ? 0xff : 0; - temp3 = svga->lc; - temp3 ^= (svga->colourcompare & 4) ? 0xff : 0; - temp3 &= (svga->colournocare & 4) ? 0xff : 0; - temp4 = svga->ld; - temp4 ^= (svga->colourcompare & 8) ? 0xff : 0; - temp4 &= (svga->colournocare & 8) ? 0xff : 0; - return ~(temp | temp2 | temp3 | temp4); - } -//pclog("Read %02X %04X %04X\n",vram[addr|svga->readplane],addr,svga->readplane); - - return svga->vram[addr | readplane]; -} - -void svga_write_linear(uint32_t addr, uint8_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - uint8_t vala, valb, valc, vald, wm = svga->writemask; - int writemask2 = svga->writemask; - - cycles -= video_timing_write_b; - cycles_lost += video_timing_write_b; - - egawrites++; - - if (svga_output) pclog("Write LFB %08X %02X ", addr, val); - if (!(svga->gdcreg[6] & 1)) - svga->fullchange = 2; - if (svga->chain4 || svga->fb_only) - { - writemask2=1<<(addr&3); - addr&=~3; - } - else if (svga->chain2_write) - { - writemask2 &= ~0xa; - if (addr & 1) - writemask2 <<= 1; - addr &= ~1; - addr <<= 2; - } - else - { - addr<<=2; - } - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - if (svga_output) pclog("%08X\n", addr); - svga->changedvram[addr >> 12]=changeframecount; - - switch (svga->writemode) - { - case 1: - if (writemask2 & 1) svga->vram[addr] = svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld; - break; - case 0: - if (svga->gdcreg[3] & 7) - val = svga_rotate[svga->gdcreg[3] & 7][val]; - if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) - { - if (writemask2 & 1) svga->vram[addr] = val; - if (writemask2 & 2) svga->vram[addr | 0x1] = val; - if (writemask2 & 4) svga->vram[addr | 0x2] = val; - if (writemask2 & 8) svga->vram[addr | 0x3] = val; - } - else - { - if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0; - else vala = val; - if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0; - else valb = val; - if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0; - else valc = val; - if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0; - else vald = val; - - switch (svga->gdcreg[3] & 0x18) - { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } -// pclog("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); - } - break; - case 2: - if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) - { - if (writemask2 & 1) svga->vram[addr] = (((val & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - } - else - { - vala = ((val & 1) ? 0xff : 0); - valb = ((val & 2) ? 0xff : 0); - valc = ((val & 4) ? 0xff : 0); - vald = ((val & 8) ? 0xff : 0); - switch (svga->gdcreg[3] & 0x18) - { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } - } - break; - case 3: - if (svga->gdcreg[3] & 7) - val = svga_rotate[svga->gdcreg[3] & 7][val]; - wm = svga->gdcreg[8]; - svga->gdcreg[8] &= val; - - vala = (svga->gdcreg[0] & 1) ? 0xff : 0; - valb = (svga->gdcreg[0] & 2) ? 0xff : 0; - valc = (svga->gdcreg[0] & 4) ? 0xff : 0; - vald = (svga->gdcreg[0] & 8) ? 0xff : 0; - switch (svga->gdcreg[3] & 0x18) - { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } - svga->gdcreg[8] = wm; - break; - } -} - -uint8_t svga_read_linear(uint32_t addr, void *p) -{ - svga_t *svga = (svga_t *)p; - uint8_t temp, temp2, temp3, temp4; - int readplane = svga->readplane; - - cycles -= video_timing_read_b; - cycles_lost += video_timing_read_b; - - egareads++; - - if (svga->chain4 || svga->fb_only) - { - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xff; - return svga->vram[addr & svga->vram_mask]; - } - else if (svga->chain2_read) - { - readplane = (readplane & 2) | (addr & 1); - addr &= ~1; - addr <<= 2; - } - else - addr<<=2; - - addr &= svga->decode_mask; - - if (addr >= svga->vram_max) - return 0xff; - - addr &= svga->vram_mask; - - svga->la = svga->vram[addr]; - svga->lb = svga->vram[addr | 0x1]; - svga->lc = svga->vram[addr | 0x2]; - svga->ld = svga->vram[addr | 0x3]; - if (svga->readmode) - { - temp = svga->la; - temp ^= (svga->colourcompare & 1) ? 0xff : 0; - temp &= (svga->colournocare & 1) ? 0xff : 0; - temp2 = svga->lb; - temp2 ^= (svga->colourcompare & 2) ? 0xff : 0; - temp2 &= (svga->colournocare & 2) ? 0xff : 0; - temp3 = svga->lc; - temp3 ^= (svga->colourcompare & 4) ? 0xff : 0; - temp3 &= (svga->colournocare & 4) ? 0xff : 0; - temp4 = svga->ld; - temp4 ^= (svga->colourcompare & 8) ? 0xff : 0; - temp4 &= (svga->colournocare & 8) ? 0xff : 0; - return ~(temp | temp2 | temp3 | temp4); - } - return svga->vram[addr | readplane]; -} - -void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) -{ - int y_add = (enable_overscan) ? overscan_y : 0; - int x_add = (enable_overscan) ? 16 : 0; - uint32_t *p, i, j; - - svga->frames++; - - if ((xsize > 2032) || (ysize > 2032)) { - x_add = 0; - y_add = 0; - suppress_overscan = 1; - } else - suppress_overscan = 0; - - if (y1 > y2) { - video_blit_memtoscreen(32, 0, 0, 0, xsize + x_add, ysize + y_add); - return; - } - - if ((wx != xsize) || ((wy + 1) != ysize) || video_force_resize_get()) { - /* Screen res has changed.. fix up, and let them know. */ - xsize = wx; - ysize = wy+1; - if (xsize<64) xsize = 640; - if (ysize<32) ysize = 200; - - set_screen_size(xsize+x_add,ysize+y_add); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - - if (enable_overscan && !suppress_overscan) { - if ((wx >= 160) && ((wy + 1) >= 120)) { - /* Draw (overscan_size - scroll size) lines of overscan on top. */ - for (i = 0; i < (y_add >> 1); i++) { - p = &((uint32_t *)buffer32->line[i & 0x7ff])[32]; - - for (j = 0; j < (xsize + x_add); j++) - p[j] = svga_color_transform(svga->overscan_color); - } - - /* Draw (overscan_size + scroll size) lines of overscan on the bottom. */ - for (i = 0; i < (y_add >> 1); i++) { - p = &((uint32_t *)buffer32->line[(ysize + (y_add >> 1) + i) & 0x7ff])[32]; - - for (j = 0; j < (xsize + x_add); j++) - p[j] = svga_color_transform(svga->overscan_color); - } - - for (i = (y_add >> 1); i < (ysize + (y_add >> 1)); i ++) { - p = &((uint32_t *)buffer32->line[i & 0x7ff])[32]; - - for (j = 0; j < 8; j++) { - p[j] = svga->pallook[svga->overscan_color]; - p[xsize + (x_add >> 1) + j] = svga_color_transform(svga->overscan_color); + svga->attrregs[svga->attraddr & 31] = val; + if (svga->attraddr < 16) + svga->fullchange = changeframecount; + if (svga->attraddr == 0x10 || svga->attraddr == 0x14 || svga->attraddr < 0x10) { + for (c = 0; c < 16; c++) { + if (svga->attrregs[0x10] & 0x80) { + svga->egapal[c] = (svga->attrregs[c] & 0xf) | + ((svga->attrregs[0x14] & 0xf) << 4); + } else { + svga->egapal[c] = (svga->attrregs[c] & 0x3f) | + ((svga->attrregs[0x14] & 0xc) << 4); + } } } + /* Recalculate timings on change of attribute register 0x11 + (overscan border color) too. */ + if (svga->attraddr == 0x10) { + if (o != val) + svga_recalctimings(svga); + } else if (svga->attraddr == 0x11) { + svga->overscan_color = svga->pallook[svga->attrregs[0x11]]; + if (o != val) + svga_recalctimings(svga); + } else if (svga->attraddr == 0x12) { + if ((val & 0xf) != svga->plane_mask) + svga->fullchange = changeframecount; + svga->plane_mask = val & 0xf; + } + } + svga->attrff ^= 1; + break; + case 0x3c2: + svga->miscout = val; + svga->vidclock = val & 4; + io_removehandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->p); + if (!(val & 1)) + io_sethandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->p); + svga_recalctimings(svga); + break; + case 0x3c4: + svga->seqaddr = val; + break; + case 0x3c5: + if (svga->seqaddr > 0xf) + return; + o = svga->seqregs[svga->seqaddr & 0xf]; + svga->seqregs[svga->seqaddr & 0xf] = val; + if (o != val && (svga->seqaddr & 0xf) == 1) + svga_recalctimings(svga); + switch (svga->seqaddr & 0xf) { + case 1: + if (svga->scrblank && !(val & 0x20)) + svga->fullchange = 3; + svga->scrblank = (svga->scrblank & ~0x20) | (val & 0x20); + svga_recalctimings(svga); + break; + case 2: + svga->writemask = val & 0xf; + break; + case 3: + svga->charsetb = (((val >> 2) & 3) * 0x10000) + 2; + svga->charseta = ((val & 3) * 0x10000) + 2; + if (val & 0x10) + svga->charseta += 0x8000; + if (val & 0x20) + svga->charsetb += 0x8000; + break; + case 4: + svga->chain2_write = !(val & 4); + svga->chain4 = val & 8; + svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && + !svga->gdcreg[1]) && svga->chain4; + break; + } + break; + case 0x3c6: + svga->dac_mask = val; + break; + case 0x3C7: + svga->dac_read = val; + svga->dac_pos = 0; + break; + case 0x3c8: + svga->dac_write = val; + svga->dac_read = val - 1; + svga->dac_pos = 0; + break; + case 0x3c9: + svga->dac_status = 0; + svga->fullchange = changeframecount; + switch (svga->dac_pos) { + case 0: + svga->dac_r = val; + svga->dac_pos++; + break; + case 1: + svga->dac_g = val; + svga->dac_pos++; + break; + case 2: + svga->vgapal[svga->dac_write].r = svga->dac_r; + svga->vgapal[svga->dac_write].g = svga->dac_g; + svga->vgapal[svga->dac_write].b = val; + if (svga->ramdac_type == RAMDAC_8BIT) + svga->pallook[svga->dac_write] = makecol32(svga->vgapal[svga->dac_write].r, svga->vgapal[svga->dac_write].g, svga->vgapal[svga->dac_write].b); + else + svga->pallook[svga->dac_write] = makecol32(video_6to8[svga->vgapal[svga->dac_write].r & 0x3f], video_6to8[svga->vgapal[svga->dac_write].g & 0x3f], video_6to8[svga->vgapal[svga->dac_write].b & 0x3f]); + svga->dac_pos = 0; + svga->dac_write = (svga->dac_write + 1) & 255; + break; + } + break; + case 0x3ce: + svga->gdcaddr = val; + break; + case 0x3cf: + o = svga->gdcreg[svga->gdcaddr & 15]; + switch (svga->gdcaddr & 15) { + case 2: + svga->colourcompare=val; + break; + case 4: + svga->readplane = val & 3; + break; + case 5: + svga->writemode = val & 3; + svga->readmode = val & 8; + svga->chain2_read = val & 0x10; + break; + case 6: + if ((svga->gdcreg[6] & 0xc) != (val & 0xc)) { + switch (val&0xC) { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + svga->banked_mask = 0xffff; + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; + break; + } + } + break; + case 7: + svga->colournocare=val; + break; + } + svga->gdcreg[svga->gdcaddr & 15] = val; + svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && + !svga->gdcreg[1]) && svga->chain4; + if (((svga->gdcaddr & 15) == 5 && (val ^ o) & 0x70) || + ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1)) + svga_recalctimings(svga); + break; + } +} + + +uint8_t +svga_in(uint16_t addr, void *p) +{ + svga_t *svga = (svga_t *)p; + uint8_t ret = 0xff; + + switch (addr) { + case 0x3c0: + ret = svga->attraddr | svga->attr_palette_enable; + break; + case 0x3c1: + ret = svga->attrregs[svga->attraddr]; + break; + case 0x3c2: + if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) + ret = 0; + else + ret = 0x10; + break; + case 0x3c4: + ret = svga->seqaddr; + break; + case 0x3c5: + ret = svga->seqregs[svga->seqaddr & 0x0f]; + break; + case 0x3c6: + ret = svga->dac_mask; + break; + case 0x3c7: + ret = svga->dac_status; + break; + case 0x3c8: + ret = svga->dac_write; + break; + case 0x3c9: + svga->dac_status = 3; + switch (svga->dac_pos) { + case 0: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + ret = svga->vgapal[svga->dac_read].r; + else + ret = svga->vgapal[svga->dac_read].r & 0x3f; + break; + case 1: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + ret = svga->vgapal[svga->dac_read].g; + else + ret = svga->vgapal[svga->dac_read].g & 0x3f; + break; + case 2: + svga->dac_pos=0; + svga->dac_read = (svga->dac_read + 1) & 255; + if (svga->ramdac_type == RAMDAC_8BIT) + ret = svga->vgapal[(svga->dac_read - 1) & 255].b; + else + ret = svga->vgapal[(svga->dac_read - 1) & 255].b & 0x3f; + break; + } + break; + case 0x3cc: + ret = svga->miscout; + break; + case 0x3ce: + ret = svga->gdcaddr; + break; + case 0x3cf: + /* The spec says GDC addresses 0xF8 to 0xFB return the latch. */ + switch(svga->gdcaddr) { + case 0xf8: + ret = (svga->latch & 0xFF); + break; + case 0xf9: + ret = ((svga->latch & 0xFF00) >> 8); + break; + case 0xfa: + ret = ((svga->latch & 0xFF0000) >> 16); + break; + case 0xfb: + ret = ((svga->latch & 0xFF000000) >> 24); + break; + default: + ret = svga->gdcreg[svga->gdcaddr & 0xf]; + break; + } + break; + case 0x3da: + svga->attrff = 0; + svga->attrff = 0; + + if (svga->cgastat & 0x01) + svga->cgastat &= ~0x30; + else + svga->cgastat ^= 0x30; + ret = svga->cgastat; + break; + } + + return(ret); +} + + +void +svga_set_ramdac_type(svga_t *svga, int type) +{ + int c; + + if (svga->ramdac_type != type) { + svga->ramdac_type = type; + + for (c = 0; c < 256; c++) { + if (svga->ramdac_type == RAMDAC_8BIT) + svga->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b); + else + svga->pallook[c] = makecol32((svga->vgapal[c].r & 0x3f) * 4, + (svga->vgapal[c].g & 0x3f) * 4, + (svga->vgapal[c].b & 0x3f) * 4); + } + } +} + + +void +svga_recalctimings(svga_t *svga) +{ + double crtcconst, _dispontime, _dispofftime, disptime; + + svga->vtotal = svga->crtc[6]; + svga->dispend = svga->crtc[0x12]; + svga->vsyncstart = svga->crtc[0x10]; + svga->split = svga->crtc[0x18]; + svga->vblankstart = svga->crtc[0x15]; + + if (svga->crtc[7] & 1) + svga->vtotal |= 0x100; + if (svga->crtc[7] & 32) + svga->vtotal |= 0x200; + svga->vtotal += 2; + + if (svga->crtc[7] & 2) + svga->dispend |= 0x100; + if (svga->crtc[7] & 64) + svga->dispend |= 0x200; + svga->dispend++; + + if (svga->crtc[7] & 4) + svga->vsyncstart |= 0x100; + if (svga->crtc[7] & 128) + svga->vsyncstart |= 0x200; + svga->vsyncstart++; + + if (svga->crtc[7] & 0x10) + svga->split|=0x100; + if (svga->crtc[9] & 0x40) + svga->split|=0x200; + svga->split++; + + if (svga->crtc[7] & 0x08) + svga->vblankstart |= 0x100; + if (svga->crtc[9] & 0x20) + svga->vblankstart |= 0x200; + svga->vblankstart++; + + svga->hdisp = svga->crtc[1]; + svga->hdisp++; + + svga->htotal = svga->crtc[0]; + svga->htotal += 6; /*+6 is required for Tyrian*/ + + svga->rowoffset = svga->crtc[0x13]; + + svga->clock = (svga->vidclock) ? VGACONST2 : VGACONST1; + + svga->lowres = svga->attrregs[0x10] & 0x40; + + svga->interlace = 0; + + svga->ma_latch = (svga->crtc[0xc] << 8) | svga->crtc[0xd]; + + svga->hdisp_time = svga->hdisp; + svga->render = svga_render_blank; + if (!svga->scrblank && svga->attr_palette_enable) { + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + if (svga->seqregs[1] & 8) /*40 column*/ { + svga->render = svga_render_text_40; + svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; + } else { + svga->render = svga_render_text_80; + svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; + } + svga->hdisp_old = svga->hdisp; + } else { + svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; + svga->hdisp_old = svga->hdisp; + + switch (svga->gdcreg[5] & 0x60) { + case 0x00: + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_4bpp_lowres; + else + svga->render = svga_render_4bpp_highres; + break; + case 0x20: /*4 colours*/ + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_2bpp_lowres; + else + svga->render = svga_render_2bpp_highres; + break; + case 0x40: case 0x60: /*256+ colours*/ + switch (svga->bpp) { + case 8: + if (svga->lowres) + svga->render = svga_render_8bpp_lowres; + else + svga->render = svga_render_8bpp_highres; + break; + case 15: + if (svga->lowres) + svga->render = svga_render_15bpp_lowres; + else + svga->render = svga_render_15bpp_highres; + break; + case 16: + if (svga->lowres) + svga->render = svga_render_16bpp_lowres; + else + svga->render = svga_render_16bpp_highres; + break; + case 24: + if (svga->lowres) + svga->render = svga_render_24bpp_lowres; + else + svga->render = svga_render_24bpp_highres; + break; + case 32: + if (svga->lowres) + svga->render = svga_render_32bpp_lowres; + else + svga->render = svga_render_32bpp_highres; + break; + } + break; + } + } + } + + svga->linedbl = svga->crtc[9] & 0x80; + svga->rowcount = svga->crtc[9] & 31; + if (enable_overscan) { + overscan_y = (svga->rowcount + 1) << 1; + if (svga->seqregs[1] & 8) /*Low res (320)*/ + overscan_y <<= 1; + if (overscan_y < 16) + overscan_y = 16; + } + if (svga->recalctimings_ex) + svga->recalctimings_ex(svga); + + if (svga->vblankstart < svga->dispend) + svga->dispend = svga->vblankstart; + + crtcconst = (svga->seqregs[1] & 1) ? (svga->clock * 8.0) : (svga->clock * 9.0); + + disptime = svga->htotal; + _dispontime = svga->hdisp_time; + + if (svga->seqregs[1] & 8) { + disptime *= 2; + _dispontime *= 2; + } + _dispofftime = disptime - _dispontime; + _dispontime *= crtcconst; + _dispofftime *= crtcconst; + + svga->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); + svga->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); +} + + +void +svga_poll(void *p) +{ + svga_t *svga = (svga_t *)p; + uint32_t x; + int wx, wy; + + if (!svga->linepos) { + if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena) { + svga->hwcursor_on = 64 - svga->hwcursor_latch.yoff; + svga->hwcursor_oddeven = 0; + } + + if (svga->displine == (svga->hwcursor_latch.y + 1) && svga->hwcursor_latch.ena && + svga->interlace) { + svga->hwcursor_on = 64 - (svga->hwcursor_latch.yoff + 1); + svga->hwcursor_oddeven = 1; + } + + if (svga->displine == svga->overlay_latch.y && svga->overlay_latch.ena) { + svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff; + svga->overlay_oddeven = 0; + } + + if (svga->displine == svga->overlay_latch.y+1 && svga->overlay_latch.ena && svga->interlace) { + svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff; + svga->overlay_oddeven = 1; + } + + svga->vidtime += svga->dispofftime; + svga->cgastat |= 1; + svga->linepos = 1; + + if (svga->dispon) { + svga->hdisp_on=1; + + svga->ma &= svga->vram_display_mask; + if (svga->firstline == 2000) { + svga->firstline = svga->displine; + video_wait_for_buffer(); + } + + if (svga->hwcursor_on || svga->overlay_on) { + svga->changedvram[svga->ma >> 12] = svga->changedvram[(svga->ma >> 12) + 1] = + svga->interlace ? 3 : 2; + } + + if (!svga->override) + svga->render(svga); + + if (svga->overlay_on) { + if (!svga->override) + svga->overlay_draw(svga, svga->displine); + svga->overlay_on--; + if (svga->overlay_on && svga->interlace) + svga->overlay_on--; + } + + if (svga->hwcursor_on) { + if (!svga->override) + svga->hwcursor_draw(svga, svga->displine); + svga->hwcursor_on--; + if (svga->hwcursor_on && svga->interlace) + svga->hwcursor_on--; + } + + if (svga->lastline < svga->displine) + svga->lastline = svga->displine; + } + + svga->displine++; + if (svga->interlace) + svga->displine++; + if ((svga->cgastat & 8) && ((svga->displine & 15) == (svga->crtc[0x11] & 15)) && svga->vslines) + svga->cgastat &= ~8; + svga->vslines++; + if (svga->displine > 1500) + svga->displine = 0; + } else { + svga->vidtime += svga->dispontime; + + if (svga->dispon) + svga->cgastat &= ~1; + svga->hdisp_on = 0; + + svga->linepos = 0; + if (svga->sc == (svga->crtc[11] & 31)) + svga->con = 0; + if (svga->dispon) { + if (svga->linedbl && !svga->linecountff) { + svga->linecountff = 1; + svga->ma = svga->maback; + } else if (svga->sc == svga->rowcount) { + svga->linecountff = 0; + svga->sc = 0; + + svga->maback += (svga->rowoffset << 3); + if (svga->interlace) + svga->maback += (svga->rowoffset << 3); + svga->maback &= svga->vram_display_mask; + svga->ma = svga->maback; + } else { + svga->linecountff = 0; + svga->sc++; + svga->sc &= 31; + svga->ma = svga->maback; + } + } + svga->vc++; + svga->vc &= 2047; + + if (svga->vc == svga->split) { + svga->ma = svga->maback = 0; + if (svga->attrregs[0x10] & 0x20) + svga->scrollcache = 0; + } + if (svga->vc == svga->dispend) { + if (svga->vblank_start) + svga->vblank_start(svga); + svga->dispon=0; + if (svga->crtc[10] & 0x20) + svga->cursoron = 0; + else + svga->cursoron = svga->blink & 16; + + if (!(svga->gdcreg[6] & 1) && !(svga->blink & 15)) + svga->fullchange = 2; + svga->blink++; + + for (x = 0; x < ((svga->vram_mask + 1) >> 12); x++) { + if (svga->changedvram[x]) + svga->changedvram[x]--; + } + if (svga->fullchange) + svga->fullchange--; + } + if (svga->vc == svga->vsyncstart) { + svga->dispon = 0; + svga->cgastat |= 8; + x = svga->hdisp; + + if (svga->interlace && !svga->oddeven) + svga->lastline++; + if (svga->interlace && svga->oddeven) + svga->firstline--; + + wx = x; + wy = svga->lastline - svga->firstline; + + if (!svga->override) + svga_doblit(svga->firstline_draw, svga->lastline_draw + 1, wx, wy, svga); + + svga->firstline = 2000; + svga->lastline = 0; + + svga->firstline_draw = 2000; + svga->lastline_draw = 0; + + svga->oddeven ^= 1; + + changeframecount = svga->interlace ? 3 : 2; + svga->vslines = 0; + + if (svga->interlace && svga->oddeven) + svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1); + else + svga->ma = svga->maback = svga->ma_latch; + svga->ca = (svga->crtc[0xe] << 8) | svga->crtc[0xf]; + + svga->ma <<= 2; + svga->maback <<= 2; + svga->ca <<= 2; + + svga->video_res_x = wx; + svga->video_res_y = wy + 1; + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + svga->video_res_x /= (svga->seqregs[1] & 1) ? 8 : 9; + svga->video_res_y /= (svga->crtc[9] & 31) + 1; + svga->video_bpp = 0; + } else { + if (svga->crtc[9] & 0x80) + svga->video_res_y /= 2; + if (!(svga->crtc[0x17] & 2)) + svga->video_res_y *= 4; + else if (!(svga->crtc[0x17] & 1)) + svga->video_res_y *= 2; + svga->video_res_y /= (svga->crtc[9] & 31) + 1; + if (svga->lowres) + svga->video_res_x /= 2; + + svga->video_bpp = svga->bpp; + } + } + if (svga->vc == svga->vtotal) { + svga->vc = 0; + svga->sc = svga->crtc[8] & 0x1f; + svga->dispon = 1; + svga->displine = (svga->interlace && svga->oddeven) ? 1 : 0; + svga->scrollcache = svga->attrregs[0x13] & 7; + svga->linecountff = 0; + + svga->hwcursor_on = 0; + svga->hwcursor_latch = svga->hwcursor; + + svga->overlay_on = 0; + svga->overlay_latch = svga->overlay; + } + if (svga->sc == (svga->crtc[10] & 31)) + svga->con = 1; + } +} + + +int +svga_init(svga_t *svga, void *p, int memsize, + void (*recalctimings_ex)(struct svga_t *svga), + uint8_t (*video_in) (uint16_t addr, void *p), + void (*video_out)(uint16_t addr, uint8_t val, void *p), + void (*hwcursor_draw)(struct svga_t *svga, int displine), + void (*overlay_draw)(struct svga_t *svga, int displine)) +{ + int c, d, e; + + svga->p = p; + + for (c = 0; c < 256; c++) { + e = c; + for (d = 0; d < 8; d++) { + svga_rotate[d][c] = e; + e = (e >> 1) | ((e & 1) ? 0x80 : 0); + } + } + svga->readmode = 0; + + svga->attrregs[0x11] = 0; + svga->overscan_color = 0x000000; + + overscan_x = 16; + overscan_y = 32; + + svga->crtc[0] = 63; + svga->crtc[6] = 255; + svga->dispontime = svga->dispofftime = 1000 * (1 << TIMER_SHIFT); + svga->bpp = 8; + svga->vram = malloc(memsize); + svga->vram_max = memsize; + svga->vram_display_mask = svga->vram_mask = memsize - 1; + svga->decode_mask = 0x7fffff; + svga->changedvram = malloc(memsize >> 12); + svga->recalctimings_ex = recalctimings_ex; + svga->video_in = video_in; + svga->video_out = video_out; + svga->hwcursor_draw = hwcursor_draw; + svga->overlay_draw = overlay_draw; + + mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, + svga_read, svga_readw, svga_readl, + svga_write, svga_writew, svga_writel, + NULL, MEM_MAPPING_EXTERNAL, svga); + + timer_add(svga_poll, &svga->vidtime, TIMER_ALWAYS_ENABLED, svga); + + svga_pri = svga; + + svga->ramdac_type = RAMDAC_6BIT; + + return 0; +} + + +void +svga_close(svga_t *svga) +{ + free(svga->changedvram); + free(svga->vram); + + svga_pri = NULL; +} + + +void +svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *p) +{ + svga_t *svga = (svga_t *)p; + + int func_select, writemask2 = svga->writemask; + uint32_t write_mask, bit_mask, set_mask, val32 = (uint32_t) val; + + egawrites++; + + cycles -= video_timing_write_b; + + if (!linear) { + addr &= svga->banked_mask; + addr += svga->write_bank; + } + + if (!(svga->gdcreg[6] & 1)) + svga->fullchange = 2; + + if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4)) { + writemask2 = 1 << (addr & 3); + addr &= ~3; + } else if (svga->chain2_write) { + writemask2 &= ~0xa; + if (addr & 1) + writemask2 <<= 1; + addr &= ~1; + addr <<= 2; + } else + addr <<= 2; + addr &= svga->decode_mask; + + if (addr >= svga->vram_max) + return; + + addr &= svga->vram_mask; + + svga->changedvram[addr >> 12] = changeframecount; + + /* standard VGA latched access */ + func_select = (svga->gdcreg[3] >> 3) & 3; + + switch (svga->writemode) { + case 0: + /* rotate */ + if (svga->gdcreg[3] & 7) + val32 = svga_rotate[svga->gdcreg[3] & 7][val32]; + + /* apply set/reset mask */ + bit_mask = svga->gdcreg[8]; + + val32 |= (val32 << 8); + val32 |= (val32 << 16); + + if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && + (!svga->gdcreg[1] || svga->set_reset_disabled)) { + /* mask data according to sr[2] */ + write_mask = mask16[writemask2 & 0x0f]; + addr >>= 2; + ((uint32_t *)(svga->vram))[addr] &= ~write_mask; + ((uint32_t *)(svga->vram))[addr] |= (val32 & write_mask); + return; + } + + set_mask = mask16[svga->gdcreg[1] & 0x0f]; + val32 = (val32 & ~set_mask) | (mask16[svga->gdcreg[0] & 0x0f] & set_mask); + break; + case 1: + val32 = svga->latch; + + /* mask data according to sr[2] */ + write_mask = mask16[writemask2 & 0x0f]; + addr >>= 2; + ((uint32_t *)(svga->vram))[addr] &= ~write_mask; + ((uint32_t *)(svga->vram))[addr] |= (val32 & write_mask); + return; + case 2: + val32 = mask16[val32 & 0x0f]; + bit_mask = svga->gdcreg[8]; + + if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) + func_select = 0; + break; + case 3: + /* rotate */ + if (svga->gdcreg[3] & 7) + val32 = svga_rotate[svga->gdcreg[3] & 7][val]; + + bit_mask = svga->gdcreg[8] & val32; + val32 = mask16[svga->gdcreg[0] & 0x0f]; + break; + default: + if (svga->ven_write) + svga->ven_write(svga, val, addr); + return; + } + + /* apply bit mask */ + bit_mask |= bit_mask << 8; + bit_mask |= bit_mask << 16; + + /* apply logical operation */ + switch(func_select) { + case 0: + default: + /* set */ + val32 &= bit_mask; + val32 |= (svga->latch & ~bit_mask); + break; + case 1: + /* and */ + val32 |= ~bit_mask; + val32 &= svga->latch; + break; + case 2: + /* or */ + val32 &= bit_mask; + val32 |= svga->latch; + break; + case 3: + /* xor */ + val32 &= bit_mask; + val32 ^= svga->latch; + break; + } + + /* mask data according to sr[2] */ + write_mask = mask16[writemask2 & 0x0f]; + addr >>= 2; + ((uint32_t *)(svga->vram))[addr] = (((uint32_t *)(svga->vram))[addr] & ~write_mask) | (val32 & write_mask); +} + + +uint8_t +svga_read_common(uint32_t addr, uint8_t linear, void *p) +{ + svga_t *svga = (svga_t *)p; + uint32_t latch_addr = 0, ret; + int readplane = svga->readplane; + uint8_t ret8; + + cycles -= video_timing_read_b; + + egareads++; + + if (!linear) { + addr &= svga->banked_mask; + addr += svga->read_bank; + + latch_addr = (addr << 2) & svga->decode_mask; + } + + if (svga->chain4 || svga->fb_only) { + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xff; + return svga->vram[addr & svga->vram_mask]; + } else if (svga->chain2_read) { + readplane = (readplane & 2) | (addr & 1); + addr &= ~1; + addr <<= 2; + } else + addr <<= 2; + + addr &= svga->decode_mask; + + /* standard VGA latched access */ + if (linear) { + if (addr >= svga->vram_max) + return 0xff; + + addr &= svga->vram_mask; + + svga->latch = ((uint32_t *)(svga->vram))[addr >> 2]; + } else { + if (latch_addr > svga->vram_max) + svga->latch = 0xffffffff; + else { + latch_addr &= svga->vram_mask; + svga->latch = ((uint32_t *)(svga->vram))[latch_addr >> 2]; + } + + if (addr >= svga->vram_max) + return 0xff; + + addr &= svga->vram_mask; + } + + if (!(svga->gdcreg[5] & 8)) { + /* read mode 0 */ + return svga->vram[addr | readplane]; + } else { + /* read mode 1 */ + ret = (svga->latch ^ mask16[svga->colourcompare & 0x0f]) & mask16[svga->colournocare & 0x0f]; + ret8 = (ret & 0xff); + ret8 |= ((ret >> 24) & 0xff); + ret8 |= ((ret >> 16) & 0xff); + ret8 |= ((ret >> 8) & 0xff); + return(~ret8); + } +} + + +void +svga_write(uint32_t addr, uint8_t val, void *p) +{ + svga_write_common(addr, val, 0, p); +} + + +void +svga_write_linear(uint32_t addr, uint8_t val, void *p) +{ + svga_write_common(addr, val, 1, p); +} + + +uint8_t +svga_read(uint32_t addr, void *p) +{ + return svga_read_common(addr, 0, p); +} + + +uint8_t +svga_read_linear(uint32_t addr, void *p) +{ + return svga_read_common(addr, 1, p); +} + + +void +svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) +{ + int y_add = (enable_overscan) ? overscan_y : 0; + int x_add = (enable_overscan) ? 16 : 0; + uint32_t *p; + int i, j; + + svga->frames++; + + if ((xsize > 2032) || (ysize > 2032)) { + x_add = 0; + y_add = 0; + suppress_overscan = 1; + } else + suppress_overscan = 0; + + if (y1 > y2) { + video_blit_memtoscreen(32, 0, 0, 0, xsize + x_add, ysize + y_add); + return; + } + + if ((wx != xsize) || ((wy + 1) != ysize) || video_force_resize_get()) { + /* Screen res has changed.. fix up, and let them know. */ + xsize = wx; + ysize = wy + 1; + if (xsize < 64) + xsize = 640; + if (ysize < 32) + ysize = 200; + + set_screen_size(xsize+x_add,ysize+y_add); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + + if (enable_overscan && !suppress_overscan) { + if ((wx >= 160) && ((wy + 1) >= 120)) { + /* Draw (overscan_size - scroll size) lines of overscan on top. */ + for (i = 0; i < (y_add >> 1); i++) { + p = &((uint32_t *)buffer32->line[i & 0x7ff])[32]; + + for (j = 0; j < (xsize + x_add); j++) + p[j] = svga->overscan_color; + } + + /* Draw (overscan_size + scroll size) lines of overscan on the bottom. */ + for (i = 0; i < (y_add >> 1); i++) { + p = &((uint32_t *)buffer32->line[(ysize + (y_add >> 1) + i) & 0x7ff])[32]; + + for (j = 0; j < (xsize + x_add); j++) + p[j] = svga->overscan_color; + } + + for (i = (y_add >> 1); i < (ysize + (y_add >> 1)); i ++) { + p = &((uint32_t *)buffer32->line[i & 0x7ff])[32]; + + for (j = 0; j < 8; j++) { + p[j] = svga->pallook[svga->overscan_color]; + p[xsize + (x_add >> 1) + j] = svga->overscan_color; + } } } + } - video_blit_memtoscreen(32, 0, y1, y2 + y_add, xsize + x_add, ysize + y_add); + video_blit_memtoscreen(32, 0, y1, y2 + y_add, xsize + x_add, ysize + y_add); } -void svga_writew(uint32_t addr, uint16_t val, void *p) + +void +svga_writeb_linear(uint32_t addr, uint8_t val, void *p) { - svga_t *svga = (svga_t *)p; - if (!svga->fast) - { - svga_write(addr, val, p); - svga_write(addr + 1, val >> 8, p); - return; - } - - egawrites += 2; + svga_t *svga = (svga_t *)p; - cycles -= video_timing_write_w; - cycles_lost += video_timing_write_w; + if (!svga->fast) { + svga_write_linear(addr, val, p); + return; + } - if (svga_output) pclog("svga_writew: %05X ", addr); - addr = (addr & svga->banked_mask) + svga->write_bank; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - if (svga_output) pclog("%08X (%i, %i) %04X\n", addr, addr & 1023, addr >> 10, val); - svga->changedvram[addr >> 12] = changeframecount; - *(uint16_t *)&svga->vram[addr] = val; + egawrites++; + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + svga->changedvram[addr >> 12] = changeframecount; + *(uint8_t *)&svga->vram[addr] = val; } -void svga_writel(uint32_t addr, uint32_t val, void *p) + +void +svga_writew_common(uint32_t addr, uint16_t val, uint8_t linear, void *p) { - svga_t *svga = (svga_t *)p; - - if (!svga->fast) - { - svga_write(addr, val, p); - svga_write(addr + 1, val >> 8, p); - svga_write(addr + 2, val >> 16, p); - svga_write(addr + 3, val >> 24, p); - return; - } - - egawrites += 4; + svga_t *svga = (svga_t *)p; - cycles -= video_timing_write_l; - cycles_lost += video_timing_write_l; + if (!svga->fast) { + svga_write_common(addr, val, linear, p); + svga_write_common(addr + 1, val >> 8, linear, p); + return; + } - if (svga_output) pclog("svga_writel: %05X ", addr); - addr = (addr & svga->banked_mask) + svga->write_bank; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - if (svga_output) pclog("%08X (%i, %i) %08X\n", addr, addr & 1023, addr >> 10, val); - - svga->changedvram[addr >> 12] = changeframecount; - *(uint32_t *)&svga->vram[addr] = val; + egawrites += 2; + + cycles -= video_timing_write_w; + + if (!linear) + addr = (addr & svga->banked_mask) + svga->write_bank; + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + svga->changedvram[addr >> 12] = changeframecount; + *(uint16_t *)&svga->vram[addr] = val; } -uint16_t svga_readw(uint32_t addr, void *p) + +void +svga_writew(uint32_t addr, uint16_t val, void *p) { - svga_t *svga = (svga_t *)p; - - if (!svga->fast) - return svga_read(addr, p) | (svga_read(addr + 1, p) << 8); - - egareads += 2; - - cycles -= video_timing_read_w; - cycles_lost += video_timing_read_w; - -// pclog("Readw %05X ", addr); - addr = (addr & svga->banked_mask) + svga->read_bank; - addr &= svga->decode_mask; -// pclog("%08X %04X\n", addr, *(uint16_t *)&vram[addr]); - if (addr >= svga->vram_max) - return 0xffff; - - return *(uint16_t *)&svga->vram[addr & svga->vram_mask]; + svga_writew_common(addr, val, 0, p); } -uint32_t svga_readl(uint32_t addr, void *p) + +void +svga_writew_linear(uint32_t addr, uint16_t val, void *p) { - svga_t *svga = (svga_t *)p; - - if (!svga->fast) - return svga_read(addr, p) | (svga_read(addr + 1, p) << 8) | (svga_read(addr + 2, p) << 16) | (svga_read(addr + 3, p) << 24); - - egareads += 4; - - cycles -= video_timing_read_l; - cycles_lost += video_timing_read_l; - -// pclog("Readl %05X ", addr); - addr = (addr & svga->banked_mask) + svga->read_bank; - addr &= svga->decode_mask; -// pclog("%08X %08X\n", addr, *(uint32_t *)&vram[addr]); - if (addr >= svga->vram_max) - return 0xffffffff; - - return *(uint32_t *)&svga->vram[addr & svga->vram_mask]; + svga_writew_common(addr, val, 1, p); } -void svga_writeb_linear(uint32_t addr, uint8_t val, void *p) + +void +svga_writel_common(uint32_t addr, uint32_t val, uint8_t linear, void *p) { - svga_t *svga = (svga_t *)p; - - if (!svga->fast) - { - svga_write_linear(addr, val, p); - return; - } - - egawrites++; + svga_t *svga = (svga_t *)p; - if (svga_output) pclog("Write LFBb %08X %04X\n", addr, val); - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - svga->changedvram[addr >> 12] = changeframecount; - *(uint8_t *)&svga->vram[addr] = val; + if (!svga->fast) { + svga_write(addr, val, p); + svga_write(addr + 1, val >> 8, p); + svga_write(addr + 2, val >> 16, p); + svga_write(addr + 3, val >> 24, p); + return; + } + + egawrites += 4; + + cycles -= video_timing_write_l; + + if (!linear) + addr = (addr & svga->banked_mask) + svga->write_bank; + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + + svga->changedvram[addr >> 12] = changeframecount; + *(uint32_t *)&svga->vram[addr] = val; } -void svga_writew_linear(uint32_t addr, uint16_t val, void *p) + +void +svga_writel(uint32_t addr, uint32_t val, void *p) { - svga_t *svga = (svga_t *)p; - - if (!svga->fast) - { - svga_write_linear(addr, val, p); - svga_write_linear(addr + 1, val >> 8, p); - return; - } - - egawrites += 2; - - cycles -= video_timing_write_w; - cycles_lost += video_timing_write_w; - - if (svga_output) pclog("Write LFBw %08X %04X\n", addr, val); - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - svga->changedvram[addr >> 12] = changeframecount; - *(uint16_t *)&svga->vram[addr] = val; + svga_writel_common(addr, val, 0, p); } -void svga_writel_linear(uint32_t addr, uint32_t val, void *p) + +void +svga_writel_linear(uint32_t addr, uint32_t val, void *p) { - svga_t *svga = (svga_t *)p; - - if (!svga->fast) - { - svga_write_linear(addr, val, p); - svga_write_linear(addr + 1, val >> 8, p); - svga_write_linear(addr + 2, val >> 16, p); - svga_write_linear(addr + 3, val >> 24, p); - return; - } - - egawrites += 4; - - cycles -= video_timing_write_l; - cycles_lost += video_timing_write_l; - - if (svga_output) pclog("Write LFBl %08X %08X\n", addr, val); - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - svga->changedvram[addr >> 12] = changeframecount; - *(uint32_t *)&svga->vram[addr] = val; + svga_writel_common(addr, val, 1, p); } -uint8_t svga_readb_linear(uint32_t addr, void *p) + +uint8_t +svga_readb_linear(uint32_t addr, void *p) { - svga_t *svga = (svga_t *)p; - - if (!svga->fast) - return svga_read_linear(addr, p); - - egareads++; + svga_t *svga = (svga_t *)p; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xff; - - return *(uint8_t *)&svga->vram[addr & svga->vram_mask]; + if (!svga->fast) + return svga_read_linear(addr, p); + + egareads++; + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xff; + + return *(uint8_t *)&svga->vram[addr & svga->vram_mask]; } -uint16_t svga_readw_linear(uint32_t addr, void *p) + +uint16_t +svga_readw_common(uint32_t addr, uint8_t linear, void *p) { - svga_t *svga = (svga_t *)p; - - if (!svga->fast) - return svga_read_linear(addr, p) | (svga_read_linear(addr + 1, p) << 8); - - egareads += 2; + svga_t *svga = (svga_t *)p; - cycles -= video_timing_read_w; - cycles_lost += video_timing_read_w; + if (!svga->fast) + return svga_read_common(addr, linear, p) | (svga_read_common(addr + 1, linear, p) << 8); - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xffff; - - return *(uint16_t *)&svga->vram[addr & svga->vram_mask]; + egareads += 2; + + cycles -= video_timing_read_w; + + if (!linear) + addr = (addr & svga->banked_mask) + svga->read_bank; + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xffff; + + return *(uint16_t *)&svga->vram[addr & svga->vram_mask]; } -uint32_t svga_readl_linear(uint32_t addr, void *p) + +uint16_t +svga_readw(uint32_t addr, void *p) { - svga_t *svga = (svga_t *)p; - - if (!svga->fast) - return svga_read_linear(addr, p) | (svga_read_linear(addr + 1, p) << 8) | (svga_read_linear(addr + 2, p) << 16) | (svga_read_linear(addr + 3, p) << 24); - - egareads += 4; - - cycles -= video_timing_read_l; - cycles_lost += video_timing_read_l; - - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xffffffff; - - return *(uint32_t *)&svga->vram[addr & svga->vram_mask]; + return svga_readw_common(addr, 0, p); } -void svga_add_status_info(char *s, int max_len, void *p) +uint16_t +svga_readw_linear(uint32_t addr, void *p) { - svga_t *svga = (svga_t *)p; - char temps[128]; - - if (svga->chain4) strcpy(temps, "SVGA chained (possibly mode 13h)\n"); - else strcpy(temps, "SVGA unchained (possibly mode-X)\n"); - strncat(s, temps, max_len); - - if (!svga->video_bpp) strcpy(temps, "SVGA in text mode\n"); - else sprintf(temps, "SVGA colour depth : %i bpp\n", svga->video_bpp); - strncat(s, temps, max_len); - - sprintf(temps, "SVGA resolution : %i x %i\n", svga->video_res_x, svga->video_res_y); - strncat(s, temps, max_len); - - sprintf(temps, "SVGA refresh rate : %i Hz\n\n", svga->frames); - svga->frames = 0; - strncat(s, temps, max_len); + return svga_readw_common(addr, 1, p); +} + + +uint32_t +svga_readl_common(uint32_t addr, uint8_t linear, void *p) +{ + svga_t *svga = (svga_t *)p; + + if (!svga->fast) { + return svga_read_common(addr, linear, p) | (svga_read_common(addr + 1, linear, p) << 8) | + (svga_read_common(addr + 2, linear, p) << 16) | (svga_read_common(addr + 3, linear, p) << 24); + } + + egareads += 4; + + cycles -= video_timing_read_l; + + if (!linear) + addr = (addr & svga->banked_mask) + svga->read_bank; + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xffffffff; + + return *(uint32_t *)&svga->vram[addr & svga->vram_mask]; +} + + +uint32_t +svga_readl(uint32_t addr, void *p) +{ + return svga_readl_common(addr, 0, p); +} + + +uint32_t +svga_readl_linear(uint32_t addr, void *p) +{ + return svga_readl_common(addr, 1, p); +} + + +void +svga_add_status_info(char *s, int max_len, void *p) +{ + svga_t *svga = (svga_t *)p; + char temps[128]; + + if (svga->chain4) + strcpy(temps, "SVGA chained (possibly mode 13h)\n"); + else + strcpy(temps, "SVGA unchained (possibly mode-X)\n"); + strncat(s, temps, max_len); + + if (!svga->video_bpp) + strcpy(temps, "SVGA in text mode\n"); + else + sprintf(temps, "SVGA colour depth : %i bpp\n", svga->video_bpp); + strncat(s, temps, max_len); + + sprintf(temps, "SVGA resolution : %i x %i\n", svga->video_res_x, svga->video_res_y); + strncat(s, temps, max_len); + + sprintf(temps, "SVGA refresh rate : %i Hz\n\n", svga->frames); + svga->frames = 0; + strncat(s, temps, max_len); } diff --git a/src/video/vid_svga.h b/src/video/vid_svga.h index b2811995b..214e62a13 100644 --- a/src/video/vid_svga.h +++ b/src/video/vid_svga.h @@ -8,7 +8,7 @@ * * Generic SVGA handling. * - * Version: @(#)vid_svga.h 1.0.10 2018/03/23 + * Version: @(#)vid_svga.h 1.0.12 2018/05/26 * * Authors: Sarah Walker, * Miran Grca, @@ -17,228 +17,156 @@ * Copyright 2016-2018 Miran Grca. */ +typedef struct { + int ena, + x, y, xoff, yoff, xsize, ysize, + v_acc, h_acc; + uint32_t addr, pitch; +} hwcursor_t; + typedef struct svga_t { - mem_mapping_t mapping; + mem_mapping_t mapping; - int enabled; + int enabled; - - uint8_t crtcreg; - uint8_t crtc[128]; - uint8_t gdcreg[64]; - int gdcaddr; - uint8_t attrregs[32]; - int attraddr, attrff; - int attr_palette_enable; - uint8_t seqregs[64]; - int seqaddr; - - uint8_t miscout; - int vidclock; + uint8_t crtcreg, crtc[128], + gdcaddr, gdcreg[64], + attrff, attr_palette_enable, + attraddr, attrregs[32], + seqaddr, seqregs[64], + miscout, cgastat, + plane_mask, writemask, + colourcompare, colournocare, + scrblank, egapal[16], + *vram, *changedvram; - /*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 : - 0MB-1MB - VRAM - 1MB-2MB - VRAM mirror - 2MB-4MB - open bus - 4MB-xMB - mirror of above - - For the example memory map, decode_mask would be 4MB-1 (4MB address space), vram_max would be 2MB - (present video memory only responds to first 2MB), vram_mask would be 1MB-1 (video memory wraps at 1MB) - */ - uint32_t decode_mask; - uint32_t vram_max; - uint32_t vram_mask; + int vidclock, fb_only, + fast; - uint8_t la, lb, lc, ld; - - uint8_t dac_mask, dac_status; - int dac_read, dac_write, dac_pos; - int dac_r, dac_g; - - uint8_t cgastat; - - uint8_t plane_mask; - - int fb_only; - - int fast; - uint8_t colourcompare, colournocare; - int readmode, writemode, readplane; - int chain4, chain2_write, chain2_read; - int oddeven_page, oddeven_chain; - int extvram; - uint8_t writemask; - uint32_t charseta, charsetb; - - int set_reset_disabled; - - uint8_t egapal[16]; - uint32_t pallook[256]; - PALETTE vgapal; - - int ramdac_type; + /*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 : + 0MB-1MB - VRAM + 1MB-2MB - VRAM mirror + 2MB-4MB - open bus + 4MB-xMB - mirror of above - int vtotal, dispend, vsyncstart, split, vblankstart; - int hdisp, hdisp_old, htotal, hdisp_time, rowoffset; - int lowres, interlace; - int linedbl, rowcount; - double clock; - uint32_t ma_latch; - int bpp; - - int64_t dispontime, dispofftime; - int64_t vidtime; - - uint8_t scrblank; - - int dispon; - int hdisp_on; + For the example memory map, decode_mask would be 4MB-1 (4MB address space), vram_max would be 2MB + (present video memory only responds to first 2MB), vram_mask would be 1MB-1 (video memory wraps at 1MB) + */ + uint32_t decode_mask; + uint32_t vram_max; + uint32_t vram_mask; - uint32_t ma, maback, ca; - int vc; - int sc; - int linepos, vslines, linecountff, oddeven; - int con, cursoron, blink; - int scrollcache; - - int firstline, lastline; - int firstline_draw, lastline_draw; - int displine; - - uint8_t *vram; - uint8_t *changedvram; - int vram_display_mask; - uint32_t banked_mask; + uint8_t dac_mask, dac_status; + int dac_read, dac_write, + dac_pos, ramdac_type, + dac_r, dac_g; - uint32_t write_bank, read_bank; - - int fullchange; - - int video_res_x, video_res_y, video_bpp; - int frames, fps; + int readmode, writemode, + readplane, extvram, + chain4, chain2_write, chain2_read, + oddeven_page, oddeven_chain, + set_reset_disabled; - struct - { - int ena; - int x, y; - int xoff, yoff; - int xsize, ysize; - uint32_t addr; - uint32_t pitch; - int v_acc, h_acc; - } hwcursor, hwcursor_latch, overlay, overlay_latch; - - int hwcursor_on; - int overlay_on; - - int hwcursor_oddeven; - int overlay_oddeven; - - void (*render)(struct svga_t *svga); - void (*recalctimings_ex)(struct svga_t *svga); + uint32_t charseta, charsetb, + latch, ma_latch, + ma, maback, + write_bank, read_bank, + banked_mask, + ca, overscan_color, + pallook[256]; - void (*video_out)(uint16_t addr, uint8_t val, void *p); - uint8_t (*video_in) (uint16_t addr, void *p); + PALETTE vgapal; - void (*hwcursor_draw)(struct svga_t *svga, int displine); + int vtotal, dispend, vsyncstart, split, vblankstart, + hdisp, hdisp_old, htotal, hdisp_time, rowoffset, + lowres, interlace, linedbl, rowcount, bpp, + dispon, hdisp_on, + vc, sc, linepos, vslines, linecountff, oddeven, + con, cursoron, blink, scrollcache, + firstline, lastline, firstline_draw, lastline_draw, + displine, fullchange, + video_res_x, video_res_y, video_bpp, frames, fps, + vram_display_mask, + hwcursor_on, overlay_on, + hwcursor_oddeven, overlay_oddeven; - void (*overlay_draw)(struct svga_t *svga, int displine); - - void (*vblank_start)(struct svga_t *svga); + double clock; - /*If set then another device is driving the monitor output and the SVGA - card should not attempt to display anything */ - int override; - void *p; + int64_t dispontime, dispofftime, + vidtime; - uint32_t linear_base; - uint32_t overscan_color; + hwcursor_t hwcursor, hwcursor_latch, + overlay, overlay_latch; + + void (*render)(struct svga_t *svga); + void (*recalctimings_ex)(struct svga_t *svga); + + void (*video_out)(uint16_t addr, uint8_t val, void *p); + uint8_t (*video_in) (uint16_t addr, void *p); + + void (*hwcursor_draw)(struct svga_t *svga, int displine); + + void (*overlay_draw)(struct svga_t *svga, int displine); + + void (*vblank_start)(struct svga_t *svga); + + void (*ven_write)(struct svga_t *svga, uint8_t val, uint32_t addr); + + /*If set then another device is driving the monitor output and the SVGA + card should not attempt to display anything */ + int override; + void *p; } svga_t; -extern int svga_init(svga_t *svga, void *p, int memsize, - void (*recalctimings_ex)(struct svga_t *svga), - uint8_t (*video_in) (uint16_t addr, void *p), - void (*video_out)(uint16_t addr, uint8_t val, void *p), - void (*hwcursor_draw)(struct svga_t *svga, int displine), - void (*overlay_draw)(struct svga_t *svga, int displine)); -extern void svga_recalctimings(svga_t *svga); -extern void svga_close(svga_t *svga); + +extern int svga_init(svga_t *svga, void *p, int memsize, + void (*recalctimings_ex)(struct svga_t *svga), + uint8_t (*video_in) (uint16_t addr, void *p), + void (*video_out)(uint16_t addr, uint8_t val, void *p), + void (*hwcursor_draw)(struct svga_t *svga, int displine), + void (*overlay_draw)(struct svga_t *svga, int displine)); +extern void svga_recalctimings(svga_t *svga); +extern void svga_close(svga_t *svga); + +uint8_t svga_read(uint32_t addr, void *p); +uint16_t svga_readw(uint32_t addr, void *p); +uint32_t svga_readl(uint32_t addr, void *p); +void svga_write(uint32_t addr, uint8_t val, void *p); +void svga_writew(uint32_t addr, uint16_t val, void *p); +void svga_writel(uint32_t addr, uint32_t val, void *p); +uint8_t svga_read_linear(uint32_t addr, void *p); +uint8_t svga_readb_linear(uint32_t addr, void *p); +uint16_t svga_readw_linear(uint32_t addr, void *p); +uint32_t svga_readl_linear(uint32_t addr, void *p); +void svga_write_linear(uint32_t addr, uint8_t val, void *p); +void svga_writeb_linear(uint32_t addr, uint8_t val, void *p); +void svga_writew_linear(uint32_t addr, uint16_t val, void *p); +void svga_writel_linear(uint32_t addr, uint32_t val, void *p); + +void svga_add_status_info(char *s, int max_len, void *p); + +extern uint8_t svga_rotate[8][256]; + +void svga_out(uint16_t addr, uint8_t val, void *p); +uint8_t svga_in(uint16_t addr, void *p); + +svga_t *svga_get_pri(); +void svga_set_override(svga_t *svga, int val); + +void svga_set_ven_write(svga_t *svga, + void (*ven_write)(struct svga_t *svga, uint8_t val, uint32_t addr)); + +void svga_set_ramdac_type(svga_t *svga, int type); +void svga_close(svga_t *svga); + +uint32_t svga_mask_addr(uint32_t addr, svga_t *svga); +uint32_t svga_mask_changedaddr(uint32_t addr, svga_t *svga); + +void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga); -uint8_t svga_read(uint32_t addr, void *p); -uint16_t svga_readw(uint32_t addr, void *p); -uint32_t svga_readl(uint32_t addr, void *p); -void svga_write(uint32_t addr, uint8_t val, void *p); -void svga_writew(uint32_t addr, uint16_t val, void *p); -void svga_writel(uint32_t addr, uint32_t val, void *p); -uint8_t svga_read_linear(uint32_t addr, void *p); -uint8_t svga_readb_linear(uint32_t addr, void *p); -uint16_t svga_readw_linear(uint32_t addr, void *p); -uint32_t svga_readl_linear(uint32_t addr, void *p); -void svga_write_linear(uint32_t addr, uint8_t val, void *p); -void svga_writeb_linear(uint32_t addr, uint8_t val, void *p); -void svga_writew_linear(uint32_t addr, uint16_t val, void *p); -void svga_writel_linear(uint32_t addr, uint32_t val, void *p); - -void svga_add_status_info(char *s, int max_len, void *p); - -extern uint8_t svga_rotate[8][256]; - -void svga_out(uint16_t addr, uint8_t val, void *p); -uint8_t svga_in(uint16_t addr, void *p); - -svga_t *svga_get_pri(); -void svga_set_override(svga_t *svga, int val); - -#define RAMDAC_6BIT 0 -#define RAMDAC_8BIT 1 -void svga_set_ramdac_type(svga_t *svga, int type); - -void svga_close(svga_t *svga); - -uint32_t svga_mask_addr(uint32_t addr, svga_t *svga); -uint32_t svga_mask_changedaddr(uint32_t addr, svga_t *svga); - -extern uint32_t shade[5][256]; - -static __inline__ uint32_t svga_color_transform(uint32_t color) -{ - uint8_t *clr8 = (uint8_t *) &color; - if (!video_grayscale && !invert_display) - return color; - if (video_grayscale) - { - if (video_graytype) - { - if (video_graytype == 1) - color = ((54 * (uint32_t)clr8[2]) + (183 * (uint32_t)clr8[1]) + (18 * (uint32_t)clr8[0])) / 255; - else - color = ((uint32_t)clr8[2] + (uint32_t)clr8[1] + (uint32_t)clr8[0]) / 3; - } - else - color = ((76 * (uint32_t)clr8[2]) + (150 * (uint32_t)clr8[1]) + (29 * (uint32_t)clr8[0])) / 255; - switch (video_grayscale) - { - case 2: - case 3: - case 4: - color = shade[video_grayscale][color]; - break; - default: - clr8[3] = 0; - clr8[0] = color; - clr8[1] = clr8[2] = clr8[0]; - break; - } - } - if (invert_display) - { - clr8[0] ^= 0xff; - clr8[1] ^= 0xff; - clr8[2] ^= 0xff; - } - return color; -} - -void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga); +enum { + RAMDAC_6BIT = 0, + RAMDAC_8BIT +}; diff --git a/src/video/vid_svga_render.c b/src/video/vid_svga_render.c index 1a6912782..3e920bd1e 100644 --- a/src/video/vid_svga_render.c +++ b/src/video/vid_svga_render.c @@ -8,7 +8,7 @@ * * SVGA renderers. * - * Version: @(#)vid_svga_render.c 1.0.10 2018/03/19 + * Version: @(#)vid_svga_render.c 1.0.11 2018/05/26 * * Authors: Sarah Walker, * Miran Grca, @@ -27,71 +27,6 @@ #include "vid_svga_render.h" -int invert_display = 0; -int video_grayscale = 0; -int video_graytype = 0; - - -uint32_t shade[5][256] = -{ - {0}, // RGB Color (unused) - {0}, // RGB Grayscale (unused) - { // Amber monitor - 0x000000, 0x060000, 0x090000, 0x0d0000, 0x100000, 0x120100, 0x150100, 0x170100, 0x1a0100, 0x1c0100, 0x1e0200, 0x210200, 0x230200, 0x250300, 0x270300, 0x290300, - 0x2b0400, 0x2d0400, 0x2f0400, 0x300500, 0x320500, 0x340500, 0x360600, 0x380600, 0x390700, 0x3b0700, 0x3d0700, 0x3f0800, 0x400800, 0x420900, 0x440900, 0x450a00, - 0x470a00, 0x480b00, 0x4a0b00, 0x4c0c00, 0x4d0c00, 0x4f0d00, 0x500d00, 0x520e00, 0x530e00, 0x550f00, 0x560f00, 0x581000, 0x591000, 0x5b1100, 0x5c1200, 0x5e1200, - 0x5f1300, 0x601300, 0x621400, 0x631500, 0x651500, 0x661600, 0x671600, 0x691700, 0x6a1800, 0x6c1800, 0x6d1900, 0x6e1a00, 0x701a00, 0x711b00, 0x721c00, 0x741c00, - 0x751d00, 0x761e00, 0x781e00, 0x791f00, 0x7a2000, 0x7c2000, 0x7d2100, 0x7e2200, 0x7f2300, 0x812300, 0x822400, 0x832500, 0x842600, 0x862600, 0x872700, 0x882800, - 0x8a2900, 0x8b2900, 0x8c2a00, 0x8d2b00, 0x8e2c00, 0x902c00, 0x912d00, 0x922e00, 0x932f00, 0x953000, 0x963000, 0x973100, 0x983200, 0x993300, 0x9b3400, 0x9c3400, - 0x9d3500, 0x9e3600, 0x9f3700, 0xa03800, 0xa23900, 0xa33a00, 0xa43a00, 0xa53b00, 0xa63c00, 0xa73d00, 0xa93e00, 0xaa3f00, 0xab4000, 0xac4000, 0xad4100, 0xae4200, - 0xaf4300, 0xb14400, 0xb24500, 0xb34600, 0xb44700, 0xb54800, 0xb64900, 0xb74a00, 0xb94a00, 0xba4b00, 0xbb4c00, 0xbc4d00, 0xbd4e00, 0xbe4f00, 0xbf5000, 0xc05100, - 0xc15200, 0xc25300, 0xc45400, 0xc55500, 0xc65600, 0xc75700, 0xc85800, 0xc95900, 0xca5a00, 0xcb5b00, 0xcc5c00, 0xcd5d00, 0xce5e00, 0xcf5f00, 0xd06000, 0xd26101, - 0xd36201, 0xd46301, 0xd56401, 0xd66501, 0xd76601, 0xd86701, 0xd96801, 0xda6901, 0xdb6a01, 0xdc6b01, 0xdd6c01, 0xde6d01, 0xdf6e01, 0xe06f01, 0xe17001, 0xe27201, - 0xe37301, 0xe47401, 0xe57501, 0xe67602, 0xe77702, 0xe87802, 0xe97902, 0xeb7a02, 0xec7b02, 0xed7c02, 0xee7e02, 0xef7f02, 0xf08002, 0xf18103, 0xf28203, 0xf38303, - 0xf48403, 0xf58503, 0xf68703, 0xf78803, 0xf88903, 0xf98a04, 0xfa8b04, 0xfb8c04, 0xfc8d04, 0xfd8f04, 0xfe9005, 0xff9105, 0xff9205, 0xff9305, 0xff9405, 0xff9606, - 0xff9706, 0xff9806, 0xff9906, 0xff9a07, 0xff9b07, 0xff9d07, 0xff9e08, 0xff9f08, 0xffa008, 0xffa109, 0xffa309, 0xffa409, 0xffa50a, 0xffa60a, 0xffa80a, 0xffa90b, - 0xffaa0b, 0xffab0c, 0xffac0c, 0xffae0d, 0xffaf0d, 0xffb00e, 0xffb10e, 0xffb30f, 0xffb40f, 0xffb510, 0xffb610, 0xffb811, 0xffb912, 0xffba12, 0xffbb13, 0xffbd14, - 0xffbe14, 0xffbf15, 0xffc016, 0xffc217, 0xffc317, 0xffc418, 0xffc619, 0xffc71a, 0xffc81b, 0xffca1c, 0xffcb1d, 0xffcc1e, 0xffcd1f, 0xffcf20, 0xffd021, 0xffd122, - 0xffd323, 0xffd424, 0xffd526, 0xffd727, 0xffd828, 0xffd92a, 0xffdb2b, 0xffdc2c, 0xffdd2e, 0xffdf2f, 0xffe031, 0xffe133, 0xffe334, 0xffe436, 0xffe538, 0xffe739 - }, - { // Green monitor - 0x000000, 0x000400, 0x000700, 0x000900, 0x000b00, 0x000d00, 0x000f00, 0x001100, 0x001300, 0x001500, 0x001600, 0x001800, 0x001a00, 0x001b00, 0x001d00, 0x001e00, - 0x002000, 0x002100, 0x002300, 0x002400, 0x002601, 0x002701, 0x002901, 0x002a01, 0x002b01, 0x002d01, 0x002e01, 0x002f01, 0x003101, 0x003201, 0x003301, 0x003401, - 0x003601, 0x003702, 0x003802, 0x003902, 0x003b02, 0x003c02, 0x003d02, 0x003e02, 0x004002, 0x004102, 0x004203, 0x004303, 0x004403, 0x004503, 0x004703, 0x004803, - 0x004903, 0x004a03, 0x004b04, 0x004c04, 0x004d04, 0x004e04, 0x005004, 0x005104, 0x005205, 0x005305, 0x005405, 0x005505, 0x005605, 0x005705, 0x005806, 0x005906, - 0x005a06, 0x005b06, 0x005d06, 0x005e07, 0x005f07, 0x006007, 0x006107, 0x006207, 0x006308, 0x006408, 0x006508, 0x006608, 0x006708, 0x006809, 0x006909, 0x006a09, - 0x006b09, 0x016c0a, 0x016d0a, 0x016e0a, 0x016f0a, 0x01700b, 0x01710b, 0x01720b, 0x01730b, 0x01740c, 0x01750c, 0x01760c, 0x01770c, 0x01780d, 0x01790d, 0x017a0d, - 0x017b0d, 0x017b0e, 0x017c0e, 0x017d0e, 0x017e0f, 0x017f0f, 0x01800f, 0x018110, 0x028210, 0x028310, 0x028410, 0x028511, 0x028611, 0x028711, 0x028812, 0x028912, - 0x028a12, 0x028a13, 0x028b13, 0x028c13, 0x028d14, 0x028e14, 0x038f14, 0x039015, 0x039115, 0x039215, 0x039316, 0x039416, 0x039417, 0x039517, 0x039617, 0x039718, - 0x049818, 0x049918, 0x049a19, 0x049b19, 0x049c19, 0x049c1a, 0x049d1a, 0x049e1b, 0x059f1b, 0x05a01b, 0x05a11c, 0x05a21c, 0x05a31c, 0x05a31d, 0x05a41d, 0x06a51e, - 0x06a61e, 0x06a71f, 0x06a81f, 0x06a920, 0x06aa20, 0x07aa21, 0x07ab21, 0x07ac21, 0x07ad22, 0x07ae22, 0x08af23, 0x08b023, 0x08b024, 0x08b124, 0x08b225, 0x09b325, - 0x09b426, 0x09b526, 0x09b527, 0x0ab627, 0x0ab728, 0x0ab828, 0x0ab929, 0x0bba29, 0x0bba2a, 0x0bbb2a, 0x0bbc2b, 0x0cbd2b, 0x0cbe2c, 0x0cbf2c, 0x0dbf2d, 0x0dc02d, - 0x0dc12e, 0x0ec22e, 0x0ec32f, 0x0ec42f, 0x0fc430, 0x0fc530, 0x0fc631, 0x10c731, 0x10c832, 0x10c932, 0x11c933, 0x11ca33, 0x11cb34, 0x12cc35, 0x12cd35, 0x12cd36, - 0x13ce36, 0x13cf37, 0x13d037, 0x14d138, 0x14d139, 0x14d239, 0x15d33a, 0x15d43a, 0x16d43b, 0x16d53b, 0x17d63c, 0x17d73d, 0x17d83d, 0x18d83e, 0x18d93e, 0x19da3f, - 0x19db40, 0x1adc40, 0x1adc41, 0x1bdd41, 0x1bde42, 0x1cdf43, 0x1ce043, 0x1de044, 0x1ee145, 0x1ee245, 0x1fe346, 0x1fe446, 0x20e447, 0x20e548, 0x21e648, 0x22e749, - 0x22e74a, 0x23e84a, 0x23e94b, 0x24ea4c, 0x25ea4c, 0x25eb4d, 0x26ec4e, 0x27ed4e, 0x27ee4f, 0x28ee50, 0x29ef50, 0x29f051, 0x2af152, 0x2bf153, 0x2cf253, 0x2cf354, - 0x2df455, 0x2ef455, 0x2ff556, 0x2ff657, 0x30f758, 0x31f758, 0x32f859, 0x32f95a, 0x33fa5a, 0x34fa5b, 0x35fb5c, 0x36fc5d, 0x37fd5d, 0x38fd5e, 0x38fe5f, 0x39ff60 - }, - { // White monitor - 0x000000, 0x010102, 0x020203, 0x020304, 0x030406, 0x040507, 0x050608, 0x060709, 0x07080a, 0x08090c, 0x080a0d, 0x090b0e, 0x0a0c0f, 0x0b0d10, 0x0c0e11, 0x0d0f12, - 0x0e1013, 0x0f1115, 0x101216, 0x111317, 0x121418, 0x121519, 0x13161a, 0x14171b, 0x15181c, 0x16191d, 0x171a1e, 0x181b1f, 0x191c20, 0x1a1d21, 0x1b1e22, 0x1c1f23, - 0x1d2024, 0x1e2125, 0x1f2226, 0x202327, 0x212428, 0x222529, 0x22262b, 0x23272c, 0x24282d, 0x25292e, 0x262a2f, 0x272b30, 0x282c30, 0x292d31, 0x2a2e32, 0x2b2f33, - 0x2c3034, 0x2d3035, 0x2e3136, 0x2f3237, 0x303338, 0x313439, 0x32353a, 0x33363b, 0x34373c, 0x35383d, 0x36393e, 0x373a3f, 0x383b40, 0x393c41, 0x3a3d42, 0x3b3e43, - 0x3c3f44, 0x3d4045, 0x3e4146, 0x3f4247, 0x404348, 0x414449, 0x42454a, 0x43464b, 0x44474c, 0x45484d, 0x46494d, 0x474a4e, 0x484b4f, 0x484c50, 0x494d51, 0x4a4e52, - 0x4b4f53, 0x4c5054, 0x4d5155, 0x4e5256, 0x4f5357, 0x505458, 0x515559, 0x52565a, 0x53575b, 0x54585b, 0x55595c, 0x565a5d, 0x575b5e, 0x585c5f, 0x595d60, 0x5a5e61, - 0x5b5f62, 0x5c6063, 0x5d6164, 0x5e6265, 0x5f6366, 0x606466, 0x616567, 0x626668, 0x636769, 0x64686a, 0x65696b, 0x666a6c, 0x676b6d, 0x686c6e, 0x696d6f, 0x6a6e70, - 0x6b6f70, 0x6c7071, 0x6d7172, 0x6f7273, 0x707374, 0x707475, 0x717576, 0x727677, 0x747778, 0x757879, 0x767979, 0x777a7a, 0x787b7b, 0x797c7c, 0x7a7d7d, 0x7b7e7e, - 0x7c7f7f, 0x7d8080, 0x7e8181, 0x7f8281, 0x808382, 0x818483, 0x828584, 0x838685, 0x848786, 0x858887, 0x868988, 0x878a89, 0x888b89, 0x898c8a, 0x8a8d8b, 0x8b8e8c, - 0x8c8f8d, 0x8d8f8e, 0x8e908f, 0x8f9190, 0x909290, 0x919391, 0x929492, 0x939593, 0x949694, 0x959795, 0x969896, 0x979997, 0x989a98, 0x999b98, 0x9a9c99, 0x9b9d9a, - 0x9c9e9b, 0x9d9f9c, 0x9ea09d, 0x9fa19e, 0xa0a29f, 0xa1a39f, 0xa2a4a0, 0xa3a5a1, 0xa4a6a2, 0xa6a7a3, 0xa7a8a4, 0xa8a9a5, 0xa9aaa5, 0xaaaba6, 0xabaca7, 0xacada8, - 0xadaea9, 0xaeafaa, 0xafb0ab, 0xb0b1ac, 0xb1b2ac, 0xb2b3ad, 0xb3b4ae, 0xb4b5af, 0xb5b6b0, 0xb6b7b1, 0xb7b8b2, 0xb8b9b2, 0xb9bab3, 0xbabbb4, 0xbbbcb5, 0xbcbdb6, - 0xbdbeb7, 0xbebfb8, 0xbfc0b8, 0xc0c1b9, 0xc1c2ba, 0xc2c3bb, 0xc3c4bc, 0xc5c5bd, 0xc6c6be, 0xc7c7be, 0xc8c8bf, 0xc9c9c0, 0xcacac1, 0xcbcbc2, 0xccccc3, 0xcdcdc3, - 0xcecec4, 0xcfcfc5, 0xd0d0c6, 0xd1d1c7, 0xd2d2c8, 0xd3d3c9, 0xd4d4c9, 0xd5d5ca, 0xd6d6cb, 0xd7d7cc, 0xd8d8cd, 0xd9d9ce, 0xdadacf, 0xdbdbcf, 0xdcdcd0, 0xdeddd1, - 0xdfded2, 0xe0dfd3, 0xe1e0d4, 0xe2e1d4, 0xe3e2d5, 0xe4e3d6, 0xe5e4d7, 0xe6e5d8, 0xe7e6d9, 0xe8e7d9, 0xe9e8da, 0xeae9db, 0xebeadc, 0xecebdd, 0xedecde, 0xeeeddf, - 0xefeedf, 0xf0efe0, 0xf1f0e1, 0xf2f1e2, 0xf3f2e3, 0xf4f3e3, 0xf6f3e4, 0xf7f4e5, 0xf8f5e6, 0xf9f6e7, 0xfaf7e8, 0xfbf8e9, 0xfcf9e9, 0xfdfaea, 0xfefbeb, 0xfffcec - } -}; - void svga_render_blank(svga_t *svga) { int x, xx; @@ -107,16 +42,16 @@ void svga_render_blank(svga_t *svga) switch (svga->seqregs[1] & 9) { case 0: - for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 9) + xx + 32 + x_add] = svga_color_transform(0); + for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 9) + xx + 32 + x_add] = 0; break; case 1: - for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 8) + xx + 32 + x_add] = svga_color_transform(0); + for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 8) + xx + 32 + x_add] = 0; break; case 8: - for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 18) + xx + 32 + x_add] = svga_color_transform(0); + for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 18) + xx + 32 + x_add] = 0; break; case 9: - for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 16) + xx + 32 + x_add] = svga_color_transform(0); + for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 16) + xx + 32 + x_add] = 0; break; } } @@ -166,9 +101,6 @@ void svga_render_text_40(svga_t *svga) } } - fg = svga_color_transform(fg); - bg = svga_color_transform(bg); - dat = svga->vram[charaddr + (svga->sc << 2)]; if (svga->seqregs[1] & 1) { @@ -237,9 +169,6 @@ void svga_render_text_80(svga_t *svga) } } - fg = svga_color_transform(fg); - bg = svga_color_transform(bg); - dat = svga->vram[charaddr + (svga->sc << 2)]; if (svga->seqregs[1] & 1) { @@ -306,9 +235,6 @@ void svga_render_text_80_ksc5601(svga_t *svga) } } - fg = svga_color_transform(fg); - bg = svga_color_transform(bg); - if(x + xinc < svga->hdisp && (chr & nextchr & 0x80)) { if((chr == 0xc9 || chr == 0xfe) && (nextchr > 0xa0 && nextchr < 0xff)) @@ -417,14 +343,14 @@ void svga_render_2bpp_lowres(svga_t *svga) svga->ma += 4; svga->ma &= svga->vram_display_mask; - p[0] = p[1] = svga_color_transform(svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]); - p[2] = p[3] = svga_color_transform(svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]); - p[4] = p[5] = svga_color_transform(svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]); - p[6] = p[7] = svga_color_transform(svga->pallook[svga->egapal[dat[0] & 3]]); - p[8] = p[9] = svga_color_transform(svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]); - p[10] = p[11] = svga_color_transform(svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]); - p[12] = p[13] = svga_color_transform(svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]); - p[14] = p[15] = svga_color_transform(svga->pallook[svga->egapal[dat[1] & 3]]); + p[0] = p[1] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]; + p[2] = p[3] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]; + p[4] = p[5] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]; + p[6] = p[7] = svga->pallook[svga->egapal[dat[0] & 3]]; + p[8] = p[9] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]; + p[10] = p[11] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]; + p[12] = p[13] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]; + p[14] = p[15] = svga->pallook[svga->egapal[dat[1] & 3]]; p += 16; } @@ -459,14 +385,14 @@ void svga_render_2bpp_highres(svga_t *svga) svga->ma += 4; svga->ma &= svga->vram_display_mask; - p[0] = svga_color_transform(svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]); - p[1] = svga_color_transform(svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]); - p[2] = svga_color_transform(svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]); - p[3] = svga_color_transform(svga->pallook[svga->egapal[dat[0] & 3]]); - p[4] = svga_color_transform(svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]); - p[5] = svga_color_transform(svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]); - p[6] = svga_color_transform(svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]); - p[7] = svga_color_transform(svga->pallook[svga->egapal[dat[1] & 3]]); + p[0] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]; + p[1] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]; + p[2] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]; + p[3] = svga->pallook[svga->egapal[dat[0] & 3]]; + p[4] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]; + p[5] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]; + p[6] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]; + p[7] = svga->pallook[svga->egapal[dat[1] & 3]]; p += 8; } @@ -498,17 +424,17 @@ void svga_render_4bpp_lowres(svga_t *svga) svga->ma &= svga->vram_display_mask; dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); - p[0] = p[1] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]); - p[2] = p[3] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]); + p[0] = p[1] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[2] = p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); - p[4] = p[5] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]); - p[6] = p[7] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]); + p[4] = p[5] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[6] = p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); - p[8] = p[9] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]); - p[10] = p[11] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]); + p[8] = p[9] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[10] = p[11] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); - p[12] = p[13] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]); - p[14] = p[15] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]); + p[12] = p[13] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[14] = p[15] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; p += 16; } @@ -544,17 +470,17 @@ void svga_render_4bpp_highres(svga_t *svga) svga->ma &= svga->vram_display_mask; dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); - p[0] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]); - p[1] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]); + p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); - p[2] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]); - p[3] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]); + p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); - p[4] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]); - p[5] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]); + p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); - p[6] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]); - p[7] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]); + p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; p += 8; } @@ -580,10 +506,10 @@ void svga_render_8bpp_lowres(svga_t *svga) { uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - p[0] = p[1] = svga_color_transform(svga->pallook[dat & 0xff]); - p[2] = p[3] = svga_color_transform(svga->pallook[(dat >> 8) & 0xff]); - p[4] = p[5] = svga_color_transform(svga->pallook[(dat >> 16) & 0xff]); - p[6] = p[7] = svga_color_transform(svga->pallook[(dat >> 24) & 0xff]); + p[0] = p[1] = svga->pallook[dat & 0xff]; + p[2] = p[3] = svga->pallook[(dat >> 8) & 0xff]; + p[4] = p[5] = svga->pallook[(dat >> 16) & 0xff]; + p[6] = p[7] = svga->pallook[(dat >> 24) & 0xff]; svga->ma += 4; p += 8; @@ -611,16 +537,16 @@ void svga_render_8bpp_highres(svga_t *svga) { uint32_t dat; dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - p[0] = svga_color_transform(svga->pallook[dat & 0xff]); - p[1] = svga_color_transform(svga->pallook[(dat >> 8) & 0xff]); - p[2] = svga_color_transform(svga->pallook[(dat >> 16) & 0xff]); - p[3] = svga_color_transform(svga->pallook[(dat >> 24) & 0xff]); + p[0] = svga->pallook[dat & 0xff]; + p[1] = svga->pallook[(dat >> 8) & 0xff]; + p[2] = svga->pallook[(dat >> 16) & 0xff]; + p[3] = svga->pallook[(dat >> 24) & 0xff]; dat = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); - p[4] = svga_color_transform(svga->pallook[dat & 0xff]); - p[5] = svga_color_transform(svga->pallook[(dat >> 8) & 0xff]); - p[6] = svga_color_transform(svga->pallook[(dat >> 16) & 0xff]); - p[7] = svga_color_transform(svga->pallook[(dat >> 24) & 0xff]); + p[4] = svga->pallook[dat & 0xff]; + p[5] = svga->pallook[(dat >> 8) & 0xff]; + p[6] = svga->pallook[(dat >> 16) & 0xff]; + p[7] = svga->pallook[(dat >> 24) & 0xff]; svga->ma += 8; p += 8; @@ -648,13 +574,13 @@ void svga_render_15bpp_lowres(svga_t *svga) { uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - p[x] = svga_color_transform(video_15to32[dat & 0xffff]); - p[x + 1] = svga_color_transform(video_15to32[dat >> 16]); + p[x] = video_15to32[dat & 0xffff]; + p[x + 1] = video_15to32[dat >> 16]; dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - p[x] = svga_color_transform(video_15to32[dat & 0xffff]); - p[x + 1] = svga_color_transform(video_15to32[dat >> 16]); + p[x] = video_15to32[dat & 0xffff]; + p[x + 1] = video_15to32[dat >> 16]; } svga->ma += x << 1; svga->ma &= svga->vram_display_mask; @@ -679,20 +605,20 @@ void svga_render_15bpp_highres(svga_t *svga) for (x = 0; x <= svga->hdisp; x += 8) { uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - p[x] = svga_color_transform(video_15to32[dat & 0xffff]); - p[x + 1] = svga_color_transform(video_15to32[dat >> 16]); + p[x] = video_15to32[dat & 0xffff]; + p[x + 1] = video_15to32[dat >> 16]; dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - p[x + 2] = svga_color_transform(video_15to32[dat & 0xffff]); - p[x + 3] = svga_color_transform(video_15to32[dat >> 16]); + p[x + 2] = video_15to32[dat & 0xffff]; + p[x + 3] = video_15to32[dat >> 16]; dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); - p[x + 4] = svga_color_transform(video_15to32[dat & 0xffff]); - p[x + 5] = svga_color_transform(video_15to32[dat >> 16]); + p[x + 4] = video_15to32[dat & 0xffff]; + p[x + 5] = video_15to32[dat >> 16]; dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); - p[x + 6] = svga_color_transform(video_15to32[dat & 0xffff]); - p[x + 7] = svga_color_transform(video_15to32[dat >> 16]); + p[x + 6] = video_15to32[dat & 0xffff]; + p[x + 7] = video_15to32[dat >> 16]; } svga->ma += x << 1; svga->ma &= svga->vram_display_mask; @@ -718,13 +644,13 @@ void svga_render_16bpp_lowres(svga_t *svga) { uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - p[x] = svga_color_transform(video_16to32[dat & 0xffff]); - p[x + 1] = svga_color_transform(video_16to32[dat >> 16]); + p[x] = video_16to32[dat & 0xffff]; + p[x + 1] = video_16to32[dat >> 16]; dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - p[x] = svga_color_transform(video_16to32[dat & 0xffff]); - p[x + 1] = svga_color_transform(video_16to32[dat >> 16]); + p[x] = video_16to32[dat & 0xffff]; + p[x + 1] = video_16to32[dat >> 16]; } svga->ma += x << 1; svga->ma &= svga->vram_display_mask; @@ -749,20 +675,20 @@ void svga_render_16bpp_highres(svga_t *svga) for (x = 0; x <= svga->hdisp; x += 8) { uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - p[x] = svga_color_transform(video_16to32[dat & 0xffff]); - p[x + 1] = svga_color_transform(video_16to32[dat >> 16]); + p[x] = video_16to32[dat & 0xffff]; + p[x + 1] = video_16to32[dat >> 16]; dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - p[x + 2] = svga_color_transform(video_16to32[dat & 0xffff]); - p[x + 3] = svga_color_transform(video_16to32[dat >> 16]); + p[x + 2] = video_16to32[dat & 0xffff]; + p[x + 3] = video_16to32[dat >> 16]; dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); - p[x + 4] = svga_color_transform(video_16to32[dat & 0xffff]); - p[x + 5] = svga_color_transform(video_16to32[dat >> 16]); + p[x + 4] = video_16to32[dat & 0xffff]; + p[x + 5] = video_16to32[dat >> 16]; dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); - p[x + 6] = svga_color_transform(video_16to32[dat & 0xffff]); - p[x + 7] = svga_color_transform(video_16to32[dat >> 16]); + p[x + 6] = video_16to32[dat & 0xffff]; + p[x + 7] = video_16to32[dat >> 16]; } svga->ma += x << 1; svga->ma &= svga->vram_display_mask; @@ -790,7 +716,7 @@ void svga_render_24bpp_lowres(svga_t *svga) fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16); svga->ma += 3; svga->ma &= svga->vram_display_mask; - ((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + offset + x_add] = ((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + 1 + offset + x_add] = svga_color_transform(fg); + ((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + offset + x_add] = ((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + 1 + offset + x_add] = fg; } } } @@ -813,16 +739,16 @@ void svga_render_24bpp_highres(svga_t *svga) for (x = 0; x <= svga->hdisp; x += 4) { uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - p[x] = svga_color_transform(dat & 0xffffff); + p[x] = dat & 0xffffff; dat = *(uint32_t *)(&svga->vram[(svga->ma + 3) & svga->vram_display_mask]); - p[x + 1] = svga_color_transform(dat & 0xffffff); + p[x + 1] = dat & 0xffffff; dat = *(uint32_t *)(&svga->vram[(svga->ma + 6) & svga->vram_display_mask]); - p[x + 2] = svga_color_transform(dat & 0xffffff); + p[x + 2] = dat & 0xffffff; dat = *(uint32_t *)(&svga->vram[(svga->ma + 9) & svga->vram_display_mask]); - p[x + 3] = svga_color_transform(dat & 0xffffff); + p[x + 3] = dat & 0xffffff; svga->ma += 12; } @@ -851,7 +777,7 @@ void svga_render_32bpp_lowres(svga_t *svga) fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16); svga->ma += 4; svga->ma &= svga->vram_display_mask; - ((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + offset + x_add] = ((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + 1 + offset + x_add] = svga_color_transform(fg); + ((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + offset + x_add] = ((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + 1 + offset + x_add] = fg; } } } @@ -876,7 +802,7 @@ void svga_render_32bpp_highres(svga_t *svga) for (x = 0; x <= svga->hdisp; x++) { uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); - p[x] = svga_color_transform(dat & 0xffffff); + p[x] = dat & 0xffffff; } svga->ma += 4; svga->ma &= svga->vram_display_mask; @@ -901,7 +827,7 @@ void svga_render_ABGR8888_highres(svga_t *svga) for (x = 0; x <= svga->hdisp; x++) { uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); - p[x] = svga_color_transform((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + p[x] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); } svga->ma += 4; svga->ma &= svga->vram_display_mask; @@ -926,7 +852,7 @@ void svga_render_RGBA8888_highres(svga_t *svga) for (x = 0; x <= svga->hdisp; x++) { uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); - p[x] = svga_color_transform(dat >> 8); + p[x] = dat >> 8; } svga->ma += 4; svga->ma &= svga->vram_display_mask; diff --git a/src/video/vid_table.c b/src/video/vid_table.c index fcb8ff503..a6d153367 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -8,7 +8,7 @@ * * Define all known video cards. * - * Version: @(#)vid_table.c 1.0.26 2018/03/20 + * Version: @(#)vid_table.c 1.0.29 2018/05/10 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -16,11 +16,13 @@ * Copyright 2016-2018 Miran Grca. * Copyright 2017,2018 Fred N. van Kempen. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../machine/machine.h" #include "../mem.h" @@ -48,7 +50,7 @@ #include "vid_mda.h" #ifdef DEV_BRANCH # ifdef USE_RIVA -# include "vid_nv_riva128.h" +# include "vid_nvidia.h" # endif #endif #include "vid_oak_oti.h" @@ -92,7 +94,9 @@ video_cards[] = { { "[ISA] ATI VGA-88 (ATI-18800-1)", "ati18800v", &ati18800_vga88_device, GFX_VGA88, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, { "[ISA] ATI VGA Charger (ATI-28800-5)", "ati28800", &ati28800_device, GFX_VGACHARGER, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}}, { "[ISA] ATI VGA Edge-16 (ATI-18800-5)", "ati18800", &ati18800_device, GFX_VGAEDGE16, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, +#if defined(DEV_BRANCH) && defined(USE_VGAWONDER) { "[ISA] ATI VGA Wonder (ATI-18800)", "ati18800w", &ati18800_wonder_device, GFX_VGAWONDER, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, +#endif #if defined(DEV_BRANCH) && defined(USE_XL24) { "[ISA] ATI VGA Wonder XL24 (ATI-28800-6)", "ati28800w", &ati28800_wonderxl24_device, GFX_VGAWONDERXL24, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}}, #endif @@ -110,7 +114,7 @@ video_cards[] = { { "[ISA] Hercules Plus", "hercules_plus", &herculesplus_device, GFX_HERCULESPLUS, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, { "[ISA] Hercules InColor", "incolor", &incolor_device, GFX_INCOLOR, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, { "[ISA] MDA", "mda", &mda_device, GFX_MDA, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - { "[ISA] MDSI Genius", "genius", &genius_device, GFX_GENIUS, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, + { "[ISA] MDSI Genius", "genius", &genius_device, GFX_GENIUS, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, { "[ISA] OAK OTI-037C", "oti037c", &oti037c_device, GFX_OTI037C, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 6, 8, 16, 6, 8, 16}}, { "[ISA] OAK OTI-067", "oti067", &oti067_device, GFX_OTI067, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 6, 8, 16, 6, 8, 16}}, { "[ISA] OAK OTI-077", "oti077", &oti077_device, GFX_OTI077, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 6, 8, 16, 6, 8, 16}}, @@ -131,6 +135,7 @@ video_cards[] = { {"[PCI] Cirrus Logic CL-GD 5430", "cl_gd5430_pci", &gd5430_pci_device, GFX_CL_GD5430_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, {"[PCI] Cirrus Logic CL-GD 5434", "cl_gd5434_pci", &gd5434_pci_device, GFX_CL_GD5434_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, {"[PCI] Cirrus Logic CL-GD 5436", "cl_gd5436_pci", &gd5436_pci_device, GFX_CL_GD5436_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, + {"[PCI] Cirrus Logic CL-GD 5440", "cl_gd5440_pci", &gd5440_pci_device, GFX_CL_GD5440_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, {"[PCI] Cirrus Logic CL-GD 5446", "cl_gd5446_pci", &gd5446_pci_device, GFX_CL_GD5446_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, {"[PCI] Cirrus Logic CL-GD 5480", "cl_gd5480_pci", &gd5480_pci_device, GFX_CL_GD5480_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, #if defined(DEV_BRANCH) && defined(USE_STEALTH32) @@ -141,8 +146,8 @@ video_cards[] = { {"[PCI] Diamond Stealth 64 DRAM (S3 Trio64)", "stealth64d_pci", &s3_diamond_stealth64_pci_device, GFX_STEALTH64_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 4, 26, 26, 42}}, #if defined(DEV_BRANCH) && defined(USE_RIVA) {"[PCI] nVidia RIVA 128", "riva128", &riva128_device, GFX_RIVA128, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 24, 24, 36}}, - {"[PCI] nVidia RIVA TNT", "rivatnt", &rivatnt_device, GFX_RIVATNT, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 24, 24, 36}}, - {"[PCI] nVidia RIVA TNT2", "rivatnt2", &rivatnt2_device, GFX_RIVATNT2, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 24, 24, 36}}, + /*{"[PCI] nVidia RIVA TNT", "rivatnt", &rivatnt_device, GFX_RIVATNT, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 24, 24, 36}}, + {"[PCI] nVidia RIVA TNT2", "rivatnt2", &rivatnt2_device, GFX_RIVATNT2, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 24, 24, 36}},*/ #endif {"[PCI] Number Nine 9FX (S3 Trio64)", "n9_9fx_pci", &s3_9fx_pci_device, GFX_N9_9FX_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 2, 4, 25, 25, 40}}, {"[PCI] Paradise Bahamas 64 (S3 Vision864)", "bahamas64_pci", &s3_bahamas64_pci_device, GFX_BAHAMAS64_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 5, 20, 20, 35}}, @@ -179,28 +184,49 @@ video_cards[] = { }; +#ifdef ENABLE_VID_TABLE_LOG +int vid_table_do_log = ENABLE_VID_TABLE_LOG; +#endif + + +static void +vid_table_log(const char *fmt, ...) +{ +#ifdef ENABLE_VID_TABLE_LOG + va_list ap; + + if (vid_table_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + void video_reset(int card) { - pclog("VIDEO: reset (romset=%d, gfxcard=%d, internal=%d)\n", + vid_table_log("VIDEO: reset (romset=%d, gfxcard=%d, internal=%d)\n", romset, card, (machines[machine].flags & MACHINE_VIDEO)?1:0); /* Reset the CGA palette. */ cga_palette = 0; cgapal_rebuild(); - /* Do not initialize internal cards here. */ - if ((card == GFX_NONE) || \ - (card == GFX_INTERNAL) || machines[machine].fixed_gfxcard) return; - if (fontdatksc5601) { free(fontdatksc5601); fontdatksc5601 = NULL; } -pclog("VIDEO: initializing '%s'\n", video_cards[video_old_to_new(card)].name); - /* Initialize the video card. */ - device_add(video_cards[video_old_to_new(card)].device); + /* Do not initialize internal cards here. */ + if (!(card == GFX_NONE) && \ + !(card == GFX_INTERNAL) && !machines[machine].fixed_gfxcard) { + vid_table_log("VIDEO: initializing '%s'\n", video_cards[video_old_to_new(card)].name); + + /* Initialize the video card. */ + device_add(video_cards[video_old_to_new(card)].device); + } /* Enable the Voodoo if configured. */ if (voodoo_enabled) diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index bd1846c2c..9b01d5661 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -47,7 +47,7 @@ * access size or host data has any affect, but the Windows 3.1 * driver always reads bytes and write words of 0xffff. * - * Version: @(#)vid_tgui9440.c 1.0.5 2018/03/18 + * Version: @(#)vid_tgui9440.c 1.0.7 2018/07/16 * * Authors: Sarah Walker, * Miran Grca, @@ -686,6 +686,10 @@ void tgui_hwcursor_draw(svga_t *svga, int displine) uint32_t dat[2]; int xx; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + int y_add, x_add; + + y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; + x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 8; @@ -697,9 +701,9 @@ void tgui_hwcursor_draw(svga_t *svga, int displine) if (offset >= svga->hwcursor_latch.x) { if (!(dat[0] & 0x80000000)) - ((uint32_t *)buffer32->line[displine])[offset + 32] = (dat[1] & 0x80000000) ? 0xffffff : 0; + ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] = (dat[1] & 0x80000000) ? 0xffffff : 0; else if (dat[1] & 0x80000000) - ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff; + ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] ^= 0xffffff; } offset++; @@ -864,7 +868,6 @@ static uint8_t tgui_ext_linear_read(uint32_t addr, void *p) int c; cycles -= video_timing_read_b; - cycles_lost += video_timing_read_b; addr &= svga->decode_mask; if (addr >= svga->vram_max) @@ -896,7 +899,6 @@ static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p) uint8_t mask = tgui->ext_gdc_regs[7]; cycles -= video_timing_write_b; - cycles_lost += video_timing_write_b; addr &= svga->decode_mask; if (addr >= svga->vram_max) @@ -966,7 +968,6 @@ static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p) uint16_t mask = (tgui->ext_gdc_regs[7] << 8) | tgui->ext_gdc_regs[8]; cycles -= video_timing_write_w; - cycles_lost += video_timing_write_w; addr &= svga->decode_mask; if (addr >= svga->vram_max) @@ -1729,22 +1730,6 @@ void tgui_accel_write_fb_l(uint32_t addr, uint32_t val, void *p) svga_writel_linear(addr, val, svga); } -void tgui_add_status_info(char *s, int max_len, void *p) -{ - tgui_t *tgui = (tgui_t *)p; - char temps[256]; - uint64_t new_time = plat_timer_read(); - uint64_t status_diff = new_time - tgui->status_time; - tgui->status_time = new_time; - - svga_add_status_info(s, max_len, &tgui->svga); - - sprintf(temps, "%f%% CPU\n%f%% CPU (real)\n\n", ((double)tgui->blitter_time * 100.0) / timer_freq, ((double)tgui->blitter_time * 100.0) / status_diff); - strncat(s, temps, max_len); - - tgui->blitter_time = 0; -} - static const device_config_t tgui9440_config[] = { { @@ -1783,7 +1768,6 @@ const device_t tgui9400cxi_device = tgui9400cxi_available, tgui_speed_changed, tgui_force_redraw, - tgui_add_status_info, tgui9440_config }; @@ -1798,7 +1782,6 @@ const device_t tgui9440_vlb_device = tgui9440_available, tgui_speed_changed, tgui_force_redraw, - tgui_add_status_info, tgui9440_config }; @@ -1813,6 +1796,5 @@ const device_t tgui9440_pci_device = tgui9440_available, tgui_speed_changed, tgui_force_redraw, - tgui_add_status_info, tgui9440_config }; \ No newline at end of file diff --git a/src/video/vid_ti_cf62011.c b/src/video/vid_ti_cf62011.c index cbf3c48b7..d3ec979f1 100644 --- a/src/video/vid_ti_cf62011.c +++ b/src/video/vid_ti_cf62011.c @@ -42,7 +42,7 @@ * which are the same as the XGA. It supports up to 1MB of VRAM, * but we lock it down to 512K. The PS/1 2122 had 256K. * - * Version: @(#)vid_ti_cf62011.c 1.0.4 2018/03/18 + * Version: @(#)vid_ti_cf62011.c 1.0.7 2018/04/29 * * Authors: Sarah Walker, * Miran Grca, @@ -95,7 +95,6 @@ vid_out(uint16_t addr, uint8_t val, void *priv) if (((addr & 0xfff0) == 0x03d0 || (addr & 0xfff0) == 0x03b0) && !(svga->miscout & 1)) addr ^= 0x60; #endif - // pclog("TISVGA_out(%04x, %02x)\n", addr, val); switch (addr) { case 0x0102: @@ -103,10 +102,12 @@ vid_out(uint16_t addr, uint8_t val, void *priv) return; case 0x03d4: - svga->crtcreg = val & 0x1f; + svga->crtcreg = val & 0x3f; return; case 0x03d5: + if (svga->crtcreg & 0x20) + return; if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) return; if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) @@ -174,7 +175,10 @@ vid_in(uint16_t addr, void *priv) break; case 0x03d5: - ret = svga->crtc[svga->crtcreg]; + if (svga->crtcreg & 0x20) + ret = 0xff; + else + ret = svga->crtc[svga->crtcreg]; break; case 0x2100: @@ -194,8 +198,6 @@ vid_in(uint16_t addr, void *priv) break; } - // pclog("TISVGA_in(%04x) = %02x\n", addr, ret); - return(ret); } @@ -218,15 +220,6 @@ vid_force_redraw(void *priv) } -static void -vid_add_status_info(char *s, int max_len, void *priv) -{ - tivga_t *ti = (tivga_t *)priv; - - svga_add_status_info(s, max_len, &ti->svga); -} - - static void vid_close(void *priv) { @@ -253,8 +246,6 @@ vid_init(const device_t *info) else ti->vram_size = info->local; - pclog("VIDEO: initializing %s, %dK VRAM\n", info->name, ti->vram_size); - svga_init(&ti->svga, ti, ti->vram_size<<10, NULL, vid_in, vid_out, NULL, NULL); @@ -304,7 +295,6 @@ const device_t ti_cf62011_device = { NULL, vid_speed_changed, vid_force_redraw, - vid_add_status_info, vid_config }; #endif @@ -318,6 +308,5 @@ const device_t ibm_ps1_2121_device = { NULL, vid_speed_changed, vid_force_redraw, - vid_add_status_info, NULL }; diff --git a/src/video/vid_tvga.c b/src/video/vid_tvga.c index d5865e013..84bc2421e 100644 --- a/src/video/vid_tvga.c +++ b/src/video/vid_tvga.c @@ -8,7 +8,7 @@ * * Trident TVGA (8900D) emulation. * - * Version: @(#)vid_tvga.c 1.0.5 2018/03/18 + * Version: @(#)vid_tvga.c 1.0.6 2018/04/26 * * Authors: Sarah Walker, * Miran Grca, @@ -341,13 +341,6 @@ void tvga_force_redraw(void *p) tvga->svga.fullchange = changeframecount; } -void tvga_add_status_info(char *s, int max_len, void *p) -{ - tvga_t *tvga = (tvga_t *)p; - - svga_add_status_info(s, max_len, &tvga->svga); -} - static const device_config_t tvga_config[] = { { @@ -384,6 +377,5 @@ const device_t tvga8900d_device = tvga8900d_available, tvga_speed_changed, tvga_force_redraw, - tvga_add_status_info, tvga_config }; diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index 2311f5a00..5ea76dc83 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -8,7 +8,7 @@ * * IBM VGA emulation. * - * Version: @(#)vid_vga.c 1.0.4 2018/03/18 + * Version: @(#)vid_vga.c 1.0.5 2018/04/26 * * Authors: Sarah Walker, * Miran Grca, @@ -50,9 +50,11 @@ void vga_out(uint16_t addr, uint8_t val, void *p) switch (addr) { case 0x3D4: - svga->crtcreg = val & 0x1f; + svga->crtcreg = val & 0x3f; return; case 0x3D5: + if (svga->crtcreg & 0x20) + return; if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) return; if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) @@ -87,7 +89,10 @@ uint8_t vga_in(uint16_t addr, void *p) temp = svga->crtcreg; break; case 0x3D5: - temp = svga->crtc[svga->crtcreg]; + if (svga->crtcreg & 0x20) + temp = 0xff; + else + temp = svga->crtc[svga->crtcreg]; break; default: temp = svga_in(addr, svga); @@ -194,13 +199,6 @@ void vga_force_redraw(void *p) vga->svga.fullchange = changeframecount; } -void vga_add_status_info(char *s, int max_len, void *p) -{ - vga_t *vga = (vga_t *)p; - - svga_add_status_info(s, max_len, &vga->svga); -} - const device_t vga_device = { "VGA", @@ -212,7 +210,7 @@ const device_t vga_device = vga_available, vga_speed_changed, vga_force_redraw, - vga_add_status_info + NULL }; #ifdef DEV_BRANCH const device_t trigem_unk_device = @@ -226,7 +224,7 @@ const device_t trigem_unk_device = vga_available, vga_speed_changed, vga_force_redraw, - vga_add_status_info + NULL }; #endif const device_t ps1vga_device = @@ -240,5 +238,5 @@ const device_t ps1vga_device = vga_available, vga_speed_changed, vga_force_redraw, - vga_add_status_info + NULL }; diff --git a/src/video/vid_voodoo.c b/src/video/vid_voodoo.c index 608708bd1..1bbdcc64a 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -8,7 +8,7 @@ * * Emulation of the 3DFX Voodoo Graphics controller. * - * Version: @(#)vid_voodoo.c 1.0.12 2018/03/18 + * Version: @(#)vid_voodoo.c 1.0.14 2018/04/26 * * Authors: Sarah Walker, * leilei @@ -37,18 +37,10 @@ #include "vid_voodoo.h" #include "vid_voodoo_dither.h" -#ifdef MIN -#undef MIN -#endif -#ifdef ABS -#undef ABS -#endif #ifdef CLAMP #undef CLAMP #endif -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - #define CLAMP(x) (((x) < 0) ? 0 : (((x) > 0xff) ? 0xff : (x))) #define CLAMP16(x) (((x) < 0) ? 0 : (((x) > 0xffff) ? 0xffff : (x))) @@ -82,8 +74,6 @@ static uint32_t texture_offset[LOD_MAX+3] = static int tris = 0; -static uint64_t status_time = 0; - typedef union { uint32_t i; float f; @@ -4007,8 +3997,6 @@ enum case 0xf: dst_dat = 0xffff; break; \ } -#define ABS(x) ((x) > 0 ? (x) : -(x)) - static void blit_start(voodoo_t *voodoo) { uint64_t dat64; @@ -4179,15 +4167,29 @@ static void blit_data(voodoo_t *voodoo, uint32_t data) { int src_bits = 32; uint32_t base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8); + uint32_t addr; uint16_t *dst; - + if ((voodoo->bltCommand & BLIT_COMMAND_MASK) != BLIT_COMMAND_CPU_TO_SCREEN) return; if (SLI_ENABLED) - dst = (uint16_t *)&voodoo->fb_mem[base_addr + (voodoo->blt.dst_y >> 1) * voodoo->blt.dst_stride]; + { + addr = base_addr + (voodoo->blt.dst_y >> 1) * voodoo->blt.dst_stride; + dst = (uint16_t *)&voodoo->fb_mem[addr]; + } else - dst = (uint16_t *)&voodoo->fb_mem[base_addr + voodoo->blt.dst_y*voodoo->blt.dst_stride]; + { + addr = base_addr + voodoo->blt.dst_y*voodoo->blt.dst_stride; + dst = (uint16_t *)&voodoo->fb_mem[addr]; + } + + if (addr >= voodoo->front_offset && voodoo->row_width) + { + int y = (addr - voodoo->front_offset) / voodoo->row_width; + if (y < voodoo->v_disp) + voodoo->dirty_line[y] = 2; + } while (src_bits && voodoo->blt.cur_x <= voodoo->blt.size_x) { @@ -7483,93 +7485,6 @@ skip_draw: voodoo->timer_count += TIMER_USEC * 32; } -static void voodoo_add_status_info(char *s, int max_len, void *p) -{ - voodoo_set_t *voodoo_set = (voodoo_set_t *)p; - voodoo_t *voodoo = voodoo_set->voodoos[0]; - voodoo_t *voodoo_slave = voodoo_set->voodoos[1]; - char temps[512], temps2[256]; - int pixel_count_current[2]; - int pixel_count_total; - int texel_count_current[2]; - int texel_count_total; - int render_time[2]; - uint64_t new_time = plat_timer_read(); - uint64_t status_diff = new_time - status_time; - status_time = new_time; - - if (!status_diff) - status_diff = 1; - - svga_add_status_info(s, max_len, &voodoo->svga); - - pixel_count_current[0] = voodoo->pixel_count[0]; - pixel_count_current[1] = voodoo->pixel_count[1]; - texel_count_current[0] = voodoo->texel_count[0]; - texel_count_current[1] = voodoo->texel_count[1]; - render_time[0] = voodoo->render_time[0]; - render_time[1] = voodoo->render_time[1]; - if (voodoo_set->nr_cards == 2) - { - pixel_count_current[0] += voodoo_slave->pixel_count[0]; - pixel_count_current[1] += voodoo_slave->pixel_count[1]; - texel_count_current[0] += voodoo_slave->texel_count[0]; - texel_count_current[1] += voodoo_slave->texel_count[1]; - render_time[0] = (render_time[0] + voodoo_slave->render_time[0]) / 2; - render_time[1] = (render_time[1] + voodoo_slave->render_time[1]) / 2; - } - pixel_count_total = (pixel_count_current[0] + pixel_count_current[1]) - (voodoo->pixel_count_old[0] + voodoo->pixel_count_old[1]); - texel_count_total = (texel_count_current[0] + texel_count_current[1]) - (voodoo->texel_count_old[0] + voodoo->texel_count_old[1]); - sprintf(temps, "%f Mpixels/sec (%f)\n%f Mtexels/sec (%f)\n%f ktris/sec\n%f%% CPU (%f%% real)\n%d frames/sec (%i)\n%f%% CPU (%f%% real)\n"/*%d reads/sec\n%d write/sec\n%d tex/sec\n*/, - (double)pixel_count_total/1000000.0, - ((double)pixel_count_total/1000000.0) / ((double)render_time[0] / status_diff), - (double)texel_count_total/1000000.0, - ((double)texel_count_total/1000000.0) / ((double)render_time[0] / status_diff), - (double)voodoo->tri_count/1000.0, ((double)voodoo->time * 100.0) / timer_freq, ((double)voodoo->time * 100.0) / status_diff, voodoo->frame_count, voodoo_recomp, - ((double)voodoo->render_time[0] * 100.0) / timer_freq, ((double)voodoo->render_time[0] * 100.0) / status_diff); - if (voodoo->render_threads == 2) - { - sprintf(temps2, "%f%% CPU (%f%% real)\n", - ((double)voodoo->render_time[1] * 100.0) / timer_freq, ((double)voodoo->render_time[1] * 100.0) / status_diff); - strncat(temps, temps2, sizeof(temps)-1); - } - if (voodoo_set->nr_cards == 2) - { - sprintf(temps2, "%f%% CPU (%f%% real)\n", - ((double)voodoo_slave->render_time[0] * 100.0) / timer_freq, ((double)voodoo_slave->render_time[0] * 100.0) / status_diff); - strncat(temps, temps2, sizeof(temps)-1); - - if (voodoo_slave->render_threads == 2) - { - sprintf(temps2, "%f%% CPU (%f%% real)\n", - ((double)voodoo_slave->render_time[1] * 100.0) / timer_freq, ((double)voodoo_slave->render_time[1] * 100.0) / status_diff); - strncat(temps, temps2, sizeof(temps)-1); - } - } - strncat(s, temps, max_len); - - voodoo->pixel_count_old[0] = pixel_count_current[0]; - voodoo->pixel_count_old[1] = pixel_count_current[1]; - voodoo->texel_count_old[0] = texel_count_current[0]; - voodoo->texel_count_old[1] = texel_count_current[1]; - voodoo->tri_count = voodoo->frame_count = 0; - voodoo->rd_count = voodoo->wr_count = voodoo->tex_count = 0; - voodoo->time = 0; - voodoo->render_time[0] = voodoo->render_time[1] = 0; - if (voodoo_set->nr_cards == 2) - { - voodoo_slave->pixel_count_old[0] = pixel_count_current[0]; - voodoo_slave->pixel_count_old[1] = pixel_count_current[1]; - voodoo_slave->texel_count_old[0] = texel_count_current[0]; - voodoo_slave->texel_count_old[1] = texel_count_current[1]; - voodoo_slave->tri_count = voodoo_slave->frame_count = 0; - voodoo_slave->rd_count = voodoo_slave->wr_count = voodoo_slave->tex_count = 0; - voodoo_slave->time = 0; - voodoo_slave->render_time[0] = voodoo_slave->render_time[1] = 0; - } - voodoo_recomp = 0; -} - static void voodoo_speed_changed(void *p) { voodoo_set_t *voodoo_set = (voodoo_set_t *)p; @@ -7969,6 +7884,5 @@ const device_t voodoo_device = NULL, voodoo_speed_changed, NULL, - voodoo_add_status_info, voodoo_config }; diff --git a/src/video/vid_wy700.c b/src/video/vid_wy700.c index 0f93813e8..814da2cca 100644 --- a/src/video/vid_wy700.c +++ b/src/video/vid_wy700.c @@ -8,7 +8,7 @@ * * Wyse-700 emulation. * - * Version: @(#)vid_wy700.c 1.0.7 2018/03/18 + * Version: @(#)vid_wy700.c 1.0.9 2018/05/20 * * Authors: Sarah Walker, * Miran Grca, @@ -906,6 +906,8 @@ void *wy700_init(const device_t *info) /* 128k video RAM */ wy700->vram = malloc(0x20000); + loadfont(L"roms/video/wyse700/wy700.rom", 3); + timer_add(wy700_poll, &wy700->vidtime, TIMER_ALWAYS_ENABLED, wy700); /* Occupy memory between 0xB0000 and 0xBFFFF (moves to 0xA0000 in @@ -1014,7 +1016,6 @@ const device_t wy700_device = NULL, NULL, wy700_speed_changed, - NULL, NULL, NULL }; diff --git a/src/video/video.c b/src/video/video.c index 8e7654617..ae7085e96 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -40,7 +40,7 @@ * W = 3 bus clocks * L = 4 bus clocks * - * Version: @(#)video.c 1.0.21 2018/03/19 + * Version: @(#)video.c 1.0.23 2018/05/25 * * Authors: Sarah Walker, * Miran Grca, @@ -106,15 +106,12 @@ int video_timing_write_b = 0, int video_res_x = 0, video_res_y = 0, video_bpp = 0; -int video_timing[6][4] = { - { VIDEO_ISA, 8, 16, 32 }, - { VIDEO_ISA, 6, 8, 16 }, - { VIDEO_ISA, 3, 3, 6 }, - { VIDEO_BUS, 4, 8, 16 }, - { VIDEO_BUS, 4, 5, 10 }, - { VIDEO_BUS, 3, 3, 4 } -}; static int video_force_resize; +int invert_display = 0; +int video_grayscale = 0; +int video_graytype = 0; + + PALETTE cgapal = { {0,0,0}, {0,42,0}, {42,0,0}, {42,21,0}, {0,0,0}, {0,42,42}, {42,0,42}, {42,42,42}, @@ -182,6 +179,67 @@ PALETTE cgapal_mono[6] = { }; +const uint32_t shade[5][256] = +{ + {0}, // RGB Color (unused) + {0}, // RGB Grayscale (unused) + { // Amber monitor + 0x000000, 0x060000, 0x090000, 0x0d0000, 0x100000, 0x120100, 0x150100, 0x170100, 0x1a0100, 0x1c0100, 0x1e0200, 0x210200, 0x230200, 0x250300, 0x270300, 0x290300, + 0x2b0400, 0x2d0400, 0x2f0400, 0x300500, 0x320500, 0x340500, 0x360600, 0x380600, 0x390700, 0x3b0700, 0x3d0700, 0x3f0800, 0x400800, 0x420900, 0x440900, 0x450a00, + 0x470a00, 0x480b00, 0x4a0b00, 0x4c0c00, 0x4d0c00, 0x4f0d00, 0x500d00, 0x520e00, 0x530e00, 0x550f00, 0x560f00, 0x581000, 0x591000, 0x5b1100, 0x5c1200, 0x5e1200, + 0x5f1300, 0x601300, 0x621400, 0x631500, 0x651500, 0x661600, 0x671600, 0x691700, 0x6a1800, 0x6c1800, 0x6d1900, 0x6e1a00, 0x701a00, 0x711b00, 0x721c00, 0x741c00, + 0x751d00, 0x761e00, 0x781e00, 0x791f00, 0x7a2000, 0x7c2000, 0x7d2100, 0x7e2200, 0x7f2300, 0x812300, 0x822400, 0x832500, 0x842600, 0x862600, 0x872700, 0x882800, + 0x8a2900, 0x8b2900, 0x8c2a00, 0x8d2b00, 0x8e2c00, 0x902c00, 0x912d00, 0x922e00, 0x932f00, 0x953000, 0x963000, 0x973100, 0x983200, 0x993300, 0x9b3400, 0x9c3400, + 0x9d3500, 0x9e3600, 0x9f3700, 0xa03800, 0xa23900, 0xa33a00, 0xa43a00, 0xa53b00, 0xa63c00, 0xa73d00, 0xa93e00, 0xaa3f00, 0xab4000, 0xac4000, 0xad4100, 0xae4200, + 0xaf4300, 0xb14400, 0xb24500, 0xb34600, 0xb44700, 0xb54800, 0xb64900, 0xb74a00, 0xb94a00, 0xba4b00, 0xbb4c00, 0xbc4d00, 0xbd4e00, 0xbe4f00, 0xbf5000, 0xc05100, + 0xc15200, 0xc25300, 0xc45400, 0xc55500, 0xc65600, 0xc75700, 0xc85800, 0xc95900, 0xca5a00, 0xcb5b00, 0xcc5c00, 0xcd5d00, 0xce5e00, 0xcf5f00, 0xd06000, 0xd26101, + 0xd36201, 0xd46301, 0xd56401, 0xd66501, 0xd76601, 0xd86701, 0xd96801, 0xda6901, 0xdb6a01, 0xdc6b01, 0xdd6c01, 0xde6d01, 0xdf6e01, 0xe06f01, 0xe17001, 0xe27201, + 0xe37301, 0xe47401, 0xe57501, 0xe67602, 0xe77702, 0xe87802, 0xe97902, 0xeb7a02, 0xec7b02, 0xed7c02, 0xee7e02, 0xef7f02, 0xf08002, 0xf18103, 0xf28203, 0xf38303, + 0xf48403, 0xf58503, 0xf68703, 0xf78803, 0xf88903, 0xf98a04, 0xfa8b04, 0xfb8c04, 0xfc8d04, 0xfd8f04, 0xfe9005, 0xff9105, 0xff9205, 0xff9305, 0xff9405, 0xff9606, + 0xff9706, 0xff9806, 0xff9906, 0xff9a07, 0xff9b07, 0xff9d07, 0xff9e08, 0xff9f08, 0xffa008, 0xffa109, 0xffa309, 0xffa409, 0xffa50a, 0xffa60a, 0xffa80a, 0xffa90b, + 0xffaa0b, 0xffab0c, 0xffac0c, 0xffae0d, 0xffaf0d, 0xffb00e, 0xffb10e, 0xffb30f, 0xffb40f, 0xffb510, 0xffb610, 0xffb811, 0xffb912, 0xffba12, 0xffbb13, 0xffbd14, + 0xffbe14, 0xffbf15, 0xffc016, 0xffc217, 0xffc317, 0xffc418, 0xffc619, 0xffc71a, 0xffc81b, 0xffca1c, 0xffcb1d, 0xffcc1e, 0xffcd1f, 0xffcf20, 0xffd021, 0xffd122, + 0xffd323, 0xffd424, 0xffd526, 0xffd727, 0xffd828, 0xffd92a, 0xffdb2b, 0xffdc2c, 0xffdd2e, 0xffdf2f, 0xffe031, 0xffe133, 0xffe334, 0xffe436, 0xffe538, 0xffe739 + }, + { // Green monitor + 0x000000, 0x000400, 0x000700, 0x000900, 0x000b00, 0x000d00, 0x000f00, 0x001100, 0x001300, 0x001500, 0x001600, 0x001800, 0x001a00, 0x001b00, 0x001d00, 0x001e00, + 0x002000, 0x002100, 0x002300, 0x002400, 0x002601, 0x002701, 0x002901, 0x002a01, 0x002b01, 0x002d01, 0x002e01, 0x002f01, 0x003101, 0x003201, 0x003301, 0x003401, + 0x003601, 0x003702, 0x003802, 0x003902, 0x003b02, 0x003c02, 0x003d02, 0x003e02, 0x004002, 0x004102, 0x004203, 0x004303, 0x004403, 0x004503, 0x004703, 0x004803, + 0x004903, 0x004a03, 0x004b04, 0x004c04, 0x004d04, 0x004e04, 0x005004, 0x005104, 0x005205, 0x005305, 0x005405, 0x005505, 0x005605, 0x005705, 0x005806, 0x005906, + 0x005a06, 0x005b06, 0x005d06, 0x005e07, 0x005f07, 0x006007, 0x006107, 0x006207, 0x006308, 0x006408, 0x006508, 0x006608, 0x006708, 0x006809, 0x006909, 0x006a09, + 0x006b09, 0x016c0a, 0x016d0a, 0x016e0a, 0x016f0a, 0x01700b, 0x01710b, 0x01720b, 0x01730b, 0x01740c, 0x01750c, 0x01760c, 0x01770c, 0x01780d, 0x01790d, 0x017a0d, + 0x017b0d, 0x017b0e, 0x017c0e, 0x017d0e, 0x017e0f, 0x017f0f, 0x01800f, 0x018110, 0x028210, 0x028310, 0x028410, 0x028511, 0x028611, 0x028711, 0x028812, 0x028912, + 0x028a12, 0x028a13, 0x028b13, 0x028c13, 0x028d14, 0x028e14, 0x038f14, 0x039015, 0x039115, 0x039215, 0x039316, 0x039416, 0x039417, 0x039517, 0x039617, 0x039718, + 0x049818, 0x049918, 0x049a19, 0x049b19, 0x049c19, 0x049c1a, 0x049d1a, 0x049e1b, 0x059f1b, 0x05a01b, 0x05a11c, 0x05a21c, 0x05a31c, 0x05a31d, 0x05a41d, 0x06a51e, + 0x06a61e, 0x06a71f, 0x06a81f, 0x06a920, 0x06aa20, 0x07aa21, 0x07ab21, 0x07ac21, 0x07ad22, 0x07ae22, 0x08af23, 0x08b023, 0x08b024, 0x08b124, 0x08b225, 0x09b325, + 0x09b426, 0x09b526, 0x09b527, 0x0ab627, 0x0ab728, 0x0ab828, 0x0ab929, 0x0bba29, 0x0bba2a, 0x0bbb2a, 0x0bbc2b, 0x0cbd2b, 0x0cbe2c, 0x0cbf2c, 0x0dbf2d, 0x0dc02d, + 0x0dc12e, 0x0ec22e, 0x0ec32f, 0x0ec42f, 0x0fc430, 0x0fc530, 0x0fc631, 0x10c731, 0x10c832, 0x10c932, 0x11c933, 0x11ca33, 0x11cb34, 0x12cc35, 0x12cd35, 0x12cd36, + 0x13ce36, 0x13cf37, 0x13d037, 0x14d138, 0x14d139, 0x14d239, 0x15d33a, 0x15d43a, 0x16d43b, 0x16d53b, 0x17d63c, 0x17d73d, 0x17d83d, 0x18d83e, 0x18d93e, 0x19da3f, + 0x19db40, 0x1adc40, 0x1adc41, 0x1bdd41, 0x1bde42, 0x1cdf43, 0x1ce043, 0x1de044, 0x1ee145, 0x1ee245, 0x1fe346, 0x1fe446, 0x20e447, 0x20e548, 0x21e648, 0x22e749, + 0x22e74a, 0x23e84a, 0x23e94b, 0x24ea4c, 0x25ea4c, 0x25eb4d, 0x26ec4e, 0x27ed4e, 0x27ee4f, 0x28ee50, 0x29ef50, 0x29f051, 0x2af152, 0x2bf153, 0x2cf253, 0x2cf354, + 0x2df455, 0x2ef455, 0x2ff556, 0x2ff657, 0x30f758, 0x31f758, 0x32f859, 0x32f95a, 0x33fa5a, 0x34fa5b, 0x35fb5c, 0x36fc5d, 0x37fd5d, 0x38fd5e, 0x38fe5f, 0x39ff60 + }, + { // White monitor + 0x000000, 0x010102, 0x020203, 0x020304, 0x030406, 0x040507, 0x050608, 0x060709, 0x07080a, 0x08090c, 0x080a0d, 0x090b0e, 0x0a0c0f, 0x0b0d10, 0x0c0e11, 0x0d0f12, + 0x0e1013, 0x0f1115, 0x101216, 0x111317, 0x121418, 0x121519, 0x13161a, 0x14171b, 0x15181c, 0x16191d, 0x171a1e, 0x181b1f, 0x191c20, 0x1a1d21, 0x1b1e22, 0x1c1f23, + 0x1d2024, 0x1e2125, 0x1f2226, 0x202327, 0x212428, 0x222529, 0x22262b, 0x23272c, 0x24282d, 0x25292e, 0x262a2f, 0x272b30, 0x282c30, 0x292d31, 0x2a2e32, 0x2b2f33, + 0x2c3034, 0x2d3035, 0x2e3136, 0x2f3237, 0x303338, 0x313439, 0x32353a, 0x33363b, 0x34373c, 0x35383d, 0x36393e, 0x373a3f, 0x383b40, 0x393c41, 0x3a3d42, 0x3b3e43, + 0x3c3f44, 0x3d4045, 0x3e4146, 0x3f4247, 0x404348, 0x414449, 0x42454a, 0x43464b, 0x44474c, 0x45484d, 0x46494d, 0x474a4e, 0x484b4f, 0x484c50, 0x494d51, 0x4a4e52, + 0x4b4f53, 0x4c5054, 0x4d5155, 0x4e5256, 0x4f5357, 0x505458, 0x515559, 0x52565a, 0x53575b, 0x54585b, 0x55595c, 0x565a5d, 0x575b5e, 0x585c5f, 0x595d60, 0x5a5e61, + 0x5b5f62, 0x5c6063, 0x5d6164, 0x5e6265, 0x5f6366, 0x606466, 0x616567, 0x626668, 0x636769, 0x64686a, 0x65696b, 0x666a6c, 0x676b6d, 0x686c6e, 0x696d6f, 0x6a6e70, + 0x6b6f70, 0x6c7071, 0x6d7172, 0x6f7273, 0x707374, 0x707475, 0x717576, 0x727677, 0x747778, 0x757879, 0x767979, 0x777a7a, 0x787b7b, 0x797c7c, 0x7a7d7d, 0x7b7e7e, + 0x7c7f7f, 0x7d8080, 0x7e8181, 0x7f8281, 0x808382, 0x818483, 0x828584, 0x838685, 0x848786, 0x858887, 0x868988, 0x878a89, 0x888b89, 0x898c8a, 0x8a8d8b, 0x8b8e8c, + 0x8c8f8d, 0x8d8f8e, 0x8e908f, 0x8f9190, 0x909290, 0x919391, 0x929492, 0x939593, 0x949694, 0x959795, 0x969896, 0x979997, 0x989a98, 0x999b98, 0x9a9c99, 0x9b9d9a, + 0x9c9e9b, 0x9d9f9c, 0x9ea09d, 0x9fa19e, 0xa0a29f, 0xa1a39f, 0xa2a4a0, 0xa3a5a1, 0xa4a6a2, 0xa6a7a3, 0xa7a8a4, 0xa8a9a5, 0xa9aaa5, 0xaaaba6, 0xabaca7, 0xacada8, + 0xadaea9, 0xaeafaa, 0xafb0ab, 0xb0b1ac, 0xb1b2ac, 0xb2b3ad, 0xb3b4ae, 0xb4b5af, 0xb5b6b0, 0xb6b7b1, 0xb7b8b2, 0xb8b9b2, 0xb9bab3, 0xbabbb4, 0xbbbcb5, 0xbcbdb6, + 0xbdbeb7, 0xbebfb8, 0xbfc0b8, 0xc0c1b9, 0xc1c2ba, 0xc2c3bb, 0xc3c4bc, 0xc5c5bd, 0xc6c6be, 0xc7c7be, 0xc8c8bf, 0xc9c9c0, 0xcacac1, 0xcbcbc2, 0xccccc3, 0xcdcdc3, + 0xcecec4, 0xcfcfc5, 0xd0d0c6, 0xd1d1c7, 0xd2d2c8, 0xd3d3c9, 0xd4d4c9, 0xd5d5ca, 0xd6d6cb, 0xd7d7cc, 0xd8d8cd, 0xd9d9ce, 0xdadacf, 0xdbdbcf, 0xdcdcd0, 0xdeddd1, + 0xdfded2, 0xe0dfd3, 0xe1e0d4, 0xe2e1d4, 0xe3e2d5, 0xe4e3d6, 0xe5e4d7, 0xe6e5d8, 0xe7e6d9, 0xe8e7d9, 0xe9e8da, 0xeae9db, 0xebeadc, 0xecebdd, 0xedecde, 0xeeeddf, + 0xefeedf, 0xf0efe0, 0xf1f0e1, 0xf2f1e2, 0xf3f2e3, 0xf4f3e3, 0xf6f3e4, 0xf7f4e5, 0xf8f5e6, 0xf9f6e7, 0xfaf7e8, 0xfbf8e9, 0xfcf9e9, 0xfdfaea, 0xfefbeb, 0xfffcec + } +}; + + static struct { int x, y, y1, y2, w, h; int busy; @@ -361,94 +419,76 @@ video_update_timing(void) video_timings_t *timing; int new_gfxcard; - if (video_speed == -1) { - new_gfxcard = 0; + new_gfxcard = 0; - switch(romset) { - case ROM_IBMPCJR: - case ROM_TANDY: - case ROM_TANDY1000HX: - case ROM_TANDY1000SL2: - timing = &timing_dram; - break; - case ROM_PC1512: - timing = &timing_pc1512; - break; - case ROM_PC1640: - timing = &timing_pc1640; - break; - case ROM_PC200: - timing = &timing_pc200; - break; - case ROM_OLIM24: - timing = &timing_m24; - break; - case ROM_PC2086: - case ROM_PC3086: - timing = &timing_pvga1a; - break; - case ROM_T1000: - case ROM_T1200: - timing = &timing_t1000; - break; - case ROM_MEGAPC: - case ROM_MEGAPCDX: - timing = &timing_wd90c11; - break; - case ROM_IBMPS1_2011: - case ROM_IBMPS2_M30_286: - case ROM_IBMPS2_M50: - case ROM_IBMPS2_M55SX: - case ROM_IBMPS2_M80: - timing = &timing_vga; - break; - case ROM_IBMPS1_2121: - case ROM_IBMPS1_2133: - timing = &timing_ps1_svga; - break; - case ROM_T3100E: - timing = &timing_t3100e; - break; - case ROM_ENDEAVOR: - timing = &timing_endeavor; - break; - default: - new_gfxcard = video_old_to_new(gfxcard); - timing = video_card_gettiming(new_gfxcard); - break; - } + switch(romset) { + case ROM_IBMPCJR: + case ROM_TANDY: + case ROM_TANDY1000HX: + case ROM_TANDY1000SL2: + timing = &timing_dram; + break; + case ROM_PC1512: + timing = &timing_pc1512; + break; + case ROM_PC1640: + timing = &timing_pc1640; + break; + case ROM_PC200: + timing = &timing_pc200; + break; + case ROM_OLIM24: + timing = &timing_m24; + break; + case ROM_PC2086: + case ROM_PC3086: + timing = &timing_pvga1a; + break; + case ROM_T1000: + case ROM_T1200: + timing = &timing_t1000; + break; + case ROM_MEGAPC: + case ROM_MEGAPCDX: + timing = &timing_wd90c11; + break; + case ROM_IBMPS1_2011: + case ROM_IBMPS2_M30_286: + case ROM_IBMPS2_M50: + case ROM_IBMPS2_M55SX: + case ROM_IBMPS2_M80: + timing = &timing_vga; + break; + case ROM_IBMPS1_2121: + case ROM_IBMPS1_2133: + timing = &timing_ps1_svga; + break; + case ROM_T3100E: + timing = &timing_t3100e; + break; + case ROM_ENDEAVOR: + timing = &timing_endeavor; + break; + default: + new_gfxcard = video_old_to_new(gfxcard); + timing = video_card_gettiming(new_gfxcard); + break; + } - if (timing->type == VIDEO_ISA) { - video_timing_read_b = ISA_CYCLES(timing->read_b); - video_timing_read_w = ISA_CYCLES(timing->read_w); - video_timing_read_l = ISA_CYCLES(timing->read_l); - video_timing_write_b = ISA_CYCLES(timing->write_b); - video_timing_write_w = ISA_CYCLES(timing->write_w); - video_timing_write_l = ISA_CYCLES(timing->write_l); - } else { - video_timing_read_b = (int)(bus_timing * timing->read_b); - video_timing_read_w = (int)(bus_timing * timing->read_w); - video_timing_read_l = (int)(bus_timing * timing->read_l); - video_timing_write_b = (int)(bus_timing * timing->write_b); - video_timing_write_w = (int)(bus_timing * timing->write_w); - video_timing_write_l = (int)(bus_timing * timing->write_l); - } - } else { - if (video_timing[video_speed][0] == VIDEO_ISA) { - video_timing_read_b = ISA_CYCLES(video_timing[video_speed][1]); - video_timing_read_w = ISA_CYCLES(video_timing[video_speed][2]); - video_timing_read_l = ISA_CYCLES(video_timing[video_speed][3]); - video_timing_write_b = ISA_CYCLES(video_timing[video_speed][1]); - video_timing_write_w = ISA_CYCLES(video_timing[video_speed][2]); - video_timing_write_l = ISA_CYCLES(video_timing[video_speed][3]); - } else { - video_timing_read_b = (int)(bus_timing * video_timing[video_speed][1]); - video_timing_read_w = (int)(bus_timing * video_timing[video_speed][2]); - video_timing_read_l = (int)(bus_timing * video_timing[video_speed][3]); - video_timing_write_b = (int)(bus_timing * video_timing[video_speed][1]); - video_timing_write_w = (int)(bus_timing * video_timing[video_speed][2]); - video_timing_write_l = (int)(bus_timing * video_timing[video_speed][3]); - } + if (timing->type == VIDEO_ISA) { + video_timing_read_b = ISA_CYCLES(timing->read_b); + video_timing_read_w = ISA_CYCLES(timing->read_w); + video_timing_read_l = ISA_CYCLES(timing->read_l); + video_timing_write_b = ISA_CYCLES(timing->write_b); + video_timing_write_w = ISA_CYCLES(timing->write_w); + video_timing_write_l = ISA_CYCLES(timing->write_l); + } else { + video_timing_read_b = (int)(bus_timing * timing->read_b); + video_timing_read_w = (int)(bus_timing * timing->read_w); + video_timing_read_l = (int)(bus_timing * timing->read_l); + video_timing_write_b = (int)(bus_timing * timing->write_b); + video_timing_write_w = (int)(bus_timing * timing->write_w); + video_timing_write_l = (int)(bus_timing * timing->write_l); } if (cpu_16bitbus) { @@ -691,10 +731,8 @@ loadfont(wchar_t *s, int format) int c,d; f = rom_fopen(s, L"rb"); - if (f == NULL) { - pclog("VIDEO: cannot load font '%ls', fmt=%d\n", s, format); + if (f == NULL) return; - } switch (format) { case 0: /* MDA */ @@ -792,3 +830,46 @@ loadfont(wchar_t *s, int format) (void)fclose(f); } + + +uint32_t +video_color_transform(uint32_t color) +{ + uint8_t *clr8 = (uint8_t *) &color; + /* if (!video_grayscale && !invert_display) + return color; */ + if (video_grayscale) { + if (video_graytype) { + if (video_graytype == 1) + color = ((54 * (uint32_t)clr8[2]) + (183 * (uint32_t)clr8[1]) + (18 * (uint32_t)clr8[0])) / 255; + else + color = ((uint32_t)clr8[2] + (uint32_t)clr8[1] + (uint32_t)clr8[0]) / 3; + } else + color = ((76 * (uint32_t)clr8[2]) + (150 * (uint32_t)clr8[1]) + (29 * (uint32_t)clr8[0])) / 255; + switch (video_grayscale) { + case 2: case 3: case 4: + color = (uint32_t) shade[video_grayscale][color]; + break; + default: + clr8[3] = 0; + clr8[0] = color; + clr8[1] = clr8[2] = clr8[0]; + break; + } + } + if (invert_display) + color ^= 0x00ffffff; + return color; +} + +void +video_transform_copy(uint32_t *dst, uint32_t *src, int len) +{ + int i; + + for (i = 0; i < len; i++) { + *dst = video_color_transform(*src); + dst++; + src++; + } +} diff --git a/src/video/video.h b/src/video/video.h index 99b54a66f..fec490fb3 100644 --- a/src/video/video.h +++ b/src/video/video.h @@ -8,7 +8,7 @@ * * Definitions for the video controller module. * - * Version: @(#)video.h 1.0.25 2018/03/20 + * Version: @(#)video.h 1.0.29 2018/07/17 * * Authors: Sarah Walker, * Miran Grca, @@ -22,9 +22,6 @@ # define EMU_VIDEO_H -#define FONT_ATIKOR_PATH L"roms/video/ati28800/ati_ksc5601.rom" - - #define makecol(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) #define makecol32(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) @@ -65,7 +62,9 @@ enum { GFX_VGA88, /* ATI VGA-88 (18800-1) */ GFX_VGAEDGE16, /* ATI VGA Edge-16 (18800-1) */ GFX_VGACHARGER, /* ATI VGA Charger (28800-5) */ +#if defined(DEV_BRANCH) && defined(USE_VGAWONDER) GFX_VGAWONDER, /* Compaq ATI VGA Wonder (18800) */ +#endif GFX_VGAWONDERXL, /* Compaq ATI VGA Wonder XL (28800-5) */ #if defined(DEV_BRANCH) && defined(USE_XL24) GFX_VGAWONDERXL24, /* Compaq ATI VGA Wonder XL24 (28800-6) */ @@ -87,6 +86,7 @@ enum { GFX_CL_GD5434_VLB, /* Cirrus Logic CL-GD 5434 VLB */ GFX_CL_GD5434_PCI, /* Cirrus Logic CL-GD 5434 PCI */ GFX_CL_GD5436_PCI, /* Cirrus Logic CL-GD 5436 PCI */ + GFX_CL_GD5440_PCI, /* Cirrus Logic CL-GD 5440 PCI */ GFX_CL_GD5446_PCI, /* Cirrus Logic CL-GD 5446 PCI */ GFX_CL_GD5446_STB_PCI, /* STB Nitro 64V (Cirrus Logic CL-GD 5446) PCI */ GFX_CL_GD5480_PCI, /* Cirrus Logic CL-GD 5480 PCI */ @@ -147,7 +147,7 @@ typedef struct { typedef struct { int w, h; uint8_t *dat; - uint8_t *line[]; + uint8_t *line[2048]; } bitmap_t; typedef struct { @@ -194,7 +194,6 @@ extern int video_timing_read_b, extern int video_timing_write_b, video_timing_write_w, video_timing_write_l; -extern int video_speed; extern int video_res_x, video_res_y, video_bpp; @@ -261,6 +260,9 @@ extern int get_actual_size_y(void); extern void svga_dump_vram(void); #endif +extern uint32_t video_color_transform(uint32_t color); +extern void video_transform_copy(uint32_t *dst, uint32_t *src, int len); + #ifdef __cplusplus } #endif diff --git a/src/vnc.c b/src/vnc.c index 7ec3ec2d8..8ee76bea6 100644 --- a/src/vnc.c +++ b/src/vnc.c @@ -8,19 +8,21 @@ * * Implement the VNC remote renderer with LibVNCServer. * - * Version: @(#)vnc.c 1.0.10 2017/12/15 + * Version: @(#)vnc.c 1.0.12 2018/05/26 * * Authors: Fred N. van Kempen, * Based on raw code by RichardG, * - * Copyright 2017 Fred N. van Kempen. + * Copyright 2017,2018 Fred N. van Kempen. */ +#include #include #include #include #include #include #include +#define HAVE_STDARG_H #include "86box.h" #include "device.h" #include "video/video.h" @@ -45,6 +47,26 @@ static int allowedX, static int ptr_x, ptr_y, ptr_but; +#ifdef ENABLE_VNC_LOG +int vnc_do_log = ENABLE_VNC_LOG; +#endif + + +static void +vnc_log(const char *format, ...) +{ +#ifdef ENABLE_VNC_LOG + va_list ap; + + if (vnc_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + static void vnc_kbdevent(rfbBool down, rfbKeySym k, rfbClientPtr cl) { @@ -85,13 +107,13 @@ vnc_ptrevent(int but, int x, int y, rfbClientPtr cl) static void vnc_clientgone(rfbClientPtr cl) { - pclog("VNC: client disconnected: %s\n", cl->host); + vnc_log("VNC: client disconnected: %s\n", cl->host); if (clients > 0) clients--; if (clients == 0) { /* No more clients, pause the emulator. */ - pclog("VNC: no clients, pausing..\n"); + vnc_log("VNC: no clients, pausing..\n"); /* Disable the mouse. */ plat_mouse_capture(0); @@ -107,7 +129,7 @@ vnc_newclient(rfbClientPtr cl) /* Hook the ClientGone function so we know when they're gone. */ cl->clientGoneHook = vnc_clientgone; - pclog("VNC: new client: %s\n", cl->host); + vnc_log("VNC: new client: %s\n", cl->host); if (++clients == 1) { /* Reset the mouse. */ ptr_x = allowedX/2; @@ -116,7 +138,7 @@ vnc_newclient(rfbClientPtr cl) mouse_buttons = 0x00; /* We now have clients, un-pause the emulator if needed. */ - pclog("VNC: unpausing..\n"); + vnc_log("VNC: unpausing..\n"); /* Enable the mouse. */ plat_mouse_capture(1); @@ -147,14 +169,18 @@ vnc_display(rfbClientPtr cl) static void vnc_blit(int x, int y, int y1, int y2, int w, int h) { - uint32_t *p; + uint32_t *p, *q; int yy; for (yy=y1; yyframeBuffer)[yy*VNC_MAX_X]); - if ((y+yy) >= 0 && (y+yy) < VNC_MAX_Y) - memcpy(p, &(((uint32_t *)buffer32->line[y+yy])[x]), w*4); + if ((y+yy) >= 0 && (y+yy) < VNC_MAX_Y) { + if (video_grayscale || invert_display) + video_transform_copy(p, &(((uint32_t *)buffer32->line[y+yy])[x]), w); + else + memcpy(p, &(((uint32_t *)buffer32->line[y+yy])[x]), w*4); + } } video_blit_complete(); @@ -215,7 +241,7 @@ vnc_init(UNUSED(void *arg)) clients = 0; - pclog("VNC: init complete.\n"); + vnc_log("VNC: init complete.\n"); return(1); } @@ -246,12 +272,12 @@ vnc_resize(int x, int y) /* TightVNC doesn't like certain sizes.. */ if (x < VNC_MIN_X || x > VNC_MAX_X || y < VNC_MIN_Y || y > VNC_MAX_Y) { - pclog("VNC: invalid resoltion %dx%d requested!\n", x, y); + vnc_log("VNC: invalid resoltion %dx%d requested!\n", x, y); return; } if ((x != rfb->width || y != rfb->height) && x > 160 && y > 0) { - pclog("VNC: updating resolution: %dx%d\n", x, y); + vnc_log("VNC: updating resolution: %dx%d\n", x, y); allowedX = (rfb->width < x) ? rfb->width : x; allowedY = (rfb->width < y) ? rfb->width : y; @@ -280,5 +306,5 @@ vnc_pause(void) void vnc_take_screenshot(wchar_t *fn) { - pclog("VNC: take_screenshot\n"); + vnc_log("VNC: take_screenshot\n"); } diff --git a/src/vnc_keymap.c b/src/vnc_keymap.c index a4fc476a8..20a9126aa 100644 --- a/src/vnc_keymap.c +++ b/src/vnc_keymap.c @@ -22,18 +22,20 @@ * NOTE: The values are as defined in the Microsoft document named * "Keyboard Scan Code Specification", version 1.3a of 2000/03/16. * - * Version: @(#)vnc_keymap.c 1.0.2 2017/10/24 + * Version: @(#)vnc_keymap.c 1.0.3 2018/04/29 * * Authors: Fred N. van Kempen, * Based on raw code by RichardG, * - * Copyright 2017 Fred N. van Kempen. + * Copyright 2017,2018 Fred N. van Kempen. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include "86box.h" #include "keyboard.h" #include "plat.h" @@ -621,15 +623,31 @@ static int keysyms_ff[] = { }; +#ifdef ENABLE_VNC_KEYMAP_LOG +int vnc_keymap_do_log = ENABLE_VNC_KEYMAP_LOG; +#endif + + +static void +vnc_keymap_log(const char *format, ...) +{ +#ifdef ENABLE_VNC_KEYMAP_LOG + va_list ap; + + if (vnc_keymap_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + void vnc_kbinput(int down, int k) { uint16_t scan; -#if 0 - pclog("VNC: kbinput %d %04x\n", down, k); -#endif - switch(k >> 8) { case 0x00: /* page 00, Latin-1 */ scan = keysyms_00[k & 0xff]; @@ -640,17 +658,14 @@ vnc_kbinput(int down, int k) break; default: - pclog("VNC: unhandled Xkbd page: %02x\n", k>>8); + vnc_keymap_log("VNC: unhandled Xkbd page: %02x\n", k>>8); return; } if (scan == 0x0000) { - pclog("VNC: unhandled Xkbd key: %d (%04x)\n", k, k); + vnc_keymap_log("VNC: unhandled Xkbd key: %d (%04x)\n", k, k); return; } -#if 0 - else pclog("VNC: translated to %02x %02x\n", (scan>>8)&0xff, scan&0xff); -#endif /* Send this scancode sequence to the PC keyboard. */ keyboard_input(down, scan); diff --git a/src/win/86Box.rc b/src/win/86Box.rc index 7122bf0f5..4312bb3d8 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -8,7 +8,7 @@ * * Application resource script for Windows. * - * Version: @(#)86Box.rc 1.0.31 2018/03/06 + * Version: @(#)86Box.rc 1.0.37 2018/05/25 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -34,7 +34,7 @@ #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) +#pragma code_page(65001) #endif //_WIN32 ///////////////////////////////////////////////////////////////////////////// @@ -66,11 +66,9 @@ BEGIN BEGIN MENUITEM "&DirectDraw", IDM_VID_DDRAW MENUITEM "Direct&3D 9", IDM_VID_D3D + MENUITEM "&SDL", IDM_VID_SDL #ifdef USE_VNC MENUITEM "&VNC", IDM_VID_VNC -#endif -#ifdef USE_RDP - MENUITEM "&RDP", IDM_VID_RDP #endif END MENUITEM SEPARATOR @@ -117,11 +115,9 @@ BEGIN POPUP "&Tools" BEGIN MENUITEM "&Settings...", IDM_CONFIG - MENUITEM SEPARATOR - MENUITEM "S&tatus", IDM_STATUS - MENUITEM "Take s&creenshot\tCtrl+F11", IDM_ACTION_SCREENSHOT - MENUITEM SEPARATOR MENUITEM "&Update status bar icons", IDM_UPDATE_ICONS + MENUITEM SEPARATOR + MENUITEM "Take s&creenshot\tCtrl+F11", IDM_ACTION_SCREENSHOT END #if defined(ENABLE_LOG_TOGGLES) || defined(ENABLE_LOG_COMMANDS) POPUP "&Logging" @@ -327,7 +323,7 @@ BEGIN #endif END -DLG_CFG_VIDEO DIALOG DISCARDABLE 97, 0, 267, 63 +DLG_CFG_VIDEO DIALOG DISCARDABLE 97, 0, 267, 45 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" BEGIN @@ -335,12 +331,9 @@ BEGIN COMBOBOX IDC_COMBO_VIDEO,71,7,140,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Configure",IDC_CONFIGURE_VID,214,7,46,12 - COMBOBOX IDC_COMBO_VIDEO_SPEED,71,25,189,120,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - LTEXT "Video speed:",IDT_1708,7,26,58,10 CONTROL "Voodoo Graphics",IDC_CHECK_VOODOO,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,45,199,10 - PUSHBUTTON "Configure",IDC_BUTTON_VOODOO,214,44,46,12 + BS_AUTOCHECKBOX | WS_TABSTOP,7,27,199,10 + PUSHBUTTON "Configure",IDC_BUTTON_VOODOO,214,26,46,12 END DLG_CFG_INPUT DIALOG DISCARDABLE 97, 0, 267, 65 @@ -445,16 +438,17 @@ BEGIN PUSHBUTTON "Configure",IDC_CONFIGURE_SCSI,214,7,46,12 LTEXT "HD Controller:",IDT_1717,7,26,61,10 - COMBOBOX IDC_COMBO_HDC,71,25,189,120,CBS_DROPDOWNLIST | + COMBOBOX IDC_COMBO_HDC,71,25,140,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Configure",IDC_CONFIGURE_HDC,214,25,46,12 - LTEXT "Tertiary IDE:",IDT_1718,7,44,61,10 - COMBOBOX IDC_COMBO_IDE_TER,71,43,189,120,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP + CONTROL "Tertiary IDE Controller",IDC_CHECK_IDE_TER,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,7,44,199,10 + PUSHBUTTON "Configure",IDC_BUTTON_IDE_TER,214,43,46,12 - LTEXT "Quaternary IDE:",IDT_1719,7,62,61,10 - COMBOBOX IDC_COMBO_IDE_QUA,71,61,189,120,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP + CONTROL "Quaternary IDE Controller",IDC_CHECK_IDE_QUA,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,7,62,199,10 + PUSHBUTTON "Configure",IDC_BUTTON_IDE_QUA,214,61,46,12 CONTROL "ISABugger device",IDC_CHECK_BUGGER,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,7,80,94,10 @@ -477,12 +471,9 @@ BEGIN COMBOBOX IDC_COMBO_HD_CHANNEL,170,117,90,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Channel:",IDT_1722,131,119,38,8 - COMBOBOX IDC_COMBO_HD_ID,170,117,22,12,CBS_DROPDOWNLIST | + COMBOBOX IDC_COMBO_HD_ID,170,117,90,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "ID:",IDT_1723,131,119,38,8 - COMBOBOX IDC_COMBO_HD_LUN,239,117,22,12,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - LTEXT "LUN:",IDT_1724,200,119,38,8 COMBOBOX IDC_COMBO_HD_CHANNEL_IDE,170,117,90,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP END @@ -514,12 +505,9 @@ BEGIN COMBOBOX IDC_COMBO_HD_CHANNEL,134,71,77,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Channel:",IDT_1722,99,73,34,8 - COMBOBOX IDC_COMBO_HD_ID,133,71,26,12,CBS_DROPDOWNLIST | + COMBOBOX IDC_COMBO_HD_ID,134,71,77,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "ID:",IDT_1723,117,73,15,8 - COMBOBOX IDC_COMBO_HD_LUN,185,71,26,12,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - LTEXT "LUN:",IDT_1724,168,73,15,8 + LTEXT "ID:",IDT_1723,99,73,34,8 COMBOBOX IDC_COMBO_HD_CHANNEL_IDE,134,71,77,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Progress:",IDT_1752,7,7,204,9 @@ -555,36 +543,30 @@ BEGIN COMBOBOX IDC_COMBO_CD_BUS,33,85,90,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Bus:",IDT_1740,7,87,24,8 - COMBOBOX IDC_COMBO_CD_ID,170,85,22,12,CBS_DROPDOWNLIST | + COMBOBOX IDC_COMBO_CD_ID,170,85,90,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "ID:",IDT_1741,131,87,38,8 - COMBOBOX IDC_COMBO_CD_LUN,239,85,22,12,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - LTEXT "LUN:",IDT_1742,200,87,38,8 COMBOBOX IDC_COMBO_CD_CHANNEL_IDE,170,85,90,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Channel:",IDT_1743,131,87,38,8 + LTEXT "Channel:",IDT_1742,131,87,38,8 COMBOBOX IDC_COMBO_CD_SPEED,33,105,90,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Speed:",IDT_1758,7,107,24,8 CONTROL "List1",IDC_LIST_ZIP_DRIVES,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SINGLESEL | WS_BORDER | WS_TABSTOP,7,137,253,60 - LTEXT "ZIP drives:",IDT_1739,7,127,50,8 - COMBOBOX IDC_COMBO_ZIP_BUS,73,204,90,12,CBS_DROPDOWNLIST | + LTEXT "ZIP drives:",IDT_1759,7,127,50,8 + COMBOBOX IDC_COMBO_ZIP_BUS,23,204,90,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Bus:",IDT_1753,57,206,14,8 - COMBOBOX IDC_COMBO_ZIP_ID,190,204,22,12,CBS_DROPDOWNLIST | + LTEXT "Bus:",IDT_1753,7,206,14,8 + COMBOBOX IDC_COMBO_ZIP_ID,139,204,61,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "ID:",IDT_1754,171,206,18,8 - COMBOBOX IDC_COMBO_ZIP_LUN,239,204,22,12,CBS_DROPDOWNLIST | + LTEXT "ID:",IDT_1754,120,206,28,8 + COMBOBOX IDC_COMBO_ZIP_CHANNEL_IDE,149,204,61,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "LUN:",IDT_1755,220,206,18,8 - COMBOBOX IDC_COMBO_ZIP_CHANNEL_IDE,200,204,60,12,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - LTEXT "Channel:",IDT_1756,171,206,28,8 + LTEXT "Channel:",IDT_1755,120,206,28,8 CONTROL "ZIP 250",IDC_CHECK250,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,204,44,10 + BS_AUTOCHECKBOX | WS_TABSTOP,218,204,44,10 END @@ -604,48 +586,42 @@ END // remains consistent on all systems. #ifdef RELEASE_BUILD /* Icon by Devcore - https://commons.wikimedia.org/wiki/File:Icon_PC_256x256.png */ -100 ICON DISCARDABLE "win/icons/86Box-RB.ico" + 10 ICON DISCARDABLE "win/icons/86Box-RB.ico" #else /* Icon by Devcore - https://commons.wikimedia.org/wiki/File:Icon_PC2_256x256.png */ -100 ICON DISCARDABLE "win/icons/86Box.ico" + 10 ICON DISCARDABLE "win/icons/86Box.ico" #endif -128 ICON DISCARDABLE "win/icons/floppy_525.ico" -129 ICON DISCARDABLE "win/icons/floppy_525_active.ico" -144 ICON DISCARDABLE "win/icons/floppy_35.ico" -145 ICON DISCARDABLE "win/icons/floppy_35_active.ico" -160 ICON DISCARDABLE "win/icons/cdrom.ico" -161 ICON DISCARDABLE "win/icons/cdrom_active.ico" -176 ICON DISCARDABLE "win/icons/zip.ico" -177 ICON DISCARDABLE "win/icons/zip_active.ico" -192 ICON DISCARDABLE "win/icons/removable_disk.ico" -193 ICON DISCARDABLE "win/icons/removable_disk_active.ico" -208 ICON DISCARDABLE "win/icons/hard_disk.ico" -209 ICON DISCARDABLE "win/icons/hard_disk_active.ico" -224 ICON DISCARDABLE "win/icons/network.ico" -225 ICON DISCARDABLE "win/icons/network_active.ico" -256 ICON DISCARDABLE "win/icons/machine.ico" -257 ICON DISCARDABLE "win/icons/display.ico" -258 ICON DISCARDABLE "win/icons/input_devices.ico" -259 ICON DISCARDABLE "win/icons/sound.ico" -260 ICON DISCARDABLE "win/icons/network.ico" -261 ICON DISCARDABLE "win/icons/ports.ico" -262 ICON DISCARDABLE "win/icons/other_peripherals.ico" -263 ICON DISCARDABLE "win/icons/hard_disk.ico" -264 ICON DISCARDABLE "win/icons/floppy_drives.ico" -265 ICON DISCARDABLE "win/icons/other_removable_devices.ico" -384 ICON DISCARDABLE "win/icons/floppy_525_empty.ico" -385 ICON DISCARDABLE "win/icons/floppy_525_empty_active.ico" -400 ICON DISCARDABLE "win/icons/floppy_35_empty.ico" -401 ICON DISCARDABLE "win/icons/floppy_35_empty_active.ico" -416 ICON DISCARDABLE "win/icons/cdrom_empty.ico" -417 ICON DISCARDABLE "win/icons/cdrom_empty_active.ico" -432 ICON DISCARDABLE "win/icons/zip_empty.ico" -433 ICON DISCARDABLE "win/icons/zip_empty_active.ico" -448 ICON DISCARDABLE "win/icons/removable_disk_empty.ico" -449 ICON DISCARDABLE "win/icons/removable_disk_empty_active.ico" -512 ICON DISCARDABLE "win/icons/floppy_disabled.ico" -514 ICON DISCARDABLE "win/icons/cdrom_disabled.ico" -515 ICON DISCARDABLE "win/icons/zip_disabled.ico" + 16 ICON DISCARDABLE "win/icons/floppy_525.ico" + 17 ICON DISCARDABLE "win/icons/floppy_525_active.ico" + 24 ICON DISCARDABLE "win/icons/floppy_35.ico" + 25 ICON DISCARDABLE "win/icons/floppy_35_active.ico" + 32 ICON DISCARDABLE "win/icons/cdrom.ico" + 33 ICON DISCARDABLE "win/icons/cdrom_active.ico" + 48 ICON DISCARDABLE "win/icons/zip.ico" + 49 ICON DISCARDABLE "win/icons/zip_active.ico" + 64 ICON DISCARDABLE "win/icons/hard_disk.ico" + 65 ICON DISCARDABLE "win/icons/hard_disk_active.ico" + 80 ICON DISCARDABLE "win/icons/network.ico" + 81 ICON DISCARDABLE "win/icons/network_active.ico" +144 ICON DISCARDABLE "win/icons/floppy_525_empty.ico" +145 ICON DISCARDABLE "win/icons/floppy_525_empty_active.ico" +152 ICON DISCARDABLE "win/icons/floppy_35_empty.ico" +153 ICON DISCARDABLE "win/icons/floppy_35_empty_active.ico" +160 ICON DISCARDABLE "win/icons/cdrom_empty.ico" +161 ICON DISCARDABLE "win/icons/cdrom_empty_active.ico" +176 ICON DISCARDABLE "win/icons/zip_empty.ico" +177 ICON DISCARDABLE "win/icons/zip_empty_active.ico" +240 ICON DISCARDABLE "win/icons/machine.ico" +241 ICON DISCARDABLE "win/icons/display.ico" +242 ICON DISCARDABLE "win/icons/input_devices.ico" +243 ICON DISCARDABLE "win/icons/sound.ico" +244 ICON DISCARDABLE "win/icons/ports.ico" +245 ICON DISCARDABLE "win/icons/other_peripherals.ico" +246 ICON DISCARDABLE "win/icons/floppy_drives.ico" +247 ICON DISCARDABLE "win/icons/other_removable_devices.ico" +248 ICON DISCARDABLE "win/icons/floppy_disabled.ico" +249 ICON DISCARDABLE "win/icons/cdrom_disabled.ico" +250 ICON DISCARDABLE "win/icons/zip_disabled.ico" #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// @@ -727,7 +703,7 @@ BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 260 TOPMARGIN, 7 - BOTTOMMARGIN, 56 + BOTTOMMARGIN, 38 END DLG_CFG_INPUT, DIALOG @@ -808,17 +784,17 @@ BEGIN IDS_2049 "86Box Error" IDS_2050 "86Box Fatal Error" IDS_2051 "This will reset 86Box.\nAre you sure you want to save the settings?" - IDS_2052 "DirectDraw Screenshot Error" - IDS_2053 "Invalid number of sectors (valid values are between 1 and 63)" - IDS_2054 "Invalid number of heads (valid values are between 1 and 16)" - IDS_2055 "Invalid number of cylinders (valid values are between 1 and 266305)" + IDS_2052 "Use CTRL+ALT+PAGE DOWN to return to windowed mode" + IDS_2053 "Speed" + IDS_2054 "ZIP %03i %i (%s): %ls" + IDS_2055 "ZIP images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" IDS_2056 "No usable ROM images found!" IDS_2057 "(empty)" - IDS_2058 "(host drive %c:)" + IDS_2058 "ZIP images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0All files (*.*)\0*.*\0" IDS_2059 "Turbo" IDS_2060 "On" IDS_2061 "Off" - IDS_2062 "86Box was unable to find any ROMs.\nAt least one ROM set is required to use 86Box." + IDS_2062 "All images (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Basic sector images (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Surface images (*.86F)\0*.86F\0" IDS_2063 "Configured ROM set not available.\nDefaulting to an available ROM set." END @@ -836,7 +812,7 @@ BEGIN IDS_2073 "Floppy drives" IDS_2074 "Other removable devices" IDS_2075 "CD-ROM images (*.ISO;*.CUE)\0*.ISO;*.CUE\0All files (*.*)\0*.*\0" - IDS_2076 "Host CD/DVD Drive (%c:)" + IDS_2076 "Surface images (*.86F)\0*.86F\0" IDS_2077 "Click to capture mouse" IDS_2078 "Press F8+F12 to release mouse" IDS_2079 "Press F8+F12 or middle button to release mouse" @@ -844,176 +820,89 @@ END STRINGTABLE DISCARDABLE BEGIN - IDS_2080 "Drive" - IDS_2081 "Location" + IDS_2080 "E&xport to 86F..." + IDS_2081 "Unable to initialize FluidSynth, make sure you have the following libraries\nin your 86Box folder:\n\nlibfluidsynth.dll\nlibglib-2.0-0.dll\nlibiconv-2.dll\nlibintl-8.dll\nlibpcre-1.dll" IDS_2082 "Bus" IDS_2083 "File" IDS_2084 "C" IDS_2085 "H" IDS_2086 "S" IDS_2087 "MB" - IDS_2088 "Unable to create bitmap file: %s" - IDS_2089 "Enabled" - IDS_2090 "Mute" - IDS_2091 "Type" - IDS_2092 "Bus" - IDS_2093 "DMA" + IDS_2088 "Check BPB" + IDS_2089 "&Image..." + IDS_2090 "&Reload previous image" + IDS_2091 "E&mpty" + IDS_2092 "&Mute" + IDS_2093 "E&ject" IDS_2094 "KB" IDS_2095 "Neither DirectDraw nor Direct3D available !" + IDS_2096 "&New image..." + IDS_2097 "&Existing image..." + IDS_2098 "Existing image (&Write-protected)..." + IDS_2099 "Default" + IDS_2100 "%i Wait state(s)" + IDS_2101 "Type" + IDS_2102 "PCap failed to set up because it may not be initialized" + IDS_2103 "No PCap devices found" + IDS_2104 "Invalid PCap device" + IDS_2105 "Standard 2-button joystick(s)" + IDS_2106 "Standard 4-button joystick" + IDS_2107 "Standard 6-button joystick" + IDS_2108 "Standard 8-button joystick" + IDS_2109 "CH Flightstick Pro" + IDS_2110 "Microsoft SideWinder Pad" + IDS_2111 "Thrustmaster Flight Control System" + IDS_2112 "None" + IDS_2113 "Unable to load Keyboard Accelerators!" + IDS_2114 "Unable to register Raw Input!" + IDS_2115 "%u" + IDS_2116 "%u MB (CHS: %i, %i, %i)" + IDS_2117 "Floppy %i (%s): %ls" + IDS_2118 "All images (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.DDI;*.DSK;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.DDI;*.DSK;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.XDF\0Advanced sector images (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basic sector images (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.DDI;*.DSK;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.DDI;*.DSK;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux images (*.FDI)\0*.FDI\0Surface images (*.86F)\0*.86F\0All files (*.*)\0*.*\0" END STRINGTABLE DISCARDABLE BEGIN - IDS_2096 "Slave" - IDS_2097 "SCSI (ID %s, LUN %s)" - IDS_2098 "Adapter Type" - IDS_2099 "Base Address" - IDS_2100 "IRQ" - IDS_2101 "8-bit DMA" - IDS_2102 "16-bit DMA" - IDS_2103 "BIOS" - IDS_2104 "Network Type" - IDS_2105 "Surround Module" - IDS_2106 "MPU-401 Base Address" - IDS_2107 "Use CTRL+ALT+PAGE DOWN to return to windowed mode" - IDS_2108 "On-board RAM" - IDS_2109 "Memory Size" - IDS_2110 "Display Type" - IDS_2111 "RGB" -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_2112 "Composite" - IDS_2113 "Composite Type" - IDS_2114 "Old" - IDS_2115 "New" - IDS_2116 "RGB Type" - IDS_2117 "Color" - IDS_2118 "Monochrome (Green)" - IDS_2119 "Monochrome (Amber)" - IDS_2120 "Monochrome (Gray)" - IDS_2121 "Color (no brown)" - IDS_2122 "Monochrome (Default)" - IDS_2123 "Snow Emulation" - IDS_2124 "Bilinear Filtering" - IDS_2125 "Dithering" - IDS_2126 "Framebuffer Memory Size" - IDS_2127 "Texture Memory Size" -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_2128 "Screen Filter" - IDS_2129 "Render Threads" - IDS_2130 "Recompiler" - IDS_2131 "Default" - IDS_2132 "%i Wait state(s)" - IDS_2133 "8-bit" - IDS_2134 "Slow 16-bit" - IDS_2135 "Fast 16-bit" - IDS_2136 "Slow VLB/PCI" - IDS_2137 "Mid VLB/PCI" - IDS_2138 "Fast VLB/PCI" -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_2139 "PCap failed to set up because it may not be initialized" - IDS_2140 "No PCap devices found" - IDS_2141 "Invalid PCap device" - IDS_2142 "&Notify disk change" - IDS_2143 "Type" - IDS_2144 "Standard 2-button joystick(s)" - IDS_2145 "Standard 4-button joystick" - IDS_2146 "Standard 6-button joystick" - IDS_2147 "Standard 8-button joystick" - IDS_2148 "CH Flightstick Pro" - IDS_2149 "Microsoft SideWinder Pad" - IDS_2150 "Thrustmaster Flight Control System" - IDS_2151 "Disabled" - IDS_2152 "None" - IDS_2153 "Unable to load Keyboard Accelerators!" - IDS_2154 "Unable to register Raw Input!" - IDS_2155 "IRQ %i" - IDS_2156 "%" PRIu64 - IDS_2157 "%" PRIu64 " MB (CHS: %" PRIu64 ", %" PRIu64 ", %" PRIu64 ")" - IDS_2158 "Floppy %i (%s): %ls" - IDS_2159 "All images (*.0??;*.1??;*.360;*.720;*.86F;*.BIN;*.CQ?;*.DSK;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.XDF)\0*.0??;*.1??;*.360;*.720;*.86F;*.BIN;*.CQ?;*.DSK;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.XDF\0Advanced sector images (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basic sector images (*.0??;*.1??;*.360;*.720;*.BIN;*.CQ?;*.DSK;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.360;*.720;*.BIN;*.CQ?;*.DSK;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux images (*.FDI)\0*.FDI\0Surface images (*.86F)\0*.86F\0All files (*.*)\0*.*\0" - IDS_2160 "Configuration files (*.CFG)\0*.CFG\0All files (*.*)\0*.*\0" - IDS_2161 "&New image..." - IDS_2162 "&Existing image..." - IDS_2163 "Existing image (&Write-protected)..." - IDS_2164 "E&ject" - IDS_2165 "&Mute" - IDS_2166 "E&mpty" - IDS_2167 "&Reload previous image" - IDS_2168 "&Image..." - IDS_2169 "Image (&Write-protected)..." - IDS_2170 "Check BPB" - IDS_2171 "Unable to initialize FluidSynth, make sure you have the following libraries\nin your 86Box folder:\n\nlibfluidsynth.dll\nlibglib-2.0-0.dll\nlibiconv-2.dll\nlibintl-8.dll\nlibpcre-1.dll" - IDS_2172 "E&xport to 86F..." - IDS_2173 "Surface images (*.86F)\0*.86F\0" - IDS_2174 "All images (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Basic sector images (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Surface images (*.86F)\0*.86F\0" - IDS_2175 "ZIP images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0All files (*.*)\0*.*\0" - IDS_2176 "ZIP images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0" - IDS_2177 "ZIP %i (%03i): %ls" - IDS_2178 "Speed" - IDS_4096 "Hard disk (%s)" IDS_4097 "%01i:%01i" IDS_4098 "%i" - IDS_4099 "Disabled" + IDS_4099 "MFM/RLL or ESDI CD-ROM drives never existed" IDS_4100 "Custom..." IDS_4101 "Custom (large)..." IDS_4102 "Add New Hard Disk" IDS_4103 "Add Existing Hard Disk" IDS_4104 "Attempting to create a HDI image larger than 4 GB" - IDS_4105 "Attempting to create a spuriously large hard disk image" + IDS_4105 "Attempting to create a hard disk image beyond the 28-bit LBA limit" IDS_4106 "Hard disk images (*.HD?;*.IM?;*.VHD)\0*.HD?;*.IM?;*.VHD\0All files (*.*)\0*.*\0" IDS_4107 "Unable to open the file for read" IDS_4108 "Unable to open the file for write" - IDS_4109 "HDI or HDX image with a sector size that is not 512 are not supported" + IDS_4109 "HDI or HDX images with a sector size that is not 512 are not supported" IDS_4110 "USB is not yet supported" IDS_4111 "This image exists and will be overwritten.\nAre you sure you want to use it?" IDS_4112 "Please enter a valid file name" IDS_4113 "Remember to partition and format the new drive" - IDS_4114 "MFM/RLL or ESDI CD-ROM drives never existed" - IDS_4115 "Removable disk %i (SCSI): %ls" IDS_4352 "MFM/RLL" - IDS_4353 "XT IDE" + IDS_4353 "XTA" IDS_4354 "ESDI" - IDS_4355 "IDE (PIO-only)" - IDS_4356 "IDE (PIO+DMA)" - IDS_4357 "SCSI" - IDS_4358 "SCSI (removable)" + IDS_4355 "IDE" + IDS_4356 "SCSI" IDS_4608 "MFM/RLL (%01i:%01i)" - IDS_4609 "XT IDE (%01i:%01i)" + IDS_4609 "XTA (%01i:%01i)" IDS_4610 "ESDI (%01i:%01i)" - IDS_4611 "IDE (PIO-only) (%01i:%01i)" - IDS_4612 "IDE (PIO+DMA) (%01i:%01i)" - IDS_4613 "SCSI (%02i:%02i)" - IDS_4614 "SCSI (removable) (%02i:%02i)" + IDS_4611 "IDE (%01i:%01i)" + IDS_4612 "SCSI (ID %02i)" IDS_5120 "CD-ROM %i (%s): %s" IDS_5376 "Disabled" - IDS_5377 "" - IDS_5378 "" - IDS_5379 "" - IDS_5380 "ATAPI (PIO-only)" - IDS_5381 "ATAPI (PIO and DMA)" - IDS_5382 "SCSI" + IDS_5380 "ATAPI" + IDS_5381 "SCSI" IDS_5632 "Disabled" - IDS_5633 "" - IDS_5634 "" - IDS_5635 "" - IDS_5636 "ATAPI (PIO-only) (%01i:%01i)" - IDS_5637 "ATAPI (PIO and DMA) (%01i:%01i)" - IDS_5638 "SCSI (%02i:%02i)" + IDS_5636 "ATAPI (%01i:%01i)" + IDS_5637 "SCSI (ID %02i)" IDS_5888 "160 kB" IDS_5889 "180 kB" @@ -1061,7 +950,7 @@ VS_VERSION_INFO VERSIONINFO BEGIN BLOCK "StringFileInfo" BEGIN - BLOCK "040904b0" + BLOCK "0409fde9" BEGIN VALUE "Comments", "\0" VALUE "CompanyName", "IRC #SoftHistory\0" diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index d0a3383df..14080b8cb 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -8,7 +8,7 @@ # # Makefile for Win32 (MinGW32) environment. # -# Version: @(#)Makefile.mingw 1.0.113 2018/03/18 +# Version: @(#)Makefile.mingw 1.0.119 2018/07/17 # # Authors: Miran Grca, # Fred N. van Kempen, @@ -41,9 +41,6 @@ ifeq ($(DEV_BUILD), y) ifndef CRASHDUMP CRASHDUMP := y endif - ifndef GREENB - GREENB := y - endif ifndef I686 I686 := y endif @@ -84,9 +81,6 @@ else ifndef CRASHDUMP CRASHDUMP := n endif - ifndef GREENB - GREENB := n - endif ifndef I686 I686 := n endif @@ -108,6 +102,9 @@ else ifndef STEALTH32 STEALTH32 := n endif + ifndef VGAWONDER + VGAWONDER := n + endif ifndef VNC VNC := n endif @@ -203,7 +200,7 @@ VPATH := $(EXPATH) . cpu \ sound/munt sound/munt/c_interface sound/munt/sha1 \ sound/munt/srchelper \ sound/resid-fp \ - scsi video floppy/lzf network network/slirp win + scsi video network network/slirp win ifeq ($(X64), y) CPP := g++ -m64 CC := gcc -m64 @@ -243,6 +240,7 @@ ifeq ($(DEBUG), y) COPTIM := -Og endif else + DFLAGS += -g0 ifeq ($(OPTIM), y) AOPTIM := -mtune=native ifndef COPTIM @@ -292,9 +290,9 @@ ifneq ($(WX), n) LIBS += $(WX_LIBS) UIOBJ := wx_main.o wx_ui.o wx_stbar.o wx_render.o else - UIOBJ := win_ui.o \ - win_ddraw.o win_d3d.o \ - win_dialog.o win_about.o win_status.o win_stbar.o \ + UIOBJ := win_ui.o win_stbar.o \ + win_ddraw.o win_d3d.o win_sdl.o \ + win_dialog.o win_about.o \ win_settings.o win_devconf.o win_snd_gain.o \ win_new_floppy.o win_jsconf.o endif @@ -353,14 +351,8 @@ OPTS += -DUSE_CRASHDUMP DEVBROBJ += win_crashdump.o endif -ifeq ($(GREENB), y) -OPTS += -DUSE_GREENB -DEVBROBJ += m_at_4gpv31.o -endif - ifeq ($(I686), y) OPTS += -DUSE_I686 -DEVBROBJ += m_at_440fx.o endif ifeq ($(LASERXT), y) @@ -374,7 +366,7 @@ endif ifeq ($(NV_RIVA), y) OPTS += -DUSE_RIVA -DEVBROBJ += vid_nv_riva128.o +DEVBROBJ += vid_nvidia.o endif ifeq ($(PAS16), y) @@ -391,6 +383,10 @@ OPTS += -DUSE_STEALTH32 DEVBROBJ += vid_icd2061.o endif +ifeq ($(VGAWONDER), y) +OPTS += -DUSE_VGAWONDER +endif + ifeq ($(XL24), y) OPTS += -DUSE_XL24 endif @@ -408,7 +404,7 @@ endif CFLAGS := $(WX_FLAGS) $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) \ $(AFLAGS) -fomit-frame-pointer -mstackrealign -Wall \ -fno-strict-aliasing -CFLAGS := $(CFLAGS) +CXXFLAGS := $(CFLAGS) ######################################################################### @@ -433,19 +429,18 @@ MCHOBJ := machine.o machine_table.o \ m_xt_xi8088.o \ m_pcjr.o \ m_amstrad.o \ - m_europc.o m_europc_hdc.o \ + m_europc.o \ m_olivetti_m24.o m_tandy.o \ m_at.o \ m_at_ali1429.o m_at_commodore.o \ m_at_neat.o m_at_headland.o \ m_at_t3100e.o m_at_t3100e_vid.o \ - m_ps1.o \ + m_ps1.o m_ps1_hdc.o \ m_ps2_isa.o m_ps2_mca.o \ m_at_opti495.o m_at_scat.o \ m_at_compaq.o m_at_wd76c10.o \ m_at_sis_85c471.o m_at_sis_85c496.o \ - m_at_430lx_nx.o m_at_430fx.o \ - m_at_430hx.o m_at_430vx.o + m_at_4x0.o DEVOBJ := bugger.o lpt.o $(SERIAL) \ sio_fdc37c66x.o sio_fdc37c669.o sio_fdc37c93x.o \ @@ -467,10 +462,10 @@ FDDOBJ := fdd.o fdc.o fdi2raw.o \ HDDOBJ := hdd.o \ hdd_image.o hdd_table.o \ hdc.o \ - hdc_mfm_xt.o hdc_xtide.o \ - hdc_mfm_at.o \ + hdc_mfm_xt.o hdc_mfm_at.o \ + hdc_xta.o \ hdc_esdi_at.o hdc_esdi_mca.o \ - hdc_ide.o + hdc_xtide.o hdc_ide.o CDROMOBJ := cdrom.o \ cdrom_dosbox.o cdrom_image.o cdrom_null.o @@ -494,7 +489,8 @@ NETOBJ := network.o \ bootp.o ip_icmp.o misc.o socket.o tcp_timer.o cksum.o \ ip_input.o queue.o tcp_input.o debug.o ip_output.o \ sbuf.o tcp_output.o udp.o if.o mbuf.o slirp.o tcp_subr.o \ - net_ne2000.o + net_dp8390.o \ + net_3c503.o net_ne2000.o SNDOBJ := sound.o \ openal.o \ @@ -549,7 +545,7 @@ VIDOBJ := video.o \ PLATOBJ := win.o \ win_dynld.o win_thread.o \ - win_cdrom.o win_cdrom_ioctl.o win_keyboard.o \ + win_cdrom.o win_keyboard.o \ win_mouse.o win_joystick.o win_midi.o OBJ := $(MAINOBJ) $(INTELOBJ) $(CPUOBJ) $(MCHOBJ) $(DEVOBJ) \ @@ -561,8 +557,6 @@ ifdef EXOBJ OBJ += $(EXOBJ) endif -LZFOBJ := lzf_c.o lzf_d.o - LIBS := -mwindows \ -lopenal.dll \ -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 \ @@ -576,8 +570,8 @@ endif ifneq ($(WX), n) LIBS += $(WX_LIBS) -lm endif -LIBS += -lpng -lz -lkernel32 -lwsock32 -liphlpapi -lpsapi -LIBS += -lpthread -static -lstdc++ -lgcc +LIBS += -lpng -lz -lwsock32 -liphlpapi +LIBS += -static -lstdc++ -lgcc ifneq ($(X64), y) LIBS += -Wl,--large-address-aware endif @@ -630,9 +624,9 @@ all: $(PROG).exe pcap_if.exe @echo Processing $< @$(WINDRES) $(RFLAGS) $(EXTRAS) -i $< -o 86Box.res -$(PROG).exe: $(OBJ) $(LZFOBJ) 86Box.res +$(PROG).exe: $(OBJ) 86Box.res @echo Linking $(PROG).exe .. - @$(CC) -o $(PROG).exe $(OBJ) $(LZFOBJ) 86Box.res $(LIBS) + @$(CC) -o $(PROG).exe $(OBJ) 86Box.res $(LIBS) ifneq ($(DEBUG), y) @strip $(PROG).exe endif diff --git a/src/win/icons/removable_disk.ico b/src/win/icons/removable_disk.ico deleted file mode 100644 index 6f67d6a56..000000000 Binary files a/src/win/icons/removable_disk.ico and /dev/null differ diff --git a/src/win/icons/removable_disk_active.ico b/src/win/icons/removable_disk_active.ico deleted file mode 100644 index bfbc3707f..000000000 Binary files a/src/win/icons/removable_disk_active.ico and /dev/null differ diff --git a/src/win/icons/removable_disk_empty.ico b/src/win/icons/removable_disk_empty.ico deleted file mode 100644 index 09229f566..000000000 Binary files a/src/win/icons/removable_disk_empty.ico and /dev/null differ diff --git a/src/win/icons/removable_disk_empty_active.ico b/src/win/icons/removable_disk_empty_active.ico deleted file mode 100644 index 4fcd2ebbc..000000000 Binary files a/src/win/icons/removable_disk_empty_active.ico and /dev/null differ diff --git a/src/win/resource.h b/src/win/resource.h index af9d94b77..9579a055e 100644 --- a/src/win/resource.h +++ b/src/win/resource.h @@ -8,7 +8,7 @@ * * Windows resource defines. * - * Version: @(#)resource.h 1.0.22 2018/03/06 + * Version: @(#)resource.h 1.0.25 2018/05/25 * * Authors: Sarah Walker, * Miran Grca, @@ -48,7 +48,6 @@ #define IDT_1705 1705 /* MB == IDC_TEXT_MB */ #define IDT_1706 1706 /* Memory: */ #define IDT_1707 1707 /* Video: */ -#define IDT_1708 1708 /* Video speed: */ #define IDT_1709 1709 /* Mouse: */ #define IDT_1710 1710 /* Joystick: */ #define IDT_1711 1711 /* Sound card: */ @@ -58,8 +57,7 @@ #define IDT_1715 1715 /* Network adapter: */ #define IDT_1716 1716 /* SCSI Controller: */ #define IDT_1717 1717 /* HD Controller: */ -#define IDT_1718 1718 /* Tertiary IDE: */ -#define IDT_1719 1719 /* Quaternary IDE: */ +#define IDT_1718 1718 #define IDT_1720 1720 /* Hard disks: */ #define IDT_1721 1721 /* Bus: */ #define IDT_1722 1722 /* Channel: */ @@ -91,6 +89,7 @@ #define IDT_1756 1756 /* Channel: */ #define IDT_1757 1757 /* Progress: */ #define IDT_1758 1758 /* Speed: */ +#define IDT_1759 1759 /* ZIP drives: */ /* @@ -121,9 +120,8 @@ #define IDC_VIDEO 1030 /* video config */ #define IDC_COMBO_VIDEO 1031 -#define IDC_COMBO_VIDEO_SPEED 1032 -#define IDC_CHECK_VOODOO 1033 -#define IDC_BUTTON_VOODOO 1034 +#define IDC_CHECK_VOODOO 1032 +#define IDC_BUTTON_VOODOO 1033 #define IDC_INPUT 1050 /* input config */ #define IDC_COMBO_MOUSE 1051 @@ -157,9 +155,12 @@ #define IDC_COMBO_SCSI 1121 #define IDC_CONFIGURE_SCSI 1122 #define IDC_COMBO_HDC 1123 -#define IDC_COMBO_IDE_TER 1124 -#define IDC_COMBO_IDE_QUA 1125 -#define IDC_CHECK_BUGGER 1126 +#define IDC_CONFIGURE_HDC 1124 +#define IDC_CHECK_IDE_TER 1125 +#define IDC_BUTTON_IDE_TER 1126 +#define IDC_CHECK_IDE_QUA 1127 +#define IDC_BUTTON_IDE_QUA 1128 +#define IDC_CHECK_BUGGER 1129 #define IDC_HARD_DISKS 1130 /* hard disk config */ #define IDC_LIST_HARD_DISKS 1131 @@ -237,36 +238,35 @@ #define IDM_CONFIG 40020 #define IDM_CONFIG_LOAD 40021 #define IDM_CONFIG_SAVE 40022 -#define IDM_STATUS 40030 -#define IDM_UPDATE_ICONS 40040 -#define IDM_VID_RESIZE 40050 -#define IDM_VID_REMEMBER 40051 -#define IDM_VID_DDRAW 40060 -#define IDM_VID_D3D 40061 -#define IDM_VID_VNC 40062 -#define IDM_VID_RDP 40063 -#define IDM_VID_SCALE_1X 40064 -#define IDM_VID_SCALE_2X 40065 -#define IDM_VID_SCALE_3X 40066 -#define IDM_VID_SCALE_4X 40067 -#define IDM_VID_FULLSCREEN 40070 -#define IDM_VID_FS_FULL 40071 -#define IDM_VID_FS_43 40072 -#define IDM_VID_FS_SQ 40073 -#define IDM_VID_FS_INT 40074 -#define IDM_VID_FS_KEEPRATIO 40075 -#define IDM_VID_FORCE43 40076 -#define IDM_VID_OVERSCAN 40077 -#define IDM_VID_INVERT 40079 -#define IDM_VID_CGACON 40080 -#define IDM_VID_GRAYCT_601 40085 -#define IDM_VID_GRAYCT_709 40086 -#define IDM_VID_GRAYCT_AVE 40087 -#define IDM_VID_GRAY_RGB 40090 -#define IDM_VID_GRAY_MONO 40091 -#define IDM_VID_GRAY_AMBER 40092 -#define IDM_VID_GRAY_GREEN 40093 -#define IDM_VID_GRAY_WHITE 40094 +#define IDM_UPDATE_ICONS 40030 +#define IDM_VID_RESIZE 40040 +#define IDM_VID_REMEMBER 40041 +#define IDM_VID_DDRAW 40050 +#define IDM_VID_D3D 40051 +#define IDM_VID_SDL 40052 +#define IDM_VID_VNC 40053 +#define IDM_VID_SCALE_1X 40054 +#define IDM_VID_SCALE_2X 40055 +#define IDM_VID_SCALE_3X 40056 +#define IDM_VID_SCALE_4X 40057 +#define IDM_VID_FULLSCREEN 40060 +#define IDM_VID_FS_FULL 40061 +#define IDM_VID_FS_43 40062 +#define IDM_VID_FS_SQ 40063 +#define IDM_VID_FS_INT 40064 +#define IDM_VID_FS_KEEPRATIO 40065 +#define IDM_VID_FORCE43 40066 +#define IDM_VID_OVERSCAN 40067 +#define IDM_VID_INVERT 40069 +#define IDM_VID_CGACON 40070 +#define IDM_VID_GRAYCT_601 40075 +#define IDM_VID_GRAYCT_709 40076 +#define IDM_VID_GRAYCT_AVE 40077 +#define IDM_VID_GRAY_RGB 40080 +#define IDM_VID_GRAY_MONO 40081 +#define IDM_VID_GRAY_AMBER 40082 +#define IDM_VID_GRAY_GREEN 40083 +#define IDM_VID_GRAY_WHITE 40084 #define IDM_LOG_BREAKPOINT 51201 #define IDM_DUMP_VRAM 51202 // should be an Action diff --git a/src/win/win.c b/src/win/win.c index d4ca6e66b..90aa29191 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -8,7 +8,7 @@ * * Platform main support module for Windows. * - * Version: @(#)win.c 1.0.46 2018/03/16 + * Version: @(#)win.c 1.0.50 2018/07/16 * * Authors: Sarah Walker, * Miran Grca, @@ -20,13 +20,15 @@ */ #define UNICODE #include -#include +#include +#include #include +#include #include #include -#include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../config.h" #include "../device.h" @@ -39,15 +41,9 @@ #ifdef USE_VNC # include "../vnc.h" #endif -#ifdef USE_RDP -# include "../rdp.h" -#endif -#ifdef USE_WX -# include "../wx/wx_ui.h" -#else # include "win_ddraw.h" # include "win_d3d.h" -#endif +# include "win_sdl.h" #include "win.h" @@ -75,6 +71,7 @@ static rc_str_t *lpRCstr2048, *lpRCstr5888, *lpRCstr6144, *lpRCstr7168; +static int vid_api_inited = 0; static struct { @@ -84,48 +81,46 @@ static struct { void (*close)(void); void (*resize)(int x, int y); int (*pause)(void); -} vid_apis[2][4] = { +} vid_apis[2][RENDERERS_NUM] = { { -#ifdef USE_WX - { "WxWidgets", 1, wx_init, wx_close, NULL, wx_pause }, - { "WxWidgets", 1, wx_init, wx_close, NULL, wx_pause }, -#else { "DDraw", 1, (int(*)(void*))ddraw_init, ddraw_close, NULL, ddraw_pause }, { "D3D", 1, (int(*)(void*))d3d_init, d3d_close, d3d_resize, d3d_pause }, -#endif + { "SDL", 1, (int(*)(void*))sdl_init, sdl_close, NULL, sdl_pause } #ifdef USE_VNC - { "VNC", 0, vnc_init, vnc_close, vnc_resize, vnc_pause }, -#else - { NULL, 0, NULL, NULL, NULL, NULL }, -#endif -#ifdef USE_RDP - { "RDP", 0, rdp_init, rdp_close, rdp_resize, rdp_pause } -#else - { NULL, 0, NULL, NULL, NULL, NULL } + ,{ "VNC", 0, vnc_init, vnc_close, vnc_resize, vnc_pause } #endif }, { -#ifdef USE_WX - { "WxWidgets", 1, wx_init, wx_close, NULL, wx_pause }, - { "WxWidgets", 1, wx_init, wx_close, NULL, wx_pause }, -#else { "DDraw", 1, (int(*)(void*))ddraw_init_fs, ddraw_close, NULL, ddraw_pause }, { "D3D", 1, (int(*)(void*))d3d_init_fs, d3d_close, NULL, d3d_pause }, -#endif + { "SDL", 1, (int(*)(void*))sdl_init_fs, sdl_close, sdl_resize, sdl_pause } #ifdef USE_VNC - { "VNC", 0, vnc_init, vnc_close, vnc_resize, vnc_pause }, -#else - { NULL, 0, NULL, NULL, NULL, NULL }, -#endif -#ifdef USE_RDP - { "RDP", 0, rdp_init, rdp_close, rdp_resize, rdp_pause } -#else - { NULL, 0, NULL, NULL, NULL, NULL } + ,{ "VNC", 0, vnc_init, vnc_close, vnc_resize, vnc_pause } #endif }, }; +#ifdef ENABLE_WIN_LOG +int win_do_log = ENABLE_WIN_LOG; +#endif + + +static void +win_log(const char *fmt, ...) +{ +#ifdef ENABLE_WIN_LOG + va_list ap; + + if (win_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + static void LoadCommonStrings(void) { @@ -157,11 +152,15 @@ LoadCommonStrings(void) for (i=0; i 3)) + LoadString(hinstance, 5376+i, lpRCstr5376[i].str, 512); + } - for (i=0; i 3)) + LoadString(hinstance, 5632+i, lpRCstr5632[i].str, 512); + } for (i=0; i= 2048) && (i <= 3071)) { + if ((i >= 2048) && (i <= 3071)) str = lpRCstr2048[i-2048].str; - } else if ((i >= 4096) && (i <= 4351)) { + else if ((i >= 4096) && (i <= 4351)) str = lpRCstr4096[i-4096].str; - } else if ((i >= 4352) && (i <= 4607)) { + else if ((i >= 4352) && (i <= 4607)) str = lpRCstr4352[i-4352].str; - } else if ((i >= 4608) && (i <= 5119)) { + else if ((i >= 4608) && (i <= 5119)) str = lpRCstr4608[i-4608].str; - } else if ((i >= 5120) && (i <= 5375)) { + else if ((i >= 5120) && (i <= 5375)) str = lpRCstr5120[i-5120].str; - } else if ((i >= 5376) && (i <= 5631)) { + else if ((i >= 5376) && (i <= 5631)) str = lpRCstr5376[i-5376].str; - } else if ((i >= 5632) && (i <= 5887)) { + else if ((i >= 5632) && (i <= 5887)) str = lpRCstr5632[i-5632].str; - } else if ((i >= 5888) && (i <= 6143)) { + else if ((i >= 5888) && (i <= 6143)) str = lpRCstr5888[i-5888].str; - } else if ((i >= 6144) && (i <= 7167)) { + else if ((i >= 6144) && (i <= 7167)) str = lpRCstr6144[i-6144].str; - } else { + else str = lpRCstr7168[i-7168].str; - } return((wchar_t *)str); } -#ifndef USE_WX /* Create a console if we don't already have one. */ static void CreateConsole(int init) @@ -251,29 +248,24 @@ CreateConsole(int init) /* Not logging to file, attach to console. */ if (! AttachConsole(ATTACH_PARENT_PROCESS)) { /* Parent has no console, create one. */ - AllocConsole(); + if (! AllocConsole()) { + /* Cannot create console, just give up. */ + return; + } + } + fp = NULL; + if ((h = GetStdHandle(STD_OUTPUT_HANDLE)) != NULL) { + /* We got the handle, now open a file descriptor. */ + if ((i = _open_osfhandle((intptr_t)h, _O_TEXT)) != -1) { + /* We got a file descriptor, now allocate a new stream. */ + if ((fp = _fdopen(i, "w")) != NULL) { + /* Got the stream, re-initialize stdout without it. */ + (void)freopen("CONOUT$", "w", stdout); + setvbuf(stdout, NULL, _IONBF, 0); + fflush(stdout); + } + } } - - h = GetStdHandle(STD_OUTPUT_HANDLE); - i = _open_osfhandle((intptr_t)h, _O_TEXT); - fp = _fdopen(i, "w"); - setvbuf(fp, NULL, _IONBF, 1); - *stdout = *fp; - - h = GetStdHandle(STD_ERROR_HANDLE); - i = _open_osfhandle((intptr_t)h, _O_TEXT); - fp = _fdopen(i, "w"); - setvbuf(fp, NULL, _IONBF, 1); - *stderr = *fp; - -#if 0 - /* Set up stdin as well. */ - h = GetStdHandle(STD_INPUT_HANDLE); - i = _open_osfhandle((intptr_t)h, _O_TEXT); - fp = _fdopen(i, "r"); - setvbuf(fp, NULL, _IONBF, 128); - *stdin = *fp; -#endif } @@ -388,7 +380,6 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow) return(i); } -#endif /*USE_WX*/ /* @@ -408,7 +399,7 @@ do_start(void) timeBeginPeriod(1); QueryPerformanceFrequency(&qpc); timer_freq = qpc.QuadPart; - pclog("Main timer precision: %llu\n", timer_freq); + win_log("Main timer precision: %llu\n", timer_freq); /* Start the emulator, really. */ thMain = thread_create(pc_thread, &quited); @@ -588,15 +579,15 @@ plat_vidapi(char *name) { int i; - if (!strcasecmp(name, "default") || !strcasecmp(name, "system")) return(1); + if (!strcasecmp(name, "default") || !strcasecmp(name, "system")) return(0); - for (i=0; i<4; i++) { + for (i = 0; i < RENDERERS_NUM; i++) { if (vid_apis[0][i].name && !strcasecmp(vid_apis[0][i].name, name)) return(i); } /* Default value. */ - return(1); + return(0); } @@ -607,36 +598,26 @@ plat_vidapi_name(int api) char *name = "default"; switch(api) { -#if USE_WX case 0: - break; - - case 1: - name = "wxwidgets"; - break; -#else - case 0: - name = "ddraw"; - break; - - case 1: #if 0 - /* Direct3D is default. */ - name = "d3d"; + /* DirectDraw is default. */ + name = "ddraw"; #endif break; -#endif + + case 1: + name = "d3d"; + break; + + case 2: + name = "sdl"; + break; #ifdef USE_VNC - case 2: + case 3: name = "vnc"; break; -#endif -#ifdef USE_RDP - case 3: - name = "rdp"; - break; #endif } @@ -649,36 +630,28 @@ plat_setvid(int api) { int i; - pclog("Initializing VIDAPI: api=%d\n", api); + win_log("Initializing VIDAPI: api=%d\n", api); startblit(); video_wait_for_blit(); /* Close the (old) API. */ vid_apis[0][vid_api].close(); -//#ifdef USE_WX -// ui_check_menu_item(IDM_View_WX+vid_api, 0); -//#endif vid_api = api; -#ifndef USE_WX if (vid_apis[0][vid_api].local) ShowWindow(hwndRender, SW_SHOW); else ShowWindow(hwndRender, SW_HIDE); -#endif /* Initialize the (new) API. */ -#ifdef USE_WX -// ui_check_menu_item(IDM_View_WX+vid_api, 1); - i = vid_apis[0][vid_api].init(NULL); -#else i = vid_apis[0][vid_api].init((void *)hwndRender); -#endif endblit(); if (! i) return(0); device_force_redraw(); + vid_api_inited = 1; + return(1); } @@ -687,7 +660,7 @@ plat_setvid(int api) void plat_vidsize(int x, int y) { - if (! vid_apis[video_fullscreen][vid_api].resize) return; + if (!vid_api_inited || !vid_apis[video_fullscreen][vid_api].resize) return; startblit(); video_wait_for_blit(); @@ -716,7 +689,7 @@ plat_setfullscreen(int on) if (on && video_fullscreen_first) { video_fullscreen_first = 0; - ui_msgbox(MBX_INFO, (wchar_t *)IDS_2107); + ui_msgbox(MBX_INFO, (wchar_t *)IDS_2052); } /* OK, claim the video. */ @@ -731,10 +704,6 @@ plat_setfullscreen(int on) hw = (video_fullscreen) ? &hwndMain : &hwndRender; vid_apis[video_fullscreen][vid_api].init((void *) *hw); -#ifdef USE_WX - wx_set_fullscreen(on); -#endif - win_mouse_init(); /* Release video and make it redraw the screen. */ @@ -742,7 +711,7 @@ plat_setfullscreen(int on) device_force_redraw(); /* Finally, handle the host's mouse cursor. */ - /* pclog("%s full screen, %s cursor\n", on ? "enter" : "leave", on ? "hide" : "show"); */ + /* win_log("%s full screen, %s cursor\n", on ? "enter" : "leave", on ? "hide" : "show"); */ show_cursor(video_fullscreen ? 0 : -1); } @@ -754,8 +723,8 @@ take_screenshot(void) struct tm *info; time_t now; - pclog("Screenshot: video API is: %i\n", vid_api); - if ((vid_api < 0) || (vid_api > 1)) return; + win_log("Screenshot: video API is: %i\n", vid_api); + if ((vid_api < 0) || (vid_api > 2)) return; memset(fn, 0, sizeof(fn)); memset(path, 0, sizeof(path)); @@ -774,12 +743,6 @@ take_screenshot(void) wcscat(path, fn); switch(vid_api) { -#ifdef USE_WX - case 0: - case 1: - wx_screenshot(path); - break; -#else case 0: /* ddraw */ ddraw_take_screenshot(path); break; @@ -787,10 +750,13 @@ take_screenshot(void) case 1: /* d3d9 */ d3d_take_screenshot(path); break; -#endif + + case 2: /* sdl */ + sdl_take_screenshot(path); + break; #ifdef USE_VNC - case 2: /* vnc */ + case 3: /* vnc */ vnc_take_screenshot(path); break; #endif @@ -798,6 +764,16 @@ take_screenshot(void) } +/* LPARAM interface to plat_get_string(). */ +LPARAM win_get_string(int id) +{ + wchar_t *ret; + + ret = plat_get_string(id); + return ((LPARAM) ret); +} + + void /* plat_ */ startblit(void) { diff --git a/src/win/win.h b/src/win/win.h index c909b0829..eb62e8aea 100644 --- a/src/win/win.h +++ b/src/win/win.h @@ -8,7 +8,7 @@ * * Platform support defintions for Win32. * - * Version: @(#)win.h 1.0.15 2018/03/18 + * Version: @(#)win.h 1.0.18 2018/05/26 * * Authors: Sarah Walker, * Miran Grca, @@ -41,6 +41,7 @@ #define SUB_CLASS_NAME L"86BoxSubWnd" #define SB_CLASS_NAME L"86BoxStatusBar" #define SB_MENU_NAME L"StatusBarMenu" +#define FS_CLASS_NAME L"86BoxFullScreen" /* Application-specific window messages. */ #define WM_RESETD3D WM_USER @@ -50,15 +51,21 @@ #define WM_PAUSE 0x8890 #define WM_SENDHWND 0x8891 +#ifdef USE_VNC +#define RENDERERS_NUM 4 +#else +#define RENDERERS_NUM 3 +#endif + extern HINSTANCE hinstance; extern HWND hwndMain, hwndRender; extern HANDLE ghMutex; extern LCID lang_id; -extern HICON hIcon[512]; +extern HICON hIcon[256]; -extern int status_is_open; +// extern int status_is_open; extern char openfilestring[260]; extern WCHAR wopenfilestring[260]; @@ -91,6 +98,8 @@ extern void keyboard_handle(LPARAM lParam, int infocus); extern void win_mouse_init(void); extern void win_mouse_close(void); +extern LPARAM win_get_string(int id); + extern intptr_t fdd_type_to_icon(int type); #ifdef EMU_DEVICE_H @@ -109,6 +118,7 @@ extern int hard_disk_was_added(void); /* Platform UI support functions. */ extern int ui_init(int nCmdShow); +extern void plat_set_input(HWND h); /* Functions in win_about.c: */ @@ -123,11 +133,6 @@ extern void SoundGainDialogCreate(HWND hwnd); extern void NewFloppyDialogCreate(HWND hwnd, int id, int part); -/* Functions in win_status.c: */ -extern HWND hwndStatus; -extern void StatusWindowCreate(HWND hwnd); - - /* Functions in win_stbar.c: */ extern HWND hwndSBAR; extern void StatusBarCreate(HWND hwndParent, uintptr_t idStatus, HINSTANCE hInst); diff --git a/src/win/win_about.c b/src/win/win_about.c index 9e83d7a5c..355dd313d 100644 --- a/src/win/win_about.c +++ b/src/win/win_about.c @@ -8,13 +8,13 @@ * * Handle the About dialog. * - * Version: @(#)win_about.c 1.0.5 2017/12/13 + * Version: @(#)win_about.c 1.0.7 2018/06/02 * * Authors: Miran Grca, * Fred N. van Kempen, * - * Copyright 2016,2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #define UNICODE #define BITMAP WINDOWS_BITMAP @@ -39,13 +39,15 @@ static BOOL CALLBACK AboutDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { HWND h; + HANDLE ih; switch (message) { case WM_INITDIALOG: plat_pause(1); h = GetDlgItem(hdlg, IDC_ABOUT_ICON); + ih = LoadImage(hinstance,(PCTSTR)10,IMAGE_ICON,64,64,0); SendMessage(h, STM_SETIMAGE, (WPARAM)IMAGE_ICON, - (LPARAM)LoadImage(hinstance,(PCTSTR)100,IMAGE_ICON,64,64,0)); + (LPARAM)ih); break; case WM_COMMAND: diff --git a/src/win/win_cdrom.c b/src/win/win_cdrom.c index 0741bfc5e..012772655 100644 --- a/src/win/win_cdrom.c +++ b/src/win/win_cdrom.c @@ -8,7 +8,7 @@ * * Handle the platform-side of CDROM drives. * - * Version: @(#)win_cdrom.c 1.0.6 2018/03/17 + * Version: @(#)win_cdrom.c 1.0.8 2018/06/02 * * Authors: Sarah Walker, * Miran Grca, @@ -28,43 +28,18 @@ #include #include #include "../config.h" +#include "../disk/hdd.h" +#include "../scsi/scsi.h" #include "../cdrom/cdrom.h" +#include "../disk/zip.h" #include "../cdrom/cdrom_image.h" #include "../cdrom/cdrom_null.h" -#include "../disk/hdd.h" -#include "../disk/zip.h" -#include "../scsi/scsi.h" #include "../scsi/scsi_disk.h" #include "../plat.h" #include "../ui.h" #include "win.h" -uint8_t host_cdrom_drive_available[26]; -uint8_t host_cdrom_drive_available_num = 0; - - -void -cdrom_init_host_drives(void) -{ - WCHAR s[64]; - int i = 0; - - host_cdrom_drive_available_num = 0; - for (i='A'; i<='Z'; i++) { - _swprintf(s, L"%c:\\", i); - - if (GetDriveType(s)==DRIVE_CDROM) { - host_cdrom_drive_available[i - 'A'] = 1; - - host_cdrom_drive_available_num++; - } else { - host_cdrom_drive_available[i - 'A'] = 0; - } - } -} - - void cdrom_eject(uint8_t id) { @@ -73,12 +48,6 @@ cdrom_eject(uint8_t id) return; } - if ((cdrom_drives[id].host_drive >= 'A') && - (cdrom_drives[id].host_drive <= 'Z')) { - ui_sb_check_menu_item(SB_CDROM|id, - IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), MF_UNCHECKED); - } - if (cdrom_image[id].prev_image_path) { free(cdrom_image[id].prev_image_path); cdrom_image[id].prev_image_path = NULL; @@ -89,12 +58,13 @@ cdrom_eject(uint8_t id) wcscpy(cdrom_image[id].prev_image_path, cdrom_image[id].image_path); } cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; - cdrom_drives[id].handler->exit(id); - cdrom_close(id); - cdrom_null_open(id, 0); + cdrom[id]->handler->exit(id); + cdrom_close_handler(id); + memset(cdrom_image[id].image_path, 0, 2048); + cdrom_null_open(id); if (cdrom_drives[id].bus_type) { /* Signal disc change to the emulated machine. */ - cdrom_insert(id); + cdrom_insert(cdrom[id]); } ui_sb_check_menu_item(SB_CDROM|id, IDM_CDROM_IMAGE | id, MF_UNCHECKED); @@ -111,14 +81,13 @@ cdrom_eject(uint8_t id) void cdrom_reload(uint8_t id) { - int new_cdrom_drive; - if ((cdrom_drives[id].host_drive == cdrom_drives[id].prev_host_drive) || (cdrom_drives[id].prev_host_drive == 0) || (cdrom_drives[id].host_drive != 0)) { /* Switch from empty to empty. Do nothing. */ return; } - cdrom_close(id); + cdrom_close_handler(id); + memset(cdrom_image[id].image_path, 0, 2048); if (cdrom_drives[id].prev_host_drive == 200) { wcscpy(cdrom_image[id].image_path, cdrom_image[id].prev_image_path); @@ -127,7 +96,7 @@ cdrom_reload(uint8_t id) image_open(id, cdrom_image[id].image_path); if (cdrom_drives[id].bus_type) { /* Signal disc change to the emulated machine. */ - cdrom_insert(id); + cdrom_insert(cdrom[id]); } if (wcslen(cdrom_image[id].image_path) == 0) { ui_sb_check_menu_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, MF_CHECKED); @@ -140,17 +109,6 @@ cdrom_reload(uint8_t id) ui_sb_check_menu_item(SB_CDROM|id, IDM_CDROM_IMAGE | id, MF_CHECKED); ui_sb_update_icon_state(SB_CDROM|id, 0); } - } else { - new_cdrom_drive = cdrom_drives[id].prev_host_drive; - ioctl_open(id, new_cdrom_drive); - if (cdrom_drives[id].bus_type) { - /* Signal disc change to the emulated machine. */ - cdrom_insert(id); - } - ui_sb_check_menu_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, MF_UNCHECKED); - cdrom_drives[id].host_drive = new_cdrom_drive; - ui_sb_check_menu_item(SB_CDROM|id, IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), MF_CHECKED); - ui_sb_update_icon_state(SB_CDROM|id, 0); } ui_sb_enable_menu_item(SB_CDROM|id, IDM_CDROM_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); @@ -163,10 +121,10 @@ cdrom_reload(uint8_t id) void zip_eject(uint8_t id) { - zip_close(id); + zip_disk_close(zip[id]); if (zip_drives[id].bus_type) { /* Signal disk change to the emulated machine. */ - zip_insert(id); + zip_insert(zip[id]); } ui_sb_update_icon_state(SB_ZIP | id, 1); @@ -180,7 +138,7 @@ zip_eject(uint8_t id) void zip_reload(uint8_t id) { - zip_disk_reload(id); + zip_disk_reload(zip[id]); if (wcslen(zip_drives[id].image_path) == 0) { ui_sb_enable_menu_item(SB_ZIP|id, IDM_ZIP_EJECT | id, MF_BYCOMMAND | MF_GRAYED); ui_sb_update_icon_state(SB_ZIP|id, 1); @@ -194,56 +152,3 @@ zip_reload(uint8_t id) config_save(); } - - -void -removable_disk_unload(uint8_t id) -{ - if (wcslen(hdd[id].fn) == 0) { - /* Switch from empty to empty. Do nothing. */ - return; - } - - scsi_unloadhd(hdd[id].scsi_id, hdd[id].scsi_lun, id); - scsi_disk_insert(id); -} - - -void -removable_disk_eject(uint8_t id) -{ - removable_disk_unload(id); - ui_sb_update_icon_state(SB_RDISK|id, 1); - ui_sb_enable_menu_item(SB_RDISK|id, IDM_RDISK_EJECT | id, MF_BYCOMMAND | MF_GRAYED); - ui_sb_enable_menu_item(SB_RDISK|id, IDM_RDISK_RELOAD | id, MF_BYCOMMAND | MF_ENABLED); - ui_sb_enable_menu_item(SB_RDISK|id, IDM_RDISK_SEND_CHANGE | id, MF_BYCOMMAND | MF_GRAYED); - - ui_sb_update_tip(SB_RDISK|id); - - config_save(); -} - - -void -removable_disk_reload(uint8_t id) -{ - if (wcslen(hdd[id].fn) != 0) { - /* Attempting to reload while an image is already loaded. Do nothing. */ - return; - } - - scsi_reloadhd(id); -#if 0 - scsi_disk_insert(id); -#endif - - ui_sb_update_icon_state(SB_RDISK|id, wcslen(hdd[id].fn) ? 0 : 1); - - ui_sb_enable_menu_item(SB_RDISK|id, IDM_RDISK_EJECT | id, MF_BYCOMMAND | (wcslen(hdd[id].fn) ? MF_ENABLED : MF_GRAYED)); - ui_sb_enable_menu_item(SB_RDISK|id, IDM_RDISK_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); - ui_sb_enable_menu_item(SB_RDISK|id, IDM_RDISK_SEND_CHANGE | id, MF_BYCOMMAND | (wcslen(hdd[id].fn) ? MF_ENABLED : MF_GRAYED)); - - ui_sb_update_tip(SB_RDISK|id); - - config_save(); -} diff --git a/src/win/win_cdrom_ioctl.c b/src/win/win_cdrom_ioctl.c deleted file mode 100644 index 3261fc441..000000000 --- a/src/win/win_cdrom_ioctl.c +++ /dev/null @@ -1,1341 +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 CD-ROM host drive IOCTL interface for - * Windows using SCSI Passthrough Direct. - * - * Version: @(#)cdrom_ioctl.c 1.0.15 2018/03/20 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ -#define WINVER 0x0600 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../scsi/scsi.h" -#include "../cdrom/cdrom.h" -#include "../plat.h" - - -#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) - - -enum { - CD_STOPPED = 0, - CD_PLAYING, - CD_PAUSED -}; - - -typedef struct { - HANDLE hIOCTL; - CDROM_TOC toc; - int is_playing; -} cdrom_ioctl_windows_t; - - -cdrom_ioctl_windows_t cdrom_ioctl_windows[CDROM_NUM]; - -#ifdef ENABLE_CDROM_IOCTL_LOG -int cdrom_ioctl_do_log = ENABLE_CDROM_IOCTL_LOG; -#endif - - -static CDROM ioctl_cdrom; - - -static void -cdrom_ioctl_log(const char *format, ...) -{ -#ifdef ENABLE_CDROM_IOCTL_LOG - va_list ap; - - if (cdrom_ioctl_do_log) { - va_start(ap, format); - pclog_ex(format, ap); - va_end(ap); - } -#endif -} - -static int ioctl_hopen(uint8_t id); - -void ioctl_audio_callback(uint8_t id, int16_t *output, int len) -{ - cdrom_t *dev = cdrom[id]; - - RAW_READ_INFO in; - DWORD count; - - if (!cdrom_drives[id].sound_on || (dev->cd_state != CD_PLAYING)) - { - if (dev->cd_state == CD_PLAYING) - { - dev->seek_pos += (len >> 11); - cdrom_ioctl_log("ioctl_audio_callback(): playing but mute\n"); - } else - cdrom_ioctl_log("ioctl_audio_callback(): not playing\n"); - cdrom_ioctl_windows[id].is_playing = 0; - memset(output, 0, len * 2); - return; - } - cdrom_ioctl_log("ioctl_audio_callback(): dev->cd_buflen = %i, len = %i\n", dev->cd_buflen, len); - while (dev->cd_buflen < len) - { - if (dev->seek_pos < dev->cd_end) - { - in.DiskOffset.LowPart = dev->seek_pos * 2048; - in.DiskOffset.HighPart = 0; - in.SectorCount = 1; - in.TrackMode = CDDA; - if (!DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_RAW_READ, &in, sizeof(in), &(dev->cd_buffer[dev->cd_buflen]), 2352, &count, NULL)) - { - memset(&(dev->cd_buffer[dev->cd_buflen]), 0, (BUF_SIZE - dev->cd_buflen) * 2); - cdrom_ioctl_windows[id].is_playing = 0; - ioctl_close(id); - dev->cd_state = CD_STOPPED; - dev->cd_buflen = len; - cdrom_ioctl_log("ioctl_audio_callback(): read sector error, stopped\n"); - } - else - { - dev->seek_pos++; - dev->cd_buflen += (2352 / 2); - cdrom_ioctl_log("ioctl_audio_callback(): dev->seek_pos = %i\n", dev->seek_pos); - } - } - else - { - memset(&(dev->cd_buffer[dev->cd_buflen]), 0, (BUF_SIZE - dev->cd_buflen) * 2); - cdrom_ioctl_windows[id].is_playing = 0; - ioctl_close(id); - dev->cd_state = CD_STOPPED; - dev->cd_buflen = len; - cdrom_ioctl_log("ioctl_audio_callback(): reached the end\n"); - } - } - memcpy(output, dev->cd_buffer, len * 2); - memcpy(&dev->cd_buffer[0], &(dev->cd_buffer[len]), (BUF_SIZE - len) * 2); - dev->cd_buflen -= len; -} - -void ioctl_audio_stop(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - cdrom_ioctl_windows[id].is_playing = 0; - ioctl_close(id); - dev->cd_state = CD_STOPPED; -} - -static int get_track_nr(uint8_t id, uint32_t pos) -{ - cdrom_t *dev = cdrom[id]; - - int c; - int track = 0; - - if (dev->disc_changed) - { - return 0; - cdrom_ioctl_log("get_track_nr(): disc changed\n"); - } - - if (cdrom_ioctl[id].last_track_pos == pos) - { - cdrom_ioctl_log("get_track_nr(): cdrom_ioctl[id].last_track_pos == pos\n"); - return cdrom_ioctl[id].last_track_nr; - } - - /* for (c = cdrom_ioctl_windows[id].toc.FirstTrack; c < cdrom_ioctl_windows[id].toc.LastTrack; c++) */ - for (c = 0; c < cdrom_ioctl_windows[id].toc.LastTrack; c++) - { - uint32_t track_address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1], - cdrom_ioctl_windows[id].toc.TrackData[c].Address[2], - cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]) - 150; - - if (track_address <= pos) - { - cdrom_ioctl_log("get_track_nr(): track = %i\n", c); - track = c; - } - } - cdrom_ioctl[id].last_track_pos = pos; - cdrom_ioctl[id].last_track_nr = track; - - cdrom_ioctl_log("get_track_nr(): return %i\n", track); - return track; -} - -static uint32_t get_track_msf(uint8_t id, uint32_t track_no) -{ - cdrom_t *dev = cdrom[id]; - int c; - - if (dev->disc_changed) - { - return 0; - } - - for (c = cdrom_ioctl_windows[id].toc.FirstTrack; c < cdrom_ioctl_windows[id].toc.LastTrack; c++) - { - if (c == track_no) - { - return cdrom_ioctl_windows[id].toc.TrackData[c].Address[3] + (cdrom_ioctl_windows[id].toc.TrackData[c].Address[2] << 8) + (cdrom_ioctl_windows[id].toc.TrackData[c].Address[1] << 16); - } - } - return 0xffffffff; -} - -static void ioctl_playaudio(uint8_t id, uint32_t pos, uint32_t len, int ismsf) -{ - cdrom_t *dev = cdrom[id]; - int m = 0, s = 0, f = 0; - uint32_t start_msf = 0, end_msf = 0; - if (!cdrom_drives[id].host_drive) - { - return; - } - cdrom_ioctl_log("Play audio - %08X %08X %i\n", pos, len, ismsf); - if (ismsf == 2) - { - start_msf = get_track_msf(id, pos); - end_msf = get_track_msf(id, len); - if (start_msf == 0xffffffff) - { - return; - } - if (end_msf == 0xffffffff) - { - return; - } - m = (start_msf >> 16) & 0xff; - s = (start_msf >> 8) & 0xff; - f = start_msf & 0xff; - pos = MSFtoLBA(m, s, f) - 150; - m = (end_msf >> 16) & 0xff; - s = (end_msf >> 8) & 0xff; - f = end_msf & 0xff; - len = MSFtoLBA(m, s, f) - 150; - } - else if (ismsf == 1) - { - m = (pos >> 16) & 0xff; - s = (pos >> 8) & 0xff; - f = pos & 0xff; - - if (pos == 0xffffff) - { - cdrom_ioctl_log("Playing from current position (MSF)\n"); - pos = dev->seek_pos; - } - else - { - pos = MSFtoLBA(m, s, f) - 150; - } - - m = (len >> 16) & 0xff; - s = (len >> 8) & 0xff; - f = len & 0xff; - len = MSFtoLBA(m, s, f) - 150; - } - else if (ismsf == 0) - { - if (pos == 0xffffffff) - { - cdrom_ioctl_log("Playing from current position\n"); - pos = dev->seek_pos; - } - len += pos; - } - dev->seek_pos = pos; - dev->cd_end = len; - - if (!cdrom_ioctl_windows[id].is_playing) - { - ioctl_hopen(id); - cdrom_ioctl_windows[id].is_playing = 1; - } - dev->cd_state = CD_PLAYING; -} - -static void ioctl_pause(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - if (!cdrom_drives[id].host_drive) - { - return; - } - if (dev->cd_state == CD_PLAYING) - { - dev->cd_state = CD_PAUSED; - } -} - -static void ioctl_resume(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - if (!cdrom_drives[id].host_drive) - { - return; - } - if (dev->cd_state == CD_PAUSED) - { - dev->cd_state = CD_PLAYING; - } -} - -static void ioctl_stop(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - if (!cdrom_drives[id].host_drive) - { - return; - } - if (cdrom_ioctl_windows[id].is_playing) - { - cdrom_ioctl_windows[id].is_playing = 0; - ioctl_close(id); - } - dev->cd_state = CD_STOPPED; -} - -static int ioctl_ready(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - unsigned long size; - int temp; - CDROM_TOC ltoc; - if (!cdrom_drives[id].host_drive) - { - return 0; - } - if (cdrom_ioctl_windows[id].hIOCTL == NULL) - { - ioctl_hopen(id); - temp = DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_READ_TOC, NULL, 0, <oc, sizeof(ltoc), &size, NULL); - ioctl_close(id); - } - else - { - temp = DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_READ_TOC, NULL, 0, <oc, sizeof(ltoc), &size, NULL); - } - if (!temp) - { - return 0; - } - if ((ltoc.TrackData[ltoc.LastTrack].Address[1] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[1]) || - (ltoc.TrackData[ltoc.LastTrack].Address[2] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[2]) || - (ltoc.TrackData[ltoc.LastTrack].Address[3] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[3]) || - dev->disc_changed || (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive)) - { - dev->cd_state = CD_STOPPED; - if (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive) - { - cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; - } - return 1; - } - return 1; -} - -static int ioctl_get_last_block(uint8_t id, unsigned char starttrack, int msf, int maxlen, int single) -{ - cdrom_t *dev = cdrom[id]; - unsigned long size; - int c, d = 0; - CDROM_TOC lbtoc; - int lb = 0; - if (!cdrom_drives[id].host_drive) - { - return 0; - } - dev->cd_state = CD_STOPPED; - ioctl_hopen(id); - DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_READ_TOC, NULL, 0, &lbtoc, sizeof(lbtoc), &size, NULL); - ioctl_close(id); - dev->disc_changed = 0; - for (c=d; c <= lbtoc.LastTrack; c++) - { - uint32_t address; - address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1], cdrom_ioctl_windows[id].toc.TrackData[c].Address[2], cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]); - if (address > lb) - { - lb = address; - } - } - return lb; -} - -static void ioctl_read_capacity(uint8_t id, uint8_t *b); - -static int ioctl_medium_changed(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - unsigned long size; - int temp; - CDROM_TOC ltoc; - if (!cdrom_drives[id].host_drive) - { - return 0; /* This will be handled by the not ready handler instead. */ - } - ioctl_hopen(id); - temp = DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_READ_TOC, NULL, 0, <oc,sizeof(ltoc), &size, NULL); - ioctl_close(id); - if (!temp) - { - return 0; /* Drive empty, a not ready handler matter, not disc change. */ - } - if (dev->disc_changed || (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive)) - { - dev->cd_state = CD_STOPPED; - cdrom_ioctl_windows[id].toc = ltoc; - dev->disc_changed = 0; - if (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive) - { - cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; - } - ioctl_hopen(id); - cdrom_ioctl[id].capacity_read=0; /* With this two lines, we read the READ CAPACITY command output from the host drive into our cache buffer. */ - ioctl_read_capacity(id, NULL); - ioctl_close(id); - dev->cdrom_capacity = ioctl_get_last_block(id, 0, 0, 4096, 0); - return 1; - } - else - { - if ((ltoc.TrackData[ltoc.LastTrack].Address[1] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[1]) || - (ltoc.TrackData[ltoc.LastTrack].Address[2] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[2]) || - (ltoc.TrackData[ltoc.LastTrack].Address[3] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[3])) - { - dev->cd_state = CD_STOPPED; - cdrom_ioctl_log("Setting TOC...\n"); - cdrom_ioctl_windows[id].toc = ltoc; - ioctl_hopen(id); - cdrom_ioctl[id].capacity_read=0; /* With this two lines, we read the READ CAPACITY command output from the host drive into our cache buffer. */ - ioctl_read_capacity(id, NULL); - ioctl_close(id); - dev->cdrom_capacity = ioctl_get_last_block(id, 0, 0, 4096, 0); - return 1; /* TOC mismatches. */ - } - } - return 0; /* None of the above, return 0. */ -} - -static uint8_t ioctl_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf) -{ - cdrom_t *dev = cdrom[id]; - CDROM_SUB_Q_DATA_FORMAT insub; - SUB_Q_CHANNEL_DATA sub; - unsigned long size; - int pos = 0, track; - uint32_t cdpos, track_address, dat; - - if (!cdrom_drives[id].host_drive) return 0; - - cdpos = dev->seek_pos; - - if (dev->last_subchannel_pos == cdpos) - { - memcpy(&insub, dev->sub_q_data_format, sizeof(insub)); - memcpy(&sub, dev->sub_q_channel_data, sizeof(sub)); - } - else - { - insub.Format = IOCTL_CDROM_CURRENT_POSITION; - ioctl_hopen(id); - DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL,&insub,sizeof(insub),&sub,sizeof(sub),&size,NULL); - ioctl_close(id); - memset(dev->sub_q_data_format, 0, 16); - memcpy(dev->sub_q_data_format, &insub, sizeof(insub)); - memset(dev->sub_q_channel_data, 0, 256); - memcpy(dev->sub_q_channel_data, &sub, sizeof(sub)); - dev->last_subchannel_pos = cdpos; - } - - if (dev->cd_state == CD_PLAYING || dev->cd_state == CD_PAUSED) - { - track = get_track_nr(id, cdpos); - track_address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[track].Address[1], - cdrom_ioctl_windows[id].toc.TrackData[track].Address[2], - cdrom_ioctl_windows[id].toc.TrackData[track].Address[3]) - 150; - - cdrom_ioctl_log("ioctl_getcurrentsubchannel(): cdpos = %i, track = %i, track_address = %i\n", cdpos, track, track_address); - - b[pos++] = sub.CurrentPosition.Control; - b[pos++] = track + 1; - b[pos++] = sub.CurrentPosition.IndexNumber; - - if (msf) - { - dat = cdpos + 150; - b[pos + 3] = (uint8_t)(dat % 75); dat /= 75; - b[pos + 2] = (uint8_t)(dat % 60); dat /= 60; - b[pos + 1] = (uint8_t)dat; - b[pos] = 0; - pos += 4; - dat = cdpos - track_address; - b[pos + 3] = (uint8_t)(dat % 75); dat /= 75; - b[pos + 2] = (uint8_t)(dat % 60); dat /= 60; - b[pos + 1] = (uint8_t)dat; - b[pos] = 0; - pos += 4; - } - else - { - b[pos++] = (cdpos >> 24) & 0xff; - b[pos++] = (cdpos >> 16) & 0xff; - b[pos++] = (cdpos >> 8) & 0xff; - b[pos++] = cdpos & 0xff; - cdpos -= track_address; - b[pos++] = (cdpos >> 24) & 0xff; - b[pos++] = (cdpos >> 16) & 0xff; - b[pos++] = (cdpos >> 8) & 0xff; - b[pos++] = cdpos & 0xff; - } - - if (dev->cd_state == CD_PLAYING) return 0x11; - return 0x12; - } - - b[pos++]=sub.CurrentPosition.Control; - b[pos++]=sub.CurrentPosition.TrackNumber; - b[pos++]=sub.CurrentPosition.IndexNumber; - - cdrom_ioctl_log("cdpos = %i, track_address = %i\n", MSFtoLBA(sub.CurrentPosition.AbsoluteAddress[1], sub.CurrentPosition.AbsoluteAddress[2], sub.CurrentPosition.AbsoluteAddress[3]), MSFtoLBA(sub.CurrentPosition.TrackRelativeAddress[1], sub.CurrentPosition.TrackRelativeAddress[2], sub.CurrentPosition.TrackRelativeAddress[3])); - - if (msf) - { - int c; - for (c = 0; c < 4; c++) - { - b[pos++] = sub.CurrentPosition.AbsoluteAddress[c]; - } - for (c = 0; c < 4; c++) - { - b[pos++] = sub.CurrentPosition.TrackRelativeAddress[c]; - } - } - else - { - uint32_t temp = MSFtoLBA(sub.CurrentPosition.AbsoluteAddress[1], sub.CurrentPosition.AbsoluteAddress[2], sub.CurrentPosition.AbsoluteAddress[3]) - 150; - b[pos++] = temp >> 24; - b[pos++] = temp >> 16; - b[pos++] = temp >> 8; - b[pos++] = temp; - temp = MSFtoLBA(sub.CurrentPosition.TrackRelativeAddress[1], sub.CurrentPosition.TrackRelativeAddress[2], sub.CurrentPosition.TrackRelativeAddress[3]) - 150; - b[pos++] = temp >> 24; - b[pos++] = temp >> 16; - b[pos++] = temp >> 8; - b[pos++] = temp; - } - - return 0x13; -} - -static void ioctl_eject(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - unsigned long size; - if (!cdrom_drives[id].host_drive) - { - return; - } - if (cdrom_ioctl_windows[id].is_playing) - { - cdrom_ioctl_windows[id].is_playing = 0; - ioctl_stop(id); - } - dev->cd_state = CD_STOPPED; - ioctl_hopen(id); - DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_STORAGE_EJECT_MEDIA,NULL,0,NULL,0,&size,NULL); - ioctl_close(id); -} - -static void ioctl_load(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - unsigned long size; - if (!cdrom_drives[id].host_drive) - { - return; - } - if (cdrom_ioctl_windows[id].is_playing) - { - cdrom_ioctl_windows[id].is_playing = 0; - ioctl_stop(id); - } - dev->cd_state = CD_STOPPED; - ioctl_hopen(id); - DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_STORAGE_LOAD_MEDIA,NULL,0,NULL,0,&size,NULL); - cdrom_ioctl[id].capacity_read=0; /* With this two lines, we read the READ CAPACITY command output from the host drive into our cache buffer. */ - ioctl_read_capacity(id, NULL); - ioctl_close(id); - dev->cdrom_capacity = ioctl_get_last_block(id, 0, 0, 4096, 0); -} - -static int ioctl_is_track_audio(uint8_t id, uint32_t pos, int ismsf) -{ - cdrom_t *dev = cdrom[id]; - - int c; - int control = 0; - - uint32_t track_address = 0; - - if (dev->disc_changed) - { - return 0; - } - - for (c = 0; cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber != 0xaa; c++) - { - if (ismsf) { - track_address = cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]; - track_address |= (cdrom_ioctl_windows[id].toc.TrackData[c].Address[2] << 8); - track_address |= (cdrom_ioctl_windows[id].toc.TrackData[c].Address[1] << 16); - } else { - track_address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1],cdrom_ioctl_windows[id].toc.TrackData[c].Address[2],cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]); - track_address -= 150; - } - - if (cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber >= cdrom_ioctl_windows[id].toc.FirstTrack && - cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber <= cdrom_ioctl_windows[id].toc.LastTrack && - track_address <= pos) - control = cdrom_ioctl_windows[id].toc.TrackData[c].Control; - } - - if ((control & 0xd) <= 1) - return 1; - else - return 0; -} - -/* 00, 08, 10, 18, 20, 28, 30, 38 */ -int flags_to_size[5][32] = { { 0, 0, 2352, 2352, 2352, 2352, 2352, 2352, /* 00-38 (CD-DA) */ - 2352, 2352, 2352, 2352, 2352, 2352, 2352, 2352, /* 40-78 */ - 2352, 2352, 2352, 2352, 2352, 2352, 2352, 2352, /* 80-B8 */ - 2352, 2352, 2352, 2352, 2352, 2352, 2352, 2352 }, /* C0-F8 */ - { 0, 0, 2048, 2336, 4, -296, 2052, 2344, /* 00-38 (Mode 1) */ - 8, -296, 2048, 2048, 12, -296, 2052, 2052, /* 40-78 */ - -296, -296, -296, -296, 16, -296, 2064, 2344, /* 80-B8 */ - -296, -296, 2048, 2048, 24, -296, 2064, 2352 }, /* C0-F8 */ - { 0, 0, 2336, 2336, 4, -296, 2340, 2340, /* 00-38 (Mode 2 non-XA) */ - 8, -296, 2336, 2336, 12, -296, 2340, 2340, /* 40-78 */ - -296, -296, -296, -296, 16, -296, 2352, 2340, /* 80-B8 */ - -296, -296, 2336, 2336, 24, -296, 2352, 2352 }, /* C0-F8 */ - { 0, 0, 2048, 2336, 4, -296, -296, -296, /* 00-38 (Mode 2 Form 1) */ - 8, -296, 2056, 2344, 12, -296, 2060, 2340, /* 40-78 */ - -296, -296, -296, -296, 16, -296, -296, -296, /* 80-B8 */ - -296, -296, -296, -296, 24, -296, 2072, 2352 }, /* C0-F8 */ - { 0, 0, 2328, 2328, 4, -296, -296, -296, /* 00-38 (Mode 2 Form 2) */ - 8, -296, 2336, 2336, 12, -296, 2340, 2340, /* 40-78 */ - -296, -296, -296, -296, 16, -296, -296, -296, /* 80-B8 */ - -296, -296, -296, -296, 24, -296, 2352, 2352 } /* C0-F8 */ - }; - -static int ioctl_get_sector_data_type(uint8_t id, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, int ismsf); - -static void cdrom_illegal_mode(uint8_t id) -{ - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_ILLEGAL_MODE_FOR_THIS_TRACK; - cdrom_ascq = 0; -} - -struct sptd_with_sense -{ - SCSI_PASS_THROUGH s; - ULONG Filler; - UCHAR sense[32]; - UCHAR data[65536]; -} sptd; - -static int ioctl_get_block_length(uint8_t id, const UCHAR *cdb, int number_of_blocks, int no_length_check) -{ - cdrom_t *dev = cdrom[id]; - - int sector_type = 0; - int temp_len = 0; - - if (no_length_check) - { - switch (cdb[0]) - { - case 0x25: /* READ CAPACITY */ - case 0x44: /* READ HEADER */ - return 8; - case 0x42: /* READ SUBCHANNEL */ - case 0x43: /* READ TOC */ - case 0x51: /* READ DISC INFORMATION */ - case 0x52: /* READ TRACK INFORMATION */ - case 0x5A: /* MODE SENSE (10) */ - return (((uint32_t) cdb[7]) << 8) | ((uint32_t) cdb[8]); - case 0xAD: /* READ DVD STRUCTURE */ - return (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - default: - return 65534; - } - } - - switch (cdb[0]) - { - case 0x25: /* READ CAPACITY */ - case 0x44: /* READ HEADER */ - return 8; - case 0x42: /* READ SUBCHANNEL */ - case 0x43: /* READ TOC */ - case 0x51: /* READ DISC INFORMATION */ - case 0x52: /* READ TRACK INFORMATION */ - case 0x5A: /* MODE SENSE (10) */ - return (((uint32_t) cdb[7]) << 8) | ((uint32_t) cdb[8]); - case 0xAD: /* READ DVD STRUCTURE */ - return (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - case 0x08: - case 0x28: - case 0xa8: - /* READ (6), READ (10), READ (12) */ - return 2048 * number_of_blocks; - break; - case 0xb9: - sector_type = (cdb[1] >> 2) & 7; - if (sector_type == 0) - { - sector_type = ioctl_get_sector_data_type(id, 0, cdb[3], cdb[4], cdb[5], 1); - if (sector_type == 0) - { - cdrom_illegal_mode(id); - return -1; - } - } - goto common_handler; - case 0xbe: - /* READ CD MSF, READ CD */ - sector_type = (cdb[1] >> 2) & 7; - if (sector_type == 0) - { - sector_type = ioctl_get_sector_data_type(id, cdb[2], cdb[3], cdb[4], cdb[5], 0); - if (sector_type == 0) - { - cdrom_illegal_mode(id); - return -1; - } - } -common_handler: - temp_len = flags_to_size[sector_type - 1][cdb[9] >> 3]; - if ((cdb[9] & 6) == 2) - { - temp_len += 294; - } - else if ((cdb[9] & 6) == 4) - { - temp_len += 296; - } - if ((cdb[10] & 7) == 1) - { - temp_len += 96; - } - else if ((cdb[10] & 7) == 2) - { - temp_len += 16; - } - else if ((cdb[10] & 7) == 4) - { - temp_len += 96; - } - if (temp_len <= 0) - { - cdrom_illegal_mode(id); - return -1; - } - return temp_len * dev->requested_blocks; - break; - default: - /* Other commands */ - return 65534; - break; - } - -} - -static int SCSICommand(uint8_t id, const UCHAR *cdb, UCHAR *buf, uint32_t *len, int no_length_check) -{ - DWORD ioctl_bytes; - int ioctl_rv = 0; - - SCSISense.SenseKey = 0; - SCSISense.Asc = 0; - SCSISense.Ascq = 0; - - *len = 0; - memset(&sptd, 0, sizeof(sptd)); - sptd.s.Length = sizeof(SCSI_PASS_THROUGH); - sptd.s.CdbLength = 12; - sptd.s.DataIn = SCSI_IOCTL_DATA_IN; - sptd.s.TimeOutValue = 80 * 60; - sptd.s.DataTransferLength = ioctl_get_block_length(id, cdb, cdrom_ioctl[id].actual_requested_blocks, no_length_check); - sptd.s.SenseInfoOffset = (uintptr_t)&sptd.sense - (uintptr_t)&sptd; - sptd.s.SenseInfoLength = 32; - sptd.s.DataBufferOffset = (uintptr_t)&sptd.data - (uintptr_t)&sptd; - - memcpy(sptd.s.Cdb, cdb, 12); - ioctl_rv = DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_SCSI_PASS_THROUGH, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL); - - if (sptd.s.SenseInfoLength) - { - cdrom_sense_key = sptd.sense[2]; - cdrom_asc = sptd.sense[12]; - cdrom_ascq = sptd.sense[13]; - } - - cdrom_ioctl_log("Transferred length: %i (command: %02X)\n", sptd.s.DataTransferLength, cdb[0]); - cdrom_ioctl_log("Sense length: %i (%02X %02X %02X %02X %02X)\n", sptd.s.SenseInfoLength, sptd.sense[0], sptd.sense[1], sptd.sense[2], sptd.sense[12], sptd.sense[13]); - cdrom_ioctl_log("IOCTL bytes: %i; SCSI status: %i, status: %i, LastError: %08X\n", ioctl_bytes, sptd.s.ScsiStatus, ioctl_rv, GetLastError()); - cdrom_ioctl_log("DATA: %02X %02X %02X %02X %02X %02X\n", sptd.data[0], sptd.data[1], sptd.data[2], sptd.data[3], sptd.data[4], sptd.data[5]); - cdrom_ioctl_log(" %02X %02X %02X %02X %02X %02X\n", sptd.data[6], sptd.data[7], sptd.data[8], sptd.data[9], sptd.data[10], sptd.data[11]); - cdrom_ioctl_log(" %02X %02X %02X %02X %02X %02X\n", sptd.data[12], sptd.data[13], sptd.data[14], sptd.data[15], sptd.data[16], sptd.data[17]); - cdrom_ioctl_log("SENSE: %02X %02X %02X %02X %02X %02X\n", sptd.sense[0], sptd.sense[1], sptd.sense[2], sptd.sense[3], sptd.sense[4], sptd.sense[5]); - cdrom_ioctl_log(" %02X %02X %02X %02X %02X %02X\n", sptd.sense[6], sptd.sense[7], sptd.sense[8], sptd.sense[9], sptd.sense[10], sptd.sense[11]); - cdrom_ioctl_log(" %02X %02X %02X %02X %02X %02X\n", sptd.sense[12], sptd.sense[13], sptd.sense[14], sptd.sense[15], sptd.sense[16], sptd.sense[17]); - *len = sptd.s.DataTransferLength; - if (sptd.s.DataTransferLength != 0) - { - memcpy(buf, sptd.data, sptd.s.DataTransferLength); - } - - return ioctl_rv; -} - -static void ioctl_read_capacity(uint8_t id, uint8_t *b) -{ - cdrom_t *dev = cdrom[id]; - uint32_t len = 0; - - const UCHAR cdb[] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - UCHAR buf[16]; - - if (!cdrom_ioctl[id].capacity_read || (b == NULL)) - { - SCSICommand(id, cdb, buf, &len, 1); - - memcpy(dev->rcbuf, buf, len); - cdrom_ioctl[id].capacity_read = 1; - } - else - { - memcpy(b, dev->rcbuf, 16); - } -} - -static int ioctl_media_type_id(uint8_t id) -{ - uint8_t old_sense[3] = { 0, 0, 0 }; - - UCHAR msbuf[28]; - uint32_t len = 0; - int sense = 0; - - const UCHAR cdb[] = { 0x5A, 0x00, 0x2A, 0, 0, 0, 0, 0, 28, 0, 0, 0 }; - - old_sense[0] = cdrom_sense_key; - old_sense[1] = cdrom_asc; - old_sense[2] = cdrom_asc; - - ioctl_hopen(id); - - SCSICommand(id, cdb, msbuf, &len, 1); - - ioctl_close(id); - - sense = cdrom_sense_key; - cdrom_sense_key = old_sense[0]; - cdrom_asc = old_sense[1]; - cdrom_asc = old_sense[2]; - - if (sense == 0) - { - return msbuf[2]; - } - else - { - return 3; - } -} - -static uint32_t msf_to_lba32(int lba) -{ - int m = (lba >> 16) & 0xff; - int s = (lba >> 8) & 0xff; - int f = lba & 0xff; - return (m * 60 * 75) + (s * 75) + f; -} - -static int ioctl_get_type(uint8_t id, UCHAR *cdb, UCHAR *buf) -{ - int i = 0; - int ioctl_rv = 0; - - uint32_t len = 0; - - for (i = 2; i <= 5; i++) - { - cdb[1] = i << 2; - ioctl_rv = SCSICommand(id, cdb, buf, &len, 1); /* Bypass length check so we don't risk calling this again and getting stuck in an endless up. */ - if (ioctl_rv) - { - return i; - } - } - return 0; -} - -static int ioctl_sector_data_type(uint8_t id, int sector, int ismsf) -{ - int ioctl_rv = 0; - UCHAR cdb_lba[] = { 0xBE, 0, 0, 0, 0, 0, 0, 0, 1, 0x10, 0, 0 }; - UCHAR cdb_msf[] = { 0xB9, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0 }; - UCHAR buf[2352]; - - cdb_lba[2] = (sector >> 24); - cdb_lba[3] = ((sector >> 16) & 0xff); - cdb_lba[4] = ((sector >> 8) & 0xff); - cdb_lba[5] = (sector & 0xff); - - cdb_msf[3] = cdb_msf[6] = ((sector >> 16) & 0xff); - cdb_msf[4] = cdb_msf[7] = ((sector >> 8) & 0xff); - cdb_msf[5] = cdb_msf[8] = (sector & 0xff); - - ioctl_hopen(id); - - if (ioctl_is_track_audio(id, sector, ismsf)) - { - return 1; - } - - if (ismsf) - { - ioctl_rv = ioctl_get_type(id, cdb_msf, buf); - } - else - { - ioctl_rv = ioctl_get_type(id, cdb_lba, buf); - } - - if (ioctl_rv) - { - ioctl_close(id); - return ioctl_rv; - } - - if (ismsf) - { - sector = msf_to_lba32(sector); - if (sector < 150) - { - ioctl_close(id); - return 0; - } - sector -= 150; - ioctl_rv = ioctl_get_type(id, (UCHAR *) cdb_lba, buf); - } - - ioctl_close(id); - return ioctl_rv; -} - -static int ioctl_get_sector_data_type(uint8_t id, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, int ismsf) -{ - int sector = b3; - sector |= ((uint32_t) b2) << 8; - sector |= ((uint32_t) b1) << 16; - sector |= ((uint32_t) b0) << 24; - return ioctl_sector_data_type(id, sector, ismsf); -} - -static void ioctl_validate_toc(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - unsigned long size; - if (!cdrom_drives[id].host_drive) - { - return; - } - dev->cd_state = CD_STOPPED; - ioctl_hopen(id); - cdrom_ioctl_log("Validating TOC...\n"); - DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&cdrom_ioctl_windows[id].toc,sizeof(cdrom_ioctl_windows[id].toc),&size,NULL); - ioctl_close(id); - dev->disc_changed = 0; -} - -UCHAR buf[262144]; - -static int ioctl_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t *len) -{ - cdrom_t *dev = cdrom[id]; - - const UCHAR cdb[12]; - - int ret = 0; - - int temp_block_length = 0; - int buffer_pos = 0; - - uint32_t temp_len = 0; - - int i = 0; - - if (in_cdb[0] == 0x43) - { - /* This is a read TOC, so we have to validate the TOC to make the rest of the emulator happy. */ - ioctl_validate_toc(id); - } - - ioctl_hopen(id); - - memcpy((void *) cdb, in_cdb, 12); - - temp_len = 0; - temp_block_length = ioctl_get_block_length(id, cdb, dev->requested_blocks, 0); - if (temp_block_length != -1) { - cdrom_ioctl[id].actual_requested_blocks = 1; - if ((cdb[0] == 0x08) || (cdb[0] == 0x28) || (cdb[0] == 0xA8) || (cdb[0] == 0xB9) || (cdb[0] == 0xBE)) { - buffer_pos = 0; - temp_len = 0; - - for (i = 0; i < dev->requested_blocks; i++) - { - cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Transferring block...\n", id, cdrom_ioctl[id].actual_requested_blocks); - cdrom_update_cdb((uint8_t *) cdb, dev->sector_pos + i, 1); - ret = SCSICommand(id, cdb, b + buffer_pos, &temp_len, 0); - buffer_pos += temp_len; - } - *len = buffer_pos; - } else { - cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Expected transfer length %i is smaller than 65534, transferring all at once...\n", id, temp_block_length); - ret = SCSICommand(id, cdb, b, len, 0); - cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Single transfer done\n", id); - } - } - - cdrom_ioctl_log("IOCTL DATA: %02X %02X %02X %02X %02X %02X %02X %02X\n", b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); - - ioctl_close(id); - - cdrom_ioctl_log("IOCTL Returned value: %i\n", ret); - - return ret; -} - -static int ioctl_readtoc(uint8_t id, unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single) -{ - cdrom_t *dev = cdrom[id]; - int len=4; - DWORD size; - int c,d; - uint32_t temp; - uint32_t last_block; - if (!cdrom_drives[id].host_drive) - { - return 0; - } - dev->cd_state = CD_STOPPED; - ioctl_hopen(id); - DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&cdrom_ioctl_windows[id].toc,sizeof(cdrom_ioctl_windows[id].toc),&size,NULL); - ioctl_close(id); - dev->disc_changed = 0; - b[2]=cdrom_ioctl_windows[id].toc.FirstTrack; - b[3]=cdrom_ioctl_windows[id].toc.LastTrack; - d=0; - for (c=0;c<=cdrom_ioctl_windows[id].toc.LastTrack;c++) - { - if (cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber>=starttrack) - { - d=c; - break; - } - } - last_block = 0; - for (c=d;c<=cdrom_ioctl_windows[id].toc.LastTrack;c++) - { - uint32_t address; - if ((len+8)>maxlen) break; - b[len++]=0; /*Reserved*/ - b[len++]=(cdrom_ioctl_windows[id].toc.TrackData[c].Adr<<4)|cdrom_ioctl_windows[id].toc.TrackData[c].Control; - b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber; - b[len++]=0; /*Reserved*/ - address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1],cdrom_ioctl_windows[id].toc.TrackData[c].Address[2],cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]); - if (address > last_block) - last_block = address; - - if (msf) - { - b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].Address[0]; - b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].Address[1]; - b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].Address[2]; - b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]; - } - else - { - temp=MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1],cdrom_ioctl_windows[id].toc.TrackData[c].Address[2],cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]) - 150; - b[len++]=temp>>24; - b[len++]=temp>>16; - b[len++]=temp>>8; - b[len++]=temp; - } - if (single) break; - } - b[0] = (uint8_t)(((len-2) >> 8) & 0xff); - b[1] = (uint8_t)((len-2) & 0xff); - return len; -} - -static int ioctl_readtoc_session(uint8_t id, unsigned char *b, int msf, int maxlen) -{ - cdrom_t *dev = cdrom[id]; - int len=4; - int size; - uint32_t temp; - CDROM_READ_TOC_EX toc_ex; - CDROM_TOC_SESSION_DATA toc; - if (!cdrom_drives[id].host_drive) - { - return 0; - } - dev->cd_state = CD_STOPPED; - memset(&toc_ex,0,sizeof(toc_ex)); - memset(&toc,0,sizeof(toc)); - toc_ex.Format=CDROM_READ_TOC_EX_FORMAT_SESSION; - toc_ex.Msf=msf; - toc_ex.SessionTrack=0; - ioctl_hopen(id); - DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC_EX, &toc_ex,sizeof(toc_ex),&toc,sizeof(toc),(PDWORD)&size,NULL); - ioctl_close(id); - b[2]=toc.FirstCompleteSession; - b[3]=toc.LastCompleteSession; - b[len++]=0; /*Reserved*/ - b[len++]=(toc.TrackData[0].Adr<<4)|toc.TrackData[0].Control; - b[len++]=toc.TrackData[0].TrackNumber; - b[len++]=0; /*Reserved*/ - if (msf) - { - b[len++]=toc.TrackData[0].Address[0]; - b[len++]=toc.TrackData[0].Address[1]; - b[len++]=toc.TrackData[0].Address[2]; - b[len++]=toc.TrackData[0].Address[3]; - } - else - { - temp=MSFtoLBA(toc.TrackData[0].Address[1],toc.TrackData[0].Address[2],toc.TrackData[0].Address[3]) - 150; - b[len++]=temp>>24; - b[len++]=temp>>16; - b[len++]=temp>>8; - b[len++]=temp; - } - - return len; -} - -static int ioctl_readtoc_raw(uint8_t id, uint8_t *b, int maxlen) -{ - cdrom_t *dev = cdrom[id]; - int len=4; - int size; - int i; - CDROM_READ_TOC_EX toc_ex; - CDROM_TOC_FULL_TOC_DATA toc; - if (!cdrom_drives[id].host_drive) - { - return 0; - } - dev->cd_state = CD_STOPPED; - memset(&toc_ex,0,sizeof(toc_ex)); - memset(&toc,0,sizeof(toc)); - toc_ex.Format=CDROM_READ_TOC_EX_FORMAT_FULL_TOC; - toc_ex.Msf=1; - toc_ex.SessionTrack=0; - ioctl_hopen(id); - DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC_EX, &toc_ex,sizeof(toc_ex),&toc,sizeof(toc),(PDWORD)&size,NULL); - ioctl_close(id); - if (maxlen >= 3) b[2]=toc.FirstCompleteSession; - if (maxlen >= 4) b[3]=toc.LastCompleteSession; - - if (len >= maxlen) return len; - - size -= sizeof(CDROM_TOC_FULL_TOC_DATA); - size /= sizeof(toc.Descriptors[0]); - - for (i = 0; i <= size; i++) - { - b[len++]=toc.Descriptors[i].SessionNumber; - if (len == maxlen) return len; - b[len++]=(toc.Descriptors[i].Adr<<4)|toc.Descriptors[i].Control; - if (len == maxlen) return len; - b[len++]=0; - if (len == maxlen) return len; - b[len++]=toc.Descriptors[i].Reserved1; /*Reserved*/ - if (len == maxlen) return len; - b[len++]=toc.Descriptors[i].MsfExtra[0]; - if (len == maxlen) return len; - b[len++]=toc.Descriptors[i].MsfExtra[1]; - if (len == maxlen) return len; - b[len++]=toc.Descriptors[i].MsfExtra[2]; - if (len == maxlen) return len; - b[len++]=toc.Descriptors[i].Zero; - if (len == maxlen) return len; - b[len++]=toc.Descriptors[i].Msf[0]; - if (len == maxlen) return len; - b[len++]=toc.Descriptors[i].Msf[1]; - if (len == maxlen) return len; - b[len++]=toc.Descriptors[i].Msf[2]; - if (len == maxlen) return len; - } - - return len; -} - -static uint32_t ioctl_size(uint8_t id) -{ - uint8_t capacity_buffer[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - uint32_t capacity = 0; - - ioctl_read_capacity(id, capacity_buffer); - capacity = ((uint32_t) capacity_buffer[0]) << 24; - capacity |= ((uint32_t) capacity_buffer[1]) << 16; - capacity |= ((uint32_t) capacity_buffer[2]) << 8; - capacity |= (uint32_t) capacity_buffer[3]; - return capacity + 1; -} - -static int ioctl_status(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - if (!(ioctl_ready(id)) && (cdrom_drives[id].host_drive <= 0)) - { - return CD_STATUS_EMPTY; - } - - switch(dev->cd_state) - { - case CD_PLAYING: - return CD_STATUS_PLAYING; - case CD_PAUSED: - return CD_STATUS_PAUSED; - case CD_STOPPED: - return CD_STATUS_STOPPED; - default: - return CD_STATUS_EMPTY; - } -} - -void ioctl_reset(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - CDROM_TOC ltoc; - unsigned long size; - - if (!cdrom_drives[id].host_drive) - { - dev->disc_changed = 1; - return; - } - - ioctl_hopen(id); - DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_READ_TOC, NULL, 0, <oc, sizeof(ltoc), &size, NULL); - ioctl_close(id); - - cdrom_ioctl_windows[id].toc = ltoc; - dev->disc_changed = 0; -} - -int ioctl_hopen(uint8_t id) -{ - if (cdrom_ioctl_windows[id].is_playing) return 0; - cdrom_ioctl_windows[id].hIOCTL = CreateFile(cdrom_ioctl[id].ioctl_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - return 0; -} - -#define rcs "Read capacity: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n" -#define drb dev->rcbuf - -int ioctl_open(uint8_t id, char d) -{ - cdrom_t *dev = cdrom[id]; - sprintf(cdrom_ioctl[id].ioctl_path,"\\\\.\\%c:",d); - pclog("IOCTL path: %s\n", cdrom_ioctl[id].ioctl_path); - dev->disc_changed = 1; - cdrom_ioctl_windows[id].hIOCTL = CreateFile(cdrom_ioctl[id].ioctl_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - cdrom_drives[id].handler = &ioctl_cdrom; - dev->handler_inited=1; - cdrom_ioctl_windows[id].is_playing = 0; - cdrom_ioctl[id].capacity_read=0; /* With these two lines, we read the READ CAPACITY command output from the host drive into our cache buffer. */ - ioctl_read_capacity(id, NULL); - pclog(rcs, drb[0], drb[1], drb[2], drb[3], drb[4], drb[5], drb[6], drb[7], - drb[8], drb[9], drb[10], drb[11], drb[12], drb[13], drb[14], drb[15]); - CloseHandle(cdrom_ioctl_windows[id].hIOCTL); - cdrom_ioctl_windows[id].hIOCTL = NULL; - return 0; -} - -void ioctl_close(uint8_t id) -{ - if (cdrom_ioctl_windows[id].is_playing) return; - if (cdrom_ioctl_windows[id].hIOCTL) - { - CloseHandle(cdrom_ioctl_windows[id].hIOCTL); - cdrom_ioctl_windows[id].hIOCTL = NULL; - } -} - -static void ioctl_exit(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - cdrom_ioctl_windows[id].is_playing = 0; - ioctl_stop(id); - dev->handler_inited=0; - dev->disc_changed = 1; -} - -static CDROM ioctl_cdrom= -{ - ioctl_ready, - ioctl_medium_changed, - ioctl_media_type_id, - ioctl_audio_callback, - ioctl_audio_stop, - ioctl_readtoc, - ioctl_readtoc_session, - ioctl_readtoc_raw, - ioctl_getcurrentsubchannel, - ioctl_pass_through, - NULL, - ioctl_playaudio, - ioctl_load, - ioctl_eject, - ioctl_pause, - ioctl_resume, - ioctl_size, - ioctl_status, - ioctl_is_track_audio, - ioctl_stop, - ioctl_exit -}; diff --git a/src/win/win_d3d.cpp b/src/win/win_d3d.cpp index 209875414..fe18d587c 100644 --- a/src/win/win_d3d.cpp +++ b/src/win/win_d3d.cpp @@ -8,7 +8,7 @@ * * Rendering module for Microsoft Direct3D 9. * - * Version: @(#)win_d3d.cpp 1.0.10 2018/01/15 + * Version: @(#)win_d3d.cpp 1.0.11 2018/05/26 * * Authors: Sarah Walker, * Miran Grca, @@ -183,8 +183,14 @@ d3d_blit_fs(int x, int y, int y1, int y2, int w, int h) hr = d3dTexture->LockRect(0, &dr, &lock_rect, 0); if (hr == D3D_OK) { - for (yy = y1; yy < y2; yy++) - if (buffer32) memcpy((void *)((uintptr_t)dr.pBits + ((yy - y1) * dr.Pitch)), &(((uint32_t *)buffer32->line[yy + y])[x]), w * 4); + for (yy = y1; yy < y2; yy++) { + if (buffer32) { + if (video_grayscale || invert_display) + video_transform_copy((uint32_t *)((uintptr_t)dr.pBits + ((yy - y1) * dr.Pitch)), &(((uint32_t *)buffer32->line[yy + y])[x]), w); + else + memcpy((void *)((uintptr_t)dr.pBits + ((yy - y1) * dr.Pitch)), &(((uint32_t *)buffer32->line[yy + y])[x]), w * 4); + } + } video_blit_complete(); d3dTexture->UnlockRect(0); @@ -288,9 +294,14 @@ d3d_blit(int x, int y, int y1, int y2, int w, int h) hr = d3dTexture->LockRect(0, &dr, &r, 0); if (hr == D3D_OK) { for (yy = y1; yy < y2; yy++) { - if (buffer32) - if ((y + yy) >= 0 && (y + yy) < buffer32->h) - memcpy((void *)((uintptr_t)dr.pBits + ((yy - y1) * dr.Pitch)), &(((uint32_t *)buffer32->line[yy + y])[x]), w * 4); + if (buffer32) { + if ((y + yy) >= 0 && (y + yy) < buffer32->h) { + if (video_grayscale || invert_display) + video_transform_copy((uint32_t *)((uintptr_t)dr.pBits + ((yy - y1) * dr.Pitch)), &(((uint32_t *)buffer32->line[yy + y])[x]), w); + else + memcpy((void *)((uintptr_t)dr.pBits + ((yy - y1) * dr.Pitch)), &(((uint32_t *)buffer32->line[yy + y])[x]), w * 4); + } + } } video_blit_complete(); diff --git a/src/win/win_ddraw.cpp b/src/win/win_ddraw.cpp index b211a6766..5168be9e2 100644 --- a/src/win/win_ddraw.cpp +++ b/src/win/win_ddraw.cpp @@ -11,7 +11,7 @@ * NOTES: This code should be re-merged into a single init() with a * 'fullscreen' argument, indicating FS mode is requested. * - * Version: @(#)win_ddraw.cpp 1.0.6 2018/03/16 + * Version: @(#)win_ddraw.cpp 1.0.10 2018/07/17 * * Authors: Sarah Walker, * Miran Grca, @@ -21,8 +21,9 @@ * Copyright 2016-2018 Miran Grca. * Copyright 2017,2018 Fred N. van Kempen. */ -#include +#include #include +#include #define UNICODE #define BITMAP WINDOWS_BITMAP #include @@ -31,6 +32,7 @@ #define PNG_DEBUG 0 #include +#define HAVE_STDARG_H #include "../86box.h" #include "../device.h" #include "../video/video.h" @@ -56,6 +58,26 @@ static png_structp png_ptr; static png_infop info_ptr; +#ifdef ENABLE_DDRAW_LOG +int ddraw_do_log = ENABLE_DDRAW_LOG; +#endif + + +static void +ddraw_log(const char *fmt, ...) +{ +#ifdef ENABLE_DDRAW_LOG + va_list ap; + + if (ddraw_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + static void CopySurface(IDirectDrawSurface4 *pDDSurface) { @@ -83,6 +105,9 @@ bgra_to_rgb(png_bytep *b_rgb, uint8_t *bgra, int width, int height) int i, j; uint8_t *r, *b; + if (video_grayscale || invert_display) + *bgra = video_color_transform(*bgra); + for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { r = &b_rgb[(height - 1) - i][j * 3]; @@ -110,7 +135,6 @@ DoubleLines(uint8_t *dst, uint8_t *src) static void SavePNG(wchar_t *szFilename, HBITMAP hBitmap) { - BITMAPFILEHEADER bmpFileHeader; BITMAPINFO bmpInfo; HDC hdc; LPVOID pBuf = NULL; @@ -121,7 +145,7 @@ SavePNG(wchar_t *szFilename, HBITMAP hBitmap) /* create file */ FILE *fp = plat_fopen(szFilename, (wchar_t *) L"wb"); if (!fp) { - pclog("[SavePNG] File %ls could not be opened for writing", szFilename); + ddraw_log("[SavePNG] File %ls could not be opened for writing", szFilename); return; } @@ -129,14 +153,14 @@ SavePNG(wchar_t *szFilename, HBITMAP hBitmap) png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { - pclog("[SavePNG] png_create_write_struct failed"); + ddraw_log("[SavePNG] png_create_write_struct failed"); fclose(fp); return; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { - pclog("[SavePNG] png_create_info_struct failed"); + ddraw_log("[SavePNG] png_create_info_struct failed"); fclose(fp); return; } @@ -155,7 +179,7 @@ SavePNG(wchar_t *szFilename, HBITMAP hBitmap) bmpInfo.bmiHeader.biWidth*abs(bmpInfo.bmiHeader.biHeight)*(bmpInfo.bmiHeader.biBitCount+7)/8; if ((pBuf = malloc(bmpInfo.bmiHeader.biSizeImage)) == NULL) { - pclog("[SavePNG] Unable to Allocate Bitmap Memory"); + ddraw_log("[SavePNG] Unable to Allocate Bitmap Memory"); fclose(fp); return; } @@ -164,7 +188,7 @@ SavePNG(wchar_t *szFilename, HBITMAP hBitmap) bmpInfo.bmiHeader.biSizeImage <<= 1; if ((pBuf2 = malloc(bmpInfo.bmiHeader.biSizeImage)) == NULL) { - pclog("[SavePNG] Unable to Allocate Secondary Bitmap Memory"); + ddraw_log("[SavePNG] Unable to Allocate Secondary Bitmap Memory"); free(pBuf); fclose(fp); return; @@ -173,7 +197,7 @@ SavePNG(wchar_t *szFilename, HBITMAP hBitmap) bmpInfo.bmiHeader.biHeight <<= 1; } - pclog("save png w=%i h=%i\n", bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight); + ddraw_log("save png w=%i h=%i\n", bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight); bmpInfo.bmiHeader.biCompression = BI_RGB; @@ -184,7 +208,7 @@ SavePNG(wchar_t *szFilename, HBITMAP hBitmap) PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); if ((b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * bmpInfo.bmiHeader.biHeight)) == NULL) { - pclog("[SavePNG] Unable to Allocate RGB Bitmap Memory"); + ddraw_log("[SavePNG] Unable to Allocate RGB Bitmap Memory"); free(pBuf2); free(pBuf); fclose(fp); @@ -216,7 +240,7 @@ SavePNG(wchar_t *szFilename, HBITMAP hBitmap) if (pBuf2) free(pBuf2); - if (pBuf) free(pBuf); + if (pBuf) free(pBuf); if (fp) fclose(fp); } @@ -238,7 +262,7 @@ ddraw_fs_size(RECT w_rect, RECT *r_dest, int w, int h) int ratio_w, ratio_h; double hsr, gsr, ra, d; - pclog("video_fullscreen_scale = %i\n", video_fullscreen_scale); + ddraw_log("video_fullscreen_scale = %i\n", video_fullscreen_scale); switch (video_fullscreen_scale) { case FULLSCR_SCALE_FULL: @@ -353,8 +377,14 @@ ddraw_blit_fs(int x, int y, int y1, int y2, int w, int h) return; } - for (yy = y1; yy < y2; yy++) - if (buffer32) memcpy((void *)((uintptr_t)ddsd.lpSurface + (yy * ddsd.lPitch)), &(((uint32_t *)buffer32->line[y + yy])[x]), w * 4); + for (yy = y1; yy < y2; yy++) { + if (buffer32) { + if (video_grayscale || invert_display) + video_transform_copy((uint32_t *)((uintptr_t)ddsd.lpSurface + (yy * ddsd.lPitch)), &(((uint32_t *)buffer32->line[y + yy])[x]), w); + else + memcpy((void *)((uintptr_t)ddsd.lpSurface + (yy * ddsd.lPitch)), &(((uint32_t *)buffer32->line[y + yy])[x]), w * 4); + } + } video_blit_complete(); lpdds_back->Unlock(NULL); @@ -426,10 +456,16 @@ ddraw_blit(int x, int y, int y1, int y2, int w, int h) } for (yy = y1; yy < y2; yy++) { - if (buffer32) - if ((y + yy) >= 0 && (y + yy) < buffer32->h) - memcpy((uint32_t *) &(((uint8_t *) ddsd.lpSurface)[yy * ddsd.lPitch]), &(((uint32_t *)buffer32->line[y + yy])[x]), w * 4); + if (buffer32) { + if ((y + yy) >= 0 && (y + yy) < buffer32->h) { + if (video_grayscale || invert_display) + video_transform_copy((uint32_t *) &(((uint8_t *) ddsd.lpSurface)[yy * ddsd.lPitch]), &(((uint32_t *)buffer32->line[y + yy])[x]), w); + else + memcpy((uint32_t *) &(((uint8_t *) ddsd.lpSurface)[yy * ddsd.lPitch]), &(((uint32_t *)buffer32->line[y + yy])[x]), w * 4); + } + } } + video_blit_complete(); lpdds_back->Unlock(NULL); diff --git a/src/win/win_devconf.c b/src/win/win_devconf.c index 5b1e80535..203fd2f32 100644 --- a/src/win/win_devconf.c +++ b/src/win/win_devconf.c @@ -8,7 +8,7 @@ * * Windows device configuration dialog implementation. * - * Version: @(#)win_devconf.c 1.0.17 2018/03/20 + * Version: @(#)win_devconf.c 1.0.18 2018/04/01 * * Authors: Sarah Walker, * Miran Grca, @@ -468,7 +468,7 @@ uint8_t deviceconfig_open(HWND hwnd, const device_t *device) deviceconfig_changed = 0; - memset(data_block, 0, 4096); + memset(data_block, 0, 16384); dlg->style = DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU; dlg->x = 10; @@ -480,10 +480,10 @@ uint8_t deviceconfig_open(HWND hwnd, const device_t *device) *data++ = 0; /*no menu*/ *data++ = 0; /*predefined dialog box class*/ - data += MultiByteToWideChar(CP_ACP, 0, "Device Configuration", -1, data, 50); + data += MultiByteToWideChar(CP_ACP, 0, "Device Configuration", -1, data, 120); *data++ = 9; /*Point*/ - data += MultiByteToWideChar(CP_ACP, 0, "Segoe UI", -1, data, 50); + data += MultiByteToWideChar(CP_ACP, 0, "Segoe UI", -1, data, 120); if (((uintptr_t)data) & 2) data++; diff --git a/src/win/win_dialog.c b/src/win/win_dialog.c index d578f7aa4..b5c0167b4 100644 --- a/src/win/win_dialog.c +++ b/src/win/win_dialog.c @@ -8,7 +8,7 @@ * * Several dialogs for the application. * - * Version: @(#)win_dialog.c 1.0.8 2018/01/21 + * Version: @(#)win_dialog.c 1.0.10 2018/04/29 * * Author: Miran Grca, * Fred N. van Kempen, @@ -21,10 +21,12 @@ #include #include #include -#include +#include #include +#include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../device.h" #include "../plat.h" @@ -32,53 +34,11 @@ #include "win.h" -WCHAR path[MAX_PATH]; WCHAR wopenfilestring[260]; char openfilestring[260]; uint8_t filterindex = 0; -static int CALLBACK -BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) -{ - if (uMsg == BFFM_INITIALIZED) - SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData); - - return(0); -} - - -wchar_t * -BrowseFolder(wchar_t *saved_path, wchar_t *title) -{ - BROWSEINFO bi = { 0 }; - LPITEMIDLIST pidl; - IMalloc *imalloc; - - bi.lpszTitle = title; - bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; - bi.lpfn = BrowseCallbackProc; - bi.lParam = (LPARAM) saved_path; - - pidl = SHBrowseForFolder(&bi); - if (pidl != 0) { - /* Get the name of the folder and put it in path. */ - SHGetPathFromIDList(pidl, path); - - /* Free memory used. */ - imalloc = 0; - if (SUCCEEDED(SHGetMalloc(&imalloc))) { - imalloc->lpVtbl->Free(imalloc, pidl); - imalloc->lpVtbl->Release(imalloc); - } - - return(path); - } - - return(L""); -} - - int ui_msgbox(int flags, void *arg) { @@ -185,28 +145,20 @@ file_dlg_w(HWND hwnd, WCHAR *f, WCHAR *fn, int save) ofn.Flags |= OFN_FILEMUSTEXIST; /* Display the Open dialog box. */ - if (save) { -// pclog("GetSaveFileName - lpstrFile = %s\n", ofn.lpstrFile); + if (save) r = GetSaveFileName(&ofn); - } else { -// pclog("GetOpenFileName - lpstrFile = %s\n", ofn.lpstrFile); + else r = GetOpenFileName(&ofn); - } plat_chdir(usr_path); if (r) { wcstombs(openfilestring, wopenfilestring, sizeof(openfilestring)); filterindex = ofn.nFilterIndex; -// pclog("File dialog return true\n"); return(0); } - /* pclog("File dialog return false\n"); */ - /* err = CommDlgExtendedError(); - pclog("CommDlgExtendedError return %04X\n", err); */ - return(1); } diff --git a/src/win/win_dynld.c b/src/win/win_dynld.c index 06a308365..a8901c4fc 100644 --- a/src/win/win_dynld.c +++ b/src/win/win_dynld.c @@ -8,22 +8,44 @@ * * Try to load a support DLL. * - * Version: @(#)win_dynld.c 1.0.6 2017/10/16 + * Version: @(#)win_dynld.c 1.0.7 2018/04/29 * * Author: Fred N. van Kempen, * - * Copyright 2017 Fred N. van Kempen + * Copyright 2017,2018 Fred N. van Kempen */ -#include +#include #include +#include #include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" #include "../plat_dynld.h" +#ifdef ENABLE_DYNLD_LOG +int dynld_do_log = ENABLE_DYNLD_LOG; +#endif + + +static void +dynld_log(const char *fmt, ...) +{ +#ifdef ENABLE_DYNLD_LOG + va_list ap; + + if (dynld_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + void * dynld_module(const char *name, dllimp_t *table) { @@ -33,7 +55,7 @@ dynld_module(const char *name, dllimp_t *table) /* See if we can load the desired module. */ if ((h = LoadLibrary(name)) == NULL) { - pclog("DynLd(\"%s\"): library not found!\n", name); + dynld_log("DynLd(\"%s\"): library not found!\n", name); return(NULL); } @@ -41,7 +63,7 @@ dynld_module(const char *name, dllimp_t *table) for (imp=table; imp->name!=NULL; imp++) { func = GetProcAddress(h, imp->name); if (func == NULL) { - pclog("DynLd(\"%s\"): function '%s' not found!\n", + dynld_log("DynLd(\"%s\"): function '%s' not found!\n", name, imp->name); CloseHandle(h); return(NULL); diff --git a/src/win/win_joystick.cpp b/src/win/win_joystick.cpp index 1cf4e6d13..5cba358e1 100644 --- a/src/win/win_joystick.cpp +++ b/src/win/win_joystick.cpp @@ -8,7 +8,7 @@ * * Joystick interface to host device. * - * Version: @(#)win_joystick.cpp 1.0.8 2018/03/18 + * Version: @(#)win_joystick.cpp 1.0.9 2018/04/29 * * Authors: Sarah Walker, * Miran Grca, @@ -19,8 +19,10 @@ #define DIRECTINPUT_VERSION 0x0800 #include #include -#include +#include #include +#include +#define HAVE_STDARG_H #include "../86box.h" #include "../device.h" #include "../plat.h" @@ -38,12 +40,32 @@ static LPDIRECTINPUTDEVICE8 lpdi_joystick[2] = {NULL, NULL}; static GUID joystick_guids[MAX_JOYSTICKS]; +#ifdef ENABLE_JOYSTICK_LOG +int joystick_do_log = ENABLE_JOYSTICK_LOG; +#endif + + +static void +joystick_log(const char *fmt, ...) +{ +#ifdef ENABLE_JOYSTICK_LOG + va_list ap; + + if (joystick_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + static BOOL CALLBACK joystick_enum_callback(LPCDIDEVICEINSTANCE lpddi, UNUSED(LPVOID data)) { if (joysticks_present >= MAX_JOYSTICKS) return DIENUM_STOP; - pclog("joystick_enum_callback : found joystick %i : %s\n", joysticks_present, lpddi->tszProductName); + joystick_log("joystick_enum_callback : found joystick %i : %s\n", joysticks_present, lpddi->tszProductName); joystick_guids[joysticks_present++] = lpddi->guidInstance; @@ -64,7 +86,7 @@ BOOL CALLBACK DIEnumDeviceObjectsCallback( lpddoi->guidType == GUID_Slider) { strncpy(state->axis[state->nr_axes].name, lpddoi->tszName, sizeof(state->axis[state->nr_axes].name)); - pclog("Axis %i : %s %x %x\n", state->nr_axes, state->axis[state->nr_axes].name, lpddoi->dwOfs, lpddoi->dwType); + joystick_log("Axis %i : %s %x %x\n", state->nr_axes, state->axis[state->nr_axes].name, lpddoi->dwOfs, lpddoi->dwType); if (lpddoi->guidType == GUID_XAxis) state->axis[state->nr_axes].id = 0; else if (lpddoi->guidType == GUID_YAxis) @@ -82,13 +104,13 @@ BOOL CALLBACK DIEnumDeviceObjectsCallback( else if (lpddoi->guidType == GUID_Button) { strncpy(state->button[state->nr_buttons].name, lpddoi->tszName, sizeof(state->button[state->nr_buttons].name)); - pclog("Button %i : %s %x %x\n", state->nr_buttons, state->button[state->nr_buttons].name, lpddoi->dwOfs, lpddoi->dwType); + joystick_log("Button %i : %s %x %x\n", state->nr_buttons, state->button[state->nr_buttons].name, lpddoi->dwOfs, lpddoi->dwType); state->nr_buttons++; } else if (lpddoi->guidType == GUID_POV) { strncpy(state->pov[state->nr_povs].name, lpddoi->tszName, sizeof(state->pov[state->nr_povs].name)); - pclog("POV %i : %s %x %x\n", state->nr_povs, state->pov[state->nr_povs].name, lpddoi->dwOfs, lpddoi->dwType); + joystick_log("POV %i : %s %x %x\n", state->nr_povs, state->pov[state->nr_povs].name, lpddoi->dwOfs, lpddoi->dwType); state->nr_povs++; } @@ -111,7 +133,7 @@ void joystick_init() if (FAILED(lpdi->EnumDevices(DIDEVTYPE_JOYSTICK, joystick_enum_callback, NULL, DIEDFL_ATTACHEDONLY))) fatal("joystick_init : EnumDevices failed\n"); - pclog("joystick_init: joysticks_present=%i\n", joysticks_present); + joystick_log("joystick_init: joysticks_present=%i\n", joysticks_present); for (c = 0; c < joysticks_present; c++) { @@ -130,18 +152,18 @@ void joystick_init() device_instance.dwSize = sizeof(device_instance); if (FAILED(lpdi_joystick[c]->GetDeviceInfo(&device_instance))) fatal("joystick_init : GetDeviceInfo failed\n"); - pclog("Joystick %i :\n", c); - pclog(" tszInstanceName = %s\n", device_instance.tszInstanceName); - pclog(" tszProductName = %s\n", device_instance.tszProductName); + joystick_log("Joystick %i :\n", c); + joystick_log(" tszInstanceName = %s\n", device_instance.tszInstanceName); + joystick_log(" tszProductName = %s\n", device_instance.tszProductName); strncpy(plat_joystick_state[c].name, device_instance.tszInstanceName, 64); memset(&devcaps, 0, sizeof(devcaps)); devcaps.dwSize = sizeof(devcaps); if (FAILED(lpdi_joystick[c]->GetCapabilities(&devcaps))) fatal("joystick_init : GetCapabilities failed\n"); - pclog(" Axes = %i\n", devcaps.dwAxes); - pclog(" Buttons = %i\n", devcaps.dwButtons); - pclog(" POVs = %i\n", devcaps.dwPOVs); + joystick_log(" Axes = %i\n", devcaps.dwAxes); + joystick_log(" Buttons = %i\n", devcaps.dwButtons); + joystick_log(" POVs = %i\n", devcaps.dwPOVs); lpdi_joystick[c]->EnumObjects(DIEnumDeviceObjectsCallback, &plat_joystick_state[c], DIDFT_ALL); @@ -246,7 +268,7 @@ void joystick_process(void) for (b = 0; b < 4; b++) plat_joystick_state[c].p[b] = joystate.rgdwPOV[b]; -// pclog("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", c, joystick_state[c].x, joystick_state[c].y, joystick_state[c].b[0], joystick_state[c].b[1], joysticks_present); +// joystick_log("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", c, joystick_state[c].x, joystick_state[c].y, joystick_state[c].b[0], joystick_state[c].b[1], joysticks_present); } for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) diff --git a/src/win/win_keyboard.c b/src/win/win_keyboard.c index 8c8873f54..7c08f6ca9 100644 --- a/src/win/win_keyboard.c +++ b/src/win/win_keyboard.c @@ -8,7 +8,7 @@ * * Windows raw keyboard input handler. * - * Version: @(#)win_keyboard.c 1.0.9 2018/02/10 + * Version: @(#)win_keyboard.c 1.0.10 2018/04/29 * * Author: Miran Grca, * @@ -95,7 +95,6 @@ keyboard_getkeymap(void) scancode_unmapped = convert_scan_code(scancode_unmapped); scancode_mapped = convert_scan_code(scancode_mapped); - /* pclog("Scan code map found: %04X -> %04X\n", scancode_unmapped, scancode_mapped); */ /* Ignore source scan codes with prefixes other than E1 that are not E1 1D. */ @@ -145,7 +144,6 @@ keyboard_handle(LPARAM lParam, int infocus) scancode = convert_scan_code(scancode); /* Remap it according to the list from the Registry */ - /* pclog("Scan code: %04X (map: %04X)\n", scancode, scancode_map[scancode]); */ scancode = scancode_map[scancode]; /* If it's not 0xFFFF, send it to the emulated diff --git a/src/win/win_midi.c b/src/win/win_midi.c index ba19c3950..6df91ca5d 100644 --- a/src/win/win_midi.c +++ b/src/win/win_midi.c @@ -1,7 +1,7 @@ #include #include -#include #include +#include #include #include #include "../86box.h" @@ -100,10 +100,7 @@ void plat_midi_play_sysex(uint8_t *sysex, unsigned int len) MMRESULT result; if (WaitForSingleObject(m_event, 2000) == WAIT_TIMEOUT) - { - pclog("Can't send MIDI message\n"); return; - } midiOutUnprepareHeader(midi_out_device, &m_hdr, sizeof(m_hdr)); diff --git a/src/win/win_new_floppy.c b/src/win/win_new_floppy.c index d00d492e3..a7954672b 100644 --- a/src/win/win_new_floppy.c +++ b/src/win/win_new_floppy.c @@ -8,7 +8,7 @@ * * Handle the New Floppy Image dialog. * - * Version: @(#)win_new_floppy.c 1.0.5 2018/03/19 + * Version: @(#)win_new_floppy.c 1.0.8 2018/05/25 * * Authors: Miran Grca, * @@ -29,6 +29,7 @@ #include "../plat.h" #include "../random.h" #include "../ui.h" +#include "../scsi/scsi.h" #include "../disk/zip.h" #include "win.h" @@ -50,22 +51,22 @@ typedef struct { } disk_size_t; -disk_size_t disk_sizes[14] = { { 0, 1, 2, 1, 0, 40, 8, 2, 0xFE, 2, 2, 1, 112 }, /* 160k */ - { 0, 1, 2, 1, 0, 40, 9, 2, 0xFC, 2, 2, 1, 112 }, /* 180k */ - { 0, 2, 2, 1, 0, 40, 8, 2, 0xFF, 2, 2, 1, 112 }, /* 320k */ - { 0, 2, 2, 1, 0, 40, 9, 2, 0xFD, 2, 2, 2, 112 }, /* 360k */ - { 0, 2, 2, 1, 0, 80, 8, 2, 0xFB, 2, 2, 2, 112 }, /* 640k */ - { 0, 2, 2, 1, 0, 80, 9, 2, 0xF9, 2, 2, 3, 112 }, /* 720k */ - { 1, 2, 0, 1, 1, 80, 15, 2, 0xF9, 1, 2, 7, 224 }, /* 1.2M */ - { 1, 2, 0, 1, 1, 77, 8, 3, 0xFE, 1, 2, 2, 192 }, /* 1.25M */ - { 1, 2, 0, 1, 0, 80, 18, 2, 0xF0, 1, 2, 9, 224 }, /* 1.44M */ - { 1, 2, 0, 1, 0, 80, 21, 2, 0xF0, 2, 2, 5, 16 }, /* DMF cluster 1024 */ - { 1, 2, 0, 1, 0, 80, 21, 2, 0xF0, 4, 2, 3, 16 }, /* DMF cluster 2048 */ - { 2, 2, 3, 1, 0, 80, 36, 2, 0xF0, 2, 2, 9, 240 }, /* 2.88M */ - { 0, 64, 0, 0, 0, 96, 32, 2, 0, 0, 0, 0, 0 }, /* ZIP 100 */ - { 0, 64, 0, 0, 0, 239, 32, 2, 0, 0, 0, 0, 0 } }; /* ZIP 250 */ +static const disk_size_t disk_sizes[14] = { { 0, 1, 2, 1, 0, 40, 8, 2, 0xfe, 2, 2, 1, 112 }, /* 160k */ + { 0, 1, 2, 1, 0, 40, 9, 2, 0xfc, 2, 2, 1, 112 }, /* 180k */ + { 0, 2, 2, 1, 0, 40, 8, 2, 0xff, 2, 2, 1, 112 }, /* 320k */ + { 0, 2, 2, 1, 0, 40, 9, 2, 0xfd, 2, 2, 2, 112 }, /* 360k */ + { 0, 2, 2, 1, 0, 80, 8, 2, 0xfb, 2, 2, 2, 112 }, /* 640k */ + { 0, 2, 2, 1, 0, 80, 9, 2, 0xf9, 2, 2, 3, 112 }, /* 720k */ + { 1, 2, 0, 1, 1, 80, 15, 2, 0xf9, 1, 2, 7, 224 }, /* 1.2M */ + { 1, 2, 0, 1, 1, 77, 8, 3, 0xfe, 1, 2, 2, 192 }, /* 1.25M */ + { 1, 2, 0, 1, 0, 80, 18, 2, 0xf0, 1, 2, 9, 224 }, /* 1.44M */ + { 1, 2, 0, 1, 0, 80, 21, 2, 0xf0, 2, 2, 5, 16 }, /* DMF cluster 1024 */ + { 1, 2, 0, 1, 0, 80, 21, 2, 0xf0, 4, 2, 3, 16 }, /* DMF cluster 2048 */ + { 2, 2, 3, 1, 0, 80, 36, 2, 0xf0, 2, 2, 9, 240 }, /* 2.88M */ + { 0, 64, 0, 0, 0, 96, 32, 2, 0, 0, 0, 0, 0 }, /* ZIP 100 */ + { 0, 64, 0, 0, 0, 239, 32, 2, 0, 0, 0, 0, 0 } }; /* ZIP 250 */ -static char *empty; +static unsigned char *empty; static int @@ -137,7 +138,7 @@ create_86f(WCHAR *file_name, disk_size_t disk_size, uint8_t rpm_mode) if (array_size2 & 15) array_size += 2; - empty = (char *) malloc(array_size); + empty = (unsigned char *) malloc(array_size); memset(tarray, 0, 2048); memset(empty, 0, array_size); @@ -209,7 +210,7 @@ create_sector_image(WCHAR *file_name, disk_size_t disk_size, uint8_t is_fdi) zero_bytes = fat2_offs + fat_size + root_dir_bytes; if (!is_zip && is_fdi) { - empty = (char *) malloc(base); + empty = (unsigned char *) malloc(base); memset(empty, 0, base); *(uint32_t *) &(empty[0x08]) = (uint32_t) base; @@ -223,7 +224,7 @@ create_sector_image(WCHAR *file_name, disk_size_t disk_size, uint8_t is_fdi) free(empty); } - empty = (char *) malloc(total_size); + empty = (unsigned char *) malloc(total_size); memset(empty, 0x00, zero_bytes); if (!is_zip) { @@ -344,7 +345,7 @@ create_zip_sector_image(WCHAR *file_name, disk_size_t disk_size, uint8_t is_zdi, pbar_max++; if (is_zdi) { - empty = (char *) malloc(base); + empty = (unsigned char *) malloc(base); memset(empty, 0, base); *(uint32_t *) &(empty[0x08]) = (uint32_t) base; @@ -364,7 +365,7 @@ create_zip_sector_image(WCHAR *file_name, disk_size_t disk_size, uint8_t is_zdi, pbar_max -= 2; } - empty = (char *) malloc(total_size); + empty = (unsigned char *) malloc(total_size); memset(empty, 0x00, zero_bytes); if (total_sectors == ZIP_SECTORS) { @@ -566,16 +567,16 @@ NewFloppyDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) if (is_zip) { zip_types = zip_drives[fdd_id].is_250 ? 2 : 1; for (i = 0; i < zip_types; i++) - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) plat_get_string(IDS_5900 + i)); + SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_5900 + i)); } else { for (i = 0; i < 12; i++) - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) plat_get_string(IDS_5888 + i)); + SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_5888 + i)); } SendMessage(h, CB_SETCURSEL, 0, 0); EnableWindow(h, FALSE); h = GetDlgItem(hdlg, IDC_COMBO_RPM_MODE); for (i = 0; i < 4; i++) - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) plat_get_string(IDS_6144 + i)); + SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_6144 + i)); SendMessage(h, CB_SETCURSEL, 0, 0); EnableWindow(h, FALSE); ShowWindow(h, SW_HIDE); @@ -624,7 +625,7 @@ NewFloppyDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) return TRUE; case IDC_CFILE: - if (!file_dlg_w(hdlg, plat_get_string(is_zip ? IDS_2176 : IDS_2174), L"", 1)) { + if (!file_dlg_w(hdlg, plat_get_string(is_zip ? IDS_2055 : IDS_2062), L"", 1)) { if (!wcschr(wopenfilestring, L'.')) { if (wcslen(wopenfilestring) && (wcslen(wopenfilestring) <= 256)) { twcs = &wopenfilestring[wcslen(wopenfilestring)]; diff --git a/src/win/win_sdl.c b/src/win/win_sdl.c new file mode 100644 index 000000000..8fafd7e54 --- /dev/null +++ b/src/win/win_sdl.c @@ -0,0 +1,625 @@ +/* + * 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. + * + * Rendering module for libSDL2 + * + * NOTE: Given all the problems reported with FULLSCREEN use of SDL, + * we will not use that, but, instead, use a new window which + * coverrs the entire desktop. + * + * Version: @(#)win_sdl.c 1.0.0 2018/05/26 + * + * Authors: Fred N. van Kempen, + * Michael Drüing, + * + * Copyright 2018 Fred N. van Kempen. + * Copyright 2018 Michael Drüing. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#define UNICODE +#define WIN32_LEAN_AND_MEAN +#include +#include + +#define PNG_DEBUG 0 +#include + +#include +#include +#include +#include +#include "../86box.h" +#include "../device.h" +#include "../plat.h" +#include "../plat_dynld.h" +#include "../video/video.h" +#include "win.h" +#include "win_sdl.h" + + +#define PATH_SDL_DLL "sdl2.dll" + + +static void *sdl_handle = NULL; /* handle to libSDL2 DLL */ +static SDL_Window *sdl_win = NULL; +static SDL_Renderer *sdl_render = NULL; +static SDL_Texture *sdl_tex = NULL; +static HWND sdl_parent_hwnd = NULL; +static HWND sdl_hwnd = NULL; +static int sdl_w, sdl_h; +static int sdl_fs; +static int cur_w, cur_h; + +static png_structp png_ptr; +static png_infop info_ptr; + + +/* Pointers to the real functions. */ +static void (*sdl_GetVersion)(SDL_version *ver); +static char *const (*sdl_GetError)(void); +static int (*sdl_Init)(Uint32 flags); +static void (*sdl_Quit)(void); +static SDL_Window *(*sdl_CreateWindowFrom)(const void *data); +static void (*sdl_DestroyWindow)(SDL_Window *window); +static SDL_Renderer *(*sdl_CreateRenderer)(SDL_Window *window, + int index, Uint32 flags); +static void (*sdl_DestroyRenderer)(SDL_Renderer *renderer); +static SDL_Texture *(*sdl_CreateTexture)(SDL_Renderer *renderer, + Uint32 format, int access, + int w, int h); +static void (*sdl_DestroyTexture)(SDL_Texture *texture); +static int (*sdl_LockTexture)(SDL_Texture *texture, + const SDL_Rect *rect, + void **pixels, int *pitch); +static void (*sdl_UnlockTexture)(SDL_Texture *texture); +static int (*sdl_RenderCopy)(SDL_Renderer *renderer, + SDL_Texture *texture, + const SDL_Rect *srcrect, + const SDL_Rect *dstrect); +static void (*sdl_RenderPresent)(SDL_Renderer *renderer); +static void (*sdl_GetWindowSize)(SDL_Window* window, + int* w, + int* h); +static int (*sdl_RenderReadPixels)(SDL_Renderer* renderer, + const SDL_Rect* rect, + Uint32 format, + void* pixels, + int pitch); +static SDL_bool (*sdl_SetHint)(const char* name, + const char* value); + +static dllimp_t sdl_imports[] = { + { "SDL_GetVersion", &sdl_GetVersion }, + { "SDL_GetError", &sdl_GetError }, + { "SDL_Init", &sdl_Init }, + { "SDL_Quit", &sdl_Quit }, + { "SDL_CreateWindowFrom", &sdl_CreateWindowFrom }, + { "SDL_DestroyWindow", &sdl_DestroyWindow }, + { "SDL_CreateRenderer", &sdl_CreateRenderer }, + { "SDL_DestroyRenderer", &sdl_DestroyRenderer }, + { "SDL_CreateTexture", &sdl_CreateTexture }, + { "SDL_DestroyTexture", &sdl_DestroyTexture }, + { "SDL_LockTexture", &sdl_LockTexture }, + { "SDL_UnlockTexture", &sdl_UnlockTexture }, + { "SDL_RenderCopy", &sdl_RenderCopy }, + { "SDL_RenderPresent", &sdl_RenderPresent }, + { "SDL_GetWindowSize", &sdl_GetWindowSize }, + { "SDL_RenderReadPixels", &sdl_RenderReadPixels }, + { "SDL_SetHint", &sdl_SetHint }, + { NULL, NULL } +}; + + +#ifdef ENABLE_SDL_LOG +int sdl_do_log = ENABLE_SDL_LOG; +#endif + + +static void +sdl_log(const char *fmt, ...) +{ +#ifdef ENABLE_SDL_LOG + va_list ap; + + if (sdl_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + +static void +sdl_stretch(int *w, int *h, int *x, int *y) +{ + double dw, dh, dx, dy, temp, temp2, ratio_w, ratio_h, gsr, hsr; + + switch (video_fullscreen_scale) { + case FULLSCR_SCALE_FULL: + *w = sdl_w; + *h = sdl_h; + *x = 0; + *y = 0; + break; + case FULLSCR_SCALE_43: + dw = (double) sdl_w; + dh = (double) sdl_h; + temp = (dh / 3.0) * 4.0; + dx = (dw - temp) / 2.0; + dw = temp; + *w = (int) dw; + *h = (int) dh; + *x = (int) dx; + *y = 0; + break; + case FULLSCR_SCALE_SQ: + dw = (double) sdl_w; + dh = (double) sdl_h; + temp = ((double) *w); + temp2 = ((double) *h); + dx = (dw / 2.0) - ((dh * temp) / (temp2 * 2.0)); + dy = 0.0; + if (dx < 0.0) { + dx = 0.0; + dy = (dw / 2.0) - ((dh * temp2) / (temp * 2.0)); + } + dw -= (dx * 2.0); + dh -= (dy * 2.0); + *w = (int) dw; + *h = (int) dh; + *x = (int) dx; + *y = (int) dy; + break; + case FULLSCR_SCALE_INT: + dw = (double) sdl_w; + dh = (double) sdl_h; + temp = ((double) *w); + temp2 = ((double) *h); + ratio_w = dw / ((double) *w); + ratio_h = dh / ((double) *h); + if (ratio_h < ratio_w) + ratio_w = ratio_h; + dx = (dw / 2.0) - ((temp * ratio_w) / 2.0); + dy = (dh / 2.0) - ((temp2 * ratio_h) / 2.0); + dw -= (dx * 2.0); + dh -= (dy * 2.0); + *w = (int) dw; + *h = (int) dh; + *x = (int) dx; + *y = (int) dy; + break; + case FULLSCR_SCALE_KEEPRATIO: + dw = (double) sdl_w; + dh = (double) sdl_h; + hsr = dw / dh; + gsr = ((double) *w) / ((double) *h); + if (gsr <= hsr) { + temp = dh * gsr; + dx = (dw - temp) / 2.0; + dw = temp; + *w = (int) dw; + *h = (int) dh; + *x = (int) dx; + *y = 0; + } else { + temp = dw / gsr; + dy = (dh - temp) / 2.0; + dh = temp; + *w = (int) dw; + *h = (int) dh; + *x = 0; + *y = (int) dy; + } + break; + } +} + + +static void +sdl_blit(int x, int y, int y1, int y2, int w, int h) +{ + SDL_Rect r_src; + void *pixeldata; + int pitch; + int yy, ret; + + if (y1 == y2) { + video_blit_complete(); + return; + } + + if (buffer32 == NULL) { + video_blit_complete(); + return; + } + + /* + * TODO: + * SDL_UpdateTexture() might be better here, as it is + * (reportedly) slightly faster. + */ + sdl_LockTexture(sdl_tex, 0, &pixeldata, &pitch); + + for (yy = y1; yy < y2; yy++) { + if ((y + yy) >= 0 && (y + yy) < buffer32->h) { + if (video_grayscale || invert_display) + video_transform_copy((uint32_t *) &(((uint8_t *)pixeldata)[yy * pitch]), &(((uint32_t *)buffer32->line[y + yy])[x]), w); + else + memcpy((uint32_t *) &(((uint8_t *)pixeldata)[yy * pitch]), &(((uint32_t *)buffer32->line[y + yy])[x]), w * 4); + } + } + + video_blit_complete(); + + sdl_UnlockTexture(sdl_tex); + + if (sdl_fs) { + pclog("sdl_blit(%i, %i, %i, %i, %i, %i) (%i, %i)\n", x, y, y1, y2, w, h, unscaled_size_x, efscrnsz_y); + if (w == unscaled_size_x) + sdl_resize(w, h); + pclog("(%08X, %08X, %08X)\n", sdl_win, sdl_render, sdl_tex); + } + + r_src.x = 0; + r_src.y = 0; + r_src.w = w; + r_src.h = h; + + ret = sdl_RenderCopy(sdl_render, sdl_tex, &r_src, 0); + if (ret) + sdl_log("SDL: unable to copy texture to renderer (%s)\n", sdl_GetError()); + + sdl_RenderPresent(sdl_render); +} + + +void +sdl_close(void) +{ + /* Unregister our renderer! */ + video_setblit(NULL); + + if (sdl_tex != NULL) { + sdl_DestroyTexture(sdl_tex); + sdl_tex = NULL; + } + + if (sdl_render != NULL) { + sdl_DestroyRenderer(sdl_render); + sdl_render = NULL; + } + + if (sdl_win != NULL) { + sdl_DestroyWindow(sdl_win); + sdl_win = NULL; + } + + if (sdl_hwnd != NULL) { + plat_set_input(hwndMain); + + ShowWindow(hwndRender, TRUE); + + SetFocus(hwndMain); + + DestroyWindow(sdl_hwnd); + sdl_hwnd = NULL; + } + + if (sdl_parent_hwnd != NULL) { + DestroyWindow(sdl_parent_hwnd); + sdl_parent_hwnd = NULL; + } + + /* Quit and unload the DLL if possible. */ + if (sdl_handle != NULL) { + sdl_Quit(); + + dynld_close(sdl_handle); + sdl_handle = NULL; + } +} + + +static int old_capture = 0; + + +static int +sdl_init_common(int fs) +{ + wchar_t temp[128]; + SDL_version ver; + int w, h, x, y; + RECT rect; + + sdl_log("SDL: init (fs=%d)\n", fs); + + cgapal_rebuild(); + + /* Try loading the DLL. */ + sdl_handle = dynld_module(PATH_SDL_DLL, sdl_imports); + if (sdl_handle == NULL) { + sdl_log("SDL: unable to load '%s', SDL not available.\n", PATH_SDL_DLL); + return(0); + } + + /* Get and log the version of the DLL we are using. */ + sdl_GetVersion(&ver); + sdl_log("SDL: version %d.%d.%d\n", ver.major, ver.minor, ver.patch); + + /* Initialize the SDL system. */ + if (sdl_Init(SDL_INIT_VIDEO) < 0) { + sdl_log("SDL: initialization failed (%s)\n", sdl_GetError()); + return(0); + } + + if (fs) { + /* Get the size of the (current) desktop. */ + sdl_w = GetSystemMetrics(SM_CXSCREEN); + sdl_h = GetSystemMetrics(SM_CYSCREEN); + + /* Create the desktop-covering window. */ + _swprintf(temp, L"%s v%s", EMU_NAME_W, EMU_VERSION_W); + sdl_parent_hwnd = CreateWindow(SUB_CLASS_NAME, + temp, + WS_POPUP, + 0, 0, sdl_w, sdl_h, + HWND_DESKTOP, + NULL, + hinstance, + NULL); + + SetWindowPos(sdl_parent_hwnd, HWND_TOPMOST, + 0, 0, sdl_w, sdl_h, SWP_SHOWWINDOW); + + /* Create the actual rendering window. */ + _swprintf(temp, L"%s v%s", EMU_NAME_W, EMU_VERSION_W); + sdl_hwnd = CreateWindow(SUB_CLASS_NAME, + temp, + WS_POPUP, + 0, 0, sdl_w, sdl_h, + sdl_parent_hwnd, + NULL, + hinstance, + NULL); + sdl_log("SDL: FS %dx%d window at %08lx\n", sdl_w, sdl_h, sdl_hwnd); + + /* Redirect RawInput to this new window. */ + plat_set_input(sdl_hwnd); + + SetFocus(sdl_hwnd); + + /* Show the window, make it topmost, and give it focus. */ + w = unscaled_size_x; + h = efscrnsz_y; + sdl_stretch(&w, &h, &x, &y); + SetWindowPos(sdl_hwnd, sdl_parent_hwnd, + x, y, w, h, SWP_SHOWWINDOW); + + /* Now create the SDL window from that. */ + sdl_win = sdl_CreateWindowFrom((void *)sdl_hwnd); + + old_capture = mouse_capture; + + GetWindowRect(sdl_hwnd, &rect); + + ClipCursor(&rect); + + mouse_capture = 1; + } else { + /* Create the SDL window from the render window. */ + sdl_win = sdl_CreateWindowFrom((void *)hwndRender); + + mouse_capture = old_capture; + + if (mouse_capture) { + GetWindowRect(hwndRender, &rect); + + ClipCursor(&rect); + } + } + if (sdl_win == NULL) { + sdl_log("SDL: unable to CreateWindowFrom (%s)\n", sdl_GetError()); + sdl_close(); + return(0); + } + + /* + * TODO: + * SDL_RENDERER_SOFTWARE, because SDL tries to do funky stuff + * otherwise (it turns off Win7 Aero and it looks like it's + * trying to switch to fullscreen even though the window is + * not a fullscreen window?) + */ + sdl_render = sdl_CreateRenderer(sdl_win, -1, SDL_RENDERER_SOFTWARE); + if (sdl_render == NULL) { + sdl_log("SDL: unable to create renderer (%s)\n", sdl_GetError()); + sdl_close(); + return(0); + } + + /* + * TODO: + * Actually the source is (apparently) XRGB8888, but the alpha + * channel seems to be set to 255 everywhere, so ARGB8888 works + * just as well. + */ + sdl_tex = sdl_CreateTexture(sdl_render, SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_STREAMING, 2048, 2048); + if (sdl_tex == NULL) { + sdl_log("SDL: unable to create texture (%s)\n", sdl_GetError()); + sdl_close(); + return(0); + } + + /* Make sure we get a clean exit. */ + atexit(sdl_close); + + /* Register our renderer! */ + video_setblit(sdl_blit); + + sdl_fs = fs; + + return(1); +} + + +int +sdl_init(HWND h) +{ + return sdl_init_common(0); +} + + +int +sdl_init_fs(HWND h) +{ + return sdl_init_common(1); +} + + +void +sdl_take_screenshot(const wchar_t *fn) +{ + int i, res, x, y, width = 0, height = 0; + unsigned char* rgba = NULL; + png_bytep *b_rgb = NULL; + FILE *fp = NULL; + + sdl_GetWindowSize(sdl_win, &width, &height); + + /* create file */ + fp = plat_fopen((wchar_t *) fn, (wchar_t *) L"wb"); + if (!fp) { + sdl_log("[sdl_take_screenshot] File %ls could not be opened for writing", fn); + return; + } + + /* initialize stuff */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + + if (!png_ptr) { + sdl_log("[sdl_take_screenshot] png_create_write_struct failed"); + fclose(fp); + return; + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + sdl_log("[sdl_take_screenshot] png_create_info_struct failed"); + fclose(fp); + return; + } + + png_init_io(png_ptr, fp); + + png_set_IHDR(png_ptr, info_ptr, width, height, + 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + if ((rgba = (unsigned char *)malloc(width * height * 4)) == NULL) { + sdl_log("[sdl_take_screenshot] Unable to Allocate RGBA Bitmap Memory"); + fclose(fp); + return; + } + + res = sdl_RenderReadPixels(sdl_render, NULL, SDL_PIXELFORMAT_ABGR8888, rgba, width * 4); + if (res) { + sdl_log("[sdl_take_screenshot] Error reading render pixels\n"); + fclose(fp); + return; + } + + if ((b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * height)) == NULL) { + sdl_log("[sdl_take_screenshot] Unable to Allocate RGB Bitmap Memory"); + free(rgba); + fclose(fp); + return; + } + + for (y = 0; y < height; ++y) { + b_rgb[y] = (png_byte *) malloc(png_get_rowbytes(png_ptr, info_ptr)); + for (x = 0; x < width; ++x) { + b_rgb[y][(x) * 3 + 0] = rgba[(y * width + x) * 4 + 0]; + b_rgb[y][(x) * 3 + 1] = rgba[(y * width + x) * 4 + 1]; + b_rgb[y][(x) * 3 + 2] = rgba[(y * width + x) * 4 + 2]; + } + } + + png_write_info(png_ptr, info_ptr); + + png_write_image(png_ptr, b_rgb); + + png_write_end(png_ptr, NULL); + + /* cleanup heap allocation */ + for (i = 0; i < height; i++) + if (b_rgb[i]) free(b_rgb[i]); + + if (b_rgb) free(b_rgb); + + if (rgba) free(rgba); + + if (fp) fclose(fp); +} + + +int +sdl_pause(void) +{ + return(0); +} + + +void +sdl_resize(int x, int y) +{ + int ww, wh, wx, wy; + + if ((x == cur_w) && (y == cur_h)) + return; + + pclog("sdl_resize(%i, %i)\n", x, y); + ww = x; + wh = y; + sdl_stretch(&ww, &wh, &wx, &wy); + + MoveWindow(sdl_hwnd, wx, wy, ww, wh, TRUE); + + cur_w = x; + cur_h = y; +} diff --git a/src/win/win_sdl.h b/src/win/win_sdl.h new file mode 100644 index 000000000..23ba344be --- /dev/null +++ b/src/win/win_sdl.h @@ -0,0 +1,62 @@ +/* + * 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. + * + * Definitions for the libSDL2 rendering module. + * + * Version: @(#)win_sdl.h 1.0.0 2018/05/26 + * + * Authors: Fred N. van Kempen, + * Michael Drüing, + * + * Copyright 2018 Fred N. van Kempen. + * Copyright 2018 Michael Drüing. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef WIN_SDL_H +# define WIN_SDL_H + + +extern void sdl_close(void); +extern int sdl_init(HWND h); +extern int sdl_init_fs(HWND h); +extern int sdl_pause(void); +extern void sdl_resize(int x, int y); + +extern void sdl_take_screenshot(const wchar_t *fn); + + +#endif /*WIN_SDL_H*/ diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 6544035b6..16d8ea151 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -8,7 +8,7 @@ * * Windows 86Box Settings dialog handler. * - * Version: @(#)win_settings.c 1.0.46 2018/03/19 + * Version: @(#)win_settings.c 1.0.51 2018/05/25 * * Author: Miran Grca, * @@ -21,8 +21,8 @@ #undef BITMAP #include #include -#include #include +#include #include #include #include "../86box.h" @@ -36,13 +36,13 @@ #include "../game/gameport.h" #include "../lpt.h" #include "../mouse.h" +#include "../scsi/scsi.h" #include "../cdrom/cdrom.h" #include "../disk/hdd.h" #include "../disk/hdc.h" #include "../disk/hdc_ide.h" #include "../disk/zip.h" #include "../floppy/fdd.h" -#include "../scsi/scsi.h" #include "../network/network.h" #include "../sound/sound.h" #include "../sound/midi.h" @@ -56,20 +56,36 @@ #include "win.h" +#define SETTINGS_PAGE_MACHINE 0 +#define SETTINGS_PAGE_VIDEO 1 +#define SETTINGS_PAGE_INPUT 2 +#define SETTINGS_PAGE_SOUND 3 +#define SETTINGS_PAGE_NETWORK 4 +#define SETTINGS_PAGE_PORTS 5 +#define SETTINGS_PAGE_PERIPHERALS 6 +#define SETTINGS_PAGE_HARD_DISKS 7 +#define SETTINGS_PAGE_FLOPPY_DRIVES 8 +#define SETTINGS_PAGE_OTHER_REMOVABLE_DEVICES 9 + +/* Icon, Bus, File, C, H, S, Size */ +#define C_COLUMNS_HARD_DISKS 6 + + /* Machine category */ -static int temp_machine, temp_cpu_m, temp_cpu, temp_wait_states, temp_mem_size, temp_fpu, temp_sync; +static int temp_machine, temp_cpu_m, temp_cpu, temp_wait_states, temp_fpu, temp_sync; +static uint32_t temp_mem_size; #ifdef USE_DYNAREC static int temp_dynarec; #endif /* Video category */ -static int temp_gfxcard, temp_video_speed, temp_voodoo; +static int temp_gfxcard, temp_voodoo; /* Input devices category */ static int temp_mouse, temp_joystick; /* Sound category */ -static int temp_sound_card, temp_midi_device, temp_mpu401, temp_SSI2001, temp_GAMEBLASTER, temp_GUS, temp_opl3_type; +static int temp_sound_card, temp_midi_device, temp_mpu401, temp_SSI2001, temp_GAMEBLASTER, temp_GUS, temp_opl_type; static int temp_float; /* Network category */ @@ -81,9 +97,9 @@ static char temp_lpt_device_names[3][16]; static int temp_serial[2], temp_lpt; /* Other peripherals category */ -static int temp_scsi_card, temp_ide_ter, temp_ide_ter_irq, temp_ide_qua, temp_ide_qua_irq; -static char temp_hdc_name[16]; -static char *hdc_names[16]; +static int temp_scsi_card, temp_ide_ter, temp_ide_qua; +static char temp_hdc_name[32]; +static char *hdc_names[32]; static int temp_bugger; static uint8_t temp_deviceconfig; @@ -102,18 +118,54 @@ static zip_drive_t temp_zip_drives[ZIP_NUM]; static HWND hwndParentDialog, hwndChildDialog; -static int displayed_category = 0; +static uint32_t displayed_category = 0; extern int is486; static int romstolist[ROM_MAX], listtomachine[ROM_MAX], romstomachine[ROM_MAX], machinetolist[ROM_MAX]; -static int settings_sound_to_list[20], settings_list_to_sound[20]; +static int settings_device_to_list[20], settings_list_to_device[20]; static int settings_midi_to_list[20], settings_list_to_midi[20]; -static int settings_mouse_to_list[20], settings_list_to_mouse[20]; -static int settings_scsi_to_list[20], settings_list_to_scsi[20]; -static int settings_network_to_list[20], settings_list_to_network[20]; -static uint64_t mfm_tracking, esdi_tracking, xtide_tracking, ide_tracking, scsi_tracking[16]; +static int max_spt = 63, max_hpc = 255, max_tracks = 266305; +static uint64_t mfm_tracking, esdi_tracking, xta_tracking, ide_tracking, scsi_tracking[2]; +static uint64_t size; +static int hd_listview_items, hdc_id_to_listview_index[HDD_NUM]; +static int no_update = 0, existing = 0, chs_enabled = 0; +static int lv1_current_sel, lv2_current_sel; +static int hard_disk_added = 0, next_free_id = 0, selection = 127; +static int spt, hpc, tracks, ignore_change = 0; +static hard_disk_t new_hdd, *hdd_ptr; + +static wchar_t hd_file_name[512]; + + +static BOOL +image_list_init(HWND hwndList, const uint8_t *icon_ids) +{ + HICON hiconItem; + HIMAGELIST hSmall; + + int i = 0; + + hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + ILC_MASK | ILC_COLOR32, 1, 1); + + while(1) { + if (icon_ids[i] == 0) + break; + + hiconItem = LoadIcon(hinstance, (LPCWSTR) ((uint32_t) icon_ids[i])); + ImageList_AddIcon(hSmall, hiconItem); + DestroyIcon(hiconItem); + + i++; + } + + ListView_SetImageList(hwndList, hSmall, LVSIL_SMALL); + + return TRUE; +} /* Show a MessageBox dialog. This is nasty, I know. --FvK */ @@ -135,481 +187,420 @@ settings_msgbox(int type, void *arg) /* This does the initial read of global variables into the temporary ones. */ -static void win_settings_init(void) +static void +win_settings_init(void) { - int i = 0; + int i = 0; - /* Machine category */ - temp_machine = machine; - temp_cpu_m = cpu_manufacturer; - temp_wait_states = cpu_waitstates; - temp_cpu = cpu; - temp_mem_size = mem_size; + /* Machine category */ + temp_machine = machine; + temp_cpu_m = cpu_manufacturer; + temp_wait_states = cpu_waitstates; + temp_cpu = cpu; + temp_mem_size = mem_size; #ifdef USE_DYNAREC - temp_dynarec = cpu_use_dynarec; + temp_dynarec = cpu_use_dynarec; #endif - temp_fpu = enable_external_fpu; - temp_sync = enable_sync; + temp_fpu = enable_external_fpu; + temp_sync = enable_sync; - /* Video category */ - temp_gfxcard = gfxcard; - temp_video_speed = video_speed; - temp_voodoo = voodoo_enabled; + /* Video category */ + temp_gfxcard = gfxcard; + temp_voodoo = voodoo_enabled; - /* Input devices category */ - temp_mouse = mouse_type; - temp_joystick = joystick_type; + /* Input devices category */ + temp_mouse = mouse_type; + temp_joystick = joystick_type; - /* Sound category */ - temp_sound_card = sound_card_current; - temp_midi_device = midi_device_current; - temp_mpu401 = mpu401_standalone_enable; - temp_SSI2001 = SSI2001; - temp_GAMEBLASTER = GAMEBLASTER; - temp_GUS = GUS; - temp_opl3_type = opl3_type; - temp_float = sound_is_float; + /* Sound category */ + temp_sound_card = sound_card_current; + temp_midi_device = midi_device_current; + temp_mpu401 = mpu401_standalone_enable; + temp_SSI2001 = SSI2001; + temp_GAMEBLASTER = GAMEBLASTER; + temp_GUS = GUS; + temp_opl_type = opl_type; + temp_float = sound_is_float; - /* Network category */ - temp_net_type = network_type; - memset(temp_pcap_dev, 0, sizeof(temp_pcap_dev)); - strcpy(temp_pcap_dev, network_host); - temp_net_card = network_card; + /* Network category */ + temp_net_type = network_type; + memset(temp_pcap_dev, 0, sizeof(temp_pcap_dev)); + strcpy(temp_pcap_dev, network_host); + temp_net_card = network_card; - /* Ports category */ - for (i = 0; i < 3; i++) - strncpy(temp_lpt_device_names[i], lpt_device_names[i], sizeof(temp_lpt_device_names[i]) - 1); - temp_serial[0] = serial_enabled[0]; - temp_serial[1] = serial_enabled[1]; - temp_lpt = lpt_enabled; + /* Ports category */ + for (i = 0; i < 3; i++) + strncpy(temp_lpt_device_names[i], lpt_device_names[i], sizeof(temp_lpt_device_names[i]) - 1); + temp_serial[0] = serial_enabled[0]; + temp_serial[1] = serial_enabled[1]; + temp_lpt = lpt_enabled; - /* Other peripherals category */ - temp_scsi_card = scsi_card_current; - strncpy(temp_hdc_name, hdc_name, sizeof(temp_hdc_name) - 1); - temp_ide_ter = ide_enable[2]; - temp_ide_ter_irq = ide_irq[2]; - temp_ide_qua = ide_enable[3]; - temp_ide_qua_irq = ide_irq[3]; - temp_bugger = bugger_enabled; + /* Other peripherals category */ + temp_scsi_card = scsi_card_current; + strncpy(temp_hdc_name, hdc_name, sizeof(temp_hdc_name) - 1); + temp_ide_ter = ide_ter_enabled; + temp_ide_qua = ide_qua_enabled; + temp_bugger = bugger_enabled; - mfm_tracking = xtide_tracking = esdi_tracking = ide_tracking = 0; - for (i = 0; i < 16; i++) - scsi_tracking[i] = 0; + mfm_tracking = xta_tracking = esdi_tracking = ide_tracking = 0; + for (i = 0; i < 2; i++) + scsi_tracking[i] = 0; - /* Hard disks category */ - memcpy(temp_hdd, hdd, HDD_NUM * sizeof(hard_disk_t)); - for (i = 0; i < HDD_NUM; i++) - { - if (hdd[i].bus == HDD_BUS_MFM) - mfm_tracking |= (1 << (hdd[i].mfm_channel << 3)); - else if (hdd[i].bus == HDD_BUS_XTIDE) - xtide_tracking |= (1 << (hdd[i].xtide_channel << 3)); - else if (hdd[i].bus == HDD_BUS_ESDI) - esdi_tracking |= (1 << (hdd[i].esdi_channel << 3)); - else if (hdd[i].bus == HDD_BUS_IDE_PIO_ONLY) - ide_tracking |= (1 << (hdd[i].ide_channel << 3)); - else if (hdd[i].bus == HDD_BUS_IDE_PIO_AND_DMA) - ide_tracking |= (1 << (hdd[i].ide_channel << 3)); - else if (hdd[i].bus == HDD_BUS_SCSI) - scsi_tracking[hdd[i].scsi_id] |= (1 << (hdd[i].scsi_lun << 3)); - else if (hdd[i].bus == HDD_BUS_SCSI_REMOVABLE) - scsi_tracking[hdd[i].scsi_id] |= (1 << (hdd[i].scsi_lun << 3)); - } + /* Hard disks category */ + memcpy(temp_hdd, hdd, HDD_NUM * sizeof(hard_disk_t)); + for (i = 0; i < HDD_NUM; i++) { + if (hdd[i].bus == HDD_BUS_MFM) + mfm_tracking |= (1 << (hdd[i].mfm_channel << 3)); + else if (hdd[i].bus == HDD_BUS_XTA) + xta_tracking |= (1 << (hdd[i].xta_channel << 3)); + else if (hdd[i].bus == HDD_BUS_ESDI) + esdi_tracking |= (1 << (hdd[i].esdi_channel << 3)); + else if (hdd[i].bus == HDD_BUS_IDE) + ide_tracking |= (1 << (hdd[i].ide_channel << 3)); + else if (hdd[i].bus == HDD_BUS_SCSI) + scsi_tracking[hdd[i].scsi_id >> 3] |= (1 << ((hdd[i].scsi_id & 0x07) << 3)); + } - /* Floppy drives category */ - for (i = 0; i < FDD_NUM; i++) - { - temp_fdd_types[i] = fdd_get_type(i); - temp_fdd_turbo[i] = fdd_get_turbo(i); - temp_fdd_check_bpb[i] = fdd_get_check_bpb(i); - } + /* Floppy drives category */ + for (i = 0; i < FDD_NUM; i++) { + temp_fdd_types[i] = fdd_get_type(i); + temp_fdd_turbo[i] = fdd_get_turbo(i); + temp_fdd_check_bpb[i] = fdd_get_check_bpb(i); + } - /* Other removable devices category */ - memcpy(temp_cdrom_drives, cdrom_drives, CDROM_NUM * sizeof(cdrom_drive_t)); - for (i = 0; i < CDROM_NUM; i++) - { - if (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) - ide_tracking |= (2 << (cdrom_drives[i].ide_channel << 3)); - else if (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA) - ide_tracking |= (2 << (cdrom_drives[i].ide_channel << 3)); - else if (cdrom_drives[i].bus_type == CDROM_BUS_SCSI) - scsi_tracking[cdrom_drives[i].scsi_device_id] |= (2 << (cdrom_drives[i].scsi_device_lun << 3)); - } - memcpy(temp_zip_drives, zip_drives, ZIP_NUM * sizeof(zip_drive_t)); - for (i = 0; i < ZIP_NUM; i++) - { - if (zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) - ide_tracking |= (4 << (zip_drives[i].ide_channel << 3)); - else if (zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA) - ide_tracking |= (4 << (zip_drives[i].ide_channel << 3)); - else if (zip_drives[i].bus_type == ZIP_BUS_SCSI) - scsi_tracking[zip_drives[i].scsi_device_id] |= (4 << (zip_drives[i].scsi_device_lun << 3)); - } + /* Other removable devices category */ + memcpy(temp_cdrom_drives, cdrom_drives, CDROM_NUM * sizeof(cdrom_drive_t)); + for (i = 0; i < CDROM_NUM; i++) { + if (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI) + ide_tracking |= (2 << (cdrom_drives[i].ide_channel << 3)); + else if (cdrom_drives[i].bus_type == CDROM_BUS_SCSI) + scsi_tracking[cdrom_drives[i].scsi_device_id >> 3] |= (1 << ((cdrom_drives[i].scsi_device_id & 0x07) << 3)); + } + memcpy(temp_zip_drives, zip_drives, ZIP_NUM * sizeof(zip_drive_t)); + for (i = 0; i < ZIP_NUM; i++) { + if (zip_drives[i].bus_type == ZIP_BUS_ATAPI) + ide_tracking |= (4 << (zip_drives[i].ide_channel << 3)); + else if (zip_drives[i].bus_type == ZIP_BUS_SCSI) + scsi_tracking[zip_drives[i].scsi_device_id >> 3] |= (1 << ((zip_drives[i].scsi_device_id & 0x07) << 3)); + } - temp_deviceconfig = 0; + temp_deviceconfig = 0; } /* This returns 1 if any variable has changed, 0 if not. */ -static int win_settings_changed(void) +static int +win_settings_changed(void) { - int i = 0; - int j = 0; + int i = 0; + int j = 0; - /* Machine category */ - i = i || (machine != temp_machine); - i = i || (cpu_manufacturer != temp_cpu_m); - i = i || (cpu_waitstates != temp_wait_states); - i = i || (cpu != temp_cpu); - i = i || (mem_size != temp_mem_size); + /* Machine category */ + i = i || (machine != temp_machine); + i = i || (cpu_manufacturer != temp_cpu_m); + i = i || (cpu_waitstates != temp_wait_states); + i = i || (cpu != temp_cpu); + i = i || (mem_size != temp_mem_size); #ifdef USE_DYNAREC - i = i || (temp_dynarec != cpu_use_dynarec); + i = i || (temp_dynarec != cpu_use_dynarec); #endif - i = i || (temp_fpu != enable_external_fpu); - i = i || (temp_sync != enable_sync); + i = i || (temp_fpu != enable_external_fpu); + i = i || (temp_sync != enable_sync); - /* Video category */ - i = i || (gfxcard != temp_gfxcard); - i = i || (video_speed != temp_video_speed); - i = i || (voodoo_enabled != temp_voodoo); + /* Video category */ + i = i || (gfxcard != temp_gfxcard); + i = i || (voodoo_enabled != temp_voodoo); - /* Input devices category */ - i = i || (mouse_type != temp_mouse); - i = i || (joystick_type != temp_joystick); + /* Input devices category */ + i = i || (mouse_type != temp_mouse); + i = i || (joystick_type != temp_joystick); - /* Sound category */ - i = i || (sound_card_current != temp_sound_card); - i = i || (midi_device_current != temp_midi_device); - i = i || (mpu401_standalone_enable != temp_mpu401); - i = i || (SSI2001 != temp_SSI2001); - i = i || (GAMEBLASTER != temp_GAMEBLASTER); - i = i || (GUS != temp_GUS); - i = i || (opl3_type != temp_opl3_type); - i = i || (sound_is_float != temp_float); + /* Sound category */ + i = i || (sound_card_current != temp_sound_card); + i = i || (midi_device_current != temp_midi_device); + i = i || (mpu401_standalone_enable != temp_mpu401); + i = i || (SSI2001 != temp_SSI2001); + i = i || (GAMEBLASTER != temp_GAMEBLASTER); + i = i || (GUS != temp_GUS); + i = i || (opl_type != temp_opl_type); + i = i || (sound_is_float != temp_float); - /* Network category */ - i = i || (network_type != temp_net_type); - i = i || strcmp(temp_pcap_dev, network_host); - i = i || (network_card != temp_net_card); + /* Network category */ + i = i || (network_type != temp_net_type); + i = i || strcmp(temp_pcap_dev, network_host); + i = i || (network_card != temp_net_card); - /* Ports category */ - for (j = 0; j < 3; j++) - i = i || strncmp(temp_lpt_device_names[j], lpt_device_names[j], sizeof(temp_lpt_device_names[j]) - 1); - i = i || (temp_serial[0] != serial_enabled[0]); - i = i || (temp_serial[1] != serial_enabled[1]); - i = i || (temp_lpt != lpt_enabled); + /* Ports category */ + for (j = 0; j < 3; j++) + i = i || strncmp(temp_lpt_device_names[j], lpt_device_names[j], sizeof(temp_lpt_device_names[j]) - 1); + i = i || (temp_serial[0] != serial_enabled[0]); + i = i || (temp_serial[1] != serial_enabled[1]); + i = i || (temp_lpt != lpt_enabled); - /* Peripherals category */ - i = i || (scsi_card_current != temp_scsi_card); - i = i || strncmp(temp_hdc_name, hdc_name, sizeof(temp_hdc_name) - 1); - i = i || (temp_ide_ter != ide_enable[2]); - i = i || (temp_ide_ter_irq != ide_irq[2]); - i = i || (temp_ide_qua != ide_enable[3]); - i = i || (temp_ide_qua_irq != ide_irq[3]); - i = i || (temp_bugger != bugger_enabled); + /* Peripherals category */ + i = i || (scsi_card_current != temp_scsi_card); + i = i || strncmp(temp_hdc_name, hdc_name, sizeof(temp_hdc_name) - 1); + i = i || (temp_ide_ter != ide_ter_enabled); + i = i || (temp_ide_qua != ide_qua_enabled); + i = i || (temp_bugger != bugger_enabled); - /* Hard disks category */ - i = i || memcmp(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t)); + /* Hard disks category */ + i = i || memcmp(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t)); - /* Floppy drives category */ - for (j = 0; j < FDD_NUM; j++) - { - i = i || (temp_fdd_types[j] != fdd_get_type(j)); - i = i || (temp_fdd_turbo[j] != fdd_get_turbo(j)); - i = i || (temp_fdd_check_bpb[j] != fdd_get_check_bpb(j)); - } + /* Floppy drives category */ + for (j = 0; j < FDD_NUM; j++) { + i = i || (temp_fdd_types[j] != fdd_get_type(j)); + i = i || (temp_fdd_turbo[j] != fdd_get_turbo(j)); + i = i || (temp_fdd_check_bpb[j] != fdd_get_check_bpb(j)); + } - /* Other removable devices category */ - i = i || memcmp(cdrom_drives, temp_cdrom_drives, CDROM_NUM * sizeof(cdrom_drive_t)); - i = i || memcmp(zip_drives, temp_zip_drives, ZIP_NUM * sizeof(zip_drive_t)); + /* Other removable devices category */ + i = i || memcmp(cdrom_drives, temp_cdrom_drives, CDROM_NUM * sizeof(cdrom_drive_t)); + i = i || memcmp(zip_drives, temp_zip_drives, ZIP_NUM * sizeof(zip_drive_t)); - i = i || !!temp_deviceconfig; + i = i || !!temp_deviceconfig; - return i; + return i; } -static int settings_msgbox_reset(void) +static int +settings_msgbox_reset(void) { - int i = 0; - int changed = 0; + int changed, i = 0; - changed = win_settings_changed(); + changed = win_settings_changed(); - if (changed) - { - i = settings_msgbox(MBX_QUESTION, (wchar_t *)IDS_2051); + if (changed) { + i = settings_msgbox(MBX_QUESTION, (wchar_t *)IDS_2051); - if (i == 1) return(1); /* no */ + if (i == 1) return(1); /* no */ - if (i < 0) return(0); /* cancel */ + if (i < 0) return(0); /* cancel */ - return(2); /* yes */ - } else { - return(1); - } + return(2); /* yes */ + } else + return(1); } /* This saves the settings back to the global variables. */ -static void win_settings_save(void) +static void +win_settings_save(void) { - int i = 0; + int i = 0; - pc_reset_hard_close(); + pc_reset_hard_close(); - /* Machine category */ - machine = temp_machine; - romset = machine_getromset(); - cpu_manufacturer = temp_cpu_m; - cpu_waitstates = temp_wait_states; - cpu = temp_cpu; - mem_size = temp_mem_size; + /* Machine category */ + machine = temp_machine; + romset = machine_getromset(); + cpu_manufacturer = temp_cpu_m; + cpu_waitstates = temp_wait_states; + cpu = temp_cpu; + mem_size = temp_mem_size; #ifdef USE_DYNAREC - cpu_use_dynarec = temp_dynarec; + cpu_use_dynarec = temp_dynarec; #endif - enable_external_fpu = temp_fpu; - enable_sync = temp_sync; + enable_external_fpu = temp_fpu; + enable_sync = temp_sync; - /* Video category */ - gfxcard = temp_gfxcard; - video_speed = temp_video_speed; - voodoo_enabled = temp_voodoo; + /* Video category */ + gfxcard = temp_gfxcard; + voodoo_enabled = temp_voodoo; - /* Input devices category */ - mouse_type = temp_mouse; - joystick_type = temp_joystick; + /* Input devices category */ + mouse_type = temp_mouse; + joystick_type = temp_joystick; - /* Sound category */ - sound_card_current = temp_sound_card; - midi_device_current = temp_midi_device; - mpu401_standalone_enable = temp_mpu401; - SSI2001 = temp_SSI2001; - GAMEBLASTER = temp_GAMEBLASTER; - GUS = temp_GUS; - opl3_type = temp_opl3_type; - sound_is_float = temp_float; + /* Sound category */ + sound_card_current = temp_sound_card; + midi_device_current = temp_midi_device; + mpu401_standalone_enable = temp_mpu401; + SSI2001 = temp_SSI2001; + GAMEBLASTER = temp_GAMEBLASTER; + GUS = temp_GUS; + opl_type = temp_opl_type; + sound_is_float = temp_float; - /* Network category */ - network_type = temp_net_type; - memset(network_host, '\0', sizeof(network_host)); - strcpy(network_host, temp_pcap_dev); - network_card = temp_net_card; + /* Network category */ + network_type = temp_net_type; + memset(network_host, '\0', sizeof(network_host)); + strcpy(network_host, temp_pcap_dev); + network_card = temp_net_card; - /* Ports category */ - for (i = 0; i < 3; i++) - strncpy(lpt_device_names[i], temp_lpt_device_names[i], sizeof(temp_lpt_device_names[i]) - 1); - serial_enabled[0] = temp_serial[0]; - serial_enabled[1] = temp_serial[1]; - lpt_enabled = temp_lpt; + /* Ports category */ + for (i = 0; i < 3; i++) + strncpy(lpt_device_names[i], temp_lpt_device_names[i], sizeof(temp_lpt_device_names[i]) - 1); + serial_enabled[0] = temp_serial[0]; + serial_enabled[1] = temp_serial[1]; + lpt_enabled = temp_lpt; - /* Peripherals category */ - scsi_card_current = temp_scsi_card; - if (hdc_name) { - free(hdc_name); - hdc_name = NULL; - } - hdc_name = (char *) malloc(sizeof(temp_hdc_name)); - strncpy(hdc_name, temp_hdc_name, sizeof(temp_hdc_name) - 1); - hdc_init(hdc_name); - ide_enable[2] = temp_ide_ter; - ide_irq[2] = temp_ide_ter_irq; - ide_enable[3] = temp_ide_qua; - ide_irq[3] = temp_ide_qua_irq; - bugger_enabled = temp_bugger; + /* Peripherals category */ + scsi_card_current = temp_scsi_card; + if (hdc_name) { + free(hdc_name); + hdc_name = NULL; + } + hdc_name = (char *) malloc(sizeof(temp_hdc_name)); + strncpy(hdc_name, temp_hdc_name, sizeof(temp_hdc_name) - 1); + hdc_init(hdc_name); + ide_ter_enabled = temp_ide_ter; + ide_qua_enabled = temp_ide_qua; + bugger_enabled = temp_bugger; - /* Hard disks category */ - memcpy(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t)); + /* Hard disks category */ + memcpy(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t)); - /* Floppy drives category */ - for (i = 0; i < FDD_NUM; i++) - { - fdd_set_type(i, temp_fdd_types[i]); - fdd_set_turbo(i, temp_fdd_turbo[i]); - fdd_set_check_bpb(i, temp_fdd_check_bpb[i]); - } + /* Floppy drives category */ + for (i = 0; i < FDD_NUM; i++) { + fdd_set_type(i, temp_fdd_types[i]); + fdd_set_turbo(i, temp_fdd_turbo[i]); + fdd_set_check_bpb(i, temp_fdd_check_bpb[i]); + } - /* Removable devices category */ - memcpy(cdrom_drives, temp_cdrom_drives, CDROM_NUM * sizeof(cdrom_drive_t)); - memcpy(zip_drives, temp_zip_drives, ZIP_NUM * sizeof(zip_drive_t)); + /* Removable devices category */ + memcpy(cdrom_drives, temp_cdrom_drives, CDROM_NUM * sizeof(cdrom_drive_t)); + memcpy(zip_drives, temp_zip_drives, ZIP_NUM * sizeof(zip_drive_t)); - /* Mark configuration as changed. */ - config_changed = 1; + /* Mark configuration as changed. */ + config_changed = 1; - pc_reset_hard_init(); + pc_reset_hard_init(); } -static void win_settings_machine_recalc_cpu(HWND hdlg) +static void +win_settings_machine_recalc_cpu(HWND hdlg) { - HWND h; - int temp_romset = 0; + HWND h; + int cpu_type, temp_romset; #ifdef USE_DYNAREC - int cpu_flags; -#endif - int cpu_type; - - temp_romset = machine_getromset_ex(temp_machine); - - h = GetDlgItem(hdlg, IDC_COMBO_WS); - cpu_type = machines[romstomachine[temp_romset]].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type; - if ((cpu_type >= CPU_286) && (cpu_type <= CPU_386DX)) - { - EnableWindow(h, TRUE); - } - else - { - EnableWindow(h, FALSE); - } - -#ifdef USE_DYNAREC - h=GetDlgItem(hdlg, IDC_CHECK_DYNAREC); - cpu_flags = machines[romstomachine[temp_romset]].cpu[temp_cpu_m].cpus[temp_cpu].cpu_flags; - if (!(cpu_flags & CPU_SUPPORTS_DYNAREC) && (cpu_flags & CPU_REQUIRES_DYNAREC)) - { - fatal("Attempting to select a CPU that requires the recompiler and does not support it at the same time\n"); - } - if (!(cpu_flags & CPU_SUPPORTS_DYNAREC) || (cpu_flags & CPU_REQUIRES_DYNAREC)) - { - if (!(cpu_flags & CPU_SUPPORTS_DYNAREC)) - { - temp_dynarec = 0; - } - if (cpu_flags & CPU_REQUIRES_DYNAREC) - { - temp_dynarec = 1; - } - SendMessage(h, BM_SETCHECK, temp_dynarec, 0); - EnableWindow(h, FALSE); - } - else - { - EnableWindow(h, TRUE); - } + int cpu_flags; #endif - h = GetDlgItem(hdlg, IDC_CHECK_FPU); - cpu_type = machines[romstomachine[temp_romset]].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type; - if ((cpu_type < CPU_i486DX) && (cpu_type >= CPU_286)) - { - EnableWindow(h, TRUE); - } - else if (cpu_type < CPU_286) - { - temp_fpu = 0; - EnableWindow(h, FALSE); - } - else - { - temp_fpu = 1; - EnableWindow(h, FALSE); - } - SendMessage(h, BM_SETCHECK, temp_fpu, 0); -} + temp_romset = machine_getromset_ex(temp_machine); - -static void win_settings_machine_recalc_cpu_m(HWND hdlg) -{ - HWND h; - int c = 0; - int temp_romset = 0; - LPTSTR lptsTemp; - char *stransi; - - temp_romset = machine_getromset_ex(temp_machine); - lptsTemp = (LPTSTR) malloc(512); - - h = GetDlgItem(hdlg, IDC_COMBO_CPU); - SendMessage(h, CB_RESETCONTENT, 0, 0); - c = 0; - while (machines[romstomachine[temp_romset]].cpu[temp_cpu_m].cpus[c].cpu_type != -1) - { - stransi = (char *) machines[romstomachine[temp_romset]].cpu[temp_cpu_m].cpus[c].name; - mbstowcs(lptsTemp, stransi, strlen(stransi) + 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)lptsTemp); - c++; - } + h = GetDlgItem(hdlg, IDC_COMBO_WS); + cpu_type = machines[romstomachine[temp_romset]].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type; + if ((cpu_type >= CPU_286) && (cpu_type <= CPU_386DX)) EnableWindow(h, TRUE); - if (temp_cpu >= c) - { - temp_cpu = (c - 1); - } - SendMessage(h, CB_SETCURSEL, temp_cpu, 0); + else + EnableWindow(h, FALSE); - win_settings_machine_recalc_cpu(hdlg); +#ifdef USE_DYNAREC + h=GetDlgItem(hdlg, IDC_CHECK_DYNAREC); + cpu_flags = machines[romstomachine[temp_romset]].cpu[temp_cpu_m].cpus[temp_cpu].cpu_flags; + if (!(cpu_flags & CPU_SUPPORTS_DYNAREC) && (cpu_flags & CPU_REQUIRES_DYNAREC)) + fatal("Attempting to select a CPU that requires the recompiler and does not support it at the same time\n"); + if (!(cpu_flags & CPU_SUPPORTS_DYNAREC) || (cpu_flags & CPU_REQUIRES_DYNAREC)) { + if (!(cpu_flags & CPU_SUPPORTS_DYNAREC)) + temp_dynarec = 0; + if (cpu_flags & CPU_REQUIRES_DYNAREC) + temp_dynarec = 1; + SendMessage(h, BM_SETCHECK, temp_dynarec, 0); + EnableWindow(h, FALSE); + } else + EnableWindow(h, TRUE); +#endif - free(lptsTemp); + h = GetDlgItem(hdlg, IDC_CHECK_FPU); + cpu_type = machines[romstomachine[temp_romset]].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type; + if ((cpu_type < CPU_i486DX) && (cpu_type >= CPU_286)) + EnableWindow(h, TRUE); + else if (cpu_type < CPU_286) { + temp_fpu = 0; + EnableWindow(h, FALSE); + } else { + temp_fpu = 1; + EnableWindow(h, FALSE); + } + SendMessage(h, BM_SETCHECK, temp_fpu, 0); } -static void win_settings_machine_recalc_machine(HWND hdlg) +static void +win_settings_machine_recalc_cpu_m(HWND hdlg) { - HWND h; - int c = 0; - int temp_romset = 0; - LPTSTR lptsTemp; - const char *stransi; - UDACCEL accel; + HWND h; + int c, temp_romset; + LPTSTR lptsTemp; + char *stransi; - temp_romset = machine_getromset_ex(temp_machine); - lptsTemp = (LPTSTR) malloc(512); + temp_romset = machine_getromset_ex(temp_machine); + lptsTemp = (LPTSTR) malloc(512); - h = GetDlgItem(hdlg, IDC_CONFIGURE_MACHINE); - if (machine_getdevice(temp_machine)) - { - EnableWindow(h, TRUE); - } - else - { - EnableWindow(h, FALSE); - } + h = GetDlgItem(hdlg, IDC_COMBO_CPU); + SendMessage(h, CB_RESETCONTENT, 0, 0); + c = 0; + while (machines[romstomachine[temp_romset]].cpu[temp_cpu_m].cpus[c].cpu_type != -1) { + stransi = (char *) machines[romstomachine[temp_romset]].cpu[temp_cpu_m].cpus[c].name; + mbstowcs(lptsTemp, stransi, strlen(stransi) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)lptsTemp); + c++; + } + EnableWindow(h, TRUE); + if (temp_cpu >= c) + temp_cpu = (c - 1); + SendMessage(h, CB_SETCURSEL, temp_cpu, 0); - h = GetDlgItem(hdlg, IDC_COMBO_CPU_TYPE); - SendMessage(h, CB_RESETCONTENT, 0, 0); - c = 0; - while (machines[romstomachine[temp_romset]].cpu[c].cpus != NULL && c < 4) - { - stransi = machines[romstomachine[temp_romset]].cpu[c].name; - mbstowcs(lptsTemp, stransi, strlen(stransi) + 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)lptsTemp); - c++; - } + win_settings_machine_recalc_cpu(hdlg); + + free(lptsTemp); +} + + +static void +win_settings_machine_recalc_machine(HWND hdlg) +{ + HWND h; + int c, temp_romset; + LPTSTR lptsTemp; + const char *stransi; + UDACCEL accel; + + temp_romset = machine_getromset_ex(temp_machine); + lptsTemp = (LPTSTR) malloc(512); + + h = GetDlgItem(hdlg, IDC_CONFIGURE_MACHINE); + if (machine_getdevice(temp_machine)) EnableWindow(h, TRUE); - if (temp_cpu_m >= c) - { - temp_cpu_m = (c - 1); - } - SendMessage(h, CB_SETCURSEL, temp_cpu_m, 0); - if (c == 1) - { - EnableWindow(h, FALSE); - } - else - { - EnableWindow(h, TRUE); - } + else + EnableWindow(h, FALSE); - win_settings_machine_recalc_cpu_m(hdlg); + h = GetDlgItem(hdlg, IDC_COMBO_CPU_TYPE); + SendMessage(h, CB_RESETCONTENT, 0, 0); + c = 0; + while (machines[romstomachine[temp_romset]].cpu[c].cpus != NULL && c < 4) { + stransi = machines[romstomachine[temp_romset]].cpu[c].name; + mbstowcs(lptsTemp, stransi, strlen(stransi) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)lptsTemp); + c++; + } + EnableWindow(h, TRUE); + if (temp_cpu_m >= c) + temp_cpu_m = (c - 1); + SendMessage(h, CB_SETCURSEL, temp_cpu_m, 0); + EnableWindow(h, (c == 1) ? FALSE : TRUE); - h = GetDlgItem(hdlg, IDC_MEMSPIN); - SendMessage(h, UDM_SETRANGE, 0, (machines[romstomachine[temp_romset]].min_ram << 16) | machines[romstomachine[temp_romset]].max_ram); - accel.nSec = 0; - accel.nInc = machines[romstomachine[temp_romset]].ram_granularity; - SendMessage(h, UDM_SETACCEL, 1, (LPARAM)&accel); - if (!(machines[romstomachine[temp_romset]].flags & MACHINE_AT) || (machines[romstomachine[temp_romset]].ram_granularity >= 128)) - { - SendMessage(h, UDM_SETPOS, 0, temp_mem_size); - h = GetDlgItem(hdlg, IDC_TEXT_MB); - SendMessage(h, WM_SETTEXT, 0, (LPARAM) plat_get_string(IDS_2094)); - } - else - { - SendMessage(h, UDM_SETPOS, 0, temp_mem_size / 1024); - h = GetDlgItem(hdlg, IDC_TEXT_MB); - SendMessage(h, WM_SETTEXT, 0, (LPARAM) plat_get_string(IDS_2087)); - } + win_settings_machine_recalc_cpu_m(hdlg); - free(lptsTemp); + h = GetDlgItem(hdlg, IDC_MEMSPIN); + SendMessage(h, UDM_SETRANGE, 0, (machines[romstomachine[temp_romset]].min_ram << 16) | machines[romstomachine[temp_romset]].max_ram); + accel.nSec = 0; + accel.nInc = machines[romstomachine[temp_romset]].ram_granularity; + SendMessage(h, UDM_SETACCEL, 1, (LPARAM)&accel); + if (!(machines[romstomachine[temp_romset]].flags & MACHINE_AT) || (machines[romstomachine[temp_romset]].ram_granularity >= 128)) { + SendMessage(h, UDM_SETPOS, 0, temp_mem_size); + h = GetDlgItem(hdlg, IDC_TEXT_MB); + SendMessage(h, WM_SETTEXT, 0, win_get_string(IDS_2094)); + } else { + SendMessage(h, UDM_SETPOS, 0, temp_mem_size / 1024); + h = GetDlgItem(hdlg, IDC_TEXT_MB); + SendMessage(h, WM_SETTEXT, 0, win_get_string(IDS_2087)); + } + + free(lptsTemp); } @@ -620,208 +611,185 @@ static BOOL CALLBACK #endif win_settings_machine_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - HWND h; - int c = 0; - int d = 0; - LPTSTR lptsTemp; - char *stransi; + HWND h, h2; + int c, d; + LPTSTR lptsTemp; + char *stransi; - switch (message) - { - case WM_INITDIALOG: - lptsTemp = (LPTSTR) malloc(512); + switch (message) { + case WM_INITDIALOG: + lptsTemp = (LPTSTR) malloc(512); - h = GetDlgItem(hdlg, IDC_COMBO_MACHINE); - for (c = 0; c < ROM_MAX; c++) - { - romstolist[c] = 0; + h = GetDlgItem(hdlg, IDC_COMBO_MACHINE); + for (c = 0; c < ROM_MAX; c++) + romstolist[c] = 0; + c = d = 0; + while (machines[c].id != -1) { + if (romspresent[machines[c].id]) { + stransi = (char *)machines[c].name; + mbstowcs(lptsTemp, stransi, strlen(stransi) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + machinetolist[c] = d; + listtomachine[d] = c; + romstolist[machines[c].id] = d; + romstomachine[machines[c].id] = c; + d++; } - c = d = 0; - while (machines[c].id != -1) - { - if (romspresent[machines[c].id]) - { - stransi = (char *)machines[c].name; - mbstowcs(lptsTemp, stransi, strlen(stransi) + 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - machinetolist[c] = d; - listtomachine[d] = c; - romstolist[machines[c].id] = d; - romstomachine[machines[c].id] = c; - d++; + c++; + } + SendMessage(h, CB_SETCURSEL, machinetolist[temp_machine], 0); + + h = GetDlgItem(hdlg, IDC_COMBO_WS); + SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_2099)); + + for (c = 0; c < 8; c++) { + wsprintf(lptsTemp, plat_get_string(2100), c); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + } + + SendMessage(h, CB_SETCURSEL, temp_wait_states, 0); + +#ifdef USE_DYNAREC + h=GetDlgItem(hdlg, IDC_CHECK_DYNAREC); + SendMessage(h, BM_SETCHECK, temp_dynarec, 0); +#endif + + h = GetDlgItem(hdlg, IDC_MEMSPIN); + h2 = GetDlgItem(hdlg, IDC_MEMTEXT); + SendMessage(h, UDM_SETBUDDY, (WPARAM)h2, 0); + + h=GetDlgItem(hdlg, IDC_CHECK_SYNC); + SendMessage(h, BM_SETCHECK, temp_sync, 0); + + win_settings_machine_recalc_machine(hdlg); + + free(lptsTemp); + + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_COMBO_MACHINE: + if (HIWORD(wParam) == CBN_SELCHANGE) { + h = GetDlgItem(hdlg, IDC_COMBO_MACHINE); + temp_machine = listtomachine[SendMessage(h,CB_GETCURSEL,0,0)]; + + win_settings_machine_recalc_machine(hdlg); } - c++; - } - SendMessage(h, CB_SETCURSEL, machinetolist[temp_machine], 0); + break; + case IDC_COMBO_CPU_TYPE: + if (HIWORD(wParam) == CBN_SELCHANGE) { + h = GetDlgItem(hdlg, IDC_COMBO_CPU_TYPE); + temp_cpu_m = SendMessage(h, CB_GETCURSEL, 0, 0); - h = GetDlgItem(hdlg, IDC_COMBO_WS); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) plat_get_string(IDS_2131)); + temp_cpu = 0; + win_settings_machine_recalc_cpu_m(hdlg); + } + break; + case IDC_COMBO_CPU: + if (HIWORD(wParam) == CBN_SELCHANGE) { + h = GetDlgItem(hdlg, IDC_COMBO_CPU); + temp_cpu = SendMessage(h, CB_GETCURSEL, 0, 0); - for (c = 0; c < 8; c++) - { - wsprintf(lptsTemp, plat_get_string(2132), c); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } + win_settings_machine_recalc_cpu(hdlg); + } + break; + case IDC_CONFIGURE_MACHINE: + h = GetDlgItem(hdlg, IDC_COMBO_MACHINE); + temp_machine = listtomachine[SendMessage(h, CB_GETCURSEL, 0, 0)]; - SendMessage(h, CB_SETCURSEL, temp_wait_states, 0); + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)machine_getdevice(temp_machine)); + break; + } + + return FALSE; + + case WM_SAVESETTINGS: + lptsTemp = (LPTSTR) malloc(512); + stransi = (char *)malloc(512); #ifdef USE_DYNAREC - h=GetDlgItem(hdlg, IDC_CHECK_DYNAREC); - SendMessage(h, BM_SETCHECK, temp_dynarec, 0); + h=GetDlgItem(hdlg, IDC_CHECK_DYNAREC); + temp_dynarec = SendMessage(h, BM_GETCHECK, 0, 0); #endif - h = GetDlgItem(hdlg, IDC_MEMSPIN); - SendMessage(h, UDM_SETBUDDY, (WPARAM)GetDlgItem(hdlg, IDC_MEMTEXT), 0); + h=GetDlgItem(hdlg, IDC_CHECK_SYNC); + temp_sync = SendMessage(h, BM_GETCHECK, 0, 0); - h=GetDlgItem(hdlg, IDC_CHECK_SYNC); - SendMessage(h, BM_SETCHECK, temp_sync, 0); + h=GetDlgItem(hdlg, IDC_CHECK_FPU); + temp_fpu = SendMessage(h, BM_GETCHECK, 0, 0); - win_settings_machine_recalc_machine(hdlg); + h = GetDlgItem(hdlg, IDC_COMBO_WS); + temp_wait_states = SendMessage(h, CB_GETCURSEL, 0, 0); - free(lptsTemp); + h = GetDlgItem(hdlg, IDC_MEMTEXT); + SendMessage(h, WM_GETTEXT, 255, (LPARAM) lptsTemp); + wcstombs(stransi, lptsTemp, 512); + sscanf(stransi, "%u", &temp_mem_size); + temp_mem_size &= ~(machines[temp_machine].ram_granularity - 1); + if (temp_mem_size < machines[temp_machine].min_ram) + temp_mem_size = machines[temp_machine].min_ram; + else if (temp_mem_size > machines[temp_machine].max_ram) + temp_mem_size = machines[temp_machine].max_ram; + if ((machines[temp_machine].flags & MACHINE_AT) && (machines[temp_machine].ram_granularity < 128)) + temp_mem_size *= 1024; + free(stransi); + free(lptsTemp); - return TRUE; + default: + return FALSE; + } - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDC_COMBO_MACHINE: - if (HIWORD(wParam) == CBN_SELCHANGE) - { - h = GetDlgItem(hdlg, IDC_COMBO_MACHINE); - temp_machine = listtomachine[SendMessage(h,CB_GETCURSEL,0,0)]; - - win_settings_machine_recalc_machine(hdlg); - } - break; - case IDC_COMBO_CPU_TYPE: - if (HIWORD(wParam) == CBN_SELCHANGE) - { - h = GetDlgItem(hdlg, IDC_COMBO_CPU_TYPE); - temp_cpu_m = SendMessage(h, CB_GETCURSEL, 0, 0); - - temp_cpu = 0; - win_settings_machine_recalc_cpu_m(hdlg); - } - break; - case IDC_COMBO_CPU: - if (HIWORD(wParam) == CBN_SELCHANGE) - { - h = GetDlgItem(hdlg, IDC_COMBO_CPU); - temp_cpu = SendMessage(h, CB_GETCURSEL, 0, 0); - - win_settings_machine_recalc_cpu(hdlg); - } - break; - case IDC_CONFIGURE_MACHINE: - h = GetDlgItem(hdlg, IDC_COMBO_MACHINE); - temp_machine = listtomachine[SendMessage(h, CB_GETCURSEL, 0, 0)]; - - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)machine_getdevice(temp_machine)); - break; - } - - return FALSE; - - case WM_SAVESETTINGS: - lptsTemp = (LPTSTR) malloc(512); - stransi = (char *)malloc(512); - -#ifdef USE_DYNAREC - h=GetDlgItem(hdlg, IDC_CHECK_DYNAREC); - temp_dynarec = SendMessage(h, BM_GETCHECK, 0, 0); -#endif - - h=GetDlgItem(hdlg, IDC_CHECK_SYNC); - temp_sync = SendMessage(h, BM_GETCHECK, 0, 0); - - h=GetDlgItem(hdlg, IDC_CHECK_FPU); - temp_fpu = SendMessage(h, BM_GETCHECK, 0, 0); - - h = GetDlgItem(hdlg, IDC_COMBO_WS); - temp_wait_states = SendMessage(h, CB_GETCURSEL, 0, 0); - - h = GetDlgItem(hdlg, IDC_MEMTEXT); - SendMessage(h, WM_GETTEXT, 255, (LPARAM) lptsTemp); - wcstombs(stransi, lptsTemp, 512); - sscanf(stransi, "%i", &temp_mem_size); - temp_mem_size &= ~(machines[temp_machine].ram_granularity - 1); - if (temp_mem_size < machines[temp_machine].min_ram) - { - temp_mem_size = machines[temp_machine].min_ram; - } - else if (temp_mem_size > machines[temp_machine].max_ram) - { - temp_mem_size = machines[temp_machine].max_ram; - } - if ((machines[temp_machine].flags & MACHINE_AT) && (machines[temp_machine].ram_granularity < 128)) - { - temp_mem_size *= 1024; - } - if (machines[temp_machine].flags & MACHINE_VIDEO) - { - gfxcard = GFX_INTERNAL; - } - free(stransi); - free(lptsTemp); - - default: - return FALSE; - } - - return FALSE; + return FALSE; } -static void recalc_vid_list(HWND hdlg) +static void +recalc_vid_list(HWND hdlg) { - HWND h = GetDlgItem(hdlg, IDC_COMBO_VIDEO); - int c = 0, d = 0; - int found_card = 0; - WCHAR szText[512]; - - SendMessage(h, CB_RESETCONTENT, 0, 0); - SendMessage(h, CB_SETCURSEL, 0, 0); - - while (1) - { - /* Skip "internal" if machine doesn't have it. */ - if (c==1 && !(machines[temp_machine].flags&MACHINE_VIDEO)) { - c++; - continue; + HWND h = GetDlgItem(hdlg, IDC_COMBO_VIDEO); + int c = 0, d = 0; + int found_card = 0; + WCHAR szText[512]; + + SendMessage(h, CB_RESETCONTENT, 0, 0); + SendMessage(h, CB_SETCURSEL, 0, 0); + + while (1) { + /* Skip "internal" if machine doesn't have it. */ + if ((c == 1) && !(machines[temp_machine].flags&MACHINE_VIDEO)) { + c++; + continue; + } + + char *s = video_card_getname(c); + + if (!s[0]) + break; + + if (video_card_available(c) && gfx_present[video_new_to_old(c)] && + device_is_valid(video_card_getdevice(c), machines[temp_machine].flags)) { + mbstowcs(szText, s, strlen(s) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) szText); + if (video_new_to_old(c) == temp_gfxcard) { + SendMessage(h, CB_SETCURSEL, d, 0); + found_card = 1; } - char *s = video_card_getname(c); + d++; + } - if (!s[0]) - break; + c++; + } + if (!found_card) + SendMessage(h, CB_SETCURSEL, 0, 0); + EnableWindow(h, machines[temp_machine].fixed_gfxcard ? FALSE : TRUE); - if (video_card_available(c) && gfx_present[video_new_to_old(c)] && - device_is_valid(video_card_getdevice(c), machines[temp_machine].flags)) - { - mbstowcs(szText, s, strlen(s) + 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) szText); - if (video_new_to_old(c) == temp_gfxcard) - { + h = GetDlgItem(hdlg, IDC_CHECK_VOODOO); + EnableWindow(h, (machines[temp_machine].flags & MACHINE_PCI) ? TRUE : FALSE); - SendMessage(h, CB_SETCURSEL, d, 0); - found_card = 1; - } - - d++; - } - - c++; - } - if (!found_card) - SendMessage(h, CB_SETCURSEL, 0, 0); - EnableWindow(h, machines[temp_machine].fixed_gfxcard ? FALSE : TRUE); - - h = GetDlgItem(hdlg, IDC_CHECK_VOODOO); - EnableWindow(h, (machines[temp_machine].flags & MACHINE_PCI) ? TRUE : FALSE); - - h = GetDlgItem(hdlg, IDC_BUTTON_VOODOO); - EnableWindow(h, ((machines[temp_machine].flags & MACHINE_PCI) && temp_voodoo) ? TRUE : FALSE); + h = GetDlgItem(hdlg, IDC_BUTTON_VOODOO); + EnableWindow(h, ((machines[temp_machine].flags & MACHINE_PCI) && temp_voodoo) ? TRUE : FALSE); } @@ -832,140 +800,118 @@ static BOOL CALLBACK #endif win_settings_video_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - HWND h; - LPTSTR lptsTemp; - char *stransi; - int gfx = 0; + HWND h; + LPTSTR lptsTemp; + char *stransi; + int gfx; - switch (message) - { - case WM_INITDIALOG: - lptsTemp = (LPTSTR) malloc(512); - stransi = (char *) malloc(512); + switch (message) { + case WM_INITDIALOG: + lptsTemp = (LPTSTR) malloc(512); + stransi = (char *) malloc(512); - recalc_vid_list(hdlg); + recalc_vid_list(hdlg); - h = GetDlgItem(hdlg, IDC_COMBO_VIDEO_SPEED); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_2131)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_2133)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_2134)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_2135)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_2136)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_2137)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_2138)); - SendMessage(h, CB_SETCURSEL, temp_video_speed + 1, 0); + h=GetDlgItem(hdlg, IDC_CHECK_VOODOO); + SendMessage(h, BM_SETCHECK, temp_voodoo, 0); - h=GetDlgItem(hdlg, IDC_CHECK_VOODOO); - SendMessage(h, BM_SETCHECK, temp_voodoo, 0); + h = GetDlgItem(hdlg, IDC_COMBO_VIDEO); + SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM) lptsTemp); + wcstombs(stransi, lptsTemp, 512); + gfx = video_card_getid(stransi); - h = GetDlgItem(hdlg, IDC_COMBO_VIDEO); - SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM) lptsTemp); - wcstombs(stransi, lptsTemp, 512); - gfx = video_card_getid(stransi); + h = GetDlgItem(hdlg, IDC_CONFIGURE_VID); + if (video_card_has_config(gfx)) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_CONFIGURE_VID); - if (video_card_has_config(gfx)) - { - EnableWindow(h, TRUE); - } - else - { - EnableWindow(h, FALSE); - } + free(stransi); + free(lptsTemp); - free(stransi); - free(lptsTemp); + return TRUE; - return TRUE; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_COMBO_VIDEO: + lptsTemp = (LPTSTR) malloc(512); + stransi = (char *) malloc(512); - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDC_COMBO_VIDEO: - lptsTemp = (LPTSTR) malloc(512); - stransi = (char *) malloc(512); + h = GetDlgItem(hdlg, IDC_COMBO_VIDEO); + SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM) lptsTemp); + wcstombs(stransi, lptsTemp, 512); + gfx = video_card_getid(stransi); + temp_gfxcard = video_new_to_old(gfx); - h = GetDlgItem(hdlg, IDC_COMBO_VIDEO); - SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM) lptsTemp); - wcstombs(stransi, lptsTemp, 512); - gfx = video_card_getid(stransi); - temp_gfxcard = video_new_to_old(gfx); + h = GetDlgItem(hdlg, IDC_CONFIGURE_VID); + if (video_card_has_config(gfx)) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_CONFIGURE_VID); - if (video_card_has_config(gfx)) - { - EnableWindow(h, TRUE); - } - else - { - EnableWindow(h, FALSE); - } + free(stransi); + free(lptsTemp); + break; - free(stransi); - free(lptsTemp); - break; + case IDC_CHECK_VOODOO: + h = GetDlgItem(hdlg, IDC_CHECK_VOODOO); + temp_voodoo = SendMessage(h, BM_GETCHECK, 0, 0); - case IDC_CHECK_VOODOO: - h = GetDlgItem(hdlg, IDC_CHECK_VOODOO); - temp_voodoo = SendMessage(h, BM_GETCHECK, 0, 0); + h = GetDlgItem(hdlg, IDC_BUTTON_VOODOO); + EnableWindow(h, temp_voodoo ? TRUE : FALSE); + break; - h = GetDlgItem(hdlg, IDC_BUTTON_VOODOO); - EnableWindow(h, temp_voodoo ? TRUE : FALSE); - break; + case IDC_BUTTON_VOODOO: + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)&voodoo_device); + break; - case IDC_BUTTON_VOODOO: - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)&voodoo_device); - break; + case IDC_CONFIGURE_VID: + lptsTemp = (LPTSTR) malloc(512); + stransi = (char *) malloc(512); - case IDC_CONFIGURE_VID: - lptsTemp = (LPTSTR) malloc(512); - stransi = (char *) malloc(512); + h = GetDlgItem(hdlg, IDC_COMBO_VIDEO); + SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM) lptsTemp); + wcstombs(stransi, lptsTemp, 512); + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)video_card_getdevice(video_card_getid(stransi))); - h = GetDlgItem(hdlg, IDC_COMBO_VIDEO); - SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM) lptsTemp); - wcstombs(stransi, lptsTemp, 512); - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)video_card_getdevice(video_card_getid(stransi))); + free(stransi); + free(lptsTemp); + break; + } + return FALSE; - free(stransi); - free(lptsTemp); - break; - } - return FALSE; + case WM_SAVESETTINGS: + lptsTemp = (LPTSTR) malloc(512); + stransi = (char *) malloc(512); - case WM_SAVESETTINGS: - lptsTemp = (LPTSTR) malloc(512); - stransi = (char *) malloc(512); + h = GetDlgItem(hdlg, IDC_COMBO_VIDEO); + SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM) lptsTemp); + wcstombs(stransi, lptsTemp, 512); + temp_gfxcard = video_new_to_old(video_card_getid(stransi)); - h = GetDlgItem(hdlg, IDC_COMBO_VIDEO); - SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM) lptsTemp); - wcstombs(stransi, lptsTemp, 512); - temp_gfxcard = video_new_to_old(video_card_getid(stransi)); + h = GetDlgItem(hdlg, IDC_CHECK_VOODOO); + temp_voodoo = SendMessage(h, BM_GETCHECK, 0, 0); - h = GetDlgItem(hdlg, IDC_COMBO_VIDEO_SPEED); - temp_video_speed = SendMessage(h, CB_GETCURSEL, 0, 0) - 1; + free(stransi); + free(lptsTemp); - h = GetDlgItem(hdlg, IDC_CHECK_VOODOO); - temp_voodoo = SendMessage(h, BM_GETCHECK, 0, 0); - - free(stransi); - free(lptsTemp); - - default: - return FALSE; - } - return FALSE; + default: + return FALSE; + } + return FALSE; } -static int mouse_valid(int num, int m) +static int +mouse_valid(int num, int m) { - const device_t *dev; + const device_t *dev; - if ((num == MOUSE_TYPE_INTERNAL) && - !(machines[m].flags & MACHINE_MOUSE)) return(0); + if ((num == MOUSE_TYPE_INTERNAL) && + !(machines[m].flags & MACHINE_MOUSE)) return(0); - dev = mouse_get_device(num); - return(device_is_valid(dev, machines[m].flags)); + dev = mouse_get_device(num); + return(device_is_valid(dev, machines[m].flags)); } @@ -976,182 +922,163 @@ static BOOL CALLBACK #endif win_settings_input_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - wchar_t str[128]; - HWND h; - int c = 0; - int d = 0; + wchar_t str[128]; + HWND h; + int c, d; - switch (message) - { - case WM_INITDIALOG: - h = GetDlgItem(hdlg, IDC_COMBO_MOUSE); - c = d = 0; - for (c = 0; c < mouse_get_ndev(); c++) - { - settings_mouse_to_list[c] = d; + switch (message) { + case WM_INITDIALOG: + h = GetDlgItem(hdlg, IDC_COMBO_MOUSE); + c = d = 0; + for (c = 0; c < mouse_get_ndev(); c++) { + settings_device_to_list[c] = d; - if (mouse_valid(c, temp_machine)) - { - mbstowcs(str, mouse_get_name(c), sizeof_w(str)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)str); + if (mouse_valid(c, temp_machine)) { + mbstowcs(str, mouse_get_name(c), sizeof_w(str)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)str); - settings_list_to_mouse[d] = c; - d++; - } + settings_list_to_device[d] = c; + d++; } + } - SendMessage(h, CB_SETCURSEL, settings_mouse_to_list[temp_mouse], 0); + SendMessage(h, CB_SETCURSEL, settings_device_to_list[temp_mouse], 0); - h = GetDlgItem(hdlg, IDC_CONFIGURE_MOUSE); - if (mouse_has_config(temp_mouse)) - { - EnableWindow(h, TRUE); - } - else - { - EnableWindow(h, FALSE); - } - - h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); - c = 0; - while (joystick_get_name(c)) - { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(2144 + c)); - c++; - } + h = GetDlgItem(hdlg, IDC_CONFIGURE_MOUSE); + if (mouse_has_config(temp_mouse)) EnableWindow(h, TRUE); - SendMessage(h, CB_SETCURSEL, temp_joystick, 0); + else + EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_JOY1); - EnableWindow(h, (joystick_get_max_joysticks(temp_joystick) >= 1) ? TRUE : FALSE); - h = GetDlgItem(hdlg, IDC_JOY2); - EnableWindow(h, (joystick_get_max_joysticks(temp_joystick) >= 2) ? TRUE : FALSE); - h = GetDlgItem(hdlg, IDC_JOY3); - EnableWindow(h, (joystick_get_max_joysticks(temp_joystick) >= 3) ? TRUE : FALSE); - h = GetDlgItem(hdlg, IDC_JOY4); - EnableWindow(h, (joystick_get_max_joysticks(temp_joystick) >= 4) ? TRUE : FALSE); + h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); + c = 0; + while (joystick_get_name(c)) { + SendMessage(h, CB_ADDSTRING, 0, win_get_string(2105 + c)); + c++; + } + EnableWindow(h, TRUE); + SendMessage(h, CB_SETCURSEL, temp_joystick, 0); - return TRUE; + h = GetDlgItem(hdlg, IDC_JOY1); + EnableWindow(h, (joystick_get_max_joysticks(temp_joystick) >= 1) ? TRUE : FALSE); + h = GetDlgItem(hdlg, IDC_JOY2); + EnableWindow(h, (joystick_get_max_joysticks(temp_joystick) >= 2) ? TRUE : FALSE); + h = GetDlgItem(hdlg, IDC_JOY3); + EnableWindow(h, (joystick_get_max_joysticks(temp_joystick) >= 3) ? TRUE : FALSE); + h = GetDlgItem(hdlg, IDC_JOY4); + EnableWindow(h, (joystick_get_max_joysticks(temp_joystick) >= 4) ? TRUE : FALSE); - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDC_COMBO_MOUSE: - h = GetDlgItem(hdlg, IDC_COMBO_MOUSE); - temp_mouse = settings_list_to_mouse[SendMessage(h, CB_GETCURSEL, 0, 0)]; + return TRUE; - h = GetDlgItem(hdlg, IDC_CONFIGURE_MOUSE); - if (mouse_has_config(temp_mouse)) - { - EnableWindow(h, TRUE); - } - else - { - EnableWindow(h, FALSE); - } - break; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_COMBO_MOUSE: + h = GetDlgItem(hdlg, IDC_COMBO_MOUSE); + temp_mouse = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; - case IDC_CONFIGURE_MOUSE: - h = GetDlgItem(hdlg, IDC_COMBO_MOUSE); - temp_mouse = settings_list_to_mouse[SendMessage(h, CB_GETCURSEL, 0, 0)]; - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)mouse_get_device(temp_mouse)); - break; + h = GetDlgItem(hdlg, IDC_CONFIGURE_MOUSE); + if (mouse_has_config(temp_mouse)) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + break; - case IDC_COMBO_JOYSTICK: - h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); - temp_joystick = SendMessage(h, CB_GETCURSEL, 0, 0); + case IDC_CONFIGURE_MOUSE: + h = GetDlgItem(hdlg, IDC_COMBO_MOUSE); + temp_mouse = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)mouse_get_device(temp_mouse)); + break; - h = GetDlgItem(hdlg, IDC_JOY1); - EnableWindow(h, (joystick_get_max_joysticks(temp_joystick) >= 1) ? TRUE : FALSE); - h = GetDlgItem(hdlg, IDC_JOY2); - EnableWindow(h, (joystick_get_max_joysticks(temp_joystick) >= 2) ? TRUE : FALSE); - h = GetDlgItem(hdlg, IDC_JOY3); - EnableWindow(h, (joystick_get_max_joysticks(temp_joystick) >= 3) ? TRUE : FALSE); - h = GetDlgItem(hdlg, IDC_JOY4); - EnableWindow(h, (joystick_get_max_joysticks(temp_joystick) >= 4) ? TRUE : FALSE); - break; + case IDC_COMBO_JOYSTICK: + h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); + temp_joystick = SendMessage(h, CB_GETCURSEL, 0, 0); - case IDC_JOY1: - h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); - temp_joystick = SendMessage(h, CB_GETCURSEL, 0, 0); - temp_deviceconfig |= joystickconfig_open(hdlg, 0, temp_joystick); - break; + h = GetDlgItem(hdlg, IDC_JOY1); + EnableWindow(h, (joystick_get_max_joysticks(temp_joystick) >= 1) ? TRUE : FALSE); + h = GetDlgItem(hdlg, IDC_JOY2); + EnableWindow(h, (joystick_get_max_joysticks(temp_joystick) >= 2) ? TRUE : FALSE); + h = GetDlgItem(hdlg, IDC_JOY3); + EnableWindow(h, (joystick_get_max_joysticks(temp_joystick) >= 3) ? TRUE : FALSE); + h = GetDlgItem(hdlg, IDC_JOY4); + EnableWindow(h, (joystick_get_max_joysticks(temp_joystick) >= 4) ? TRUE : FALSE); + break; - case IDC_JOY2: - h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); - temp_joystick = SendMessage(h, CB_GETCURSEL, 0, 0); - temp_deviceconfig |= joystickconfig_open(hdlg, 1, temp_joystick); - break; + case IDC_JOY1: + h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); + temp_joystick = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_deviceconfig |= joystickconfig_open(hdlg, 0, temp_joystick); + break; - case IDC_JOY3: - h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); - temp_joystick = SendMessage(h, CB_GETCURSEL, 0, 0); - temp_deviceconfig |= joystickconfig_open(hdlg, 2, temp_joystick); - break; + case IDC_JOY2: + h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); + temp_joystick = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_deviceconfig |= joystickconfig_open(hdlg, 1, temp_joystick); + break; - case IDC_JOY4: - h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); - temp_joystick = SendMessage(h, CB_GETCURSEL, 0, 0); - temp_deviceconfig |= joystickconfig_open(hdlg, 3, temp_joystick); - break; - } - return FALSE; + case IDC_JOY3: + h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); + temp_joystick = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_deviceconfig |= joystickconfig_open(hdlg, 2, temp_joystick); + break; - case WM_SAVESETTINGS: - h = GetDlgItem(hdlg, IDC_COMBO_MOUSE); - temp_mouse = settings_list_to_mouse[SendMessage(h, CB_GETCURSEL, 0, 0)]; + case IDC_JOY4: + h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); + temp_joystick = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_deviceconfig |= joystickconfig_open(hdlg, 3, temp_joystick); + break; + } + return FALSE; - h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); - temp_joystick = SendMessage(h, CB_GETCURSEL, 0, 0); + case WM_SAVESETTINGS: + h = GetDlgItem(hdlg, IDC_COMBO_MOUSE); + temp_mouse = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; - default: - return FALSE; - } - return FALSE; + h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); + temp_joystick = SendMessage(h, CB_GETCURSEL, 0, 0); + + default: + return FALSE; + } + return FALSE; } -int mpu401_present(void) +static int +mpu401_present(void) { - char *n; + char *n; - n = sound_card_get_internal_name(temp_sound_card); - if (n != NULL) - { - if (!strcmp(n, "sb16") || !strcmp(n, "sbawe32")) - { - return 1; - } - } + n = sound_card_get_internal_name(temp_sound_card); + if (n != NULL) { + if (!strcmp(n, "sb16") || !strcmp(n, "sbawe32")) + return 1; + } - return temp_mpu401 ? 1 : 0; + return temp_mpu401 ? 1 : 0; } -int mpu401_standalone_allow(void) + +int +mpu401_standalone_allow(void) { - char *n, *md; + char *n, *md; - n = sound_card_get_internal_name(temp_sound_card); - md = midi_device_get_internal_name(temp_midi_device); - if (n != NULL) - { - if (!strcmp(n, "sb16") || !strcmp(n, "sbawe32")) - { - return 0; - } - } + n = sound_card_get_internal_name(temp_sound_card); + md = midi_device_get_internal_name(temp_midi_device); + if (n != NULL) { + if (!strcmp(n, "sb16") || !strcmp(n, "sbawe32")) + return 0; + } - if (md != NULL) - { - if (!strcmp(md, "none")) - { - return 0; - } - } + if (md != NULL) { + if (!strcmp(md, "none")) + return 0; + } - return 1; + return 1; } + #ifdef __amd64__ static LRESULT CALLBACK #else @@ -1159,239 +1086,202 @@ static BOOL CALLBACK #endif win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - HWND h; - int c = 0; - int d = 0; - LPTSTR lptsTemp; - const device_t *sound_dev; - char *s; + HWND h; + int c, d; + LPTSTR lptsTemp; + const device_t *sound_dev; + char *s; - switch (message) - { - case WM_INITDIALOG: - lptsTemp = (LPTSTR) malloc(512); + switch (message) { + case WM_INITDIALOG: + lptsTemp = (LPTSTR) malloc(512); - h = GetDlgItem(hdlg, IDC_COMBO_SOUND); - c = d = 0; - while (1) - { - s = sound_card_getname(c); + h = GetDlgItem(hdlg, IDC_COMBO_SOUND); + c = d = 0; + while (1) { + s = sound_card_getname(c); - if (!s[0]) - { - break; - } + if (!s[0]) + break; - settings_sound_to_list[c] = d; + settings_device_to_list[c] = d; - if (sound_card_available(c)) - { - sound_dev = sound_card_getdevice(c); + if (sound_card_available(c)) { + sound_dev = sound_card_getdevice(c); - if (device_is_valid(sound_dev, machines[temp_machine].flags)) - { - if (c == 0) - { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) plat_get_string(IDS_2152)); - } - else - { - mbstowcs(lptsTemp, s, strlen(s) + 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } - settings_list_to_sound[d] = c; - d++; - } - } - - c++; - } - SendMessage(h, CB_SETCURSEL, settings_sound_to_list[temp_sound_card], 0); - - EnableWindow(h, d ? TRUE : FALSE); - - h = GetDlgItem(hdlg, IDC_CONFIGURE_SND); - if (sound_card_has_config(temp_sound_card)) - { - EnableWindow(h, TRUE); - } - else - { - EnableWindow(h, FALSE); - } - - h = GetDlgItem(hdlg, IDC_COMBO_MIDI); - c = d = 0; - while (1) - { - s = midi_device_getname(c); - - if (!s[0]) - { - break; - } - - settings_midi_to_list[c] = d; - - if (midi_device_available(c)) - { + if (device_is_valid(sound_dev, machines[temp_machine].flags)) { if (c == 0) - { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_2152)); - } - else - { + SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_2112)); + else { mbstowcs(lptsTemp, s, strlen(s) + 1); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } - settings_list_to_midi[d] = c; + settings_list_to_device[d] = c; d++; } - - c++; - } - SendMessage(h, CB_SETCURSEL, settings_midi_to_list[temp_midi_device], 0); - - h = GetDlgItem(hdlg, IDC_CONFIGURE_MIDI); - if (midi_device_has_config(temp_midi_device)) - { - EnableWindow(h, TRUE); - } - else - { - EnableWindow(h, FALSE); } - h = GetDlgItem(hdlg, IDC_CHECK_MPU401); - SendMessage(h, BM_SETCHECK, temp_mpu401, 0); - EnableWindow(h, mpu401_standalone_allow() ? TRUE : FALSE); + c++; + } + SendMessage(h, CB_SETCURSEL, settings_device_to_list[temp_sound_card], 0); - h = GetDlgItem(hdlg, IDC_CONFIGURE_MPU401); - EnableWindow(h, (mpu401_standalone_allow() && temp_mpu401) ? TRUE : FALSE); + EnableWindow(h, d ? TRUE : FALSE); - h=GetDlgItem(hdlg, IDC_CHECK_CMS); - SendMessage(h, BM_SETCHECK, temp_GAMEBLASTER, 0); + h = GetDlgItem(hdlg, IDC_CONFIGURE_SND); + EnableWindow(h, sound_card_has_config(temp_sound_card) ? TRUE : FALSE); - h=GetDlgItem(hdlg, IDC_CHECK_GUS); - SendMessage(h, BM_SETCHECK, temp_GUS, 0); + h = GetDlgItem(hdlg, IDC_COMBO_MIDI); + c = d = 0; + while (1) { + s = midi_device_getname(c); - h=GetDlgItem(hdlg, IDC_CHECK_SSI); - SendMessage(h, BM_SETCHECK, temp_SSI2001, 0); + if (!s[0]) + break; - h=GetDlgItem(hdlg, IDC_CHECK_NUKEDOPL); - SendMessage(h, BM_SETCHECK, temp_opl3_type, 0); + settings_midi_to_list[c] = d; - h=GetDlgItem(hdlg, IDC_CHECK_FLOAT); - SendMessage(h, BM_SETCHECK, temp_float, 0); - - free(lptsTemp); - - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDC_COMBO_SOUND: - h = GetDlgItem(hdlg, IDC_COMBO_SOUND); - temp_sound_card = settings_list_to_sound[SendMessage(h, CB_GETCURSEL, 0, 0)]; - - h = GetDlgItem(hdlg, IDC_CONFIGURE_SND); - if (sound_card_has_config(temp_sound_card)) - { - EnableWindow(h, TRUE); - } - else - { - EnableWindow(h, FALSE); - } - - h = GetDlgItem(hdlg, IDC_CHECK_MPU401); - SendMessage(h, BM_SETCHECK, temp_mpu401, 0); - EnableWindow(h, mpu401_standalone_allow() ? TRUE : FALSE); - - h = GetDlgItem(hdlg, IDC_CONFIGURE_MPU401); - EnableWindow(h, (mpu401_standalone_allow() && temp_mpu401) ? TRUE : FALSE); - break; - - case IDC_CONFIGURE_SND: - h = GetDlgItem(hdlg, IDC_COMBO_SOUND); - temp_sound_card = settings_list_to_sound[SendMessage(h, CB_GETCURSEL, 0, 0)]; - - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)sound_card_getdevice(temp_sound_card)); - break; - - case IDC_COMBO_MIDI: - h = GetDlgItem(hdlg, IDC_COMBO_MIDI); - temp_midi_device = settings_list_to_midi[SendMessage(h, CB_GETCURSEL, 0, 0)]; - - h = GetDlgItem(hdlg, IDC_CONFIGURE_MIDI); - if (midi_device_has_config(temp_midi_device)) - { - EnableWindow(h, TRUE); - } - else - { - EnableWindow(h, FALSE); - } - - h = GetDlgItem(hdlg, IDC_CHECK_MPU401); - SendMessage(h, BM_SETCHECK, temp_mpu401, 0); - EnableWindow(h, mpu401_standalone_allow() ? TRUE : FALSE); - - h = GetDlgItem(hdlg, IDC_CONFIGURE_MPU401); - EnableWindow(h, (mpu401_standalone_allow() && temp_mpu401) ? TRUE : FALSE); - break; - - case IDC_CONFIGURE_MIDI: - h = GetDlgItem(hdlg, IDC_COMBO_MIDI); - temp_midi_device = settings_list_to_midi[SendMessage(h, CB_GETCURSEL, 0, 0)]; - - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)midi_device_getdevice(temp_midi_device)); - break; - - case IDC_CHECK_MPU401: - h = GetDlgItem(hdlg, IDC_CHECK_MPU401); - temp_mpu401 = SendMessage(h, BM_GETCHECK, 0, 0); - - h = GetDlgItem(hdlg, IDC_CONFIGURE_MPU401); - EnableWindow(h, mpu401_present() ? TRUE : FALSE); - break; - - case IDC_CONFIGURE_MPU401: - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)&mpu401_device); - break; + if (midi_device_available(c)) { + if (c == 0) + SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_2112)); + else { + mbstowcs(lptsTemp, s, strlen(s) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + } + settings_list_to_midi[d] = c; + d++; } - return FALSE; - case WM_SAVESETTINGS: - h = GetDlgItem(hdlg, IDC_COMBO_SOUND); - temp_sound_card = settings_list_to_sound[SendMessage(h, CB_GETCURSEL, 0, 0)]; + c++; + } + SendMessage(h, CB_SETCURSEL, settings_midi_to_list[temp_midi_device], 0); - h = GetDlgItem(hdlg, IDC_COMBO_MIDI); - temp_midi_device = settings_list_to_midi[SendMessage(h, CB_GETCURSEL, 0, 0)]; + h = GetDlgItem(hdlg, IDC_CONFIGURE_MIDI); + if (midi_device_has_config(temp_midi_device)) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_CHECK_MPU401); - temp_mpu401 = SendMessage(h, BM_GETCHECK, 0, 0); + h = GetDlgItem(hdlg, IDC_CHECK_MPU401); + SendMessage(h, BM_SETCHECK, temp_mpu401, 0); + EnableWindow(h, mpu401_standalone_allow() ? TRUE : FALSE); - h = GetDlgItem(hdlg, IDC_CHECK_CMS); - temp_GAMEBLASTER = SendMessage(h, BM_GETCHECK, 0, 0); + h = GetDlgItem(hdlg, IDC_CONFIGURE_MPU401); + EnableWindow(h, (mpu401_standalone_allow() && temp_mpu401) ? TRUE : FALSE); - h = GetDlgItem(hdlg, IDC_CHECK_GUS); - temp_GUS = SendMessage(h, BM_GETCHECK, 0, 0); + h=GetDlgItem(hdlg, IDC_CHECK_CMS); + SendMessage(h, BM_SETCHECK, temp_GAMEBLASTER, 0); - h = GetDlgItem(hdlg, IDC_CHECK_SSI); - temp_SSI2001 = SendMessage(h, BM_GETCHECK, 0, 0); + h=GetDlgItem(hdlg, IDC_CHECK_GUS); + SendMessage(h, BM_SETCHECK, temp_GUS, 0); - h = GetDlgItem(hdlg, IDC_CHECK_NUKEDOPL); - temp_opl3_type = SendMessage(h, BM_GETCHECK, 0, 0); + h=GetDlgItem(hdlg, IDC_CHECK_SSI); + SendMessage(h, BM_SETCHECK, temp_SSI2001, 0); - h = GetDlgItem(hdlg, IDC_CHECK_FLOAT); - temp_float = SendMessage(h, BM_GETCHECK, 0, 0); + h=GetDlgItem(hdlg, IDC_CHECK_NUKEDOPL); + SendMessage(h, BM_SETCHECK, temp_opl_type, 0); - default: - return FALSE; - } - return FALSE; + h=GetDlgItem(hdlg, IDC_CHECK_FLOAT); + SendMessage(h, BM_SETCHECK, temp_float, 0); + + free(lptsTemp); + + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_COMBO_SOUND: + h = GetDlgItem(hdlg, IDC_COMBO_SOUND); + temp_sound_card = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + h = GetDlgItem(hdlg, IDC_CONFIGURE_SND); + if (sound_card_has_config(temp_sound_card)) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + + h = GetDlgItem(hdlg, IDC_CHECK_MPU401); + SendMessage(h, BM_SETCHECK, temp_mpu401, 0); + EnableWindow(h, mpu401_standalone_allow() ? TRUE : FALSE); + + h = GetDlgItem(hdlg, IDC_CONFIGURE_MPU401); + EnableWindow(h, (mpu401_standalone_allow() && temp_mpu401) ? TRUE : FALSE); + break; + + case IDC_CONFIGURE_SND: + h = GetDlgItem(hdlg, IDC_COMBO_SOUND); + temp_sound_card = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)sound_card_getdevice(temp_sound_card)); + break; + + case IDC_COMBO_MIDI: + h = GetDlgItem(hdlg, IDC_COMBO_MIDI); + temp_midi_device = settings_list_to_midi[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + h = GetDlgItem(hdlg, IDC_CONFIGURE_MIDI); + if (midi_device_has_config(temp_midi_device)) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + + h = GetDlgItem(hdlg, IDC_CHECK_MPU401); + SendMessage(h, BM_SETCHECK, temp_mpu401, 0); + EnableWindow(h, mpu401_standalone_allow() ? TRUE : FALSE); + + h = GetDlgItem(hdlg, IDC_CONFIGURE_MPU401); + EnableWindow(h, (mpu401_standalone_allow() && temp_mpu401) ? TRUE : FALSE); + break; + + case IDC_CONFIGURE_MIDI: + h = GetDlgItem(hdlg, IDC_COMBO_MIDI); + temp_midi_device = settings_list_to_midi[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)midi_device_getdevice(temp_midi_device)); + break; + + case IDC_CHECK_MPU401: + h = GetDlgItem(hdlg, IDC_CHECK_MPU401); + temp_mpu401 = SendMessage(h, BM_GETCHECK, 0, 0); + + h = GetDlgItem(hdlg, IDC_CONFIGURE_MPU401); + EnableWindow(h, mpu401_present() ? TRUE : FALSE); + break; + + case IDC_CONFIGURE_MPU401: + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)&mpu401_device); + break; + } + return FALSE; + + case WM_SAVESETTINGS: + h = GetDlgItem(hdlg, IDC_COMBO_SOUND); + temp_sound_card = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + h = GetDlgItem(hdlg, IDC_COMBO_MIDI); + temp_midi_device = settings_list_to_midi[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + h = GetDlgItem(hdlg, IDC_CHECK_MPU401); + temp_mpu401 = SendMessage(h, BM_GETCHECK, 0, 0); + + h = GetDlgItem(hdlg, IDC_CHECK_CMS); + temp_GAMEBLASTER = SendMessage(h, BM_GETCHECK, 0, 0); + + h = GetDlgItem(hdlg, IDC_CHECK_GUS); + temp_GUS = SendMessage(h, BM_GETCHECK, 0, 0); + + h = GetDlgItem(hdlg, IDC_CHECK_SSI); + temp_SSI2001 = SendMessage(h, BM_GETCHECK, 0, 0); + + h = GetDlgItem(hdlg, IDC_CHECK_NUKEDOPL); + temp_opl_type = SendMessage(h, BM_GETCHECK, 0, 0); + + h = GetDlgItem(hdlg, IDC_CHECK_FLOAT); + temp_float = SendMessage(h, BM_GETCHECK, 0, 0); + + default: + return FALSE; + } + return FALSE; } @@ -1402,173 +1292,133 @@ static BOOL CALLBACK #endif win_settings_ports_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - HWND h; - int c = 0; - int d = 0; - char *s; - LPTSTR lptsTemp; - int i; + HWND h; + int c, d, i; + char *s; + LPTSTR lptsTemp; - switch (message) - { - case WM_INITDIALOG: - lptsTemp = (LPTSTR) malloc(512); + switch (message) { + case WM_INITDIALOG: + lptsTemp = (LPTSTR) malloc(512); - for (i = 0; i < 3; i++) { - h = GetDlgItem(hdlg, IDC_COMBO_LPT1 + i); - c = d = 0; - while (1) { - s = lpt_device_get_name(c); + for (i = 0; i < 3; i++) { + h = GetDlgItem(hdlg, IDC_COMBO_LPT1 + i); + c = d = 0; + while (1) { + s = lpt_device_get_name(c); - if (!s) - break; + if (!s) + break; - if (c == 0) { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) plat_get_string(IDS_2152)); - } else { - mbstowcs(lptsTemp, s, strlen(s) + 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } - - if (!strcmp(temp_lpt_device_names[i], lpt_device_get_internal_name(c))) - d = c; - - c++; + if (c == 0) + SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_2112)); + else { + mbstowcs(lptsTemp, s, strlen(s) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } - SendMessage(h, CB_SETCURSEL, d, 0); + + if (!strcmp(temp_lpt_device_names[i], lpt_device_get_internal_name(c))) + d = c; + + c++; } - - h=GetDlgItem(hdlg, IDC_CHECK_SERIAL1); - SendMessage(h, BM_SETCHECK, temp_serial[0], 0); - - h=GetDlgItem(hdlg, IDC_CHECK_SERIAL2); - SendMessage(h, BM_SETCHECK, temp_serial[1], 0); - - h=GetDlgItem(hdlg, IDC_CHECK_PARALLEL); - SendMessage(h, BM_SETCHECK, temp_lpt, 0); - - free(lptsTemp); - - return TRUE; - - case WM_SAVESETTINGS: - for (i = 0; i < 3; i++) { - h = GetDlgItem(hdlg, IDC_COMBO_LPT1 + i); - c = SendMessage(h, CB_GETCURSEL, 0, 0); - strcpy(temp_lpt_device_names[i], lpt_device_get_internal_name(c)); - } - - h = GetDlgItem(hdlg, IDC_CHECK_SERIAL1); - temp_serial[0] = SendMessage(h, BM_GETCHECK, 0, 0); - - h = GetDlgItem(hdlg, IDC_CHECK_SERIAL2); - temp_serial[1] = SendMessage(h, BM_GETCHECK, 0, 0); - - h = GetDlgItem(hdlg, IDC_CHECK_PARALLEL); - temp_lpt = SendMessage(h, BM_GETCHECK, 0, 0); - - default: - return FALSE; - } - return FALSE; -} - - -static void recalc_hdc_list(HWND hdlg, int machine, int use_selected_hdc) -{ - HWND h; - - char *s; - int valid = 0; - char old_name[16]; - int c, d; - - LPTSTR lptsTemp; - - lptsTemp = (LPTSTR) malloc(512); - - h = GetDlgItem(hdlg, IDC_COMBO_HDC); - - valid = 0; - - if (use_selected_hdc) - { - c = SendMessage(h, CB_GETCURSEL, 0, 0); - - if (c != -1 && hdc_names[c]) - { - strncpy(old_name, hdc_names[c], sizeof(old_name) - 1); - } - else - { - strcpy(old_name, "none"); - } - } - else - { - strncpy(old_name, temp_hdc_name, sizeof(old_name) - 1); - } - - SendMessage(h, CB_RESETCONTENT, 0, 0); - c = d = 0; - while (1) - { - s = hdc_get_name(c); - if (s[0] == 0) - { - break; - } - if (c==1 && !(machines[temp_machine].flags&MACHINE_HDC)) - { - /* Skip "Internal" if machine doesn't have one. */ - c++; - continue; - } - if (!hdc_available(c) || !device_is_valid(hdc_get_device(c), machines[temp_machine].flags)) - { - c++; - continue; - } - mbstowcs(lptsTemp, s, strlen(s) + 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - - hdc_names[d] = hdc_get_internal_name(c); - if (!strcmp(old_name, hdc_names[d])) - { SendMessage(h, CB_SETCURSEL, d, 0); - valid = 1; } - c++; - d++; - } - if (!valid) - { - SendMessage(h, CB_SETCURSEL, 0, 0); - } + h=GetDlgItem(hdlg, IDC_CHECK_SERIAL1); + SendMessage(h, BM_SETCHECK, temp_serial[0], 0); - EnableWindow(h, d ? TRUE : FALSE); + h=GetDlgItem(hdlg, IDC_CHECK_SERIAL2); + SendMessage(h, BM_SETCHECK, temp_serial[1], 0); - free(lptsTemp); + h=GetDlgItem(hdlg, IDC_CHECK_PARALLEL); + SendMessage(h, BM_SETCHECK, temp_lpt, 0); + + free(lptsTemp); + + return TRUE; + + case WM_SAVESETTINGS: + for (i = 0; i < 3; i++) { + h = GetDlgItem(hdlg, IDC_COMBO_LPT1 + i); + c = SendMessage(h, CB_GETCURSEL, 0, 0); + strcpy(temp_lpt_device_names[i], lpt_device_get_internal_name(c)); + } + + h = GetDlgItem(hdlg, IDC_CHECK_SERIAL1); + temp_serial[0] = SendMessage(h, BM_GETCHECK, 0, 0); + + h = GetDlgItem(hdlg, IDC_CHECK_SERIAL2); + temp_serial[1] = SendMessage(h, BM_GETCHECK, 0, 0); + + h = GetDlgItem(hdlg, IDC_CHECK_PARALLEL); + temp_lpt = SendMessage(h, BM_GETCHECK, 0, 0); + + default: + return FALSE; + } + return FALSE; } -int valid_ide_irqs[11] = { 2, 3, 4, 5, 7, 9, 10, 11, 12, 14, 15 }; - - -int find_irq_in_array(int irq, int def) +static void +recalc_hdc_list(HWND hdlg, int machine, int use_selected_hdc) { - int i = 0; + HWND h; + char *s, old_name[32]; + int valid, c, d; - for (i = 0; i < 11; i++) - { - if (valid_ide_irqs[i] == irq) - { - return i + 1; - } + LPTSTR lptsTemp; + + lptsTemp = (LPTSTR) malloc(512); + + h = GetDlgItem(hdlg, IDC_COMBO_HDC); + + valid = 0; + + if (use_selected_hdc) { + c = SendMessage(h, CB_GETCURSEL, 0, 0); + + if (c != -1 && hdc_names[c]) + strncpy(old_name, hdc_names[c], sizeof(old_name) - 1); + else + strcpy(old_name, "none"); + } else + strncpy(old_name, temp_hdc_name, sizeof(old_name) - 1); + + SendMessage(h, CB_RESETCONTENT, 0, 0); + c = d = 0; + while (1) { + s = hdc_get_name(c); + if (s[0] == 0) + break; + if (c==1 && !(machines[temp_machine].flags&MACHINE_HDC)) { + /* Skip "Internal" if machine doesn't have one. */ + c++; + continue; } + if (!hdc_available(c) || !device_is_valid(hdc_get_device(c), machines[temp_machine].flags)) { + c++; + continue; + } + mbstowcs(lptsTemp, s, strlen(s) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - return 7 + def; + hdc_names[d] = hdc_get_internal_name(c); + if (!strcmp(old_name, hdc_names[d])) { + SendMessage(h, CB_SETCURSEL, d, 0); + valid = 1; + } + c++; + d++; + } + + if (!valid) + SendMessage(h, CB_SETCURSEL, 0, 0); + + EnableWindow(h, d ? TRUE : FALSE); + + free(lptsTemp); } @@ -1579,234 +1429,201 @@ static BOOL CALLBACK #endif win_settings_peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - HWND h; - int c = 0; - int d = 0; - LPTSTR lptsTemp; - const device_t *scsi_dev; + HWND h; + int c, d, temp_hdc_type; + LPTSTR lptsTemp; + const device_t *scsi_dev; - switch (message) - { - case WM_INITDIALOG: - lptsTemp = (LPTSTR) malloc(512); + switch (message) { + case WM_INITDIALOG: + lptsTemp = (LPTSTR) malloc(512); - /*SCSI config*/ - h = GetDlgItem(hdlg, IDC_COMBO_SCSI); - c = d = 0; - while (1) - { - char *s = scsi_card_getname(c); + /*SCSI config*/ + h = GetDlgItem(hdlg, IDC_COMBO_SCSI); + c = d = 0; + while (1) { + char *s = scsi_card_getname(c); - if (!s[0]) - { - break; + if (!s[0]) + break; + + settings_device_to_list[c] = d; + + if (scsi_card_available(c)) { + scsi_dev = scsi_card_getdevice(c); + + if (device_is_valid(scsi_dev, machines[temp_machine].flags)) { + if (c == 0) + SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_2112)); + else { + mbstowcs(lptsTemp, s, strlen(s) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + } + settings_list_to_device[d] = c; + d++; } - - settings_scsi_to_list[c] = d; - - if (scsi_card_available(c)) - { - scsi_dev = scsi_card_getdevice(c); - - - if (device_is_valid(scsi_dev, machines[temp_machine].flags)) - { - if (c == 0) - { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) plat_get_string(IDS_2152)); - } - else - { - mbstowcs(lptsTemp, s, strlen(s) + 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } - settings_list_to_scsi[d] = c; - d++; - } - } - - c++; - } - SendMessage(h, CB_SETCURSEL, settings_scsi_to_list[temp_scsi_card], 0); - - EnableWindow(h, d ? TRUE : FALSE); - - h = GetDlgItem(hdlg, IDC_CONFIGURE_SCSI); - if (scsi_card_has_config(temp_scsi_card)) - { - EnableWindow(h, TRUE); - } - else - { - EnableWindow(h, FALSE); } - recalc_hdc_list(hdlg, temp_machine, 0); + c++; + } + SendMessage(h, CB_SETCURSEL, settings_device_to_list[temp_scsi_card], 0); - h=GetDlgItem(hdlg, IDC_COMBO_IDE_TER); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_5376)); + EnableWindow(h, d ? TRUE : FALSE); - for (c = 0; c < 11; c++) - { - wsprintf(lptsTemp, plat_get_string(IDS_2155), valid_ide_irqs[c]); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } + h = GetDlgItem(hdlg, IDC_CONFIGURE_SCSI); + EnableWindow(h, scsi_card_has_config(temp_scsi_card) ? TRUE : FALSE); - if (temp_ide_ter) - { - SendMessage(h, CB_SETCURSEL, find_irq_in_array(temp_ide_ter_irq, 0), 0); - } - else - { - SendMessage(h, CB_SETCURSEL, 0, 0); - } + recalc_hdc_list(hdlg, temp_machine, 0); - h=GetDlgItem(hdlg, IDC_COMBO_IDE_QUA); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_5376)); + h = GetDlgItem(hdlg, IDC_CONFIGURE_HDC); + EnableWindow(h, hdc_has_config(hdc_get_from_internal_name(temp_hdc_name)) ? TRUE : FALSE); - for (c = 0; c < 11; c++) - { - wsprintf(lptsTemp, plat_get_string(IDS_2155), valid_ide_irqs[c]); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } + h = GetDlgItem(hdlg, IDC_CHECK_IDE_TER); + EnableWindow(h, (machines[temp_machine].flags & MACHINE_AT) ? TRUE : FALSE); - if (temp_ide_qua) - { - SendMessage(h, CB_SETCURSEL, find_irq_in_array(temp_ide_qua_irq, 1), 0); - } - else - { - SendMessage(h, CB_SETCURSEL, 0, 0); - } + h = GetDlgItem(hdlg, IDC_BUTTON_IDE_TER); + EnableWindow(h, ((machines[temp_machine].flags & MACHINE_AT) && temp_ide_ter) ? TRUE : FALSE); - h=GetDlgItem(hdlg, IDC_CHECK_BUGGER); - SendMessage(h, BM_SETCHECK, temp_bugger, 0); + h = GetDlgItem(hdlg, IDC_CHECK_IDE_QUA); + EnableWindow(h, (machines[temp_machine].flags & MACHINE_AT) ? TRUE : FALSE); - free(lptsTemp); + h = GetDlgItem(hdlg, IDC_BUTTON_IDE_QUA); + EnableWindow(h, ((machines[temp_machine].flags & MACHINE_AT) && temp_ide_qua) ? TRUE : FALSE); - return TRUE; + h=GetDlgItem(hdlg, IDC_CHECK_IDE_TER); + SendMessage(h, BM_SETCHECK, temp_ide_ter, 0); - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDC_CONFIGURE_SCSI: - h = GetDlgItem(hdlg, IDC_COMBO_SCSI); - temp_scsi_card = settings_list_to_scsi[SendMessage(h, CB_GETCURSEL, 0, 0)]; + h=GetDlgItem(hdlg, IDC_CHECK_IDE_QUA); + SendMessage(h, BM_SETCHECK, temp_ide_qua, 0); - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)scsi_card_getdevice(temp_scsi_card)); - break; + h=GetDlgItem(hdlg, IDC_CHECK_BUGGER); + SendMessage(h, BM_SETCHECK, temp_bugger, 0); - case IDC_COMBO_SCSI: - h = GetDlgItem(hdlg, IDC_COMBO_SCSI); - temp_scsi_card = settings_list_to_scsi[SendMessage(h, CB_GETCURSEL, 0, 0)]; + free(lptsTemp); - h = GetDlgItem(hdlg, IDC_CONFIGURE_SCSI); - if (scsi_card_has_config(temp_scsi_card)) - { - EnableWindow(h, TRUE); - } - else - { - EnableWindow(h, FALSE); - } - break; - } - return FALSE; + return TRUE; - case WM_SAVESETTINGS: - h = GetDlgItem(hdlg, IDC_COMBO_HDC); - c = SendMessage(h, CB_GETCURSEL, 0, 0); - if (hdc_names[c]) - { - strncpy(temp_hdc_name, hdc_names[c], sizeof(temp_hdc_name) - 1); - } - else - { - strcpy(temp_hdc_name, "none"); - } + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_COMBO_HDC: + h = GetDlgItem(hdlg, IDC_COMBO_HDC); + temp_hdc_type = hdc_get_from_internal_name(hdc_names[SendMessage(h, CB_GETCURSEL, 0, 0)]); - h = GetDlgItem(hdlg, IDC_COMBO_SCSI); - temp_scsi_card = settings_list_to_scsi[SendMessage(h, CB_GETCURSEL, 0, 0)]; + h = GetDlgItem(hdlg, IDC_CONFIGURE_HDC); + EnableWindow(h, hdc_has_config(temp_hdc_type) ? TRUE : FALSE); + break; - h = GetDlgItem(hdlg, IDC_COMBO_IDE_TER); - temp_ide_ter = SendMessage(h, CB_GETCURSEL, 0, 0); - if (temp_ide_ter > 1) - { - temp_ide_ter_irq = valid_ide_irqs[temp_ide_ter - 1]; - temp_ide_ter = 1; - } + case IDC_CONFIGURE_HDC: + h = GetDlgItem(hdlg, IDC_COMBO_HDC); + temp_hdc_type = hdc_get_from_internal_name(hdc_names[SendMessage(h, CB_GETCURSEL, 0, 0)]); - h = GetDlgItem(hdlg, IDC_COMBO_IDE_QUA); - temp_ide_qua = SendMessage(h, CB_GETCURSEL, 0, 0); - if (temp_ide_qua > 1) - { - temp_ide_qua_irq = valid_ide_irqs[temp_ide_qua - 1]; - temp_ide_qua = 1; - } + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)hdc_get_device(temp_hdc_type)); + break; - h = GetDlgItem(hdlg, IDC_CHECK_BUGGER); - temp_bugger = SendMessage(h, BM_GETCHECK, 0, 0); + case IDC_CONFIGURE_SCSI: + h = GetDlgItem(hdlg, IDC_COMBO_SCSI); + temp_scsi_card = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; - default: - return FALSE; - } - return FALSE; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)scsi_card_getdevice(temp_scsi_card)); + break; + + case IDC_COMBO_SCSI: + h = GetDlgItem(hdlg, IDC_COMBO_SCSI); + temp_scsi_card = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + h = GetDlgItem(hdlg, IDC_CONFIGURE_SCSI); + if (scsi_card_has_config(temp_scsi_card)) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + break; + + case IDC_CHECK_IDE_TER: + h = GetDlgItem(hdlg, IDC_CHECK_IDE_TER); + temp_ide_ter = SendMessage(h, BM_GETCHECK, 0, 0); + + h = GetDlgItem(hdlg, IDC_BUTTON_IDE_TER); + EnableWindow(h, temp_ide_ter ? TRUE : FALSE); + break; + + case IDC_BUTTON_IDE_TER: + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)&ide_ter_device); + break; + + case IDC_CHECK_IDE_QUA: + h = GetDlgItem(hdlg, IDC_CHECK_IDE_QUA); + temp_ide_qua = SendMessage(h, BM_GETCHECK, 0, 0); + + h = GetDlgItem(hdlg, IDC_BUTTON_IDE_QUA); + EnableWindow(h, temp_ide_qua ? TRUE : FALSE); + break; + + case IDC_BUTTON_IDE_QUA: + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)&ide_qua_device); + break; + } + return FALSE; + + case WM_SAVESETTINGS: + h = GetDlgItem(hdlg, IDC_COMBO_HDC); + c = SendMessage(h, CB_GETCURSEL, 0, 0); + if (hdc_names[c]) + strncpy(temp_hdc_name, hdc_names[c], sizeof(temp_hdc_name) - 1); + else + strcpy(temp_hdc_name, "none"); + + h = GetDlgItem(hdlg, IDC_COMBO_SCSI); + temp_scsi_card = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + h = GetDlgItem(hdlg, IDC_CHECK_IDE_TER); + temp_ide_ter = SendMessage(h, BM_GETCHECK, 0, 0); + + h = GetDlgItem(hdlg, IDC_CHECK_IDE_QUA); + temp_ide_qua = SendMessage(h, BM_GETCHECK, 0, 0); + + h = GetDlgItem(hdlg, IDC_CHECK_BUGGER); + temp_bugger = SendMessage(h, BM_GETCHECK, 0, 0); + + default: + return FALSE; + } + return FALSE; } -int net_ignore_message = 0; - static void network_recalc_combos(HWND hdlg) { - HWND h; + HWND h; - net_ignore_message = 1; + ignore_change = 1; - h = GetDlgItem(hdlg, IDC_COMBO_PCAP); - if (temp_net_type == NET_TYPE_PCAP) - { - EnableWindow(h, TRUE); - } - else - { - EnableWindow(h, FALSE); - } + h = GetDlgItem(hdlg, IDC_COMBO_PCAP); + EnableWindow(h, (temp_net_type == NET_TYPE_PCAP) ? TRUE : FALSE); - h = GetDlgItem(hdlg, IDC_COMBO_NET); - if (temp_net_type == NET_TYPE_SLIRP) - { - EnableWindow(h, TRUE); - } - else if ((temp_net_type == NET_TYPE_PCAP) && - (network_dev_to_id(temp_pcap_dev) > 0)) - { - EnableWindow(h, TRUE); - } - else - { - EnableWindow(h, FALSE); - } + h = GetDlgItem(hdlg, IDC_COMBO_NET); + if (temp_net_type == NET_TYPE_SLIRP) + EnableWindow(h, TRUE); + else if ((temp_net_type == NET_TYPE_PCAP) && + (network_dev_to_id(temp_pcap_dev) > 0)) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_CONFIGURE_NET); - if (network_card_has_config(temp_net_card) && - (temp_net_type == NET_TYPE_SLIRP)) - { - EnableWindow(h, TRUE); - } - else if (network_card_has_config(temp_net_card) && - (temp_net_type == NET_TYPE_PCAP) && - (network_dev_to_id(temp_pcap_dev) > 0)) - { - EnableWindow(h, TRUE); - } - else - { - EnableWindow(h, FALSE); - } + h = GetDlgItem(hdlg, IDC_CONFIGURE_NET); + if (network_card_has_config(temp_net_card) && + (temp_net_type == NET_TYPE_SLIRP)) + EnableWindow(h, TRUE); + else if (network_card_has_config(temp_net_card) && + (temp_net_type == NET_TYPE_PCAP) && + (network_dev_to_id(temp_pcap_dev) > 0)) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); - net_ignore_message = 0; + ignore_change = 0; } + #ifdef __amd64__ static LRESULT CALLBACK #else @@ -1814,910 +1631,726 @@ static BOOL CALLBACK #endif win_settings_network_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - HWND h; - int c = 0; - int d = 0; - LPTSTR lptsTemp; + HWND h; + int c, d; + LPTSTR lptsTemp; + char *s; - switch (message) - { - case WM_INITDIALOG: - lptsTemp = (LPTSTR) malloc(512); + switch (message) { + case WM_INITDIALOG: + lptsTemp = (LPTSTR) malloc(512); - h = GetDlgItem(hdlg, IDC_COMBO_NET_TYPE); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) L"None"); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) L"PCap"); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) L"SLiRP"); - SendMessage(h, CB_SETCURSEL, temp_net_type, 0); + h = GetDlgItem(hdlg, IDC_COMBO_NET_TYPE); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) L"None"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) L"PCap"); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) L"SLiRP"); + SendMessage(h, CB_SETCURSEL, temp_net_type, 0); - h = GetDlgItem(hdlg, IDC_COMBO_PCAP); - if (temp_net_type == NET_TYPE_PCAP) - { - EnableWindow(h, TRUE); - } - else - { - EnableWindow(h, FALSE); - } + h = GetDlgItem(hdlg, IDC_COMBO_PCAP); + if (temp_net_type == NET_TYPE_PCAP) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_COMBO_PCAP); - for (c = 0; c < network_ndev; c++) - { - mbstowcs(lptsTemp, network_devs[c].description, strlen(network_devs[c].description) + 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } - SendMessage(h, CB_SETCURSEL, network_dev_to_id(temp_pcap_dev), 0); - - /*NIC config*/ - h = GetDlgItem(hdlg, IDC_COMBO_NET); - c = d = 0; - while (1) - { - char *s = network_card_getname(c); - - if (s[0] == '\0') - { - break; - } - - settings_network_to_list[c] = d; - - if (network_card_available(c) && device_is_valid(network_card_getdevice(c), machines[temp_machine].flags)) - { - if (c == 0) - { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) plat_get_string(2152)); - } - else - { - mbstowcs(lptsTemp, s, strlen(s) + 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } - settings_list_to_network[d] = c; - d++; - } - - c++; - } - SendMessage(h, CB_SETCURSEL, settings_network_to_list[temp_net_card], 0); - - EnableWindow(h, d ? TRUE : FALSE); - - network_recalc_combos(hdlg); - - free(lptsTemp); - - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDC_COMBO_NET_TYPE: - if (net_ignore_message) - { - return FALSE; - } - - h = GetDlgItem(hdlg, IDC_COMBO_NET_TYPE); - temp_net_type = SendMessage(h, CB_GETCURSEL, 0, 0); - - network_recalc_combos(hdlg); - break; - - case IDC_COMBO_PCAP: - if (net_ignore_message) - { - return FALSE; - } - - h = GetDlgItem(hdlg, IDC_COMBO_PCAP); - memset(temp_pcap_dev, '\0', sizeof(temp_pcap_dev)); - strcpy(temp_pcap_dev, network_devs[SendMessage(h, CB_GETCURSEL, 0, 0)].device); - - network_recalc_combos(hdlg); - break; - - case IDC_COMBO_NET: - if (net_ignore_message) - { - return FALSE; - } - - h = GetDlgItem(hdlg, IDC_COMBO_NET); - temp_net_card = settings_list_to_network[SendMessage(h, CB_GETCURSEL, 0, 0)]; - - network_recalc_combos(hdlg); - break; - - case IDC_CONFIGURE_NET: - if (net_ignore_message) - { - return FALSE; - } - - h = GetDlgItem(hdlg, IDC_COMBO_NET); - temp_net_card = settings_list_to_network[SendMessage(h, CB_GETCURSEL, 0, 0)]; - - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)network_card_getdevice(temp_net_card)); - break; - } - return FALSE; - - case WM_SAVESETTINGS: - h = GetDlgItem(hdlg, IDC_COMBO_NET_TYPE); - temp_net_type = SendMessage(h, CB_GETCURSEL, 0, 0); - - h = GetDlgItem(hdlg, IDC_COMBO_PCAP); - memset(temp_pcap_dev, '\0', sizeof(temp_pcap_dev)); - strcpy(temp_pcap_dev, network_devs[SendMessage(h, CB_GETCURSEL, 0, 0)].device); - - h = GetDlgItem(hdlg, IDC_COMBO_NET); - temp_net_card = settings_list_to_network[SendMessage(h, CB_GETCURSEL, 0, 0)]; - - default: - return FALSE; - } - - return FALSE; -} - -static BOOL win_settings_hard_disks_image_list_init(HWND hwndList) -{ - HICON hiconItem; - HIMAGELIST hSmall; - - hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), - GetSystemMetrics(SM_CYSMICON), - ILC_MASK | ILC_COLOR32, 1, 1); - - hiconItem = LoadIcon(hinstance, (LPCWSTR) 208); - ImageList_AddIcon(hSmall, hiconItem); - DestroyIcon(hiconItem); - - hiconItem = LoadIcon(hinstance, (LPCWSTR) 192); - ImageList_AddIcon(hSmall, hiconItem); - DestroyIcon(hiconItem); - - ListView_SetImageList(hwndList, hSmall, LVSIL_SMALL); - - return TRUE; -} - -int next_free_id = 0; - -static void normalize_hd_list() -{ - hard_disk_t ihdd[HDD_NUM]; - int i, j; - - j = 0; - memset(ihdd, 0x00, HDD_NUM * sizeof(hard_disk_t)); - - for (i = 0; i < HDD_NUM; i++) - { - if (temp_hdd[i].bus != HDD_BUS_DISABLED) - { - memcpy(&(ihdd[j]), &(temp_hdd[i]), sizeof(hard_disk_t)); - j++; + h = GetDlgItem(hdlg, IDC_COMBO_PCAP); + for (c = 0; c < network_ndev; c++) { + mbstowcs(lptsTemp, network_devs[c].description, strlen(network_devs[c].description) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); } - } + SendMessage(h, CB_SETCURSEL, network_dev_to_id(temp_pcap_dev), 0); - memcpy(temp_hdd, ihdd, HDD_NUM * sizeof(hard_disk_t)); -} + /*NIC config*/ + h = GetDlgItem(hdlg, IDC_COMBO_NET); + c = d = 0; + while (1) { + s = network_card_getname(c); -int hdc_id_to_listview_index[HDD_NUM]; -int hd_listview_items; + if (s[0] == '\0') + break; -hard_disk_t new_hdd; -int hdlv_current_sel; + settings_device_to_list[c] = d; -static int get_selected_hard_disk(HWND hdlg) -{ - int hard_disk = -1; - int i, j = 0; - HWND h; + if (network_card_available(c) && device_is_valid(network_card_getdevice(c), machines[temp_machine].flags)) { + if (c == 0) + SendMessage(h, CB_ADDSTRING, 0, win_get_string(2112)); + else { + mbstowcs(lptsTemp, s, strlen(s) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + } + settings_list_to_device[d] = c; + d++; + } - if (hd_listview_items == 0) - { - return 0; - } - - for (i = 0; i < hd_listview_items; i++) - { - h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); - j = ListView_GetItemState(h, i, LVIS_SELECTED); - if (j) - { - hard_disk = i; + c++; } - } - return hard_disk; + SendMessage(h, CB_SETCURSEL, settings_device_to_list[temp_net_card], 0); + EnableWindow(h, d ? TRUE : FALSE); + network_recalc_combos(hdlg); + free(lptsTemp); + + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_COMBO_NET_TYPE: + if (ignore_change) + return FALSE; + + h = GetDlgItem(hdlg, IDC_COMBO_NET_TYPE); + temp_net_type = SendMessage(h, CB_GETCURSEL, 0, 0); + + network_recalc_combos(hdlg); + break; + + case IDC_COMBO_PCAP: + if (ignore_change) + return FALSE; + + h = GetDlgItem(hdlg, IDC_COMBO_PCAP); + memset(temp_pcap_dev, '\0', sizeof(temp_pcap_dev)); + strcpy(temp_pcap_dev, network_devs[SendMessage(h, CB_GETCURSEL, 0, 0)].device); + + network_recalc_combos(hdlg); + break; + + case IDC_COMBO_NET: + if (ignore_change) + return FALSE; + + h = GetDlgItem(hdlg, IDC_COMBO_NET); + temp_net_card = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + network_recalc_combos(hdlg); + break; + + case IDC_CONFIGURE_NET: + if (ignore_change) + return FALSE; + + h = GetDlgItem(hdlg, IDC_COMBO_NET); + temp_net_card = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)network_card_getdevice(temp_net_card)); + break; + } + return FALSE; + + case WM_SAVESETTINGS: + h = GetDlgItem(hdlg, IDC_COMBO_NET_TYPE); + temp_net_type = SendMessage(h, CB_GETCURSEL, 0, 0); + + h = GetDlgItem(hdlg, IDC_COMBO_PCAP); + memset(temp_pcap_dev, '\0', sizeof(temp_pcap_dev)); + strcpy(temp_pcap_dev, network_devs[SendMessage(h, CB_GETCURSEL, 0, 0)].device); + + h = GetDlgItem(hdlg, IDC_COMBO_NET); + temp_net_card = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + default: + return FALSE; + } + + return FALSE; } -static void add_locations(HWND hdlg) -{ - LPTSTR lptsTemp; - HWND h; - int i = 0; - lptsTemp = (LPTSTR) malloc(512); +static void +normalize_hd_list() +{ + hard_disk_t ihdd[HDD_NUM]; + int i, j; + + j = 0; + memset(ihdd, 0x00, HDD_NUM * sizeof(hard_disk_t)); + + for (i = 0; i < HDD_NUM; i++) { + if (temp_hdd[i].bus != HDD_BUS_DISABLED) { + memcpy(&(ihdd[j]), &(temp_hdd[i]), sizeof(hard_disk_t)); + j++; + } + } + + memcpy(temp_hdd, ihdd, HDD_NUM * sizeof(hard_disk_t)); +} + + +static int +get_selected_hard_disk(HWND hdlg) +{ + int hard_disk = -1; + int i, j = 0; + HWND h; + + if (hd_listview_items == 0) + return 0; + + for (i = 0; i < hd_listview_items; i++) { + h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); + j = ListView_GetItemState(h, i, LVIS_SELECTED); + if (j) + hard_disk = i; + } + + return hard_disk; +} + + +static void +add_locations(HWND hdlg) +{ + LPTSTR lptsTemp; + HWND h; + int i = 0; + + lptsTemp = (LPTSTR) malloc(512); + + h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); + for (i = 0; i < 5; i++) + SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_4352 + i)); + + h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); + for (i = 0; i < 2; i++) { + wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + } + + h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); + for (i = 0; i < 16; i++) { + wsprintf(lptsTemp, plat_get_string(IDS_4098), i); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + } + + h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); + for (i = 0; i < 8; i++) { + wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + } + + free(lptsTemp); +} + + +static uint8_t +next_free_binary_channel(uint64_t *tracking) +{ + int64_t i; + + for (i = 0; i < 2; i++) { + if (!(*tracking & (0xffLL << (i << 3LL)))) + return i; + } + + return 2; +} + + +static uint8_t +next_free_ide_channel(void) +{ + int64_t i; + + for (i = 0; i < 8; i++) { + if (!(ide_tracking & (0xffLL << (i << 3LL)))) + return i; + } + + return 7; +} + + +static void +next_free_scsi_id(uint8_t *id) +{ + int64_t i; + + for (i = 0; i < 16; i++) { + if (!(scsi_tracking[i >> 3] & (0xffLL << ((i & 0x07) << 3LL)))) { + *id = i; + return; + } + } + + *id = 6; +} + + +static void +recalc_location_controls(HWND hdlg, int is_add_dlg, int assign_id) +{ + int i = 0; + HWND h; + + int bus = 0; + + for (i = IDT_1722; i <= IDT_1723; i++) { + h = GetDlgItem(hdlg, i); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + } + + h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + + h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + + h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + + if ((hd_listview_items > 0) || is_add_dlg) { + h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); + bus = SendMessage(h, CB_GETCURSEL, 0, 0); + bus++; + + switch(bus) { + case HDD_BUS_MFM: /* MFM */ + h = GetDlgItem(hdlg, IDT_1722); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + + h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + if (assign_id) + temp_hdd[lv1_current_sel].mfm_channel = next_free_binary_channel(&mfm_tracking); + SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.mfm_channel : temp_hdd[lv1_current_sel].mfm_channel, 0); + break; + case HDD_BUS_XTA: /* XTA */ + h = GetDlgItem(hdlg, IDT_1722); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + + h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + if (assign_id) + temp_hdd[lv1_current_sel].xta_channel = next_free_binary_channel(&xta_tracking); + SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.xta_channel : temp_hdd[lv1_current_sel].xta_channel, 0); + break; + case HDD_BUS_ESDI: /* ESDI */ + h = GetDlgItem(hdlg, IDT_1722); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + + h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + if (assign_id) + temp_hdd[lv1_current_sel].esdi_channel = next_free_binary_channel(&esdi_tracking); + SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.esdi_channel : temp_hdd[lv1_current_sel].esdi_channel, 0); + break; + case HDD_BUS_IDE: /* IDE */ + h = GetDlgItem(hdlg, IDT_1722); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + + h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + if (assign_id) + temp_hdd[lv1_current_sel].ide_channel = next_free_ide_channel(); + SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.ide_channel : temp_hdd[lv1_current_sel].ide_channel, 0); + break; + case HDD_BUS_SCSI: /* SCSI */ + h = GetDlgItem(hdlg, IDT_1723); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + h = GetDlgItem(hdlg, IDT_1724); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + + if (assign_id) + next_free_scsi_id((uint8_t *) is_add_dlg ? &new_hdd.scsi_id : &temp_hdd[lv1_current_sel].scsi_id); + + h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.scsi_id : temp_hdd[lv1_current_sel].scsi_id, 0); + } + } + + if ((hd_listview_items == 0) && !is_add_dlg) { + h = GetDlgItem(hdlg, IDT_1721); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); - for (i = 0; i < 7; i++) - { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_4352 + i)); - } + EnableWindow(h, FALSE); ShowWindow(h, SW_HIDE); + } else { + h = GetDlgItem(hdlg, IDT_1721); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); - h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); - for (i = 0; i < 8; i++) - { - wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } - - h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); - for (i = 0; i < 16; i++) - { - wsprintf(lptsTemp, plat_get_string(IDS_4098), i); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } - - h = GetDlgItem(hdlg, IDC_COMBO_HD_LUN); - for (i = 0; i < 8; i++) - { - wsprintf(lptsTemp, plat_get_string(IDS_4098), i); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } - - h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); - for (i = 0; i < 8; i++) - { - wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } - - free(lptsTemp); + h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + } } -static uint8_t next_free_binary_channel(uint64_t *tracking) + +static int +bus_full(uint64_t *tracking, int count) { - int64_t i; - - for (i = 0; i < 2; i++) { - if (!(*tracking & (0xffLL << (i << 3LL)))) - return i; - } - - return 2; + int full = 0; + switch(count) { + case 2: + default: + full = (*tracking & 0xFF00LL); + full = full && (*tracking & 0x00FFLL); + return full; + case 8: + full = (*tracking & 0xFF00000000000000LL); + full = full && (*tracking & 0x00FF000000000000LL); + full = full && (*tracking & 0x0000FF0000000000LL); + full = full && (*tracking & 0x000000FF00000000LL); + full = full && (*tracking & 0x00000000FF000000LL); + full = full && (*tracking & 0x0000000000FF0000LL); + full = full && (*tracking & 0x000000000000FF00LL); + full = full && (*tracking & 0x00000000000000FFLL); + return full; + } } -static uint8_t next_free_ide_channel(void) + +static void +recalc_next_free_id(HWND hdlg) { - int64_t i; + HWND h; + int i, enable_add = 0; + int c_mfm = 0, c_esdi = 0; + int c_xta = 0, c_ide = 0; + int c_scsi = 0; - for (i = 0; i < 8; i++) { - if (!(ide_tracking & (0xffLL << (i << 3LL)))) - return i; + next_free_id = -1; + + for (i = 0; i < HDD_NUM; i++) { + if (temp_hdd[i].bus == HDD_BUS_MFM) + c_mfm++; + else if (temp_hdd[i].bus == HDD_BUS_ESDI) + c_esdi++; + else if (temp_hdd[i].bus == HDD_BUS_XTA) + c_xta++; + else if (temp_hdd[i].bus == HDD_BUS_IDE) + c_ide++; + else if (temp_hdd[i].bus == HDD_BUS_SCSI) + c_scsi++; + } + + for (i = 0; i < HDD_NUM; i++) { + if (temp_hdd[i].bus == HDD_BUS_DISABLED) { + next_free_id = i; + break; } + } - return 7; + enable_add = enable_add || (next_free_id >= 0); + enable_add = enable_add && ((c_mfm < MFM_NUM) || (c_esdi < ESDI_NUM) || (c_xta < XTA_NUM) || + (c_ide < IDE_NUM) || (c_scsi < SCSI_NUM)); + enable_add = enable_add && !bus_full(&mfm_tracking, 2); + enable_add = enable_add && !bus_full(&esdi_tracking, 2); + enable_add = enable_add && !bus_full(&xta_tracking, 2); + enable_add = enable_add && !bus_full(&ide_tracking, 8); + for (i = 0; i < 2; i++) + enable_add = enable_add && !bus_full(&(scsi_tracking[i]), 8); + + h = GetDlgItem(hdlg, IDC_BUTTON_HDD_ADD_NEW); + EnableWindow(h, enable_add ? TRUE : FALSE); + + h = GetDlgItem(hdlg, IDC_BUTTON_HDD_ADD); + EnableWindow(h, enable_add ? TRUE : FALSE); + + h = GetDlgItem(hdlg, IDC_BUTTON_HDD_REMOVE); + EnableWindow(h, ((c_mfm == 0) && (c_esdi == 0) && (c_xta == 0) && (c_ide == 0) && (c_scsi == 0)) ? + FALSE : TRUE); } -static void next_free_scsi_id_and_lun(uint8_t *id, uint8_t *lun) + +static void +win_settings_hard_disks_update_item(HWND hwndList, int i, int column) { - int64_t i, j; + LVITEM lvI; + WCHAR szText[256]; - for (j = 0; j < 8; j++) { - for (i = 0; i < 16; i++) { - if (!(scsi_tracking[i] & (0xffLL << (j << 3LL)))) { - *id = i; - *lun = j; - return; - } - } - } + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.stateMask = lvI.iSubItem = lvI.state = 0; - *id = 6; - *lun = 7; -} + lvI.iSubItem = column; + lvI.iItem = i; -static void recalc_location_controls(HWND hdlg, int is_add_dlg, int assign_id) -{ - int i = 0; - HWND h; - - int bus = 0; - - for (i = IDT_1722; i <= IDT_1724; i++) - { - h = GetDlgItem(hdlg, i); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - } - - h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - - h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - - h = GetDlgItem(hdlg, IDC_COMBO_HD_LUN); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - - h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - - if ((hd_listview_items > 0) || is_add_dlg) - { - h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); - bus = SendMessage(h, CB_GETCURSEL, 0, 0); - bus++; - - switch(bus) - { - case HDD_BUS_MFM: /* MFM */ - h = GetDlgItem(hdlg, IDT_1722); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - - h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - if (assign_id) - temp_hdd[hdlv_current_sel].mfm_channel = next_free_binary_channel(&mfm_tracking); - SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.mfm_channel : temp_hdd[hdlv_current_sel].mfm_channel, 0); - break; - case HDD_BUS_XTIDE: /* XT IDE */ - h = GetDlgItem(hdlg, IDT_1722); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - - h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - if (assign_id) - temp_hdd[hdlv_current_sel].xtide_channel = next_free_binary_channel(&xtide_tracking); - SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.xtide_channel : temp_hdd[hdlv_current_sel].xtide_channel, 0); - break; - case HDD_BUS_ESDI: /* ESDI */ - h = GetDlgItem(hdlg, IDT_1722); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - - h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - if (assign_id) - temp_hdd[hdlv_current_sel].esdi_channel = next_free_binary_channel(&esdi_tracking); - SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.esdi_channel : temp_hdd[hdlv_current_sel].esdi_channel, 0); - break; - case HDD_BUS_IDE_PIO_ONLY: /* IDE (PIO-only) */ - case HDD_BUS_IDE_PIO_AND_DMA: /* IDE (PIO and DMA) */ - h = GetDlgItem(hdlg, IDT_1722); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - - h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - if (assign_id) - temp_hdd[hdlv_current_sel].ide_channel = next_free_ide_channel(); - SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.ide_channel : temp_hdd[hdlv_current_sel].ide_channel, 0); - break; - case HDD_BUS_SCSI: /* SCSI */ - case HDD_BUS_SCSI_REMOVABLE: /* SCSI (removable) */ - h = GetDlgItem(hdlg, IDT_1723); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - h = GetDlgItem(hdlg, IDT_1724); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - - if (assign_id) - next_free_scsi_id_and_lun((uint8_t *) &temp_hdd[hdlv_current_sel].scsi_id, (uint8_t *) &temp_hdd[hdlv_current_sel].scsi_lun); - - h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.scsi_id : temp_hdd[hdlv_current_sel].scsi_id, 0); - - h = GetDlgItem(hdlg, IDC_COMBO_HD_LUN); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.scsi_lun : temp_hdd[hdlv_current_sel].scsi_lun, 0); - break; - } - } - - if ((hd_listview_items == 0) && !is_add_dlg) - { - h = GetDlgItem(hdlg, IDT_1721); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - - h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); - EnableWindow(h, FALSE); ShowWindow(h, SW_HIDE); - } - else - { - h = GetDlgItem(hdlg, IDT_1721); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - - h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - } -} - -static int bus_full(uint64_t *tracking, int count) -{ - int full = 0; - switch(count) { - case 2: - default: - full = (*tracking & 0xFF00LL); - full = full && (*tracking & 0x00FFLL); - return full; - case 8: - full = (*tracking & 0xFF00000000000000LL); - full = full && (*tracking & 0x00FF000000000000LL); - full = full && (*tracking & 0x0000FF0000000000LL); - full = full && (*tracking & 0x000000FF00000000LL); - full = full && (*tracking & 0x00000000FF000000LL); - full = full && (*tracking & 0x0000000000FF0000LL); - full = full && (*tracking & 0x000000000000FF00LL); - full = full && (*tracking & 0x00000000000000FFLL); - return full; - } -} - -static void recalc_next_free_id(HWND hdlg) -{ - HWND h; - int i; - - int c_mfm = 0; - int c_esdi = 0; - int c_xtide = 0; - int c_ide_pio = 0; - int c_ide_dma = 0; - int c_scsi = 0; - int enable_add = 0; - - next_free_id = -1; - - for (i = 0; i < HDD_NUM; i++) - { - if (temp_hdd[i].bus == HDD_BUS_MFM) - { - c_mfm++; - } - else if (temp_hdd[i].bus == HDD_BUS_ESDI) - { - c_esdi++; - } - else if (temp_hdd[i].bus == HDD_BUS_XTIDE) - { - c_xtide++; - } - else if (temp_hdd[i].bus == HDD_BUS_IDE_PIO_ONLY) - { - c_ide_pio++; - } - else if (temp_hdd[i].bus == HDD_BUS_IDE_PIO_AND_DMA) - { - c_ide_dma++; - } - else if (temp_hdd[i].bus == HDD_BUS_SCSI) - { - c_scsi++; - } - else if (temp_hdd[i].bus == HDD_BUS_SCSI_REMOVABLE) - { - c_scsi++; - } - } - - for (i = 0; i < HDD_NUM; i++) - { - if (temp_hdd[i].bus == HDD_BUS_DISABLED) - { - next_free_id = i; + if (column == 0) { + switch(temp_hdd[i].bus) { + case HDD_BUS_MFM: + wsprintf(szText, plat_get_string(IDS_4608), temp_hdd[i].mfm_channel >> 1, temp_hdd[i].mfm_channel & 1); + break; + case HDD_BUS_XTA: + wsprintf(szText, plat_get_string(IDS_4609), temp_hdd[i].xta_channel >> 1, temp_hdd[i].xta_channel & 1); + break; + case HDD_BUS_ESDI: + wsprintf(szText, plat_get_string(IDS_4610), temp_hdd[i].esdi_channel >> 1, temp_hdd[i].esdi_channel & 1); + break; + case HDD_BUS_IDE: + wsprintf(szText, plat_get_string(IDS_4611), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1); + break; + case HDD_BUS_SCSI: + wsprintf(szText, plat_get_string(IDS_4612), temp_hdd[i].scsi_id); break; - } } + lvI.pszText = szText; + lvI.iImage = 0; + } else if (column == 1) { + lvI.pszText = temp_hdd[i].fn; + lvI.iImage = 0; + } else if (column == 2) { + wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].tracks); + lvI.pszText = szText; + lvI.iImage = 0; + } else if (column == 3) { + wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].hpc); + lvI.pszText = szText; + lvI.iImage = 0; + } else if (column == 4) { + wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].spt); + lvI.pszText = szText; + lvI.iImage = 0; + } else if (column == 5) { + wsprintf(szText, plat_get_string(IDS_4098), (temp_hdd[i].tracks * temp_hdd[i].hpc * temp_hdd[i].spt) >> 11); + lvI.pszText = szText; + lvI.iImage = 0; + } - enable_add = enable_add || (next_free_id >= 0); - enable_add = enable_add && ((c_mfm < MFM_NUM) || (c_esdi < ESDI_NUM) || (c_xtide < XTIDE_NUM) || (c_ide_pio < IDE_NUM) || (c_ide_dma < IDE_NUM) || (c_scsi < SCSI_NUM)); - enable_add = enable_add && !bus_full(&mfm_tracking, 2); - enable_add = enable_add && !bus_full(&esdi_tracking, 2); - enable_add = enable_add && !bus_full(&xtide_tracking, 2); - enable_add = enable_add && !bus_full(&ide_tracking, 8); - for (i = 0; i < 16; i++) - enable_add = enable_add && !bus_full(&(scsi_tracking[i]), 8); - - h = GetDlgItem(hdlg, IDC_BUTTON_HDD_ADD_NEW); - - if (enable_add) - { - EnableWindow(h, TRUE); - } - else - { - EnableWindow(h, FALSE); - } - - h = GetDlgItem(hdlg, IDC_BUTTON_HDD_ADD); - - if (enable_add) - { - EnableWindow(h, TRUE); - } - else - { - EnableWindow(h, FALSE); - } - - h = GetDlgItem(hdlg, IDC_BUTTON_HDD_REMOVE); - - if ((c_mfm == 0) && (c_esdi == 0) && (c_xtide == 0) && (c_ide_pio == 0) && (c_ide_dma == 0) && (c_scsi == 0)) - { - EnableWindow(h, FALSE); - } - else - { - EnableWindow(h, TRUE); - } + if (ListView_SetItem(hwndList, &lvI) == -1) + return; } -static void win_settings_hard_disks_update_item(HWND hwndList, int i, int column) + +static BOOL +win_settings_hard_disks_recalc_list(HWND hwndList) { - LVITEM lvI; - WCHAR szText[256]; + LVITEM lvI; + int i, j = 0; + WCHAR szText[256]; - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvI.stateMask = lvI.iSubItem = lvI.state = 0; + hd_listview_items = 0; + lv1_current_sel = -1; - lvI.iSubItem = column; - lvI.iItem = i; + ListView_DeleteAllItems(hwndList); - if (column == 0) - { - switch(temp_hdd[i].bus) - { + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.stateMask = lvI.iSubItem = lvI.state = 0; + + for (i = 0; i < HDD_NUM; i++) { + if (temp_hdd[i].bus > 0) { + hdc_id_to_listview_index[i] = j; + lvI.iSubItem = 0; + switch(temp_hdd[i].bus) { case HDD_BUS_MFM: wsprintf(szText, plat_get_string(IDS_4608), temp_hdd[i].mfm_channel >> 1, temp_hdd[i].mfm_channel & 1); break; - case HDD_BUS_XTIDE: - wsprintf(szText, plat_get_string(IDS_4609), temp_hdd[i].xtide_channel >> 1, temp_hdd[i].xtide_channel & 1); + case HDD_BUS_XTA: + wsprintf(szText, plat_get_string(IDS_4609), temp_hdd[i].xta_channel >> 1, temp_hdd[i].xta_channel & 1); break; case HDD_BUS_ESDI: wsprintf(szText, plat_get_string(IDS_4610), temp_hdd[i].esdi_channel >> 1, temp_hdd[i].esdi_channel & 1); break; - case HDD_BUS_IDE_PIO_ONLY: + case HDD_BUS_IDE: wsprintf(szText, plat_get_string(IDS_4611), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1); break; - case HDD_BUS_IDE_PIO_AND_DMA: - wsprintf(szText, plat_get_string(IDS_4612), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1); - break; case HDD_BUS_SCSI: - wsprintf(szText, plat_get_string(IDS_4613), temp_hdd[i].scsi_id, temp_hdd[i].scsi_lun); - break; - case HDD_BUS_SCSI_REMOVABLE: - wsprintf(szText, plat_get_string(IDS_4614), temp_hdd[i].scsi_id, temp_hdd[i].scsi_lun); + wsprintf(szText, plat_get_string(IDS_4612), temp_hdd[i].scsi_id); break; } lvI.pszText = szText; - lvI.iImage = (temp_hdd[i].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0; - } - else if (column == 1) - { - lvI.pszText = temp_hdd[i].fn; + lvI.iItem = j; lvI.iImage = 0; - } - else if (column == 2) - { + + if (ListView_InsertItem(hwndList, &lvI) == -1) + return FALSE; + + lvI.iSubItem = 1; + lvI.pszText = temp_hdd[i].fn; + lvI.iItem = j; + lvI.iImage = 0; + + if (ListView_SetItem(hwndList, &lvI) == -1) + return FALSE; + + lvI.iSubItem = 2; wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].tracks); lvI.pszText = szText; + lvI.iItem = j; lvI.iImage = 0; - } - else if (column == 3) - { + + if (ListView_SetItem(hwndList, &lvI) == -1) + return FALSE; + + lvI.iSubItem = 3; wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].hpc); lvI.pszText = szText; + lvI.iItem = j; lvI.iImage = 0; - } - else if (column == 4) - { + + if (ListView_SetItem(hwndList, &lvI) == -1) + return FALSE; + + lvI.iSubItem = 4; wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].spt); lvI.pszText = szText; + lvI.iItem = j; lvI.iImage = 0; - } - else if (column == 5) - { + + if (ListView_SetItem(hwndList, &lvI) == -1) + return FALSE; + + lvI.iSubItem = 5; wsprintf(szText, plat_get_string(IDS_4098), (temp_hdd[i].tracks * temp_hdd[i].hpc * temp_hdd[i].spt) >> 11); lvI.pszText = szText; + lvI.iItem = j; lvI.iImage = 0; - } - if (ListView_SetItem(hwndList, &lvI) == -1) - { - return; - } -} - -static BOOL win_settings_hard_disks_recalc_list(HWND hwndList) -{ - LVITEM lvI; - int i = 0; - int j = 0; - WCHAR szText[256]; - - hd_listview_items = 0; - hdlv_current_sel = -1; - - ListView_DeleteAllItems(hwndList); - - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvI.stateMask = lvI.iSubItem = lvI.state = 0; - - for (i = 0; i < HDD_NUM; i++) - { - if (temp_hdd[i].bus > 0) - { - hdc_id_to_listview_index[i] = j; - lvI.iSubItem = 0; - switch(temp_hdd[i].bus) - { - case HDD_BUS_MFM: - wsprintf(szText, plat_get_string(IDS_4608), temp_hdd[i].mfm_channel >> 1, temp_hdd[i].mfm_channel & 1); - break; - case HDD_BUS_XTIDE: - wsprintf(szText, plat_get_string(IDS_4609), temp_hdd[i].xtide_channel >> 1, temp_hdd[i].xtide_channel & 1); - break; - case HDD_BUS_ESDI: - wsprintf(szText, plat_get_string(IDS_4610), temp_hdd[i].esdi_channel >> 1, temp_hdd[i].esdi_channel & 1); - break; - case HDD_BUS_IDE_PIO_ONLY: - wsprintf(szText, plat_get_string(IDS_4611), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1); - break; - case HDD_BUS_IDE_PIO_AND_DMA: - wsprintf(szText, plat_get_string(IDS_4612), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1); - break; - case HDD_BUS_SCSI: - wsprintf(szText, plat_get_string(IDS_4613), temp_hdd[i].scsi_id, temp_hdd[i].scsi_lun); - break; - case HDD_BUS_SCSI_REMOVABLE: - wsprintf(szText, plat_get_string(IDS_4614), temp_hdd[i].scsi_id, temp_hdd[i].scsi_lun); - break; - } - lvI.pszText = szText; - lvI.iItem = j; - lvI.iImage = (temp_hdd[i].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0; - - if (ListView_InsertItem(hwndList, &lvI) == -1) - { - return FALSE; - } - - lvI.iSubItem = 1; - lvI.pszText = temp_hdd[i].fn; - lvI.iItem = j; - lvI.iImage = 0; - - if (ListView_SetItem(hwndList, &lvI) == -1) - { - return FALSE; - } - - lvI.iSubItem = 2; - wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].tracks); - lvI.pszText = szText; - lvI.iItem = j; - lvI.iImage = 0; - - if (ListView_SetItem(hwndList, &lvI) == -1) - { - return FALSE; - } - - lvI.iSubItem = 3; - wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].hpc); - lvI.pszText = szText; - lvI.iItem = j; - lvI.iImage = 0; - - if (ListView_SetItem(hwndList, &lvI) == -1) - { - return FALSE; - } - - lvI.iSubItem = 4; - wsprintf(szText, plat_get_string(IDS_4098), temp_hdd[i].spt); - lvI.pszText = szText; - lvI.iItem = j; - lvI.iImage = 0; - - if (ListView_SetItem(hwndList, &lvI) == -1) - { - return FALSE; - } - - lvI.iSubItem = 5; - wsprintf(szText, plat_get_string(IDS_4098), (temp_hdd[i].tracks * temp_hdd[i].hpc * temp_hdd[i].spt) >> 11); - lvI.pszText = szText; - lvI.iItem = j; - lvI.iImage = 0; - - if (ListView_SetItem(hwndList, &lvI) == -1) - { - return FALSE; - } - - j++; - } - else - { - hdc_id_to_listview_index[i] = -1; - } - } - - hd_listview_items = j; - - return TRUE; -} - -/* Icon, Bus, File, C, H, S, Size */ -#define C_COLUMNS_HARD_DISKS 6 - -static BOOL win_settings_hard_disks_init_columns(HWND hwndList) -{ - LVCOLUMN lvc; - int iCol; - - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - - for (iCol = 0; iCol < C_COLUMNS_HARD_DISKS; iCol++) - { - lvc.iSubItem = iCol; - lvc.pszText = plat_get_string(2082 + iCol); - - switch(iCol) - { - - case 0: /* Bus */ - lvc.cx = 135; - lvc.fmt = LVCFMT_LEFT; - break; - case 2: /* Cylinders */ - lvc.cx = 41; - lvc.fmt = LVCFMT_RIGHT; - break; - case 3: /* Heads */ - case 4: /* Sectors */ - lvc.cx = 25; - lvc.fmt = LVCFMT_RIGHT; - break; - case 1: /* File */ - lvc.cx = 150; - lvc.fmt = LVCFMT_LEFT; - break; - case 5: /* Size (MB) 8 */ - lvc.cx = 41; - lvc.fmt = LVCFMT_RIGHT; - break; - } - - if (ListView_InsertColumn(hwndList, iCol, &lvc) == -1) - { + if (ListView_SetItem(hwndList, &lvI) == -1) return FALSE; - } + + j++; + } else + hdc_id_to_listview_index[i] = -1; + } + + hd_listview_items = j; + + return TRUE; +} + + +static BOOL +win_settings_hard_disks_init_columns(HWND hwndList) +{ + LVCOLUMN lvc; + int iCol; + + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + + for (iCol = 0; iCol < C_COLUMNS_HARD_DISKS; iCol++) { + lvc.iSubItem = iCol; + lvc.pszText = plat_get_string(IDS_2082 + iCol); + + switch(iCol) { + case 0: /* Bus */ + lvc.cx = 135; + lvc.fmt = LVCFMT_LEFT; + break; + case 2: /* Cylinders */ + lvc.cx = 41; + lvc.fmt = LVCFMT_RIGHT; + break; + case 3: /* Heads */ + case 4: /* Sectors */ + lvc.cx = 25; + lvc.fmt = LVCFMT_RIGHT; + break; + case 1: /* File */ + lvc.cx = 150; + lvc.fmt = LVCFMT_LEFT; + break; + case 5: /* Size (MB) 8 */ + lvc.cx = 41; + lvc.fmt = LVCFMT_RIGHT; + break; } - return TRUE; + if (ListView_InsertColumn(hwndList, iCol, &lvc) == -1) + return FALSE; + } + + return TRUE; } -static void get_edit_box_contents(HWND hdlg, int id, uint64_t *val) + +static void +get_edit_box_contents(HWND hdlg, int id, uint32_t *val) { - HWND h; - WCHAR szText[256]; - char stransi[256]; + HWND h; + WCHAR szText[256]; + char stransi[256]; - h = GetDlgItem(hdlg, id); - SendMessage(h, WM_GETTEXT, 255, (LPARAM) szText); - wcstombs(stransi, szText, 256); - sscanf(stransi, "%" PRIu64, val); + h = GetDlgItem(hdlg, id); + SendMessage(h, WM_GETTEXT, 255, (LPARAM) szText); + wcstombs(stransi, szText, 256); + sscanf(stransi, "%u", val); } -static void get_combo_box_selection(HWND hdlg, int id, uint64_t *val) + +static void +get_combo_box_selection(HWND hdlg, int id, uint32_t *val) { - HWND h; + HWND h; - h = GetDlgItem(hdlg, id); - *val = SendMessage(h, CB_GETCURSEL, 0, 0); + h = GetDlgItem(hdlg, id); + *val = SendMessage(h, CB_GETCURSEL, 0, 0); } -static void set_edit_box_contents(HWND hdlg, int id, uint64_t val) + +static void +set_edit_box_contents(HWND hdlg, int id, uint32_t val) { - HWND h; - WCHAR szText[256]; + HWND h; + WCHAR szText[256]; - h = GetDlgItem(hdlg, id); - wsprintf(szText, plat_get_string(IDS_2156), val); - SendMessage(h, WM_SETTEXT, (WPARAM) wcslen(szText), (LPARAM) szText); + h = GetDlgItem(hdlg, id); + wsprintf(szText, plat_get_string(IDS_2115), val); + SendMessage(h, WM_SETTEXT, (WPARAM) wcslen(szText), (LPARAM) szText); } -int hard_disk_added = 0; -int max_spt = 63; -int max_hpc = 255; -int max_tracks = 266305; - -int no_update = 0; - -int existing = 0; -uint64_t selection = 127; - -uint64_t spt, hpc, tracks, size; -wchar_t hd_file_name[512]; - -static hard_disk_t *hdd_ptr; static int hdconf_initialize_hdt_combo(HWND hdlg) { - HWND h; - int i = 0; - uint64_t temp_size = 0; - uint64_t size_mb = 0; - WCHAR szText[256]; + HWND h; + int i = 0; + uint64_t temp_size = 0; + uint32_t size_mb = 0; + WCHAR szText[256]; - selection = 127; + selection = 127; - h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); - for (i = 0; i < 127; i++) - { - temp_size = hdd_table[i][0] * hdd_table[i][1] * hdd_table[i][2]; - size_mb = temp_size >> 11; - wsprintf(szText, plat_get_string(IDS_2157), size_mb, hdd_table[i][0], hdd_table[i][1], hdd_table[i][2]); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) szText); - if ((tracks == hdd_table[i][0]) && (hpc == hdd_table[i][1]) && (spt == hdd_table[i][2])) - { - selection = i; - } - } - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_4100)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_4101)); - SendMessage(h, CB_SETCURSEL, selection, 0); - return selection; + h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); + for (i = 0; i < 127; i++) { + temp_size = hdd_table[i][0] * hdd_table[i][1] * hdd_table[i][2]; + size_mb = (uint32_t) (temp_size >> 11LL); + wsprintf(szText, plat_get_string(IDS_2116), size_mb, hdd_table[i][0], hdd_table[i][1], hdd_table[i][2]); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) szText); + if ((tracks == (int) hdd_table[i][0]) && (hpc == (int) hdd_table[i][1]) && + (spt == (int) hdd_table[i][2])) + selection = i; + } + SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_4100)); + SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_4101)); + SendMessage(h, CB_SETCURSEL, selection, 0); + return selection; } -static void recalc_selection(HWND hdlg) + +static void +recalc_selection(HWND hdlg) { - HWND h; - int i = 0; + HWND h; + int i = 0; - selection = 127; - h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); - for (i = 0; i < 127; i++) - { - if ((tracks == hdd_table[i][0]) && (hpc == hdd_table[i][1]) && (spt == hdd_table[i][2])) - { - selection = i; - } - } - if ((selection == 127) && (hpc == 16) && (spt == 63)) - { - selection = 128; - } - SendMessage(h, CB_SETCURSEL, selection, 0); + selection = 127; + h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); + for (i = 0; i < 127; i++) { + if ((tracks == (int) hdd_table[i][0]) && + (hpc == (int) hdd_table[i][1]) && + (spt == (int) hdd_table[i][2])) + selection = i; + } + if ((selection == 127) && (hpc == 16) && (spt == 63)) + selection = 128; + SendMessage(h, CB_SETCURSEL, selection, 0); } -static int chs_enabled = 0; #ifdef __amd64__ static LRESULT CALLBACK @@ -2726,839 +2359,696 @@ static BOOL CALLBACK #endif win_settings_hard_disks_add_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - HWND h; - int64_t i = 0; - uint64_t temp; - FILE *f; - uint32_t sector_size = 512; - uint32_t zero = 0; - uint32_t base = 0x1000; - uint64_t signature = 0xD778A82044445459ll; - char buf[512]; - char *big_buf; - int b = 0; - uint64_t r = 0; - uint8_t channel = 0; - uint8_t id = 0, lun = 0; - wchar_t *twcs; + HWND h; + FILE *f; + uint32_t temp, i = 0, sector_size = 512; + uint32_t zero = 0, base = 0x1000; + uint64_t signature = 0xD778A82044445459ll; + uint64_t temp_size, r = 0; + char buf[512], *big_buf; + int b = 0; + uint8_t channel = 0; + uint8_t id = 0; + wchar_t *twcs; + vhd_footer_t *vft = NULL; - switch (message) - { - case WM_INITDIALOG: - memset(hd_file_name, 0, sizeof(hd_file_name)); + switch (message) { + case WM_INITDIALOG: + memset(hd_file_name, 0, sizeof(hd_file_name)); - if (existing & 2) - { - next_free_id = (existing >> 3) & 0x1f; - hdd_ptr = &(hdd[next_free_id]); - } - else - { - hdd_ptr = &(temp_hdd[next_free_id]); - } + hdd_ptr = &(temp_hdd[next_free_id]); - SetWindowText(hdlg, plat_get_string((existing & 1) ? IDS_4103 : IDS_4102)); + SetWindowText(hdlg, plat_get_string((existing & 1) ? IDS_4103 : IDS_4102)); - no_update = 1; - spt = (existing & 1) ? 0 : 17; - set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); - hpc = (existing & 1) ? 0 : 15; - set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); - tracks = (existing & 1) ? 0 : 1023; - set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); - size = (tracks * hpc * spt) << 9; - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, size >> 20); - hdconf_initialize_hdt_combo(hdlg); - if (existing & 1) - { - h = GetDlgItem(hdlg, IDC_EDIT_HD_SPT); - EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_EDIT_HD_HPC); - EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_EDIT_HD_CYL); - EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_EDIT_HD_SIZE); - EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); - EnableWindow(h, FALSE); - chs_enabled = 0; - } - else - { - chs_enabled = 1; - } - add_locations(hdlg); - h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); - if (existing & 2) - { - hdd_ptr->bus = HDD_BUS_SCSI_REMOVABLE; - max_spt = 99; - max_hpc = 255; - } - else - { - hdd_ptr->bus = HDD_BUS_IDE_PIO_ONLY; - max_spt = 63; - max_hpc = 255; - } - SendMessage(h, CB_SETCURSEL, hdd_ptr->bus, 0); - max_tracks = 266305; - recalc_location_controls(hdlg, 1, 0); - if (existing & 2) - { - /* We're functioning as a load image dialog for a removable SCSI hard disk, - called from win.c, so let's hide the bus selection as we should not - allow it at this point. */ - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - - h = GetDlgItem(hdlg, 1798); - ShowWindow(h, SW_HIDE); - - /* Disable and hide the SCSI ID and LUN combo boxes. */ - h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - - h = GetDlgItem(hdlg, IDC_COMBO_HD_LUN); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - - /* Set the file name edit box contents to our existing parameters. */ - h = GetDlgItem(hdlg, IDC_EDIT_HD_FILE_NAME); - SendMessage(h, WM_SETTEXT, 0, (LPARAM) hdd[next_free_id].fn); - } - else - { - channel = next_free_ide_channel(); - next_free_scsi_id_and_lun(&id, &lun); - h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); - SendMessage(h, CB_SETCURSEL, 0, 0); - h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); - SendMessage(h, CB_SETCURSEL, id, 0); - h = GetDlgItem(hdlg, IDC_COMBO_HD_LUN); - SendMessage(h, CB_SETCURSEL, lun, 0); - h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); - SendMessage(h, CB_SETCURSEL, channel, 0); - - new_hdd.mfm_channel = next_free_binary_channel(&mfm_tracking); - new_hdd.esdi_channel = next_free_binary_channel(&esdi_tracking); - new_hdd.xtide_channel = next_free_binary_channel(&xtide_tracking); - new_hdd.ide_channel = channel; - new_hdd.scsi_id = id; - new_hdd.scsi_lun = lun; - } - h = GetDlgItem(hdlg, IDC_EDIT_HD_FILE_NAME); + no_update = 1; + spt = (existing & 1) ? 0 : 17; + set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); + hpc = (existing & 1) ? 0 : 15; + set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); + tracks = (existing & 1) ? 0 : 1023; + set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); + size = (tracks * hpc * spt) << 9; + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20LL)); + hdconf_initialize_hdt_combo(hdlg); + if (existing & 1) { + h = GetDlgItem(hdlg, IDC_EDIT_HD_SPT); EnableWindow(h, FALSE); - - h = GetDlgItem(hdlg, IDT_1752); + h = GetDlgItem(hdlg, IDC_EDIT_HD_HPC); EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - - h = GetDlgItem(hdlg, IDC_PBAR_IMG_CREATE); + h = GetDlgItem(hdlg, IDC_EDIT_HD_CYL); EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); + h = GetDlgItem(hdlg, IDC_EDIT_HD_SIZE); + EnableWindow(h, FALSE); + h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); + EnableWindow(h, FALSE); + chs_enabled = 0; + } else + chs_enabled = 1; + add_locations(hdlg); + h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); + hdd_ptr->bus = HDD_BUS_IDE; + max_spt = 63; + max_hpc = 255; + SendMessage(h, CB_SETCURSEL, hdd_ptr->bus, 0); + max_tracks = 266305; + recalc_location_controls(hdlg, 1, 0); - no_update = 0; - return TRUE; + channel = next_free_ide_channel(); + next_free_scsi_id(&id); + h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); + SendMessage(h, CB_SETCURSEL, 0, 0); + h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); + SendMessage(h, CB_SETCURSEL, id, 0); + h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); + SendMessage(h, CB_SETCURSEL, channel, 0); - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDOK: - if (!(existing & 2)) - { - h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); - hdd_ptr->bus = SendMessage(h, CB_GETCURSEL, 0, 0) + 1; - } + new_hdd.mfm_channel = next_free_binary_channel(&mfm_tracking); + new_hdd.esdi_channel = next_free_binary_channel(&esdi_tracking); + new_hdd.xta_channel = next_free_binary_channel(&xta_tracking); + new_hdd.ide_channel = channel; + new_hdd.scsi_id = id; - /* Make sure no file name is allowed with removable SCSI hard disks. */ - if ((wcslen(hd_file_name) == 0) && (hdd_ptr->bus != HDD_BUS_SCSI_REMOVABLE)) - { - hdd_ptr->bus = HDD_BUS_DISABLED; - settings_msgbox(MBX_ERROR, (wchar_t *)IDS_4112); - return TRUE; - } - else if ((wcslen(hd_file_name) == 0) && (hdd_ptr->bus == HDD_BUS_SCSI_REMOVABLE)) - { - /* Mark hard disk added but return empty - it will signify the disk was ejected. */ - hdd_ptr->spt = hdd_ptr->hpc = hdd_ptr->tracks = 0; - memset(hdd_ptr->fn, 0, sizeof(hdd_ptr->fn)); + h = GetDlgItem(hdlg, IDC_EDIT_HD_FILE_NAME); + EnableWindow(h, FALSE); - goto hd_add_ok_common; - } + h = GetDlgItem(hdlg, IDT_1752); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); - get_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, &(hdd_ptr->spt)); - get_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, &(hdd_ptr->hpc)); - get_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, &(hdd_ptr->tracks)); - spt = hdd_ptr->spt; - hpc = hdd_ptr->hpc; - tracks = hdd_ptr->tracks; + h = GetDlgItem(hdlg, IDC_PBAR_IMG_CREATE); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); - if (existing & 2) - { - if (hdd_ptr->bus == HDD_BUS_SCSI_REMOVABLE) - { - memset(hdd_ptr->prev_fn, 0, sizeof(hdd_ptr->prev_fn)); - wcscpy(hdd_ptr->prev_fn, hdd_ptr->fn); - } - } - else - { - switch(hdd_ptr->bus) - { - case HDD_BUS_MFM: - h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); - hdd_ptr->mfm_channel = SendMessage(h, CB_GETCURSEL, 0, 0); - break; - case HDD_BUS_ESDI: - h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); - hdd_ptr->esdi_channel = SendMessage(h, CB_GETCURSEL, 0, 0); - break; - case HDD_BUS_XTIDE: - h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); - hdd_ptr->xtide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); - break; - case HDD_BUS_IDE_PIO_ONLY: - case HDD_BUS_IDE_PIO_AND_DMA: - h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); - hdd_ptr->ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); - break; - case HDD_BUS_SCSI: - case HDD_BUS_SCSI_REMOVABLE: - h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); - hdd_ptr->scsi_id = SendMessage(h, CB_GETCURSEL, 0, 0); - h = GetDlgItem(hdlg, IDC_COMBO_HD_LUN); - hdd_ptr->scsi_lun = SendMessage(h, CB_GETCURSEL, 0, 0); - break; - } - } + no_update = 0; + return TRUE; - memset(hdd_ptr->fn, 0, sizeof(hdd_ptr->fn)); - wcscpy(hdd_ptr->fn, hd_file_name); + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); + hdd_ptr->bus = SendMessage(h, CB_GETCURSEL, 0, 0) + 1; - sector_size = 512; + /* Make sure no file name is allowed with removable SCSI hard disks. */ + if (wcslen(hd_file_name) == 0) { + hdd_ptr->bus = HDD_BUS_DISABLED; + settings_msgbox(MBX_ERROR, (wchar_t *)IDS_4112); + return TRUE; + } - if (!(existing & 1) && (wcslen(hd_file_name) > 0)) - { - f = _wfopen(hd_file_name, L"wb"); + get_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, &(hdd_ptr->spt)); + get_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, &(hdd_ptr->hpc)); + get_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, &(hdd_ptr->tracks)); + spt = hdd_ptr->spt; + hpc = hdd_ptr->hpc; + tracks = hdd_ptr->tracks; - if (image_is_hdi(hd_file_name)) - { - if (size >= 0x100000000ll) - { - fclose(f); - settings_msgbox(MBX_ERROR, (wchar_t *)IDS_4104); - return TRUE; - } + switch(hdd_ptr->bus) { + case HDD_BUS_MFM: + h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); + hdd_ptr->mfm_channel = SendMessage(h, CB_GETCURSEL, 0, 0); + break; + case HDD_BUS_ESDI: + h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); + hdd_ptr->esdi_channel = SendMessage(h, CB_GETCURSEL, 0, 0); + break; + case HDD_BUS_XTA: + h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); + hdd_ptr->xta_channel = SendMessage(h, CB_GETCURSEL, 0, 0); + break; + case HDD_BUS_IDE: + h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); + hdd_ptr->ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); + break; + case HDD_BUS_SCSI: + h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); + hdd_ptr->scsi_id = SendMessage(h, CB_GETCURSEL, 0, 0); + break; + } - fwrite(&zero, 1, 4, f); /* 00000000: Zero/unknown */ - fwrite(&zero, 1, 4, f); /* 00000004: Zero/unknown */ - fwrite(&base, 1, 4, f); /* 00000008: Offset at which data starts */ - fwrite(&size, 1, 4, f); /* 0000000C: Full size of the data (32-bit) */ - fwrite(§or_size, 1, 4, f); /* 00000010: Sector size in bytes */ - fwrite(&spt, 1, 4, f); /* 00000014: Sectors per cylinder */ - fwrite(&hpc, 1, 4, f); /* 00000018: Heads per cylinder */ - fwrite(&tracks, 1, 4, f); /* 0000001C: Cylinders */ + memset(hdd_ptr->fn, 0, sizeof(hdd_ptr->fn)); + wcscpy(hdd_ptr->fn, hd_file_name); - for (i = 0; i < 0x3f8; i++) - { - fwrite(&zero, 1, 4, f); - } - } - else if (image_is_hdx(hd_file_name, 0)) - { - if (size > 0xffffffffffffffffll) - { - fclose(f); - settings_msgbox(MBX_ERROR, (wchar_t *)IDS_4105); - return TRUE; - } + sector_size = 512; - fwrite(&signature, 1, 8, f); /* 00000000: Signature */ - fwrite(&size, 1, 8, f); /* 00000008: Full size of the data (64-bit) */ - fwrite(§or_size, 1, 4, f); /* 00000010: Sector size in bytes */ - fwrite(&spt, 1, 4, f); /* 00000014: Sectors per cylinder */ - fwrite(&hpc, 1, 4, f); /* 00000018: Heads per cylinder */ - fwrite(&tracks, 1, 4, f); /* 0000001C: Cylinders */ - fwrite(&zero, 1, 4, f); /* 00000020: [Translation] Sectors per cylinder */ - fwrite(&zero, 1, 4, f); /* 00000004: [Translation] Heads per cylinder */ - } - - memset(buf, 0, 512); - - r = size >> 20; - size &= 0xfffff; - - if (size || r) { - h = GetDlgItem(hdlg, IDT_1731); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - - h = GetDlgItem(hdlg, IDC_EDIT_HD_FILE_NAME); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - - h = GetDlgItem(hdlg, IDC_CFILE); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - - h = GetDlgItem(hdlg, IDC_PBAR_IMG_CREATE); - EnableWindow(h, TRUE); - ShowWindow(h, SW_SHOW); - SendMessage(h, PBM_SETRANGE32, (WPARAM) 0, (LPARAM) r); - SendMessage(h, PBM_SETPOS, (WPARAM) 0, (LPARAM) 0); - - h = GetDlgItem(hdlg, IDT_1752); - EnableWindow(h, TRUE); - ShowWindow(h, SW_SHOW); - } - - if (size) - { - fwrite(buf, 1, size, f); - SendMessage(h, PBM_SETPOS, (WPARAM) 1, (LPARAM) 0); - } - - if (r) - { - big_buf = (char *) malloc(1048576); - memset(big_buf, 0, 1048576); - for (i = 0; i < r; i++) - { - fwrite(big_buf, 1, 1048576, f); - SendMessage(h, PBM_SETPOS, (WPARAM) (size + 1), (LPARAM) 0); - } - free(big_buf); - } + if (!(existing & 1) && (wcslen(hd_file_name) > 0)) { + f = _wfopen(hd_file_name, L"wb"); + if (size > 0x1FFFFFFE00ll) { fclose(f); - settings_msgbox(MBX_INFO, (wchar_t *)IDS_4113); + settings_msgbox(MBX_ERROR, (wchar_t *)IDS_4105); + return TRUE; } -hd_add_ok_common: - hard_disk_added = 1; - EndDialog(hdlg, 0); - return TRUE; - - case IDCANCEL: - hard_disk_added = 0; - if (!(existing & 2)) - { - hdd_ptr->bus = HDD_BUS_DISABLED; - } - EndDialog(hdlg, 0); - return TRUE; - - case IDC_CFILE: - if (!file_dlg_w(hdlg, plat_get_string(IDS_4106), L"", !(existing & 1))) - { - if (!wcschr(wopenfilestring, L'.')) { - if (wcslen(wopenfilestring) && (wcslen(wopenfilestring) <= 256)) { - twcs = &wopenfilestring[wcslen(wopenfilestring)]; - twcs[0] = L'.'; - twcs[1] = L'i'; - twcs[2] = L'm'; - twcs[3] = L'g'; - } - } - - if (!(existing & 1)) - { - f = _wfopen(wopenfilestring, L"rb"); - if (f != NULL) - { - fclose(f); - if (settings_msgbox(MBX_QUESTION, (wchar_t *)IDS_4111) != 0) /* yes */ - { - return FALSE; - } - } - } - - f = _wfopen(wopenfilestring, (existing & 1) ? L"rb" : L"wb"); - if (f == NULL) - { -hdd_add_file_open_error: - settings_msgbox(MBX_ERROR, (existing & 1) ? (wchar_t *)IDS_4107 : (wchar_t *)IDS_4108); + if (image_is_hdi(hd_file_name)) { + if (size >= 0x100000000ll) { + fclose(f); + settings_msgbox(MBX_ERROR, (wchar_t *)IDS_4104); return TRUE; } - if (existing & 1) - { - if (image_is_hdi(wopenfilestring) || image_is_hdx(wopenfilestring, 1)) - { - fseeko64(f, 0x10, SEEK_SET); - fread(§or_size, 1, 4, f); - if (sector_size != 512) - { - settings_msgbox(MBX_ERROR, (wchar_t *)IDS_4109); - fclose(f); - return TRUE; - } - spt = hpc = tracks = 0; - fread(&spt, 1, 4, f); - fread(&hpc, 1, 4, f); - fread(&tracks, 1, 4, f); - } - else - { - fseeko64(f, 0, SEEK_END); - size = ftello64(f); - fclose(f); - if (((size % 17) == 0) && (size <= 142606336)) - { - spt = 17; - if (size <= 26738688) - { - hpc = 4; - } - else if (((size % 3072) == 0) && (size <= 53477376)) - { - hpc = 6; - } - else - { - for (i = 5; i < 16; i++) - { - if (((size % (i << 9)) == 0) && (size <= ((i * 17) << 19))) - { - break; - } - if (i == 5) - { - i++; - } - } - hpc = i; - } - } - else - { - spt = 63; - hpc = 16; - } - tracks = ((size >> 9) / hpc) / spt; - } + fwrite(&zero, 1, 4, f); /* 00000000: Zero/unknown */ + fwrite(&zero, 1, 4, f); /* 00000004: Zero/unknown */ + fwrite(&base, 1, 4, f); /* 00000008: Offset at which data starts */ + fwrite(&size, 1, 4, f); /* 0000000C: Full size of the data (32-bit) */ + fwrite(§or_size, 1, 4, f); /* 00000010: Sector size in bytes */ + fwrite(&spt, 1, 4, f); /* 00000014: Sectors per cylinder */ + fwrite(&hpc, 1, 4, f); /* 00000018: Heads per cylinder */ + fwrite(&tracks, 1, 4, f); /* 0000001C: Cylinders */ - if ((spt > max_spt) || (hpc > max_hpc) || (tracks > max_tracks)) - { - goto hdd_add_file_open_error; - } - no_update = 1; - - set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); - set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); - set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, size >> 20); - recalc_selection(hdlg); - - h = GetDlgItem(hdlg, IDC_EDIT_HD_SPT); - EnableWindow(h, TRUE); - h = GetDlgItem(hdlg, IDC_EDIT_HD_HPC); - EnableWindow(h, TRUE); - h = GetDlgItem(hdlg, IDC_EDIT_HD_CYL); - EnableWindow(h, TRUE); - h = GetDlgItem(hdlg, IDC_EDIT_HD_SIZE); - EnableWindow(h, TRUE); - h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); - EnableWindow(h, TRUE); - - chs_enabled = 1; - - no_update = 0; + for (i = 0; i < 0x3f8; i++) + fwrite(&zero, 1, 4, f); + } else if (image_is_hdx(hd_file_name, 0)) { + fwrite(&signature, 1, 8, f); /* 00000000: Signature */ + fwrite(&size, 1, 8, f); /* 00000008: Full size of the data (64-bit) */ + fwrite(§or_size, 1, 4, f); /* 00000010: Sector size in bytes */ + fwrite(&spt, 1, 4, f); /* 00000014: Sectors per cylinder */ + fwrite(&hpc, 1, 4, f); /* 00000018: Heads per cylinder */ + fwrite(&tracks, 1, 4, f); /* 0000001C: Cylinders */ + fwrite(&zero, 1, 4, f); /* 00000020: [Translation] Sectors per cylinder */ + fwrite(&zero, 1, 4, f); /* 00000004: [Translation] Heads per cylinder */ } - else - { - fclose(f); + + memset(buf, 0, 512); + + temp_size = size; + + r = size >> 20; + size &= 0xfffff; + + if (size || r) { + h = GetDlgItem(hdlg, IDT_1731); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + + h = GetDlgItem(hdlg, IDC_EDIT_HD_FILE_NAME); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + + h = GetDlgItem(hdlg, IDC_CFILE); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + + h = GetDlgItem(hdlg, IDC_PBAR_IMG_CREATE); + EnableWindow(h, TRUE); + ShowWindow(h, SW_SHOW); + SendMessage(h, PBM_SETRANGE32, (WPARAM) 0, (LPARAM) r); + SendMessage(h, PBM_SETPOS, (WPARAM) 0, (LPARAM) 0); + + h = GetDlgItem(hdlg, IDT_1752); + EnableWindow(h, TRUE); + ShowWindow(h, SW_SHOW); + } + + if (size) { + fwrite(buf, 1, size, f); + SendMessage(h, PBM_SETPOS, (WPARAM) 1, (LPARAM) 0); + } + + if (r) { + big_buf = (char *) malloc(1048576); + memset(big_buf, 0, 1048576); + for (i = 0; i < r; i++) { + fwrite(big_buf, 1, 1048576, f); + SendMessage(h, PBM_SETPOS, (WPARAM) (size + 1), (LPARAM) 0); + } + free(big_buf); + } + + if (image_is_vhd(hd_file_name, 0)) { + /* VHD image. */ + /* Generate new footer. */ + new_vhd_footer(&vft); + vft->orig_size = vft->curr_size = temp_size; + vft->geom.cyl = tracks; + vft->geom.heads = hpc; + vft->geom.spt = spt; + generate_vhd_checksum(vft); + memset(buf, 0, 512); + vhd_footer_to_bytes((uint8_t *) buf, vft); + fwrite(buf, 1, 512, f); + memset(buf, 0, 512); + free(vft); + vft = NULL; + } + + fclose(f); + settings_msgbox(MBX_INFO, (wchar_t *)IDS_4113); + } + + hard_disk_added = 1; + EndDialog(hdlg, 0); + return TRUE; + + case IDCANCEL: + hard_disk_added = 0; + hdd_ptr->bus = HDD_BUS_DISABLED; + EndDialog(hdlg, 0); + return TRUE; + + case IDC_CFILE: + if (!file_dlg_w(hdlg, plat_get_string(IDS_4106), L"", !(existing & 1))) { + if (!wcschr(wopenfilestring, L'.')) { + if (wcslen(wopenfilestring) && (wcslen(wopenfilestring) <= 256)) { + twcs = &wopenfilestring[wcslen(wopenfilestring)]; + twcs[0] = L'.'; + twcs[1] = L'i'; + twcs[2] = L'm'; + twcs[3] = L'g'; } } - h = GetDlgItem(hdlg, IDC_EDIT_HD_FILE_NAME); - SendMessage(h, WM_SETTEXT, 0, (LPARAM) wopenfilestring); - memset(hd_file_name, 0, sizeof(hd_file_name)); - wcscpy(hd_file_name, wopenfilestring); - - return TRUE; - - case IDC_EDIT_HD_CYL: - if (no_update) - { - return FALSE; + if (!(existing & 1)) { + f = _wfopen(wopenfilestring, L"rb"); + if (f != NULL) { + fclose(f); + if (settings_msgbox(MBX_QUESTION, (wchar_t *)IDS_4111) != 0) /* yes */ + return FALSE; + } } - no_update = 1; - get_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, &temp); - if (temp != tracks) - { - tracks = temp; - size = (tracks * hpc * spt) << 9; - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, size >> 20); - recalc_selection(hdlg); + f = _wfopen(wopenfilestring, (existing & 1) ? L"rb" : L"wb"); + if (f == NULL) { +hdd_add_file_open_error: + settings_msgbox(MBX_ERROR, (existing & 1) ? (wchar_t *)IDS_4107 : (wchar_t *)IDS_4108); + return TRUE; } - - if (tracks > max_tracks) - { - tracks = max_tracks; - size = (tracks * hpc * spt) << 9; - set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); - recalc_selection(hdlg); - } - - no_update = 0; - break; - - case IDC_EDIT_HD_HPC: - if (no_update) - { - return FALSE; - } - - no_update = 1; - get_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, &temp); - if (temp != hpc) - { - hpc = temp; - size = (tracks * hpc * spt) << 9; - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, size >> 20); - recalc_selection(hdlg); - } - - if (hpc > max_hpc) - { - hpc = max_hpc; - size = (tracks * hpc * spt) << 9; - set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); - recalc_selection(hdlg); - } - - no_update = 0; - break; - - case IDC_EDIT_HD_SPT: - if (no_update) - { - return FALSE; - } - - no_update = 1; - get_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, &temp); - if (temp != spt) - { - spt = temp; - size = (tracks * hpc * spt) << 9; - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, size >> 20); - recalc_selection(hdlg); - } - - if (spt > max_spt) - { - spt = max_spt; - size = (tracks * hpc * spt) << 9; - set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); - recalc_selection(hdlg); - } - - no_update = 0; - break; - - case IDC_EDIT_HD_SIZE: - if (no_update) - { - return FALSE; - } - - no_update = 1; - get_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, &temp); - if (temp != (size >> 20)) - { - size = temp << 20; - tracks = ((size >> 9) / hpc) / spt; - set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); - recalc_selection(hdlg); - } - - if (tracks > max_tracks) - { - tracks = max_tracks; - size = (tracks * hpc * spt) << 9; - set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); - recalc_selection(hdlg); - } - - no_update = 0; - break; - - case IDC_COMBO_HD_TYPE: - if (no_update) - { - return FALSE; - } - - no_update = 1; - get_combo_box_selection(hdlg, IDC_COMBO_HD_TYPE, &temp); - if ((temp != selection) && (temp != 127) && (temp != 128)) - { - selection = temp; - tracks = hdd_table[selection][0]; - hpc = hdd_table[selection][1]; - spt = hdd_table[selection][2]; - size = (tracks * hpc * spt) << 9; - set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); - set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, size >> 20); - } - else if ((temp != selection) && (temp == 127)) - { - selection = temp; - } - else if ((temp != selection) && (temp == 128)) - { - selection = temp; - hpc = 16; - spt = 63; - size = (tracks * hpc * spt) << 9; - set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, size >> 20); - } - - if (spt > max_spt) - { - spt = max_spt; - size = (tracks * hpc * spt) << 9; - set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); - recalc_selection(hdlg); - } - - if (hpc > max_hpc) - { - hpc = max_hpc; - size = (tracks * hpc * spt) << 9; - set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); - recalc_selection(hdlg); - } - - if (tracks > max_tracks) - { - tracks = max_tracks; - size = (tracks * hpc * spt) << 9; - set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); - recalc_selection(hdlg); - } - - no_update = 0; - break; - - case IDC_COMBO_HD_BUS: - if (no_update) - { - return FALSE; - } - - no_update = 1; - recalc_location_controls(hdlg, 1, 0); - h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); - b = SendMessage(h,CB_GETCURSEL,0,0) + 1; - if (b == hdd_ptr->bus) - { - goto hd_add_bus_skip; - } - - hdd_ptr->bus = b; - - switch(hdd_ptr->bus) - { - case HDD_BUS_DISABLED: - default: - max_spt = max_hpc = max_tracks = 0; - break; - case HDD_BUS_MFM: - max_spt = 17; - max_hpc = 15; - max_tracks = 1023; - break; - case HDD_BUS_ESDI: - case HDD_BUS_XTIDE: - max_spt = 63; - max_hpc = 16; - max_tracks = 1023; - break; - case HDD_BUS_IDE_PIO_ONLY: - case HDD_BUS_IDE_PIO_AND_DMA: - max_spt = 63; - max_hpc = 255; - max_tracks = 266305; - break; - case HDD_BUS_SCSI_REMOVABLE: - if (spt == 0) - { + if (existing & 1) { + if (image_is_hdi(wopenfilestring) || image_is_hdx(wopenfilestring, 1)) { + fseeko64(f, 0x10, SEEK_SET); + fread(§or_size, 1, 4, f); + if (sector_size != 512) { + settings_msgbox(MBX_ERROR, (wchar_t *)IDS_4109); + fclose(f); + return TRUE; + } + spt = hpc = tracks = 0; + fread(&spt, 1, 4, f); + fread(&hpc, 1, 4, f); + fread(&tracks, 1, 4, f); + } else if (image_is_vhd(wopenfilestring, 1)) { + fseeko64(f, -512, SEEK_END); + fread(buf, 1, 512, f); + new_vhd_footer(&vft); + vhd_footer_from_bytes(vft, (uint8_t *) buf); + size = vft->orig_size; + tracks = vft->geom.cyl; + hpc = vft->geom.heads; + spt = vft->geom.spt; + free(vft); + vft = NULL; + } else { + fseeko64(f, 0, SEEK_END); + size = ftello64(f); + fclose(f); + if (((size % 17) == 0) && (size <= 142606336)) { + spt = 17; + if (size <= 26738688) + hpc = 4; + else if (((size % 3072) == 0) && (size <= 53477376)) + hpc = 6; + else { + for (i = 5; i < 16; i++) { + if (((size % (i << 9)) == 0) && (size <= ((i * 17) << 19))) + break; + if (i == 5) + i++; + } + hpc = i; + } + } else { spt = 63; - size = (tracks * hpc * spt) << 9; - set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); - } - if (hpc == 0) - { hpc = 16; - size = (tracks * hpc * spt) << 9; - set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); } - if (tracks == 0) - { - tracks = 1023; - size = (tracks * hpc * spt) << 9; - set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); - } - case HDD_BUS_SCSI: - max_spt = 99; - max_hpc = 255; - max_tracks = 266305; - break; - } - if ((hdd_ptr->bus == HDD_BUS_SCSI_REMOVABLE) && !chs_enabled) - { - h = GetDlgItem(hdlg, IDC_EDIT_HD_SPT); - EnableWindow(h, TRUE); - h = GetDlgItem(hdlg, IDC_EDIT_HD_HPC); - EnableWindow(h, TRUE); - h = GetDlgItem(hdlg, IDC_EDIT_HD_CYL); - EnableWindow(h, TRUE); - h = GetDlgItem(hdlg, IDC_EDIT_HD_SIZE); - EnableWindow(h, TRUE); - h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); - EnableWindow(h, TRUE); - } - else if ((hdd_ptr->bus != HDD_BUS_SCSI_REMOVABLE) && !chs_enabled) - { - h = GetDlgItem(hdlg, IDC_EDIT_HD_SPT); - EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_EDIT_HD_HPC); - EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_EDIT_HD_CYL); - EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_EDIT_HD_SIZE); - EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); - EnableWindow(h, FALSE); - } + tracks = ((size >> 9) / hpc) / spt; + } + + if ((spt > max_spt) || (hpc > max_hpc) || (tracks > max_tracks)) + goto hdd_add_file_open_error; + no_update = 1; - if (spt > max_spt) - { - spt = max_spt; - size = (tracks * hpc * spt) << 9; set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); - recalc_selection(hdlg); - } - - if (hpc > max_hpc) - { - hpc = max_hpc; - size = (tracks * hpc * spt) << 9; set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); - recalc_selection(hdlg); - } - - if (tracks > max_tracks) - { - tracks = max_tracks; - size = (tracks * hpc * spt) << 9; set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); - set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, size >> 20); recalc_selection(hdlg); - } + + h = GetDlgItem(hdlg, IDC_EDIT_HD_SPT); + EnableWindow(h, TRUE); + h = GetDlgItem(hdlg, IDC_EDIT_HD_HPC); + EnableWindow(h, TRUE); + h = GetDlgItem(hdlg, IDC_EDIT_HD_CYL); + EnableWindow(h, TRUE); + h = GetDlgItem(hdlg, IDC_EDIT_HD_SIZE); + EnableWindow(h, TRUE); + h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); + EnableWindow(h, TRUE); + + chs_enabled = 1; + + no_update = 0; + } else + fclose(f); + } + + h = GetDlgItem(hdlg, IDC_EDIT_HD_FILE_NAME); + SendMessage(h, WM_SETTEXT, 0, (LPARAM) wopenfilestring); + memset(hd_file_name, 0, sizeof(hd_file_name)); + wcscpy(hd_file_name, wopenfilestring); + + return TRUE; + + case IDC_EDIT_HD_CYL: + if (no_update) + return FALSE; + + no_update = 1; + get_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, &temp); + if (tracks != (int64_t) temp) { + tracks = temp; + size = (tracks * hpc * spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } + + if (tracks > max_tracks) { + tracks = max_tracks; + size = (tracks * hpc * spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } + + no_update = 0; + break; + + case IDC_EDIT_HD_HPC: + if (no_update) + return FALSE; + + no_update = 1; + get_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, &temp); + if (hpc != (int64_t) temp) { + hpc = temp; + size = (tracks * hpc * spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } + + if (hpc > max_hpc) { + hpc = max_hpc; + size = (tracks * hpc * spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } + + no_update = 0; + break; + + case IDC_EDIT_HD_SPT: + if (no_update) + return FALSE; + + no_update = 1; + get_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, &temp); + if (spt != (int64_t) temp) { + spt = temp; + size = (tracks * hpc * spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } + + if (spt > max_spt) { + spt = max_spt; + size = (tracks * hpc * spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } + + no_update = 0; + break; + + case IDC_EDIT_HD_SIZE: + if (no_update) + return FALSE; + + no_update = 1; + get_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, &temp); + if (temp != (uint32_t) (size >> 20)) { + size = ((uint64_t) temp) << 20LL; + /* This is needed to ensure VHD standard compliance. */ + hdd_image_calc_chs((uint32_t *) &tracks, (uint32_t *) &hpc, (uint32_t *) &spt, temp); + set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); + set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); + recalc_selection(hdlg); + } + + if (tracks > max_tracks) { + tracks = max_tracks; + size = (tracks * hpc * spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } + + if (hpc > max_hpc) { + hpc = max_hpc; + size = (tracks * hpc * spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } + + if (spt > max_spt) { + spt = max_spt; + size = (tracks * hpc * spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } + + no_update = 0; + break; + + case IDC_COMBO_HD_TYPE: + if (no_update) + return FALSE; + + no_update = 1; + get_combo_box_selection(hdlg, IDC_COMBO_HD_TYPE, &temp); + if ((temp != selection) && (temp != 127) && (temp != 128)) { + selection = temp; + tracks = hdd_table[selection][0]; + hpc = hdd_table[selection][1]; + spt = hdd_table[selection][2]; + size = (tracks * hpc * spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); + set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + } else if ((temp != selection) && (temp == 127)) + selection = temp; + else if ((temp != selection) && (temp == 128)) { + selection = temp; + hpc = 16; + spt = 63; + size = (tracks * hpc * spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + } + + if (spt > max_spt) { + spt = max_spt; + size = (tracks * hpc * spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } + + if (hpc > max_hpc) { + hpc = max_hpc; + size = (tracks * hpc * spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } + + if (tracks > max_tracks) { + tracks = max_tracks; + size = (tracks * hpc * spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } + + no_update = 0; + break; + + case IDC_COMBO_HD_BUS: + if (no_update) + return FALSE; + + no_update = 1; + recalc_location_controls(hdlg, 1, 0); + h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); + b = SendMessage(h,CB_GETCURSEL,0,0) + 1; + if (b == hdd_ptr->bus) + goto hd_add_bus_skip; + + hdd_ptr->bus = b; + + switch(hdd_ptr->bus) { + case HDD_BUS_DISABLED: + default: + max_spt = max_hpc = max_tracks = 0; + break; + case HDD_BUS_MFM: + max_spt = 17; + max_hpc = 15; + max_tracks = 1023; + break; + case HDD_BUS_ESDI: + case HDD_BUS_XTA: + max_spt = 63; + max_hpc = 16; + max_tracks = 1023; + break; + case HDD_BUS_IDE: + max_spt = 63; + max_hpc = 255; + max_tracks = 266305; + break; + case HDD_BUS_SCSI: + max_spt = 99; + max_hpc = 255; + max_tracks = 266305; + break; + } + + if (!chs_enabled) { + h = GetDlgItem(hdlg, IDC_EDIT_HD_SPT); + EnableWindow(h, FALSE); + h = GetDlgItem(hdlg, IDC_EDIT_HD_HPC); + EnableWindow(h, FALSE); + h = GetDlgItem(hdlg, IDC_EDIT_HD_CYL); + EnableWindow(h, FALSE); + h = GetDlgItem(hdlg, IDC_EDIT_HD_SIZE); + EnableWindow(h, FALSE); + h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); + EnableWindow(h, FALSE); + } + + if (spt > max_spt) { + spt = max_spt; + size = (tracks * hpc * spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } + + if (hpc > max_hpc) { + hpc = max_hpc; + size = (tracks * hpc * spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } + + if (tracks > max_tracks) { + tracks = max_tracks; + size = (tracks * hpc * spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); + set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (uint32_t) (size >> 20)); + recalc_selection(hdlg); + } hd_add_bus_skip: - no_update = 0; - break; - } + no_update = 0; + break; + } - return FALSE; - } + return FALSE; + } - return FALSE; + return FALSE; } -int hard_disk_was_added(void) + +int +hard_disk_was_added(void) { - return hard_disk_added; + return hard_disk_added; } -void hard_disk_add_open(HWND hwnd, int is_existing) + +void +hard_disk_add_open(HWND hwnd, int is_existing) { - existing = is_existing; - hard_disk_added = 0; - DialogBox(hinstance, (LPCWSTR)DLG_CFG_HARD_DISKS_ADD, hwnd, win_settings_hard_disks_add_proc); + existing = is_existing; + hard_disk_added = 0; + DialogBox(hinstance, (LPCWSTR)DLG_CFG_HARD_DISKS_ADD, hwnd, win_settings_hard_disks_add_proc); } -static void hard_disk_track(uint8_t id) + +static void +hard_disk_track(uint8_t id) { - switch(temp_hdd[id].bus) { - case HDD_BUS_MFM: - mfm_tracking |= (1 << (temp_hdd[id].mfm_channel << 3)); - break; - case HDD_BUS_ESDI: - esdi_tracking |= (1 << (temp_hdd[id].esdi_channel << 3)); - break; - case HDD_BUS_XTIDE: - xtide_tracking |= (1 << (temp_hdd[id].xtide_channel << 3)); - break; - case HDD_BUS_IDE_PIO_ONLY: - case HDD_BUS_IDE_PIO_AND_DMA: - ide_tracking |= (1 << (temp_hdd[id].ide_channel << 3)); - break; - case HDD_BUS_SCSI: - case HDD_BUS_SCSI_REMOVABLE: - scsi_tracking[temp_hdd[id].scsi_id] |= (1 << (temp_hdd[id].scsi_lun << 3)); - break; - } + switch(temp_hdd[id].bus) { + case HDD_BUS_MFM: + mfm_tracking |= (1 << (temp_hdd[id].mfm_channel << 3)); + break; + case HDD_BUS_ESDI: + esdi_tracking |= (1 << (temp_hdd[id].esdi_channel << 3)); + break; + case HDD_BUS_XTA: + xta_tracking |= (1 << (temp_hdd[id].xta_channel << 3)); + break; + case HDD_BUS_IDE: + ide_tracking |= (1 << (temp_hdd[id].ide_channel << 3)); + break; + case HDD_BUS_SCSI: + scsi_tracking[temp_hdd[id].scsi_id >> 3] |= (1 << ((temp_hdd[id].scsi_id & 0x07) << 3)); + break; + } } -static void hard_disk_untrack(uint8_t id) + +static void +hard_disk_untrack(uint8_t id) { - switch(temp_hdd[id].bus) { - case HDD_BUS_MFM: - mfm_tracking &= ~(1 << (temp_hdd[id].mfm_channel << 3)); - break; - case HDD_BUS_ESDI: - esdi_tracking &= ~(1 << (temp_hdd[id].esdi_channel << 3)); - break; - case HDD_BUS_XTIDE: - xtide_tracking &= ~(1 << (temp_hdd[id].xtide_channel << 3)); - break; - case HDD_BUS_IDE_PIO_ONLY: - case HDD_BUS_IDE_PIO_AND_DMA: - ide_tracking &= ~(1 << (temp_hdd[id].ide_channel << 3)); - break; - case HDD_BUS_SCSI: - case HDD_BUS_SCSI_REMOVABLE: - scsi_tracking[temp_hdd[id].scsi_id] &= ~(1 << (temp_hdd[id].scsi_lun << 3)); - break; - } + switch(temp_hdd[id].bus) { + case HDD_BUS_MFM: + mfm_tracking &= ~(1 << (temp_hdd[id].mfm_channel << 3)); + break; + case HDD_BUS_ESDI: + esdi_tracking &= ~(1 << (temp_hdd[id].esdi_channel << 3)); + break; + case HDD_BUS_XTA: + xta_tracking &= ~(1 << (temp_hdd[id].xta_channel << 3)); + break; + case HDD_BUS_IDE: + ide_tracking &= ~(1 << (temp_hdd[id].ide_channel << 3)); + break; + case HDD_BUS_SCSI: + scsi_tracking[temp_hdd[id].scsi_id >> 3] &= ~(1 << ((temp_hdd[id].scsi_id & 0x07) << 3)); + break; + } } -static void hard_disk_track_all(void) + +static void +hard_disk_track_all(void) { - int i; + int i; - for (i = 0; i < HDD_NUM; i++) - hard_disk_track(i); + for (i = 0; i < HDD_NUM; i++) + hard_disk_track(i); } -int ignore_change = 0; #ifdef __amd64__ static LRESULT CALLBACK @@ -3567,679 +3057,210 @@ static BOOL CALLBACK #endif win_settings_hard_disks_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - HWND h; - int old_sel = 0; - int b = 0; - int assign = 0; + HWND h; + int old_sel = 0, b = 0, assign = 0; + const uint8_t hd_icons[2] = { 64, 0 }; - switch (message) - { - case WM_INITDIALOG: - ignore_change = 1; + switch (message) { + case WM_INITDIALOG: + ignore_change = 1; - normalize_hd_list(); /* Normalize the hard disks so that non-disabled hard disks start from index 0, and so they are contiguous. - This will cause an emulator reset prompt on the first opening of this category with a messy hard disk list - (which can only happen by manually editing the configuration file). */ - h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); - win_settings_hard_disks_init_columns(h); - win_settings_hard_disks_image_list_init(h); - win_settings_hard_disks_recalc_list(h); - recalc_next_free_id(hdlg); - add_locations(hdlg); - if (hd_listview_items > 0) - { - ListView_SetItemState(h, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); - hdlv_current_sel = 0; - h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); - SendMessage(h, CB_SETCURSEL, temp_hdd[0].bus - 1, 0); - } - else - { - hdlv_current_sel = -1; - } - recalc_location_controls(hdlg, 0, 0); - - ignore_change = 0; - return TRUE; + normalize_hd_list(); /* Normalize the hard disks so that non-disabled hard disks start from index 0, and so they are contiguous. + This will cause an emulator reset prompt on the first opening of this category with a messy hard disk list + (which can only happen by manually editing the configuration file). */ + h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); + win_settings_hard_disks_init_columns(h); + image_list_init(h, (const uint8_t *) hd_icons); + win_settings_hard_disks_recalc_list(h); + recalc_next_free_id(hdlg); + add_locations(hdlg); + if (hd_listview_items > 0) { + ListView_SetItemState(h, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); + lv1_current_sel = 0; + h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); + SendMessage(h, CB_SETCURSEL, temp_hdd[0].bus - 1, 0); + } else + lv1_current_sel = -1; + recalc_location_controls(hdlg, 0, 0); - case WM_NOTIFY: - if ((hd_listview_items == 0) || ignore_change) - { + ignore_change = 0; + return TRUE; + + case WM_NOTIFY: + if ((hd_listview_items == 0) || ignore_change) + return FALSE; + + if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_HARD_DISKS)) { + old_sel = lv1_current_sel; + lv1_current_sel = get_selected_hard_disk(hdlg); + if (lv1_current_sel == old_sel) + return FALSE; + else if (lv1_current_sel == -1) { + ignore_change = 1; + lv1_current_sel = old_sel; + ListView_SetItemState(h, lv1_current_sel, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); + ignore_change = 0; return FALSE; } + ignore_change = 1; + h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); + SendMessage(h, CB_SETCURSEL, temp_hdd[lv1_current_sel].bus - 1, 0); + recalc_location_controls(hdlg, 0, 0); + ignore_change = 0; + } + break; - if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_HARD_DISKS)) - { - old_sel = hdlv_current_sel; - hdlv_current_sel = get_selected_hard_disk(hdlg); - if (hdlv_current_sel == old_sel) - { - return FALSE; - } - else if (hdlv_current_sel == -1) - { - ignore_change = 1; - hdlv_current_sel = old_sel; - ListView_SetItemState(h, hdlv_current_sel, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); - ignore_change = 0; - return FALSE; - } + case WM_COMMAND: + if (ignore_change && (LOWORD(wParam) != IDC_BUTTON_HDD_ADD) && + (LOWORD(wParam) != IDC_BUTTON_HDD_ADD_NEW) && (LOWORD(wParam) != IDC_BUTTON_HDD_REMOVE)) + return FALSE; + switch (LOWORD(wParam)) { + case IDC_COMBO_HD_BUS: ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); - SendMessage(h, CB_SETCURSEL, temp_hdd[hdlv_current_sel].bus - 1, 0); - recalc_location_controls(hdlg, 0, 0); - ignore_change = 0; - } - break; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDC_COMBO_HD_BUS: - if (ignore_change) - { - return FALSE; - } - - ignore_change = 1; - h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); - b = SendMessage(h, CB_GETCURSEL, 0, 0) + 1; - if (b == temp_hdd[hdlv_current_sel].bus) - { - goto hd_bus_skip; - } - hard_disk_untrack(hdlv_current_sel); - assign = (temp_hdd[hdlv_current_sel].bus == b) ? 0 : 1; - if ((b == HDD_BUS_IDE_PIO_ONLY) && (temp_hdd[hdlv_current_sel].bus == HDD_BUS_IDE_PIO_AND_DMA)) - assign = 0; - else if ((b == HDD_BUS_IDE_PIO_AND_DMA) && (temp_hdd[hdlv_current_sel].bus == HDD_BUS_IDE_PIO_ONLY)) - assign = 0; - temp_hdd[hdlv_current_sel].bus = b; - recalc_location_controls(hdlg, 0, assign); - hard_disk_track(hdlv_current_sel); - h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); - win_settings_hard_disks_update_item(h, hdlv_current_sel, 0); + b = SendMessage(h, CB_GETCURSEL, 0, 0) + 1; + if (b == temp_hdd[lv1_current_sel].bus) + goto hd_bus_skip; + hard_disk_untrack(lv1_current_sel); + assign = (temp_hdd[lv1_current_sel].bus == b) ? 0 : 1; + temp_hdd[lv1_current_sel].bus = b; + recalc_location_controls(hdlg, 0, assign); + hard_disk_track(lv1_current_sel); + h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); + win_settings_hard_disks_update_item(h, lv1_current_sel, 0); hd_bus_skip: - ignore_change = 0; - return FALSE; + ignore_change = 0; + return FALSE; - case IDC_COMBO_HD_CHANNEL: - if (ignore_change) - { - return FALSE; - } + case IDC_COMBO_HD_CHANNEL: + ignore_change = 1; + h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); + hard_disk_untrack(lv1_current_sel); + if (temp_hdd[lv1_current_sel].bus == HDD_BUS_MFM) + temp_hdd[lv1_current_sel].mfm_channel = SendMessage(h, CB_GETCURSEL, 0, 0); + else if (temp_hdd[lv1_current_sel].bus == HDD_BUS_ESDI) + temp_hdd[lv1_current_sel].esdi_channel = SendMessage(h, CB_GETCURSEL, 0, 0); + else if (temp_hdd[lv1_current_sel].bus == HDD_BUS_XTA) + temp_hdd[lv1_current_sel].xta_channel = SendMessage(h, CB_GETCURSEL, 0, 0); + hard_disk_track(lv1_current_sel); + h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); + win_settings_hard_disks_update_item(h, lv1_current_sel, 0); + ignore_change = 0; + return FALSE; - ignore_change = 1; - h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); - hard_disk_untrack(hdlv_current_sel); - if (temp_hdd[hdlv_current_sel].bus == HDD_BUS_MFM) - { - temp_hdd[hdlv_current_sel].mfm_channel = SendMessage(h, CB_GETCURSEL, 0, 0); - } - else if (temp_hdd[hdlv_current_sel].bus == HDD_BUS_ESDI) - { - temp_hdd[hdlv_current_sel].esdi_channel = SendMessage(h, CB_GETCURSEL, 0, 0); - } - else if (temp_hdd[hdlv_current_sel].bus == HDD_BUS_XTIDE) - { - temp_hdd[hdlv_current_sel].xtide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); - } - hard_disk_track(hdlv_current_sel); - h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); - win_settings_hard_disks_update_item(h, hdlv_current_sel, 0); - ignore_change = 0; - return FALSE; + case IDC_COMBO_HD_CHANNEL_IDE: + ignore_change = 1; + h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); + hard_disk_untrack(lv1_current_sel); + temp_hdd[lv1_current_sel].ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); + hard_disk_track(lv1_current_sel); + h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); + win_settings_hard_disks_update_item(h, lv1_current_sel, 0); + ignore_change = 0; + return FALSE; - case IDC_COMBO_HD_CHANNEL_IDE: - if (ignore_change) - { - return FALSE; - } + case IDC_COMBO_HD_ID: + ignore_change = 1; + h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); + hard_disk_untrack(lv1_current_sel); + temp_hdd[lv1_current_sel].scsi_id = SendMessage(h, CB_GETCURSEL, 0, 0); + hard_disk_track(lv1_current_sel); + h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); + win_settings_hard_disks_update_item(h, lv1_current_sel, 0); + ignore_change = 0; + return FALSE; - ignore_change = 1; - h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); - hard_disk_untrack(hdlv_current_sel); - temp_hdd[hdlv_current_sel].ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); - hard_disk_track(hdlv_current_sel); - h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); - win_settings_hard_disks_update_item(h, hdlv_current_sel, 0); - ignore_change = 0; - return FALSE; - - case IDC_COMBO_HD_ID: - if (ignore_change) - { - return FALSE; - } - - ignore_change = 1; - h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); - hard_disk_untrack(hdlv_current_sel); - temp_hdd[hdlv_current_sel].scsi_id = SendMessage(h, CB_GETCURSEL, 0, 0); - hard_disk_track(hdlv_current_sel); - h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); - win_settings_hard_disks_update_item(h, hdlv_current_sel, 0); - ignore_change = 0; - return FALSE; - - case IDC_COMBO_HD_LUN: - if (ignore_change) - { - return FALSE; - } - - ignore_change = 1; - h = GetDlgItem(hdlg, IDC_COMBO_HD_LUN); - hard_disk_untrack(hdlv_current_sel); - temp_hdd[hdlv_current_sel].scsi_lun = SendMessage(h, CB_GETCURSEL, 0, 0); - hard_disk_track(hdlv_current_sel); - h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); - win_settings_hard_disks_update_item(h, hdlv_current_sel, 0); - ignore_change = 0; - return FALSE; - - case IDC_BUTTON_HDD_ADD: - hard_disk_add_open(hdlg, 1); - if (hard_disk_added) - { - ignore_change = 1; - h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); - win_settings_hard_disks_recalc_list(h); - recalc_next_free_id(hdlg); - hard_disk_track_all(); - ignore_change = 0; - } - return FALSE; - - case IDC_BUTTON_HDD_ADD_NEW: - hard_disk_add_open(hdlg, 0); - if (hard_disk_added) - { - ignore_change = 1; - h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); - win_settings_hard_disks_recalc_list(h); - recalc_next_free_id(hdlg); - hard_disk_track_all(); - ignore_change = 0; - } - return FALSE; - - case IDC_BUTTON_HDD_REMOVE: - memcpy(temp_hdd[hdlv_current_sel].fn, L"", 4); - hard_disk_untrack(hdlv_current_sel); - temp_hdd[hdlv_current_sel].bus = HDD_BUS_DISABLED; /* Only set the bus to zero, the list normalize code below will take care of turning this entire entry to a complete zero. */ - normalize_hd_list(); /* Normalize the hard disks so that non-disabled hard disks start from index 0, and so they are contiguous. */ + case IDC_BUTTON_HDD_ADD: + hard_disk_add_open(hdlg, 1); + if (hard_disk_added) { ignore_change = 1; h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); win_settings_hard_disks_recalc_list(h); recalc_next_free_id(hdlg); - if (hd_listview_items > 0) - { - ListView_SetItemState(h, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); - hdlv_current_sel = 0; - h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); - SendMessage(h, CB_SETCURSEL, temp_hdd[0].bus - 1, 0); - } - else - { - hdlv_current_sel = -1; - } - recalc_location_controls(hdlg, 0, 0); + hard_disk_track_all(); ignore_change = 0; - return FALSE; - } + } + return FALSE; - default: - return FALSE; - } + case IDC_BUTTON_HDD_ADD_NEW: + hard_disk_add_open(hdlg, 0); + if (hard_disk_added) { + ignore_change = 1; + h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); + win_settings_hard_disks_recalc_list(h); + recalc_next_free_id(hdlg); + hard_disk_track_all(); + ignore_change = 0; + } + return FALSE; - return FALSE; -} - -static int fdlv_current_sel; - -static int cdlv_current_sel; -static int zdlv_current_sel; - -static int combo_id_to_string_id(int combo_id) -{ - return IDS_5376 + combo_id; -} - -static int combo_id_to_format_string_id(int combo_id) -{ - return IDS_5632 + combo_id; -} - -static BOOL win_settings_floppy_drives_image_list_init(HWND hwndList) -{ - HICON hiconItem; - HIMAGELIST hSmall; - - int i = 0; - - hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), - GetSystemMetrics(SM_CYSMICON), - ILC_MASK | ILC_COLOR32, 1, 1); - - for (i = 0; i < 14; i++) - { - hiconItem = LoadIcon(hinstance, (LPCWSTR) fdd_type_to_icon(i)); - ImageList_AddIcon(hSmall, hiconItem); - DestroyIcon(hiconItem); - } - - ListView_SetImageList(hwndList, hSmall, LVSIL_SMALL); - - return TRUE; -} - -static BOOL win_settings_cdrom_drives_image_list_init(HWND hwndList) -{ - HICON hiconItem; - HIMAGELIST hSmall; - - hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), - GetSystemMetrics(SM_CYSMICON), - ILC_MASK | ILC_COLOR32, 1, 1); - - hiconItem = LoadIcon(hinstance, (LPCWSTR) 514); - ImageList_AddIcon(hSmall, hiconItem); - DestroyIcon(hiconItem); - - hiconItem = LoadIcon(hinstance, (LPCWSTR) 160); - ImageList_AddIcon(hSmall, hiconItem); - DestroyIcon(hiconItem); - - ListView_SetImageList(hwndList, hSmall, LVSIL_SMALL); - - return TRUE; -} - -static BOOL win_settings_zip_drives_image_list_init(HWND hwndList) -{ - HICON hiconItem; - HIMAGELIST hSmall; - - hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), - GetSystemMetrics(SM_CYSMICON), - ILC_MASK | ILC_COLOR32, 1, 1); - - hiconItem = LoadIcon(hinstance, (LPCWSTR) 515); - ImageList_AddIcon(hSmall, hiconItem); - DestroyIcon(hiconItem); - - hiconItem = LoadIcon(hinstance, (LPCWSTR) 176); - ImageList_AddIcon(hSmall, hiconItem); - DestroyIcon(hiconItem); - - ListView_SetImageList(hwndList, hSmall, LVSIL_SMALL); - - return TRUE; -} - -static BOOL win_settings_floppy_drives_recalc_list(HWND hwndList) -{ - LVITEM lvI; - int i = 0; - char s[256]; - WCHAR szText[256]; - - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvI.stateMask = lvI.state = 0; - - for (i = 0; i < 4; i++) - { - lvI.iSubItem = 0; - if (temp_fdd_types[i] > 0) - { - strcpy(s, fdd_getname(temp_fdd_types[i])); - mbstowcs(szText, s, strlen(s) + 1); - lvI.pszText = szText; - } - else - { - lvI.pszText = plat_get_string(IDS_5376); - } - lvI.iItem = i; - lvI.iImage = temp_fdd_types[i]; - - if (ListView_InsertItem(hwndList, &lvI) == -1) - return FALSE; - - lvI.iSubItem = 1; - lvI.pszText = plat_get_string(temp_fdd_turbo[i] ? IDS_2060 : IDS_2061); - lvI.iItem = i; - lvI.iImage = 0; - - if (ListView_SetItem(hwndList, &lvI) == -1) - { - return FALSE; + case IDC_BUTTON_HDD_REMOVE: + memcpy(temp_hdd[lv1_current_sel].fn, L"", 4); + hard_disk_untrack(lv1_current_sel); + temp_hdd[lv1_current_sel].bus = HDD_BUS_DISABLED; /* Only set the bus to zero, the list normalize code below will take care of turning this entire entry to a complete zero. */ + normalize_hd_list(); /* Normalize the hard disks so that non-disabled hard disks start from index 0, and so they are contiguous. */ + ignore_change = 1; + h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); + win_settings_hard_disks_recalc_list(h); + recalc_next_free_id(hdlg); + if (hd_listview_items > 0) { + ListView_SetItemState(h, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); + lv1_current_sel = 0; + h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); + SendMessage(h, CB_SETCURSEL, temp_hdd[0].bus - 1, 0); + } else + lv1_current_sel = -1; + recalc_location_controls(hdlg, 0, 0); + ignore_change = 0; + return FALSE; } - lvI.iSubItem = 2; - lvI.pszText = plat_get_string(temp_fdd_check_bpb[i] ? IDS_2060 : IDS_2061); - lvI.iItem = i; - lvI.iImage = 0; - - if (ListView_SetItem(hwndList, &lvI) == -1) - { - return FALSE; - } - } - - return TRUE; -} - -static BOOL win_settings_cdrom_drives_recalc_list(HWND hwndList) -{ - LVITEM lvI; - int i = 0; - WCHAR szText[256]; - int fsid = 0; - - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvI.stateMask = lvI.iSubItem = lvI.state = 0; - - for (i = 0; i < 4; i++) - { - fsid = combo_id_to_format_string_id(temp_cdrom_drives[i].bus_type); - - lvI.iSubItem = 0; - switch (temp_cdrom_drives[i].bus_type) - { - case CDROM_BUS_DISABLED: - default: - lvI.pszText = plat_get_string(fsid); - lvI.iImage = 0; - break; - case CDROM_BUS_ATAPI_PIO_ONLY: - wsprintf(szText, plat_get_string(fsid), temp_cdrom_drives[i].ide_channel >> 1, temp_cdrom_drives[i].ide_channel & 1); - lvI.pszText = szText; - lvI.iImage = 1; - break; - case CDROM_BUS_ATAPI_PIO_AND_DMA: - wsprintf(szText, plat_get_string(fsid), temp_cdrom_drives[i].ide_channel >> 1, temp_cdrom_drives[i].ide_channel & 1); - lvI.pszText = szText; - lvI.iImage = 1; - break; - case CDROM_BUS_SCSI: - wsprintf(szText, plat_get_string(fsid), temp_cdrom_drives[i].scsi_device_id, temp_cdrom_drives[i].scsi_device_lun); - lvI.pszText = szText; - lvI.iImage = 1; - break; - } - - lvI.iItem = i; - - if (ListView_InsertItem(hwndList, &lvI) == -1) - return FALSE; - - lvI.iSubItem = 1; - if (temp_cdrom_drives[i].bus_type == CDROM_BUS_DISABLED) - lvI.pszText = plat_get_string(IDS_2152); - else { - wsprintf(szText, L"%ix", temp_cdrom_drives[i].speed); - lvI.pszText = szText; - } - lvI.iItem = i; - lvI.iImage = 0; - - if (ListView_SetItem(hwndList, &lvI) == -1) - { - return FALSE; - } - } - - return TRUE; -} - -static BOOL win_settings_zip_drives_recalc_list(HWND hwndList) -{ - LVITEM lvI; - int i = 0; - WCHAR szText[256]; - int fsid = 0; - - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvI.stateMask = lvI.iSubItem = lvI.state = 0; - - for (i = 0; i < 4; i++) - { - fsid = combo_id_to_format_string_id(temp_zip_drives[i].bus_type); - - lvI.iSubItem = 0; - switch (temp_zip_drives[i].bus_type) - { - case ZIP_BUS_DISABLED: - default: - lvI.pszText = plat_get_string(fsid); - lvI.iImage = 0; - break; - case ZIP_BUS_ATAPI_PIO_ONLY: - wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].ide_channel >> 1, temp_zip_drives[i].ide_channel & 1); - lvI.pszText = szText; - lvI.iImage = 1; - break; - case ZIP_BUS_ATAPI_PIO_AND_DMA: - wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].ide_channel >> 1, temp_zip_drives[i].ide_channel & 1); - lvI.pszText = szText; - lvI.iImage = 1; - break; - case ZIP_BUS_SCSI: - wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].scsi_device_id, temp_zip_drives[i].scsi_device_lun); - lvI.pszText = szText; - lvI.iImage = 1; - break; - } - - lvI.iItem = i; - - if (ListView_InsertItem(hwndList, &lvI) == -1) - return FALSE; - - lvI.iSubItem = 1; - lvI.pszText = plat_get_string(temp_zip_drives[i].is_250 ? IDS_5901 : IDS_5900); - lvI.iItem = i; - lvI.iImage = 0; - - if (ListView_SetItem(hwndList, &lvI) == -1) - { - return FALSE; - } - } - - return TRUE; -} - -static BOOL win_settings_floppy_drives_init_columns(HWND hwndList) -{ - LVCOLUMN lvc; - - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - - lvc.iSubItem = 0; - lvc.pszText = plat_get_string(IDS_2143); - - lvc.cx = 292; - lvc.fmt = LVCFMT_LEFT; - - if (ListView_InsertColumn(hwndList, 0, &lvc) == -1) - { + default: return FALSE; - } + } - lvc.iSubItem = 1; - lvc.pszText = plat_get_string(IDS_2059); - - lvc.cx = 50; - lvc.fmt = LVCFMT_LEFT; - - if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) - { - return FALSE; - } - - lvc.iSubItem = 2; - lvc.pszText = plat_get_string(IDS_2170); - - lvc.cx = 75; - lvc.fmt = LVCFMT_LEFT; - - if (ListView_InsertColumn(hwndList, 2, &lvc) == -1) - { - return FALSE; - } - return TRUE; + return FALSE; } -static BOOL win_settings_cdrom_drives_init_columns(HWND hwndList) + +static int +combo_id_to_string_id(int combo_id) { - LVCOLUMN lvc; - - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - - lvc.iSubItem = 0; - lvc.pszText = plat_get_string(IDS_2082); - - lvc.cx = 342; - lvc.fmt = LVCFMT_LEFT; - - if (ListView_InsertColumn(hwndList, 0, &lvc) == -1) - { - return FALSE; - } - - lvc.iSubItem = 1; - lvc.pszText = plat_get_string(IDS_2178); - - lvc.cx = 50; - lvc.fmt = LVCFMT_LEFT; - - if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) - { - return FALSE; - } - - return TRUE; + return IDS_5376 + combo_id; } -static BOOL win_settings_zip_drives_init_columns(HWND hwndList) + +static int +combo_id_to_format_string_id(int combo_id) { - LVCOLUMN lvc; - - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - - lvc.iSubItem = 0; - lvc.pszText = plat_get_string(IDS_2082); - - lvc.cx = 342; - lvc.fmt = LVCFMT_LEFT; - - if (ListView_InsertColumn(hwndList, 0, &lvc) == -1) - { - return FALSE; - } - - lvc.iSubItem = 1; - lvc.pszText = plat_get_string(IDS_2143); - - lvc.cx = 50; - lvc.fmt = LVCFMT_LEFT; - - if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) - { - return FALSE; - } - - return TRUE; + return IDS_5632 + combo_id; } -static int get_selected_floppy_drive(HWND hdlg) + +static BOOL +win_settings_floppy_drives_recalc_list(HWND hwndList) { - int floppy_drive = -1; - int i, j = 0; - HWND h; + LVITEM lvI; + int i = 0; + char s[256]; + WCHAR szText[256]; - for (i = 0; i < 6; i++) - { - h = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); - j = ListView_GetItemState(h, i, LVIS_SELECTED); - if (j) - { - floppy_drive = i; - } - } - - return floppy_drive; -} - -static int get_selected_cdrom_drive(HWND hdlg) -{ - int cd_drive = -1; - int i, j = 0; - HWND h; - - for (i = 0; i < 6; i++) - { - h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); - j = ListView_GetItemState(h, i, LVIS_SELECTED); - if (j) - { - cd_drive = i; - } - } - - return cd_drive; -} - -static int get_selected_zip_drive(HWND hdlg) -{ - int zip_disk_drive = -1; - int i, j = 0; - HWND h; - - for (i = 0; i < 6; i++) - { - h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); - j = ListView_GetItemState(h, i, LVIS_SELECTED); - if (j) - { - zip_disk_drive = i; - } - } - - return zip_disk_drive; -} - -static void win_settings_floppy_drives_update_item(HWND hwndList, int i) -{ - LVITEM lvI; - char s[256]; - WCHAR szText[256]; - - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvI.stateMask = lvI.iSubItem = lvI.state = 0; + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.stateMask = lvI.state = 0; + for (i = 0; i < 4; i++) { lvI.iSubItem = 0; - lvI.iItem = i; - - if (temp_fdd_types[i] > 0) - { + if (temp_fdd_types[i] > 0) { strcpy(s, fdd_getname(temp_fdd_types[i])); mbstowcs(szText, s, strlen(s) + 1); lvI.pszText = szText; - } - else - { + } else lvI.pszText = plat_get_string(IDS_5376); - } + lvI.iItem = i; lvI.iImage = temp_fdd_types[i]; - if (ListView_SetItem(hwndList, &lvI) == -1) - { - return; - } + if (ListView_InsertItem(hwndList, &lvI) == -1) + return FALSE; lvI.iSubItem = 1; lvI.pszText = plat_get_string(temp_fdd_turbo[i] ? IDS_2060 : IDS_2061); @@ -4247,9 +3268,7 @@ static void win_settings_floppy_drives_update_item(HWND hwndList, int i) lvI.iImage = 0; if (ListView_SetItem(hwndList, &lvI) == -1) - { - return; - } + return FALSE; lvI.iSubItem = 2; lvI.pszText = plat_get_string(temp_fdd_check_bpb[i] ? IDS_2060 : IDS_2061); @@ -4257,57 +3276,53 @@ static void win_settings_floppy_drives_update_item(HWND hwndList, int i) lvI.iImage = 0; if (ListView_SetItem(hwndList, &lvI) == -1) - { - return; - } + return FALSE; + } + + return TRUE; } -static void win_settings_cdrom_drives_update_item(HWND hwndList, int i) + +static BOOL +win_settings_cdrom_drives_recalc_list(HWND hwndList) { - LVITEM lvI; - WCHAR szText[256]; - int fsid; + LVITEM lvI; + int i = 0, fsid = 0; + WCHAR szText[256]; - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvI.stateMask = lvI.iSubItem = lvI.state = 0; - - lvI.iSubItem = 0; - lvI.iItem = i; + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.stateMask = lvI.iSubItem = lvI.state = 0; + for (i = 0; i < 4; i++) { fsid = combo_id_to_format_string_id(temp_cdrom_drives[i].bus_type); - switch (temp_cdrom_drives[i].bus_type) - { + lvI.iSubItem = 0; + switch (temp_cdrom_drives[i].bus_type) { case CDROM_BUS_DISABLED: default: lvI.pszText = plat_get_string(fsid); lvI.iImage = 0; break; - case CDROM_BUS_ATAPI_PIO_ONLY: - wsprintf(szText, plat_get_string(fsid), temp_cdrom_drives[i].ide_channel >> 1, temp_cdrom_drives[i].ide_channel & 1); - lvI.pszText = szText; - lvI.iImage = 1; - break; - case CDROM_BUS_ATAPI_PIO_AND_DMA: + case CDROM_BUS_ATAPI: wsprintf(szText, plat_get_string(fsid), temp_cdrom_drives[i].ide_channel >> 1, temp_cdrom_drives[i].ide_channel & 1); lvI.pszText = szText; lvI.iImage = 1; break; case CDROM_BUS_SCSI: - wsprintf(szText, plat_get_string(fsid), temp_cdrom_drives[i].scsi_device_id, temp_cdrom_drives[i].scsi_device_lun); + wsprintf(szText, plat_get_string(fsid), temp_cdrom_drives[i].scsi_device_id); lvI.pszText = szText; lvI.iImage = 1; break; } - if (ListView_SetItem(hwndList, &lvI) == -1) - { - return; - } + lvI.iItem = i; + + if (ListView_InsertItem(hwndList, &lvI) == -1) + return FALSE; lvI.iSubItem = 1; if (temp_cdrom_drives[i].bus_type == CDROM_BUS_DISABLED) - lvI.pszText = plat_get_string(IDS_2152); + lvI.pszText = plat_get_string(IDS_2112); else { wsprintf(szText, L"%ix", temp_cdrom_drives[i].speed); lvI.pszText = szText; @@ -4316,53 +3331,49 @@ static void win_settings_cdrom_drives_update_item(HWND hwndList, int i) lvI.iImage = 0; if (ListView_SetItem(hwndList, &lvI) == -1) - { - return; - } + return FALSE; + } + + return TRUE; } -static void win_settings_zip_drives_update_item(HWND hwndList, int i) + +static BOOL +win_settings_zip_drives_recalc_list(HWND hwndList) { - LVITEM lvI; - WCHAR szText[256]; - int fsid; + LVITEM lvI; + int i = 0, fsid = 0; + WCHAR szText[256]; - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvI.stateMask = lvI.iSubItem = lvI.state = 0; - - lvI.iSubItem = 0; - lvI.iItem = i; + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.stateMask = lvI.iSubItem = lvI.state = 0; + for (i = 0; i < 4; i++) { fsid = combo_id_to_format_string_id(temp_zip_drives[i].bus_type); - switch (temp_zip_drives[i].bus_type) - { + lvI.iSubItem = 0; + switch (temp_zip_drives[i].bus_type) { case ZIP_BUS_DISABLED: default: lvI.pszText = plat_get_string(fsid); lvI.iImage = 0; break; - case ZIP_BUS_ATAPI_PIO_ONLY: - wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].ide_channel >> 1, temp_zip_drives[i].ide_channel & 1); - lvI.pszText = szText; - lvI.iImage = 1; - break; - case ZIP_BUS_ATAPI_PIO_AND_DMA: + case ZIP_BUS_ATAPI: wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].ide_channel >> 1, temp_zip_drives[i].ide_channel & 1); lvI.pszText = szText; lvI.iImage = 1; break; case ZIP_BUS_SCSI: - wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].scsi_device_id, temp_zip_drives[i].scsi_device_lun); + wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].scsi_device_id); lvI.pszText = szText; lvI.iImage = 1; break; } - if (ListView_SetItem(hwndList, &lvI) == -1) - { - return; - } + lvI.iItem = i; + + if (ListView_InsertItem(hwndList, &lvI) == -1) + return FALSE; lvI.iSubItem = 1; lvI.pszText = plat_get_string(temp_zip_drives[i].is_250 ? IDS_5901 : IDS_5900); @@ -4370,298 +3381,507 @@ static void win_settings_zip_drives_update_item(HWND hwndList, int i) lvI.iImage = 0; if (ListView_SetItem(hwndList, &lvI) == -1) - { - return; - } + return FALSE; + } + + return TRUE; } -static void cdrom_add_locations(HWND hdlg) + +static BOOL +win_settings_floppy_drives_init_columns(HWND hwndList) { - LPTSTR lptsTemp; - HWND h; - int i = 0; + LVCOLUMN lvc; - lptsTemp = (LPTSTR) malloc(512); + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - h = GetDlgItem(hdlg, IDC_COMBO_CD_BUS); - for (i = CDROM_BUS_DISABLED; i <= CDROM_BUS_SCSI; i++) - { - if ((i == CDROM_BUS_DISABLED) || (i >= CDROM_BUS_ATAPI_PIO_ONLY)) - { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(combo_id_to_string_id(i))); - } - } + lvc.iSubItem = 0; + lvc.pszText = plat_get_string(IDS_2101); - h = GetDlgItem(hdlg, IDC_COMBO_CD_SPEED); - for (i = 1; i <= 72; i++) - { - wsprintf(lptsTemp, L"%ix", i); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } + lvc.cx = 292; + lvc.fmt = LVCFMT_LEFT; - h = GetDlgItem(hdlg, IDC_COMBO_CD_ID); - for (i = 0; i < 16; i++) - { - wsprintf(lptsTemp, plat_get_string(IDS_4098), i); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } + if (ListView_InsertColumn(hwndList, 0, &lvc) == -1) + return FALSE; - h = GetDlgItem(hdlg, IDC_COMBO_CD_LUN); - for (i = 0; i < 8; i++) - { - wsprintf(lptsTemp, plat_get_string(IDS_4098), i); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } + lvc.iSubItem = 1; + lvc.pszText = plat_get_string(IDS_2059); - h = GetDlgItem(hdlg, IDC_COMBO_CD_CHANNEL_IDE); - for (i = 0; i < 8; i++) - { - wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } + lvc.cx = 50; + lvc.fmt = LVCFMT_LEFT; - free(lptsTemp); + if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) + return FALSE; + + lvc.iSubItem = 2; + lvc.pszText = plat_get_string(IDS_2088); + + lvc.cx = 75; + lvc.fmt = LVCFMT_LEFT; + + if (ListView_InsertColumn(hwndList, 2, &lvc) == -1) + return FALSE; + + return TRUE; } + +static BOOL +win_settings_cdrom_drives_init_columns(HWND hwndList) +{ + LVCOLUMN lvc; + + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + + lvc.iSubItem = 0; + lvc.pszText = plat_get_string(IDS_2082); + + lvc.cx = 342; + lvc.fmt = LVCFMT_LEFT; + + if (ListView_InsertColumn(hwndList, 0, &lvc) == -1) + return FALSE; + + lvc.iSubItem = 1; + lvc.pszText = plat_get_string(IDS_2053); + + lvc.cx = 50; + lvc.fmt = LVCFMT_LEFT; + + if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) + return FALSE; + + return TRUE; +} + + +static BOOL +win_settings_zip_drives_init_columns(HWND hwndList) +{ + LVCOLUMN lvc; + + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + + lvc.iSubItem = 0; + lvc.pszText = plat_get_string(IDS_2082); + + lvc.cx = 342; + lvc.fmt = LVCFMT_LEFT; + + if (ListView_InsertColumn(hwndList, 0, &lvc) == -1) + return FALSE; + + lvc.iSubItem = 1; + lvc.pszText = plat_get_string(IDS_2101); + + lvc.cx = 50; + lvc.fmt = LVCFMT_LEFT; + + if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) + return FALSE; + + return TRUE; +} + + +static int +get_selected_drive(HWND hdlg, int id) +{ + int drive = -1; + int i, j = 0; + HWND h; + + for (i = 0; i < 4; i++) { + h = GetDlgItem(hdlg, id); + j = ListView_GetItemState(h, i, LVIS_SELECTED); + if (j) + drive = i; + } + + return drive; +} + + +static void +win_settings_floppy_drives_update_item(HWND hwndList, int i) +{ + LVITEM lvI; + char s[256]; + WCHAR szText[256]; + + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.stateMask = lvI.iSubItem = lvI.state = 0; + + lvI.iSubItem = 0; + lvI.iItem = i; + + if (temp_fdd_types[i] > 0) { + strcpy(s, fdd_getname(temp_fdd_types[i])); + mbstowcs(szText, s, strlen(s) + 1); + lvI.pszText = szText; + } else + lvI.pszText = plat_get_string(IDS_5376); + lvI.iImage = temp_fdd_types[i]; + + if (ListView_SetItem(hwndList, &lvI) == -1) + return; + + lvI.iSubItem = 1; + lvI.pszText = plat_get_string(temp_fdd_turbo[i] ? IDS_2060 : IDS_2061); + lvI.iItem = i; + lvI.iImage = 0; + + if (ListView_SetItem(hwndList, &lvI) == -1) + return; + + lvI.iSubItem = 2; + lvI.pszText = plat_get_string(temp_fdd_check_bpb[i] ? IDS_2060 : IDS_2061); + lvI.iItem = i; + lvI.iImage = 0; + + if (ListView_SetItem(hwndList, &lvI) == -1) + return; +} + + +static void +win_settings_cdrom_drives_update_item(HWND hwndList, int i) +{ + LVITEM lvI; + WCHAR szText[256]; + int fsid; + + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.stateMask = lvI.iSubItem = lvI.state = 0; + + lvI.iSubItem = 0; + lvI.iItem = i; + + fsid = combo_id_to_format_string_id(temp_cdrom_drives[i].bus_type); + + switch (temp_cdrom_drives[i].bus_type) { + case CDROM_BUS_DISABLED: + default: + lvI.pszText = plat_get_string(fsid); + lvI.iImage = 0; + break; + case CDROM_BUS_ATAPI: + wsprintf(szText, plat_get_string(fsid), temp_cdrom_drives[i].ide_channel >> 1, temp_cdrom_drives[i].ide_channel & 1); + lvI.pszText = szText; + lvI.iImage = 1; + break; + case CDROM_BUS_SCSI: + wsprintf(szText, plat_get_string(fsid), temp_cdrom_drives[i].scsi_device_id); + lvI.pszText = szText; + lvI.iImage = 1; + break; + } + + if (ListView_SetItem(hwndList, &lvI) == -1) + return; + + lvI.iSubItem = 1; + if (temp_cdrom_drives[i].bus_type == CDROM_BUS_DISABLED) + lvI.pszText = plat_get_string(IDS_2112); + else { + wsprintf(szText, L"%ix", temp_cdrom_drives[i].speed); + lvI.pszText = szText; + } + lvI.iItem = i; + lvI.iImage = 0; + + if (ListView_SetItem(hwndList, &lvI) == -1) + return; +} + + +static void +win_settings_zip_drives_update_item(HWND hwndList, int i) +{ + LVITEM lvI; + WCHAR szText[256]; + int fsid; + + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.stateMask = lvI.iSubItem = lvI.state = 0; + + lvI.iSubItem = 0; + lvI.iItem = i; + + fsid = combo_id_to_format_string_id(temp_zip_drives[i].bus_type); + + switch (temp_zip_drives[i].bus_type) { + case ZIP_BUS_DISABLED: + default: + lvI.pszText = plat_get_string(fsid); + lvI.iImage = 0; + break; + case ZIP_BUS_ATAPI: + wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].ide_channel >> 1, temp_zip_drives[i].ide_channel & 1); + lvI.pszText = szText; + lvI.iImage = 1; + break; + case ZIP_BUS_SCSI: + wsprintf(szText, plat_get_string(fsid), temp_zip_drives[i].scsi_device_id); + lvI.pszText = szText; + lvI.iImage = 1; + break; + } + + if (ListView_SetItem(hwndList, &lvI) == -1) + return; + + lvI.iSubItem = 1; + lvI.pszText = plat_get_string(temp_zip_drives[i].is_250 ? IDS_5901 : IDS_5900); + lvI.iItem = i; + lvI.iImage = 0; + + if (ListView_SetItem(hwndList, &lvI) == -1) + return; +} + + +static void +cdrom_add_locations(HWND hdlg) +{ + LPTSTR lptsTemp; + HWND h; + int i = 0; + + lptsTemp = (LPTSTR) malloc(512); + + h = GetDlgItem(hdlg, IDC_COMBO_CD_BUS); + for (i = CDROM_BUS_DISABLED; i <= CDROM_BUS_SCSI; i++) { + if ((i == CDROM_BUS_DISABLED) || (i >= CDROM_BUS_ATAPI)) + SendMessage(h, CB_ADDSTRING, 0, win_get_string(combo_id_to_string_id(i))); + } + + h = GetDlgItem(hdlg, IDC_COMBO_CD_SPEED); + for (i = 1; i <= 72; i++) { + wsprintf(lptsTemp, L"%ix", i); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + } + + h = GetDlgItem(hdlg, IDC_COMBO_CD_ID); + for (i = 0; i < 16; i++) { + wsprintf(lptsTemp, plat_get_string(IDS_4098), i); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + } + + h = GetDlgItem(hdlg, IDC_COMBO_CD_CHANNEL_IDE); + for (i = 0; i < 8; i++) { + wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + } + + free(lptsTemp); +} + + static void cdrom_recalc_location_controls(HWND hdlg, int assign_id) { - int i = 0; - HWND h; + int i = 0; + HWND h; - int bus = temp_cdrom_drives[cdlv_current_sel].bus_type; + int bus = temp_cdrom_drives[lv1_current_sel].bus_type; - for (i = IDT_1741; i < (IDT_1743 + 1); i++) - { - h = GetDlgItem(hdlg, i); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - } - - h = GetDlgItem(hdlg, IDC_COMBO_CD_ID); + for (i = IDT_1741; i < (IDT_1742 + 1); i++) { + h = GetDlgItem(hdlg, i); EnableWindow(h, FALSE); ShowWindow(h, SW_HIDE); + } - h = GetDlgItem(hdlg, IDC_COMBO_CD_LUN); + h = GetDlgItem(hdlg, IDC_COMBO_CD_ID); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + + h = GetDlgItem(hdlg, IDC_COMBO_CD_CHANNEL_IDE); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + + h = GetDlgItem(hdlg, IDC_COMBO_CD_SPEED); + if (bus == CDROM_BUS_DISABLED) { EnableWindow(h, FALSE); ShowWindow(h, SW_HIDE); + } else { + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + SendMessage(h, CB_SETCURSEL, temp_cdrom_drives[lv1_current_sel].speed - 1, 0); + } - h = GetDlgItem(hdlg, IDC_COMBO_CD_CHANNEL_IDE); + h = GetDlgItem(hdlg, IDT_1758); + if (bus == CDROM_BUS_DISABLED) { EnableWindow(h, FALSE); ShowWindow(h, SW_HIDE); + } else { + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + } - h = GetDlgItem(hdlg, IDC_COMBO_CD_SPEED); - if (bus == CDROM_BUS_DISABLED) { - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - } else { + switch(bus) { + case CDROM_BUS_ATAPI: /* ATAPI */ + h = GetDlgItem(hdlg, IDT_1742); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); - SendMessage(h, CB_SETCURSEL, temp_cdrom_drives[cdlv_current_sel].speed - 1, 0); - } - switch(bus) - { - case CDROM_BUS_ATAPI_PIO_ONLY: /* ATAPI (PIO-only) */ - case CDROM_BUS_ATAPI_PIO_AND_DMA: /* ATAPI (PIO and DMA) */ - h = GetDlgItem(hdlg, IDT_1743); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); + if (assign_id) + temp_cdrom_drives[lv1_current_sel].ide_channel = next_free_ide_channel(); - if (assign_id) - temp_cdrom_drives[cdlv_current_sel].ide_channel = next_free_ide_channel(); + h = GetDlgItem(hdlg, IDC_COMBO_CD_CHANNEL_IDE); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + SendMessage(h, CB_SETCURSEL, temp_cdrom_drives[lv1_current_sel].ide_channel, 0); + break; + case CDROM_BUS_SCSI: /* SCSI */ + h = GetDlgItem(hdlg, IDT_1741); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); - h = GetDlgItem(hdlg, IDC_COMBO_CD_CHANNEL_IDE); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - SendMessage(h, CB_SETCURSEL, temp_cdrom_drives[cdlv_current_sel].ide_channel, 0); - break; - case CDROM_BUS_SCSI: /* SCSI */ - h = GetDlgItem(hdlg, IDT_1741); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - h = GetDlgItem(hdlg, IDT_1742); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); + if (assign_id) + next_free_scsi_id((uint8_t *) &temp_cdrom_drives[lv1_current_sel].scsi_device_id); - if (assign_id) - next_free_scsi_id_and_lun((uint8_t *) &temp_cdrom_drives[cdlv_current_sel].scsi_device_id, (uint8_t *) &temp_cdrom_drives[cdlv_current_sel].scsi_device_lun); - - h = GetDlgItem(hdlg, IDC_COMBO_CD_ID); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - SendMessage(h, CB_SETCURSEL, temp_cdrom_drives[cdlv_current_sel].scsi_device_id, 0); - - h = GetDlgItem(hdlg, IDC_COMBO_CD_LUN); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - SendMessage(h, CB_SETCURSEL, temp_cdrom_drives[cdlv_current_sel].scsi_device_lun, 0); - break; - } + h = GetDlgItem(hdlg, IDC_COMBO_CD_ID); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + SendMessage(h, CB_SETCURSEL, temp_cdrom_drives[lv1_current_sel].scsi_device_id, 0); + break; + } } -static void zip_add_locations(HWND hdlg) + +static void +zip_add_locations(HWND hdlg) { - LPTSTR lptsTemp; - HWND h; - int i = 0; + LPTSTR lptsTemp; + HWND h; + int i = 0; - lptsTemp = (LPTSTR) malloc(512); + lptsTemp = (LPTSTR) malloc(512); - h = GetDlgItem(hdlg, IDC_COMBO_ZIP_BUS); - for (i = ZIP_BUS_DISABLED; i <= ZIP_BUS_SCSI; i++) - { - if ((i == ZIP_BUS_DISABLED) || (i >= ZIP_BUS_ATAPI_PIO_ONLY)) - { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(combo_id_to_string_id(i))); - } - } + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_BUS); + for (i = ZIP_BUS_DISABLED; i <= ZIP_BUS_SCSI; i++) { + if ((i == ZIP_BUS_DISABLED) || (i >= ZIP_BUS_ATAPI)) + SendMessage(h, CB_ADDSTRING, 0, win_get_string(combo_id_to_string_id(i))); + } - h = GetDlgItem(hdlg, IDC_COMBO_ZIP_ID); - for (i = 0; i < 16; i++) - { - wsprintf(lptsTemp, plat_get_string(IDS_4098), i); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_ID); + for (i = 0; i < 16; i++) { + wsprintf(lptsTemp, plat_get_string(IDS_4098), i); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + } - h = GetDlgItem(hdlg, IDC_COMBO_ZIP_LUN); - for (i = 0; i < 8; i++) - { - wsprintf(lptsTemp, plat_get_string(IDS_4098), i); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE); + for (i = 0; i < 8; i++) { + wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + } - h = GetDlgItem(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE); - for (i = 0; i < 8; i++) - { - wsprintf(lptsTemp, plat_get_string(IDS_4097), i >> 1, i & 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); - } - - free(lptsTemp); + free(lptsTemp); } -static void zip_recalc_location_controls(HWND hdlg, int assign_id) + +static void +zip_recalc_location_controls(HWND hdlg, int assign_id) { - int i = 0; - HWND h; + int i = 0; + HWND h; - int bus = temp_zip_drives[zdlv_current_sel].bus_type; + int bus = temp_zip_drives[lv2_current_sel].bus_type; - for (i = IDT_1754; i < (IDT_1756 + 1); i++) - { - h = GetDlgItem(hdlg, i); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - } - - h = GetDlgItem(hdlg, IDC_COMBO_ZIP_ID); + for (i = IDT_1754; i < (IDT_1755 + 1); i++) { + h = GetDlgItem(hdlg, i); EnableWindow(h, FALSE); ShowWindow(h, SW_HIDE); + } - h = GetDlgItem(hdlg, IDC_COMBO_ZIP_LUN); + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_ID); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE); + EnableWindow(h, FALSE); + ShowWindow(h, SW_HIDE); + + h = GetDlgItem(hdlg, IDC_CHECK250); + if (bus == ZIP_BUS_DISABLED) { EnableWindow(h, FALSE); ShowWindow(h, SW_HIDE); + } else { + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + SendMessage(h, BM_SETCHECK, temp_zip_drives[lv2_current_sel].is_250, 0); + } - h = GetDlgItem(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE); - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); + switch(bus) { + case ZIP_BUS_ATAPI: /* ATAPI */ + h = GetDlgItem(hdlg, IDT_1755); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); - switch(bus) - { - case ZIP_BUS_ATAPI_PIO_ONLY: /* ATAPI (PIO-only) */ - case ZIP_BUS_ATAPI_PIO_AND_DMA: /* ATAPI (PIO and DMA) */ - h = GetDlgItem(hdlg, IDT_1756); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); + if (assign_id) + temp_zip_drives[lv2_current_sel].ide_channel = next_free_ide_channel(); - if (assign_id) - temp_zip_drives[zdlv_current_sel].ide_channel = next_free_ide_channel(); + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + SendMessage(h, CB_SETCURSEL, temp_zip_drives[lv2_current_sel].ide_channel, 0); + break; + case ZIP_BUS_SCSI: /* SCSI */ + h = GetDlgItem(hdlg, IDT_1754); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); - h = GetDlgItem(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - SendMessage(h, CB_SETCURSEL, temp_zip_drives[zdlv_current_sel].ide_channel, 0); - break; - case ZIP_BUS_SCSI: /* SCSI */ - h = GetDlgItem(hdlg, IDT_1754); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - h = GetDlgItem(hdlg, IDT_1755); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); + if (assign_id) + next_free_scsi_id((uint8_t *) &temp_zip_drives[lv2_current_sel].scsi_device_id); - if (assign_id) - next_free_scsi_id_and_lun((uint8_t *) &temp_zip_drives[zdlv_current_sel].scsi_device_id, (uint8_t *) &temp_zip_drives[zdlv_current_sel].scsi_device_lun); - - h = GetDlgItem(hdlg, IDC_COMBO_ZIP_ID); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - SendMessage(h, CB_SETCURSEL, temp_zip_drives[zdlv_current_sel].scsi_device_id, 0); - - h = GetDlgItem(hdlg, IDC_COMBO_ZIP_LUN); - ShowWindow(h, SW_SHOW); - EnableWindow(h, TRUE); - SendMessage(h, CB_SETCURSEL, temp_zip_drives[zdlv_current_sel].scsi_device_lun, 0); - break; - } + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_ID); + ShowWindow(h, SW_SHOW); + EnableWindow(h, TRUE); + SendMessage(h, CB_SETCURSEL, temp_zip_drives[lv2_current_sel].scsi_device_id, 0); + break; + } } -static void cdrom_track(uint8_t id) +static void +cdrom_track(uint8_t id) { - if ((temp_cdrom_drives[id].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) || (temp_cdrom_drives[id].bus_type == CDROM_BUS_ATAPI_PIO_ONLY)) - ide_tracking |= (2 << (temp_cdrom_drives[id].ide_channel << 3)); - else if (temp_cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - scsi_tracking[temp_cdrom_drives[id].scsi_device_id] |= (1 << temp_cdrom_drives[id].scsi_device_lun); + if (temp_cdrom_drives[id].bus_type == CDROM_BUS_ATAPI) + ide_tracking |= (2 << (temp_cdrom_drives[id].ide_channel << 3)); + else if (temp_cdrom_drives[id].bus_type == CDROM_BUS_SCSI) + scsi_tracking[temp_cdrom_drives[id].scsi_device_id >> 3] |= (1 << (temp_cdrom_drives[id].scsi_device_id & 0x07)); } -static void cdrom_untrack(uint8_t id) + +static void +cdrom_untrack(uint8_t id) { - if ((temp_cdrom_drives[id].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) || (temp_cdrom_drives[id].bus_type == CDROM_BUS_ATAPI_PIO_ONLY)) - ide_tracking &= ~(2 << (temp_cdrom_drives[id].ide_channel << 3)); - else if (temp_cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - scsi_tracking[temp_cdrom_drives[id].scsi_device_id] &= ~(1 << temp_cdrom_drives[id].scsi_device_lun); + if (temp_cdrom_drives[id].bus_type == CDROM_BUS_ATAPI) + ide_tracking &= ~(2 << (temp_cdrom_drives[id].ide_channel << 3)); + else if (temp_cdrom_drives[id].bus_type == CDROM_BUS_SCSI) + scsi_tracking[temp_cdrom_drives[id].scsi_device_id >> 3] &= ~(1 << (temp_cdrom_drives[id].scsi_device_id & 0x07)); } -#if 0 -static void cdrom_track_all(void) + +static void +zip_track(uint8_t id) { - int i; - - for (i = 0; i < CDROM_NUM; i++) - cdrom_track(i); + if (temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI) + ide_tracking |= (1 << temp_zip_drives[id].ide_channel); + else if (temp_zip_drives[id].bus_type == ZIP_BUS_SCSI) + scsi_tracking[temp_zip_drives[id].scsi_device_id >> 3] |= (1 << (temp_zip_drives[id].scsi_device_id & 0x07)); } -#endif -static void zip_track(uint8_t id) +static void +zip_untrack(uint8_t id) { - if ((temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || (temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI_PIO_ONLY)) - ide_tracking |= (1 << temp_zip_drives[id].ide_channel); - else if (temp_zip_drives[id].bus_type == ZIP_BUS_SCSI) - scsi_tracking[temp_zip_drives[id].scsi_device_id] |= (1 << temp_zip_drives[id].scsi_device_lun); + if (temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI) + ide_tracking &= ~(1 << temp_zip_drives[id].ide_channel); + else if (temp_zip_drives[id].bus_type == ZIP_BUS_SCSI) + scsi_tracking[temp_zip_drives[id].scsi_device_id >> 3] &= ~(1 << (temp_zip_drives[id].scsi_device_id & 0x07)); } -static void zip_untrack(uint8_t id) -{ - if ((temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || (temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI_PIO_ONLY)) - ide_tracking &= ~(1 << temp_zip_drives[id].ide_channel); - else if (temp_zip_drives[id].bus_type == ZIP_BUS_SCSI) - scsi_tracking[temp_zip_drives[id].scsi_device_id] &= ~(1 << temp_zip_drives[id].scsi_device_lun); -} - -#if 0 -static void zip_track_all(void) -{ - int i; - - for (i = 0; i < ZIP_NUM; i++) - zip_track(i); -} -#endif - - -int fd_ignore_change = 0; #ifdef __amd64__ static LRESULT CALLBACK @@ -4670,133 +3890,104 @@ static BOOL CALLBACK #endif win_settings_floppy_drives_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - HWND h; - int i = 0; - int old_sel = 0; - WCHAR szText[256]; + HWND h; + int i = 0, old_sel = 0; + WCHAR szText[256]; + const uint8_t fd_icons[15] = { 248, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 0 }; - switch (message) - { - case WM_INITDIALOG: - fd_ignore_change = 1; + switch (message) { + case WM_INITDIALOG: + ignore_change = 1; - fdlv_current_sel = 0; - h = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); - win_settings_floppy_drives_init_columns(h); - win_settings_floppy_drives_image_list_init(h); - win_settings_floppy_drives_recalc_list(h); - ListView_SetItemState(h, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); - h = GetDlgItem(hdlg, IDC_COMBO_FD_TYPE); - for (i = 0; i < 14; i++) - { - if (i == 0) - { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_5376)); - } - else - { - mbstowcs(szText, fdd_getname(i), strlen(fdd_getname(i)) + 1); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) szText); - } + lv1_current_sel = 0; + h = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); + win_settings_floppy_drives_init_columns(h); + image_list_init(h, (const uint8_t *) fd_icons); + win_settings_floppy_drives_recalc_list(h); + ListView_SetItemState(h, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); + h = GetDlgItem(hdlg, IDC_COMBO_FD_TYPE); + for (i = 0; i < 14; i++) { + if (i == 0) + SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_5376)); + else { + mbstowcs(szText, fdd_getname(i), strlen(fdd_getname(i)) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) szText); } - SendMessage(h, CB_SETCURSEL, temp_fdd_types[fdlv_current_sel], 0); + } + SendMessage(h, CB_SETCURSEL, temp_fdd_types[lv1_current_sel], 0); - h = GetDlgItem(hdlg, IDC_CHECKTURBO); - SendMessage(h, BM_SETCHECK, temp_fdd_turbo[fdlv_current_sel], 0); + h = GetDlgItem(hdlg, IDC_CHECKTURBO); + SendMessage(h, BM_SETCHECK, temp_fdd_turbo[lv1_current_sel], 0); - h = GetDlgItem(hdlg, IDC_CHECKBPB); - SendMessage(h, BM_SETCHECK, temp_fdd_check_bpb[fdlv_current_sel], 0); + h = GetDlgItem(hdlg, IDC_CHECKBPB); + SendMessage(h, BM_SETCHECK, temp_fdd_check_bpb[lv1_current_sel], 0); - fd_ignore_change = 0; - return TRUE; + ignore_change = 0; + return TRUE; - case WM_NOTIFY: - if (fd_ignore_change) - { + case WM_NOTIFY: + if (ignore_change) + return FALSE; + + if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_FLOPPY_DRIVES)) { + old_sel = lv1_current_sel; + lv1_current_sel = get_selected_drive(hdlg, IDC_LIST_FLOPPY_DRIVES); + if (lv1_current_sel == old_sel) + return FALSE; + else if (lv1_current_sel == -1) { + ignore_change = 1; + lv1_current_sel = old_sel; + ListView_SetItemState(h, lv1_current_sel, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); + ignore_change = 0; return FALSE; } + ignore_change = 1; + h = GetDlgItem(hdlg, IDC_COMBO_FD_TYPE); + SendMessage(h, CB_SETCURSEL, temp_fdd_types[lv1_current_sel], 0); + h = GetDlgItem(hdlg, IDC_CHECKTURBO); + SendMessage(h, BM_SETCHECK, temp_fdd_turbo[lv1_current_sel], 0); + h = GetDlgItem(hdlg, IDC_CHECKBPB); + SendMessage(h, BM_SETCHECK, temp_fdd_check_bpb[lv1_current_sel], 0); + ignore_change = 0; + } + break; - if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_FLOPPY_DRIVES)) - { - old_sel = fdlv_current_sel; - fdlv_current_sel = get_selected_floppy_drive(hdlg); - if (fdlv_current_sel == old_sel) - { - return FALSE; - } - else if (fdlv_current_sel == -1) - { - fd_ignore_change = 1; - fdlv_current_sel = old_sel; - ListView_SetItemState(h, fdlv_current_sel, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); - fd_ignore_change = 0; - return FALSE; - } - fd_ignore_change = 1; - h = GetDlgItem(hdlg, IDC_COMBO_FD_TYPE); - SendMessage(h, CB_SETCURSEL, temp_fdd_types[fdlv_current_sel], 0); - h = GetDlgItem(hdlg, IDC_CHECKTURBO); - SendMessage(h, BM_SETCHECK, temp_fdd_turbo[fdlv_current_sel], 0); - h = GetDlgItem(hdlg, IDC_CHECKBPB); - SendMessage(h, BM_SETCHECK, temp_fdd_check_bpb[fdlv_current_sel], 0); - fd_ignore_change = 0; - } - break; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDC_COMBO_FD_TYPE: - if (fd_ignore_change) - { - return FALSE; - } - - fd_ignore_change = 1; - h = GetDlgItem(hdlg, IDC_COMBO_FD_TYPE); - temp_fdd_types[fdlv_current_sel] = SendMessage(h, CB_GETCURSEL, 0, 0); - h = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); - win_settings_floppy_drives_update_item(h, fdlv_current_sel); - fd_ignore_change = 0; - return FALSE; - - case IDC_CHECKTURBO: - if (fd_ignore_change) - { - return FALSE; - } - - fd_ignore_change = 1; - h = GetDlgItem(hdlg, IDC_CHECKTURBO); - temp_fdd_turbo[fdlv_current_sel] = SendMessage(h, BM_GETCHECK, 0, 0); - h = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); - win_settings_floppy_drives_update_item(h, fdlv_current_sel); - fd_ignore_change = 0; - return FALSE; - - case IDC_CHECKBPB: - if (fd_ignore_change) - { - return FALSE; - } - - fd_ignore_change = 1; - h = GetDlgItem(hdlg, IDC_CHECKBPB); - temp_fdd_check_bpb[fdlv_current_sel] = SendMessage(h, BM_GETCHECK, 0, 0); - h = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); - win_settings_floppy_drives_update_item(h, fdlv_current_sel); - fd_ignore_change = 0; - return FALSE; - } - - default: + case WM_COMMAND: + if (ignore_change) return FALSE; - } - return FALSE; + ignore_change = 1; + switch (LOWORD(wParam)) { + case IDC_COMBO_FD_TYPE: + h = GetDlgItem(hdlg, IDC_COMBO_FD_TYPE); + temp_fdd_types[lv1_current_sel] = SendMessage(h, CB_GETCURSEL, 0, 0); + h = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); + win_settings_floppy_drives_update_item(h, lv1_current_sel); + break; + + case IDC_CHECKTURBO: + h = GetDlgItem(hdlg, IDC_CHECKTURBO); + temp_fdd_turbo[lv1_current_sel] = SendMessage(h, BM_GETCHECK, 0, 0); + h = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); + win_settings_floppy_drives_update_item(h, lv1_current_sel); + break; + + case IDC_CHECKBPB: + h = GetDlgItem(hdlg, IDC_CHECKBPB); + temp_fdd_check_bpb[lv1_current_sel] = SendMessage(h, BM_GETCHECK, 0, 0); + h = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); + win_settings_floppy_drives_update_item(h, lv1_current_sel); + break; + } + ignore_change = 0; + + default: + return FALSE; + } + + return FALSE; } -int rd_ignore_change = 0; #ifdef __amd64__ static LRESULT CALLBACK @@ -4805,72 +3996,136 @@ static BOOL CALLBACK #endif win_settings_other_removable_devices_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - HWND h; - int old_sel = 0; - int b = 0; - int b2 = 0; - int assign = 0; + HWND h; + int old_sel = 0, b = 0, assign = 0; + uint32_t b2 = 0; + const uint8_t cd_icons[3] = { 249, 32, 0 }; + const uint8_t zip_icons[3] = { 250, 48, 0 }; - switch (message) - { - case WM_INITDIALOG: - rd_ignore_change = 1; + switch (message) { + case WM_INITDIALOG: + ignore_change = 1; - cdlv_current_sel = 0; - h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); - win_settings_cdrom_drives_init_columns(h); - win_settings_cdrom_drives_image_list_init(h); - win_settings_cdrom_drives_recalc_list(h); - ListView_SetItemState(h, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); - cdrom_add_locations(hdlg); + lv1_current_sel = 0; + h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); + win_settings_cdrom_drives_init_columns(h); + image_list_init(h, (const uint8_t *) cd_icons); + win_settings_cdrom_drives_recalc_list(h); + ListView_SetItemState(h, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); + cdrom_add_locations(hdlg); + + h = GetDlgItem(hdlg, IDC_COMBO_CD_BUS); + + switch (temp_cdrom_drives[lv1_current_sel].bus_type) { + case CDROM_BUS_DISABLED: + default: + b = 0; + break; + case CDROM_BUS_ATAPI: + b = 1; + break; + case CDROM_BUS_SCSI: + b = 2; + break; + } + + SendMessage(h, CB_SETCURSEL, b, 0); + + cdrom_recalc_location_controls(hdlg, 0); + + lv2_current_sel = 0; + h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); + win_settings_zip_drives_init_columns(h); + image_list_init(h, (const uint8_t *) zip_icons); + win_settings_zip_drives_recalc_list(h); + ListView_SetItemState(h, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); + zip_add_locations(hdlg); + + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_BUS); + + switch (temp_zip_drives[lv2_current_sel].bus_type) { + case ZIP_BUS_DISABLED: + default: + b = 0; + break; + case ZIP_BUS_ATAPI: + b = 1; + break; + case ZIP_BUS_SCSI: + b = 2; + break; + } + + SendMessage(h, CB_SETCURSEL, b, 0); + + zip_recalc_location_controls(hdlg, 0); + + ignore_change = 0; + return TRUE; + + case WM_NOTIFY: + if (ignore_change) + return FALSE; + + if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_CDROM_DRIVES)) { + old_sel = lv1_current_sel; + lv1_current_sel = get_selected_drive(hdlg, IDC_LIST_CDROM_DRIVES); + if (lv1_current_sel == old_sel) + return FALSE; + else if (lv1_current_sel == -1) { + ignore_change = 1; + lv1_current_sel = old_sel; + ListView_SetItemState(h, lv1_current_sel, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); + ignore_change = 0; + return FALSE; + } + ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_CD_BUS); - switch (temp_cdrom_drives[cdlv_current_sel].bus_type) - { + switch (temp_cdrom_drives[lv1_current_sel].bus_type) { case CDROM_BUS_DISABLED: default: b = 0; break; - case CDROM_BUS_ATAPI_PIO_ONLY: + case CDROM_BUS_ATAPI: b = 1; break; - case CDROM_BUS_ATAPI_PIO_AND_DMA: - b = 2; - break; case CDROM_BUS_SCSI: - b = 3; + b = 2; break; } SendMessage(h, CB_SETCURSEL, b, 0); cdrom_recalc_location_controls(hdlg, 0); - - zdlv_current_sel = 0; - h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); - win_settings_zip_drives_init_columns(h); - win_settings_zip_drives_image_list_init(h); - win_settings_zip_drives_recalc_list(h); - ListView_SetItemState(h, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); - zip_add_locations(hdlg); + ignore_change = 0; + } else if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_ZIP_DRIVES)) { + old_sel = lv2_current_sel; + lv2_current_sel = get_selected_drive(hdlg, IDC_LIST_ZIP_DRIVES); + if (lv2_current_sel == old_sel) + return FALSE; + else if (lv2_current_sel == -1) { + ignore_change = 1; + lv2_current_sel = old_sel; + ListView_SetItemState(h, lv2_current_sel, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); + ignore_change = 0; + return FALSE; + } + ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_ZIP_BUS); - switch (temp_zip_drives[zdlv_current_sel].bus_type) - { + switch (temp_zip_drives[lv2_current_sel].bus_type) { case ZIP_BUS_DISABLED: default: b = 0; break; - case ZIP_BUS_ATAPI_PIO_ONLY: + case ZIP_BUS_ATAPI: b = 1; break; - case ZIP_BUS_ATAPI_PIO_AND_DMA: - b = 2; - break; case ZIP_BUS_SCSI: - b = 3; + b = 2; break; } @@ -4878,440 +4133,200 @@ win_settings_other_removable_devices_proc(HWND hdlg, UINT message, WPARAM wParam zip_recalc_location_controls(hdlg, 0); - h = GetDlgItem(hdlg, IDC_CHECK250); - SendMessage(h, BM_SETCHECK, temp_zip_drives[zdlv_current_sel].is_250, 0); + ignore_change = 0; + } + break; - rd_ignore_change = 0; - return TRUE; - - case WM_NOTIFY: - if (rd_ignore_change) - { - return FALSE; - } - - if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_CDROM_DRIVES)) - { - old_sel = cdlv_current_sel; - cdlv_current_sel = get_selected_cdrom_drive(hdlg); - if (cdlv_current_sel == old_sel) - { - return FALSE; - } - else if (cdlv_current_sel == -1) - { - rd_ignore_change = 1; - cdlv_current_sel = old_sel; - ListView_SetItemState(h, cdlv_current_sel, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); - rd_ignore_change = 0; - return FALSE; - } - rd_ignore_change = 1; - - h = GetDlgItem(hdlg, IDC_COMBO_CD_BUS); - - switch (temp_cdrom_drives[cdlv_current_sel].bus_type) - { - case CDROM_BUS_DISABLED: - default: - b = 0; - break; - case CDROM_BUS_ATAPI_PIO_ONLY: - b = 1; - break; - case CDROM_BUS_ATAPI_PIO_AND_DMA: - b = 2; - break; - case CDROM_BUS_SCSI: - b = 3; - break; - } - - SendMessage(h, CB_SETCURSEL, b, 0); - - cdrom_recalc_location_controls(hdlg, 0); - rd_ignore_change = 0; - } - else if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_ZIP_DRIVES)) - { - old_sel = zdlv_current_sel; - zdlv_current_sel = get_selected_zip_drive(hdlg); - if (zdlv_current_sel == old_sel) - { - return FALSE; - } - else if (zdlv_current_sel == -1) - { - rd_ignore_change = 1; - zdlv_current_sel = old_sel; - ListView_SetItemState(h, zdlv_current_sel, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); - rd_ignore_change = 0; - return FALSE; - } - rd_ignore_change = 1; - - h = GetDlgItem(hdlg, IDC_COMBO_ZIP_BUS); - - switch (temp_zip_drives[zdlv_current_sel].bus_type) - { - case ZIP_BUS_DISABLED: - default: - b = 0; - break; - case ZIP_BUS_ATAPI_PIO_ONLY: - b = 1; - break; - case ZIP_BUS_ATAPI_PIO_AND_DMA: - b = 2; - break; - case ZIP_BUS_SCSI: - b = 3; - break; - } - - SendMessage(h, CB_SETCURSEL, b, 0); - - zip_recalc_location_controls(hdlg, 0); - - h = GetDlgItem(hdlg, IDC_CHECK250); - SendMessage(h, BM_SETCHECK, temp_zip_drives[zdlv_current_sel].is_250, 0); - - rd_ignore_change = 0; - } - break; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDC_COMBO_CD_BUS: - if (rd_ignore_change) - { - return FALSE; - } - - rd_ignore_change = 1; - h = GetDlgItem(hdlg, IDC_COMBO_CD_BUS); - b = SendMessage(h, CB_GETCURSEL, 0, 0); - switch (b) - { - case 0: - b2 = CDROM_BUS_DISABLED; - break; - case 1: - b2 = CDROM_BUS_ATAPI_PIO_ONLY; - break; - case 2: - b2 = CDROM_BUS_ATAPI_PIO_AND_DMA; - break; - case 3: - b2 = CDROM_BUS_SCSI; - break; - } - if (b2 == temp_cdrom_drives[cdlv_current_sel].bus_type) - { - goto cdrom_bus_skip; - } - cdrom_untrack(cdlv_current_sel); - assign = (temp_cdrom_drives[cdlv_current_sel].bus_type == b2) ? 0 : 1; - if (temp_cdrom_drives[cdlv_current_sel].bus_type == CDROM_BUS_DISABLED) - temp_cdrom_drives[cdlv_current_sel].speed = 8; - if ((b2 == CDROM_BUS_ATAPI_PIO_ONLY) && (temp_cdrom_drives[cdlv_current_sel].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA)) - assign = 0; - else if ((b2 == CDROM_BUS_ATAPI_PIO_AND_DMA) && (temp_cdrom_drives[cdlv_current_sel].bus_type == CDROM_BUS_ATAPI_PIO_ONLY)) - assign = 0; - temp_cdrom_drives[cdlv_current_sel].bus_type = b2; - cdrom_recalc_location_controls(hdlg, assign); - cdrom_track(cdlv_current_sel); - h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); - win_settings_cdrom_drives_update_item(h, cdlv_current_sel); -cdrom_bus_skip: - rd_ignore_change = 0; - return FALSE; - - case IDC_COMBO_CD_ID: - if (rd_ignore_change) - { - return FALSE; - } - - rd_ignore_change = 1; - h = GetDlgItem(hdlg, IDC_COMBO_CD_ID); - cdrom_untrack(cdlv_current_sel); - temp_cdrom_drives[cdlv_current_sel].scsi_device_id = SendMessage(h, CB_GETCURSEL, 0, 0); - cdrom_track(cdlv_current_sel); - h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); - win_settings_cdrom_drives_update_item(h, cdlv_current_sel); - rd_ignore_change = 0; - return FALSE; - - case IDC_COMBO_CD_LUN: - if (rd_ignore_change) - { - return FALSE; - } - - rd_ignore_change = 1; - h = GetDlgItem(hdlg, IDC_COMBO_CD_LUN); - cdrom_untrack(cdlv_current_sel); - temp_cdrom_drives[cdlv_current_sel].scsi_device_lun = SendMessage(h, CB_GETCURSEL, 0, 0); - cdrom_track(cdlv_current_sel); - h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); - win_settings_cdrom_drives_update_item(h, cdlv_current_sel); - rd_ignore_change = 0; - return FALSE; - - case IDC_COMBO_CD_CHANNEL_IDE: - if (rd_ignore_change) - { - return FALSE; - } - - rd_ignore_change = 1; - h = GetDlgItem(hdlg, IDC_COMBO_CD_CHANNEL_IDE); - cdrom_untrack(cdlv_current_sel); - temp_cdrom_drives[cdlv_current_sel].ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); - cdrom_track(cdlv_current_sel); - h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); - win_settings_cdrom_drives_update_item(h, cdlv_current_sel); - rd_ignore_change = 0; - return FALSE; - - case IDC_COMBO_CD_SPEED: - if (rd_ignore_change) - { - return FALSE; - } - - rd_ignore_change = 1; - h = GetDlgItem(hdlg, IDC_COMBO_CD_SPEED); - temp_cdrom_drives[cdlv_current_sel].speed = SendMessage(h, CB_GETCURSEL, 0, 0) + 1; - h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); - win_settings_cdrom_drives_update_item(h, cdlv_current_sel); - rd_ignore_change = 0; - return FALSE; - - case IDC_COMBO_ZIP_BUS: - if (rd_ignore_change) - { - return FALSE; - } - - rd_ignore_change = 1; - h = GetDlgItem(hdlg, IDC_COMBO_ZIP_BUS); - b = SendMessage(h, CB_GETCURSEL, 0, 0); - switch (b) - { - case 0: - b2 = ZIP_BUS_DISABLED; - break; - case 1: - b2 = ZIP_BUS_ATAPI_PIO_ONLY; - break; - case 2: - b2 = ZIP_BUS_ATAPI_PIO_AND_DMA; - break; - case 3: - b2 = ZIP_BUS_SCSI; - break; - } - if (b2 == temp_zip_drives[zdlv_current_sel].bus_type) - { - goto zip_bus_skip; - } - zip_untrack(zdlv_current_sel); - assign = (temp_zip_drives[zdlv_current_sel].bus_type == b2) ? 0 : 1; - if ((b2 == ZIP_BUS_ATAPI_PIO_ONLY) && (temp_zip_drives[zdlv_current_sel].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA)) - assign = 0; - else if ((b2 == ZIP_BUS_ATAPI_PIO_AND_DMA) && (temp_zip_drives[cdlv_current_sel].bus_type == ZIP_BUS_ATAPI_PIO_ONLY)) - assign = 0; - temp_zip_drives[zdlv_current_sel].bus_type = b2; - zip_recalc_location_controls(hdlg, assign); - zip_track(zdlv_current_sel); - h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); - win_settings_zip_drives_update_item(h, zdlv_current_sel); -zip_bus_skip: - rd_ignore_change = 0; - return FALSE; - - case IDC_COMBO_ZIP_ID: - if (rd_ignore_change) - { - return FALSE; - } - - rd_ignore_change = 1; - h = GetDlgItem(hdlg, IDC_COMBO_ZIP_ID); - zip_untrack(zdlv_current_sel); - temp_zip_drives[zdlv_current_sel].scsi_device_id = SendMessage(h, CB_GETCURSEL, 0, 0); - zip_track(zdlv_current_sel); - h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); - win_settings_zip_drives_update_item(h, zdlv_current_sel); - rd_ignore_change = 0; - return FALSE; - - case IDC_COMBO_ZIP_LUN: - if (rd_ignore_change) - { - return FALSE; - } - - rd_ignore_change = 1; - h = GetDlgItem(hdlg, IDC_COMBO_ZIP_LUN); - zip_untrack(zdlv_current_sel); - temp_zip_drives[zdlv_current_sel].scsi_device_lun = SendMessage(h, CB_GETCURSEL, 0, 0); - zip_track(zdlv_current_sel); - h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); - win_settings_zip_drives_update_item(h, zdlv_current_sel); - rd_ignore_change = 0; - return FALSE; - - case IDC_COMBO_ZIP_CHANNEL_IDE: - if (rd_ignore_change) - { - return FALSE; - } - - rd_ignore_change = 1; - h = GetDlgItem(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE); - zip_untrack(zdlv_current_sel); - temp_zip_drives[zdlv_current_sel].ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); - zip_track(zdlv_current_sel); - h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); - win_settings_zip_drives_update_item(h, zdlv_current_sel); - rd_ignore_change = 0; - return FALSE; - - case IDC_CHECK250: - if (rd_ignore_change) - { - return FALSE; - } - - rd_ignore_change = 1; - h = GetDlgItem(hdlg, IDC_CHECK250); - temp_zip_drives[zdlv_current_sel].is_250 = SendMessage(h, BM_GETCHECK, 0, 0); - h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); - win_settings_zip_drives_update_item(h, zdlv_current_sel); - rd_ignore_change = 0; - return FALSE; - } - - default: + case WM_COMMAND: + if (ignore_change) return FALSE; - } - return FALSE; + ignore_change = 1; + switch (LOWORD(wParam)) { + case IDC_COMBO_CD_BUS: + h = GetDlgItem(hdlg, IDC_COMBO_CD_BUS); + b = SendMessage(h, CB_GETCURSEL, 0, 0); + switch (b) { + case 0: + b2 = CDROM_BUS_DISABLED; + break; + case 1: + b2 = CDROM_BUS_ATAPI; + break; + case 2: + b2 = CDROM_BUS_SCSI; + break; + } + if (b2 == temp_cdrom_drives[lv1_current_sel].bus_type) + break; + cdrom_untrack(lv1_current_sel); + assign = (temp_cdrom_drives[lv1_current_sel].bus_type == b2) ? 0 : 1; + if (temp_cdrom_drives[lv1_current_sel].bus_type == CDROM_BUS_DISABLED) + temp_cdrom_drives[lv1_current_sel].speed = 8; + temp_cdrom_drives[lv1_current_sel].bus_type = b2; + cdrom_recalc_location_controls(hdlg, assign); + cdrom_track(lv1_current_sel); + h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); + win_settings_cdrom_drives_update_item(h, lv1_current_sel); + break; + + case IDC_COMBO_CD_ID: + h = GetDlgItem(hdlg, IDC_COMBO_CD_ID); + cdrom_untrack(lv1_current_sel); + temp_cdrom_drives[lv1_current_sel].scsi_device_id = SendMessage(h, CB_GETCURSEL, 0, 0); + cdrom_track(lv1_current_sel); + h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); + win_settings_cdrom_drives_update_item(h, lv1_current_sel); + break; + + case IDC_COMBO_CD_CHANNEL_IDE: + h = GetDlgItem(hdlg, IDC_COMBO_CD_CHANNEL_IDE); + cdrom_untrack(lv1_current_sel); + temp_cdrom_drives[lv1_current_sel].ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); + cdrom_track(lv1_current_sel); + h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); + win_settings_cdrom_drives_update_item(h, lv1_current_sel); + break; + + case IDC_COMBO_CD_SPEED: + h = GetDlgItem(hdlg, IDC_COMBO_CD_SPEED); + temp_cdrom_drives[lv1_current_sel].speed = SendMessage(h, CB_GETCURSEL, 0, 0) + 1; + h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); + win_settings_cdrom_drives_update_item(h, lv1_current_sel); + break; + + case IDC_COMBO_ZIP_BUS: + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_BUS); + b = SendMessage(h, CB_GETCURSEL, 0, 0); + switch (b) { + case 0: + b2 = ZIP_BUS_DISABLED; + break; + case 1: + b2 = ZIP_BUS_ATAPI; + break; + case 2: + b2 = ZIP_BUS_SCSI; + break; + } + if (b2 == temp_zip_drives[lv2_current_sel].bus_type) + break; + zip_untrack(lv2_current_sel); + assign = (temp_zip_drives[lv2_current_sel].bus_type == b2) ? 0 : 1; + temp_zip_drives[lv2_current_sel].bus_type = b2; + zip_recalc_location_controls(hdlg, assign); + zip_track(lv2_current_sel); + h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); + win_settings_zip_drives_update_item(h, lv2_current_sel); + break; + + case IDC_COMBO_ZIP_ID: + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_ID); + zip_untrack(lv2_current_sel); + temp_zip_drives[lv2_current_sel].scsi_device_id = SendMessage(h, CB_GETCURSEL, 0, 0); + zip_track(lv2_current_sel); + h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); + win_settings_zip_drives_update_item(h, lv2_current_sel); + break; + + case IDC_COMBO_ZIP_CHANNEL_IDE: + h = GetDlgItem(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE); + zip_untrack(lv2_current_sel); + temp_zip_drives[lv2_current_sel].ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0); + zip_track(lv2_current_sel); + h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); + win_settings_zip_drives_update_item(h, lv2_current_sel); + break; + + case IDC_CHECK250: + h = GetDlgItem(hdlg, IDC_CHECK250); + temp_zip_drives[lv2_current_sel].is_250 = SendMessage(h, BM_GETCHECK, 0, 0); + h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); + win_settings_zip_drives_update_item(h, lv2_current_sel); + break; + } + ignore_change = 0; + + default: + return FALSE; + } + + return FALSE; } -#define SETTINGS_PAGE_MACHINE 0 -#define SETTINGS_PAGE_VIDEO 1 -#define SETTINGS_PAGE_INPUT 2 -#define SETTINGS_PAGE_SOUND 3 -#define SETTINGS_PAGE_NETWORK 4 -#define SETTINGS_PAGE_PORTS 5 -#define SETTINGS_PAGE_PERIPHERALS 6 -#define SETTINGS_PAGE_HARD_DISKS 7 -#define SETTINGS_PAGE_FLOPPY_DRIVES 8 -#define SETTINGS_PAGE_OTHER_REMOVABLE_DEVICES 9 void win_settings_show_child(HWND hwndParent, DWORD child_id) { - if (child_id == displayed_category) - { + if (child_id == displayed_category) + return; + else + displayed_category = child_id; + + SendMessage(hwndChildDialog, WM_SAVESETTINGS, 0, 0); + + DestroyWindow(hwndChildDialog); + + switch(child_id) { + case SETTINGS_PAGE_MACHINE: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_MACHINE, hwndParent, win_settings_machine_proc); + break; + case SETTINGS_PAGE_VIDEO: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_VIDEO, hwndParent, win_settings_video_proc); + break; + case SETTINGS_PAGE_INPUT: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_INPUT, hwndParent, win_settings_input_proc); + break; + case SETTINGS_PAGE_SOUND: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_SOUND, hwndParent, win_settings_sound_proc); + break; + case SETTINGS_PAGE_NETWORK: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_NETWORK, hwndParent, win_settings_network_proc); + break; + case SETTINGS_PAGE_PORTS: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_PORTS, hwndParent, win_settings_ports_proc); + break; + case SETTINGS_PAGE_PERIPHERALS: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_PERIPHERALS, hwndParent, win_settings_peripherals_proc); + break; + case SETTINGS_PAGE_HARD_DISKS: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_HARD_DISKS, hwndParent, win_settings_hard_disks_proc); + break; + case SETTINGS_PAGE_FLOPPY_DRIVES: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_FLOPPY_DRIVES, hwndParent, win_settings_floppy_drives_proc); + break; + case SETTINGS_PAGE_OTHER_REMOVABLE_DEVICES: + hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_OTHER_REMOVABLE_DEVICES, hwndParent, win_settings_other_removable_devices_proc); + break; + default: + fatal("Invalid child dialog ID\n"); return; - } - else - { - displayed_category = child_id; - } + } - SendMessage(hwndChildDialog, WM_SAVESETTINGS, 0, 0); - - DestroyWindow(hwndChildDialog); - - switch(child_id) - { - case SETTINGS_PAGE_MACHINE: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_MACHINE, hwndParent, win_settings_machine_proc); - break; - case SETTINGS_PAGE_VIDEO: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_VIDEO, hwndParent, win_settings_video_proc); - break; - case SETTINGS_PAGE_INPUT: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_INPUT, hwndParent, win_settings_input_proc); - break; - case SETTINGS_PAGE_SOUND: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_SOUND, hwndParent, win_settings_sound_proc); - break; - case SETTINGS_PAGE_NETWORK: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_NETWORK, hwndParent, win_settings_network_proc); - break; - case SETTINGS_PAGE_PORTS: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_PORTS, hwndParent, win_settings_ports_proc); - break; - case SETTINGS_PAGE_PERIPHERALS: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_PERIPHERALS, hwndParent, win_settings_peripherals_proc); - break; - case SETTINGS_PAGE_HARD_DISKS: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_HARD_DISKS, hwndParent, win_settings_hard_disks_proc); - break; - case SETTINGS_PAGE_FLOPPY_DRIVES: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_FLOPPY_DRIVES, hwndParent, win_settings_floppy_drives_proc); - break; - case SETTINGS_PAGE_OTHER_REMOVABLE_DEVICES: - hwndChildDialog = CreateDialog(hinstance, (LPCWSTR)DLG_CFG_OTHER_REMOVABLE_DEVICES, hwndParent, win_settings_other_removable_devices_proc); - break; - default: - fatal("Invalid child dialog ID\n"); - return; - } - - ShowWindow(hwndChildDialog, SW_SHOWNORMAL); + ShowWindow(hwndChildDialog, SW_SHOWNORMAL); } -static BOOL win_settings_main_image_list_init(HWND hwndList) + +static BOOL +win_settings_main_insert_categories(HWND hwndList) { - HICON hiconItem; - HIMAGELIST hSmall; + LVITEM lvI; + int i = 0; - int i = 0; + lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; + lvI.stateMask = lvI.iSubItem = lvI.state = 0; - hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), - GetSystemMetrics(SM_CYSMICON), - ILC_MASK | ILC_COLOR32, 1, 1); + for (i = 0; i < 10; i++) { + lvI.pszText = plat_get_string(IDS_2065+i); + lvI.iItem = i; + lvI.iImage = i; - for (i = 0; i < 10; i++) - { - hiconItem = LoadIcon(hinstance, (LPCWSTR) (256 + (uintptr_t) i)); - ImageList_AddIcon(hSmall, hiconItem); - DestroyIcon(hiconItem); - } + if (ListView_InsertItem(hwndList, &lvI) == -1) + return FALSE; + } - ListView_SetImageList(hwndList, hSmall, LVSIL_SMALL); - - return TRUE; + return TRUE; } -static BOOL win_settings_main_insert_categories(HWND hwndList) -{ - LVITEM lvI; - int i = 0; - - lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; - lvI.stateMask = lvI.iSubItem = lvI.state = 0; - - for (i = 0; i < 10; i++) - { - lvI.pszText = plat_get_string(IDS_2065+i); - lvI.iItem = i; - lvI.iImage = i; - - if (ListView_InsertItem(hwndList, &lvI) == -1) - return FALSE; - } - - return TRUE; -} #ifdef __amd64__ static LRESULT CALLBACK @@ -5320,93 +4335,67 @@ static BOOL CALLBACK #endif win_settings_main_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - HWND h; - int category; - int i = 0; - int j = 0; + HWND h; + int category, i = 0, j = 0; + const uint8_t cat_icons[11] = { 240, 241, 242, 243, 80, 244, 245, 64, 246, 247, 0 }; - hwndParentDialog = hdlg; + hwndParentDialog = hdlg; - switch (message) - { - case WM_INITDIALOG: - plat_pause(1); - win_settings_init(); - displayed_category = -1; - h = GetDlgItem(hdlg, IDC_SETTINGSCATLIST); - win_settings_main_image_list_init(h); - win_settings_main_insert_categories(h); - ListView_SetItemState(h, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); -/* Leave this commented out until we do localization. */ -#if 0 - h = GetDlgItem(hdlg, IDC_COMBO_LANG); /* This is currently disabled, I am going to add localization options in the future. */ - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); - h = GetDlgItem(hdlg, IDS_LANG_ENUS); /*was:2047 !*/ - EnableWindow(h, FALSE); - ShowWindow(h, SW_HIDE); -#endif - return TRUE; - case WM_NOTIFY: - if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_SETTINGSCATLIST)) - { - category = -1; - for (i = 0; i < 10; i++) - { - h = GetDlgItem(hdlg, IDC_SETTINGSCATLIST); - j = ListView_GetItemState(h, i, LVIS_SELECTED); - if (j) - { - category = i; - /* pclog("Category %i selected\n", i); */ - } - } - if (category != -1) - { - /* pclog("Showing child: %i\n", category); */ - win_settings_show_child(hdlg, category); - } + switch (message) { + case WM_INITDIALOG: + plat_pause(1); + win_settings_init(); + displayed_category = -1; + h = GetDlgItem(hdlg, IDC_SETTINGSCATLIST); + image_list_init(h, (const uint8_t *) cat_icons); + win_settings_main_insert_categories(h); + ListView_SetItemState(h, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); + return TRUE; + case WM_NOTIFY: + if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_SETTINGSCATLIST)) { + category = -1; + for (i = 0; i < 10; i++) { + h = GetDlgItem(hdlg, IDC_SETTINGSCATLIST); + j = ListView_GetItemState(h, i, LVIS_SELECTED); + if (j) + category = i; } - break; - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDOK: - /* pclog("Saving settings...\n"); */ - SendMessage(hwndChildDialog, WM_SAVESETTINGS, 0, 0); - i = settings_msgbox_reset(); - if (i > 0) - { - if (i == 2) - { - win_settings_save(); - } + if (category != -1) + win_settings_show_child(hdlg, category); + } + break; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + SendMessage(hwndChildDialog, WM_SAVESETTINGS, 0, 0); + i = settings_msgbox_reset(); + if (i > 0) { + if (i == 2) + win_settings_save(); - /* pclog("Destroying window...\n"); */ - DestroyWindow(hwndChildDialog); - EndDialog(hdlg, 0); - plat_pause(0); - return TRUE; - } - else - { - return FALSE; - } - case IDCANCEL: DestroyWindow(hwndChildDialog); - EndDialog(hdlg, 0); - plat_pause(0); - return TRUE; - } - break; - default: - return FALSE; - } + EndDialog(hdlg, 0); + plat_pause(0); + return TRUE; + } else + return FALSE; + case IDCANCEL: + DestroyWindow(hwndChildDialog); + EndDialog(hdlg, 0); + plat_pause(0); + return TRUE; + } + break; + default: + return FALSE; + } - return FALSE; + return FALSE; } -void win_settings_open(HWND hwnd) + +void +win_settings_open(HWND hwnd) { - DialogBox(hinstance, (LPCWSTR)DLG_CONFIG, hwnd, win_settings_main_proc); + DialogBox(hinstance, (LPCWSTR)DLG_CONFIG, hwnd, win_settings_main_proc); } diff --git a/src/win/win_status.c b/src/win/win_status.c deleted file mode 100644 index 4ab31c7e1..000000000 --- a/src/win/win_status.c +++ /dev/null @@ -1,124 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -#define BITMAP WINDOWS_BITMAP -#include -#include -#undef BITMAP -#include -#include -#include -#include -#include "../86box.h" -#include "../pit.h" -#include "../mem.h" -#include "../cpu/cpu.h" -#include "../cpu/x86_ops.h" -#ifdef USE_DYNAREC -# include "../cpu/codegen.h" -#endif -#include "../device.h" -#include "../plat.h" -#include "win.h" - - - -HWND hwndStatus = NULL; - - -extern int sreadlnum, swritelnum, segareads, segawrites, scycles_lost; -extern uint64_t main_time; -static uint64_t status_time; - - -#ifdef __amd64__ -static LRESULT CALLBACK -#else -static BOOL CALLBACK -#endif -StatusWindowProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - char temp[4096]; - uint64_t new_time; - uint64_t status_diff; - - switch (message) { - case WM_INITDIALOG: - hwndStatus = hdlg; - /*FALLTHROUGH*/ - - case WM_USER: - new_time = plat_timer_read(); - status_diff = new_time - status_time; - status_time = new_time; - sprintf(temp, - "CPU speed : %f MIPS\n" - "FPU speed : %f MFLOPS\n\n" - - "Video throughput (read) : %i bytes/sec\n" - "Video throughput (write) : %i bytes/sec\n\n" - "Effective clockspeed : %iHz\n\n" - "Timer 0 frequency : %fHz\n\n" - "CPU time : %f%% (%f%%)\n" - -#ifdef USE_DYNAREC - "New blocks : %i\nOld blocks : %i\nRecompiled speed : %f MIPS\nAverage size : %f\n" - "Flushes : %i\nEvicted : %i\nReused : %i\nRemoved : %i" -#endif - ,mips, - flops, - segareads, - segawrites, - clockrate - scycles_lost, - pit_timer0_freq(), - ((double)main_time * 100.0) / status_diff, - ((double)main_time * 100.0) / timer_freq - -#ifdef USE_DYNAREC - , cpu_new_blocks_latched, cpu_recomp_blocks_latched, (double)cpu_recomp_ins_latched / 1000000.0, (double)cpu_recomp_ins_latched/cpu_recomp_blocks_latched, - cpu_recomp_flushes_latched, cpu_recomp_evicted_latched, - cpu_recomp_reuse_latched, cpu_recomp_removed_latched -#endif - ); - main_time = 0; - SendDlgItemMessage(hdlg, IDT_SDEVICE, WM_SETTEXT, - (WPARAM)NULL, (LPARAM)temp); - - temp[0] = 0; - device_add_status_info(temp, 4096); - SendDlgItemMessage(hdlg, IDT_STEXT, WM_SETTEXT, - (WPARAM)NULL, (LPARAM)temp); - return(TRUE); - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - case IDCANCEL: - hwndStatus = NULL; - EndDialog(hdlg, 0); - return(TRUE); - } - break; - } - - return(FALSE); -} - - -void -StatusWindowCreate(HWND hwndParent) -{ - HWND hwnd; - - hwnd = CreateDialog(hinstance, (LPCSTR)DLG_STATUS, - hwndParent, StatusWindowProcedure); - ShowWindow(hwnd, SW_SHOW); -} - - -/* Tell the Status window to update. */ -void -ui_status_update(void) -{ - SendMessage(hwndStatus, WM_USER, 0, 0); -} diff --git a/src/win/win_stbar.c b/src/win/win_stbar.c index 9c2ac2593..750b8837d 100644 --- a/src/win/win_stbar.c +++ b/src/win/win_stbar.c @@ -8,7 +8,7 @@ * * Implement the application's Status Bar. * - * Version: @(#)win_stbar.c 1.0.17 2018/03/18 + * Version: @(#)win_stbar.c 1.0.18 2018/05/25 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -33,14 +33,14 @@ #include "../cpu/cpu.h" #include "../device.h" #include "../machine/machine.h" -#include "../cdrom/cdrom.h" -#include "../cdrom/cdrom_image.h" -#include "../cdrom/cdrom_null.h" #include "../disk/hdd.h" #include "../disk/hdc.h" -#include "../disk/zip.h" #include "../floppy/fdd.h" #include "../scsi/scsi.h" +#include "../cdrom/cdrom.h" +#include "../disk/zip.h" +#include "../cdrom/cdrom_image.h" +#include "../cdrom/cdrom_null.h" #include "../scsi/scsi_disk.h" #include "../network/network.h" #include "../video/video.h" @@ -63,40 +63,31 @@ static HMENU *sb_menu_handles; static HMENU menuSBAR; static WCHAR **sbTips; static int *iStatusWidths; -static int *sb_icon_flags; static int *sb_part_meanings; -static int *sb_part_icons; +static uint8_t *sb_part_icons; static int sb_parts = 0; static int sb_ready = 0; +static uint8_t sb_map[256]; /* Also used by win_settings.c */ intptr_t fdd_type_to_icon(int type) { - int ret = 512; + int ret = 248; switch(type) { case 0: break; - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - ret = 128; + case 1: case 2: case 3: case 4: + case 5: case 6: + ret = 16; break; - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - ret = 144; + case 7: case 8: case 9: case 10: + case 11: case 12: case 13: + ret = 24; break; default: @@ -127,18 +118,18 @@ static void StatusBarCreateFloppySubmenu(HMENU m, int id) { AppendMenu(m, MF_STRING, IDM_FLOPPY_IMAGE_NEW | id, - plat_get_string(IDS_2161)); + plat_get_string(IDS_2096)); AppendMenu(m, MF_SEPARATOR, 0, 0); AppendMenu(m, MF_STRING, IDM_FLOPPY_IMAGE_EXISTING | id, - plat_get_string(IDS_2162)); + plat_get_string(IDS_2097)); AppendMenu(m, MF_STRING, IDM_FLOPPY_IMAGE_EXISTING_WP | id, - plat_get_string(IDS_2163)); + plat_get_string(IDS_2098)); AppendMenu(m, MF_SEPARATOR, 0, 0); AppendMenu(m, MF_STRING, IDM_FLOPPY_EXPORT_TO_86F | id, - plat_get_string(IDS_2172)); + plat_get_string(IDS_2080)); AppendMenu(m, MF_SEPARATOR, 0, 0); AppendMenu(m, MF_STRING, IDM_FLOPPY_EJECT | id, - plat_get_string(IDS_2164)); + plat_get_string(IDS_2093)); if (floppyfns[id][0] == 0x0000) { EnableMenuItem(m, IDM_FLOPPY_EJECT | id, MF_BYCOMMAND | MF_GRAYED); @@ -150,55 +141,23 @@ StatusBarCreateFloppySubmenu(HMENU m, int id) static void StatusBarCreateCdromSubmenu(HMENU m, int id) { - WCHAR s[64]; - int i; - AppendMenu(m, MF_STRING, IDM_CDROM_MUTE | id, - plat_get_string(IDS_2165)); + plat_get_string(IDS_2092)); AppendMenu(m, MF_SEPARATOR, 0, 0); AppendMenu(m, MF_STRING, IDM_CDROM_EMPTY | id, - plat_get_string(IDS_2166)); + plat_get_string(IDS_2091)); AppendMenu(m, MF_STRING, IDM_CDROM_RELOAD | id, - plat_get_string(IDS_2167)); + plat_get_string(IDS_2090)); AppendMenu(m, MF_SEPARATOR, 0, 0); AppendMenu(m, MF_STRING, IDM_CDROM_IMAGE | id, - plat_get_string(IDS_2168)); + plat_get_string(IDS_2089)); - if (host_cdrom_drive_available_num == 0) { - if ((cdrom_drives[id].host_drive >= 'A') && - (cdrom_drives[id].host_drive <= 'Z')) { - cdrom_drives[id].host_drive = 0; - } - - goto check_menu_items; - } else { - if ((cdrom_drives[id].host_drive >= 'A') && - (cdrom_drives[id].host_drive <= 'Z')) { - if (!host_cdrom_drive_available[cdrom_drives[id].host_drive - 'A']) { - cdrom_drives[id].host_drive = 0; - } - } - } - - AppendMenu(m, MF_SEPARATOR, 0, 0); - - for (i=0; i<26; i++) { - _swprintf(s, L"Host CD/DVD Drive (%c:)", i+'A'); - if (host_cdrom_drive_available[i]) - AppendMenu(m, MF_STRING, IDM_CDROM_HOST_DRIVE | (i<<3)|id, s); - } - -check_menu_items: if (! cdrom_drives[id].sound_on) CheckMenuItem(m, IDM_CDROM_MUTE | id, MF_CHECKED); if (cdrom_drives[id].host_drive == 200) CheckMenuItem(m, IDM_CDROM_IMAGE | id, MF_CHECKED); - else - if ((cdrom_drives[id].host_drive >= 'A') && (cdrom_drives[id].host_drive <= 'Z')) { - CheckMenuItem(m, IDM_CDROM_HOST_DRIVE | id | - ((cdrom_drives[id].host_drive - 'A') << 3), MF_CHECKED); - } else { + else { cdrom_drives[id].host_drive = 0; CheckMenuItem(m, IDM_CDROM_EMPTY | id, MF_CHECKED); } @@ -209,17 +168,17 @@ static void StatusBarCreateZIPSubmenu(HMENU m, int id) { AppendMenu(m, MF_STRING, IDM_ZIP_IMAGE_NEW | id, - plat_get_string(IDS_2161)); + plat_get_string(IDS_2096)); AppendMenu(m, MF_SEPARATOR, 0, 0); AppendMenu(m, MF_STRING, IDM_ZIP_IMAGE_EXISTING | id, - plat_get_string(IDS_2162)); + plat_get_string(IDS_2097)); AppendMenu(m, MF_STRING, IDM_ZIP_IMAGE_EXISTING_WP | id, - plat_get_string(IDS_2163)); + plat_get_string(IDS_2098)); AppendMenu(m, MF_SEPARATOR, 0, 0); AppendMenu(m, MF_STRING, IDM_ZIP_EJECT | id, - plat_get_string(IDS_2164)); + plat_get_string(IDS_2093)); AppendMenu(m, MF_STRING, IDM_ZIP_RELOAD | id, - plat_get_string(IDS_2167)); + plat_get_string(IDS_2090)); if (zip_drives[id].image_path[0] == 0x0000) { EnableMenuItem(m, IDM_ZIP_EJECT | id, MF_BYCOMMAND | MF_GRAYED); @@ -231,74 +190,26 @@ StatusBarCreateZIPSubmenu(HMENU m, int id) } -static void -StatusBarCreateRemovableDiskSubmenu(HMENU m, int id) -{ - AppendMenu(m, MF_STRING, IDM_RDISK_EJECT | id, - plat_get_string(IDS_2164)); - AppendMenu(m, MF_STRING, IDM_RDISK_RELOAD | id, - plat_get_string(IDS_2167)); - AppendMenu(m, MF_SEPARATOR, 0, 0); - AppendMenu(m, MF_STRING, IDM_RDISK_SEND_CHANGE | id, - plat_get_string(IDS_2142)); - AppendMenu(m, MF_SEPARATOR, 0, 0); - AppendMenu(m, MF_STRING, IDM_RDISK_IMAGE | id, - plat_get_string(IDS_2168)); - AppendMenu(m, MF_STRING, IDM_RDISK_IMAGE_WP | id, - plat_get_string(IDS_2169)); -} - - /* API */ -int -ui_sb_find_part(int tag) -{ - int found = -1; - int i; - - if (!sb_ready || (sb_parts == 0) || (sb_part_meanings == NULL)) { - return -1; - } - - for (i=0; i= SB_TEXT) || !sb_ready || (sb_parts == 0) || (sb_icon_flags == NULL) || (sb_part_icons == NULL)) { + if (((tag & 0xf0) >= SB_TEXT) || !sb_ready) return; - } - temp_flags |= active; + found = sb_map[tag]; + if (found != 0xff) { + sb_part_icons[found] &= ~1; + sb_part_icons[found] |= (uint8_t) active; - found = ui_sb_find_part(tag); - if (found != -1) { - if (temp_flags != (sb_icon_flags[found] & 1)) { - sb_icon_flags[found] &= ~1; - sb_icon_flags[found] |= active; - - sb_part_icons[found] &= ~257; - sb_part_icons[found] |= sb_icon_flags[found]; - - SendMessage(hwndSBAR, SB_SETICON, found, - (LPARAM)hIcon[sb_part_icons[found]]); - } + SendMessage(hwndSBAR, SB_SETICON, found, + (LPARAM)hIcon[sb_part_icons[found]]); } } @@ -307,19 +218,15 @@ ui_sb_update_icon(int tag, int active) void ui_sb_update_icon_state(int tag, int state) { - int found = -1; + uint8_t found = 0xff; - if (((tag & 0xf0) >= SB_HDD) || !sb_ready || (sb_parts == 0) || (sb_icon_flags == NULL) || (sb_part_icons == NULL)) { + if (((tag & 0xf0) >= SB_HDD) || !sb_ready) return; - } - found = ui_sb_find_part(tag); - if (found != -1) { - sb_icon_flags[found] &= ~256; - sb_icon_flags[found] |= state ? 256 : 0; - - sb_part_icons[found] &= ~257; - sb_part_icons[found] |= sb_icon_flags[found]; + found = sb_map[tag]; + if (found != 0xff) { + sb_part_icons[found] &= ~128; + sb_part_icons[found] |= (state ? 128 : 0); SendMessage(hwndSBAR, SB_SETICON, found, (LPARAM)hIcon[sb_part_icons[found]]); @@ -338,10 +245,10 @@ StatusBarCreateFloppyTip(int part) mbstowcs(wtext, fdd_getname(fdd_get_type(drive)), strlen(fdd_getname(fdd_get_type(drive))) + 1); if (wcslen(floppyfns[drive]) == 0) { - _swprintf(tempTip, plat_get_string(IDS_2158), + _swprintf(tempTip, plat_get_string(IDS_2117), drive+1, wtext, plat_get_string(IDS_2057)); } else { - _swprintf(tempTip, plat_get_string(IDS_2158), + _swprintf(tempTip, plat_get_string(IDS_2117), drive+1, wtext, floppyfns[drive]); } @@ -357,28 +264,22 @@ StatusBarCreateFloppyTip(int part) static void StatusBarCreateCdromTip(int part) { - WCHAR wtext[512]; WCHAR tempTip[512]; WCHAR *szText; int id; int drive = sb_part_meanings[part] & 0xf; int bus = cdrom_drives[drive].bus_type; - id = IDS_4352 + (bus - 1); + id = IDS_5377 + (bus - 1); szText = plat_get_string(id); if (cdrom_drives[drive].host_drive == 200) { - if (wcslen(cdrom_image[drive].image_path) == 0) { + if (wcslen(cdrom_image[drive].image_path) == 0) _swprintf(tempTip, plat_get_string(IDS_5120), drive+1, szText, plat_get_string(IDS_2057)); - } else { + else _swprintf(tempTip, plat_get_string(IDS_5120), drive+1, szText, cdrom_image[drive].image_path); - } - } else if ((cdrom_drives[drive].host_drive >= 'A') && (cdrom_drives[drive].host_drive <= 'Z')) { - _swprintf(wtext, plat_get_string(IDS_2058), cdrom_drives[drive].host_drive & ~0x20); - _swprintf(tempTip, plat_get_string(IDS_5120), drive+1, szText, wtext); - } else { + } else _swprintf(tempTip, plat_get_string(IDS_5120), drive+1, szText, plat_get_string(IDS_2057)); - } if (sbTips[part] != NULL) { free(sbTips[part]); @@ -393,38 +294,22 @@ static void StatusBarCreateZIPTip(int part) { WCHAR tempTip[512]; - + WCHAR *szText; + int id; int drive = sb_part_meanings[part] & 0xf; + int bus = zip_drives[drive].bus_type; + + id = IDS_5377 + (bus - 1); + szText = plat_get_string(id); int type = zip_drives[drive].is_250 ? 250 : 100; if (wcslen(zip_drives[drive].image_path) == 0) { - _swprintf(tempTip, plat_get_string(IDS_2177), - drive+1, type, plat_get_string(IDS_2057)); + _swprintf(tempTip, plat_get_string(IDS_2054), + type, drive+1, szText, plat_get_string(IDS_2057)); } else { - _swprintf(tempTip, plat_get_string(IDS_2177), - drive+1, type, zip_drives[drive].image_path); - } - - if (sbTips[part] != NULL) { - free(sbTips[part]); - sbTips[part] = NULL; - } - sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2); - wcscpy(sbTips[part], tempTip); -} - - -static void -StatusBarCreateRemovableDiskTip(int part) -{ - WCHAR tempTip[512]; - int drive = sb_part_meanings[part] & 0x1f; - - if (wcslen(hdd[drive].fn) == 0) { - _swprintf(tempTip, plat_get_string(IDS_4115), drive, plat_get_string(IDS_2057)); - } else { - _swprintf(tempTip, plat_get_string(IDS_4115), drive, hdd[drive].fn); + _swprintf(tempTip, plat_get_string(IDS_2054), + type, drive+1, szText, zip_drives[drive].image_path); } if (sbTips[part] != NULL) { @@ -487,18 +372,13 @@ StatusBarCreateSoundTip(int part) void ui_sb_update_tip(int meaning) { - int part = -1; - int i; + uint8_t part = 0xff; if (!sb_ready || (sb_parts == 0) || (sb_part_meanings == NULL)) return; - for (i=0; i= 'A') && (cdrom_drives[id].host_drive <= 'Z')) { - sb_icon_flags[i] = 0; - } else { - sb_icon_flags[i] = 256; - } - sb_part_icons[i] = 160 | sb_icon_flags[i]; + if (cdrom_drives[id].host_drive == 200) + sb_part_icons[i] = (wcslen(cdrom_image[id].image_path) == 0) ? 128 : 0; + else + sb_part_icons[i] = 128; + sb_part_icons[i] |= 32; sb_menu_handles[i] = StatusBarCreatePopupMenu(i); StatusBarCreateCdromSubmenu(sb_menu_handles[i], sb_part_meanings[i] & 0xf); EnableMenuItem(sb_menu_handles[i], IDM_CDROM_RELOAD | (sb_part_meanings[i] & 0xf), MF_BYCOMMAND | MF_GRAYED); @@ -872,53 +692,41 @@ ui_sb_update_panes(void) break; case SB_ZIP: /* Iomega ZIP */ - sb_icon_flags[i] = (wcslen(zip_drives[sb_part_meanings[i] & 0xf].image_path) == 0) ? 256 : 0; - sb_part_icons[i] = 176 + sb_icon_flags[i]; + sb_part_icons[i] = (wcslen(zip_drives[sb_part_meanings[i] & 0xf].image_path) == 0) ? 128 : 0; + sb_part_icons[i] |= 48; sb_menu_handles[i] = StatusBarCreatePopupMenu(i); StatusBarCreateZIPSubmenu(sb_menu_handles[i], sb_part_meanings[i] & 0xf); - EnableMenuItem(sb_menu_handles[i], IDM_ZIP_EJECT | (sb_part_meanings[i] & 0xf), MF_BYCOMMAND | ((sb_icon_flags[i] & 256) ? MF_GRAYED : MF_ENABLED)); + EnableMenuItem(sb_menu_handles[i], IDM_ZIP_EJECT | (sb_part_meanings[i] & 0xf), MF_BYCOMMAND | ((sb_part_icons[i] & 128) ? MF_GRAYED : MF_ENABLED)); StatusBarCreateZIPTip(i); break; - case SB_RDISK: /* Removable hard disk */ - sb_icon_flags[i] = (wcslen(hdd[sb_part_meanings[i] & 0x1f].fn) == 0) ? 256 : 0; - sb_part_icons[i] = 192 + sb_icon_flags[i]; - sb_menu_handles[i] = StatusBarCreatePopupMenu(i); - StatusBarCreateRemovableDiskSubmenu(sb_menu_handles[i], sb_part_meanings[i] & 0x1f); - EnableMenuItem(sb_menu_handles[i], IDM_RDISK_EJECT | (sb_part_meanings[i] & 0x1f), MF_BYCOMMAND | ((sb_icon_flags[i] & 256) ? MF_GRAYED : MF_ENABLED)); - EnableMenuItem(sb_menu_handles[i], IDM_RDISK_RELOAD | (sb_part_meanings[i] & 0x1f), MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(sb_menu_handles[i], IDM_RDISK_SEND_CHANGE | (sb_part_meanings[i] & 0x1f), MF_BYCOMMAND | ((sb_icon_flags[i] & 256) ? MF_GRAYED : MF_ENABLED)); - StatusBarCreateRemovableDiskTip(i); - break; - case SB_HDD: /* Hard disk */ - sb_part_icons[i] = 208; + sb_part_icons[i] = 64; StatusBarCreateDiskTip(i); break; case SB_NETWORK: /* Network */ - sb_part_icons[i] = 224; + sb_part_icons[i] = 80; StatusBarCreateNetworkTip(i); break; case SB_SOUND: /* Sound */ - sb_part_icons[i] = 259; + sb_part_icons[i] = 243; StatusBarCreateSoundTip(i); break; case SB_TEXT: /* Status text */ SendMessage(hwndSBAR, SB_SETTEXT, i | SBT_NOBORDERS, (LPARAM)L""); - sb_part_icons[i] = -1; + sb_part_icons[i] = 255; break; } - if (sb_part_icons[i] != -1) { + if (sb_part_icons[i] != 255) { SendMessage(hwndSBAR, SB_SETTEXT, i | SBT_NOBORDERS, (LPARAM)L""); SendMessage(hwndSBAR, SB_SETICON, i, (LPARAM)hIcon[sb_part_icons[i]]); SendMessage(hwndSBAR, SB_SETTIPTEXT, i, (LPARAM)sbTips[i]); - } else { + } else SendMessage(hwndSBAR, SB_SETICON, i, (LPARAM)NULL); - } } sb_ready = 1; @@ -956,10 +764,10 @@ ui_sb_mount_floppy_img(uint8_t id, int part, uint8_t wp, wchar_t *file_name) void ui_sb_mount_zip_img(uint8_t id, int part, uint8_t wp, wchar_t *file_name) { - zip_close(id); + zip_disk_close(zip[id]); zip_drives[id].ui_writeprot = wp; - zip_load(id, file_name); - zip_insert(id); + zip_load(zip[id], file_name); + zip_insert(zip[id]); ui_sb_update_icon_state(SB_ZIP | id, wcslen(zip_drives[id].image_path) ? 0 : 1); EnableMenuItem(sb_menu_handles[part], IDM_ZIP_EJECT | id, MF_BYCOMMAND | (wcslen(zip_drives[id].image_path) ? MF_ENABLED : MF_GRAYED)); EnableMenuItem(sb_menu_handles[part], IDM_ZIP_RELOAD | id, MF_BYCOMMAND | (wcslen(zip_drives[id].image_path) ? MF_GRAYED : MF_ENABLED)); @@ -979,13 +787,11 @@ StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) WCHAR temp_path[1024]; RECT rc; POINT pt; - int new_cdrom_drive; int ret = 0; int item_id = 0; int item_params = 0; int id = 0; - int part = 0; - int letter = 0; + uint8_t part = 0; switch (message) { case WM_COMMAND: @@ -995,26 +801,26 @@ StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) switch (item_id) { case IDM_FLOPPY_IMAGE_NEW: id = item_params & 0x0003; - part = ui_sb_find_part(SB_FLOPPY | id); + part = sb_map[SB_FLOPPY | id]; NewFloppyDialogCreate(hwnd, id, part); break; case IDM_FLOPPY_IMAGE_EXISTING: case IDM_FLOPPY_IMAGE_EXISTING_WP: id = item_params & 0x0003; - part = ui_sb_find_part(SB_FLOPPY | id); - if ((part == -1) || (sb_menu_handles == NULL)) + part = sb_map[SB_FLOPPY | id]; + if ((part == 0xff) || (sb_menu_handles == NULL)) break; - ret = file_dlg_w_st(hwnd, IDS_2159, floppyfns[id], 0); + ret = file_dlg_w_st(hwnd, IDS_2118, floppyfns[id], 0); if (! ret) ui_sb_mount_floppy_img(id, part, (item_id == IDM_FLOPPY_IMAGE_EXISTING_WP) ? 1 : 0, wopenfilestring); break; case IDM_FLOPPY_EJECT: id = item_params & 0x0003; - part = ui_sb_find_part(SB_FLOPPY | id); - if ((part == -1) || (sb_menu_handles == NULL)) + part = sb_map[SB_FLOPPY | id]; + if ((part == 0xff) || (sb_menu_handles == NULL)) break; fdd_close(id); @@ -1027,11 +833,11 @@ StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case IDM_FLOPPY_EXPORT_TO_86F: id = item_params & 0x0003; - part = ui_sb_find_part(SB_FLOPPY | id); - if ((part == -1) || (sb_menu_handles == NULL)) + part = sb_map[SB_FLOPPY | id]; + if ((part == 0xff) || (sb_menu_handles == NULL)) break; - ret = file_dlg_w_st(hwnd, IDS_2173, floppyfns[id], 1); + ret = file_dlg_w_st(hwnd, IDS_2076, floppyfns[id], 1); if (! ret) { plat_pause(1); ret = d86f_export(id, wopenfilestring); @@ -1043,8 +849,8 @@ StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case IDM_CDROM_MUTE: id = item_params & 0x0007; - part = ui_sb_find_part(SB_CDROM | id); - if ((part == -1) || (sb_menu_handles == NULL)) + part = sb_map[SB_CDROM | id]; + if ((part == 0xff) || (sb_menu_handles == NULL)) break; cdrom_drives[id].sound_on ^= 1; @@ -1065,8 +871,8 @@ StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case IDM_CDROM_IMAGE: id = item_params & 0x0007; - part = ui_sb_find_part(SB_CDROM | id); - if ((part == -1) || (sb_menu_handles == NULL)) + part = sb_map[SB_CDROM | id]; + if ((part == 0xff) || (sb_menu_handles == NULL)) break; if (!file_dlg_w_st(hwnd, IDS_2075, cdrom_image[id].image_path, 0)) { @@ -1075,15 +881,13 @@ StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if (!cdrom_image[id].prev_image_path) cdrom_image[id].prev_image_path = (wchar_t *) malloc(1024); wcscpy(cdrom_image[id].prev_image_path, cdrom_image[id].image_path); - cdrom_drives[id].handler->exit(id); - cdrom_close(id); + cdrom[id]->handler->exit(id); + cdrom_close_handler(id); + memset(cdrom_image[id].image_path, 0, 2048); image_open(id, temp_path); /* Signal media change to the emulated machine. */ - cdrom_insert(id); + cdrom_insert(cdrom[id]); CheckMenuItem(sb_menu_handles[part], IDM_CDROM_EMPTY | id, MF_UNCHECKED); - if ((cdrom_drives[id].host_drive >= 'A') && (cdrom_drives[id].host_drive <= 'Z')) { - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), MF_UNCHECKED); - } cdrom_drives[id].host_drive = (wcslen(cdrom_image[id].image_path) == 0) ? 0 : 200; if (cdrom_drives[id].host_drive == 200) { CheckMenuItem(sb_menu_handles[part], IDM_CDROM_IMAGE | id, MF_CHECKED); @@ -1099,55 +903,20 @@ StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } break; - case IDM_CDROM_HOST_DRIVE: - id = item_params & 0x0007; - letter = ((item_params >> 3) & 0x001f) + 'A'; - part = ui_sb_find_part(SB_CDROM | id); - if ((part == -1) || (sb_menu_handles == NULL)) - { - break; - } - - new_cdrom_drive = letter; - if (cdrom_drives[id].host_drive == new_cdrom_drive) - { - /* Switching to the same drive. Do nothing. */ - break; - } - cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; - cdrom_drives[id].handler->exit(id); - cdrom_close(id); - ioctl_open(id, new_cdrom_drive); - /* Signal media change to the emulated machine. */ - cdrom_insert(id); - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_EMPTY | id, MF_UNCHECKED); - if ((cdrom_drives[id].host_drive >= 'A') && (cdrom_drives[id].host_drive <= 'Z')) - { - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), MF_UNCHECKED); - } - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_IMAGE | id, MF_UNCHECKED); - cdrom_drives[id].host_drive = new_cdrom_drive; - CheckMenuItem(sb_menu_handles[part], IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), MF_CHECKED); - EnableMenuItem(sb_menu_handles[part], IDM_CDROM_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); - ui_sb_update_icon_state(SB_CDROM | id, 0); - ui_sb_update_tip(SB_CDROM | id); - config_save(); - break; - case IDM_ZIP_IMAGE_NEW: id = item_params & 0x0003; - part = ui_sb_find_part(SB_ZIP | id); + part = sb_map[SB_ZIP | id]; NewFloppyDialogCreate(hwnd, id | 0x80, part); /* NewZIPDialogCreate */ break; case IDM_ZIP_IMAGE_EXISTING: case IDM_ZIP_IMAGE_EXISTING_WP: id = item_params & 0x0003; - part = ui_sb_find_part(SB_ZIP | id); - if ((part == -1) || (sb_menu_handles == NULL)) + part = sb_map[SB_ZIP | id]; + if ((part == 0xff) || (sb_menu_handles == NULL)) break; - ret = file_dlg_w_st(hwnd, IDS_2175, zip_drives[id].image_path, 0); + ret = file_dlg_w_st(hwnd, IDS_2058, zip_drives[id].image_path, 0); if (! ret) ui_sb_mount_zip_img(id, part, (item_id == IDM_ZIP_IMAGE_EXISTING_WP) ? 1 : 0, wopenfilestring); break; @@ -1162,49 +931,6 @@ StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) zip_reload(id); break; - case IDM_RDISK_EJECT: - id = item_params & 0x001f; - removable_disk_eject(id); - break; - - case IDM_RDISK_RELOAD: - id = item_params & 0x001f; - removable_disk_reload(id); - break; - - case IDM_RDISK_SEND_CHANGE: - id = item_params & 0x001f; - scsi_disk_insert(id); - break; - - case IDM_RDISK_IMAGE: - case IDM_RDISK_IMAGE_WP: - id = item_params & 0x001f; - ret = file_dlg_w_st(hwnd, IDS_4106, hdd[id].fn, id); - if (!ret) { - removable_disk_unload(id); - memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); - wcscpy(hdd[id].fn, wopenfilestring); - hdd[id].wp = (item_id == IDM_RDISK_IMAGE_WP) ? 1 : 0; - scsi_loadhd(hdd[id].scsi_id, hdd[id].scsi_lun, id); - scsi_disk_insert(id); - if (wcslen(hdd[id].fn) > 0) { - ui_sb_update_icon_state(SB_RDISK | id, 0); - EnableMenuItem(sb_menu_handles[part], IDM_RDISK_EJECT | id, MF_BYCOMMAND | MF_ENABLED); - EnableMenuItem(sb_menu_handles[part], IDM_RDISK_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(sb_menu_handles[part], IDM_RDISK_SEND_CHANGE | id, MF_BYCOMMAND | MF_ENABLED); - } - else { - ui_sb_update_icon_state(SB_RDISK | id, 1); - EnableMenuItem(sb_menu_handles[part], IDM_RDISK_EJECT | id, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(sb_menu_handles[part], IDM_RDISK_RELOAD | id, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(sb_menu_handles[part], IDM_RDISK_SEND_CHANGE | id, MF_BYCOMMAND | MF_GRAYED); - } - ui_sb_update_tip(SB_RDISK | id); - config_save(); - } - break; - default: break; } @@ -1245,35 +971,31 @@ StatusBarCreate(HWND hwndParent, uintptr_t idStatus, HINSTANCE hInst) { RECT rectDialog; int dw, dh; - uintptr_t i; + uint8_t i; /* Load our icons into the cache for faster access. */ - for (i = 128; i < 130; i++) - hIcon[i] = LoadIconEx((PCTSTR) i); + for (i = 16; i < 18; i++) + hIcon[i] = LoadIconEx((PCTSTR) (uintptr_t) i); + for (i = 24; i < 26; i++) + hIcon[i] = LoadIconEx((PCTSTR) (uintptr_t) i); + for (i = 32; i < 34; i++) + hIcon[i] = LoadIconEx((PCTSTR) (uintptr_t) i); + for (i = 48; i < 50; i++) + hIcon[i] = LoadIconEx((PCTSTR) (uintptr_t) i); + for (i = 64; i < 66; i++) + hIcon[i] = LoadIconEx((PCTSTR) (uintptr_t) i); + for (i = 80; i < 82; i++) + hIcon[i] = LoadIconEx((PCTSTR) (uintptr_t) i); for (i = 144; i < 146; i++) - hIcon[i] = LoadIconEx((PCTSTR) i); + hIcon[i] = LoadIconEx((PCTSTR) (uintptr_t) i); + for (i = 152; i < 154; i++) + hIcon[i] = LoadIconEx((PCTSTR) (uintptr_t) i); for (i = 160; i < 162; i++) - hIcon[i] = LoadIconEx((PCTSTR) i); + hIcon[i] = LoadIconEx((PCTSTR) (uintptr_t) i); for (i = 176; i < 178; i++) - hIcon[i] = LoadIconEx((PCTSTR) i); - for (i = 192; i < 194; i++) - hIcon[i] = LoadIconEx((PCTSTR) i); - for (i = 208; i < 210; i++) - hIcon[i] = LoadIconEx((PCTSTR) i); - for (i = 224; i < 226; i++) - hIcon[i] = LoadIconEx((PCTSTR) i); - for (i = 259; i < 260; i++) - hIcon[i] = LoadIconEx((PCTSTR) i); - for (i = 384; i < 386; i++) - hIcon[i] = LoadIconEx((PCTSTR) i); - for (i = 400; i < 402; i++) - hIcon[i] = LoadIconEx((PCTSTR) i); - for (i = 416; i < 418; i++) - hIcon[i] = LoadIconEx((PCTSTR) i); - for (i = 432; i < 434; i++) - hIcon[i] = LoadIconEx((PCTSTR) i); - for (i = 448; i < 450; i++) - hIcon[i] = LoadIconEx((PCTSTR) i); + hIcon[i] = LoadIconEx((PCTSTR) (uintptr_t) i); + for (i = 243; i < 244; i++) + hIcon[i] = LoadIconEx((PCTSTR) (uintptr_t) i); GetWindowRect(hwndParent, &rectDialog); dw = rectDialog.right - rectDialog.left; @@ -1315,10 +1037,8 @@ StatusBarCreate(HWND hwndParent, uintptr_t idStatus, HINSTANCE hInst) memset(iStatusWidths, 0, sb_parts * sizeof(int)); sb_part_meanings = (int *)malloc(sb_parts * sizeof(int)); memset(sb_part_meanings, 0, sb_parts * sizeof(int)); - sb_part_icons = (int *)malloc(sb_parts * sizeof(int)); - memset(sb_part_icons, 0, sb_parts * sizeof(int)); - sb_icon_flags = (int *)malloc(sb_parts * sizeof(int)); - memset(sb_icon_flags, 0, sb_parts * sizeof(int)); + sb_part_icons = (uint8_t *)malloc(sb_parts * sizeof(uint8_t)); + memset(sb_part_icons, 0, sb_parts * sizeof(uint8_t)); sb_menu_handles = (HMENU *)malloc(sb_parts * sizeof(HMENU)); memset(sb_menu_handles, 0, sb_parts * sizeof(HMENU)); sbTips = (WCHAR **)malloc(sb_parts * sizeof(WCHAR *)); @@ -1326,7 +1046,7 @@ StatusBarCreate(HWND hwndParent, uintptr_t idStatus, HINSTANCE hInst) sb_parts = 0; iStatusWidths[sb_parts] = -1; sb_part_meanings[sb_parts] = SB_TEXT; - sb_part_icons[sb_parts] = -1; + sb_part_icons[sb_parts] = 255; sb_parts++; SendMessage(hwndSBAR, SB_SETPARTS, (WPARAM)sb_parts, (LPARAM)iStatusWidths); SendMessage(hwndSBAR, SB_SETTEXT, 0 | SBT_NOBORDERS, @@ -1339,10 +1059,10 @@ StatusBarCreate(HWND hwndParent, uintptr_t idStatus, HINSTANCE hInst) void ui_sb_check_menu_item(int tag, int id, int chk) { - int part; + uint8_t part; - part = ui_sb_find_part(tag); - if ((part == -1) || (sb_menu_handles == NULL)) + part = sb_map[tag]; + if ((part == 0xff) || (sb_menu_handles == NULL)) return; CheckMenuItem(sb_menu_handles[part], id, chk); @@ -1353,10 +1073,10 @@ ui_sb_check_menu_item(int tag, int id, int chk) void ui_sb_enable_menu_item(int tag, int id, int flg) { - int part; + uint8_t part; - part = ui_sb_find_part(tag); - if ((part == -1) || (sb_menu_handles == NULL)) + part = sb_map[tag]; + if ((part == 0xff) || (sb_menu_handles == NULL)) return; EnableMenuItem(sb_menu_handles[part], id, flg); @@ -1367,18 +1087,14 @@ ui_sb_enable_menu_item(int tag, int id, int flg) void ui_sb_set_text_w(wchar_t *wstr) { - int part = -1; - int i; + uint8_t part = 0xff; - if (!sb_ready || (sb_parts == 0) || (sb_part_meanings == NULL)) return; + if (!sb_ready || (sb_parts == 0) || (sb_part_meanings == NULL)) + return; - for (i=0; i * Fred N. van Kempen, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2017,2018 Fred N. van Kempen. */ #define UNICODE #define BITMAP WINDOWS_BITMAP @@ -39,7 +39,8 @@ typedef struct { thread_t * thread_create(void (*func)(void *param), void *param) { - return((thread_t *)_beginthread(func, 0, param)); + uintptr_t bt = _beginthread(func, 0, param); + return((thread_t *)bt); } diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 75c933fb3..786e54986 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -8,7 +8,7 @@ * * user Interface module for WinAPI on Windows. * - * Version: @(#)win_ui.c 1.0.23 2018/03/19 + * Version: @(#)win_ui.c 1.0.28 2018/05/25 * * Authors: Sarah Walker, * Miran Grca, @@ -21,8 +21,8 @@ #define UNICODE #include #include -#include #include +#include #include #include #include @@ -48,7 +48,7 @@ HWND hwndMain, /* application main window */ hwndRender; /* machine render window */ HMENU menuMain; /* application main menu */ -HICON hIcon[512]; /* icon data loaded from resources */ +HICON hIcon[256]; /* icon data loaded from resources */ RECT oldclip; /* mouse rect */ int infocus = 1; int rctrl_is_lalt = 0; @@ -59,7 +59,6 @@ WCHAR wopenfilestring[260]; /* Local data. */ static wchar_t wTitle[512]; -static RAWINPUTDEVICE device; static HHOOK hKeyboardHook; static int hook_enabled = 0; static int save_window_pos = 0; @@ -75,12 +74,10 @@ show_cursor(int val) return; if (val == 0) { - while (1) { + while (1) if (ShowCursor(FALSE) < 0) break; - } - } else { + } else ShowCursor(TRUE); - } vis = val; } @@ -94,23 +91,6 @@ LoadIconEx(PCTSTR pszIconName) } -#if 0 -static void -win_menu_update(void) -{ - menuMain = LoadMenu(hinstance, L"MainMenu")); - - menuSBAR = LoadMenu(hinstance, L"StatusBarMenu"); - - initmenu(); - - SetMenu(hwndMain, menu); - - win_title_update = 1; -} -#endif - - static void video_toggle_option(HMENU h, int *val, int id) { @@ -168,9 +148,7 @@ ResetAllMenus(void) CheckMenuItem(menuMain, IDM_VID_RESIZE, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_DDRAW+0, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_DDRAW+1, MF_UNCHECKED); -#ifdef USE_VNC CheckMenuItem(menuMain, IDM_VID_DDRAW+2, MF_UNCHECKED); -#endif #ifdef USE_VNC CheckMenuItem(menuMain, IDM_VID_DDRAW+3, MF_UNCHECKED); #endif @@ -246,7 +224,7 @@ LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) BOOL bControlKeyDown; KBDLLHOOKSTRUCT *p; - if (nCode < 0 || nCode != HC_ACTION) + if (nCode < 0 || nCode != HC_ACTION || (!mouse_capture && !video_fullscreen)) return(CallNextHookEx(hKeyboardHook, nCode, wParam, lParam)); p = (KBDLLHOOKSTRUCT*)lParam; @@ -334,10 +312,6 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) AboutDialogCreate(hwnd); break; - case IDM_STATUS: - StatusWindowCreate(hwnd); - break; - case IDM_UPDATE_ICONS: update_icons ^= 1; CheckMenuItem(hmenu, IDM_UPDATE_ICONS, update_icons ? MF_CHECKED : MF_UNCHECKED); @@ -405,11 +379,9 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case IDM_VID_DDRAW: case IDM_VID_D3D: + case IDM_VID_SDL: #ifdef USE_VNC case IDM_VID_VNC: -#endif -#ifdef USE_RDP - case IDM_VID_RDP: #endif CheckMenuItem(hmenu, IDM_VID_DDRAW+vid_api, MF_UNCHECKED); plat_setvid(LOWORD(wParam) - IDM_VID_DDRAW); @@ -418,7 +390,6 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) break; case IDM_VID_FULLSCREEN: - /* pclog("enter full screen though menu\n"); */ plat_setfullscreen(1); config_save(); break; @@ -553,61 +524,9 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) svga_dump_vram(); break; #endif - - case IDM_CONFIG_LOAD: - plat_pause(1); - if (!file_dlg_st(hwnd, IDS_2160, "", 0) && - (ui_msgbox(MBX_QUESTION, (wchar_t *)IDS_2051) == IDYES)) { - pc_reload(wopenfilestring); - ResetAllMenus(); - } - plat_pause(0); - break; - - case IDM_CONFIG_SAVE: - plat_pause(1); - if (! file_dlg_st(hwnd, IDS_2160, "", 1)) { - config_write(wopenfilestring); - } - plat_pause(0); - break; } return(0); - case WM_INPUT: - keyboard_handle(lParam, infocus); - break; - - case WM_SETFOCUS: - infocus = 1; - if (! hook_enabled) { - hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, - LowLevelKeyboardProc, - GetModuleHandle(NULL), - 0); - hook_enabled = 1; - } - break; - - case WM_KILLFOCUS: - infocus = 0; - plat_mouse_capture(0); - if (hook_enabled) { - UnhookWindowsHookEx(hKeyboardHook); - hook_enabled = 0; - } - break; - - case WM_LBUTTONUP: - if (! video_fullscreen) - plat_mouse_capture(1); - break; - - case WM_MBUTTONUP: - if (mouse_get_buttons() < 3) - plat_mouse_capture(0); - break; - case WM_ENTERMENULOOP: break; @@ -688,7 +607,6 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_LEAVEFULLSCREEN: - /* pclog("leave full screen on window message\n"); */ plat_setfullscreen(0); config_save(); break; @@ -726,6 +644,26 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) default: return(DefWindowProc(hwnd, message, wParam, lParam)); + + case WM_SETFOCUS: + infocus = 1; + if (! hook_enabled) { + hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, + LowLevelKeyboardProc, + GetModuleHandle(NULL), + 0); + hook_enabled = 1; + } + break; + + case WM_KILLFOCUS: + infocus = 0; + plat_mouse_capture(0); + if (hook_enabled) { + UnhookWindowsHookEx(hKeyboardHook); + hook_enabled = 0; + } + break; } return(0); @@ -744,16 +682,12 @@ ui_init(int nCmdShow) { WCHAR title[200]; WNDCLASSEX wincl; /* buffer for main window's class */ + RAWINPUTDEVICE ridev; /* RawInput device */ MSG messages; /* received-messages buffer */ HWND hwnd; /* handle for our window */ HACCEL haccel; /* handle to accelerator table */ int bRet; -#if 0 - /* We should have an application-wide at_exit catcher. */ - atexit(plat_mouse_capture); -#endif - if (settings_only) { if (! pc_init_modules()) { /* Dang, no ROMs found at all! */ @@ -774,8 +708,8 @@ ui_init(int nCmdShow) wincl.lpfnWndProc = MainWindowProcedure; wincl.style = CS_DBLCLKS; /* Catch double-clicks */ wincl.cbSize = sizeof(WNDCLASSEX); - wincl.hIcon = LoadIcon(hinstance, (LPCTSTR)100); - wincl.hIconSm = LoadIcon(hinstance, (LPCTSTR)100); + wincl.hIcon = LoadIcon(hinstance, (LPCTSTR)10); + wincl.hIconSm = LoadIcon(hinstance, (LPCTSTR)10); wincl.hCursor = NULL; wincl.lpszMenuName = NULL; wincl.cbClsExtra = 0; @@ -828,30 +762,34 @@ ui_init(int nCmdShow) /* Make the window visible on the screen. */ ShowWindow(hwnd, nCmdShow); - /* Load the accelerator table */ - haccel = LoadAccelerators(hinstance, ACCEL_NAME); - if (haccel == NULL) { + /* Initialize the RawInput (keyboard) module. */ + memset(&ridev, 0x00, sizeof(ridev)); + ridev.usUsagePage = 0x01; + ridev.usUsage = 0x06; + ridev.dwFlags = RIDEV_NOHOTKEYS; + ridev.hwndTarget = NULL; /* current focus window */ + if (! RegisterRawInputDevices(&ridev, 1, sizeof(ridev))) { MessageBox(hwndMain, - plat_get_string(IDS_2153), - plat_get_string(IDS_2050), - MB_OK | MB_ICONERROR); - return(3); - } - - /* Initialize the input (keyboard, mouse, game) module. */ - device.usUsagePage = 0x01; - device.usUsage = 0x06; - device.dwFlags = RIDEV_NOHOTKEYS; - device.hwndTarget = hwnd; - if (! RegisterRawInputDevices(&device, 1, sizeof(device))) { - MessageBox(hwndMain, - plat_get_string(IDS_2154), + plat_get_string(IDS_2114), plat_get_string(IDS_2050), MB_OK | MB_ICONERROR); return(4); } keyboard_getkeymap(); + /* Set up the main window for RawInput. */ + plat_set_input(hwndMain); + + /* Load the accelerator table */ + haccel = LoadAccelerators(hinstance, ACCEL_NAME); + if (haccel == NULL) { + MessageBox(hwndMain, + plat_get_string(IDS_2113), + plat_get_string(IDS_2050), + MB_OK | MB_ICONERROR); + return(3); + } + /* Initialize the mouse module. */ win_mouse_init(); @@ -942,7 +880,6 @@ ui_init(int nCmdShow) if (video_fullscreen && keyboard_isfsexit()) { /* Signal "exit fullscreen mode". */ - /* pclog("leave full screen though key combination\n"); */ plat_setfullscreen(0); } } @@ -1021,9 +958,6 @@ plat_resize(int x, int y) int sb_borders[3]; RECT r; -#if 0 -pclog("PLAT: VID[%d,%d] resizing to %dx%d\n", video_fullscreen, vid_api, x, y); -#endif /* First, see if we should resize the UI window. */ if (!vid_resize) { video_wait_for_blit(); @@ -1064,15 +998,84 @@ plat_mouse_capture(int on) GetClipCursor(&oldclip); GetWindowRect(hwndRender, &rect); ClipCursor(&rect); - /* pclog("mouse capture off, hide cursor\n"); */ show_cursor(0); mouse_capture = 1; } else if (!on && mouse_capture) { /* Disable the in-app mouse. */ ClipCursor(&oldclip); - /* pclog("mouse capture on, show cursor\n"); */ show_cursor(-1); mouse_capture = 0; } } + + +/* Catch WM_INPUT messages for 'current focus' window. */ +static LONG_PTR input_orig_proc; +static HWND input_orig_hwnd = NULL; +#ifdef __amd64__ +static LRESULT CALLBACK +#else +static BOOL CALLBACK +#endif +input_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) { + case WM_INPUT: + keyboard_handle(lParam, infocus); + break; + + case WM_SETFOCUS: + infocus = 1; + if (! hook_enabled) { + hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, + LowLevelKeyboardProc, + GetModuleHandle(NULL), + 0); + hook_enabled = 1; + } + break; + + case WM_KILLFOCUS: + infocus = 0; + plat_mouse_capture(0); + if (hook_enabled) { + UnhookWindowsHookEx(hKeyboardHook); + hook_enabled = 0; + } + break; + + case WM_LBUTTONUP: + if (! video_fullscreen) + plat_mouse_capture(1); + break; + + case WM_MBUTTONUP: + if (mouse_get_buttons() < 3) + plat_mouse_capture(0); + break; + + default: + return(CallWindowProc((WNDPROC)input_orig_proc, + hwnd, message, wParam, lParam)); + } + + return(0); +} + + +/* Set up a handler for the 'currently active' window. */ +void +plat_set_input(HWND h) +{ + /* If needed, rest the old one first. */ + if (input_orig_hwnd != NULL) { + SetWindowLongPtr(input_orig_hwnd, GWL_WNDPROC, + (LONG_PTR)input_orig_proc); + } + + /* Redirect the window procedure so we can catch WM_INPUT. */ + input_orig_proc = GetWindowLongPtr(h, GWLP_WNDPROC); + input_orig_hwnd = h; + SetWindowLongPtr(h, GWL_WNDPROC, (LONG_PTR)&input_proc); +}