Applied all relevant PCem commits;

Extensively cleaned up and changed the CD-ROM code;
Removed CD-ROM IOCTTL (it was causing performance and stability issues);
Turned a lot of things into device_t's;
Added the PS/1 Model 2011 XTA and standalone XTA hard disk controllers, ported from Varcem;
Numerous FDC fixes for the PS/1 Model 2121;
NVR changes ported from Varcem;
The PCap code no longer requires libpcap to be compiled;
Numerous fixes to various SCSI controllers;
Updated NukedOPL to 1.8;
Fixes to OpenAL initialization and closing, should give less Audio issues now;
Revorked parts of the common (S)VGA code (also based on code from QEMU);
Removed the Removable SCSI hard disks (they were a never finished experiment so there was no need to keep them there);
Cleaned up the SCSI hard disk and Iomega ZIP code (but more cleanups of that are coming in the future);
In some occasions (IDE hard disks in multiple sector mode and SCSI hard disks) the status bar icon is no longer updated, should improve performance a bit;
Redid the way the tertiary and quaternary IDE controllers are configured (and they are now device_t's);
Extensively reworked the IDE code and fixed quite a few bugs;
Fixes to XT MFM, AT MFM, and AT ESDI code;
Some changes to XTIDE and MCA ESDI code;
Some fixes to the CD-ROM image handler.
This commit is contained in:
OBattler
2018-04-25 23:51:13 +02:00
parent 2789adca0e
commit a412ceb4d9
151 changed files with 21026 additions and 21058 deletions

View File

@@ -8,7 +8,7 @@
*
* Main include file for the application.
*
* Version: @(#)86box.h 1.0.21 2018/03/19
* Version: @(#)86box.h 1.0.22 2018/03/28
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -100,7 +100,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 */
@@ -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);

View File

@@ -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.11 2018/03/26
#
# Author: Fred N. van Kempen, <decwiz@yahoo.com>
#
@@ -38,6 +38,7 @@ STUFF :=
# -DENABLE_KEYBOARD_AT_LOG=N sets logging level at N.
# -DENABLE_KEYBOARD_LOG=N sets logging level at N.
# -DENABLE_PCI_LOG=N sets logging level at N.
# -DENABLE_PIIX_LOG=N sets logging level at N.
# -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.

File diff suppressed because it is too large Load Diff

View File

@@ -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.11 2018/03/26
*
* Author: Miran Grca, <mgrca8@gmail.com>
*
@@ -19,22 +19,22 @@
#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
@@ -46,177 +46,106 @@
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, scsi_device_lun,
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];
#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 +153,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 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);

View File

@@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@@ -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, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2016 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
* Copyright 2016-2018 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#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
};

View File

@@ -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, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* 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);

View File

@@ -8,7 +8,7 @@
*
* Configuration file handler.
*
* Version: @(#)config.c 1.0.46 2018/03/18
* Version: @(#)config.c 1.0.47 2018/03/26
*
* Authors: Sarah Walker,
* Miran Grca, <mgrca8@gmail.com>
@@ -31,11 +31,10 @@
#include <inttypes.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"
@@ -47,6 +46,7 @@
#include "mouse.h"
#include "network/network.h"
#include "scsi/scsi.h"
#include "cdrom/cdrom.h"
#include "sound/sound.h"
#include "sound/midi.h"
#include "sound/snd_dbopl.h"
@@ -522,7 +522,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 +535,11 @@ 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);
}
video_speed = config_get_int(cat, "video_speed", -1);
voodoo_enabled = !!config_get_int(cat, "voodoo", 0);
}
@@ -612,12 +611,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");
@@ -714,8 +713,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 +745,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 +762,15 @@ 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;
memset(temp, '\0', sizeof(temp));
for (c=0; c<HDD_NUM; c++) {
sprintf(temp, "hdd_%02i_parameters", c+1);
p = config_get_string(cat, temp, "0, 0, 0, 0, none");
if (tally_char(p, ',') == 3) {
sscanf(p, "%" PRIu64 ", %" PRIu64", %" PRIu64 ", %s",
&hdd[c].spt, &hdd[c].hpc, &hdd[c].tracks, s);
hdd[c].wp = 0;
} else {
sscanf(p, "%" PRIu64 ", %" PRIu64", %" PRIu64 ", %i, %s",
&hdd[c].spt, &hdd[c].hpc, &hdd[c].tracks, (int *)&hdd[c].wp, s);
}
sscanf(p, "%u, %u, %u, %i, %s",
&hdd[c].spt, &hdd[c].hpc, &hdd[c].tracks, (int *)&hdd[c].wp, s);
hdd[c].bus = hdd_string_to_bus(s, 0);
switch(hdd[c].bus) {
@@ -815,21 +786,19 @@ load_hard_disks(void)
break;
case HDD_BUS_ESDI:
case HDD_BUS_XTIDE:
case HDD_BUS_XTA:
max_spt = 63;
max_hpc = 16;
max_tracks = 1023;
break;
case HDD_BUS_IDE_PIO_ONLY:
case HDD_BUS_IDE_PIO_AND_DMA:
case HDD_BUS_IDE:
max_spt = 63;
max_hpc = 16;
max_tracks = 266305;
break;
case HDD_BUS_SCSI:
case HDD_BUS_SCSI_REMOVABLE:
max_spt = 99;
max_hpc = 255;
max_tracks = 266305;
@@ -850,10 +819,10 @@ load_hard_disks(void)
else
config_delete_var(cat, temp);
/* XT IDE */
sprintf(temp, "hdd_%02i_xtide_channel", c+1);
if (hdd[c].bus == HDD_BUS_XTIDE)
hdd[c].xtide_channel = !!config_get_int(cat, temp, c & 1);
/* XTA */
sprintf(temp, "hdd_%02i_xta_channel", c+1);
if (hdd[c].bus == HDD_BUS_XTA)
hdd[c].xta_channel = !!config_get_int(cat, temp, c & 1);
else
config_delete_var(cat, temp);
@@ -865,21 +834,21 @@ load_hard_disks(void)
config_delete_var(cat, temp);
/* IDE */
// FIXME: Remove in a month.
sprintf(temp, "hdd_%02i_xtide_channel", c+1);
if (hdd[c].bus == HDD_BUS_IDE)
hdd[c].ide_channel = !!config_get_int(cat, temp, c & 1);
else
config_delete_var(cat, temp);
sprintf(temp, "hdd_%02i_ide_channel", c+1);
if ((hdd[c].bus == HDD_BUS_IDE_PIO_ONLY) ||
(hdd[c].bus == HDD_BUS_IDE_PIO_AND_DMA)) {
if (hdd[c].bus == HDD_BUS_IDE) {
sprintf(tmp2, "%01u:%01u", 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;
@@ -889,12 +858,11 @@ 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)) {
if (hdd[c].bus == HDD_BUS_SCSI) {
sprintf(tmp2, "%02u:%02u", c, 0);
p = config_get_string(cat, temp, tmp2);
sscanf(p, "%02u:%02u",
sscanf(p, "%02i:%02i",
(int *)&hdd[c].scsi_id, (int *)&hdd[c].scsi_lun);
if (hdd[c].scsi_id > 15)
@@ -956,181 +924,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<FDD_NUM; c++) {
sprintf(temp, "fdd_%02i_type", c+1);
p = config_get_string(cat, temp, (c < 2) ? "525_2dd" : "none");
fdd_set_type(c, fdd_get_from_internal_name(p));
if (fdd_get_type(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<CDROM_NUM; c++) {
sprintf(temp, "cdrom_%02i_host_drive", c+1);
cdrom_drives[c].host_drive = config_get_int(cat, temp, 0);
cdrom_drives[c].prev_host_drive = cdrom_drives[c].host_drive;
sprintf(temp, "cdrom_%02i_parameters", c+1);
p = config_get_string(cat, temp, NULL);
if (p != NULL)
sscanf(p, "%01u, %s", &cdrom_drives[c].sound_on, s);
else
sscanf("0, none", "%01u, %s", &cdrom_drives[c].sound_on, s);
cdrom_drives[c].bus_type = hdd_string_to_bus(s, 1);
/* Default values, needed for proper operation of the Settings dialog. */
cdrom_drives[c].ide_channel = cdrom_drives[c].scsi_device_id = c + 2;
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)) {
sprintf(tmp2, "%01u:%01u", (c+2)>>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)
@@ -1235,20 +1028,13 @@ load_other_removable_devices(void)
cdrom_drives[c].ide_channel = cdrom_drives[c].scsi_device_id = c + 2;
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) {
sprintf(tmp2, "%01u:%01u", (c+2)>>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;
@@ -1335,20 +1121,13 @@ 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;
@@ -1420,16 +1199,28 @@ load_other_removable_devices(void)
void
config_load(void)
{
int i;
pclog("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;
#ifdef USE_LANGUAGE
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");
video_speed = -1;
enable_sync = 1;
joystick_type = 7;
if (hdc_name) {
@@ -1438,12 +1229,20 @@ 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);
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);
fdd_set_turbo(i, 0);
fdd_set_check_bpb(i, 1);
}
mem_size = 640;
opl_type = 0;
pclog("Config file not present or invalid!\n");
return;
@@ -1460,7 +1259,6 @@ 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;
@@ -1730,10 +1528,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 +1619,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 +1628,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 +1661,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,9 +1674,9 @@ 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);
@@ -1891,7 +1687,7 @@ save_hard_disks(void)
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);
@@ -1899,7 +1695,7 @@ save_hard_disks(void)
}
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))) {
if (! hdd_is_valid(c) || (hdd[c].bus != HDD_BUS_SCSI)) {
config_delete_var(cat, temp);
} else {
sprintf(tmp2, "%02u:%02u", hdd[c].scsi_id, hdd[c].scsi_lun);
@@ -2002,10 +1798,9 @@ 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);
@@ -2040,10 +1835,9 @@ 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);
@@ -2157,7 +1951,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 +1972,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 +1993,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)

View File

@@ -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.3 2018/04/19
*
* Authors: Sarah Walker, <tommowalker@tommowalker.co.uk>
* Miran Grca, <mgrca8@gmail.com>
@@ -58,9 +58,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"
@@ -648,7 +645,6 @@ void resetx86()
#endif
x86_was_reset = 1;
port_92_clear_reset();
scsi_card_reset();
}
void softresetx86()
@@ -658,7 +654,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 +681,6 @@ void softresetx86()
x86seg_reset();
x86_was_reset = 1;
port_92_clear_reset();
scsi_card_reset();
}
static void setznp8(uint8_t val)

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;

View File

@@ -8,7 +8,7 @@
*
* CPU type handler.
*
* Version: @(#)cpu.c 1.0.14 2018/03/11
* Version: @(#)cpu.c 1.0.15 2018/04/08
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* leilei,
@@ -1313,7 +1313,7 @@ void cpu_CPUID()
EDX = CPUID_FPU; /*FPU*/
}
else
EAX = 0;
EAX = EBX = ECX = EDX = 0;
break;
case CPU_iDX4:
@@ -1331,7 +1331,7 @@ void cpu_CPUID()
EDX = CPUID_FPU | CPUID_VME;
}
else
EAX = 0;
EAX = EBX = ECX = EDX = 0;
break;
case CPU_Am486SX:
@@ -1348,7 +1348,7 @@ void cpu_CPUID()
EBX = ECX = EDX = 0; /*No FPU*/
}
else
EAX = 0;
EAX = EBX = ECX = EDX = 0;
break;
case CPU_Am486DX:
@@ -1366,7 +1366,7 @@ void cpu_CPUID()
EDX = CPUID_FPU; /*FPU*/
}
else
EAX = 0;
EAX = EBX = ECX = EDX = 0;
break;
case CPU_WINCHIP:
@@ -1397,7 +1397,7 @@ void cpu_CPUID()
EDX |= CPUID_MMX;
}
else
EAX = 0;
EAX = EBX = ECX = EDX = 0;
break;
case CPU_PENTIUM:
@@ -1415,7 +1415,7 @@ 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
@@ -1435,7 +1435,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 +1487,7 @@ void cpu_CPUID()
EDX = 0x10040120;
}
else
EAX = 0;
EAX = EBX = ECX = EDX = 0;
break;
case CPU_K6:
@@ -1549,7 +1549,7 @@ void cpu_CPUID()
EDX = 0x444D416E;
}
else
EAX = 0;
EAX = EBX = ECX = EDX = 0;
break;
#endif
#endif
@@ -1569,7 +1569,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 +1588,7 @@ void cpu_CPUID()
EDX = CPUID_FPU;
}
else
EAX = 0;
EAX = EBX = ECX = EDX = 0;
break;
@@ -1607,7 +1607,7 @@ void cpu_CPUID()
EDX = CPUID_FPU | CPUID_CMPXCHG8B;
}
else
EAX = 0;
EAX = EBX = ECX = EDX = 0;
break;
@@ -1626,7 +1626,7 @@ void cpu_CPUID()
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B;
}
else
EAX = 0;
EAX = EBX = ECX = EDX = 0;
break;
@@ -1646,7 +1646,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 +1669,7 @@ void cpu_CPUID()
{
}
else
EAX = 0;
EAX = EBX = ECX = EDX = 0;
break;
/* case CPU_PENTIUM2:
@@ -1693,7 +1693,7 @@ void cpu_CPUID()
EDX = 0x0C040843;
}
else
EAX = 0;
EAX = EBX = ECX = EDX = 0;
break; */
case CPU_PENTIUM2D:
@@ -1717,7 +1717,7 @@ void cpu_CPUID()
EDX = 0x0C040844;
}
else
EAX = 0;
EAX = EBX = ECX = EDX = 0;
break;
#endif
#endif
@@ -2260,7 +2260,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;

View File

@@ -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, <http://pcem-emulator.co.uk/>
* 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)

View File

@@ -8,18 +8,20 @@
*
* AMD SYSCALL and SYSRET CPU Instructions.
*
* Version: @(#)x86_ops_amd.h 1.0.1 2018/01/01
* Version: @(#)x86_ops_amd.h 1.0.2 2018/03/26
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016-2018 Miran Grca.
*/
#ifndef internal_illegal
static int internal_illegal(char *s)
{
cpu_state.pc = cpu_state.oldpc;
x86gpf(s, 0);
return cpu_state.abrt;
}
#endif
/* 0 = Limit 0-15
1 = Base 0-15

View File

@@ -8,12 +8,21 @@
*
* 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.3 2018/03/26
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016-2018 Miran Grca.
*/
#ifndef internal_illegal
static int internal_illegal(char *s)
{
cpu_state.pc = cpu_state.oldpc;
x86gpf(s, 0);
return cpu_state.abrt;
}
#endif
/* 0 = Limit 0-15
1 = Base 0-15
2 = Base 16-23 (bits 0-7), Access rights

View File

@@ -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, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* 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);

View File

@@ -24,6 +24,7 @@
#include <wchar.h>
#include "../86box.h"
#include "cpu.h"
#include "../device.h"
#include "../machine/machine.h"
#include "../mem.h"
#include "../nvr.h"

View File

@@ -8,15 +8,15 @@
*
* x87 FPU instructions core.
*
* Version: @(#)x87_ops.h 1.0.1 2017/10/28
* Version: @(#)x87_ops.h 1.0.2 2018/04/05
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* leilei,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016-2017 leilei.
* Copyright 2016,2017 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 leilei.
* Copyright 2016-2018 Miran Grca.
*/
#include <math.h>
#include <fenv.h>
@@ -80,6 +80,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];

View File

@@ -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;
}

View File

@@ -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.6 2018/03/26
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -82,18 +82,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
else
pclog("DEVICE: device init failed\n");
device_priv[c] = NULL;
return(NULL);
}
}
devices[c] = (device_t *)d;
device_priv[c] = priv;
return(priv);
@@ -152,6 +156,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; c<DEVICE_MAX; c++) {
if (devices[c] != NULL) {
if ((devices[c]->reset != NULL) && (devices[c]->flags & DEVICE_PCI))
devices[c]->reset(device_priv[c]);
}
}
}
void *
device_get_priv(const device_t *d)
{

View File

@@ -8,7 +8,7 @@
*
* Definitions for the device handler.
*
* Version: @(#)device.h 1.0.3 2018/03/15
* Version: @(#)device.h 1.0.4 2018/03/26
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -119,6 +119,7 @@ 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);

View File

@@ -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.13 2018/04/04
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -25,6 +25,7 @@
#include "../device.h"
#include "hdc.h"
#include "hdc_ide.h"
#include "hdd.h"
char *hdc_name; /* configured HDC name */
@@ -106,6 +107,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 },
@@ -146,6 +150,9 @@ hdc_init(char *name)
break;
}
}
/* Zero all the hard disk image arrays. */
hdd_image_init();
}
@@ -154,20 +161,17 @@ void
hdc_reset(void)
{
pclog("HDC: reset(current=%d, internal=%d)\n",
hdc_current, (machines[machine].flags & MACHINE_HDC)?1:0);
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 +189,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 +212,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)
{

View File

@@ -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, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -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);

View File

@@ -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.10 2018/04/17
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -104,35 +104,28 @@ typedef struct {
} esdi_t;
static __inline void irq_raise(esdi_t *esdi)
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);
}
if (!(esdi->fdisk&2))
picint(1 << 14);
/* Remember this. */
esdi->irqstat = 1;
}
esdi->irqstat=1;
}
static __inline void irq_lower(esdi_t *esdi)
static inline void
irq_lower(esdi_t *esdi)
{
/* If raised.. */
if (esdi->irqstat) {
/* If enabled in the control register.. */
if (! (esdi->fdisk & 0x02)) {
/* .. drop IRQ14. */
picintc(1<<14);
}
picintc(1 << 14);
}
/* Remember this. */
esdi->irqstat = 0;
}
static void
irq_update(esdi_t *esdi)
{
if (esdi->irqstat && !((pic2.pend|pic2.ins)&0x40) && !(esdi->fdisk & 2))
picint(1 << 14);
}
@@ -384,6 +377,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
esdi->status = STAT_BUSY;
}
esdi->fdisk = val;
irq_update(esdi);
break;
}
}

View File

@@ -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.11 2018/04/17
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -101,8 +101,6 @@ typedef struct esdi_drive {
} drive_t;
typedef struct esdi {
uint16_t base;
int8_t irq;
int8_t dma;
uint32_t bios;
@@ -190,6 +188,7 @@ 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)
@@ -197,14 +196,14 @@ 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 +249,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 +395,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 +457,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 +469,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 +491,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 +507,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 +522,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 +550,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);
@@ -557,8 +576,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 +585,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 +706,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 +731,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;
@@ -739,9 +755,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);
pclog("ESDI: wr(%04x, %02x)\n", port & 7, val);
#endif
switch (port-dev->base) {
switch (port & 7) {
case 2: /*Basic control register*/
if ((dev->basic_ctrl & CTRL_RESET) && !(val & CTRL_RESET)) {
dev->in_reset = 1;
@@ -751,7 +767,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 +781,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 +810,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 +833,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 +864,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;
}
@@ -870,9 +888,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);
pclog("ESDI: wrw(%04x, %04x)\n", port & 7, val);
#endif
switch (port-dev->base) {
switch (port & 7) {
case 0: /*Command Interface Register*/
if (dev->cmd_pos >= 4)
fatal("CIR pos 4\n");
@@ -919,123 +937,55 @@ esdi_mca_write(int port, uint8_t val, void *priv)
pclog("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);
pclog("ESDI: I/O=3510, IRQ=14, DMA=%d, BIOS @%05X\n",
dev->dma, dev->bios);
}
}
@@ -1054,9 +1004,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 +1027,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. */

File diff suppressed because it is too large Load Diff

View File

@@ -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.9 2018/03/26
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -21,59 +21,53 @@
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, specify_success,
mdma_mode, do_initial_read,
spt, hpc,
tracks;
uint32_t secount, sector,
cylinder, head,
drive, cylprecomp,
t_spt, t_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 +75,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*/

View File

@@ -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.14 2018/04/16
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -110,35 +110,28 @@ typedef struct {
} mfm_t;
static __inline void irq_raise(mfm_t *mfm)
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);
}
if (!(mfm->fdisk&2))
picint(1 << 14);
/* Remember this. */
mfm->irqstat = 1;
}
mfm->irqstat=1;
}
static __inline void irq_lower(mfm_t *mfm)
static inline void
irq_lower(mfm_t *mfm)
{
/* If raised.. */
if (mfm->irqstat) {
/* If enabled in the control register.. */
if (! (mfm->fdisk&0x02)) {
/* .. drop IRQ14. */
picintc(1<<14);
}
picintc(1 << 14);
}
/* Remember this. */
mfm->irqstat = 0;
}
static void
irq_update(mfm_t *mfm)
{
if (mfm->irqstat && !((pic2.pend|pic2.ins)&0x40) && !(mfm->fdisk & 2))
picint(1 << 14);
}
@@ -233,6 +226,7 @@ mfm_cmd(mfm_t *mfm, uint8_t val)
}
irq_lower(mfm);
mfm->command = val;
mfm->error = 0;
switch (val & 0xf0) {
@@ -244,13 +238,13 @@ mfm_cmd(mfm_t *mfm, uint8_t val)
#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,6 +252,7 @@ mfm_cmd(mfm_t *mfm, uint8_t val)
break;
default:
mfm->command = val;
switch (val) {
case CMD_READ:
case CMD_READ+1:
@@ -267,7 +262,7 @@ mfm_cmd(mfm_t *mfm, uint8_t val)
pclog("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;
@@ -284,7 +279,7 @@ mfm_cmd(mfm_t *mfm, uint8_t val)
pclog("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 +288,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 +296,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;
@@ -417,7 +410,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 +421,22 @@ 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;
irq_update(mfm);
break;
}
}
@@ -619,19 +613,18 @@ 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:

View File

@@ -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.15 2018/04/18
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -71,7 +71,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"
@@ -429,7 +430,7 @@ mfm_callback(void *priv)
}
hdd_image_zero(drive->hdd_num, addr, 17);
mfm_complete(mfm);
break;
@@ -757,7 +758,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;
}
@@ -859,7 +860,7 @@ mfm_close(void *priv)
static int
xebec_available(void)
{
return(rom_present(XEBEC_BIOS_FILE));
return(rom_present(XEBEC_BIOS_FILE));
}
@@ -884,7 +885,7 @@ dtc5150x_init(const device_t *info)
pclog("MFM: looking for disks..\n");
for (i=0; i<HDD_NUM; i++) {
if ((hdd[i].bus == HDD_BUS_MFM) && (hdd[i].mfm_channel < MFM_NUM)) {
pclog("Found MFM hard disk on channel %i\n", hdd[i].mfm_channel);
pclog("Found MFM hard disk on channel %i (%ls)\n", hdd[i].mfm_channel, hdd[i].fn);
loadhd(dtc, i, hdd[i].mfm_channel, hdd[i].fn);
if (++c > MFM_NUM) break;

1200
src/disk/hdc_xta.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -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.12 2018/04/05
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -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;
@@ -248,7 +260,7 @@ const device_t xtide_at_device = {
"XTIDE (AT)",
DEVICE_ISA | DEVICE_AT,
0,
xtide_at_init, xtide_close, NULL,
xtide_at_init, xtide_at_close, NULL,
xtide_at_available, NULL, 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_init, xtide_at_close, NULL,
xtide_at_ps2_available, NULL, NULL, NULL,
NULL
};

View File

@@ -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.8 2018/04/24
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2016,2017 Miran Grca.
* Copyright 2017 Fred N. van Kempen.
* Copyright 2016-2018 Miran Grca.
* Copyright 2017,2018 Fred N. van Kempen.
*/
#include <stdio.h>
#include <stdint.h>
@@ -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);
}

View File

@@ -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.4 2018/03/29
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* 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,16 @@ 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 +101,7 @@ typedef struct {
extern hard_disk_t hdd[HDD_NUM];
extern uint64_t hdd_table[128][3];
extern unsigned int hdd_table[128][3];
extern int hdd_init(void);
@@ -75,6 +109,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);

View File

@@ -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.14 2018/03/28
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -34,11 +34,11 @@
typedef struct
{
FILE *file;
uint32_t base;
uint32_t last_sector;
uint8_t type;
uint8_t loaded;
FILE *file;
uint32_t base;
uint32_t last_sector;
uint8_t type;
uint8_t loaded;
} hdd_image_t;
@@ -69,393 +69,442 @@ hdd_image_log(const char *fmt, ...)
}
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)
static int
prepare_new_hard_disk(uint8_t id, uint64_t full_size)
{
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 };
uint64_t target_size = (full_size + hdd_images[id].base) - ftello64(hdd_images[id].file);
memset(empty_sector, 0, sizeof(empty_sector));
uint32_t size;
uint32_t t, i;
hdd_images[id].base = 0;
t = (uint32_t) (target_size >> 20); /* Amount of 1 MB blocks. */
size = (uint32_t) (target_size & 0xfffff); /* 1 MB mask. */
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;
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("#");
}
}
is_hdx[0] = image_is_hdx(fn, 0);
is_hdx[1] = image_is_hdx(fn, 1);
/* 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();
/* 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;
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;
uint64_t s = 0;
wchar_t *fn = hdd[id].fn;
int is_hdx[2] = { 0, 0 };
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].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;
}
hdd_images[id].loaded = 0;
}
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(&sector_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(&sector_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;
}
is_hdx[0] = image_is_hdx(fn, 0);
is_hdx[1] = image_is_hdx(fn, 1);
s = full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512;
goto prepare_new_hard_disk;
} else {
/* Failed for another reason */
hdd_image_log("Failed for another reason\n");
/* 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(&sector_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(&sector_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(&sector_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(&sector_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);
return prepare_new_hard_disk(id, full_size);
} 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(&sector_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(&sector_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 {
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 * 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 << 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;
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)
{
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;
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;
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;
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;
}
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;
}

View File

@@ -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, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2016,2017 Miran Grca.
* Copyright 2017 Fred N. van Kempen.
* Copyright 2016-2018 Miran Grca.
* Copyright 2017,2018 Fred N. van Kempen.
*/
#include <stdio.h>
#include <stdint.h>
@@ -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 },

File diff suppressed because it is too large Load Diff

View File

@@ -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.5 2018/03/26
*
* Author: Miran Grca, <mgrca8@gmail.com>
*
@@ -19,15 +19,15 @@
#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
@@ -42,134 +42,81 @@
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;
uint8_t previous_command, error,
features, status,
phase, *buffer,
atapi_cdb[16],
current_cdb[16],
sense[256];
int toctimes;
int media_status;
uint16_t request_length, max_transfer_len;
int is_dma;
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;
int requested_blocks; /* This will be set to something other than 1 when block reads are implemented. */
uint32_t sector_pos, sector_len,
packet_len, pos,
seek_pos;
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;
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;
uint64_t current_page_code;
} zip_t;
typedef struct {
int host_drive;
int prev_host_drive;
unsigned int bus_type; /* 0 = ATAPI, 1 = SCSI */
uint8_t ide_channel,
bus_mode; /* Bit 0 = PIO suported;
Bit 1 = DMA supportd. */
unsigned int bus_type; /* 0 = ATAPI, 1 = SCSI */
uint8_t bus_mode; /* Bit 0 = PIO suported;
Bit 1 = DMA supportd. */
unsigned int scsi_device_id, scsi_device_lun,
is_250;
uint8_t ide_channel;
wchar_t image_path[1024],
prev_image_path[1024];
unsigned int scsi_device_id;
unsigned int scsi_device_lun;
unsigned int is_250;
unsigned int atapi_dma;
int read_only, ui_writeprot;
wchar_t image_path[1024];
wchar_t prev_image_path[1024];
uint32_t medium_size, base;
uint32_t medium_size;
int read_only;
int ui_writeprot;
uint32_t base;
FILE *f;
FILE *f;
} zip_drive_t;
extern zip_t zip[ZIP_NUM];
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];
#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 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]
#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 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 void ioctl_close(uint8_t id);
extern uint32_t zip_mode_sense_get_channel(uint8_t id, int channel);
@@ -183,8 +130,6 @@ extern void zip_phase_callback(uint8_t id);
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);
@@ -200,6 +145,8 @@ 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_destroy_drives(void);
extern void zip_close(uint8_t id);
#ifdef __cplusplus

1666
src/dma.c

File diff suppressed because it is too large Load Diff

View File

@@ -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, <http://pcem-emulator.co.uk/>
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <tommowalker@tommowalker.co.uk>
*
* 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);

View File

@@ -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.6 2018/04/12
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <tommowalker@tommowalker.co.uk>
@@ -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)
@@ -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;
@@ -1055,6 +1066,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc_seek(fdc, fdc->drive, -fdc->max_track);
fdc_log("Recalibrating...\n");
fdc->time = 5000LL;
fdc->step = fdc->seek_dir = 1;
break;
case 0x0d: /*Format*/
fdc_rate(fdc, fdc->drive);
@@ -1098,14 +1110,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->step = 1;
} else {
fdc->st0 = 0x20 | (fdc->params[0] & 7);
fdc->interrupt = -3;
@@ -1125,9 +1140,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->step = 1;
fdc_log("fdc->time = %i\n", fdc->time);
}
break;
@@ -1154,7 +1174,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 +1193,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 +1308,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 +1341,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;
@@ -1530,7 +1601,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,7 +1684,8 @@ 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;
fdc->res[5] = st5;
@@ -1977,7 +2050,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 +2068,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 {

View File

@@ -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, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -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;

View File

@@ -8,7 +8,7 @@
*
* Implementation of the floppy drive emulation.
*
* Version: @(#)fdd.c 1.0.5 2018/03/16
* Version: @(#)fdd.c 1.0.6 2018/04/10
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -495,7 +495,6 @@ void fdd_close(int 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 +505,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);
}

View File

@@ -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, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -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;

View File

@@ -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.8 2018/04/11
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -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"

File diff suppressed because it is too large Load Diff

View File

@@ -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.7 2018/03/26
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "device.h"
#include "cpu/cpu.h"
#include "io.h"
#include "dma.h"
@@ -26,144 +28,181 @@
#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,
NULL
};

View File

@@ -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, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* 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;

View File

@@ -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, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -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 *);

View File

@@ -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.34 2018/03/26
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -2044,15 +2044,25 @@ const device_t keyboard_ps2_quadtel_device = {
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, 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, NULL
};
void

View File

@@ -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.12 2018/04/11
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -1205,7 +1205,7 @@ machine_amstrad_init(const machine_t *model)
ams = (amstrad_t *)malloc(sizeof(amstrad_t));
memset(ams, 0x00, sizeof(amstrad_t));
device_add(&amstrad_nvr_device);
machine_common_init(model);

View File

@@ -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);

View File

@@ -8,16 +8,17 @@
*
* Implementation of the Intel 430FX PCISet chip.
*
* Version: @(#)m_at_430fx.c 1.0.14 2018/03/18
* Version: @(#)m_at_430fx.c 1.0.16 2018/04/04
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016,2018 Miran Grca.
* Copyright 2016-2018 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
@@ -36,220 +37,231 @@
#include "machine.h"
static uint8_t card_i430fx[256];
static void i430fx_map(uint32_t addr, uint32_t size, int state)
typedef struct
{
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();
}
uint8_t regs[256];
} i430fx_t;
static void i430fx_write(int func, int addr, uint8_t val, void *priv)
static void
i430fx_map(uint32_t addr, uint32_t size, int state)
{
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);
switch (state & 3) {
case 0:
mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
break;
}
card_i430fx[addr] = val;
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 uint8_t i430fx_read(int func, int addr, void *priv)
static void
i430fx_write(int func, int addr, uint8_t val, void *priv)
{
if (func)
return 0xff;
i430fx_t *dev = (i430fx_t *) priv;
return card_i430fx[addr];
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 ((dev->regs[0x59] ^ val) & 0xf0) {
i430fx_map(0xf0000, 0x10000, val >> 4);
shadowbios = (val & 0x10);
}
break;
case 0x5a: /*PAM1*/
if ((dev->regs[0x5a] ^ val) & 0x0f)
i430fx_map(0xc0000, 0x04000, val & 0xf);
if ((dev->regs[0x5a] ^ val) & 0xf0)
i430fx_map(0xc4000, 0x04000, val >> 4);
break;
case 0x5b: /*PAM2*/
if ((dev->regs[0x5b] ^ val) & 0x0f)
i430fx_map(0xc8000, 0x04000, val & 0xf);
if ((dev->regs[0x5b] ^ val) & 0xf0)
i430fx_map(0xcc000, 0x04000, val >> 4);
break;
case 0x5c: /*PAM3*/
if ((dev->regs[0x5c] ^ val) & 0x0f)
i430fx_map(0xd0000, 0x04000, val & 0xf);
if ((dev->regs[0x5c] ^ val) & 0xf0)
i430fx_map(0xd4000, 0x04000, val >> 4);
break;
case 0x5d: /*PAM4*/
if ((dev->regs[0x5d] ^ val) & 0x0f)
i430fx_map(0xd8000, 0x04000, val & 0xf);
if ((dev->regs[0x5d] ^ val) & 0xf0)
i430fx_map(0xdc000, 0x04000, val >> 4);
break;
case 0x5e: /*PAM5*/
if ((dev->regs[0x5e] ^ val) & 0x0f)
i430fx_map(0xe0000, 0x04000, val & 0xf);
if ((dev->regs[0x5e] ^ val) & 0xf0)
i430fx_map(0xe4000, 0x04000, val >> 4);
break;
case 0x5f: /*PAM6*/
if ((dev->regs[0x5f] ^ val) & 0x0f)
i430fx_map(0xe8000, 0x04000, val & 0xf);
if ((dev->regs[0x5f] ^ val) & 0xf0)
i430fx_map(0xec000, 0x04000, val >> 4);
break;
case 0x72: /*SMRAM*/
if ((dev->regs[0x72] ^ val) & 0x48)
i430fx_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0);
break;
}
dev->regs[addr] = val;
}
static void i430fx_reset(void)
static uint8_t
i430fx_read(int func, int addr, void *priv)
{
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;
}
i430fx_t *dev = (i430fx_t *) priv;
if (func)
return 0xff;
return dev->regs[addr];
}
static void i430fx_pci_reset(void)
static void
i430fx_reset(void *priv)
{
i430fx_write(0, 0x59, 0x00, NULL);
i430fx_write(0, 0x72, 0x02, NULL);
i430fx_write(0, 0x59, 0x00, priv);
i430fx_write(0, 0x72, 0x02, priv);
}
static void i430fx_init(void)
static void
i430fx_close(void *p)
{
pci_add_card(0, i430fx_read, i430fx_write, NULL);
i430fx_t *i430fx = (i430fx_t *)p;
i430fx_reset();
pci_reset_handler.pci_master_reset = i430fx_pci_reset;
free(i430fx);
}
static void
*i430fx_init(const device_t *info)
{
i430fx_t *i430fx = (i430fx_t *) malloc(sizeof(i430fx_t));
memset(i430fx, 0, sizeof(i430fx_t));
i430fx->regs[0x00] = 0x86; i430fx->regs[0x01] = 0x80; /*Intel*/
i430fx->regs[0x02] = 0x2d; i430fx->regs[0x03] = 0x12; /*SB82437FX-66*/
i430fx->regs[0x04] = 0x06; i430fx->regs[0x05] = 0x00;
i430fx->regs[0x06] = 0x00; i430fx->regs[0x07] = 0x82;
i430fx->regs[0x08] = 0x00; /*A0 stepping*/
i430fx->regs[0x09] = 0x00; i430fx->regs[0x0a] = 0x00; i430fx->regs[0x0b] = 0x06;
i430fx->regs[0x52] = 0x40; /*256kb PLB cache*/
i430fx->regs[0x57] = 0x01;
i430fx->regs[0x60] = i430fx->regs[0x61] = i430fx->regs[0x62] = i430fx->regs[0x63] = 0x02;
i430fx->regs[0x64] = 0x02;
i430fx->regs[0x72] = 0x02;
pci_add_card(0, i430fx_read, i430fx_write, i430fx);
return i430fx;
}
const device_t i430fx_device =
{
"Intel SB82437FX-66",
DEVICE_PCI,
0,
i430fx_init,
i430fx_close,
i430fx_reset,
NULL,
NULL,
NULL,
NULL,
NULL
};
void
machine_at_p54tp4xe_init(const machine_t *model)
{
machine_at_ps2_init(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);
i430fx_init();
piix3_init(7);
fdc37c665_init();
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);
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);
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);
i430fx_init();
piix_init(7);
pc87306_init();
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);
device_add(&intel_flash_bxt_ami_device);
if (gfxcard == GFX_INTERNAL)
device_add(&s3_phoenix_trio64_onboard_pci_device);
if (gfxcard == GFX_INTERNAL)
device_add(&s3_phoenix_trio64_onboard_pci_device);
}
@@ -263,83 +275,85 @@ at_endeavor_get_device(void)
void
machine_at_zappa_init(const machine_t *model)
{
machine_at_common_init(model);
device_add(&keyboard_ps2_ami_device);
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);
i430fx_init();
piix_init(7);
pc87306_init();
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);
device_add(&intel_flash_bxt_ami_device);
}
void
machine_at_mb500n_init(const machine_t *model)
{
machine_at_ps2_init(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);
i430fx_init();
piix_init(7);
fdc37c665_init();
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);
device_add(&intel_flash_bxt_device);
}
void
machine_at_president_init(const machine_t *model)
{
machine_at_ps2_init(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);
i430fx_init();
piix_init(7);
w83877f_init();
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);
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);
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);
i430fx_init();
piix_init(7);
pc87306_init();
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);
device_add(&intel_flash_bxt_ami_device);
}

View File

@@ -8,7 +8,7 @@
*
* Implementation of the Intel 430HX PCISet chip.
*
* Version: @(#)m_at_430hx.c 1.0.11 2018/03/18
* Version: @(#)m_at_430hx.c 1.0.12 2018/04/04
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -18,6 +18,7 @@
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
@@ -33,297 +34,372 @@
#include "machine.h"
static uint8_t card_i430hx[256];
typedef struct
{
uint8_t regs[256];
} i430hx_t;
typedef struct
{
int index;
} acerm3a_t;
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);
switch (state & 3) {
case 0:
mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
break;
}
card_i430hx[addr] = val;
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 uint8_t i430hx_read(int func, int addr, void *priv)
static void
i430hx_write(int func, int addr, uint8_t val, void *priv)
{
if (func)
return 0xff;
i430hx_t *dev = (i430hx_t *) priv;
return card_i430hx[addr];
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 ((dev->regs[0x59] ^ val) & 0xf0) {
i430hx_map(0xf0000, 0x10000, val >> 4);
shadowbios = (val & 0x10);
}
break;
case 0x5a: /*PAM1*/
if ((dev->regs[0x5a] ^ val) & 0x0f)
i430hx_map(0xc0000, 0x04000, val & 0xf);
if ((dev->regs[0x5a] ^ val) & 0xf0)
i430hx_map(0xc4000, 0x04000, val >> 4);
break;
case 0x5b: /*PAM2*/
if ((dev->regs[0x5b] ^ val) & 0x0f)
i430hx_map(0xc8000, 0x04000, val & 0xf);
if ((dev->regs[0x5b] ^ val) & 0xf0)
i430hx_map(0xcc000, 0x04000, val >> 4);
break;
case 0x5c: /*PAM3*/
if ((dev->regs[0x5c] ^ val) & 0x0f)
i430hx_map(0xd0000, 0x04000, val & 0xf);
if ((dev->regs[0x5c] ^ val) & 0xf0)
i430hx_map(0xd4000, 0x04000, val >> 4);
break;
case 0x5d: /*PAM4*/
if ((dev->regs[0x5d] ^ val) & 0x0f)
i430hx_map(0xd8000, 0x04000, val & 0xf);
if ((dev->regs[0x5d] ^ val) & 0xf0)
i430hx_map(0xdc000, 0x04000, val >> 4);
break;
case 0x5e: /*PAM5*/
if ((dev->regs[0x5e] ^ val) & 0x0f)
i430hx_map(0xe0000, 0x04000, val & 0xf);
if ((dev->regs[0x5e] ^ val) & 0xf0)
i430hx_map(0xe4000, 0x04000, val >> 4);
break;
case 0x5f: /*PAM6*/
if ((dev->regs[0x5f] ^ val) & 0x0f)
i430hx_map(0xe8000, 0x04000, val & 0xf);
if ((dev->regs[0x5f] ^ val) & 0xf0)
i430hx_map(0xec000, 0x04000, val >> 4);
break;
case 0x72: /*SMRAM*/
if ((dev->regs[0x72] ^ val) & 0x48)
i430hx_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0);
break;
}
dev->regs[addr] = val;
}
static uint8_t
i430hx_read(int func, int addr, void *priv)
{
i430hx_t *dev = (i430hx_t *) priv;
if (func)
return 0xff;
return dev->regs[addr];
}
static void i430hx_reset(void)
static void
i430hx_reset(void *priv)
{
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);
i430hx_write(0, 0x59, 0x00, priv);
i430hx_write(0, 0x72, 0x02, priv);
}
static void i430hx_init(void)
static void
i430hx_close(void *p)
{
pci_add_card(0, i430hx_read, i430hx_write, NULL);
i430hx_t *i430hx = (i430hx_t *)p;
i430hx_reset();
pci_reset_handler.pci_master_reset = i430hx_pci_reset;
free(i430hx);
}
static int acerm3a_index;
static void
*i430hx_init(const device_t *info)
{
i430hx_t *i430hx = (i430hx_t *) malloc(sizeof(i430hx_t));
memset(i430hx, 0, sizeof(i430hx_t));
i430hx->regs[0x00] = 0x86; i430hx->regs[0x01] = 0x80; /*Intel*/
i430hx->regs[0x02] = 0x50; i430hx->regs[0x03] = 0x12; /*82439HX*/
i430hx->regs[0x04] = 0x06; i430hx->regs[0x05] = 0x00;
i430hx->regs[0x06] = 0x00; i430hx->regs[0x07] = 0x02;
i430hx->regs[0x08] = 0x00; /*A0 stepping*/
i430hx->regs[0x09] = 0x00; i430hx->regs[0x0a] = 0x00; i430hx->regs[0x0b] = 0x06;
i430hx->regs[0x51] = 0x20;
i430hx->regs[0x52] = 0xB5; /*512kb cache*/
i430hx->regs[0x59] = 0x40;
i430hx->regs[0x5A] = i430hx->regs[0x5B] = i430hx->regs[0x5C] = i430hx->regs[0x5D] = 0x44;
i430hx->regs[0x5E] = i430hx->regs[0x5F] = 0x44;
i430hx->regs[0x56] = 0x52; /*DRAM control*/
i430hx->regs[0x57] = 0x01;
i430hx->regs[0x60] = i430hx->regs[0x61] = i430hx->regs[0x62] = i430hx->regs[0x63] = 0x02;
i430hx->regs[0x64] = i430hx->regs[0x65] = i430hx->regs[0x66] = i430hx->regs[0x67] = 0x02;
i430hx->regs[0x68] = 0x11;
i430hx->regs[0x72] = 0x02;
pci_add_card(0, i430hx_read, i430hx_write, i430hx);
return i430hx;
}
const device_t i430hx_device =
{
"Intel 82439HX",
DEVICE_PCI,
0,
i430hx_init,
i430hx_close,
i430hx_reset,
NULL,
NULL,
NULL,
NULL,
NULL
};
static void
acerm3a_out(uint16_t port, uint8_t val, void *p)
{
if (port == 0xea)
acerm3a_index = val;
acerm3a_t *dev = (acerm3a_t *) p;
if (port == 0xea)
dev->index = val;
}
static uint8_t
acerm3a_in(uint16_t port, void *p)
{
if (port == 0xeb)
{
switch (acerm3a_index)
{
case 2:
return 0xfd;
}
}
return 0xff;
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,
NULL
};
void
machine_at_acerm3a_init(const machine_t *model)
{
machine_at_ps2_init(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);
i430hx_init();
piix3_init(7);
fdc37c932fr_init();
io_sethandler(0x00ea, 0x0002, acerm3a_in, NULL, NULL, acerm3a_out, NULL, NULL, NULL);
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);
device_add(&intel_flash_bxb_device);
}
void
machine_at_acerv35n_init(const machine_t *model)
{
machine_at_ps2_init(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);
i430hx_init();
piix3_init(7);
fdc37c932fr_init();
io_sethandler(0x00ea, 0x0002, acerm3a_in, NULL, NULL, acerm3a_out, NULL, NULL, NULL);
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);
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);
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);
i430hx_init();
piix3_init(7);
fdc37c669_init();
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);
device_add(&intel_flash_bxt_device);
}
void
machine_at_p55t2p4_init(const machine_t *model)
{
machine_at_ps2_init(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);
i430hx_init();
piix3_init(7);
w83877f_init();
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);
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);
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);
i430hx_init();
piix3_init(7);
pc87306_init();
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);
device_add(&intel_flash_bxt_device);
}

View File

@@ -8,7 +8,7 @@
*
* Implementation of the Intel 430LX and 430NX PCISet chips.
*
* Version: @(#)m_at_430lx_nx.c 1.0.10 2018/03/18
* Version: @(#)m_at_430lx_nx.c 1.0.11 2018/04/04
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -18,6 +18,7 @@
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
@@ -34,217 +35,240 @@
#include "machine.h"
static uint8_t card_i430_lx_nx[256];
static void i430lx_nx_map(uint32_t addr, uint32_t size, int state)
typedef struct
{
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();
uint8_t regs[256];
} i430lx_nx_t;
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)
static void
i430lx_nx_write(int func, int addr, uint8_t val, void *priv)
{
if (func)
return;
i430lx_nx_t *dev = (i430lx_nx_t *) priv;
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);
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 ((dev->regs[0x59] ^ val) & 0xf0) {
i430lx_nx_map(0xf0000, 0x10000, val >> 4);
shadowbios = (val & 0x10);
}
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;
break;
case 0x5a: /*PAM1*/
if ((dev->regs[0x5a] ^ val) & 0x0f)
i430lx_nx_map(0xc0000, 0x04000, val & 0xf);
if ((dev->regs[0x5a] ^ val) & 0xf0)
i430lx_nx_map(0xc4000, 0x04000, val >> 4);
break;
case 0x5b: /*PAM2*/
if ((dev->regs[0x5b] ^ val) & 0x0f)
i430lx_nx_map(0xc8000, 0x04000, val & 0xf);
if ((dev->regs[0x5b] ^ val) & 0xf0)
i430lx_nx_map(0xcc000, 0x04000, val >> 4);
break;
case 0x5c: /*PAM3*/
if ((dev->regs[0x5c] ^ val) & 0x0f)
i430lx_nx_map(0xd0000, 0x04000, val & 0xf);
if ((dev->regs[0x5c] ^ val) & 0xf0)
i430lx_nx_map(0xd4000, 0x04000, val >> 4);
break;
case 0x5d: /*PAM4*/
if ((dev->regs[0x5d] ^ val) & 0x0f)
i430lx_nx_map(0xd8000, 0x04000, val & 0xf);
if ((dev->regs[0x5d] ^ val) & 0xf0)
i430lx_nx_map(0xdc000, 0x04000, val >> 4);
break;
case 0x5e: /*PAM5*/
if ((dev->regs[0x5e] ^ val) & 0x0f)
i430lx_nx_map(0xe0000, 0x04000, val & 0xf);
if ((dev->regs[0x5e] ^ val) & 0xf0)
i430lx_nx_map(0xe4000, 0x04000, val >> 4);
break;
case 0x5f: /*PAM6*/
if ((dev->regs[0x5f] ^ val) & 0x0f)
i430lx_nx_map(0xe8000, 0x04000, val & 0xf);
if ((dev->regs[0x5f] ^ val) & 0xf0)
i430lx_nx_map(0xec000, 0x04000, val >> 4);
break;
}
dev->regs[addr] = val;
}
static uint8_t i430lx_nx_read(int func, int addr, void *priv)
static uint8_t
i430lx_nx_read(int func, int addr, void *priv)
{
if (func)
return 0xff;
i430lx_nx_t *dev = (i430lx_nx_t *) priv;
return card_i430_lx_nx[addr];
if (func)
return 0xff;
return dev->regs[addr];
}
static void i430lx_nx_reset_common(void)
static void
i430lx_nx_reset(void *priv)
{
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;
i430lx_nx_write(0, 0x59, 0x00, priv);
}
static void i430lx_reset(void)
static void
i430lx_nx_close(void *p)
{
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*/
i430lx_nx_t *i430lx_nx = (i430lx_nx_t *)p;
free(i430lx_nx);
}
static void i430nx_reset(void)
static void
*i430lx_nx_init(const device_t *info)
{
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;
i430lx_nx_t *i430lx_nx = (i430lx_nx_t *) malloc(sizeof(i430lx_nx_t));
memset(i430lx_nx, 0, sizeof(i430lx_nx_t));
i430lx_nx->regs[0x00] = 0x86; i430lx_nx->regs[0x01] = 0x80; /*Intel*/
i430lx_nx->regs[0x02] = 0xa3; i430lx_nx->regs[0x03] = 0x04; /*82434LX/NX*/
i430lx_nx->regs[0x04] = 0x06; i430lx_nx->regs[0x05] = 0x00;
i430lx_nx->regs[0x06] = 0x00; i430lx_nx->regs[0x07] = 0x02;
i430lx_nx->regs[0x09] = 0x00; i430lx_nx->regs[0x0a] = 0x00; i430lx_nx->regs[0x0b] = 0x06;
i430lx_nx->regs[0x57] = 0x31;
i430lx_nx->regs[0x60] = i430lx_nx->regs[0x61] = i430lx_nx->regs[0x62] = i430lx_nx->regs[0x63] = 0x02;
i430lx_nx->regs[0x64] = 0x02;
if (info->local == 1) {
i430lx_nx->regs[0x08] = 0x10; /*A0 stepping*/
i430lx_nx->regs[0x50] = 0xA0;
i430lx_nx->regs[0x52] = 0x44; /*256kb PLB cache*/
i430lx_nx->regs[0x66] = i430lx_nx->regs[0x67] = 0x02;
} else {
i430lx_nx->regs[0x08] = 0x03; /*A3 stepping*/
i430lx_nx->regs[0x50] = 0x80;
i430lx_nx->regs[0x52] = 0x40; /*256kb PLB cache*/
}
pci_add_card(0, i430lx_nx_read, i430lx_nx_write, i430lx_nx);
return i430lx_nx;
}
static void i430lx_nx_pci_reset(void)
const device_t i430lx_device =
{
i430lx_nx_write(0, 0x59, 0x00, NULL);
}
"Intel 82434LX",
DEVICE_PCI,
0,
i430lx_nx_init,
i430lx_nx_close,
i430lx_nx_reset,
NULL,
NULL,
NULL,
NULL,
NULL
};
static void i430lx_init(void)
const device_t i430nx_device =
{
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;
}
"Intel 82434NX",
DEVICE_PCI,
1,
i430lx_nx_init,
i430lx_nx_close,
i430lx_nx_reset,
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_device);
machine_at_common_init(model);
device_add(&keyboard_ps2_ami_pci_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();
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);
device_add(&intel_flash_bxt_ami_device);
}
void
machine_at_batman_init(const machine_t *model)
{
machine_at_premiere_common_init(model);
machine_at_premiere_common_init(model);
i430lx_init();
device_add(&i430lx_device);
}
void
machine_at_plato_init(const machine_t *model)
{
machine_at_premiere_common_init(model);
machine_at_premiere_common_init(model);
i430nx_init();
device_add(&i430nx_device);
}

View File

@@ -8,7 +8,7 @@
*
* Implementation of the Intel 430VX PCISet chip.
*
* Version: @(#)m_at_430vx.c 1.0.11 2018/03/18
* Version: @(#)m_at_430vx.c 1.0.12 2018/04/04
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -18,237 +18,269 @@
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../device.h"
#include "../keyboard.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)
typedef struct
{
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();
uint8_t regs[256];
} i430vx_t;
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)
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);
i430vx_t *dev = (i430vx_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*/
val &= 0x02;
val |= 0x04;
break;
}
card_i430vx[addr] = val;
case 0x05:
val = 0;
break;
case 0x06: /*Status*/
val = 0;
break;
case 0x07:
val &= 0x80;
val |= 0x02;
break;
case 0x59: /*PAM0*/
if ((dev->regs[0x59] ^ val) & 0xf0) {
i430vx_map(0xf0000, 0x10000, val >> 4);
shadowbios = (val & 0x10);
}
break;
case 0x5a: /*PAM1*/
if ((dev->regs[0x5a] ^ val) & 0x0f)
i430vx_map(0xc0000, 0x04000, val & 0xf);
if ((dev->regs[0x5a] ^ val) & 0xf0)
i430vx_map(0xc4000, 0x04000, val >> 4);
break;
case 0x5b: /*PAM2*/
if ((dev->regs[0x5b] ^ val) & 0x0f)
i430vx_map(0xc8000, 0x04000, val & 0xf);
if ((dev->regs[0x5b] ^ val) & 0xf0)
i430vx_map(0xcc000, 0x04000, val >> 4);
break;
case 0x5c: /*PAM3*/
if ((dev->regs[0x5c] ^ val) & 0x0f)
i430vx_map(0xd0000, 0x04000, val & 0xf);
if ((dev->regs[0x5c] ^ val) & 0xf0)
i430vx_map(0xd4000, 0x04000, val >> 4);
break;
case 0x5d: /*PAM4*/
if ((dev->regs[0x5d] ^ val) & 0x0f)
i430vx_map(0xd8000, 0x04000, val & 0xf);
if ((dev->regs[0x5d] ^ val) & 0xf0)
i430vx_map(0xdc000, 0x04000, val >> 4);
break;
case 0x5e: /*PAM5*/
if ((dev->regs[0x5e] ^ val) & 0x0f)
i430vx_map(0xe0000, 0x04000, val & 0xf);
if ((dev->regs[0x5e] ^ val) & 0xf0)
i430vx_map(0xe4000, 0x04000, val >> 4);
break;
case 0x5f: /*PAM6*/
if ((dev->regs[0x5f] ^ val) & 0x0f)
i430vx_map(0xe8000, 0x04000, val & 0xf);
if ((dev->regs[0x5f] ^ val) & 0xf0)
i430vx_map(0xec000, 0x04000, val >> 4);
break;
case 0x72: /*SMRAM*/
if ((dev->regs[0x72] ^ val) & 0x48)
i430vx_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0);
break;
}
dev->regs[addr] = val;
}
static uint8_t i430vx_read(int func, int addr, void *priv)
{
if (func)
return 0xff;
i430vx_t *dev = (i430vx_t *) priv;
return card_i430vx[addr];
if (func)
return 0xff;
return dev->regs[addr];
}
static void i430vx_reset(void)
static void
i430vx_reset(void *priv)
{
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;
i430vx_write(0, 0x59, 0x00, priv);
i430vx_write(0, 0x72, 0x02, priv);
}
static void i430vx_pci_reset(void)
static void
i430vx_close(void *p)
{
i430vx_write(0, 0x59, 0x00, NULL);
i430vx_write(0, 0x72, 0x02, NULL);
i430vx_t *i430vx = (i430vx_t *)p;
free(i430vx);
}
void i430vx_init(void)
static void
*i430vx_init(const device_t *info)
{
pci_add_card(0, i430vx_read, i430vx_write, NULL);
i430vx_reset();
i430vx_t *i430vx = (i430vx_t *) malloc(sizeof(i430vx_t));
memset(i430vx, 0, sizeof(i430vx_t));
pci_reset_handler.pci_master_reset = i430vx_pci_reset;
i430vx->regs[0x00] = 0x86; i430vx->regs[0x01] = 0x80; /*Intel*/
i430vx->regs[0x02] = 0x30; i430vx->regs[0x03] = 0x70; /*82437VX*/
i430vx->regs[0x04] = 0x06; i430vx->regs[0x05] = 0x00;
i430vx->regs[0x06] = 0x00; i430vx->regs[0x07] = 0x02;
i430vx->regs[0x08] = 0x00; /*A0 stepping*/
i430vx->regs[0x09] = 0x00; i430vx->regs[0x0a] = 0x00; i430vx->regs[0x0b] = 0x06;
i430vx->regs[0x52] = 0x42; /*256kb PLB cache*/
i430vx->regs[0x53] = 0x14;
i430vx->regs[0x56] = 0x52; /*DRAM control*/
i430vx->regs[0x57] = 0x01;
i430vx->regs[0x60] = i430vx->regs[0x61] = i430vx->regs[0x62] = i430vx->regs[0x63] = 0x02;
i430vx->regs[0x64] = 0x02;
i430vx->regs[0x67] = 0x11;
i430vx->regs[0x69] = 0x03;
i430vx->regs[0x70] = 0x20;
i430vx->regs[0x72] = 0x02;
i430vx->regs[0x74] = 0x0e;
i430vx->regs[0x78] = 0x23;
pci_add_card(0, i430vx_read, i430vx_write, i430vx);
return i430vx;
}
const device_t i430vx_device =
{
"Intel 82437VX",
DEVICE_PCI,
0,
i430vx_init,
i430vx_close,
i430vx_reset,
NULL,
NULL,
NULL,
NULL,
NULL
};
void
machine_at_p55tvp4_init(const machine_t *model)
{
machine_at_ps2_init(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);
i430vx_init();
piix3_init(7);
w83877f_init();
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);
device_add(&intel_flash_bxt_device);
}
void
machine_at_i430vx_init(const machine_t *model)
{
machine_at_ps2_init(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(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();
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);
device_add(&intel_flash_bxt_device);
}
void
machine_at_p55va_init(const machine_t *model)
{
machine_at_ps2_init(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);
i430vx_init();
piix3_init(7);
fdc37c932fr_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(&i430vx_device);
device_add(&piix3_device);
fdc37c932fr_init();
device_add(&intel_flash_bxt_device);
device_add(&intel_flash_bxt_device);
}

View File

@@ -8,7 +8,7 @@
*
* Implementation of the Intel 440FX PCISet chip.
*
* Version: @(#)m_at_440fx.c 1.0.11 2018/03/18
* Version: @(#)m_at_440fx.c 1.0.12 2018/04/04
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -18,6 +18,7 @@
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
@@ -33,207 +34,239 @@
#include "machine.h"
static uint8_t card_i440fx[256];
static void i440fx_map(uint32_t addr, uint32_t size, int state)
typedef struct
{
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();
}
uint8_t regs[256];
} i440fx_t;
static void i440fx_write(int func, int addr, uint8_t val, void *priv)
static void
i440fx_map(uint32_t addr, uint32_t size, int state)
{
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);
switch (state & 3) {
case 0:
mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
break;
}
card_i440fx[addr] = val;
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 uint8_t i440fx_read(int func, int addr, void *priv)
static void
i440fx_write(int func, int addr, uint8_t val, void *priv)
{
if (func)
return 0xff;
i440fx_t *dev = (i440fx_t *) priv;
return card_i440fx[addr];
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 ((dev->regs[0x59] ^ val) & 0xf0) {
i440fx_map(0xf0000, 0x10000, val >> 4);
shadowbios = (val & 0x10);
}
break;
case 0x5a: /*PAM1*/
if ((dev->regs[0x5a] ^ val) & 0x0f)
i440fx_map(0xc0000, 0x04000, val & 0xf);
if ((dev->regs[0x5a] ^ val) & 0xf0)
i440fx_map(0xc4000, 0x04000, val >> 4);
break;
case 0x5b: /*PAM2*/
if ((dev->regs[0x5b] ^ val) & 0x0f)
i440fx_map(0xc8000, 0x04000, val & 0xf);
if ((dev->regs[0x5b] ^ val) & 0xf0)
i440fx_map(0xcc000, 0x04000, val >> 4);
break;
case 0x5c: /*PAM3*/
if ((dev->regs[0x5c] ^ val) & 0x0f)
i440fx_map(0xd0000, 0x04000, val & 0xf);
if ((dev->regs[0x5c] ^ val) & 0xf0)
i440fx_map(0xd4000, 0x04000, val >> 4);
break;
case 0x5d: /*PAM4*/
if ((dev->regs[0x5d] ^ val) & 0x0f)
i440fx_map(0xd8000, 0x04000, val & 0xf);
if ((dev->regs[0x5d] ^ val) & 0xf0)
i440fx_map(0xdc000, 0x04000, val >> 4);
break;
case 0x5e: /*PAM5*/
if ((dev->regs[0x5e] ^ val) & 0x0f)
i440fx_map(0xe0000, 0x04000, val & 0xf);
if ((dev->regs[0x5e] ^ val) & 0xf0)
i440fx_map(0xe4000, 0x04000, val >> 4);
break;
case 0x5f: /*PAM6*/
if ((dev->regs[0x5f] ^ val) & 0x0f)
i440fx_map(0xe8000, 0x04000, val & 0xf);
if ((dev->regs[0x5f] ^ val) & 0xf0)
i440fx_map(0xec000, 0x04000, val >> 4);
break;
case 0x72: /*SMRAM*/
if ((dev->regs[0x72] ^ val) & 0x48)
i440fx_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0);
break;
}
dev->regs[addr] = val;
}
static uint8_t
i440fx_read(int func, int addr, void *priv)
{
i440fx_t *dev = (i440fx_t *) priv;
if (func)
return 0xff;
return dev->regs[addr];
}
static void i440fx_reset(void)
static void
i440fx_reset(void *priv)
{
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);
i440fx_write(0, 0x59, 0x00, priv);
i440fx_write(0, 0x72, 0x02, priv);
}
static void i440fx_init(void)
static void
i440fx_close(void *p)
{
pci_add_card(0, i440fx_read, i440fx_write, NULL);
i440fx_reset();
i440fx_t *i440fx = (i440fx_t *)p;
pci_reset_handler.pci_master_reset = i440fx_pci_reset;
free(i440fx);
}
static void
*i440fx_init(const device_t *info)
{
i440fx_t *i440fx = (i440fx_t *) malloc(sizeof(i440fx_t));
memset(i440fx, 0, sizeof(i440fx_t));
i440fx->regs[0x00] = 0x86; i440fx->regs[0x01] = 0x80; /*Intel*/
i440fx->regs[0x02] = 0x37; i440fx->regs[0x03] = 0x12; /*82441FX*/
i440fx->regs[0x04] = 0x03; i440fx->regs[0x05] = 0x01;
i440fx->regs[0x06] = 0x80; i440fx->regs[0x07] = 0x00;
i440fx->regs[0x08] = 0x02; /*A0 stepping*/
i440fx->regs[0x09] = 0x00; i440fx->regs[0x0a] = 0x00; i440fx->regs[0x0b] = 0x06;
i440fx->regs[0x0d] = 0x00;
i440fx->regs[0x0f] = 0x00;
i440fx->regs[0x2c] = 0xf4;
i440fx->regs[0x2d] = 0x1a;
i440fx->regs[0x2e] = 0x00;
i440fx->regs[0x2f] = 0x11;
i440fx->regs[0x50] = 0x00;
i440fx->regs[0x51] = 0x01;
i440fx->regs[0x52] = i440fx->regs[0x54] = i440fx->regs[0x55] = i440fx->regs[0x56] = 0x00;
i440fx->regs[0x53] = 0x80;
i440fx->regs[0x57] = 0x01;
i440fx->regs[0x58] = 0x10;
i440fx->regs[0x5a] = i440fx->regs[0x5b] = i440fx->regs[0x5c] = i440fx->regs[0x5d] = 0x11;
i440fx->regs[0x5e] = 0x11;
i440fx->regs[0x5f] = 0x31;
i440fx->regs[0x72] = 0x02;
pci_add_card(0, i440fx_read, i440fx_write, i440fx);
return i440fx;
}
const device_t i440fx_device =
{
"Intel 82441FX",
DEVICE_PCI,
0,
i440fx_init,
i440fx_close,
i440fx_reset,
NULL,
NULL,
NULL,
NULL,
NULL
};
void
machine_at_i440fx_init(const machine_t *model)
{
machine_at_ps2_init(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);
i440fx_init();
piix3_init(7);
fdc37c665_init();
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);
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);
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);
i440fx_init();
piix3_init(7);
fdc37c665_init();
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);
device_add(&intel_flash_bxt_device);
}

View File

@@ -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.0 2018/04/17
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#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,196 @@
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,
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();
}

View File

@@ -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.4 2018/04/11
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
@@ -120,8 +120,8 @@
#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"
@@ -652,13 +652,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);
}
@@ -715,12 +718,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. */
@@ -735,9 +739,6 @@ machine_europc_init(const machine_t *model)
/* 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);
}

View File

@@ -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, <decwiz@yahoo.com>
* Sarah Walker, <tommowalker@tommowalker.co.uk>
*
* 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 <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.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_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<<dev->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->track<drive->tracks; dev->track++) {
drive->cur_cyl = dev->track;
for (dev->head=0; dev->head<drive->hpc; 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; i<HDD_NUM; i++) {
if ((hdd[i].bus == HDD_BUS_MFM) && (hdd[i].mfm_channel < MFM_NUM)) {
drive = &dev->drives[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
};

View File

@@ -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.13 2018/04/10
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -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();
}

View File

@@ -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.8 2018/04/10
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -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;
@@ -334,7 +330,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 +363,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 +375,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 +419,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 +431,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 +448,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 +466,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 +520,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)
{

1523
src/machine/m_ps1_hdc.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -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);

View File

@@ -1172,7 +1172,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();

View File

@@ -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.5 2018/04/11
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -92,8 +92,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"

View File

@@ -129,7 +129,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);

View File

@@ -8,7 +8,7 @@
*
* Handling of the emulated machines.
*
* Version: @(#)machine.c 1.0.32 2018/03/19
* Version: @(#)machine.c 1.0.33 2018/03/26
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -31,8 +31,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"
@@ -46,8 +45,6 @@ machine_init(void)
{
pclog("Initializing as \"%s\"\n", machine_getname());
ide_set_bus_master(NULL, NULL, NULL);
/* Set up the architecture flags. */
AT = IS_ARCH(machine, MACHINE_AT);
PCI = IS_ARCH(machine, MACHINE_PCI);
@@ -68,10 +65,16 @@ void
machine_common_init(const machine_t *model)
{
/* System devices first. */
dma_init();
pic_init();
dma_init();
pit_init();
cpu_set();
if (AT)
setrtcconst(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed);
else
setrtcconst(14318184.0);
if (lpt_enabled)
lpt_init();

View File

@@ -8,7 +8,7 @@
*
* Handling of the emulated machines.
*
* Version: @(#)machine.h 1.0.22 2018/03/18
* Version: @(#)machine.h 1.0.23 2018/03/28
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -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;
@@ -156,6 +155,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 +178,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 *);

View File

@@ -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.28 2018/04/10
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -28,155 +28,146 @@
#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_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_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/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 },
{ "[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 },
{ "[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 },
{ "[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/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 },
{ "[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 },
{ "[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 },
{ "[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 +258,3 @@ machine_get_machine_from_internal_name(char *s)
return(0);
}
void
machine_close(void)
{
if (machines[machine].nvr_close)
machines[machine].nvr_close();
}

View File

@@ -193,11 +193,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 +220,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 +239,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 +259,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 +403,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)];
@@ -496,7 +496,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 +520,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 +545,7 @@ writemembl(uint32_t addr, uint8_t val)
uint8_t
readmemb386l(uint32_t seg, uint32_t addr)
{
{
if (seg == (uint32_t) -1) {
x86gpf("NULL segment", 0);
@@ -554,7 +554,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);
addr = (ram_mapped_addr[addr >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr : (ram_mapped_addr[addr >> 14] & ~0x3fff) + (addr & 0x3fff);
if (addr < (uint32_t) (mem_size * 1024))
return ram[addr];
return 0xff;
@@ -577,7 +577,7 @@ readmemb386l(uint32_t seg, uint32_t addr)
void
writememb386l(uint32_t seg, uint32_t addr, uint8_t val)
{
{
if (seg == (uint32_t) -1) {
x86gpf("NULL segment", 0);
return;
@@ -585,7 +585,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);
addr = (ram_mapped_addr[addr >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr : (ram_mapped_addr[addr >> 14] & ~0x3fff) + (addr & 0x3fff);
if (addr < (uint32_t) (mem_size * 1024))
ram[addr] = val;
return;
@@ -613,7 +613,7 @@ readmemwl(uint32_t seg, uint32_t addr)
readmemwl(uint32_t seg, uint32_t addr)
{
uint32_t addr2 = mem_logical_addr = seg + addr;
if (seg == (uint32_t) -1) {
x86gpf("NULL segment", 0);
return -1;
@@ -626,16 +626,16 @@ readmemwl(uint32_t seg, uint32_t addr)
if (cr0 >> 31) {
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);
}
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] != (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);
addr = (ram_mapped_addr[addr2 >> 14] & MEM_MAP_TO_SHADOW_RAM_MASK) ? addr2 : (ram_mapped_addr[addr2 >> 14] & ~0x3fff) + (addr2 & 0x3fff);
if (addr < (uint32_t) (mem_size * 1024))
return *((uint16_t *)&ram[addr]);
return 0xffff;
@@ -653,9 +653,11 @@ readmemwl(uint32_t seg, uint32_t addr)
return _mem_read_w[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]);
if (_mem_read_b[addr2 >> 14]) {
if (AT)
if (AT)
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
else
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);
}
@@ -667,7 +669,7 @@ writememwl(uint32_t seg, uint32_t addr, uint16_t val)
writememwl(uint32_t seg, uint32_t addr, uint16_t val)
{
uint32_t addr2 = mem_logical_addr = seg + addr;
if (seg == (uint32_t) -1) {
x86gpf("NULL segment", 0);
return;
@@ -695,7 +697,7 @@ writememwl(uint32_t seg, uint32_t addr, uint16_t val)
writemembl(seg+addr,val);
writemembl(seg+addr+1,val>>8);
}
return;
return;
} else if (writelookup2[addr2 >> 12] != (uintptr_t) -1) {
*(uint16_t *)(writelookup2[addr2 >> 12] + addr2) = val;
return;
@@ -736,7 +738,7 @@ readmemll(uint32_t seg, uint32_t addr)
readmemll(uint32_t seg, uint32_t addr)
{
uint32_t addr2 = mem_logical_addr = seg + addr;
if (seg == (uint32_t) -1) {
x86gpf("NULL segment", 0);
return -1;
@@ -757,7 +759,7 @@ readmemll(uint32_t seg, uint32_t addr)
if (mmutranslate_read(addr2) == 0xffffffff) return 0xffffffff;
if (mmutranslate_read(addr2+3) == 0xffffffff) return 0xffffffff;
}
return readmemwl(seg,addr)|(readmemwl(seg,addr+2)<<16);
return readmemwl(seg,addr)|(readmemwl(seg,addr+2)<<16);
} else if (readlookup2[addr2 >> 12] != (uintptr_t) -1)
return *(uint32_t *)(readlookup2[addr2 >> 12] + addr2);
}
@@ -773,10 +775,14 @@ readmemll(uint32_t seg, uint32_t addr)
if (_mem_read_l[addr2 >> 14])
return _mem_read_l[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]);
if (_mem_read_w[addr2 >> 14])
if (_mem_read_w[addr2 >> 14])
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])
if (_mem_read_b[addr2 >> 14])
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 +793,7 @@ writememll(uint32_t seg, uint32_t addr, uint32_t val)
writememll(uint32_t seg, uint32_t addr, uint32_t val)
{
uint32_t addr2 = mem_logical_addr = seg + addr;
if (seg == (uint32_t) -1) {
x86gpf("NULL segment", 0);
return;
@@ -810,7 +816,7 @@ writememll(uint32_t seg, uint32_t addr, uint32_t val)
}
writememwl(seg,addr,val);
writememwl(seg,addr+2,val>>16);
return;
return;
} else if (writelookup2[addr2 >> 12] != (uintptr_t) -1) {
*(uint32_t *)(writelookup2[addr2 >> 12] + addr2) = val;
return;
@@ -852,7 +858,7 @@ readmemql(uint32_t seg, uint32_t addr)
readmemql(uint32_t seg, uint32_t addr)
{
uint32_t addr2 = mem_logical_addr = seg + addr;
if (seg == (uint32_t) -1) {
x86gpf("NULL segment", 0);
return -1;
@@ -872,7 +878,7 @@ readmemql(uint32_t seg, uint32_t addr)
if (mmutranslate_read(addr2) == 0xffffffff) return 0xffffffff;
if (mmutranslate_read(addr2+7) == 0xffffffff) return 0xffffffff;
}
return readmemll(seg,addr)|((uint64_t)readmemll(seg,addr+4)<<32);
return readmemll(seg,addr)|((uint64_t)readmemll(seg,addr+4)<<32);
} else if (readlookup2[addr2 >> 12] != (uintptr_t) -1)
return *(uint64_t *)(readlookup2[addr2 >> 12] + addr2);
}
@@ -897,7 +903,7 @@ writememql(uint32_t seg, uint32_t addr, uint64_t val)
writememql(uint32_t seg, uint32_t addr, uint64_t val)
{
uint32_t addr2 = mem_logical_addr = seg + addr;
if (seg == (uint32_t) -1) {
x86gpf("NULL segment", 0);
return;
@@ -919,7 +925,7 @@ writememql(uint32_t seg, uint32_t addr, uint64_t val)
}
writememll(seg, addr, val);
writememll(seg, addr+4, val >> 32);
return;
return;
} else if (writelookup2[addr2 >> 12] != (uintptr_t) -1) {
*(uint64_t *)(writelookup2[addr2 >> 12] + addr2) = val;
return;
@@ -1278,6 +1284,7 @@ mem_mapping_recalc(uint64_t base, uint64_t size)
for (c = base; c < base + size; c += 0x4000) {
_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;
@@ -1760,7 +1767,7 @@ mem_init(void)
static void
mem_remap_top(int max_size)
mem_remap_top(int max_size)
{
uint32_t c;
@@ -1799,7 +1806,7 @@ mem_remap_top_384k(void)
void
mem_reset_page_blocks(void)
mem_reset_page_blocks(void)
{
uint32_t c;

View File

@@ -49,7 +49,7 @@
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <pcap/pcap.h>
// #include <pcap/pcap.h>
#include "../86box.h"
#include "../config.h"
#include "../device.h"
@@ -58,8 +58,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 +113,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 },
@@ -118,7 +164,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);
@@ -251,14 +297,14 @@ net_pcap_init(void)
void
net_pcap_close(void)
{
pcap_t *pc;
void *pc;
if (pcap == NULL) return;
pclog("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) {
@@ -326,15 +372,15 @@ net_pcap_reset(const netcard_t *card, uint8_t *mac)
"( ((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) {
if (f_pcap_compile((void *)pcap, &fp, filter_exp, 0, 0xffffffff) != -1) {
if (f_pcap_setfilter((void *)pcap, &fp) != 0) {
pclog("PCAP: error installing filter (%s) !\n", filter_exp);
f_pcap_close((pcap_t *)pcap);
f_pcap_close((void *)pcap);
return(-1);
}
} else {
pclog("PCAP: could not compile filter (%s) !\n", filter_exp);
f_pcap_close((pcap_t *)pcap);
f_pcap_close((void *)pcap);
return(-1);
}
@@ -358,7 +404,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);
}

315
src/nvr.c
View File

@@ -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.6 2018/04/11
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
@@ -65,23 +63,11 @@
#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;
@@ -113,25 +99,23 @@ static 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++;
}
}
}
}
}
}
@@ -168,9 +152,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 +167,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 +185,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 +208,138 @@ 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));
/* 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);
pclog("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);
pclog("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)
{
int8_t dom, mon, sum, wd;
int16_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_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)

View File

@@ -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.6 2018/04/11
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
@@ -58,29 +58,36 @@
/* 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 */
wchar_t *fn; /* pathname of image file */
uint16_t size; /* device configuration */
int8_t irq;
int8_t irq;
int8_t upd_stat, /* FIXME: move to private struct */
addr;
int64_t upd_ecount, /* FIXME: move to private struct */
onesec_time,
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_device;
extern const device_t ps_nvr_device;
extern const device_t amstrad_nvr_device;
#endif
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 +95,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 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_period_recalc(void);
#endif /*EMU_NVR_H*/

View File

@@ -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.5 2018/04/09
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -218,6 +218,7 @@
* Boston, MA 02111-1307
* USA.
*/
#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
@@ -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,53 @@
# 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];
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]);
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 +334,50 @@ 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);
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);
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 +385,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 +405,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. */
/* Clear update status. */
local->stat = 0x00;
/* Check for any alarms we need to handle. */
/* Check for any alarms we need to handle. */
if (check_alarm(nvr->regs, RTC_SECONDS) &&
check_alarm(nvr->regs, RTC_MINUTES) &&
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)
if (nvr->irq != -1)
picint(1 << nvr->irq);
}
}
@@ -421,41 +434,43 @@ update_timer(void *priv)
/* Generate an interrupt. */
if (nvr->irq != -1)
if (nvr->irq != -1)
picint(1 << nvr->irq);
}
}
local->ecount = 0;
}
/* Re-calculate the timer values. */
static void
static void
timer_recalc(nvr_t *nvr, int add)
{
local_t *local = (local_t *)nvr->data;
int64_t c, nt;
c = 1ULL << ((nvr->regs[RTC_REGA] & REGA_RS) - 1);
nt = (int64_t)(RTCCONST * c * (1<<TIMER_SHIFT));
if (add)
if (add)
nvr->rtctime += nt;
else if (nvr->rtctime > nt)
local->rtctime += nt;
else if (local->rtctime > nt)
local->rtctime = nt;
}
static void
static void
timer_intr(void *priv)
{
nvr_t *nvr = (nvr_t *)priv;
local_t *local = (local_t *)nvr->data;
if (! (nvr->regs[RTC_REGA] & REGA_RS)) {
if (! (nvr->regs[RTC_REGA] & REGA_RS)) {
local->rtctime = 0x7fffffff;
return;
}
/* Update our timer interval. */
/* Update our timer interval. */
timer_recalc(nvr, 1);
nvr->regs[RTC_REGC] |= REGC_PF;
if (nvr->regs[RTC_REGB] & REGB_PIE) {
@@ -463,20 +478,27 @@ rtc_timer(void *priv)
/* Generate an interrupt. */
if (nvr->irq != -1)
if (nvr->irq != -1)
picint(1 << nvr->irq);
}
}
/* Callback from internal clock, another second passed. */
static void
static void
timer_tick(nvr_t *nvr)
{
{
local_t *local = (local_t *)nvr->data;
/* 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;
timer_recalc(nvr, 0);
/* Schedule the actual update. */
local->ecount = (int64_t)((244.0 + 1984.0) * TIMER_USEC);
}
}
@@ -485,20 +507,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) {
if (addr & 1) {
old = nvr->regs[nvr->addr];
old = nvr->regs[local->addr];
switch(local->addr) {
case RTC_REGA:
nvr->regs[RTC_REGA] = val;
if (val & REGA_RS)
if (val & REGA_RS)
timer_recalc(nvr, 1);
else
else
local->rtctime = 0x7fffffff;
break;
case RTC_REGB:
@@ -515,25 +538,25 @@ nvr_write(uint16_t addr, uint8_t val, void *priv)
break;
default: /* non-RTC registers are just NVRAM */
default: /* non-RTC registers are just NVRAM */
if (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 ((local->addr < RTC_REGA) || (local->addr == local->cent)) {
if ((local->addr != 1) && (local->addr != 3) && (local->addr != 5)) {
if ((old != val) && !enable_sync) {
/* Update internal clock. */
/* Update internal clock. */
time_get(nvr, &tm);
nvr_time_set(&tm);
nvr_dosave = 1;
}
}
}
} else {
} else {
local->addr = (val & (nvr->size - 1));
if (!(machines[machine].flags & MACHINE_MCA) &&
(romset != ROM_IBMPS1_2133))
nmi_mask = (~val & 0x80);
@@ -546,17 +569,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(local->addr) {
case RTC_REGA:
case RTC_REGA:
ret = (nvr->regs[RTC_REGA] & 0x7f) | local->stat;
break;
case RTC_REGC:
case RTC_REGC:
picintc(1 << nvr->irq);
ret = nvr->regs[RTC_REGC];
nvr->regs[RTC_REGC] = 0x00;
break;
@@ -567,10 +591,10 @@ nvr_read(uint16_t addr, void *priv)
break;
default:
default:
ret = nvr->regs[local->addr];
break;
} else {
} else {
ret = local->addr;
}
return(ret);
@@ -579,19 +603,21 @@ nvr_read(uint16_t addr, void *priv)
/* Reset the RTC state to 1980/01/01 00:00. */
static void
static void
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_YEAR] = RTC_BCD(80);
nvr->regs[local->cent] = RTC_BCD(19);
}
/* Process after loading from file. */
static void
static void
nvr_start(nvr_t *nvr)
{
struct tm tm;
@@ -599,63 +625,120 @@ nvr_at_start(nvr_t *nvr)
if (enable_sync) {
/* Use the internal clock's time. */
nvr_time_get(&tm);
nvr_time_get(&tm);
time_set(nvr, &tm);
} else {
/* Set the internal clock from the chip time. */
/* Set the internal clock from the chip time. */
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;
nvr->regs[RTC_REGB] = REGB_2412;
timer_recalc(nvr, 1);
}
void
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));
nvr = (nvr_t *)malloc(sizeof(nvr_t));
if (nvr == NULL) return(NULL);
memset(nvr, 0x00, sizeof(nvr_t));
local = (local_t *)malloc(sizeof(local_t));
memset(local, 0xff, sizeof(local_t));
nvr->data = local;
/* This is machine specific. */
nvr->size = machines[machine].nvrmask + 1;
nvr->size = machines[machine].nvrmask + 1;
switch(info->local) {
case 0: /* standard AT */
nvr->irq = 8;
local->cent = RTC_CENTURY_AT;
break;
case 1: /* PS/1 or PS/2 */
nvr->irq = 8;
local->cent = RTC_CENTURY_PS;
break;
case 2: /* Amstrad PC's */
nvr->irq = 1;
local->cent = RTC_CENTURY_AT;
break;
}
/* Set up any local handlers here. */
/* Set up any local handlers here. */
nvr->reset = nvr_at_reset;
nvr->start = nvr_at_start;
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. */
/* Start the timers. */
timer_add(update_timer, &nvr->upd_ecount, &nvr->upd_ecount, 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);
return(nvr);
}
void
static void
nvr_at_close(void *priv)
{
{
nvr_t *nvr = (nvr_t *)priv;
if (nvrp->fn != NULL)
if (nvr->fn != NULL)
free(nvr->fn);
if (nvr->data != NULL)
free(nvr->data);
free(nvr);
}
const device_t at_nvr_device = {
"PC/AT NVRAM",
DEVICE_ISA | DEVICE_AT,
0,
nvr_at_init, nvr_at_close, NULL,
NULL, NULL, NULL,
NULL
};
const device_t ps_nvr_device = {
"PS/1 or PS/2 NVRAM",
DEVICE_PS2,
1,
nvr_at_init, nvr_at_close, NULL,
NULL, NULL, NULL,
NULL
};
const device_t amstrad_nvr_device = {
"Amstrad NVRAM",
MACHINE_ISA | MACHINE_AT,
2,
nvr_at_init, nvr_at_close, NULL,
NULL, NULL, NULL,
NULL
};

163
src/pc.c
View File

@@ -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.69 2018/03/26
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -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"
@@ -57,21 +58,14 @@
#include "disk/hdc.h"
#include "disk/hdc_ide.h"
#include "disk/zip.h"
#include "scsi/scsi.h"
#include "cdrom/cdrom.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"
@@ -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 */
@@ -299,6 +293,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 +324,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 +348,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 +363,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.. */
@@ -512,6 +496,8 @@ pc_full_speed(void)
setpitclock(14318184.0);
}
atfullspeed = 1;
nvr_period_recalc();
}
@@ -522,9 +508,12 @@ pc_speed_changed(void)
setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed);
else
setpitclock(14318184.0);
nvr_period_recalc();
}
#if 0
/* Re-load system configuration and restart. */
/* FIXME: this has to be reviewed! */
void
@@ -536,10 +525,8 @@ pc_reload(wchar_t *fn)
for (i=0; i<FDD_NUM; i++)
fdd_close(i);
for (i=0; i<CDROM_NUM; i++) {
cdrom_drives[i].handler->exit(i);
cdrom_close(i);
}
cdrom_close();
pc_reset_hard_close();
@@ -547,24 +534,9 @@ pc_reload(wchar_t *fn)
config_load();
for (i=0; i<CDROM_NUM; i++) {
if (cdrom_drives[i].bus_type)
SCSIReset(cdrom_drives[i].scsi_device_id, cdrom_drives[i].scsi_device_lun);
cdrom_hard_reset();
if (cdrom_drives[i].host_drive == 200)
image_open(i, cdrom_image[i].image_path);
else if ((cdrom_drives[i].host_drive >= '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);
}
for (i=0; i<ZIP_NUM; i++) {
if (zip_drives[i].bus_type)
SCSIReset(zip_drives[i].scsi_device_id, zip_drives[i].scsi_device_lun);
zip_load(i, zip_drives[i].image_path);
}
zip_hard_reset();
fdd_load(0, floppyfns[0]);
fdd_load(1, floppyfns[1]);
@@ -575,6 +547,7 @@ pc_reload(wchar_t *fn)
pc_reset_hard_init();
}
#endif
/* Initialize modules, ran once, after pc_init. */
@@ -653,21 +626,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();
@@ -677,8 +642,6 @@ again2:
cdrom_hard_reset();
zip_hard_reset();
ide_reset_hard();
scsi_card_init();
pc_full_speed();
@@ -699,16 +662,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,37 +686,19 @@ 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);
}
void
pc_reset_hard_close(void)
{
pclog("pc_reset_hard_close()\n");
suppress_overscan = 0;
nvr_save();
machine_close();
mouse_close();
lpt_devices_close();
@@ -755,6 +707,8 @@ pc_reset_hard_close(void)
midi_close();
cdrom_close();
closeal();
}
@@ -768,29 +722,27 @@ pc_reset_hard_close(void)
void
pc_reset_hard_init(void)
{
pclog("pc_reset_hard_init()\n");
/*
* First, we reset the modules that are not part of
* 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();
/* Initialize the actual machine and its basic modules. */
machine_init();
@@ -810,11 +762,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 +774,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,7 +802,6 @@ pc_reset_hard_init(void)
device_add(&bugger_device);
/* Reset the CPU module. */
cpu_set();
resetx86();
dma_reset();
pic_reset();
@@ -938,9 +873,6 @@ pc_close(thread_t *ptr)
for (i=0; i<ZIP_NUM; i++)
zip_close(i);
for (i=0; i<CDROM_NUM; i++)
cdrom_drives[i].handler->exit(i);
for (i=0; i<FDD_NUM; i++)
fdd_close(i);
@@ -957,10 +889,9 @@ pc_close(thread_t *ptr)
network_close();
sound_cd_thread_end();
cdrom_close();
ide_destroy_buffers();
cdrom_destroy_drives();
zip_destroy_drives();
}

View File

@@ -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)

View File

@@ -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);

View File

@@ -3,6 +3,7 @@
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "86box.h"
#include "io.h"
#include "pci.h"
#include "pci_dummy.h"

View File

@@ -8,26 +8,18 @@
*
* Emulation core dispatcher.
*
* Version: @(#)piix.h 1.0.2 2017/10/25
* Version: @(#)piix.h 1.0.3 2018/03/26
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* 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 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);

View File

@@ -39,6 +39,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,8 +58,8 @@ 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();
}
@@ -336,7 +342,6 @@ void pit_write(uint16_t addr, uint8_t val, void *p)
{
PIT *pit = (PIT *)p;
int t;
cycles -= (int)PITCONST;
switch (addr&3)
{
@@ -444,7 +449,6 @@ uint8_t pit_read(uint16_t addr, void *p)
PIT *pit = (PIT *)p;
int64_t t;
uint8_t temp = 0xff;
cycles -= (int)PITCONST;
switch (addr&3)
{
case 0: case 1: case 2: /*Timers*/

View File

@@ -58,6 +58,8 @@ 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);

View File

@@ -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);

View File

@@ -8,7 +8,7 @@
*
* Handling of the SCSI controllers.
*
* Version: @(#)scsi.c 1.0.17 2018/03/18
* Version: @(#)scsi.c 1.0.18 2018/03/26
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -27,11 +27,12 @@
#include "../rom.h"
#include "../timer.h"
#include "../device.h"
#include "../cdrom/cdrom.h"
#include "../disk/hdc.h"
#include "../disk/zip.h"
#include "../plat.h"
#include "scsi.h"
#include "../cdrom/cdrom.h"
#include "scsi_device.h"
#include "scsi_aha154x.h"
#include "scsi_buslogic.h"
#include "scsi_ncr5380.h"
@@ -60,30 +61,29 @@ 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, },
};
@@ -149,6 +149,9 @@ void scsi_card_init(void)
{
int i, j;
if (!scsi_cards[scsi_card_current].device)
return;
pclog("Building SCSI hard disk map...\n");
build_scsi_hd_map();
pclog("Building SCSI CD-ROM map...\n");
@@ -158,41 +161,24 @@ void scsi_card_init(void)
for (i=0; i<SCSI_ID_MAX; i++) {
for (j=0; j<SCSI_LUN_MAX; j++) {
if (scsi_hard_disks[i][j] != 0xff) {
if (scsi_hard_disks[i][j] != 0xff)
SCSIDevices[i][j].LunType = SCSI_DISK;
} else if (scsi_cdrom_drives[i][j] != 0xff) {
else if (scsi_cdrom_drives[i][j] != 0xff)
SCSIDevices[i][j].LunType = SCSI_CDROM;
} else if (scsi_zip_drives[i][j] != 0xff) {
else if (scsi_zip_drives[i][j] != 0xff)
SCSIDevices[i][j].LunType = SCSI_ZIP;
} else {
else
SCSIDevices[i][j].LunType = SCSI_NONE;
}
SCSIDevices[i][j].CmdBuffer = NULL;
}
}
if (scsi_cards[scsi_card_current].device)
device_add(scsi_cards[scsi_card_current].device);
device_add(scsi_cards[scsi_card_current].device);
scsi_card_last = scsi_card_current;
}
void scsi_card_reset(void)
{
void *p = NULL;
if (scsi_cards[scsi_card_current].device) {
p = device_get_priv(scsi_cards[scsi_card_current].device);
if (p) {
if (scsi_cards[scsi_card_current].reset) {
scsi_cards[scsi_card_current].reset(p);
}
}
}
}
/* Initialization function for the SCSI layer */
void SCSIReset(uint8_t id, uint8_t lun)
{
@@ -200,20 +186,16 @@ void SCSIReset(uint8_t id, uint8_t lun)
uint8_t zip_id = scsi_zip_drives[id][lun];
uint8_t hdc_id = scsi_hard_disks[id][lun];
if (hdc_id != 0xff) {
scsi_hd_reset(hdc_id);
if (hdc_id != 0xff)
SCSIDevices[id][lun].LunType = SCSI_DISK;
} else {
if (cdrom_id != 0xff) {
cdrom_reset(cdrom_id);
SCSIDevices[id][lun].LunType = SCSI_CDROM;
} else if (zip_id != 0xff) {
zip_reset(zip_id);
SCSIDevices[id][lun].LunType = SCSI_ZIP;
} else {
SCSIDevices[id][lun].LunType = SCSI_NONE;
}
}
else if (cdrom_id != 0xff)
SCSIDevices[id][lun].LunType = SCSI_CDROM;
else if (zip_id != 0xff)
SCSIDevices[id][lun].LunType = SCSI_ZIP;
else
SCSIDevices[id][lun].LunType = SCSI_NONE;
scsi_device_reset(id, lun);
if (SCSIDevices[id][lun].CmdBuffer != NULL) {
free(SCSIDevices[id][lun].CmdBuffer);

View File

@@ -8,7 +8,7 @@
*
* SCSI controller handler header.
*
* Version: @(#)scsi_h 1.0.15 2018/03/21
* Version: @(#)scsi_h 1.0.16 2018/03/28
*
* Authors: TheCollector1995, <mariogplayer@gmail.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -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
@@ -306,7 +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];

View File

@@ -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.40 2018/04/11
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* 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"

View File

@@ -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.37 2018/03/28
*
* Authors: TheCollector1995, <mariogplayer@gmail.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -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"
@@ -529,6 +529,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;
@@ -550,7 +551,7 @@ static void
BuslogicSCSIBIOSDMATransfer(ESCMD *ESCSICmd, uint8_t TargetID, uint8_t LUN, int dir)
{
uint32_t DataPointer = ESCSICmd->DataPointer;
uint32_t DataLength = ESCSICmd->DataLength;
int DataLength = ESCSICmd->DataLength;
uint32_t Address;
uint32_t TransferLength;
@@ -997,6 +998,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;
@@ -1583,6 +1587,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 +1688,7 @@ static const device_config_t BT_ISA_Config[] = {
"0x134", 0x134
},
{
""
"", 0
}
},
},
@@ -1709,7 +1714,7 @@ static const device_config_t BT_ISA_Config[] = {
"IRQ 15", 15
},
{
""
"", 0
}
},
},
@@ -1726,7 +1731,7 @@ static const device_config_t BT_ISA_Config[] = {
"DMA 7", 7
},
{
""
"", 0
}
},
},
@@ -1746,7 +1751,7 @@ static const device_config_t BT_ISA_Config[] = {
"D800H", 0xd8000
},
{
""
"", 0
}
},
},

View File

@@ -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.16 2018/03/26
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -22,10 +22,10 @@
#include <wchar.h>
#include "../86box.h"
#include "../device.h"
#include "../cdrom/cdrom.h"
#include "../disk/hdd.h"
#include "../disk/zip.h"
#include "scsi.h"
#include "../cdrom/cdrom.h"
#include "scsi_disk.h"
@@ -41,8 +41,8 @@ static uint8_t scsi_device_target_command(int lun_type, uint8_t id, uint8_t *cdb
}
else if (lun_type == SCSI_CDROM)
{
cdrom_command(id, cdb);
return cdrom_CDROM_PHASE_to_scsi(id);
cdrom_command(cdrom[id], cdb);
return cdrom_CDROM_PHASE_to_scsi(cdrom[id]);
}
else if (lun_type == SCSI_ZIP)
{
@@ -64,7 +64,7 @@ static void scsi_device_target_phase_callback(int lun_type, uint8_t id)
}
else if (lun_type == SCSI_CDROM)
{
cdrom_phase_callback(id);
cdrom_phase_callback(cdrom[id]);
}
else if (lun_type == SCSI_ZIP)
{
@@ -85,7 +85,7 @@ static int scsi_device_target_err_stat_to_scsi(int lun_type, uint8_t id)
}
else if (lun_type == SCSI_CDROM)
{
return cdrom_CDROM_PHASE_to_scsi(id);
return cdrom_CDROM_PHASE_to_scsi(cdrom[id]);
}
else if (lun_type == SCSI_ZIP)
{
@@ -110,7 +110,7 @@ static void scsi_device_target_save_cdb_byte(int lun_type, uint8_t id, uint8_t c
}
else if (lun_type == SCSI_ZIP)
{
zip[id].request_length = cdb_byte;
zip[id]->request_length = cdb_byte;
}
else
{
@@ -137,7 +137,7 @@ int64_t scsi_device_get_callback(uint8_t scsi_id, uint8_t scsi_lun)
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id][scsi_lun];
return zip[id].callback;
return zip[id]->callback;
break;
default:
return -1LL;
@@ -164,7 +164,7 @@ uint8_t *scsi_device_sense(uint8_t scsi_id, uint8_t scsi_lun)
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id][scsi_lun];
return zip[id].sense;
return zip[id]->sense;
break;
default:
return scsi_null_device_sense;
@@ -187,7 +187,7 @@ void scsi_device_request_sense(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *buffe
break;
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id][scsi_lun];
cdrom_request_sense_for_scsi(id, buffer, alloc_length);
cdrom_request_sense_for_scsi(cdrom[id], buffer, alloc_length);
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id][scsi_lun];
@@ -200,7 +200,7 @@ 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 scsi_lun)
{
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
@@ -210,8 +210,28 @@ void scsi_device_type_data(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *type, uin
{
case SCSI_DISK:
id = scsi_hard_disks[scsi_id][scsi_lun];
*type = 0x00;
*rmb = (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? 0x80 : 0x00;
scsi_hd_reset(id);
break;
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id][scsi_lun];
cdrom_reset(cdrom[id]);
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id][scsi_lun];
zip_reset(id);
break;
}
}
void scsi_device_type_data(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *type, uint8_t *rmb)
{
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
switch (lun_type)
{
case SCSI_DISK:
*type = *rmb = 0x00;
break;
case SCSI_CDROM:
*type = 0x05;
@@ -222,7 +242,7 @@ 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;
}
}
@@ -241,7 +261,7 @@ int scsi_device_read_capacity(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *cdb, u
return scsi_hd_read_capacity(id, cdb, buffer, len);
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id][scsi_lun];
return cdrom_read_capacity(id, cdb, buffer, len);
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);
@@ -304,7 +324,7 @@ int scsi_device_cdb_length(uint8_t scsi_id, uint8_t scsi_lun)
return cdrom[id]->cdb_len;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id][scsi_lun];
return zip[id].cdb_len;
return zip[id]->cdb_len;
default:
return 12;
}

View File

@@ -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.7 2018/03/29
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -39,6 +39,7 @@ 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,
uint8_t alloc_length);
extern void scsi_device_reset(uint8_t scsi_id, uint8_t scsi_lun);
extern int scsi_device_read_capacity(uint8_t id, uint8_t lun,
uint8_t *cdb, uint8_t *buffer,
uint32_t *len);

File diff suppressed because it is too large Load Diff

View File

@@ -6,54 +6,31 @@
*
* Emulation of SCSI fixed and removable disks.
*
* Version: @(#)scsi_disk.h 1.0.3 2017/10/14
* Version: @(#)scsi_disk.h 1.0.4 2018/04/24
*
* Author: Miran Grca, <mgrca8@gmail.com>
* 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;
uint8_t status, phase,
error,
current_cdb[16],
sense[256];
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];
int requested_blocks, block_total,
packet_status, callback,
block_descriptor_len,
total_length, do_page_save;
uint32_t sector_pos, sector_len,
packet_len;
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;
int block_descriptor_len;
uint8_t *temp_buffer;
} scsi_hard_disk_t;
@@ -63,9 +40,6 @@ extern scsi_hard_disk_t shdc[HDD_NUM];
extern FILE *shdf[HDD_NUM];
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);
int scsi_hd_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len);

View File

@@ -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.13 2018/04/11
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* TheCollector1995, <mariogplayer@gmail.com>
@@ -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"

View File

@@ -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.11 2018/03/28
*
* Authors: Paul Brook (QEMU)
* Artyom Tarasenko (QEMU)
@@ -35,8 +35,8 @@
#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"
@@ -329,6 +329,8 @@ ncr53c810_irq_on_rsl(ncr53c810_t *dev)
static void
ncr53c810_soft_reset(ncr53c810_t *dev)
{
int i, j;
ncr53c810_log("LSI Reset\n");
dev->timer_period = dev->timer_enabled = 0;
@@ -383,13 +385,18 @@ ncr53c810_soft_reset(ncr53c810_t *dev)
dev->last_level = 0;
dev->gpreg0 = 0;
dev->sstop = 1;
for (i = 0; i < 16; i++) {
for (j = 0; j < 8; j++)
scsi_device_reset(i, j);
}
}
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 +414,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 +589,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];
if ((((id) == -1) && !scsi_device_present(id, dev->current_lun))) {
if ((!scsi_device_present(id, dev->current_lun))) {
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;
}
@@ -673,7 +681,7 @@ ncr53c810_do_command(ncr53c810_t *dev, uint8_t id)
dev->command_complete = 0;
sd = &SCSIDevices[id][dev->current_lun];
if (((id == -1) || !scsi_device_present(id, dev->current_lun))) {
if (!scsi_device_present(id, dev->current_lun)) {
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;
@@ -747,7 +755,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;
@@ -1067,7 +1075,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, 0)) {
ncr53c810_bad_selection(dev, id);
break;
}

View File

@@ -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/03/28
*
* Authors: TheCollector1995, <mariogplayer@gmail.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -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"
@@ -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);
@@ -793,8 +792,7 @@ 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;
uint32_t Address, i;
int32_t BufLen = SCSIDevices[req->TargetID][req->LUN].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)));
@@ -823,7 +821,7 @@ 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);
@@ -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][req->LUN].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][req->LUN].CmdBuffer, MIN(BufLen, (int) DataLength));
}
}
}
@@ -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);
@@ -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, lun);
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, j;
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,14 @@ x54x_reset(x54x_t *dev)
dev->MailboxCount = 0;
dev->MailboxOutPosCur = 0;
if (dev->ven_reset) {
dev->ven_reset(dev);
/* Reset all devices on controller reset. */
for (i = 0; i < 16; i++) {
for (j = 0; j < 8; j++)
scsi_device_reset(i, j);
}
if (dev->ven_reset)
dev->ven_reset(dev);
}
@@ -1476,6 +1501,14 @@ 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++) {
for (j = 0; j < 8; j++)
scsi_device_reset(i, j);
}
}
if (val & CTRL_IRST) {
clear_irq(dev);
x54x_log("Interrupt reset: ");
@@ -1643,7 +1676,7 @@ 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; i<SCSI_ID_MAX; i++) {
for (i=0; i<8; i++) {
dev->DataBuf[i] = 0x00;
/* Skip the HA .. */
@@ -1902,6 +1935,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;

View File

@@ -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, <mariogplayer@gmail.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -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 */

View File

@@ -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.8 2018/04/04
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016-2018 Miran Grca.
@@ -125,7 +125,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
@@ -206,7 +206,7 @@ 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;
@@ -345,6 +345,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;
}

View File

@@ -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, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -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;
}

View File

@@ -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.12 2018/04/04
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016-2018 Miran Grca.
@@ -566,14 +566,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;
}

View File

@@ -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.10 2018/04/04
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016-2018 Miran Grca.
@@ -256,7 +256,7 @@ process_value:
ide_set_side(0, 0x376 | or_value);
if (val & 0x40)
{
ide_pri_enable_ex();
ide_pri_enable();
}
#endif
}
@@ -476,6 +476,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;
}

Some files were not shown because too many files have changed in this diff Show More