From 908664243e419a4a4b1bed345e8112e69b6815f0 Mon Sep 17 00:00:00 2001 From: waltje Date: Wed, 25 Apr 2018 16:03:28 -0400 Subject: [PATCH] Added the Western Digital WDXT-150 XTA disk controller. Updated SettingsUI to have a for disk controllers. Moved machine config code to machine/machine_table.c. Fixed more constness stuff in device.c and machine_table.c Fixed an issue in win_devconf.c (buffers too small.) Misc changes and fixes. --- src/config.c | 2 +- src/device.c | 88 +-- src/device.h | 42 +- src/disk/hdc.c | 22 +- src/disk/hdc.h | 7 +- src/disk/hdc_ide_xta.c | 1201 +++++++++++++++++++++++++++++++++ src/dma.c | 1 + src/machine/m_at_430fx.c | 6 +- src/machine/m_europc.c | 17 +- src/machine/m_europc_hdc.c | 987 --------------------------- src/machine/machine.h | 164 ++--- src/machine/machine_table.c | 45 +- src/rom_load.c | 3 +- src/sound/midi_fluidsynth.c | 4 +- src/win/VARCem.rc | 5 +- src/win/mingw/Makefile.MinGW | 17 +- src/win/msvc/Makefile.VC | 17 +- src/win/resource.h | 9 +- src/win/win_devconf.c | 6 +- src/win/win_settings_periph.h | 26 +- src/win/win_stbar.c | 10 +- 21 files changed, 1453 insertions(+), 1226 deletions(-) create mode 100644 src/disk/hdc_ide_xta.c delete mode 100644 src/machine/m_europc_hdc.c diff --git a/src/config.c b/src/config.c index a6f9087..50b69b4 100644 --- a/src/config.c +++ b/src/config.c @@ -1596,7 +1596,7 @@ config_read(const wchar_t *fn) if (buff[c] == L'[') { /*Section*/ c++; d = 0; - while (buff[c] != L']' && buff[c]) + while (buff[c] && (buff[c] != L']')) wctomb(&(sname[d++]), buff[c++]); sname[d] = L'\0'; diff --git a/src/device.c b/src/device.c index a579ecf..cf17597 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.6 2018/04/09 + * Version: @(#)device.c 1.0.7 2018/04/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -247,14 +247,14 @@ device_add_status_info(char *s, int max_len) } -char * -device_get_config_string(char *s) +const char * +device_get_config_string(const char *s) { const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) - return(config_get_string((char *)device_current->name, s, (char *)c->default_string)); + return(config_get_string(device_current->name, s, c->default_string)); c++; } @@ -264,13 +264,13 @@ device_get_config_string(char *s) int -device_get_config_int(char *s) +device_get_config_int(const char *s) { const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) - return(config_get_int((char *)device_current->name, s, c->default_int)); + return(config_get_int(device_current->name, s, c->default_int)); c++; } @@ -280,29 +280,29 @@ device_get_config_int(char *s) int -device_get_config_int_ex(char *s, int default_int) +device_get_config_int_ex(const char *s, int def) { const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) - return(config_get_int((char *)device_current->name, s, default_int)); + return(config_get_int(device_current->name, s, def)); c++; } - return(default_int); + return(def); } int -device_get_config_hex16(char *s) +device_get_config_hex16(const char *s) { const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) - return(config_get_hex16((char *)device_current->name, s, c->default_int)); + return(config_get_hex16(device_current->name, s, c->default_int)); c++; } @@ -312,13 +312,13 @@ device_get_config_hex16(char *s) int -device_get_config_hex20(char *s) +device_get_config_hex20(const char *s) { const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) - return(config_get_hex20((char *)device_current->name, s, c->default_int)); + return(config_get_hex20(device_current->name, s, c->default_int)); c++; } @@ -328,29 +328,29 @@ device_get_config_hex20(char *s) int -device_get_config_mac(char *s, int default_int) +device_get_config_mac(const char *s, int def) { const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) - return(config_get_mac((char *)device_current->name, s, default_int)); + return(config_get_mac(device_current->name, s, def)); c++; } - return(default_int); + return(def); } void -device_set_config_int(char *s, int val) +device_set_config_int(const char *s, int val) { const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) { - config_set_int((char *)device_current->name, s, val); + config_set_int(device_current->name, s, val); break; } @@ -360,13 +360,13 @@ device_set_config_int(char *s, int val) void -device_set_config_hex16(char *s, int val) +device_set_config_hex16(const char *s, int val) { const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) { - config_set_hex16((char *)device_current->name, s, val); + config_set_hex16(device_current->name, s, val); break; } @@ -376,13 +376,13 @@ device_set_config_hex16(char *s, int val) void -device_set_config_hex20(char *s, int val) +device_set_config_hex20(const char *s, int val) { const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) { - config_set_hex20((char *)device_current->name, s, val); + config_set_hex20(device_current->name, s, val); break; } @@ -392,13 +392,13 @@ device_set_config_hex20(char *s, int val) void -device_set_config_mac(char *s, int val) +device_set_config_mac(const char *s, int val) { const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) { - config_set_mac((char *)device_current->name, s, val); + config_set_mac(device_current->name, s, val); break; } @@ -431,43 +431,3 @@ device_is_valid(const device_t *device, int mflags) return(1); } - - -int -machine_get_config_int(char *s) -{ - const device_t *d = machine_getdevice(machine); - const device_config_t *c; - - if (d == NULL) return(0); - - c = d->config; - while (c && c->type != -1) { - if (! strcmp(s, c->name)) - return(config_get_int((char *)d->name, s, c->default_int)); - - c++; - } - - return(0); -} - - -char * -machine_get_config_string(char *s) -{ - const device_t *d = machine_getdevice(machine); - const device_config_t *c; - - if (d == NULL) return(0); - - c = d->config; - while (c && c->type != -1) { - if (! strcmp(s, c->name)) - return(config_get_string((char *)d->name, s, (char *)c->default_string)); - - c++; - } - - return(NULL); -} diff --git a/src/device.h b/src/device.h index e374ce6..fd09bc9 100644 --- a/src/device.h +++ b/src/device.h @@ -8,7 +8,7 @@ * * Definitions for the device handler. * - * Version: @(#)device.h 1.0.4 2018/04/09 + * Version: @(#)device.h 1.0.5 2018/04/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -99,12 +99,12 @@ typedef struct _device_ { uint32_t local; /* flags local to device */ void *(*init)(const struct _device_ *); - void (*close)(void *p); - void (*reset)(void *p); + void (*close)(void *priv); + void (*reset)(void *priv); int (*available)(/*void*/); - void (*speed_changed)(void *p); - void (*force_redraw)(void *p); - void (*add_status_info)(char *s, int max_len, void *p); + void (*speed_changed)(void *priv); + void (*force_redraw)(void *priv); + void (*add_status_info)(char *s, int max_len, void *priv); const device_config_t *config; } device_t; @@ -115,30 +115,28 @@ extern "C" { #endif extern void device_init(void); -extern void *device_add(const device_t *d); +extern void *device_add(const device_t *); 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_get_priv(const device_t *d); -extern int device_available(const device_t *d); +extern void *device_get_priv(const device_t *); +extern int device_available(const device_t *); 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); -extern int device_get_config_hex16(char *name); -extern int device_get_config_hex20(char *name); -extern int device_get_config_mac(char *name, int default_int); -extern void device_set_config_int(char *s, int val); -extern void device_set_config_hex16(char *s, int val); -extern void device_set_config_hex20(char *s, int val); -extern void device_set_config_mac(char *s, int val); -extern char *device_get_config_string(char *name); -extern int device_is_valid(const device_t *device, int machine_flags); +extern int device_is_valid(const device_t *, int machine_flags); -extern int machine_get_config_int(char *s); -extern char *machine_get_config_string(char *s); +extern int device_get_config_int(const char *name); +extern int device_get_config_int_ex(const char *s, int default_int); +extern int device_get_config_hex16(const char *name); +extern int device_get_config_hex20(const char *name); +extern int device_get_config_mac(const char *name, int default_int); +extern void device_set_config_int(const char *s, int val); +extern void device_set_config_hex16(const char *s, int val); +extern void device_set_config_hex20(const char *s, int val); +extern void device_set_config_mac(const char *s, int val); +extern const char *device_get_config_string(const char *name); #ifdef __cplusplus } diff --git a/src/disk/hdc.c b/src/disk/hdc.c index bbb31a1..22eba6e 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.10 2018/04/23 + * Version: @(#)hdc.c 1.0.12 2018/04/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -112,10 +112,8 @@ static const struct { { "[ISA] [ST506] DTC-5150X Fixed Disk Adapter", "st506_dtc5150x", &st506_xt_dtc5150x_device, 1 }, -#ifdef USE_XTA - { "[ISA] [IDE] PC/XT IDE (XTA) Adapter", "xta_isa", - &xta_isa_device, 0, }, -#endif + { "[ISA] [IDE] WDXT-150 IDE (XTA) Adapter", "xta_wdxt150", + &xta_wdxt150_device, 0, }, { "[ISA] [IDE] PC/XT XTIDE (ATA)", "xtide", &xtide_device, 0 }, @@ -213,6 +211,7 @@ hdc_get_internal_name(int hdc) } + const device_t * hdc_get_device(int hdc) { @@ -220,6 +219,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 3ed627f..39c1874 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.10 2018/04/23 + * Version: @(#)hdc.h 1.0.13 2018/04/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -62,8 +62,8 @@ extern const device_t st506_at_wd1003_device; /* st506_at_wd1003 */ extern const device_t esdi_at_wd1007vse1_device; /* esdi_at */ extern const device_t esdi_ps2_device; /* esdi_mca */ -extern const device_t xta_isa_device; /* xta_isa */ -extern const device_t xta_ps1_device; /* xta_ps1 */ +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_acculogic_device; /* xtide_ps2 */ @@ -87,6 +87,7 @@ extern void hdc_reset(void); extern const char *hdc_get_name(int hdc); extern const char *hdc_get_internal_name(int hdc); +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_ide_xta.c b/src/disk/hdc_ide_xta.c new file mode 100644 index 0000000..24f33fb --- /dev/null +++ b/src/disk/hdc_ide_xta.c @@ -0,0 +1,1201 @@ +/* + * 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.3 2018/04/25 + * + * 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 "../emu.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 XTA_NUM 2 /* we support 2 drives */ + +#define WD_BIOS_FILE L"disk/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; + + +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) { + hdc_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) { + hdc_log("%s: get_sector: past end of heads\n", dev->name); + dev->sense = ERR_ILLADDR; + return(1); + } + + if (dev->sector >= drive->spt) { + hdc_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; + +#ifdef ENABLE_HDC_LOG + hdc_log("%s: format_%s(%d) %d,%d\n", dev->name, + (dcb->cmd==CMD_FORMAT_DRIVE)?"drive":"track", + drive->id, dev->track, dev->head); +#endif + /* Activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_IDE, 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_IDE, 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: +#ifdef ENABLE_HDC_LOG + hdc_log("%s: test_ready(%d) ready=%d\n", + dev->name, dcb->drvsel, drive->present); +#endif + if (! drive->present) { + dev->comp |= COMP_ERR; + dev->sense = ERR_NOTRDY; + } + set_intr(dev); + break; + + case CMD_RECALIBRATE: +#ifdef ENABLE_HDC_LOG + hdc_log("%s: recalibrate(%d) ready=%d\n", + dev->name, dcb->drvsel, drive->present); +#endif + 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: +#ifdef ENABLE_HDC_LOG + hdc_log("%s: sense(%d)\n", + dev->name, dcb->drvsel); +#endif + 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_IDE, 1); +#ifdef ENABLE_HDC_LOG + hdc_log("%s: read_%s(%d: %d,%d,%d) cnt=%d\n", + dev->name, (no_data)?"verify":"sector", + drive->id, dev->track, dev->head, + dev->sector, dev->count); +#endif +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_IDE, 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) { + hdc_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) { +#ifdef ENABLE_HDC_LOG + hdc_log("%s: read_%s(%d) DONE\n", + dev->name, + (no_data)?"verify":"sector", + drive->id); +#endif + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_IDE, 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_IDE, 1); +#ifdef ENABLE_HDC_LOG + hdc_log("%s: write_%s(%d: %d,%d,%d) cnt=%d\n", + dev->name, (no_data)?"verify":"sector", + dcb->drvsel, dev->track, + dev->head, dev->sector, dev->count); +#endif +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) { + hdc_log("%s: CMD_WRITE_SECTORS out of data (idx=%d, len=%d)!\n", dev->name, dev->buf_idx, dev->buf_len); + + hdc_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_IDE, 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) { +#ifdef ENABLE_HDC_LOG + hdc_log("HDC: write_%s(%d) DONE\n", + (no_data)?"verify":"sector", + drive->id); +#endif + /* De-activate the status icon. */ + ui_sb_update_icon(SB_HDD|HDD_BUS_IDE, 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)); +#ifdef ENABLE_HDC_LOG + hdc_log("%s: seek(%d) %d/%d ready=%d\n", dev->name, + dcb->drvsel, val, drive->cur_cyl, drive->present); +#endif + 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*/; +#ifdef ENABLE_HDC_LOG + pclog("%s: set_params(%d) cyl=%d,hd=%d,spt=%d\n", + dev->name, dcb->drvsel, drive->tracks, + drive->hpc, drive->spt); +#endif + dev->status &= ~STAT_REQ; + set_intr(dev); + break; + } + break; + + case CMD_WRITE_SECTOR_BUFFER: + switch (dev->state) { + case STATE_IDLE: +#ifdef ENABLE_HDC_LOG + hdc_log("%s: write_sector_buffer()\n", + dev->name); +#endif + 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) { + hdc_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: +#ifdef ENABLE_HDC_LOG + hdc_log("%s: ram_diags\n", dev->name); +#endif + 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: +#ifdef ENABLE_HDC_LOG + hdc_log("%s: drive_diags(%d) ready=%d\n", + dev->name, dcb->drvsel, drive->present); +#endif + 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: +#ifdef ENABLE_HDC_LOG + hdc_log("%s: ctrl_diags\n", dev->name); +#endif + dev->state = STATE_RDONE; + dev->callback = 10*HDC_TIME; + break; + + case STATE_RDONE: + set_intr(dev); + break; + } + break; + + default: + hdc_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) { + hdc_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) { +pclog("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)) { + hdc_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) { + hdc_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 */ +//pclog("%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; + + /* 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; + break; + + case 1: /* EuroPC */ + dev->name = "HD20"; + dev->base = 0x0320; + dev->irq = 5; + dev->dma = 3; + break; + } + + pclog("%s: initializing (I/O=%04X, IRQ=%d, DMA=%d", + dev->name, dev->base, dev->irq, dev->dma); + if (dev->rom_addr != 0x000000) + pclog(", BIOS=%06X", dev->rom_addr); + pclog(")\n"); + + /* Load any disks for this device class. */ + c = 0; + for (i = 0; i < HDD_NUM; i++) { + if ((hdd[i].bus == HDD_BUS_IDE) && (hdd[i].id.ide_channel < XTA_NUM)) { + drive = &dev->drives[hdd[i].id.ide_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; + + pclog("%s: drive%d (cyl=%d,hd=%d,spt=%d), disk %d\n", + dev->name, hdd[i].id.ide_channel, drive->tracks, + drive->hpc, drive->spt, i); + + if (++c > XTA_NUM) 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, 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, + NULL +}; diff --git a/src/dma.c b/src/dma.c index c520eb5..f58914d 100644 --- a/src/dma.c +++ b/src/dma.c @@ -163,6 +163,7 @@ dma_write(uint16_t addr, uint8_t val, void *priv) dma_m |= (1 << (val & 3)); else dma_m &= ~(1 << (val & 3)); +//pclog("DMA: %s mask for channel %d\n", (val&4)?"set":"clear", val&3); return; case 0xb: /*Mode*/ diff --git a/src/machine/m_at_430fx.c b/src/machine/m_at_430fx.c index da97402..53090c0 100644 --- a/src/machine/m_at_430fx.c +++ b/src/machine/m_at_430fx.c @@ -8,7 +8,7 @@ * * Implementation of the Intel 430FX PCISet chip. * - * Version: @(#)m_at_430fx.c 1.0.9 2018/04/15 + * Version: @(#)m_at_430fx.c 1.0.10 2018/04/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -54,10 +54,6 @@ #include "machine.h" -/* Defined in the Video module. */ -extern const device_t s3_phoenix_trio64_onboard_pci_device; - - static uint8_t card_i430fx[256]; diff --git a/src/machine/m_europc.c b/src/machine/m_europc.c index cffbf48..daa56fb 100644 --- a/src/machine/m_europc.c +++ b/src/machine/m_europc.c @@ -66,7 +66,7 @@ * bit 1: b8000 memory available * 0000:046a: 00 jim 250 01 jim 350 * - * Version: @(#)m_europc.c 1.0.7 2018/04/14 + * Version: @(#)m_europc.c 1.0.8 2018/04/24 * * Author: Fred N. van Kempen, * @@ -651,13 +651,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_type == 1) - (void)device_add(&europc_hdc_device); + (void)device_add(&xta_hd20_device); return(sys); } @@ -714,14 +717,13 @@ const device_t europc_device = { void machine_europc_init(const machine_t *model, void *arg) { + machine_common_init(model, arg); + nmi_init(); + /* Clear the machine state. */ memset(&europc, 0x00, sizeof(europc_t)); europc.jim = 0x0250; - machine_common_init(model, arg); - nmi_init(); - mem_add_bios(); - /* This is machine specific. */ europc.nvr.size = model->nvrsz; europc.nvr.irq = -1; @@ -734,9 +736,6 @@ machine_europc_init(const machine_t *model, void *arg) /* 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 b886e0a..0000000 --- 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.5 2018/04/23 - * - * 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 "../emu.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[ST506_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_ST506, 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_ST506, 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_ST506, 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_ST506, 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_ST506, 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_ST506, 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_ST506, 1); - - next_sector(dev, drive); - - dev->buf_idx = 0; - if (--dev->count == 0) { - ui_sb_update_icon(SB_HDD|HDD_BUS_ST506, 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].id.st506_channel]; - - if (! hdd_image_load(i)) { - drive->present = 0; - continue; - } - - /* These are the "hardware" parameters (from the image.) */ - drive->spt = (uint8_t)(hdd[i].spt & 0xff); - drive->hpc = (uint8_t)(hdd[i].hpc & 0xff); - drive->tracks = (uint16_t)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].id.st506_channel,drive->tracks,drive->hpc,drive->spt,i); - - if (++c > ST506_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/machine.h b/src/machine/machine.h index cb03870..81982ef 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.19 2018/04/20 + * Version: @(#)machine.h 1.0.20 2018/04/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -234,147 +234,147 @@ extern int romspresent[ROM_MAX]; /* Core functions. */ -extern int machine_count(void); -extern int machine_getromset(void); -extern int machine_getmachine(int romset); +extern int machine_count(void); +extern int machine_getromset(void); +extern int machine_getmachine(int romset); extern const char *machine_getname(void); extern const char *machine_get_internal_name(void); -extern int machine_get_machine_from_internal_name(const char *s); -extern int machine_available(int id); -extern int machine_detect(void); -extern void machine_init(void); -extern void machine_close(void); +extern int machine_get_machine_from_internal_name(const char *s); +extern int machine_available(int id); +extern int machine_detect(void); +extern void machine_init(void); +extern void machine_close(void); #ifdef EMU_DEVICE_H extern const device_t *machine_getdevice(int machine); #endif -extern int machine_getromset_ex(int m); +extern int machine_getromset_ex(int m); extern const char *machine_get_internal_name_ex(int m); -extern void machine_close(void); +extern int machine_get_config_int(const char *s); +extern const char *machine_get_config_string(const char *s); /* Initialization functions for boards and systems. */ -extern void machine_common_init(const machine_t *, void *); +extern void machine_common_init(const machine_t *, void *); -extern void machine_at_common_init(const machine_t *, void *); -extern void machine_at_init(const machine_t *, void *); -extern void machine_at_ps2_init(const machine_t *, void *); -extern void machine_at_common_ide_init(const machine_t *, void *); -extern void machine_at_ide_init(const machine_t *, void *); -extern void machine_at_ps2_ide_init(const machine_t *, void *); -extern void machine_at_top_remap_init(const machine_t *, void *); -extern void machine_at_ide_top_remap_init(const machine_t *, void *); +extern void machine_at_common_init(const machine_t *, void *); +extern void machine_at_init(const machine_t *, void *); +extern void machine_at_ps2_init(const machine_t *, void *); +extern void machine_at_common_ide_init(const machine_t *, void *); +extern void machine_at_ide_init(const machine_t *, void *); +extern void machine_at_ps2_ide_init(const machine_t *, void *); +extern void machine_at_top_remap_init(const machine_t *, void *); +extern void machine_at_ide_top_remap_init(const machine_t *, void *); -extern void machine_at_ibm_init(const machine_t *, void *); +extern void machine_at_ibm_init(const machine_t *, void *); -extern void machine_at_t3100e_init(const machine_t *, void *); +extern void machine_at_t3100e_init(const machine_t *, void *); -extern void machine_at_p54tp4xe_init(const machine_t *, void *); -extern void machine_at_endeavor_init(const machine_t *, void *); +extern void machine_at_p54tp4xe_init(const machine_t *, void *); +extern void machine_at_endeavor_init(const machine_t *, void *); #ifdef EMU_DEVICE_H -extern const device_t s3_phoenix_trio64_onboard_pci_device; -#define m_at_endeavor_device s3_phoenix_trio64_onboard_pci_device +extern const device_t s3_phoenix_trio64_onboard_pci_device; #endif -extern void machine_at_zappa_init(const machine_t *, void *); -extern void machine_at_mb500n_init(const machine_t *, void *); -extern void machine_at_president_init(const machine_t *, void *); -extern void machine_at_thor_init(const machine_t *, void *); +extern void machine_at_zappa_init(const machine_t *, void *); +extern void machine_at_mb500n_init(const machine_t *, void *); +extern void machine_at_president_init(const machine_t *, void *); +extern void machine_at_thor_init(const machine_t *, void *); -extern void machine_at_acerm3a_init(const machine_t *, void *); -extern void machine_at_acerv35n_init(const machine_t *, void *); -extern void machine_at_ap53_init(const machine_t *, void *); -extern void machine_at_p55t2p4_init(const machine_t *, void *); -extern void machine_at_p55t2s_init(const machine_t *, void *); +extern void machine_at_acerm3a_init(const machine_t *, void *); +extern void machine_at_acerv35n_init(const machine_t *, void *); +extern void machine_at_ap53_init(const machine_t *, void *); +extern void machine_at_p55t2p4_init(const machine_t *, void *); +extern void machine_at_p55t2s_init(const machine_t *, void *); -extern void machine_at_batman_init(const machine_t *, void *); -extern void machine_at_plato_init(const machine_t *, void *); +extern void machine_at_batman_init(const machine_t *, void *); +extern void machine_at_plato_init(const machine_t *, void *); -extern void machine_at_p55tvp4_init(const machine_t *, void *); -extern void machine_at_i430vx_init(const machine_t *, void *); -extern void machine_at_p55va_init(const machine_t *, void *); +extern void machine_at_p55tvp4_init(const machine_t *, void *); +extern void machine_at_i430vx_init(const machine_t *, void *); +extern void machine_at_p55va_init(const machine_t *, void *); #if defined(DEV_BRANCH) && defined(USE_I686) -extern void machine_at_i440fx_init(const machine_t *, void *); -extern void machine_at_s1668_init(const machine_t *, void *); +extern void machine_at_i440fx_init(const machine_t *, void *); +extern void machine_at_s1668_init(const machine_t *, void *); #endif -extern void machine_at_ali1429_init(const machine_t *, void *); -extern void machine_at_cmdpc_init(const machine_t *, void *); +extern void machine_at_ali1429_init(const machine_t *, void *); +extern void machine_at_cmdpc_init(const machine_t *, void *); -extern void machine_at_headland_init(const machine_t *, void *); -extern void machine_at_neat_init(const machine_t *, void *); -extern void machine_at_neat_ami_init(const machine_t *, void *); -extern void machine_at_opti495_init(const machine_t *, void *); -extern void machine_at_opti495_ami_init(const machine_t *, void *); -extern void machine_at_scat_init(const machine_t *, void *); -extern void machine_at_scatsx_init(const machine_t *, void *); -extern void machine_at_compaq_init(const machine_t *, void *); +extern void machine_at_headland_init(const machine_t *, void *); +extern void machine_at_neat_init(const machine_t *, void *); +extern void machine_at_neat_ami_init(const machine_t *, void *); +extern void machine_at_opti495_init(const machine_t *, void *); +extern void machine_at_opti495_ami_init(const machine_t *, void *); +extern void machine_at_scat_init(const machine_t *, void *); +extern void machine_at_scatsx_init(const machine_t *, void *); +extern void machine_at_compaq_init(const machine_t *, void *); -extern void machine_at_dtk486_init(const machine_t *, void *); -extern void machine_at_r418_init(const machine_t *, void *); +extern void machine_at_dtk486_init(const machine_t *, void *); +extern void machine_at_r418_init(const machine_t *, void *); -extern void machine_at_wd76c10_init(const machine_t *, void *); +extern void machine_at_wd76c10_init(const machine_t *, void *); #if defined(DEV_BRANCH) && defined(USE_GREENB) -extern void machine_at_4gpv31_init(const machine_t *, void *); +extern void machine_at_4gpv31_init(const machine_t *, void *); #endif -extern void machine_pcjr_init(const machine_t *, void *); +extern void machine_pcjr_init(const machine_t *, void *); #ifdef EMU_DEVICE_H extern const device_t m_pcjr_device; #endif -extern void machine_ps1_m2011_init(const machine_t *, void *); -extern void machine_ps1_m2121_init(const machine_t *, void *); -extern void machine_ps1_m2133_init(const machine_t *, void *); +extern void machine_ps1_m2011_init(const machine_t *, void *); +extern void machine_ps1_m2121_init(const machine_t *, void *); +extern void machine_ps1_m2133_init(const machine_t *, void *); #ifdef EMU_DEVICE_H -extern void ps1_hdc_inform(void *, void *); -extern void ps1_set_feedback(void *); +extern void ps1_hdc_inform(void *, void *); +extern void ps1_set_feedback(void *); extern const device_t m_ps1_device; extern const device_t ps1_hdc_device; #endif -extern void machine_ps2_m30_286_init(const machine_t *, void *); -extern void machine_ps2_model_50_init(const machine_t *, void *); -extern void machine_ps2_model_55sx_init(const machine_t *, void *); -extern void machine_ps2_model_70_type3_init(const machine_t *, void *); -extern void machine_ps2_model_70_type4_init(const machine_t *, void *); -extern void machine_ps2_model_80_init(const machine_t *, void *); +extern void machine_ps2_m30_286_init(const machine_t *, void *); +extern void machine_ps2_model_50_init(const machine_t *, void *); +extern void machine_ps2_model_55sx_init(const machine_t *, void *); +extern void machine_ps2_model_70_type3_init(const machine_t *, void *); +extern void machine_ps2_model_70_type4_init(const machine_t *, void *); +extern void machine_ps2_model_80_init(const machine_t *, void *); -extern void machine_amstrad_init(const machine_t *, void *); +extern void machine_amstrad_init(const machine_t *, void *); -extern void machine_europc_init(const machine_t *, void *); +extern void machine_europc_init(const machine_t *, void *); #ifdef EMU_DEVICE_H -extern const device_t europc_device, europc_hdc_device; +extern const device_t m_europc_device; #endif -extern void machine_olim24_init(const machine_t *, void *); -extern void machine_olim24_video_init(void); +extern void machine_olim24_init(const machine_t *, void *); +extern void machine_olim24_video_init(void); -extern void machine_tandy1k_init(const machine_t *, void *); +extern void machine_tandy1k_init(const machine_t *, void *); #ifdef EMU_DEVICE_H extern const device_t m_tandy1k_device; extern const device_t m_tandy1k_hx_device; extern const device_t m_tandy1k_sl2_device; #endif -extern int tandy1k_eeprom_read(void); +extern int tandy1k_eeprom_read(void); -extern void machine_xt_init(const machine_t *, void *); +extern void machine_xt_init(const machine_t *, void *); #ifdef EMU_DEVICE_H extern const device_t m_xt_device; #endif -extern void machine_xt_compaq_init(const machine_t *, void *); +extern void machine_xt_compaq_init(const machine_t *, void *); #if defined(DEV_BRANCH) && defined(USE_LASERXT) -extern void machine_xt_laserxt_init(const machine_t *, void *); +extern void machine_xt_laserxt_init(const machine_t *, void *); #endif -extern void machine_xt_t1000_init(const machine_t *, void *); +extern void machine_xt_t1000_init(const machine_t *, void *); #ifdef EMU_DEVICE_H extern const device_t m_xt_t1000_device; #endif -extern void machine_xt_t1200_init(const machine_t *, void *); -extern void machine_xt_t1x00_close(void); +extern void machine_xt_t1200_init(const machine_t *, void *); +extern void machine_xt_t1x00_close(void); -extern void machine_xt_xi8088_init(const machine_t *, void *); +extern void machine_xt_xi8088_init(const machine_t *, void *); #ifdef EMU_DEVICE_H extern const device_t m_xi8088_device; #endif diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index c4a49eb..f42067e 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.19 2018/04/20 + * Version: @(#)machine_table.c 1.0.20 2018/04/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -44,6 +44,7 @@ #include #include #include "../emu.h" +#include "../config.h" #include "../cpu/cpu.h" #include "../mem.h" #include "../nvr.h" @@ -142,7 +143,7 @@ const machine_t machines[] = { { "[Socket 5 NX] Intel Premiere/PCI II", ROM_PLATO, "intel_plato", L"intel/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, 128, machine_at_plato_init, NULL, NULL }, { "[Socket 5 FX] ASUS P/I-P54TP4XE", ROM_P54TP4XE, "asus_p54tp4xe", L"asus/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, 128, machine_at_p54tp4xe_init, NULL, NULL }, - { "[Socket 5 FX] Intel Advanced/EV", ROM_ENDEAVOR, "intel_endeavor", L"intel/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, 128, machine_at_endeavor_init, &m_at_endeavor_device, NULL }, + { "[Socket 5 FX] Intel Advanced/EV", ROM_ENDEAVOR, "intel_endeavor", L"intel/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, 128, machine_at_endeavor_init, &s3_phoenix_trio64_onboard_pci_device, NULL }, { "[Socket 5 FX] Intel Advanced/ZP", ROM_ZAPPA, "intel_zappa", L"intel/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, 128, machine_at_zappa_init, NULL, NULL }, { "[Socket 5 FX] PC Partner MB500N", ROM_MB500N, "pcpartner_mb500n", L"pcpartner/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, 128, machine_at_mb500n_init, NULL, NULL }, { "[Socket 5 FX] President Award 430FX PCI",ROM_PRESIDENT, "president", L"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, 128, machine_at_president_init, NULL, NULL }, @@ -269,3 +270,43 @@ machine_get_machine_from_internal_name(const char *s) /* Not found. */ return(-1); } + + +int +machine_get_config_int(const char *s) +{ + const device_t *d = machine_getdevice(machine); + const device_config_t *c; + + if (d == NULL) return(0); + + c = d->config; + while (c && c->type != -1) { + if (! strcmp(s, c->name)) + return(config_get_int(d->name, s, c->default_int)); + + c++; + } + + return(0); +} + + +const char * +machine_get_config_string(const char *s) +{ + const device_t *d = machine_getdevice(machine); + const device_config_t *c; + + if (d == NULL) return(0); + + c = d->config; + while (c && c->type != -1) { + if (! strcmp(s, c->name)) + return(config_get_string(d->name, s, c->default_string)); + + c++; + } + + return(NULL); +} diff --git a/src/rom_load.c b/src/rom_load.c index 70ae92d..9f0eed5 100644 --- a/src/rom_load.c +++ b/src/rom_load.c @@ -17,7 +17,7 @@ * or to use a generic handler, and then pass it a pointer * to a command table. For now, we don't. * - * Version: @(#)rom_load.c 1.0.7 2018/04/01 + * Version: @(#)rom_load.c 1.0.8 2018/04/25 * * Author: Fred N. van Kempen, * @@ -60,6 +60,7 @@ #include #include #include "emu.h" +#include "machine/machine.h" #include "mem.h" #include "rom.h" #include "device.h" diff --git a/src/sound/midi_fluidsynth.c b/src/sound/midi_fluidsynth.c index 5ebee57..3e416bb 100644 --- a/src/sound/midi_fluidsynth.c +++ b/src/sound/midi_fluidsynth.c @@ -17,7 +17,7 @@ * website (for 32bit and 64bit Windows) are working, and * need no additional support files other than sound fonts. * - * Version: @(#)midi_fluidsynth.c 1.0.6 2018/03/31 + * Version: @(#)midi_fluidsynth.c 1.0.7 2018/04/25 * * Code borrowed from scummvm. * @@ -293,7 +293,7 @@ fluidsynth_init(const device_t *info) data->synth = f_new_fluid_synth(data->settings); - char* sound_font = device_get_config_string("sound_font"); + const char *sound_font = device_get_config_string("sound_font"); data->sound_font = f_fluid_synth_sfload(data->synth, sound_font, 1); if (device_get_config_int("chorus")) { diff --git a/src/win/VARCem.rc b/src/win/VARCem.rc index cc34520..bc3bb04 100644 --- a/src/win/VARCem.rc +++ b/src/win/VARCem.rc @@ -8,7 +8,7 @@ * * Application resource script for Windows. * - * Version: @(#)VARCem.rc 1.0.20 2018/04/23 + * Version: @(#)VARCem.rc 1.0.21 2018/04/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -542,8 +542,9 @@ 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 | diff --git a/src/win/mingw/Makefile.MinGW b/src/win/mingw/Makefile.MinGW index 7f40c02..4ae9760 100644 --- a/src/win/mingw/Makefile.MinGW +++ b/src/win/mingw/Makefile.MinGW @@ -8,7 +8,7 @@ # # Makefile for Windows systems using the MinGW32 environment. # -# Version: @(#)Makefile.mingw 1.0.28 2018/04/23 +# Version: @(#)Makefile.mingw 1.0.30 2018/04/24 # # Author: Fred N. van Kempen, # @@ -119,9 +119,6 @@ endif ifndef I686 I686 := n endif -ifndef XTA - XTA := n -endif ifndef OPENAL OPENAL := y endif @@ -447,10 +444,6 @@ ifeq ($(DEV_BRANCH), y) DEVBROBJ += m_at_440fx.o endif - ifeq ($(XTA), y) - OPTS += -DUSE_XTA - endif - ifeq ($(STEALTH32), y) OPTS += -DUSE_STEALTH32 DEVBROBJ += vid_icd2061.o @@ -510,8 +503,7 @@ MCHOBJ := machine.o machine_table.o \ m_xt_t1000.o m_xt_t1000_vid.o \ m_xt_xi8088.o \ m_pcjr.o \ - m_amstrad.o \ - m_europc.o m_europc_hdc.o \ + m_amstrad.o m_europc.o \ m_olivetti_m24.o m_tandy.o \ m_at.o \ m_at_ali1429.o m_at_commodore.o \ @@ -547,10 +539,7 @@ HDDOBJ := hdd.o \ hdc.o \ hdc_st506_xt.o hdc_st506_at.o \ hdc_esdi_at.o hdc_esdi_mca.o \ - hdc_ide.o hdc_xtide.o -ifeq ($(XTA), y) -HDDOBJ += hdc_ide_xta.o -endif + hdc_ide.o hdc_xtide.o hdc_ide_xta.o CDROMOBJ := cdrom.o \ cdrom_dosbox.o cdrom_image.o cdrom_null.o diff --git a/src/win/msvc/Makefile.VC b/src/win/msvc/Makefile.VC index bb7c703..58eb227 100644 --- a/src/win/msvc/Makefile.VC +++ b/src/win/msvc/Makefile.VC @@ -8,7 +8,7 @@ # # Makefile for Windows using Visual Studio 2015. # -# Version: @(#)Makefile.VC 1.0.14 2018/04/23 +# Version: @(#)Makefile.VC 1.0.16 2018/04/24 # # Author: Fred N. van Kempen, # @@ -119,9 +119,6 @@ endif ifndef I686 I686 := n endif -ifndef XTA - XTA := n -endif ifndef OPENAL OPENAL := y endif @@ -415,10 +412,6 @@ ifeq ($(DEV_BRANCH), y) DEVBROBJ += m_at_440fx.obj endif - ifeq ($(XTA), y) - OPTS += -DUSE_XTA - endif - ifeq ($(STEALTH32), y) OPTS += -DUSE_STEALTH32 DEVBROBJ += vid_icd2061.obj @@ -475,8 +468,7 @@ MCHOBJ := machine.obj machine_table.obj \ m_xt_t1000.obj m_xt_t1000_vid.obj \ m_xt_xi8088.obj \ m_pcjr.obj \ - m_amstrad.obj \ - m_europc.obj m_europc_hdc.obj \ + m_amstrad.obj m_europc.obj \ m_olivetti_m24.obj m_tandy.obj \ m_at.obj \ m_at_ali1429.obj m_at_commodore.obj \ @@ -512,10 +504,7 @@ HDDOBJ := hdd.obj \ hdc.obj \ hdc_st506_xt.obj hdc_st506_at.obj \ hdc_esdi_at.obj hdc_esdi_mca.obj \ - hdc_ide.obj hdc_xtide.obj -ifeq ($(XTA), y) -HDDOBJ += hdc_ide_xta.o -#endif + hdc_ide.obj hdc_xtide.obj hdc_ide_xta.o CDROMOBJ := cdrom.obj \ cdrom_dosbox.obj cdrom_image.obj cdrom_null.obj diff --git a/src/win/resource.h b/src/win/resource.h index 6dfc76c..e4f0e14 100644 --- a/src/win/resource.h +++ b/src/win/resource.h @@ -8,7 +8,7 @@ * * Windows resource defines. * - * Version: @(#)resource.h 1.0.10 2018/04/08 + * Version: @(#)resource.h 1.0.11 2018/04/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -178,9 +178,10 @@ #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_COMBO_IDE_TER 1125 +#define IDC_COMBO_IDE_QUA 1126 +#define IDC_CHECK_BUGGER 1127 #define IDC_HARD_DISKS 1130 /* hard disk config */ #define IDC_LIST_HARD_DISKS 1131 diff --git a/src/win/win_devconf.c b/src/win/win_devconf.c index 4a73963..a17fbbf 100644 --- a/src/win/win_devconf.c +++ b/src/win/win_devconf.c @@ -12,7 +12,7 @@ * and builds a complete Win32 DIALOG resource block in a * buffer in memory, and then passes that to the API handler. * - * Version: @(#)win_devconf.c 1.0.10 2018/04/14 + * Version: @(#)win_devconf.c 1.0.11 2018/04/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -476,11 +476,11 @@ deviceconfig_open(HWND hwnd, device_t *device) *data++ = 0; /* no menu bar */ *data++ = 0; /* predefined dialog box class */ sprintf(temp, "%s Configuration", device->name); - data += MultiByteToWideChar(CP_ACP, 0, temp, -1, data, 50); + data += MultiByteToWideChar(CP_ACP, 0, temp, -1, data, 120); /* Font style and size to use. */ *data++ = 9; /* point size */ - 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_settings_periph.h b/src/win/win_settings_periph.h index 60638f3..bc59368 100644 --- a/src/win/win_settings_periph.h +++ b/src/win/win_settings_periph.h @@ -8,7 +8,7 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings_periph.h 1.0.3 2018/04/10 + * Version: @(#)win_settings_periph.h 1.0.4 2018/04/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -171,6 +171,12 @@ peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) else EnableWindow(h, FALSE); + h = GetDlgItem(hdlg, IDC_CONFIGURE_HDC); + if (hdc_has_config(temp_hdc_type)) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + recalc_hdc_list(hdlg, temp_machine, 0); h = GetDlgItem(hdlg, IDC_COMBO_IDE_TER); @@ -209,6 +215,13 @@ peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) temp_deviceconfig |= deviceconfig_open(hdlg, (void *)scsi_card_getdevice(temp_scsi_card)); break; + 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)]); + + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)hdc_get_device(temp_hdc_type)); + break; + case IDC_COMBO_SCSI: h = GetDlgItem(hdlg, IDC_COMBO_SCSI); temp_scsi_card = list_to_scsi[SendMessage(h, CB_GETCURSEL, 0, 0)]; @@ -219,6 +232,17 @@ peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) else EnableWindow(h, FALSE); break; + + 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_CONFIGURE_HDC); + if (hdc_has_config(temp_hdc_type)) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + break; } return FALSE; diff --git a/src/win/win_stbar.c b/src/win/win_stbar.c index e39baf1..5f082ab 100644 --- a/src/win/win_stbar.c +++ b/src/win/win_stbar.c @@ -8,7 +8,7 @@ * * Implementation of the Status Bar module. * - * Version: @(#)win_stbar.c 1.0.10 2018/04/23 + * Version: @(#)win_stbar.c 1.0.11 2018/04/24 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -667,7 +667,7 @@ ui_sb_update_panes(void) /* Could be Internal or External IDE.. */ if (((cdrom_drives[i].bus_type==CDROM_BUS_ATAPI_PIO_ONLY) && (cdrom_drives[i].bus_type==CDROM_BUS_ATAPI_PIO_AND_DMA)) && - !(hdint || !strncmp(hdc, "ide", 3))) { + !(hdint || !strncmp(hdc, "ide", 3) || !strncmp(hdc, "xta", 3))) { continue; } @@ -684,7 +684,7 @@ ui_sb_update_panes(void) /* Could be Internal or External IDE.. */ if (((zip_drives[i].bus_type==ZIP_BUS_ATAPI_PIO_ONLY) && (zip_drives[i].bus_type==ZIP_BUS_ATAPI_PIO_AND_DMA)) && - !(hdint || !strncmp(hdc, "ide", 3))) { + !(hdint || !strncmp(hdc, "ide", 3) || !strncmp(hdc, "xta", 3))) { continue; } @@ -710,7 +710,7 @@ ui_sb_update_panes(void) /* ESDI drives, and ESDI or Internal controller. */ sb_parts++; } - if (c_ide_pio && (hdint || !strncmp(hdc, "ide", 3))) { + if (c_ide_pio && (hdint || !strncmp(hdc, "ide", 3) || !strncmp(hdc, "xta", 3))) { /* IDE_PIO drives, and IDE or Internal controller. */ sb_parts++; } @@ -813,7 +813,7 @@ ui_sb_update_panes(void) sb_part_meanings[sb_parts] = SB_HDD | HDD_BUS_ESDI; sb_parts++; } - if (c_ide_pio && (hdint || !strncmp(hdc, "ide", 3))) { + if (c_ide_pio && (hdint || !strncmp(hdc, "ide", 3) || !strncmp(hdc, "xta", 3))) { edge += SB_ICON_WIDTH; iStatusWidths[sb_parts] = edge; sb_part_meanings[sb_parts] = SB_HDD | HDD_BUS_IDE_PIO_ONLY;