Separation of HDD (disks) and HDC (disk controllers) with major cleanup. IDE remains same until Kotori finishes that part.

This commit is contained in:
waltje
2017-09-30 16:56:38 -04:00
parent c62e0b923c
commit 9d9f5fdd58
44 changed files with 3098 additions and 2843 deletions

View File

@@ -8,7 +8,7 @@
#
# Modified Makefile for Win32 (MinGW32) environment.
#
# Version: @(#)Makefile.mingw 1.0.49 2017/09/28
# Version: @(#)Makefile.mingw 1.0.49 2017/09/29
#
# Authors: Miran Grca, <mgrca8@gmail.com>
# Fred N. van Kempen, <decwiz@yahoo.com>
@@ -264,7 +264,7 @@ DEVOBJ := bugger.o lpt.o $(SERIAL) \
tandy_eeprom.o tandy_rom.o \
sio_detect.o \
sio_fdc37c665.o sio_fdc37c669.o sio_fdc37c932fr.o \
sio_pc87306.o sio_w83877f.o sio_um8669f.o \
sio_pc87306.o sio_w83877f.o sio_um8669f.o piix.o \
keyboard.o \
keyboard_xt.o keyboard_at.o keyboard_pcjr.o \
keyboard_amstrad.o keyboard_olim24.o \
@@ -279,13 +279,15 @@ FDDOBJ := fdd.o fdc.o fdi2raw.o \
floppy_fdi.o floppy_imd.o floppy_img.o floppy_json.o \
floppy_td0.o
HDDOBJ := hdd.o \
hdd_image.o hdd_table.o \
hdc.o \
hdc_esdi_at.o hdc_esdi_mca.o hdc_ide.o hdc_mfm_at.o \
hdc_mfm_xt.o hdc_xtide.o
CDROMOBJ := cdrom.o \
cdrom_dosbox.o cdrom_image.o cdrom_ioctl.o cdrom_null.o
HDDOBJ := hdd.o hdd_image.o \
hdd_mfm_at.o hdd_mfm_xebec.o hdd_esdi_at.o hdd_esdi_mca.o \
hdd_ide_at.o hdd_ide_xt.o piix.o
ifeq ($(USB), y)
USBOBJ := usb.o
endif

View File

@@ -9,7 +9,7 @@
* Implementation of the CD-ROM drive with SCSI(-like)
* commands, for both ATAPI and SCSI usage.
*
* Version: @(#)cdrom.c 1.0.6 2017/09/24
* Version: @(#)cdrom.c 1.0.7 2017/09/29
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016,2017 Miran Grca.
@@ -26,7 +26,8 @@
#include "../scsi/scsi.h"
#include "../timer.h"
#include "../nvr.h"
#include "../hdd/hdd_ide_at.h"
#include "../hdd/hdd.h"
#include "../hdd/hdc_ide.h"
#include "../win/plat_iodev.h"
#include "cdrom.h"

View File

@@ -8,7 +8,7 @@
*
* Configuration file handler.
*
* Version: @(#)config.c 1.0.6 2017/09/24
* Version: @(#)config.c 1.0.7 2017/09/29
*
* Authors: Sarah Walker,
* Miran Grca, <mgrca8@gmail.com>
@@ -40,7 +40,8 @@
#include "floppy/fdc.h"
#include "floppy/fdd.h"
#include "hdd/hdd.h"
#include "hdd/hdd_ide_at.h"
#include "hdd/hdc.h"
#include "hdd/hdc_ide.h"
#include "machine/machine.h"
#include "mouse.h"
#ifdef USE_NETWORK
@@ -793,12 +794,17 @@ load_other_peripherals(void)
else
scsi_card_current = 0;
memset(hdd_controller_name, '\0', sizeof(hdd_controller_name));
p = config_get_string(cat, "hdd_controller", NULL);
if (p != NULL)
strcpy(hdd_controller_name, p);
memset(hdc_name, '\0', sizeof(hdc_name));
p = config_get_string(cat, "hdc", NULL);
if (p == NULL) {
p = config_get_string(cat, "hdd_controller", NULL);
if (p != NULL)
config_delete_var(cat, "hdd_controller");
}
if (p != NULL)
strcpy(hdc_name, p);
else
strcpy(hdd_controller_name, "none");
strcpy(hdc_name, "none");
memset(temp, '\0', sizeof(temp));
for (c = 2; c < 4; c++)
@@ -821,8 +827,9 @@ load_other_peripherals(void)
/* FIXME: this should be in HDD somewhere. --FvK */
static int
string_to_bus(char *str, int cdrom)
/* will be moved to hdd.c */
int
hdd_string_to_bus(char *str, int cdrom)
{
if (! strcmp(str, "none"))
{
@@ -929,21 +936,55 @@ no_mfm_cdrom:
}
/* FIXME: this should be in HDD. --FvK */
static int
hard_disk_is_valid(int c)
char *
hdd_bus_to_string(int bus, int cdrom)
{
if (hdc[c].bus == HDD_BUS_DISABLED)
switch (bus)
{
case HDD_BUS_DISABLED:
default:
return "none";
break;
case HDD_BUS_MFM:
return "mfm";
break;
case HDD_BUS_XTIDE:
return "xtide";
break;
case HDD_BUS_ESDI:
return "esdi";
break;
case HDD_BUS_IDE_PIO_ONLY:
return cdrom ? "atapi_pio_only" : "ide_pio_only";
break;
case HDD_BUS_IDE_PIO_AND_DMA:
return cdrom ? "atapi_pio_and_dma" : "ide_pio_and_dma";
break;
case HDD_BUS_SCSI:
return "scsi";
break;
case HDD_BUS_SCSI_REMOVABLE:
return "scsi_removable";
break;
}
}
/* FIXME: this should be in HDD. --FvK */
int
hdd_is_valid(int c)
{
if (hdd[c].bus == HDD_BUS_DISABLED)
{
return 0;
}
if ((wcslen(hdc[c].fn) == 0) && (hdc[c].bus != HDD_BUS_SCSI_REMOVABLE))
if ((wcslen(hdd[c].fn) == 0) && (hdd[c].bus != HDD_BUS_SCSI_REMOVABLE))
{
return 0;
}
if ((hdc[c].tracks == 0) || (hdc[c].hpc == 0) || (hdc[c].spt == 0))
if ((hdd[c].tracks == 0) || (hdd[c].hpc == 0) || (hdd[c].spt == 0))
{
return 0;
}
@@ -995,7 +1036,7 @@ load_hard_disks(void)
int board = 0, dev = 0;
memset(temps, '\0', sizeof(temps));
for (c = 0; c < HDC_NUM; c++)
for (c = 0; c < HDD_NUM; c++)
{
sprintf(temps, "hdd_%02i_parameters", c + 1);
p = config_get_string(cat, temps, NULL);
@@ -1003,17 +1044,19 @@ load_hard_disks(void)
p = "0, 0, 0, 0, none";
if (tally_char(p, ',') == 3)
{
sscanf(p, "%" PRIu64 ", %" PRIu64", %" PRIu64 ", %s", &hdc[c].spt, &hdc[c].hpc, &hdc[c].tracks, s);
hdc[c].wp = 0;
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", &hdc[c].spt, &hdc[c].hpc, &hdc[c].tracks, &hdc[c].wp, s);
sscanf(p, "%" PRIu64 ", %" PRIu64", %" PRIu64 ", %i, %s",
&hdd[c].spt, &hdd[c].hpc, &hdd[c].tracks, (int *)&hdd[c].wp, s);
}
hdc[c].bus = string_to_bus(s, 0);
hdd[c].bus = hdd_string_to_bus(s, 0);
switch(hdc[c].bus)
switch(hdd[c].bus)
{
case HDD_BUS_DISABLED:
default:
@@ -1044,63 +1087,45 @@ load_hard_disks(void)
break;
}
if (hdc[c].spt > max_spt)
{
hdc[c].spt = max_spt;
}
if (hdc[c].hpc > max_hpc)
{
hdc[c].hpc = max_hpc;
}
if (hdc[c].tracks > max_tracks)
{
hdc[c].tracks = max_tracks;
}
if (hdd[c].spt > max_spt)
hdd[c].spt = max_spt;
if (hdd[c].hpc > max_hpc)
hdd[c].hpc = max_hpc;
if (hdd[c].tracks > max_tracks)
hdd[c].tracks = max_tracks;
/* MFM/RLL */
sprintf(temps, "hdd_%02i_mfm_channel", c + 1);
if (hdc[c].bus == HDD_BUS_MFM)
{
hdc[c].mfm_channel = !!config_get_int(cat, temps, c & 1);
}
if (hdd[c].bus == HDD_BUS_MFM)
hdd[c].mfm_channel = !!config_get_int(cat, temps, c & 1);
else
{
config_delete_var(cat, temps);
}
/* XT IDE */
sprintf(temps, "hdd_%02i_xtide_channel", c + 1);
if (hdc[c].bus == HDD_BUS_XTIDE)
{
hdc[c].xtide_channel = !!config_get_int(cat, temps, c & 1);
}
if (hdd[c].bus == HDD_BUS_XTIDE)
hdd[c].xtide_channel = !!config_get_int(cat, temps, c & 1);
else
{
config_delete_var(cat, temps);
}
/* ESDI */
sprintf(temps, "hdd_%02i_esdi_channel", c + 1);
if (hdc[c].bus == HDD_BUS_ESDI)
{
hdc[c].esdi_channel = !!config_get_int(cat, temps, c & 1);
}
if (hdd[c].bus == HDD_BUS_ESDI)
hdd[c].esdi_channel = !!config_get_int(cat, temps, c & 1);
else
{
config_delete_var(cat, temps);
}
/* IDE */
sprintf(temps, "hdd_%02i_ide_channel", c + 1);
if ((hdc[c].bus == HDD_BUS_IDE_PIO_ONLY) || (hdc[c].bus == HDD_BUS_IDE_PIO_AND_DMA))
if ((hdd[c].bus == HDD_BUS_IDE_PIO_ONLY) || (hdd[c].bus == HDD_BUS_IDE_PIO_AND_DMA))
{
sprintf(temps2, "%01u:%01u", c >> 1, c & 1);
p = config_get_string(cat, temps, temps2);
if (strstr(p, ":") == NULL)
{
sscanf(p, "%i", &hdc[c].ide_channel);
hdc[c].ide_channel &= 7;
sscanf(p, "%i", (int *)&hdd[c].ide_channel);
hdd[c].ide_channel &= 7;
}
else
{
@@ -1108,13 +1133,11 @@ load_hard_disks(void)
board &= 3;
dev &= 1;
hdc[c].ide_channel = (board << 1) + dev;
hdd[c].ide_channel = (board << 1) + dev;
}
if (hdc[c].ide_channel > 7)
{
hdc[c].ide_channel = 7;
}
if (hdd[c].ide_channel > 7)
hdd[c].ide_channel = 7;
}
else
{
@@ -1123,32 +1146,28 @@ load_hard_disks(void)
/* SCSI */
sprintf(temps, "hdd_%02i_scsi_location", c + 1);
if ((hdc[c].bus == HDD_BUS_SCSI) || (hdc[c].bus == HDD_BUS_SCSI_REMOVABLE))
if ((hdd[c].bus == HDD_BUS_SCSI) || (hdd[c].bus == HDD_BUS_SCSI_REMOVABLE))
{
sprintf(temps2, "%02u:%02u", c, 0);
p = config_get_string(cat, temps, temps2);
sscanf(p, "%02u:%02u", &hdc[c].scsi_id, &hdc[c].scsi_lun);
sscanf(p, "%02u:%02u", (int *)&hdd[c].scsi_id, (int *)&hdd[c].scsi_lun);
if (hdc[c].scsi_id > 15)
{
hdc[c].scsi_id = 15;
}
if (hdc[c].scsi_lun > 7)
{
hdc[c].scsi_lun = 7;
}
if (hdd[c].scsi_id > 15)
hdd[c].scsi_id = 15;
if (hdd[c].scsi_lun > 7)
hdd[c].scsi_lun = 7;
}
else
{
config_delete_var(cat, temps);
}
memset(hdc[c].fn, 0x00, sizeof(hdc[c].fn));
memset(hdc[c].prev_fn, 0x00, sizeof(hdc[c].prev_fn));
memset(hdd[c].fn, 0x00, sizeof(hdd[c].fn));
memset(hdd[c].prev_fn, 0x00, sizeof(hdd[c].prev_fn));
sprintf(temps, "hdd_%02i_fn", c + 1);
wp = config_get_wstring(cat, temps, L"");
#if 1
#if 0
/*
* NOTE:
* Temporary hack to remove the absolute
@@ -1165,31 +1184,31 @@ load_hard_disks(void)
wcscpy((wchar_t *)hdc[c].fn, &wp[wcslen(cfg_path)]);
} else
#endif
memcpy(hdc[c].fn, wp, (wcslen(wp) << 1) + 2);
memcpy(hdd[c].fn, wp, (wcslen(wp) << 1) + 2);
/* If the hard disk is in any way empty or invalid, mark the relevant variables for deletion. */
if (!hard_disk_is_valid(c))
if (! hdd_is_valid(c))
{
sprintf(temps, "hdd_%02i_parameters", c + 1);
sprintf(temps, "hdd_%02i_parameters", c+1);
config_delete_var(cat, temps);
sprintf(temps, "hdd_%02i_preide_channels", c + 1);
sprintf(temps, "hdd_%02i_preide_channels", c+1);
config_delete_var(cat, temps);
sprintf(temps, "hdd_%02i_ide_channels", c + 1);
sprintf(temps, "hdd_%02i_ide_channels", c+1);
config_delete_var(cat, temps);
sprintf(temps, "hdd_%02i_scsi_location", c + 1);
sprintf(temps, "hdd_%02i_scsi_location", c+1);
config_delete_var(cat, temps);
sprintf(temps, "hdd_%02i_fn", c + 1);
sprintf(temps, "hdd_%02i_fn", c+1);
config_delete_var(cat, temps);
}
sprintf(temps, "hdd_%02i_mfm_channel", c + 1);
sprintf(temps, "hdd_%02i_mfm_channel", c+1);
config_delete_var(cat, temps);
sprintf(temps, "hdd_%02i_ide_channel", c + 1);
sprintf(temps, "hdd_%02i_ide_channel", c+1);
config_delete_var(cat, temps);
}
}
@@ -1296,7 +1315,7 @@ load_removable_devices(void)
sscanf("0, none", "%u, %s", &cdrom_drives[c].sound_on, s);
}
cdrom_drives[c].bus_type = string_to_bus(s, 1);
cdrom_drives[c].bus_type = hdd_string_to_bus(s, 1);
sprintf(temps, "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))
@@ -1306,7 +1325,7 @@ load_removable_devices(void)
if (strstr(p, ":") == NULL)
{
sscanf(p, "%i", &hdc[c].ide_channel);
sscanf(p, "%i", (int *)&hdd[c].ide_channel);
cdrom_drives[c].ide_channel &= 7;
}
else
@@ -1427,7 +1446,7 @@ config_load(wchar_t *fn)
vid_api = 1;
enable_sync = 1;
joystick_type = 7;
strcpy(hdd_controller_name, "none");
strcpy(hdc_name, "none");
serial_enabled[0] = 1;
serial_enabled[1] = 1;
lpt_enabled = 1;
@@ -1979,13 +1998,13 @@ save_other_peripherals(void)
config_set_string(cat, "scsicard", scsi_card_get_internal_name(scsi_card_current));
}
if (!strcmp(hdd_controller_name, "none"))
if (!strcmp(hdc_name, "none"))
{
config_delete_var(cat, "hdd_controller");
config_delete_var(cat, "hdc");
}
else
{
config_set_string(cat, "hdd_controller", hdd_controller_name);
config_set_string(cat, "hdc", hdc_name);
}
memset(temps, '\0', sizeof(temps));
@@ -2017,40 +2036,6 @@ save_other_peripherals(void)
}
static char *
bus_to_string(int bus, int cdrom)
{
switch (bus)
{
case HDD_BUS_DISABLED:
default:
return "none";
break;
case HDD_BUS_MFM:
return "mfm";
break;
case HDD_BUS_XTIDE:
return "xtide";
break;
case HDD_BUS_ESDI:
return "esdi";
break;
case HDD_BUS_IDE_PIO_ONLY:
return cdrom ? "atapi_pio_only" : "ide_pio_only";
break;
case HDD_BUS_IDE_PIO_AND_DMA:
return cdrom ? "atapi_pio_and_dma" : "ide_pio_and_dma";
break;
case HDD_BUS_SCSI:
return "scsi";
break;
case HDD_BUS_SCSI_REMOVABLE:
return "scsi_removable";
break;
}
}
/* Save "Hard Disks" section. */
static void
save_hard_disks(void)
@@ -2063,81 +2048,82 @@ save_hard_disks(void)
char *p;
memset(temps, 0, sizeof(temps));
for (c = 0; c < HDC_NUM; c++)
for (c = 0; c < HDD_NUM; c++)
{
sprintf(temps, "hdd_%02i_parameters", c + 1);
sprintf(temps, "hdd_%02i_parameters", c+1);
memset(s, 0, sizeof(s));
if (!hard_disk_is_valid(c))
if (! hdd_is_valid(c))
{
config_delete_var(cat, temps);
}
else
{
p = bus_to_string(hdc[c].bus, 0);
sprintf(temps2, "%" PRIu64 ", %" PRIu64", %" PRIu64 ", %i, %s", hdc[c].spt, hdc[c].hpc, hdc[c].tracks, hdc[c].wp, p);
p = hdd_bus_to_string(hdd[c].bus, 0);
sprintf(temps2, "%" PRIu64 ", %" PRIu64", %" PRIu64 ", %i, %s",
hdd[c].spt, hdd[c].hpc, hdd[c].tracks, hdd[c].wp, p);
config_set_string(cat, temps, temps2);
}
sprintf(temps, "hdd_%02i_mfm_channel", c + 1);
if (!hard_disk_is_valid(c) || (hdc[c].bus != HDD_BUS_MFM))
sprintf(temps, "hdd_%02i_mfm_channel", c+1);
if (! hdd_is_valid(c) || (hdd[c].bus != HDD_BUS_MFM))
{
config_delete_var(cat, temps);
}
else
{
config_set_int(cat, temps, hdc[c].mfm_channel);
config_set_int(cat, temps, hdd[c].mfm_channel);
}
sprintf(temps, "hdd_%02i_xtide_channel", c + 1);
if (!hard_disk_is_valid(c) || (hdc[c].bus != HDD_BUS_XTIDE))
sprintf(temps, "hdd_%02i_xtide_channel", c+1);
if (! hdd_is_valid(c) || (hdd[c].bus != HDD_BUS_XTIDE))
{
config_delete_var(cat, temps);
}
else
{
config_set_int(cat, temps, hdc[c].xtide_channel);
config_set_int(cat, temps, hdd[c].xtide_channel);
}
sprintf(temps, "hdd_%02i_esdi_channel", c + 1);
if (!hard_disk_is_valid(c) || (hdc[c].bus != HDD_BUS_ESDI))
sprintf(temps, "hdd_%02i_esdi_channel", c+1);
if (! hdd_is_valid(c) || (hdd[c].bus != HDD_BUS_ESDI))
{
config_delete_var(cat, temps);
}
else
{
config_set_int(cat, temps, hdc[c].esdi_channel);
config_set_int(cat, temps, hdd[c].esdi_channel);
}
sprintf(temps, "hdd_%02i_ide_channel", c + 1);
if (!hard_disk_is_valid(c) || ((hdc[c].bus != HDD_BUS_IDE_PIO_ONLY) && (hdc[c].bus != HDD_BUS_IDE_PIO_AND_DMA)))
if (! hdd_is_valid(c) || ((hdd[c].bus != HDD_BUS_IDE_PIO_ONLY) && (hdd[c].bus != HDD_BUS_IDE_PIO_AND_DMA)))
{
config_delete_var(cat, temps);
}
else
{
sprintf(temps2, "%01u:%01u", hdc[c].ide_channel >> 1, hdc[c].ide_channel & 1);
sprintf(temps2, "%01u:%01u", hdd[c].ide_channel >> 1, hdd[c].ide_channel & 1);
config_set_string(cat, temps, temps2);
}
sprintf(temps, "hdd_%02i_scsi_location", c + 1);
if (!hard_disk_is_valid(c) || ((hdc[c].bus != HDD_BUS_SCSI) && (hdc[c].bus != HDD_BUS_SCSI_REMOVABLE)))
if (! hdd_is_valid(c) || ((hdd[c].bus != HDD_BUS_SCSI) && (hdd[c].bus != HDD_BUS_SCSI_REMOVABLE)))
{
config_delete_var(cat, temps);
}
else
{
sprintf(temps2, "%02u:%02u", hdc[c].scsi_id, hdc[c].scsi_lun);
sprintf(temps2, "%02u:%02u", hdd[c].scsi_id, hdd[c].scsi_lun);
config_set_string(cat, temps, temps2);
}
sprintf(temps, "hdd_%02i_fn", c + 1);
if (!hard_disk_is_valid(c) || (wcslen(hdc[c].fn) == 0))
sprintf(temps, "hdd_%02i_fn", c+1);
if (! hdd_is_valid(c) || (wcslen(hdd[c].fn) == 0))
{
config_delete_var(cat, temps);
}
else
{
config_set_wstring(cat, temps, hdc[c].fn);
config_set_wstring(cat, temps, hdd[c].fn);
}
}
@@ -2233,7 +2219,7 @@ save_removable_devices(void)
}
else
{
sprintf(temps2, "%u, %s", cdrom_drives[c].sound_on, bus_to_string(cdrom_drives[c].bus_type, 1));
sprintf(temps2, "%u, %s", cdrom_drives[c].sound_on, hdd_bus_to_string(cdrom_drives[c].bus_type, 1));
config_set_string(cat, temps, temps2);
}

149
src/hdd/hdc.c Normal file
View File

@@ -0,0 +1,149 @@
/*
* 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.
*
* Common code to handle all sorts of disk controllers.
*
* Version: @(#)hdc.c 1.0.1 2017/09/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.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../ibm.h"
#include "../cpu/cpu.h"
#include "../device.h"
#include "../machine/machine.h"
#include "hdc.h"
char hdc_name[16];
int hdc_current;
static void *
null_init(void)
{
return(NULL);
}
static void
null_close(void *priv)
{
}
static device_t null_device = {
"Null HDC", 0,
null_init, null_close,
NULL, NULL, NULL, NULL, NULL
};
static struct {
char name[50];
char internal_name[16];
device_t *device;
int is_mfm;
} controllers[] = {
{ "None", "none",
&null_device, 0 },
{ "Internal Controller", "internal",
&null_device, 0 },
{ "IBM PC Fixed Disk Adapter (MFM,Xebec)", "mfm_xebec",
&mfm_xt_xebec_device, 1 },
{ "PC DTC-5150X Fixed Disk Adapter (MFM)", "dtc5150x",
&mfm_xt_dtc5150x_device, 1 },
{ "IBM PC/AT Fixed Disk Adapter (WD1003)", "mfm_at",
&mfm_at_wd1003_device, 1 },
{ "PC/AT ESDI Fixed Disk Adapter (WD1007V-SE1)", "wd1007vse1",
&esdi_at_wd1007vse1_device, 0 },
{ "IBM PS/2 ESDI Fixed Disk Adapter (ESDI)","esdi_mca",
&esdi_ps2_device, 1 },
{ "[IDE] PC/XT XTIDE", "xtide",
&xtide_device , 0 },
{ "[IDE] PC/AT XTIDE", "xtide_at",
&xtide_at_device, 0 },
{ "[IDE] PS/2 XTIDE (Acculogic)", "xtide_ps2",
&xtide_ps2_device, 0 },
{ "[IDE] PS/2 AT XTIDE (1.1.5)", "xtide_at_ps2",
&xtide_at_ps2_device, 0 },
{ "", "", NULL, 0 }
};
char *
hdc_get_name(int hdc)
{
return(controllers[hdc].name);
}
char *
hdc_get_internal_name(int hdc)
{
return(controllers[hdc].internal_name);
}
int
hdc_get_flags(int hdc)
{
return(controllers[hdc].device->flags);
}
int
hdc_available(int hdc)
{
return(device_available(controllers[hdc].device));
}
int
hdc_current_is_mfm(void)
{
return(controllers[hdc_current].is_mfm);
}
void
hdc_init(char *name)
{
int c;
if (machines[machine].flags & MACHINE_HAS_IDE) return;
for (c=0; controllers[c].device; c++) {
if (! strcmp(name, controllers[c].internal_name)) {
hdc_current = c;
if (strcmp(name, "none")) {
device_add(controllers[c].device);
return;
}
}
}
}

47
src/hdd/hdc.h Normal file
View File

@@ -0,0 +1,47 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Definitions for the common disk controller handler.
*
* Version: @(#)hdc.h 1.0.1 2017/09/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.
*/
#ifndef EMU_HDC_H
# define EMU_HDC_H
extern char hdc_name[16];
extern int hdc_current;
extern device_t mfm_xt_xebec_device; /* mfm_xt_xebec */
extern device_t mfm_xt_dtc5150x_device; /* mfm_xt_dtc */
extern device_t mfm_at_wd1003_device; /* mfm_at_wd1003 */
extern device_t esdi_at_wd1007vse1_device; /* esdi_at */
extern device_t esdi_ps2_device; /* esdi_mca */
extern device_t xtide_device; /* xtide_xt */
extern device_t xtide_at_device; /* xtide_at */
extern device_t xtide_ps2_device; /* xtide_ps2 */
extern device_t xtide_at_ps2_device; /* xtide_at_ps2 */
extern char *hdc_get_name(int hdc);
extern char *hdc_get_internal_name(int hdc);
extern int hdc_get_flags(int hdc);
extern int hdc_available(int hdc);
extern int hdc_current_is_mfm(void);
extern void hdc_init(char *internal_name);
#endif /*EMU_HDC_H*/

847
src/hdd/hdc_esdi_at.c Normal file
View File

@@ -0,0 +1,847 @@
/*
* 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.
*
* Driver for the ESDI controller (WD1007-vse1) for PC/AT.
*
* Version: @(#)hdc_esdi_at.c 1.0.1 2017/09/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.
*/
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../ibm.h"
#include "../device.h"
#include "../io.h"
#include "../mem.h"
#include "../pic.h"
#include "../rom.h"
#include "../timer.h"
#include "hdc.h"
#include "hdd.h"
#define HDC_TIME (TIMER_USEC*10)
#define BIOS_FILE L"roms/hdd/esdi_at/62-000279-061.bin"
#define STAT_ERR 0x01
#define STAT_INDEX 0x02
#define STAT_CORRECTED_DATA 0x04
#define STAT_DRQ 0x08 /* Data request */
#define STAT_DSC 0x10
#define STAT_SEEK_COMPLETE 0x20
#define STAT_READY 0x40
#define STAT_BUSY 0x80
#define ERR_DAM_NOT_FOUND 0x01 /*Data Address Mark not found*/
#define ERR_TR000 0x02 /*Track 0 not found*/
#define ERR_ABRT 0x04 /*Command aborted*/
#define ERR_ID_NOT_FOUND 0x10 /*ID not found*/
#define ERR_DATA_CRC 0x40 /*Data CRC error*/
#define ERR_BAD_BLOCK 0x80 /*Bad Block detected*/
#define CMD_NOP 0x00
#define CMD_RESTORE 0x10
#define CMD_READ 0x20
#define CMD_WRITE 0x30
#define CMD_VERIFY 0x40
#define CMD_FORMAT 0x50
#define CMD_SEEK 0x70
#define CMD_DIAGNOSE 0x90
#define CMD_SET_PARAMETERS 0x91
#define CMD_READ_PARAMETERS 0xec
extern char ide_fn[4][512];
typedef struct {
int cfg_spt;
int cfg_hpc;
int current_cylinder;
int real_spt;
int real_hpc;
int real_tracks;
int present;
int hdd_num;
} drive_t;
typedef struct {
uint8_t status;
uint8_t error;
int secount,sector,cylinder,head,cylprecomp;
uint8_t command;
uint8_t fdisk;
int pos;
int drive_sel;
int reset;
uint16_t buffer[256];
int irqstat;
int callback;
drive_t drives[2];
rom_t bios_rom;
} esdi_t;
static inline void
irq_raise(esdi_t *esdi)
{
if (! (esdi->fdisk&2))
picint(1<<14);
esdi->irqstat=1;
}
static inline void
irq_lower(esdi_t *esdi)
{
picintc(1<<14);
}
static void
irq_update(esdi_t *esdi)
{
if (esdi->irqstat && !((pic2.pend|pic2.ins)&0x40) && !(esdi->fdisk & 2))
picint(1<<14);
}
/* Return the sector offset for the current register values. */
static int
get_sector(esdi_t *esdi, off64_t *addr)
{
drive_t *drive = &esdi->drives[esdi->drive_sel];
int heads = drive->cfg_hpc;
int sectors = drive->cfg_spt;
if (esdi->head > heads) {
pclog("esdi_get_sector: past end of configured heads\n");
return 1;
}
if (esdi->sector >= sectors+1) {
pclog("esdi_get_sector: past end of configured sectors\n");
return 1;
}
if (drive->cfg_spt==drive->real_spt && drive->cfg_hpc==drive->real_hpc) {
*addr = ((((off64_t) esdi->cylinder * heads) + esdi->head) *
sectors) + (esdi->sector - 1);
} else {
/*
* When performing translation, the firmware seems to leave 1
* sector per track inaccessible (spare sector)
*/
int c, h, s;
*addr = ((((off64_t) esdi->cylinder * heads) + esdi->head) *
sectors) + (esdi->sector - 1);
s = *addr % (drive->real_spt - 1);
h = (*addr / (drive->real_spt - 1)) % drive->real_hpc;
c = (*addr / (drive->real_spt - 1)) / drive->real_hpc;
*addr = ((((off64_t)c * drive->real_hpc) + h) * drive->real_spt) + s;
}
return(0);
}
/* Move to the next sector using CHS addressing. */
static void
next_sector(esdi_t *esdi)
{
drive_t *drive = &esdi->drives[esdi->drive_sel];
esdi->sector++;
if (esdi->sector == (drive->cfg_spt + 1)) {
esdi->sector = 1;
if (++esdi->head == drive->cfg_hpc) {
esdi->head = 0;
esdi->cylinder++;
if (drive->current_cylinder < drive->real_tracks)
drive->current_cylinder++;
}
}
}
static void
esdi_writew(uint16_t port, uint16_t val, void *priv)
{
esdi_t *esdi = (esdi_t *)priv;
esdi->buffer[esdi->pos >> 1] = val;
esdi->pos += 2;
if (esdi->pos >= 512) {
esdi->pos = 0;
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 6*HDC_TIME;
timer_update_outstanding();
}
}
static void
esdi_write(uint16_t port, uint8_t val, void *priv)
{
esdi_t *esdi = (esdi_t *)priv;
switch (port) {
case 0x1F0: /* Data */
esdi_writew(port, val | (val << 8), priv);
return;
case 0x1F1: /* Write precompenstation */
esdi->cylprecomp = val;
return;
case 0x1F2: /* Sector count */
esdi->secount = val;
return;
case 0x1F3: /* Sector */
esdi->sector = val;
return;
case 0x1F4: /* Cylinder low */
esdi->cylinder = (esdi->cylinder & 0xFF00) | val;
return;
case 0x1F5: /* Cylinder high */
esdi->cylinder = (esdi->cylinder & 0xFF) | (val << 8);
return;
case 0x1F6: /* Drive/Head */
esdi->head = val & 0xF;
esdi->drive_sel = (val & 0x10) ? 1 : 0;
if (esdi->drives[esdi->drive_sel].present)
esdi->status = 0;
else
esdi->status = STAT_READY | STAT_DSC;
return;
case 0x1F7: /* Command register */
irq_lower(esdi);
esdi->command = val;
esdi->error = 0;
switch (val & 0xf0) {
case CMD_RESTORE:
esdi->command &= ~0x0f; /*Mask off step rate*/
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200*HDC_TIME;
timer_update_outstanding();
break;
case CMD_SEEK:
esdi->command &= ~0x0f; /*Mask off step rate*/
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200*HDC_TIME;
timer_update_outstanding();
break;
default:
switch (val) {
case CMD_NOP:
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200*HDC_TIME;
timer_update_outstanding();
break;
case CMD_READ:
case CMD_READ+1:
case CMD_READ+2:
case CMD_READ+3:
esdi->command &= ~3;
if (val & 2)
fatal("Read with ECC\n");
case 0xa0:
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200*HDC_TIME;
timer_update_outstanding();
break;
case CMD_WRITE:
case CMD_WRITE+1:
case CMD_WRITE+2:
case CMD_WRITE+3:
esdi->command &= ~3;
if (val & 2)
fatal("Write with ECC\n");
esdi->status = STAT_DRQ | STAT_DSC;
esdi->pos=0;
break;
case CMD_VERIFY:
case CMD_VERIFY+1:
esdi->command &= ~1;
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200*HDC_TIME;
timer_update_outstanding();
break;
case CMD_FORMAT:
esdi->status = STAT_DRQ;
esdi->pos=0;
break;
case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 30*HDC_TIME;
timer_update_outstanding();
break;
case CMD_DIAGNOSE: /* Execute Drive Diagnostics */
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200*HDC_TIME;
timer_update_outstanding();
break;
case 0xe0: /*???*/
case CMD_READ_PARAMETERS:
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200*HDC_TIME;
timer_update_outstanding();
break;
default:
pclog("Bad esdi command %02X\n", val);
case 0xe8: /*???*/
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200*HDC_TIME;
timer_update_outstanding();
break;
}
}
break;
case 0x3F6: /* Device control */
if ((esdi->fdisk & 4) && !(val & 4)) {
timer_process();
esdi->callback = 500*HDC_TIME;
timer_update_outstanding();
esdi->reset = 1;
esdi->status = STAT_BUSY;
}
if (val & 4) {
/*Drive held in reset*/
timer_process();
esdi->callback = 0;
timer_update_outstanding();
esdi->status = STAT_BUSY;
}
esdi->fdisk = val;
irq_update(esdi);
}
}
static uint16_t
esdi_readw(uint16_t port, void *priv)
{
esdi_t *esdi = (esdi_t *)priv;
uint16_t temp;
temp = esdi->buffer[esdi->pos >> 1];
esdi->pos += 2;
if (esdi->pos >= 512) {
esdi->pos=0;
esdi->status = STAT_READY | STAT_DSC;
if (esdi->command == CMD_READ || esdi->command == 0xa0) {
esdi->secount = (esdi->secount - 1) & 0xff;
if (esdi->secount) {
next_sector(esdi);
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 6*HDC_TIME;
timer_update_outstanding();
}
}
}
return(temp);
}
static uint8_t
esdi_read(uint16_t port, void *priv)
{
esdi_t *esdi = (esdi_t *)priv;
uint8_t temp = 0xff;
switch (port) {
case 0x1F0: /* Data */
temp = esdi_readw(port, esdi) & 0xff;
break;
case 0x1F1: /* Error */
temp = esdi->error;
break;
case 0x1F2: /* Sector count */
temp = (uint8_t)esdi->secount;
break;
case 0x1F3: /* Sector */
temp = (uint8_t)esdi->sector;
break;
case 0x1F4: /* Cylinder low */
temp = (uint8_t)(esdi->cylinder&0xFF);
break;
case 0x1F5: /* Cylinder high */
temp = (uint8_t)(esdi->cylinder>>8);
break;
case 0x1F6: /* Drive/Head */
temp = (uint8_t)(esdi->head | (esdi->drive_sel?0x10:0) | 0xa0);
break;
case 0x1F7: /* Status */
irq_lower(esdi);
temp = esdi->status;
break;
}
return(temp);
}
static void
esdi_callback(void *priv)
{
esdi_t *esdi = (esdi_t *)priv;
drive_t *drive = &esdi->drives[esdi->drive_sel];
off64_t addr;
esdi->callback = 0;
if (esdi->reset) {
esdi->status = STAT_READY | STAT_DSC;
esdi->error = 1;
esdi->secount = 1;
esdi->sector = 1;
esdi->head = 0;
esdi->cylinder = 0;
esdi->reset = 0;
return;
}
switch (esdi->command) {
case CMD_RESTORE:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
} else {
drive->current_cylinder = 0;
esdi->status = STAT_READY | STAT_DSC;
}
irq_raise(esdi);
break;
case CMD_SEEK:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
} else {
esdi->status = STAT_READY | STAT_DSC;
}
irq_raise(esdi);
break;
case CMD_READ:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
irq_raise(esdi);
break;
}
if (get_sector(esdi, &addr)) {
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
irq_raise(esdi);
break;
}
if (hdd_image_read_ex(drive->hdd_num, addr, 1,
(uint8_t *)esdi->buffer)) {
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
irq_raise(esdi);
break;
}
esdi->pos = 0;
esdi->status = STAT_DRQ | STAT_READY | STAT_DSC;
irq_raise(esdi);
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1);
break;
case CMD_WRITE:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
irq_raise(esdi);
break;
}
if (get_sector(esdi, &addr)) {
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
irq_raise(esdi);
break;
}
if (hdd_image_write_ex(drive->hdd_num, addr, 1,
(uint8_t *)esdi->buffer)) {
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
irq_raise(esdi);
break;
}
irq_raise(esdi);
esdi->secount = (esdi->secount - 1) & 0xff;
if (esdi->secount) {
esdi->status = STAT_DRQ | STAT_READY | STAT_DSC;
esdi->pos = 0;
next_sector(esdi);
} else {
esdi->status = STAT_READY | STAT_DSC;
}
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1);
break;
case CMD_VERIFY:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
irq_raise(esdi);
break;
}
if (get_sector(esdi, &addr)) {
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
irq_raise(esdi);
break;
}
if (hdd_image_read_ex(drive->hdd_num, addr, 1,
(uint8_t *)esdi->buffer)) {
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
irq_raise(esdi);
break;
}
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1);
next_sector(esdi);
esdi->secount = (esdi->secount - 1) & 0xff;
if (esdi->secount)
esdi->callback = 6*HDC_TIME;
else {
esdi->pos = 0;
esdi->status = STAT_READY | STAT_DSC;
irq_raise(esdi);
}
break;
case CMD_FORMAT:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
irq_raise(esdi);
break;
}
if (get_sector(esdi, &addr)) {
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
irq_raise(esdi);
break;
}
if (hdd_image_zero_ex(drive->hdd_num, addr, esdi->secount)) {
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
irq_raise(esdi);
break;
}
esdi->status = STAT_READY | STAT_DSC;
irq_raise(esdi);
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1);
break;
case CMD_DIAGNOSE:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
} else {
esdi->error = 1; /*No error detected*/
esdi->status = STAT_READY | STAT_DSC;
}
irq_raise(esdi);
break;
case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
irq_raise(esdi);
break;
}
drive->cfg_spt = esdi->secount;
drive->cfg_hpc = esdi->head+1;
pclog("Parameters: spt=%i hpc=%i\n", drive->cfg_spt,drive->cfg_hpc);
if (! esdi->secount)
fatal("secount=0\n");
esdi->status = STAT_READY | STAT_DSC;
irq_raise(esdi);
break;
case CMD_NOP:
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
irq_raise(esdi);
break;
case 0xe0:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
irq_raise(esdi);
break;
}
switch (esdi->cylinder >> 8) {
case 0x31:
esdi->cylinder = drive->real_tracks;
break;
case 0x33:
esdi->cylinder = drive->real_hpc;
break;
case 0x35:
esdi->cylinder = 0x200;
break;
case 0x36:
esdi->cylinder = drive->real_spt;
break;
default:
pclog("EDSI Bad read config %02x\n",
esdi->cylinder >> 8);
}
esdi->status = STAT_READY | STAT_DSC;
irq_raise(esdi);
break;
case 0xa0:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
} else {
memset(esdi->buffer, 0, 512);
memset(&esdi->buffer[3], 0xff, 512-6);
esdi->pos = 0;
esdi->status = STAT_DRQ | STAT_READY | STAT_DSC;
}
irq_raise(esdi);
break;
case CMD_READ_PARAMETERS:
if (! drive->present) {
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
irq_raise(esdi);
break;
}
memset(esdi->buffer, 0, 512);
esdi->buffer[0] = 0x44; /* general configuration */
esdi->buffer[1] = drive->real_tracks; /* number of non-removable cylinders */
esdi->buffer[2] = 0; /* number of removable cylinders */
esdi->buffer[3] = drive->real_hpc; /* number of heads */
esdi->buffer[4] = 600; /* number of unformatted bytes/track */
esdi->buffer[5] = esdi->buffer[4] * drive->real_spt; /* number of unformatted bytes/sector */
esdi->buffer[6] = drive->real_spt; /* number of sectors */
esdi->buffer[7] = 0; /*minimum bytes in inter-sector gap*/
esdi->buffer[8] = 0; /* minimum bytes in postamble */
esdi->buffer[9] = 0; /* number of words of vendor status */
/* controller info */
esdi->buffer[20] = 2; /* controller type */
esdi->buffer[21] = 1; /* sector buffer size, in sectors */
esdi->buffer[22] = 0; /* ecc bytes appended */
esdi->buffer[27] = 'W' | ('D' << 8);
esdi->buffer[28] = '1' | ('0' << 8);
esdi->buffer[29] = '0' | ('7' << 8);
esdi->buffer[30] = 'V' | ('-' << 8);
esdi->buffer[31] = 'S' | ('E' << 8);
esdi->buffer[32] = '1';
esdi->buffer[47] = 0; /* sectors per interrupt */
esdi->buffer[48] = 0;/* can use double word read/write? */
esdi->pos = 0;
esdi->status = STAT_DRQ | STAT_READY | STAT_DSC;
irq_raise(esdi);
break;
default:
pclog("ESDI Callback on unknown command %02x\n", esdi->command);
case 0xe8:
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
irq_raise(esdi);
break;
}
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 0);
}
static void
esdi_rom_write(uint32_t addr, uint8_t val, void *priv)
{
rom_t *rom = (rom_t *)priv;
addr &= rom->mask;
if (addr >= 0x1f00 && addr < 0x2000)
rom->rom[addr] = val;
}
static void
loadhd(esdi_t *esdi, int hdd_num, int d, const wchar_t *fn)
{
drive_t *drive = &esdi->drives[d];
if (! hdd_image_load(hdd_num)) {
drive->present = 0;
return;
}
drive->cfg_spt = drive->real_spt = hdd[hdd_num].spt;
drive->cfg_hpc = drive->real_hpc = hdd[hdd_num].hpc;
drive->real_tracks = hdd[hdd_num].tracks;
drive->hdd_num = hdd_num;
drive->present = 1;
}
static void *
wd1007vse1_init(void)
{
int i, c = 0;
esdi_t *esdi = malloc(sizeof(esdi_t));
memset(esdi, 0x00, sizeof(esdi_t));
esdi->drives[0].present = esdi->drives[1].present = 0;
for (i=0; i<HDD_NUM; i++) {
if ((hdd[i].bus==HDD_BUS_ESDI) && (hdd[i].esdi_channel<ESDI_NUM)) {
loadhd(esdi, i, hdd[i].esdi_channel, hdd[i].fn);
if (++c >= ESDI_NUM) break;
}
}
esdi->status = STAT_READY | STAT_DSC;
esdi->error = 1;
rom_init(&esdi->bios_rom,
BIOS_FILE, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
mem_mapping_set_handler(
&esdi->bios_rom.mapping,
rom_read, rom_readw, rom_readl,
esdi_rom_write, NULL, NULL);
io_sethandler(0x01f0, 1,
esdi_read, esdi_readw, NULL,
esdi_write, esdi_writew, NULL, esdi);
io_sethandler(0x01f1, 7,
esdi_read, NULL, NULL,
esdi_write, NULL, NULL, esdi);
io_sethandler(0x03f6, 1, NULL, NULL, NULL,
esdi_write, NULL, NULL, esdi);
timer_add(esdi_callback, &esdi->callback, &esdi->callback, esdi);
return(esdi);
}
static void
wd1007vse1_close(void *priv)
{
esdi_t *esdi = (esdi_t *)priv;
drive_t *drive;
int d;
esdi->drives[0].present = esdi->drives[1].present = 0;
for (d=0; d<2; d++) {
drive = &esdi->drives[d];
hdd_image_close(drive->hdd_num);
}
free(esdi);
}
static int
wd1007vse1_available(void)
{
return(rom_present(BIOS_FILE));
}
device_t esdi_at_wd1007vse1_device = {
"Western Digital WD1007V-SE1 (ESDI)",
DEVICE_AT,
wd1007vse1_init,
wd1007vse1_close,
wd1007vse1_available,
NULL, NULL, NULL, NULL
};

View File

@@ -52,7 +52,7 @@
* however, are auto-configured by the system software as
* shown above.
*
* Version: @(#)hdd_esdi_mca.c 1.0.3 2017/09/24
* Version: @(#)hdc_esdi_mca.c 1.0.4 2017/09/29
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -73,8 +73,8 @@
#include "../pic.h"
#include "../rom.h"
#include "../timer.h"
#include "hdd_image.h"
#include "hdd_esdi_mca.h"
#include "hdc.h"
#include "hdd.h"
/* These are hardwired. */
@@ -82,8 +82,11 @@
#define ESDI_IOADDR_SEC 0x3518
#define ESDI_IRQCHAN 14
#define BIOS_FILE_L L"roms/hdd/esdi/90x8969.bin"
#define BIOS_FILE_H L"roms/hdd/esdi/90x8970.bin"
#define ESDI_TIME (2000 * TIMER_USEC)
#define ESDI_TIME (200*TIMER_USEC)
#define CMD_ADAPTER 0
@@ -92,8 +95,8 @@ typedef struct esdi_drive {
int tracks;
int sectors;
int present;
int hdc_num;
} esdi_drive_t;
int hdd_num;
} drive_t;
typedef struct esdi {
uint16_t base;
@@ -137,7 +140,7 @@ typedef struct esdi {
int req_in_progress;
} cmds[3];
esdi_drive_t drives[2];
drive_t drives[2];
uint8_t pos_regs[8];
} esdi_t;
@@ -271,7 +274,7 @@ static void
esdi_callback(void *priv)
{
esdi_t *dev = (esdi_t *)priv;
esdi_drive_t *drive;
drive_t *drive;
int val;
dev->callback = 0;
@@ -321,7 +324,7 @@ esdi_callback(void *priv)
if (! dev->data_pos) {
if (dev->rba >= drive->sectors)
fatal("Read past end of drive\n");
hdd_image_read(drive->hdc_num, dev->rba, 1, (uint8_t *)dev->data);
hdd_image_read(drive->hdd_num, dev->rba, 1, (uint8_t *)dev->data);
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1);
}
@@ -400,7 +403,7 @@ esdi_callback(void *priv)
if (dev->rba >= drive->sectors)
fatal("Write past end of drive\n");
hdd_image_write(drive->hdc_num, dev->rba, 1, (uint8_t *)dev->data);
hdd_image_write(drive->hdd_num, dev->rba, 1, (uint8_t *)dev->data);
dev->rba++;
dev->sector_pos++;
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1);
@@ -969,7 +972,7 @@ esdi_mca_write(int port, uint8_t val, void *priv)
static void *
esdi_init(void)
{
esdi_drive_t *drive;
drive_t *drive;
esdi_t *dev;
int c, i;
@@ -984,17 +987,16 @@ esdi_init(void)
dev->irq = ESDI_IRQCHAN;
rom_init_interleaved(&dev->bios_rom,
L"roms/hdd/esdi/90x8970.bin",
L"roms/hdd/esdi/90x8969.bin",
0x00000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
BIOS_FILE_L, BIOS_FILE_H,
0x00000, 16384, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
mem_mapping_disable(&dev->bios_rom.mapping);
dev->drives[0].present = dev->drives[1].present = 0;
for (c=0,i=0; i<HDC_NUM; i++) {
if ((hdc[i].bus == HDD_BUS_ESDI) && (hdc[i].esdi_channel < ESDI_NUM)) {
for (c=0,i=0; i<HDD_NUM; i++) {
if ((hdd[i].bus == HDD_BUS_ESDI) && (hdd[i].esdi_channel < ESDI_NUM)) {
/* This is an ESDI drive. */
drive = &dev->drives[hdc[i].esdi_channel];
drive = &dev->drives[hdd[i].esdi_channel];
/* Try to load an image for the drive. */
if (! hdd_image_load(i)) {
@@ -1004,11 +1006,11 @@ esdi_init(void)
}
/* OK, so fill in geometry info. */
drive->spt = hdc[i].spt;
drive->hpc = hdc[i].hpc;
drive->tracks = hdc[i].tracks;
drive->sectors = hdc[i].spt*hdc[i].hpc*hdc[i].tracks;
drive->hdc_num = i;
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->hdd_num = i;
/* Mark drive as present. */
drive->present = 1;
@@ -1040,7 +1042,7 @@ static void
esdi_close(void *priv)
{
esdi_t *dev = (esdi_t *)priv;
esdi_drive_t *drive;
drive_t *drive;
int d;
dev->drives[0].present = dev->drives[1].present = 0;
@@ -1048,7 +1050,7 @@ esdi_close(void *priv)
for (d=0; d<2; d++) {
drive = &dev->drives[d];
hdd_image_close(drive->hdc_num);
hdd_image_close(drive->hdd_num);
}
free(dev);
@@ -1058,20 +1060,13 @@ esdi_close(void *priv)
static int
esdi_available(void)
{
return(rom_present(L"roms/hdd/esdi/90x8969.bin") &&
rom_present(L"roms/hdd/esdi/90x8970.bin"));
return(rom_present(BIOS_FILE_L) && rom_present(BIOS_FILE_H));
}
device_t hdd_esdi_device =
{
device_t esdi_ps2_device = {
"IBM ESDI Fixed Disk Adapter (MCA)",
DEVICE_MCA,
esdi_init,
esdi_close,
esdi_available,
NULL,
NULL,
NULL,
NULL
esdi_init, esdi_close, esdi_available,
NULL, NULL, NULL, NULL
};

View File

@@ -9,7 +9,7 @@
* Implementation of the IDE emulation for hard disks and ATAPI
* CD-ROM devices.
*
* Version: @(#)hdd_ide_at.c 1.0.7 2017/09/24
* Version: @(#)hdc_ide.c 1.0.8 2017/09/29
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -28,10 +28,12 @@
#include "../pic.h"
#include "../pci.h"
#include "../timer.h"
#include "../device.h"
#include "../cdrom/cdrom.h"
#include "../scsi/scsi.h"
#include "hdd_image.h"
#include "hdd_ide_at.h"
#include "hdd.h"
#include "hdc.h"
#include "hdc_ide.h"
/* Bits of 'atastat' */
@@ -84,23 +86,7 @@ enum
IDE_CDROM
};
uint64_t hdt[128][3] = { { 306, 4, 17 }, { 615, 2, 17 }, { 306, 4, 26 }, { 1024, 2, 17 }, { 697, 3, 17 }, { 306, 8, 17 }, { 614, 4, 17 }, { 615, 4, 17 }, /* 000-007 */
{ 670, 4, 17 }, { 697, 4, 17 }, { 987, 3, 17 }, { 820, 4, 17 }, { 670, 5, 17 }, { 697, 5, 17 }, { 733, 5, 17 }, { 615, 6, 17 }, /* 008-015 */
{ 462, 8, 17 }, { 306, 8, 26 }, { 615, 4, 26 }, { 1024, 4, 17 }, { 855, 5, 17 }, { 925, 5, 17 }, { 932, 5, 17 }, { 1024, 2, 40 }, /* 016-023 */
{ 809, 6, 17 }, { 976, 5, 17 }, { 977, 5, 17 }, { 698, 7, 17 }, { 699, 7, 17 }, { 981, 5, 17 }, { 615, 8, 17 }, { 989, 5, 17 }, /* 024-031 */
{ 820, 4, 26 }, { 1024, 5, 17 }, { 733, 7, 17 }, { 754, 7, 17 }, { 733, 5, 26 }, { 940, 6, 17 }, { 615, 6, 26 }, { 462, 8, 26 }, /* 032-039 */
{ 830, 7, 17 }, { 855, 7, 17 }, { 751, 8, 17 }, { 1024, 4, 26 }, { 918, 7, 17 }, { 925, 7, 17 }, { 855, 5, 26 }, { 977, 7, 17 }, /* 040-047 */
{ 987, 7, 17 }, { 1024, 7, 17 }, { 823, 4, 38 }, { 925, 8, 17 }, { 809, 6, 26 }, { 976, 5, 26 }, { 977, 5, 26 }, { 698, 7, 26 }, /* 048-055 */
{ 699, 7, 26 }, { 940, 8, 17 }, { 615, 8, 26 }, { 1024, 5, 26 }, { 733, 7, 26 }, { 1024, 8, 17 }, { 823, 10, 17 }, { 754, 11, 17 }, /* 056-063 */
{ 830, 10, 17 }, { 925, 9, 17 }, { 1224, 7, 17 }, { 940, 6, 26 }, { 855, 7, 26 }, { 751, 8, 26 }, { 1024, 9, 17 }, { 965, 10, 17 }, /* 064-071 */
{ 969, 5, 34 }, { 980, 10, 17 }, { 960, 5, 35 }, { 918, 11, 17 }, { 1024, 10, 17 }, { 977, 7, 26 }, { 1024, 7, 26 }, { 1024, 11, 17 }, /* 072-079 */
{ 940, 8, 26 }, { 776, 8, 33 }, { 755, 16, 17 }, { 1024, 12, 17 }, { 1024, 8, 26 }, { 823, 10, 26 }, { 830, 10, 26 }, { 925, 9, 26 }, /* 080-087 */
{ 960, 9, 26 }, { 1024, 13, 17 }, { 1224, 11, 17 }, { 900, 15, 17 }, { 969, 7, 34 }, { 917, 15, 17 }, { 918, 15, 17 }, { 1524, 4, 39 }, /* 088-095 */
{ 1024, 9, 26 }, { 1024, 14, 17 }, { 965, 10, 26 }, { 980, 10, 26 }, { 1020, 15, 17 }, { 1023, 15, 17 }, { 1024, 15, 17 }, { 1024, 16, 17 }, /* 096-103 */
{ 1224, 15, 17 }, { 755, 16, 26 }, { 903, 8, 46 }, { 984, 10, 34 }, { 900, 15, 26 }, { 917, 15, 26 }, { 1023, 15, 26 }, { 684, 16, 38 }, /* 104-111 */
{ 1930, 4, 62 }, { 967, 16, 31 }, { 1013, 10, 63 }, { 1218, 15, 36 }, { 654, 16, 63 }, { 659, 16, 63 }, { 702, 16, 63 }, { 1002, 13, 63 }, /* 112-119 */
{ 854, 16, 63 }, { 987, 16, 63 }, { 995, 16, 63 }, { 1024, 16, 63 }, { 1036, 16, 63 }, { 1120, 16, 59 }, { 1054, 16, 63 }, { 0, 0, 0 } }; /* 119-127 */
IDE ide_drives[IDE_NUM + XTIDE_NUM];
IDE *ext_ide;
@@ -341,29 +327,29 @@ static void ide_identify(IDE *ide)
uint32_t c, h, s;
char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 };
#if 0
uint64_t full_size = (hdc[ide->hdc_num].tracks * hdc[ide->hdc_num].hpc * hdc[ide->hdc_num].spt);
uint64_t full_size = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt);
#endif
device_identify[6] = (ide->hdc_num / 10) + 0x30;
device_identify[7] = (ide->hdc_num % 10) + 0x30;
device_identify[6] = (ide->hdd_num / 10) + 0x30;
device_identify[7] = (ide->hdd_num % 10) + 0x30;
ide_log("IDE Identify: %s\n", device_identify);
memset(ide->buffer, 0, 512);
c = hdc[ide->hdc_num].tracks; /* Cylinders */
h = hdc[ide->hdc_num].hpc; /* Heads */
s = hdc[ide->hdc_num].spt; /* Sectors */
c = hdd[ide->hdd_num].tracks; /* Cylinders */
h = hdd[ide->hdd_num].hpc; /* Heads */
s = hdd[ide->hdd_num].spt; /* Sectors */
if (hdc[ide->hdc_num].tracks <= 16383)
if (hdd[ide->hdd_num].tracks <= 16383)
{
ide->buffer[1] = hdc[ide->hdc_num].tracks; /* Cylinders */
ide->buffer[1] = hdd[ide->hdd_num].tracks; /* Cylinders */
}
else
{
ide->buffer[1] = 16383; /* Cylinders */
}
ide->buffer[3] = hdc[ide->hdc_num].hpc; /* Heads */
ide->buffer[6] = hdc[ide->hdc_num].spt; /* Sectors */
ide->buffer[3] = hdd[ide->hdd_num].hpc; /* Heads */
ide->buffer[6] = hdd[ide->hdd_num].spt; /* Sectors */
ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */
ide_padstr((char *) (ide->buffer + 23), EMU_VERSION, 8); /* Firmware */
ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */
@@ -371,7 +357,7 @@ static void ide_identify(IDE *ide)
ide->buffer[21] = 512; /*Buffer size*/
ide->buffer[47] = 16; /*Max sectors on multiple transfer command*/
ide->buffer[48] = 1; /*Dword transfers supported*/
if (PCI && (ide->board < 2) && (hdc[ide->hdc_num].bus == HDD_BUS_IDE_PIO_AND_DMA))
if (PCI && (ide->board < 2) && (hdd[ide->hdd_num].bus == HDD_BUS_IDE_PIO_AND_DMA))
{
ide->buffer[49] = (1 << 8); /* LBA and DMA supported */
}
@@ -404,10 +390,10 @@ static void ide_identify(IDE *ide)
ide->buffer[59] = ide->blocksize ? (ide->blocksize | 0x100) : 0;
if (ide->buffer[49] & (1 << 9))
{
ide->buffer[60] = (hdc[ide->hdc_num].tracks * hdc[ide->hdc_num].hpc * hdc[ide->hdc_num].spt) & 0xFFFF; /* Total addressable sectors (LBA) */
ide->buffer[61] = ((hdc[ide->hdc_num].tracks * hdc[ide->hdc_num].hpc * hdc[ide->hdc_num].spt) >> 16) & 0x0FFF;
ide->buffer[60] = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt) & 0xFFFF; /* Total addressable sectors (LBA) */
ide->buffer[61] = ((hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt) >> 16) & 0x0FFF;
}
if (PCI && (ide->board < 2) && (hdc[ide->hdc_num].bus == HDD_BUS_IDE_PIO_AND_DMA))
if (PCI && (ide->board < 2) && (hdd[ide->hdd_num].bus == HDD_BUS_IDE_PIO_AND_DMA))
{
ide->buffer[52] = 2 << 8; /*DMA timing mode*/
@@ -497,21 +483,16 @@ static void ide_next_sector(IDE *ide)
static void loadhd(IDE *ide, int d, const wchar_t *fn)
{
int ret = 0;
ret = hdd_image_load(d);
if (!ret)
{
if (! hdd_image_load(d)) {
ide->type = IDE_NONE;
return;
}
ide->spt = hdc[d].spt;
ide->hpc = hdc[d].hpc;
ide->tracks = hdc[d].tracks;
ide->spt = hdd[d].spt;
ide->hpc = hdd[d].hpc;
ide->tracks = hdd[d].tracks;
ide->type = IDE_HDD;
ide->hdc_num = d;
ide->hdd_num = d;
ide->hdi = hdd_image_get_type(d);
}
@@ -588,7 +569,7 @@ static int ide_set_features(IDE *ide)
break;
case 0x04: /* Multiword DMA mode */
if (!PCI || (hdc[ide->hdc_num].bus != HDD_BUS_IDE_PIO_AND_DMA) || (ide->board >= 2) || (submode > 2))
if (!PCI || (hdd[ide->hdd_num].bus != HDD_BUS_IDE_PIO_AND_DMA) || (ide->board >= 2) || (submode > 2))
{
return 0;
}
@@ -617,11 +598,11 @@ void ide_set_sector(IDE *ide, int64_t sector_num)
}
else
{
cyl = sector_num / (hdc[ide->hdc_num].hpc * hdc[ide->hdc_num].spt);
r = sector_num % (hdc[ide->hdc_num].hpc * hdc[ide->hdc_num].spt);
cyl = sector_num / (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt);
r = sector_num % (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt);
ide->cylinder = cyl;
ide->head = ((r / hdc[ide->hdc_num].spt) & 0x0f);
ide->sector = (r % hdc[ide->hdc_num].spt) + 1;
ide->head = ((r / hdd[ide->hdd_num].spt) & 0x0f);
ide->sector = (r % hdd[ide->hdd_num].spt) + 1;
}
}
@@ -635,11 +616,11 @@ void resetide(void)
build_atapi_cdrom_map();
/* Close hard disk image files (if previously open) */
for (d = 0; d < (IDE_NUM + XTIDE_NUM); d++)
for (d = 0; d < (IDE_NUM+XTIDE_NUM); d++)
{
ide_drives[d].channel = d;
ide_drives[d].type = IDE_NONE;
hdd_image_close(ide_drives[d].hdc_num);
hdd_image_close(ide_drives[d].hdd_num);
if (ide_drive_is_cdrom(&ide_drives[d]))
{
cdrom[atapi_cdrom_drives[d]].status = READY_STAT | DSC_STAT;
@@ -654,21 +635,19 @@ void resetide(void)
idecallback[4]=0;
c = 0;
for (d = 0; d < HDC_NUM; d++)
for (d = 0; d < HDD_NUM; d++)
{
if (((hdc[d].bus == HDD_BUS_IDE_PIO_ONLY) || (hdc[d].bus == HDD_BUS_IDE_PIO_AND_DMA)) && (hdc[d].ide_channel < IDE_NUM))
if (((hdd[d].bus == HDD_BUS_IDE_PIO_ONLY) || (hdd[d].bus == HDD_BUS_IDE_PIO_AND_DMA)) && (hdd[d].ide_channel < IDE_NUM))
{
ide_log("Found IDE hard disk on channel %i\n", hdc[d].ide_channel);
loadhd(&ide_drives[hdc[d].ide_channel], d, hdc[d].fn);
c++;
if (c >= (IDE_NUM + XTIDE_NUM)) break;
ide_log("Found IDE hard disk on channel %i\n", hdd[d].ide_channel);
loadhd(&ide_drives[hdd[d].ide_channel], d, hdd[d].fn);
if (++c >= (IDE_NUM+XTIDE_NUM)) break;
}
if ((hdc[d].bus == HDD_BUS_XTIDE) && (hdc[d].xtide_channel < XTIDE_NUM))
if ((hdd[d].bus==HDD_BUS_XTIDE) && (hdd[d].xtide_channel < XTIDE_NUM))
{
ide_log("Found XT IDE hard disk on channel %i\n", hdc[d].xtide_channel);
loadhd(&ide_drives[hdc[d].xtide_channel | 8], d, hdc[d].fn);
c++;
if (c >= (IDE_NUM + XTIDE_NUM)) break;
ide_log("Found XT IDE hard disk on channel %i\n", hdd[d].xtide_channel);
loadhd(&ide_drives[hdd[d].xtide_channel | 8], d, hdd[d].fn);
if (++c >= (IDE_NUM+XTIDE_NUM)) break;
}
}
@@ -1317,7 +1296,7 @@ uint32_t ide_read_data(int ide_board, int length)
}
else
{
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 0);
update_status_bar_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
}
}
}
@@ -1511,7 +1490,7 @@ void callbackide(int ide_board)
ide_other = &ide_drives[cur_ide[ide_board] ^ 1];
if (ide->type == IDE_HDD)
{
full_size = (hdc[ide->hdc_num].tracks * hdc[ide->hdc_num].hpc * hdc[ide->hdc_num].spt);
full_size = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt);
}
ext_ide = ide;
@@ -1648,11 +1627,11 @@ void callbackide(int ide_board)
ide->sector_pos = 0;
if (ide->secount)
{
hdd_image_read(ide->hdc_num, ide_get_sector(ide), ide->secount, ide->sector_buffer);
hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer);
}
else
{
hdd_image_read(ide->hdc_num, ide_get_sector(ide), 256, ide->sector_buffer);
hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer);
}
}
@@ -1665,7 +1644,7 @@ void callbackide(int ide_board)
ide_irq_raise(ide);
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1);
update_status_bar_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
return;
case WIN_READ_DMA:
@@ -1684,11 +1663,11 @@ void callbackide(int ide_board)
ide->sector_pos = 0;
if (ide->secount)
{
hdd_image_read(ide->hdc_num, ide_get_sector(ide), ide->secount, ide->sector_buffer);
hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer);
}
else
{
hdd_image_read(ide->hdc_num, ide_get_sector(ide), 256, ide->sector_buffer);
hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer);
}
}
@@ -1712,12 +1691,12 @@ void callbackide(int ide_board)
ide_next_sector(ide);
ide->atastat = BUSY_STAT;
idecallback[ide_board]=6*IDE_TIME;
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1);
update_status_bar_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
}
else
{
ide_irq_raise(ide);
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 0);
update_status_bar_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
}
}
}
@@ -1746,11 +1725,11 @@ void callbackide(int ide_board)
ide->sector_pos = 0;
if (ide->secount)
{
hdd_image_read(ide->hdc_num, ide_get_sector(ide), ide->secount, ide->sector_buffer);
hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer);
}
else
{
hdd_image_read(ide->hdc_num, ide_get_sector(ide), 256, ide->sector_buffer);
hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer);
}
}
@@ -1770,7 +1749,7 @@ void callbackide(int ide_board)
ide->blockcount = 0;
}
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1);
update_status_bar_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
return;
case WIN_WRITE:
@@ -1783,7 +1762,7 @@ void callbackide(int ide_board)
{
goto id_not_found;
}
hdd_image_write(ide->hdc_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
ide_irq_raise(ide);
ide->secount = (ide->secount - 1) & 0xff;
if (ide->secount)
@@ -1791,12 +1770,12 @@ void callbackide(int ide_board)
ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
ide->pos=0;
ide_next_sector(ide);
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1);
update_status_bar_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
}
else
{
ide->atastat = READY_STAT | DSC_STAT;
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 0);
update_status_bar_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
}
return;
@@ -1820,7 +1799,7 @@ void callbackide(int ide_board)
else
{
/*DMA successful*/
hdd_image_write(ide->hdc_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
@@ -1830,12 +1809,12 @@ void callbackide(int ide_board)
ide_next_sector(ide);
ide->atastat = BUSY_STAT;
idecallback[ide_board]=6*IDE_TIME;
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1);
update_status_bar_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
}
else
{
ide_irq_raise(ide);
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 0);
update_status_bar_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
}
}
}
@@ -1851,7 +1830,7 @@ void callbackide(int ide_board)
{
goto id_not_found;
}
hdd_image_write(ide->hdc_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
ide->blockcount++;
if (ide->blockcount >= ide->blocksize || ide->secount == 1)
{
@@ -1864,12 +1843,12 @@ void callbackide(int ide_board)
ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
ide->pos=0;
ide_next_sector(ide);
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1);
update_status_bar_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
}
else
{
ide->atastat = READY_STAT | DSC_STAT;
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 0);
update_status_bar_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
}
return;
@@ -1886,7 +1865,7 @@ void callbackide(int ide_board)
ide->pos=0;
ide->atastat = READY_STAT | DSC_STAT;
ide_irq_raise(ide);
update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1);
update_status_bar_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
return;
case WIN_FORMAT:
@@ -1898,12 +1877,12 @@ void callbackide(int ide_board)
{
goto id_not_found;
}
hdd_image_zero(ide->hdc_num, ide_get_sector(ide), ide->secount);
hdd_image_zero(ide->hdd_num, ide_get_sector(ide), ide->secount);
ide->atastat = READY_STAT | DSC_STAT;
ide_irq_raise(ide);
/* update_status_bar_icon(SB_HDD | hdc[ide->hdc_num].bus, 1); */
/* update_status_bar_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); */
return;
case WIN_DRIVE_DIAGNOSTICS:
@@ -1950,7 +1929,7 @@ void callbackide(int ide_board)
full_size /= (ide->head+1);
full_size /= ide->secount;
ide->specify_success = 1;
hdd_image_specify(ide->hdc_num, ide->head + 1, ide->secount);
hdd_image_specify(ide->hdd_num, ide->head + 1, ide->secount);
ide->spt=ide->secount;
ide->hpc=ide->head+1;
ide->atastat = READY_STAT | DSC_STAT;
@@ -2002,9 +1981,9 @@ void callbackide(int ide_board)
{
goto abort_cmd;
}
snum = hdc[ide->hdc_num].spt;
snum *= hdc[ide->hdc_num].hpc;
snum *= hdc[ide->hdc_num].tracks;
snum = hdd[ide->hdd_num].spt;
snum *= hdd[ide->hdd_num].hpc;
snum *= hdd[ide->hdd_num].tracks;
ide_set_sector(ide, snum - 1);
ide->atastat = READY_STAT | DSC_STAT;
ide_irq_raise(ide);
@@ -2204,7 +2183,8 @@ uint32_t ide_read_qua_l(uint16_t addr, void *priv)
static uint16_t ide_base_main[2] = { 0x1f0, 0x170 };
static uint16_t ide_side_main[2] = { 0x3f6, 0x376 };
void ide_pri_enable()
void ide_pri_enable(void)
{
io_sethandler(0x01f0, 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL);
io_sethandler(0x03f6, 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL);
@@ -2212,7 +2192,7 @@ void ide_pri_enable()
ide_side_main[0] = 0x3f6;
}
void ide_pri_enable_ex()
void ide_pri_enable_ex(void)
{
if (ide_base_main[0] & 0x300)
{
@@ -2226,13 +2206,13 @@ void ide_pri_enable_ex()
}
}
void ide_pri_disable()
void ide_pri_disable(void)
{
io_removehandler(ide_base_main[0], 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL);
io_removehandler(ide_side_main[0], 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL);
}
void ide_sec_enable()
void ide_sec_enable(void)
{
io_sethandler(0x0170, 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL);
io_sethandler(0x0376, 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL);
@@ -2240,7 +2220,7 @@ void ide_sec_enable()
ide_side_main[1] = 0x376;
}
void ide_sec_enable_ex()
void ide_sec_enable_ex(void)
{
if (ide_base_main[1] & 0x300)
{
@@ -2252,12 +2232,13 @@ void ide_sec_enable_ex()
}
}
void ide_sec_disable()
void ide_sec_disable(void)
{
io_removehandler(ide_base_main[1], 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL);
io_removehandler(ide_side_main[1], 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL);
}
void ide_set_base(int controller, uint16_t port)
{
ide_base_main[controller] = port;
@@ -2268,19 +2249,19 @@ void ide_set_side(int controller, uint16_t port)
ide_side_main[controller] = port;
}
void ide_ter_enable()
void ide_ter_enable(void)
{
io_sethandler(0x0168, 0x0008, ide_read_ter, ide_read_ter_w, ide_read_ter_l, ide_write_ter, ide_write_ter_w, ide_write_ter_l, NULL);
io_sethandler(0x036e, 0x0001, ide_read_ter, NULL, NULL, ide_write_ter, NULL, NULL , NULL);
}
void ide_ter_disable()
void ide_ter_disable(void)
{
io_removehandler(0x0168, 0x0008, ide_read_ter, ide_read_ter_w, ide_read_ter_l, ide_write_ter, ide_write_ter_w, ide_write_ter_l, NULL);
io_removehandler(0x036e, 0x0001, ide_read_ter, NULL, NULL, ide_write_ter, NULL, NULL , NULL);
}
void ide_ter_disable_cond()
void ide_ter_disable_cond(void)
{
if ((ide_drives[4].type == IDE_NONE) && (ide_drives[5].type == IDE_NONE))
{
@@ -2288,20 +2269,20 @@ void ide_ter_disable_cond()
}
}
void ide_ter_init()
void ide_ter_init(void)
{
ide_ter_enable();
timer_add(ide_callback_ter, &idecallback[2], &idecallback[2], NULL);
}
void ide_qua_enable()
void ide_qua_enable(void)
{
io_sethandler(0x01e8, 0x0008, ide_read_qua, ide_read_qua_w, ide_read_qua_l, ide_write_qua, ide_write_qua_w, ide_write_qua_l, NULL);
io_sethandler(0x03ee, 0x0001, ide_read_qua, NULL, NULL, ide_write_qua, NULL, NULL , NULL);
}
void ide_qua_disable_cond()
void ide_qua_disable_cond(void)
{
if ((ide_drives[6].type == IDE_NONE) && (ide_drives[7].type == IDE_NONE))
{
@@ -2309,20 +2290,21 @@ void ide_qua_disable_cond()
}
}
void ide_qua_disable()
void ide_qua_disable(void)
{
io_removehandler(0x01e8, 0x0008, ide_read_qua, ide_read_qua_w, ide_read_qua_l, ide_write_qua, ide_write_qua_w, ide_write_qua_l, NULL);
io_removehandler(0x03ee, 0x0001, ide_read_qua, NULL, NULL, ide_write_qua, NULL, NULL , NULL);
}
void ide_qua_init()
void ide_qua_init(void)
{
ide_qua_enable();
timer_add(ide_callback_qua, &idecallback[3], &idecallback[3], NULL);
}
void ide_init()
void ide_init(void)
{
ide_pri_enable();
ide_sec_enable();
@@ -2332,7 +2314,8 @@ void ide_init()
timer_add(ide_callback_sec, &idecallback[1], &idecallback[1], NULL);
}
void ide_xtide_init()
void ide_xtide_init(void)
{
ide_bus_master_read = ide_bus_master_write = NULL;

View File

@@ -9,7 +9,7 @@
* Implementation of the IDE emulation for hard disks and ATAPI
* CD-ROM devices.
*
* Version: @(#)hdd_ide_at.h 1.0.2 2017/08/24
* Version: @(#)hdd_ide.h 1.0.3 2017/09/29
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -21,7 +21,6 @@
# define EMU_IDE_H
#pragma pack(push,1)
typedef struct {
int type;
int board;
@@ -47,14 +46,13 @@ typedef struct {
int blocksize, blockcount;
uint16_t dma_identify_data[3];
int hdi,base;
int hdc_num;
int hdd_num;
uint8_t specify_success;
int mdma_mode;
uint8_t sector_buffer[256*512];
int do_initial_read;
int sector_pos;
} IDE;
#pragma pack(pop)
extern int ideboard;

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: @(#)hdd_mfm_at.c 1.0.3 2017/09/24
* Version: @(#)hdd_mfm_at.c 1.0.4 2017/09/29
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -31,8 +31,8 @@
#include "../io.h"
#include "../pic.h"
#include "../timer.h"
#include "hdd_image.h"
#include "hdd_mfm_at.h"
#include "hdc.h"
#include "hdd.h"
#define MFM_TIME (TIMER_USEC*10)
@@ -66,7 +66,7 @@
typedef struct {
int8_t present, /* drive is present */
hdc_num, /* drive number in system */
hdd_num, /* drive number in system */
steprate, /* current servo step rate */
spt, /* physical #sectors per track */
hpc, /* physical #heads per cylinder */
@@ -77,7 +77,7 @@ typedef struct {
cfg_hpc; /* configured #heads per track */
int16_t curcyl; /* current track number */
} mfm_drive_t;
} drive_t;
typedef struct {
@@ -101,7 +101,7 @@ typedef struct {
uint16_t buffer[256]; /* data buffer (16b wide) */
mfm_drive_t drives[MFM_NUM]; /* attached drives */
drive_t drives[MFM_NUM]; /* attached drives */
} mfm_t;
@@ -152,7 +152,7 @@ static __inline void irq_lower(mfm_t *mfm)
static int
get_sector(mfm_t *mfm, off64_t *addr)
{
mfm_drive_t *drive = &mfm->drives[mfm->drvsel];
drive_t *drive = &mfm->drives[mfm->drvsel];
if (drive->curcyl != mfm->cylinder) {
pclog("WD1003(%d) sector: wrong cylinder\n");
@@ -195,7 +195,7 @@ get_sector(mfm_t *mfm, off64_t *addr)
static void
next_sector(mfm_t *mfm)
{
mfm_drive_t *drive = &mfm->drives[mfm->drvsel];
drive_t *drive = &mfm->drives[mfm->drvsel];
if (++mfm->sector == (drive->cfg_spt+1)) {
mfm->sector = 1;
@@ -212,7 +212,7 @@ next_sector(mfm_t *mfm)
static void
mfm_cmd(mfm_t *mfm, uint8_t val)
{
mfm_drive_t *drive = &mfm->drives[mfm->drvsel];
drive_t *drive = &mfm->drives[mfm->drvsel];
if (! drive->present) {
/* This happens if sofware polls all drives. */
@@ -526,7 +526,7 @@ mfm_read(uint16_t port, void *priv)
static void
do_seek(mfm_t *mfm)
{
mfm_drive_t *drive = &mfm->drives[mfm->drvsel];
drive_t *drive = &mfm->drives[mfm->drvsel];
#if MFM_DEBUG
pclog("WD1003(%d) seek(%d) max=%d\n",
@@ -543,7 +543,7 @@ static void
do_callback(void *priv)
{
mfm_t *mfm = (mfm_t *)priv;
mfm_drive_t *drive = &mfm->drives[mfm->drvsel];
drive_t *drive = &mfm->drives[mfm->drvsel];
off64_t addr;
mfm->callback = 0;
@@ -592,7 +592,7 @@ do_callback(void *priv)
break;
}
hdd_image_read(drive->hdc_num, addr, 1, (uint8_t *)mfm->buffer);
hdd_image_read(drive->hdd_num, addr, 1, (uint8_t *)mfm->buffer);
mfm->pos = 0;
mfm->status = STAT_DRQ|STAT_READY|STAT_DSC;
@@ -613,7 +613,7 @@ do_callback(void *priv)
break;
}
hdd_image_write(drive->hdc_num, addr, 1,(uint8_t *)mfm->buffer);
hdd_image_write(drive->hdd_num, addr, 1,(uint8_t *)mfm->buffer);
mfm->status = STAT_READY|STAT_DSC;
mfm->secount = (mfm->secount - 1) & 0xff;
@@ -654,7 +654,7 @@ do_callback(void *priv)
break;
}
hdd_image_zero(drive->hdc_num, addr, mfm->secount);
hdd_image_zero(drive->hdd_num, addr, mfm->secount);
mfm->status = STAT_READY|STAT_DSC;
irq_raise(mfm);
@@ -685,7 +685,7 @@ do_callback(void *priv)
static void
loadhd(mfm_t *mfm, int c, int d, const wchar_t *fn)
{
mfm_drive_t *drive = &mfm->drives[c];
drive_t *drive = &mfm->drives[c];
if (! hdd_image_load(d)) {
drive->present = 0;
@@ -693,10 +693,10 @@ loadhd(mfm_t *mfm, int c, int d, const wchar_t *fn)
return;
}
drive->spt = hdc[d].spt;
drive->hpc = hdc[d].hpc;
drive->tracks = hdc[d].tracks;
drive->hdc_num = d;
drive->spt = hdd[d].spt;
drive->hpc = hdd[d].hpc;
drive->tracks = hdd[d].tracks;
drive->hdd_num = d;
drive->present = 1;
}
@@ -712,12 +712,12 @@ mfm_init(void)
memset(mfm, 0x00, sizeof(mfm_t));
c = 0;
for (d=0; d<HDC_NUM; d++) {
if ((hdc[d].bus == HDD_BUS_MFM) && (hdc[d].mfm_channel < MFM_NUM)) {
loadhd(mfm, hdc[d].mfm_channel, d, hdc[d].fn);
for (d=0; d<HDD_NUM; d++) {
if ((hdd[d].bus == HDD_BUS_MFM) && (hdd[d].mfm_channel < MFM_NUM)) {
loadhd(mfm, hdd[d].mfm_channel, d, hdd[d].fn);
pclog("WD1003(%d): (%S) geometry %d/%d/%d\n", c, hdc[d].fn,
(int)hdc[d].tracks, (int)hdc[d].hpc, (int)hdc[d].spt);
pclog("WD1003(%d): (%S) geometry %d/%d/%d\n", c, hdd[d].fn,
(int)hdd[d].tracks, (int)hdd[d].hpc, (int)hdd[d].spt);
if (++c >= MFM_NUM) break;
}
@@ -748,9 +748,9 @@ mfm_close(void *priv)
int d;
for (d=0; d<2; d++) {
mfm_drive_t *drive = &mfm->drives[d];
drive_t *drive = &mfm->drives[d];
hdd_image_close(drive->hdc_num);
hdd_image_close(drive->hdd_num);
}
free(mfm);
@@ -759,15 +759,9 @@ mfm_close(void *priv)
}
device_t mfm_at_device =
{
device_t mfm_at_wd1003_device = {
"WD1003 AT MFM/RLL Controller",
DEVICE_AT,
mfm_init,
mfm_close,
NULL,
NULL,
NULL,
NULL,
NULL
mfm_init, mfm_close, NULL,
NULL, NULL, NULL, NULL
};

888
src/hdd/hdc_mfm_xt.c Normal file
View File

@@ -0,0 +1,888 @@
/*
* 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.
*
* Driver for the IBM PC-XT MFM/RLL Fixed Disk controller.
*
* The original controller shipped by IBM was made by Xebec, and
* several variations had been made.
*
*
* Since all controllers (including the ones made by DTC) we do
* keep them all in this module.
*
* Version: @(#)hdd_mfm_xt.c 1.0.5 2017/09/29
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
* Copyright 2017 Fred N. van Kempen.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../ibm.h"
#include "../device.h"
#include "../dma.h"
#include "../io.h"
#include "../mem.h"
#include "../pic.h"
#include "../rom.h"
#include "../timer.h"
#include "hdc.h"
#include "hdd.h"
#define MFM_TIME (2000*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"
enum {
STATE_IDLE,
STATE_RECEIVE_COMMAND,
STATE_START_COMMAND,
STATE_RECEIVE_DATA,
STATE_RECEIVED_DATA,
STATE_SEND_DATA,
STATE_SENT_DATA,
STATE_COMPLETION_BYTE,
STATE_DUNNO
};
typedef struct {
int spt, hpc;
int tracks;
int cfg_spt;
int cfg_hpc;
int cfg_cyl;
int current_cylinder;
int present;
int hdd_num;
} drive_t;
typedef struct {
rom_t bios_rom;
int callback;
int state;
uint8_t status;
uint8_t command[6];
int command_pos;
uint8_t data[512];
int data_pos, data_len;
uint8_t sector_buf[512];
uint8_t irq_dma_mask;
uint8_t completion_byte;
uint8_t error;
int drive_sel;
drive_t drives[2];
int sector, head, cylinder;
int sector_count;
uint8_t switches;
} mfm_t;
#define STAT_IRQ 0x20
#define STAT_DRQ 0x10
#define STAT_BSY 0x08
#define STAT_CD 0x04
#define STAT_IO 0x02
#define STAT_REQ 0x01
#define IRQ_ENA 0x02
#define DMA_ENA 0x01
#define CMD_TEST_DRIVE_READY 0x00
#define CMD_RECALIBRATE 0x01
#define CMD_READ_STATUS 0x03
#define CMD_VERIFY_SECTORS 0x05
#define CMD_FORMAT_TRACK 0x06
#define CMD_READ_SECTORS 0x08
#define CMD_WRITE_SECTORS 0x0a
#define CMD_SEEK 0x0b
#define CMD_INIT_DRIVE_PARAMS 0x0c
#define CMD_WRITE_SECTOR_BUFFER 0x0f
#define CMD_BUFFER_DIAGNOSTIC 0xe0
#define CMD_CONTROLLER_DIAGNOSTIC 0xe4
#define CMD_DTC_GET_DRIVE_PARAMS 0xfb
#define CMD_DTC_SET_STEP_RATE 0xfc
#define CMD_DTC_SET_GEOMETRY 0xfe
#define CMD_DTC_GET_GEOMETRY 0xff
#define ERR_NOT_READY 0x04
#define ERR_SEEK_ERROR 0x15
#define ERR_ILLEGAL_SECTOR_ADDRESS 0x21
static uint8_t
mfm_read(uint16_t port, void *priv)
{
mfm_t *mfm = (mfm_t *)priv;
uint8_t temp = 0xff;
switch (port) {
case 0x320: /*Read data*/
mfm->status &= ~STAT_IRQ;
switch (mfm->state) {
case STATE_COMPLETION_BYTE:
if ((mfm->status & 0xf) != (STAT_CD | STAT_IO | STAT_REQ | STAT_BSY))
fatal("Read data STATE_COMPLETION_BYTE, status=%02x\n", mfm->status);
temp = mfm->completion_byte;
mfm->status = 0;
mfm->state = STATE_IDLE;
break;
case STATE_SEND_DATA:
if ((mfm->status & 0xf) != (STAT_IO | STAT_REQ | STAT_BSY))
fatal("Read data STATE_COMPLETION_BYTE, status=%02x\n", mfm->status);
if (mfm->data_pos >= mfm->data_len)
fatal("Data write with full data!\n");
temp = mfm->data[mfm->data_pos++];
if (mfm->data_pos == mfm->data_len) {
mfm->status = STAT_BSY;
mfm->state = STATE_SENT_DATA;
mfm->callback = MFM_TIME;
}
break;
default:
fatal("Read data register - %i, %02x\n", mfm->state, mfm->status);
}
break;
case 0x321: /*Read status*/
temp = mfm->status;
break;
case 0x322: /*Read option jumpers*/
temp = mfm->switches;
break;
}
return(temp);
}
static void
mfm_write(uint16_t port, uint8_t val, void *priv)
{
mfm_t *mfm = (mfm_t *)priv;
switch (port) {
case 0x320: /*Write data*/
switch (mfm->state) {
case STATE_RECEIVE_COMMAND:
if ((mfm->status & 0xf) != (STAT_BSY | STAT_CD | STAT_REQ))
fatal("Bad write data state - STATE_START_COMMAND, status=%02x\n", mfm->status);
if (mfm->command_pos >= 6)
fatal("Command write with full command!\n");
/*Command data*/
mfm->command[mfm->command_pos++] = val;
if (mfm->command_pos == 6) {
mfm->status = STAT_BSY;
mfm->state = STATE_START_COMMAND;
mfm->callback = MFM_TIME;
}
break;
case STATE_RECEIVE_DATA:
if ((mfm->status & 0xf) != (STAT_BSY | STAT_REQ))
fatal("Bad write data state - STATE_RECEIVE_DATA, status=%02x\n", mfm->status);
if (mfm->data_pos >= mfm->data_len)
fatal("Data write with full data!\n");
/*Command data*/
mfm->data[mfm->data_pos++] = val;
if (mfm->data_pos == mfm->data_len) {
mfm->status = STAT_BSY;
mfm->state = STATE_RECEIVED_DATA;
mfm->callback = MFM_TIME;
}
break;
default:
fatal("Write data unknown state - %i %02x\n", mfm->state, mfm->status);
}
break;
case 0x321: /*Controller reset*/
mfm->status = 0;
break;
case 0x322: /*Generate controller-select-pulse*/
mfm->status = STAT_BSY | STAT_CD | STAT_REQ;
mfm->command_pos = 0;
mfm->state = STATE_RECEIVE_COMMAND;
break;
case 0x323: /*DMA/IRQ mask register*/
mfm->irq_dma_mask = val;
break;
}
}
static void mfm_complete(mfm_t *mfm)
{
mfm->status = STAT_REQ | STAT_CD | STAT_IO | STAT_BSY;
mfm->state = STATE_COMPLETION_BYTE;
if (mfm->irq_dma_mask & IRQ_ENA) {
mfm->status |= STAT_IRQ;
picint(1 << 5);
}
}
static void
mfm_error(mfm_t *mfm, uint8_t error)
{
mfm->completion_byte |= 0x02;
mfm->error = error;
pclog("mfm_error - %02x\n", mfm->error);
}
static int
get_sector(mfm_t *mfm, off64_t *addr)
{
drive_t *drive = &mfm->drives[mfm->drive_sel];
int heads = drive->cfg_hpc;
if (drive->current_cylinder != mfm->cylinder) {
pclog("mfm_get_sector: wrong cylinder\n");
mfm->error = ERR_ILLEGAL_SECTOR_ADDRESS;
return(1);
}
if (mfm->head > heads) {
pclog("mfm_get_sector: past end of configured heads\n");
mfm->error = ERR_ILLEGAL_SECTOR_ADDRESS;
return(1);
}
if (mfm->head > drive->hpc) {
pclog("mfm_get_sector: past end of heads\n");
mfm->error = ERR_ILLEGAL_SECTOR_ADDRESS;
return(1);
}
if (mfm->sector >= 17) {
pclog("mfm_get_sector: past end of sectors\n");
mfm->error = ERR_ILLEGAL_SECTOR_ADDRESS;
return(1);
}
*addr = ((((off64_t) mfm->cylinder * heads) + mfm->head) *
17) + mfm->sector;
return(0);
}
static void
next_sector(mfm_t *mfm)
{
drive_t *drive = &mfm->drives[mfm->drive_sel];
mfm->sector++;
if (mfm->sector >= 17) {
mfm->sector = 0;
mfm->head++;
if (mfm->head >= drive->cfg_hpc) {
mfm->head = 0;
mfm->cylinder++;
drive->current_cylinder++;
if (drive->current_cylinder >= drive->cfg_cyl)
drive->current_cylinder = drive->cfg_cyl-1;
}
}
}
static void
mfm_callback(void *priv)
{
mfm_t *mfm = (mfm_t *)priv;
drive_t *drive;
off64_t addr;
mfm->callback = 0;
mfm->drive_sel = (mfm->command[1] & 0x20) ? 1 : 0;
mfm->completion_byte = mfm->drive_sel & 0x20;
drive = &mfm->drives[mfm->drive_sel];
switch (mfm->command[0]) {
case CMD_TEST_DRIVE_READY:
if (!drive->present)
mfm_error(mfm, ERR_NOT_READY);
mfm_complete(mfm);
break;
case CMD_RECALIBRATE:
if (!drive->present)
mfm_error(mfm, ERR_NOT_READY);
else {
mfm->cylinder = 0;
drive->current_cylinder = 0;
}
mfm_complete(mfm);
break;
case CMD_READ_STATUS:
switch (mfm->state) {
case STATE_START_COMMAND:
mfm->state = STATE_SEND_DATA;
mfm->data_pos = 0;
mfm->data_len = 4;
mfm->status = STAT_BSY | STAT_IO | STAT_REQ;
mfm->data[0] = mfm->error;
mfm->data[1] = mfm->drive_sel ? 0x20 : 0;
mfm->data[2] = mfm->data[3] = 0;
mfm->error = 0;
break;
case STATE_SENT_DATA:
mfm_complete(mfm);
break;
}
break;
case CMD_VERIFY_SECTORS:
switch (mfm->state) {
case STATE_START_COMMAND:
mfm->cylinder = mfm->command[3] | ((mfm->command[2] & 0xc0) << 2);
drive->current_cylinder = (mfm->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : mfm->cylinder;
mfm->head = mfm->command[1] & 0x1f;
mfm->sector = mfm->command[2] & 0x1f;
mfm->sector_count = mfm->command[4];
do {
if (get_sector(mfm, &addr)) {
pclog("get_sector failed\n");
mfm_error(mfm, mfm->error);
mfm_complete(mfm);
return;
}
next_sector(mfm);
mfm->sector_count = (mfm->sector_count-1) & 0xff;
} while (mfm->sector_count);
mfm_complete(mfm);
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
break;
default:
fatal("CMD_VERIFY_SECTORS: bad state %i\n", mfm->state);
}
break;
case CMD_FORMAT_TRACK:
mfm->cylinder = mfm->command[3] | ((mfm->command[2] & 0xc0) << 2);
drive->current_cylinder = (mfm->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : mfm->cylinder;
mfm->head = mfm->command[1] & 0x1f;
if (get_sector(mfm, &addr)) {
pclog("get_sector failed\n");
mfm_error(mfm, mfm->error);
mfm_complete(mfm);
return;
}
hdd_image_zero(drive->hdd_num, addr, 17);
mfm_complete(mfm);
break;
case CMD_READ_SECTORS:
switch (mfm->state) {
case STATE_START_COMMAND:
mfm->cylinder = mfm->command[3] | ((mfm->command[2] & 0xc0) << 2);
drive->current_cylinder = (mfm->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : mfm->cylinder;
mfm->head = mfm->command[1] & 0x1f;
mfm->sector = mfm->command[2] & 0x1f;
mfm->sector_count = mfm->command[4];
mfm->state = STATE_SEND_DATA;
mfm->data_pos = 0;
mfm->data_len = 512;
if (get_sector(mfm, &addr)) {
mfm_error(mfm, mfm->error);
mfm_complete(mfm);
return;
}
hdd_image_read(drive->hdd_num, addr, 1,
(uint8_t *) mfm->sector_buf);
update_status_bar_icon(SB_HDD|HDD_BUS_MFM, 1);
if (mfm->irq_dma_mask & DMA_ENA)
mfm->callback = MFM_TIME;
else {
mfm->status = STAT_BSY | STAT_IO | STAT_REQ;
memcpy(mfm->data, mfm->sector_buf, 512);
}
break;
case STATE_SEND_DATA:
mfm->status = STAT_BSY;
if (mfm->irq_dma_mask & DMA_ENA) {
for (; mfm->data_pos < 512; mfm->data_pos++) {
int val = dma_channel_write(3, mfm->sector_buf[mfm->data_pos]);
if (val == DMA_NODATA) {
pclog("CMD_READ_SECTORS out of data!\n");
mfm->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ;
mfm->callback = MFM_TIME;
return;
}
}
mfm->state = STATE_SENT_DATA;
mfm->callback = MFM_TIME;
} else
fatal("Read sectors no DMA! - shouldn't get here\n");
break;
case STATE_SENT_DATA:
next_sector(mfm);
mfm->data_pos = 0;
mfm->sector_count = (mfm->sector_count-1) & 0xff;
if (mfm->sector_count) {
if (get_sector(mfm, &addr)) {
mfm_error(mfm, mfm->error);
mfm_complete(mfm);
return;
}
hdd_image_read(drive->hdd_num, addr, 1,
(uint8_t *) mfm->sector_buf);
update_status_bar_icon(SB_HDD|HDD_BUS_MFM, 1);
mfm->state = STATE_SEND_DATA;
if (mfm->irq_dma_mask & DMA_ENA)
mfm->callback = MFM_TIME;
else {
mfm->status = STAT_BSY | STAT_IO | STAT_REQ;
memcpy(mfm->data, mfm->sector_buf, 512);
}
} else {
mfm_complete(mfm);
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 0);
}
break;
default:
fatal("CMD_READ_SECTORS: bad state %i\n", mfm->state);
}
break;
case CMD_WRITE_SECTORS:
switch (mfm->state) {
case STATE_START_COMMAND:
mfm->cylinder = mfm->command[3] | ((mfm->command[2] & 0xc0) << 2);
drive->current_cylinder = (mfm->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : mfm->cylinder;
mfm->head = mfm->command[1] & 0x1f;
mfm->sector = mfm->command[2] & 0x1f;
mfm->sector_count = mfm->command[4];
mfm->state = STATE_RECEIVE_DATA;
mfm->data_pos = 0;
mfm->data_len = 512;
if (mfm->irq_dma_mask & DMA_ENA)
mfm->callback = MFM_TIME;
else
mfm->status = STAT_BSY | STAT_REQ;
break;
case STATE_RECEIVE_DATA:
mfm->status = STAT_BSY;
if (mfm->irq_dma_mask & DMA_ENA) {
for (; mfm->data_pos < 512; mfm->data_pos++) {
int val = dma_channel_read(3);
if (val == DMA_NODATA) {
pclog("CMD_WRITE_SECTORS out of data!\n");
mfm->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ;
mfm->callback = MFM_TIME;
return;
}
mfm->sector_buf[mfm->data_pos] = val & 0xff;
}
mfm->state = STATE_RECEIVED_DATA;
mfm->callback = MFM_TIME;
} else
fatal("Write sectors no DMA! - should never get here\n");
break;
case STATE_RECEIVED_DATA:
if (! (mfm->irq_dma_mask & DMA_ENA))
memcpy(mfm->sector_buf, mfm->data, 512);
if (get_sector(mfm, &addr))
{
mfm_error(mfm, mfm->error);
mfm_complete(mfm);
return;
}
hdd_image_write(drive->hdd_num, addr, 1,
(uint8_t *) mfm->sector_buf);
update_status_bar_icon(SB_HDD|HDD_BUS_MFM, 1);
next_sector(mfm);
mfm->data_pos = 0;
mfm->sector_count = (mfm->sector_count-1) & 0xff;
if (mfm->sector_count) {
mfm->state = STATE_RECEIVE_DATA;
if (mfm->irq_dma_mask & DMA_ENA)
mfm->callback = MFM_TIME;
else
mfm->status = STAT_BSY | STAT_REQ;
} else
mfm_complete(mfm);
break;
default:
fatal("CMD_WRITE_SECTORS: bad state %i\n", mfm->state);
}
break;
case CMD_SEEK:
if (! drive->present)
mfm_error(mfm, ERR_NOT_READY);
else {
int cylinder = mfm->command[3] | ((mfm->command[2] & 0xc0) << 2);
drive->current_cylinder = (cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : cylinder;
if (cylinder != drive->current_cylinder)
mfm_error(mfm, ERR_SEEK_ERROR);
}
mfm_complete(mfm);
break;
case CMD_INIT_DRIVE_PARAMS:
switch (mfm->state) {
case STATE_START_COMMAND:
mfm->state = STATE_RECEIVE_DATA;
mfm->data_pos = 0;
mfm->data_len = 8;
mfm->status = STAT_BSY | STAT_REQ;
break;
case STATE_RECEIVED_DATA:
drive->cfg_cyl = mfm->data[1] | (mfm->data[0] << 8);
drive->cfg_hpc = mfm->data[2];
pclog("Drive %i: cylinders=%i, heads=%i\n", mfm->drive_sel, drive->cfg_cyl, drive->cfg_hpc);
mfm_complete(mfm);
break;
default:
fatal("CMD_INIT_DRIVE_PARAMS bad state %i\n", mfm->state);
}
break;
case CMD_WRITE_SECTOR_BUFFER:
switch (mfm->state) {
case STATE_START_COMMAND:
mfm->state = STATE_RECEIVE_DATA;
mfm->data_pos = 0;
mfm->data_len = 512;
if (mfm->irq_dma_mask & DMA_ENA)
mfm->callback = MFM_TIME;
else
mfm->status = STAT_BSY | STAT_REQ;
break;
case STATE_RECEIVE_DATA:
if (mfm->irq_dma_mask & DMA_ENA) {
mfm->status = STAT_BSY;
for (; mfm->data_pos < 512; mfm->data_pos++) {
int val = dma_channel_read(3);
if (val == DMA_NODATA) {
pclog("CMD_WRITE_SECTOR_BUFFER out of data!\n");
mfm->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ;
mfm->callback = MFM_TIME;
return;
}
mfm->data[mfm->data_pos] = val & 0xff;
}
mfm->state = STATE_RECEIVED_DATA;
mfm->callback = MFM_TIME;
} else
fatal("CMD_WRITE_SECTOR_BUFFER - should never get here!\n");
break;
case STATE_RECEIVED_DATA:
memcpy(mfm->sector_buf, mfm->data, 512);
mfm_complete(mfm);
break;
default:
fatal("CMD_WRITE_SECTOR_BUFFER bad state %i\n", mfm->state);
}
break;
case CMD_BUFFER_DIAGNOSTIC:
case CMD_CONTROLLER_DIAGNOSTIC:
mfm_complete(mfm);
break;
case 0xfa:
mfm_complete(mfm);
break;
case CMD_DTC_SET_STEP_RATE:
mfm_complete(mfm);
break;
case CMD_DTC_GET_DRIVE_PARAMS:
switch (mfm->state) {
case STATE_START_COMMAND:
mfm->state = STATE_SEND_DATA;
mfm->data_pos = 0;
mfm->data_len = 4;
mfm->status = STAT_BSY | STAT_IO | STAT_REQ;
memset(mfm->data, 0, 4);
mfm->data[0] = drive->tracks & 0xff;
mfm->data[1] = 17 | ((drive->tracks >> 2) & 0xc0);
mfm->data[2] = drive->hpc-1;
pclog("Get drive params %02x %02x %02x %i\n", mfm->data[0], mfm->data[1], mfm->data[2], drive->tracks);
break;
case STATE_SENT_DATA:
mfm_complete(mfm);
break;
default:
fatal("CMD_INIT_DRIVE_PARAMS bad state %i\n", mfm->state);
}
break;
case CMD_DTC_GET_GEOMETRY:
switch (mfm->state) {
case STATE_START_COMMAND:
mfm->state = STATE_SEND_DATA;
mfm->data_pos = 0;
mfm->data_len = 16;
mfm->status = STAT_BSY | STAT_IO | STAT_REQ;
memset(mfm->data, 0, 16);
mfm->data[0x4] = drive->tracks & 0xff;
mfm->data[0x5] = (drive->tracks >> 8) & 0xff;
mfm->data[0xa] = drive->hpc;
break;
case STATE_SENT_DATA:
mfm_complete(mfm);
break;
}
break;
case CMD_DTC_SET_GEOMETRY:
switch (mfm->state) {
case STATE_START_COMMAND:
mfm->state = STATE_RECEIVE_DATA;
mfm->data_pos = 0;
mfm->data_len = 16;
mfm->status = STAT_BSY | STAT_REQ;
break;
case STATE_RECEIVED_DATA:
/*Bit of a cheat here - we always report the actual geometry of the drive in use*/
mfm_complete(mfm);
break;
}
break;
default:
fatal("Unknown Xebec command - %02x %02x %02x %02x %02x %02x\n",
mfm->command[0], mfm->command[1],
mfm->command[2], mfm->command[3],
mfm->command[4], mfm->command[5]);
}
}
static void
loadhd(mfm_t *mfm, int c, int d, const wchar_t *fn)
{
drive_t *drive = &mfm->drives[d];
if (! hdd_image_load(d)) {
drive->present = 0;
return;
}
drive->spt = hdd[c].spt;
drive->hpc = hdd[c].hpc;
drive->tracks = hdd[c].tracks;
drive->hdd_num = c;
drive->present = 1;
}
static struct {
int tracks, hpc;
} hd_types[4] = {
{ 306, 4 }, /* Type 0 */
{ 612, 4 }, /* Type 16 */
{ 615, 4 }, /* Type 2 */
{ 306, 8 } /* Type 13 */
};
static void
mfm_set_switches(mfm_t *mfm)
{
int c, d;
mfm->switches = 0;
for (d=0; d<2; d++) {
drive_t *drive = &mfm->drives[d];
if (! drive->present) continue;
for (c=0; c<4; c++) {
if (drive->spt == 17 &&
drive->hpc == hd_types[c].hpc &&
drive->tracks == hd_types[c].tracks) {
mfm->switches |= (c << (d ? 0 : 2));
break;
}
}
if (c == 4)
pclog("WARNING: Drive %c: has format not supported by Fixed Disk Adapter", d ? 'D' : 'C');
}
}
static void *
xebec_init(void)
{
int i, c = 0;
mfm_t *xebec = malloc(sizeof(mfm_t));
memset(xebec, 0x00, sizeof(mfm_t));
for (i=0; i<HDD_NUM; i++) {
if ((hdd[i].bus == HDD_BUS_MFM) && (hdd[i].mfm_channel < MFM_NUM)) {
loadhd(xebec, i, hdd[i].mfm_channel, hdd[i].fn);
if (++c > MFM_NUM) break;
}
}
mfm_set_switches(xebec);
rom_init(&xebec->bios_rom, XEBEC_BIOS_FILE,
0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
io_sethandler(0x0320, 4,
mfm_read, NULL, NULL, mfm_write, NULL, NULL, xebec);
timer_add(mfm_callback, &xebec->callback, &xebec->callback, xebec);
return(xebec);
}
static void
mfm_close(void *priv)
{
mfm_t *mfm = (mfm_t *)priv;
int d;
for (d=0; d<2; d++) {
drive_t *drive = &mfm->drives[d];
hdd_image_close(drive->hdd_num);
}
free(mfm);
}
static int
xebec_available(void)
{
return(rom_present(XEBEC_BIOS_FILE));
}
device_t mfm_xt_xebec_device = {
"IBM PC Fixed Disk Adapter",
0,
xebec_init, mfm_close, xebec_available,
NULL, NULL, NULL, NULL
};
static void *
dtc5150x_init(void)
{
int i, c = 0;
mfm_t *dtc = malloc(sizeof(mfm_t));
memset(dtc, 0x00, sizeof(mfm_t));
for (i=0; i<HDD_NUM; i++) {
if ((hdd[i].bus == HDD_BUS_MFM) && (hdd[i].mfm_channel < MFM_NUM)) {
loadhd(dtc, i, hdd[i].mfm_channel, hdd[i].fn);
if (++c > MFM_NUM) break;
}
}
dtc->switches = 0xff;
dtc->drives[0].cfg_cyl = dtc->drives[0].tracks;
dtc->drives[0].cfg_hpc = dtc->drives[0].hpc;
dtc->drives[1].cfg_cyl = dtc->drives[1].tracks;
dtc->drives[1].cfg_hpc = dtc->drives[1].hpc;
rom_init(&dtc->bios_rom, DTC_BIOS_FILE,
0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
io_sethandler(0x0320, 4,
mfm_read, NULL, NULL, mfm_write, NULL, NULL, dtc);
timer_add(mfm_callback, &dtc->callback, &dtc->callback, dtc);
return(dtc);
}
static int
dtc5150x_available(void)
{
return(rom_present(DTC_BIOS_FILE));
}
device_t mfm_xt_dtc5150x_device = {
"DTC 5150X",
0,
dtc5150x_init, mfm_close, dtc5150x_available,
NULL, NULL, NULL, NULL
};

257
src/hdd/hdc_xtide.c Normal file
View File

@@ -0,0 +1,257 @@
/*
* 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.
*
* XT-IDE controller emulation.
*
* The XT-IDE project is intended to allow 8-bit ("XT") systems
* to use regular IDE drives. IDE is a standard based on the
* 16b PC/AT design, and so a special board (with its own BIOS)
* had to be created for this.
*
* XT-IDE is *NOT* the same as XTA, or X-IDE, which is an older
* standard where the actual MFM/RLL controller for the PC/XT
* was placed on the hard drive (hard drives where its drive
* type would end in "X" or "XT", such as the 8425XT.) This was
* more or less the original IDE, but since those systems were
* 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: @(#)xtide.c 1.0.5 2017/09/29
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../ibm.h"
#include "../io.h"
#include "../mem.h"
#include "../rom.h"
#include "../device.h"
#include "hdd.h"
#include "hdc.h"
#include "hdc_ide.h"
#define XT_ROM_PATH L"roms/hdd/xtide/ide_xt.bin"
#define AT_ROM_PATH L"roms/hdd/xtide/ide_at.bin"
#define PS2_ROM_PATH L"roms/hdd/xtide/SIDE1V12.BIN"
#define PS2AT_ROM_PATH L"roms/hdd/xtide/ide_at_1_1_5.bin"
typedef struct {
uint8_t data_high;
rom_t bios_rom;
} xtide_t;
static void
xtide_write(uint16_t port, uint8_t val, void *priv)
{
xtide_t *xtide = (xtide_t *)priv;
switch (port & 0xf) {
case 0x0:
writeidew(4, val | (xtide->data_high << 8));
return;
case 0x1:
case 0x2:
case 0x3:
case 0x4:
case 0x5:
case 0x6:
case 0x7:
writeide(4, (port & 0xf) | 0x1f0, val);
return;
case 0x8:
xtide->data_high = val;
return;
case 0xe:
writeide(4, 0x3f6, val);
return;
}
}
static uint8_t
xtide_read(uint16_t port, void *priv)
{
xtide_t *xtide = (xtide_t *)priv;
uint16_t tempw;
switch (port & 0xf) {
case 0x0:
tempw = readidew(4);
xtide->data_high = tempw >> 8;
return(tempw & 0xff);
case 0x1:
case 0x2:
case 0x3:
case 0x4:
case 0x5:
case 0x6:
case 0x7:
return(readide(4, (port & 0xf) | 0x1f0));
case 0x8:
return(xtide->data_high);
case 0xe:
return(readide(4, 0x3f6));
default:
return(0xff);
}
}
static void *
xtide_init(void)
{
xtide_t *xtide = malloc(sizeof(xtide_t));
memset(xtide, 0x00, sizeof(xtide_t));
rom_init(&xtide->bios_rom, XT_ROM_PATH,
0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
ide_xtide_init();
io_sethandler(0x0300, 16,
xtide_read, NULL, NULL,
xtide_write, NULL, NULL, xtide);
return(xtide);
}
static int
xtide_available(void)
{
return(rom_present(XT_ROM_PATH));
}
static void *
xtide_at_init(void)
{
xtide_t *xtide = malloc(sizeof(xtide_t));
memset(xtide, 0x00, sizeof(xtide_t));
rom_init(&xtide->bios_rom, AT_ROM_PATH,
0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
ide_init();
return(xtide);
}
static int
xtide_at_available(void)
{
return(rom_present(AT_ROM_PATH));
}
static void *
xtide_ps2_init(void)
{
xtide_t *xtide = malloc(sizeof(xtide_t));
memset(xtide, 0x00, sizeof(xtide_t));
rom_init(&xtide->bios_rom, PS2_ROM_PATH,
0xc8000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
ide_xtide_init();
io_sethandler(0x0360, 16,
xtide_read, NULL, NULL,
xtide_write, NULL, NULL, xtide);
return(xtide);
}
static int
xtide_ps2_available(void)
{
return(rom_present(PS2_ROM_PATH));
}
static void *
xtide_at_ps2_init(void)
{
xtide_t *xtide = malloc(sizeof(xtide_t));
memset(xtide, 0x00, sizeof(xtide_t));
rom_init(&xtide->bios_rom, PS2AT_ROM_PATH,
0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
ide_init();
return(xtide);
}
static int
xtide_at_ps2_available(void)
{
return(rom_present(PS2AT_ROM_PATH));
}
static void
xtide_close(void *priv)
{
xtide_t *xtide = (xtide_t *)priv;
free(xtide);
}
device_t xtide_device = {
"XTIDE",
0,
xtide_init, xtide_close, xtide_available,
NULL, NULL, NULL, NULL
};
device_t xtide_at_device = {
"XTIDE (AT)",
DEVICE_AT,
xtide_at_init, xtide_close, xtide_at_available,
NULL, NULL, NULL, NULL
};
device_t xtide_ps2_device = {
"XTIDE (Acculogic)",
0,
xtide_ps2_init, xtide_close, xtide_ps2_available,
NULL, NULL, NULL, NULL
};
device_t xtide_at_ps2_device = {
"XTIDE (AT) (1.1.5)",
DEVICE_PS2,
xtide_at_ps2_init, xtide_close, xtide_at_ps2_available,
NULL, NULL, NULL, NULL
};

View File

@@ -1,3 +1,20 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Common code to handle all sorts of hard disk images.
*
* Version: @(#)hdd.c 1.0.1 2017/09/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.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
@@ -7,107 +24,6 @@
#include "../device.h"
#include "../machine/machine.h"
#include "hdd.h"
#include "hdd_esdi_at.h"
#include "hdd_esdi_mca.h"
#include "hdd_mfm_at.h"
#include "hdd_mfm_xebec.h"
#include "hdd_ide_xt.h"
char hdd_controller_name[16];
hard_disk_t hdc[HDC_NUM];
static device_t null_hdd_device;
static int hdd_controller_current;
static struct
{
char name[50];
char internal_name[16];
device_t *device;
int is_mfm;
} hdd_controllers[] =
{
{"None", "none", &null_hdd_device, 0},
{"[MFM] AT Fixed Disk Adapter", "mfm_at", &mfm_at_device, 1},
{"[MFM] DTC 5150X", "dtc5150x", &dtc_5150x_device, 1},
{"[MFM] Fixed Disk Adapter (Xebec)", "mfm_xebec", &mfm_xebec_device, 1},
{"[ESDI] IBM ESDI Fixed Disk Adapter", "esdi_mca", &hdd_esdi_device, 1},
{"[ESDI] Western Digital WD1007V-SE1", "wd1007vse1", &wd1007vse1_device, 0},
{"[IDE] XTIDE", "xtide", &xtide_device, 0},
{"[IDE] XTIDE (Acculogic)", "xtide_ps2", &xtide_ps2_device, 0},
{"[IDE] XTIDE (AT)", "xtide_at", &xtide_at_device, 0},
{"[IDE] XTIDE (AT) (1.1.5)", "xtide_at_ps2", &xtide_at_ps2_device, 0},
{"", "", NULL, 0}
};
char *hdd_controller_get_name(int hdd)
{
return hdd_controllers[hdd].name;
}
char *hdd_controller_get_internal_name(int hdd)
{
return hdd_controllers[hdd].internal_name;
}
int hdd_controller_get_flags(int hdd)
{
return hdd_controllers[hdd].device->flags;
}
int hdd_controller_available(int hdd)
{
return device_available(hdd_controllers[hdd].device);
}
int hdd_controller_current_is_mfm()
{
return hdd_controllers[hdd_controller_current].is_mfm;
}
void hdd_controller_init(char *internal_name)
{
int c = 0;
if (machines[machine].flags & MACHINE_HAS_IDE)
{
return;
}
while (hdd_controllers[c].device)
{
if (!strcmp(internal_name, hdd_controllers[c].internal_name))
{
hdd_controller_current = c;
if (strcmp(internal_name, "none"))
device_add(hdd_controllers[c].device);
return;
}
c++;
}
}
static void *null_hdd_init()
{
return NULL;
}
static void null_hdd_close(void *p)
{
}
static device_t null_hdd_device =
{
"Null HDD controller",
0,
null_hdd_init,
null_hdd_close,
NULL,
NULL,
NULL,
NULL,
NULL
};
hard_disk_t hdd[HDD_NUM];

View File

@@ -1,16 +1,97 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Definitions for the hard disk image handler.
*
* Version: @(#)hdd.h 1.0.1 2017/09/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.
*/
#ifndef EMU_HDD_H
# define EMU_HDD_H
extern char hdd_controller_name[16];
#define HDD_NUM 30 /* total of 30 images supported */
#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 IDE_NUM 8
#define SCSI_NUM 16 /* theoretically the controller can have at
* least 7 devices, with each device being
* able to support 8 units, but hey... */
/* Hard Disk bus types. */
enum {
HDD_BUS_DISABLED = 0,
HDD_BUS_MFM,
HDD_BUS_XTIDE,
HDD_BUS_ESDI,
HDD_BUS_IDE_PIO_ONLY,
HDD_BUS_IDE_PIO_AND_DMA,
HDD_BUS_SCSI,
HDD_BUS_SCSI_REMOVABLE,
HDD_BUS_USB
};
extern char *hdd_controller_get_name(int hdd);
extern char *hdd_controller_get_internal_name(int hdd);
extern int hdd_controller_get_flags(int hdd);
extern int hdd_controller_available(int hdd);
extern int hdd_controller_current_is_mfm(void);
extern void hdd_controller_init(char *internal_name);
/* Define the virtual Hard Disk. */
typedef struct {
int8_t is_hdi; /* image type (should rename) */
int8_t wp; /* disk has been mounted READ-ONLY */
uint8_t bus;
uint8_t mfm_channel; /* should rename and/or unionize */
uint8_t esdi_channel;
uint8_t xtide_channel;
uint8_t ide_channel;
uint8_t scsi_id;
uint8_t scsi_lun;
uint32_t base;
uint64_t spt,
hpc, /* physical geometry parameters */
tracks;
uint64_t at_spt, /* [Translation] parameters */
at_hpc;
FILE *f; /* current file handle to image */
wchar_t fn[260]; /* name of current image file */
wchar_t prev_fn[260]; /* name of previous image file */
} hard_disk_t;
extern hard_disk_t hdd[HDD_NUM];
extern uint64_t hdd_table[128][3];
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);
extern int hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
extern void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
extern int hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
extern void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count);
extern int hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count);
extern uint32_t hdd_image_get_last_sector(uint8_t id);
extern uint8_t hdd_image_get_type(uint8_t id);
extern void hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt);
extern void hdd_image_unload(uint8_t id, int fn_preserve);
extern void hdd_image_close(uint8_t id);
extern int image_is_hdi(const wchar_t *s);
extern int image_is_hdx(const wchar_t *s, int check_signature);
#endif /*EMU_HDD_H*/

View File

@@ -1,849 +0,0 @@
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../ibm.h"
#include "../device.h"
#include "../io.h"
#include "../mem.h"
#include "../pic.h"
#include "../rom.h"
#include "../timer.h"
#include "hdd_image.h"
#include "hdd_esdi_at.h"
#define IDE_TIME (TIMER_USEC*10)
#define STAT_ERR 0x01
#define STAT_INDEX 0x02
#define STAT_CORRECTED_DATA 0x04
#define STAT_DRQ 0x08 /* Data request */
#define STAT_DSC 0x10
#define STAT_SEEK_COMPLETE 0x20
#define STAT_READY 0x40
#define STAT_BUSY 0x80
#define ERR_DAM_NOT_FOUND 0x01 /*Data Address Mark not found*/
#define ERR_TR000 0x02 /*Track 0 not found*/
#define ERR_ABRT 0x04 /*Command aborted*/
#define ERR_ID_NOT_FOUND 0x10 /*ID not found*/
#define ERR_DATA_CRC 0x40 /*Data CRC error*/
#define ERR_BAD_BLOCK 0x80 /*Bad Block detected*/
#define CMD_NOP 0x00
#define CMD_RESTORE 0x10
#define CMD_READ 0x20
#define CMD_WRITE 0x30
#define CMD_VERIFY 0x40
#define CMD_FORMAT 0x50
#define CMD_SEEK 0x70
#define CMD_DIAGNOSE 0x90
#define CMD_SET_PARAMETERS 0x91
#define CMD_READ_PARAMETERS 0xec
extern char ide_fn[4][512];
typedef struct esdi_drive_t
{
int cfg_spt;
int cfg_hpc;
int current_cylinder;
int real_spt;
int real_hpc;
int real_tracks;
int present;
int hdc_num;
} esdi_drive_t;
typedef struct esdi_t
{
uint8_t status;
uint8_t error;
int secount,sector,cylinder,head,cylprecomp;
uint8_t command;
uint8_t fdisk;
int pos;
int drive_sel;
int reset;
uint16_t buffer[256];
int irqstat;
int callback;
esdi_drive_t drives[2];
rom_t bios_rom;
} esdi_t;
uint16_t esdi_readw(uint16_t port, void *p);
void esdi_writew(uint16_t port, uint16_t val, void *p);
static inline void esdi_irq_raise(esdi_t *esdi)
{
if (!(esdi->fdisk&2))
picint(1 << 14);
esdi->irqstat=1;
}
static inline void esdi_irq_lower(esdi_t *esdi)
{
picintc(1 << 14);
}
void esdi_irq_update(esdi_t *esdi)
{
if (esdi->irqstat && !((pic2.pend|pic2.ins)&0x40) && !(esdi->fdisk & 2))
picint(1 << 14);
}
/*
* Return the sector offset for the current register values
*/
int esdi_get_sector(esdi_t *esdi, off64_t *addr)
{
esdi_drive_t *drive = &esdi->drives[esdi->drive_sel];
int heads = drive->cfg_hpc;
int sectors = drive->cfg_spt;
if (esdi->head > heads)
{
pclog("esdi_get_sector: past end of configured heads\n");
return 1;
}
if (esdi->sector >= sectors+1)
{
pclog("esdi_get_sector: past end of configured sectors\n");
return 1;
}
if (drive->cfg_spt == drive->real_spt && drive->cfg_hpc == drive->real_hpc)
{
*addr = ((((off64_t) esdi->cylinder * heads) + esdi->head) *
sectors) + (esdi->sector - 1);
}
else
{
/*When performing translation, the firmware seems to leave 1
sector per track inaccessible (spare sector)*/
int c, h, s;
*addr = ((((off64_t) esdi->cylinder * heads) + esdi->head) *
sectors) + (esdi->sector - 1);
s = *addr % (drive->real_spt - 1);
h = (*addr / (drive->real_spt - 1)) % drive->real_hpc;
c = (*addr / (drive->real_spt - 1)) / drive->real_hpc;
*addr = ((((off64_t) c * drive->real_hpc) + h) *
drive->real_spt) + s;
}
return 0;
}
/**
* Move to the next sector using CHS addressing
*/
void esdi_next_sector(esdi_t *esdi)
{
esdi_drive_t *drive = &esdi->drives[esdi->drive_sel];
esdi->sector++;
if (esdi->sector == (drive->cfg_spt + 1))
{
esdi->sector = 1;
esdi->head++;
if (esdi->head == drive->cfg_hpc)
{
esdi->head = 0;
esdi->cylinder++;
if (drive->current_cylinder < drive->real_tracks)
drive->current_cylinder++;
}
}
}
void esdi_write(uint16_t port, uint8_t val, void *p)
{
esdi_t *esdi = (esdi_t *)p;
switch (port)
{
case 0x1F0: /* Data */
esdi_writew(port, val | (val << 8), p);
return;
case 0x1F1: /* Write precompenstation */
esdi->cylprecomp = val;
return;
case 0x1F2: /* Sector count */
esdi->secount = val;
return;
case 0x1F3: /* Sector */
esdi->sector = val;
return;
case 0x1F4: /* Cylinder low */
esdi->cylinder = (esdi->cylinder & 0xFF00) | val;
return;
case 0x1F5: /* Cylinder high */
esdi->cylinder = (esdi->cylinder & 0xFF) | (val << 8);
return;
case 0x1F6: /* Drive/Head */
esdi->head = val & 0xF;
esdi->drive_sel = (val & 0x10) ? 1 : 0;
if (esdi->drives[esdi->drive_sel].present)
esdi->status = 0;
else
esdi->status = STAT_READY | STAT_DSC;
return;
case 0x1F7: /* Command register */
esdi_irq_lower(esdi);
esdi->command = val;
esdi->error = 0;
switch (val & 0xf0)
{
case CMD_RESTORE:
esdi->command &= ~0x0f; /*Mask off step rate*/
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200*IDE_TIME;
timer_update_outstanding();
break;
case CMD_SEEK:
esdi->command &= ~0x0f; /*Mask off step rate*/
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200*IDE_TIME;
timer_update_outstanding();
break;
default:
switch (val)
{
case CMD_NOP:
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200*IDE_TIME;
timer_update_outstanding();
break;
case CMD_READ: case CMD_READ+1:
case CMD_READ+2: case CMD_READ+3:
esdi->command &= ~3;
if (val & 2)
fatal("Read with ECC\n");
case 0xa0:
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200*IDE_TIME;
timer_update_outstanding();
break;
case CMD_WRITE: case CMD_WRITE+1:
case CMD_WRITE+2: case CMD_WRITE+3:
esdi->command &= ~3;
if (val & 2)
fatal("Write with ECC\n");
esdi->status = STAT_DRQ | STAT_DSC;
esdi->pos=0;
break;
case CMD_VERIFY: case CMD_VERIFY+1:
esdi->command &= ~1;
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200 * IDE_TIME;
timer_update_outstanding();
break;
case CMD_FORMAT:
esdi->status = STAT_DRQ;
esdi->pos=0;
break;
case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 30*IDE_TIME;
timer_update_outstanding();
break;
case CMD_DIAGNOSE: /* Execute Drive Diagnostics */
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200*IDE_TIME;
timer_update_outstanding();
break;
case 0xe0: /*???*/
case CMD_READ_PARAMETERS:
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200*IDE_TIME;
timer_update_outstanding();
break;
default:
pclog("Bad esdi command %02X\n", val);
case 0xe8: /*???*/
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 200*IDE_TIME;
timer_update_outstanding();
break;
}
}
break;
case 0x3F6: /* Device control */
if ((esdi->fdisk & 4) && !(val & 4))
{
timer_process();
esdi->callback = 500*IDE_TIME;
timer_update_outstanding();
esdi->reset = 1;
esdi->status = STAT_BUSY;
}
if (val & 4)
{
/*Drive held in reset*/
timer_process();
esdi->callback = 0;
timer_update_outstanding();
esdi->status = STAT_BUSY;
}
esdi->fdisk = val;
esdi_irq_update(esdi);
return;
}
}
void esdi_writew(uint16_t port, uint16_t val, void *p)
{
esdi_t *esdi = (esdi_t *)p;
esdi->buffer[esdi->pos >> 1] = val;
esdi->pos += 2;
if (esdi->pos >= 512)
{
esdi->pos = 0;
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 6*IDE_TIME;
timer_update_outstanding();
}
}
uint8_t esdi_read(uint16_t port, void *p)
{
esdi_t *esdi = (esdi_t *)p;
uint8_t temp = 0xff;
switch (port)
{
case 0x1F0: /* Data */
temp = esdi_readw(port, esdi) & 0xff;
break;
case 0x1F1: /* Error */
temp = esdi->error;
break;
case 0x1F2: /* Sector count */
temp = (uint8_t)esdi->secount;
break;
case 0x1F3: /* Sector */
temp = (uint8_t)esdi->sector;
break;
case 0x1F4: /* Cylinder low */
temp = (uint8_t)(esdi->cylinder&0xFF);
break;
case 0x1F5: /* Cylinder high */
temp = (uint8_t)(esdi->cylinder>>8);
break;
case 0x1F6: /* Drive/Head */
temp = (uint8_t)(esdi->head | (esdi->drive_sel ? 0x10 : 0) | 0xa0);
break;
case 0x1F7: /* Status */
esdi_irq_lower(esdi);
temp = esdi->status;
break;
}
return temp;
}
uint16_t esdi_readw(uint16_t port, void *p)
{
esdi_t *esdi = (esdi_t *)p;
uint16_t temp;
temp = esdi->buffer[esdi->pos >> 1];
esdi->pos += 2;
if (esdi->pos >= 512)
{
esdi->pos=0;
esdi->status = STAT_READY | STAT_DSC;
if (esdi->command == CMD_READ || esdi->command == 0xa0)
{
esdi->secount = (esdi->secount - 1) & 0xff;
if (esdi->secount)
{
esdi_next_sector(esdi);
esdi->status = STAT_BUSY;
timer_process();
esdi->callback = 6*IDE_TIME;
timer_update_outstanding();
}
}
}
return temp;
}
void esdi_callback(void *p)
{
esdi_t *esdi = (esdi_t *)p;
esdi_drive_t *drive = &esdi->drives[esdi->drive_sel];
off64_t addr;
esdi->callback = 0;
if (esdi->reset)
{
esdi->status = STAT_READY | STAT_DSC;
esdi->error = 1;
esdi->secount = 1;
esdi->sector = 1;
esdi->head = 0;
esdi->cylinder = 0;
esdi->reset = 0;
return;
}
switch (esdi->command)
{
case CMD_RESTORE:
if (!drive->present)
{
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
esdi_irq_raise(esdi);
}
else
{
drive->current_cylinder = 0;
esdi->status = STAT_READY | STAT_DSC;
esdi_irq_raise(esdi);
}
break;
case CMD_SEEK:
if (!drive->present)
{
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
esdi_irq_raise(esdi);
}
else
{
esdi->status = STAT_READY | STAT_DSC;
esdi_irq_raise(esdi);
}
break;
case CMD_READ:
if (!drive->present)
{
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
esdi_irq_raise(esdi);
}
else
{
if (esdi_get_sector(esdi, &addr))
{
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
esdi_irq_raise(esdi);
break;
}
if (hdd_image_read_ex(drive->hdc_num, addr, 1, (uint8_t *) esdi->buffer))
{
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
esdi_irq_raise(esdi);
break;
}
esdi->pos = 0;
esdi->status = STAT_DRQ | STAT_READY | STAT_DSC;
esdi_irq_raise(esdi);
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1);
}
break;
case CMD_WRITE:
if (!drive->present)
{
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
esdi_irq_raise(esdi);
}
else
{
if (esdi_get_sector(esdi, &addr))
{
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
esdi_irq_raise(esdi);
break;
}
if (hdd_image_write_ex(drive->hdc_num, addr, 1, (uint8_t *) esdi->buffer))
{
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
esdi_irq_raise(esdi);
break;
}
esdi_irq_raise(esdi);
esdi->secount = (esdi->secount - 1) & 0xff;
if (esdi->secount)
{
esdi->status = STAT_DRQ | STAT_READY | STAT_DSC;
esdi->pos = 0;
esdi_next_sector(esdi);
}
else
esdi->status = STAT_READY | STAT_DSC;
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1);
}
break;
case CMD_VERIFY:
if (!drive->present)
{
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
esdi_irq_raise(esdi);
}
else
{
if (esdi_get_sector(esdi, &addr))
{
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
esdi_irq_raise(esdi);
break;
}
if (hdd_image_read_ex(drive->hdc_num, addr, 1, (uint8_t *) esdi->buffer))
{
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
esdi_irq_raise(esdi);
break;
}
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1);
esdi_next_sector(esdi);
esdi->secount = (esdi->secount - 1) & 0xff;
if (esdi->secount)
esdi->callback = 6*IDE_TIME;
else
{
esdi->pos = 0;
esdi->status = STAT_READY | STAT_DSC;
esdi_irq_raise(esdi);
}
}
break;
case CMD_FORMAT:
if (!drive->present)
{
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
esdi_irq_raise(esdi);
}
else
{
if (esdi_get_sector(esdi, &addr))
{
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
esdi_irq_raise(esdi);
break;
}
if (hdd_image_zero_ex(drive->hdc_num, addr, esdi->secount))
{
esdi->error = ERR_ID_NOT_FOUND;
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
esdi_irq_raise(esdi);
break;
}
esdi->status = STAT_READY | STAT_DSC;
esdi_irq_raise(esdi);
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 1);
}
break;
case CMD_DIAGNOSE:
if (!drive->present)
{
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
esdi_irq_raise(esdi);
}
else
{
esdi->error = 1; /*No error detected*/
esdi->status = STAT_READY | STAT_DSC;
esdi_irq_raise(esdi);
}
break;
case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */
if (!drive->present)
{
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
esdi_irq_raise(esdi);
}
else
{
drive->cfg_spt = esdi->secount;
drive->cfg_hpc = esdi->head+1;
pclog("Parameters: spt=%i hpc=%i\n", drive->cfg_spt,drive->cfg_hpc);
if (!esdi->secount)
fatal("secount=0\n");
esdi->status = STAT_READY | STAT_DSC;
esdi_irq_raise(esdi);
}
break;
case CMD_NOP:
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
esdi_irq_raise(esdi);
break;
case 0xe0:
if (!drive->present)
{
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
esdi_irq_raise(esdi);
}
else
{
switch (esdi->cylinder >> 8)
{
case 0x31:
esdi->cylinder = drive->real_tracks;
break;
case 0x33:
esdi->cylinder = drive->real_hpc;
break;
case 0x35:
esdi->cylinder = 0x200;
break;
case 0x36:
esdi->cylinder = drive->real_spt;
break;
default:
pclog("EDSI Bad read config %02x\n", esdi->cylinder >> 8);
}
esdi->status = STAT_READY | STAT_DSC;
esdi_irq_raise(esdi);
}
break;
case 0xa0:
if (!drive->present)
{
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
esdi_irq_raise(esdi);
}
else
{
memset(esdi->buffer, 0, 512);
memset(&esdi->buffer[3], 0xff, 512-6);
esdi->pos = 0;
esdi->status = STAT_DRQ | STAT_READY | STAT_DSC;
esdi_irq_raise(esdi);
}
break;
case CMD_READ_PARAMETERS:
if (!drive->present)
{
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
esdi_irq_raise(esdi);
}
else
{
memset(esdi->buffer, 0, 512);
esdi->buffer[0] = 0x44; /* general configuration */
esdi->buffer[1] = drive->real_tracks; /* number of non-removable cylinders */
esdi->buffer[2] = 0; /* number of removable cylinders */
esdi->buffer[3] = drive->real_hpc; /* number of heads */
esdi->buffer[5] = esdi->buffer[4] * drive->real_spt; /* number of unformatted bytes/sector */
esdi->buffer[4] = 600; /* number of unformatted bytes/track */
esdi->buffer[6] = drive->real_spt; /* number of sectors */
esdi->buffer[7] = 0; /*minimum bytes in inter-sector gap*/
esdi->buffer[8] = 0; /* minimum bytes in postamble */
esdi->buffer[9] = 0; /* number of words of vendor status */
/* controller info */
esdi->buffer[20] = 2; /* controller type */
esdi->buffer[21] = 1; /* sector buffer size, in sectors */
esdi->buffer[22] = 0; /* ecc bytes appended */
esdi->buffer[27] = 'W' | ('D' << 8);
esdi->buffer[28] = '1' | ('0' << 8);
esdi->buffer[29] = '0' | ('7' << 8);
esdi->buffer[30] = 'V' | ('-' << 8);
esdi->buffer[31] = 'S' | ('E' << 8);
esdi->buffer[32] = '1';
esdi->buffer[47] = 0; /* sectors per interrupt */
esdi->buffer[48] = 0;/* can use double word read/write? */
esdi->pos = 0;
esdi->status = STAT_DRQ | STAT_READY | STAT_DSC;
esdi_irq_raise(esdi);
}
break;
default:
pclog("ESDI Callback on unknown command %02x\n", esdi->command);
case 0xe8:
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
esdi->error = ERR_ABRT;
esdi_irq_raise(esdi);
break;
}
update_status_bar_icon(SB_HDD | HDD_BUS_ESDI, 0);
}
static void esdi_rom_write(uint32_t addr, uint8_t val, void *p)
{
rom_t *rom = (rom_t *)p;
addr &= rom->mask;
if (addr >= 0x1f00 && addr < 0x2000)
rom->rom[addr] = val;
}
static void loadhd(esdi_t *esdi, int hdc_num, int d, const wchar_t *fn)
{
esdi_drive_t *drive = &esdi->drives[d];
int ret = 0;
ret = hdd_image_load(hdc_num);
if (!ret)
{
drive->present = 0;
return;
}
drive->cfg_spt = drive->real_spt = hdc[hdc_num].spt;
drive->cfg_hpc = drive->real_hpc = hdc[hdc_num].hpc;
drive->real_tracks = hdc[hdc_num].tracks;
drive->hdc_num = hdc_num;
drive->present = 1;
}
void *wd1007vse1_init()
{
int i = 0;
int c = 0;
esdi_t *esdi = malloc(sizeof(esdi_t));
memset(esdi, 0, sizeof(esdi_t));
esdi->drives[0].present = esdi->drives[1].present = 0;
for (i = 0; i < HDC_NUM; i++)
{
if ((hdc[i].bus == HDD_BUS_ESDI) && (hdc[i].esdi_channel < ESDI_NUM))
{
loadhd(esdi, i, hdc[i].esdi_channel, hdc[i].fn);
c++;
if (c >= ESDI_NUM) break;
}
}
esdi->status = STAT_READY | STAT_DSC;
esdi->error = 1; /*No errors*/
rom_init(&esdi->bios_rom, L"roms/hdd/esdi_at/62-000279-061.bin", 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
mem_mapping_set_handler(&esdi->bios_rom.mapping,
rom_read, rom_readw, rom_readl,
esdi_rom_write, NULL, NULL);
io_sethandler(0x01f0, 0x0001, esdi_read, esdi_readw, NULL, esdi_write, esdi_writew, NULL, esdi);
io_sethandler(0x01f1, 0x0007, esdi_read, NULL, NULL, esdi_write, NULL, NULL, esdi);
io_sethandler(0x03f6, 0x0001, NULL, NULL, NULL, esdi_write, NULL, NULL, esdi);
timer_add(esdi_callback, &esdi->callback, &esdi->callback, esdi);
return esdi;
}
void wd1007vse1_close(void *p)
{
esdi_t *esdi = (esdi_t *)p;
esdi_drive_t *drive;
int d;
esdi->drives[0].present = esdi->drives[1].present = 0;
for (d = 0; d < 2; d++)
{
drive = &esdi->drives[d];
hdd_image_close(drive->hdc_num);
}
free(esdi);
}
static int wd1007vse1_available()
{
return rom_present(L"roms/hdd/esdi_at/62-000279-061.bin");
}
device_t wd1007vse1_device =
{
"Western Digital WD1007V-SE1 (ESDI)",
DEVICE_AT,
wd1007vse1_init,
wd1007vse1_close,
wd1007vse1_available,
NULL,
NULL,
NULL,
NULL
};

View File

@@ -1 +0,0 @@
extern device_t wd1007vse1_device;

View File

@@ -1 +0,0 @@
extern device_t hdd_esdi_device;

View File

@@ -1,228 +0,0 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* XT IDE controller emulation.
*
* Version: @(#)xtide.c 1.0.4 2017/09/24
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../ibm.h"
#include "../io.h"
#include "../mem.h"
#include "../rom.h"
#include "../device.h"
#include "hdd_ide_at.h"
#include "hdd_ide_xt.h"
#define XTIDE_ROM_PATH L"roms/hdd/xtide/ide_xt.bin"
#define ATIDE_ROM_PATH L"roms/hdd/xtide/ide_at.bin"
typedef struct xtide_t
{
uint8_t data_high;
rom_t bios_rom;
} xtide_t;
static void xtide_write(uint16_t port, uint8_t val, void *p)
{
xtide_t *xtide = (xtide_t *)p;
switch (port & 0xf)
{
case 0x0:
writeidew(4, val | (xtide->data_high << 8));
return;
case 0x1: case 0x2: case 0x3:
case 0x4: case 0x5: case 0x6: case 0x7:
writeide(4, (port & 0xf) | 0x1f0, val);
return;
case 0x8:
xtide->data_high = val;
return;
case 0xe:
writeide(4, 0x3f6, val);
return;
}
}
static uint8_t xtide_read(uint16_t port, void *p)
{
xtide_t *xtide = (xtide_t *)p;
uint16_t tempw;
switch (port & 0xf)
{
case 0x0:
tempw = readidew(4);
xtide->data_high = tempw >> 8;
return tempw & 0xff;
case 0x1: case 0x2: case 0x3:
case 0x4: case 0x5: case 0x6: case 0x7:
return readide(4, (port & 0xf) | 0x1f0);
case 0x8:
return xtide->data_high;
case 0xe:
return readide(4, 0x3f6);
default:
return 0xff;
}
}
static void *xtide_init(void)
{
xtide_t *xtide = malloc(sizeof(xtide_t));
memset(xtide, 0, sizeof(xtide_t));
rom_init(&xtide->bios_rom, XTIDE_ROM_PATH, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
ide_xtide_init();
io_sethandler(0x0300, 0x0010, xtide_read, NULL, NULL, xtide_write, NULL, NULL, xtide);
return xtide;
}
static void *xtide_at_init(void)
{
xtide_t *xtide = malloc(sizeof(xtide_t));
memset(xtide, 0, sizeof(xtide_t));
rom_init(&xtide->bios_rom, ATIDE_ROM_PATH, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
ide_init();
return xtide;
}
static void *xtide_ps2_init(void)
{
xtide_t *xtide = malloc(sizeof(xtide_t));
memset(xtide, 0, sizeof(xtide_t));
rom_init(&xtide->bios_rom, L"roms/hdd/xtide/SIDE1V12.BIN", 0xc8000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
ide_xtide_init();
io_sethandler(0x0360, 0x0010, xtide_read, NULL, NULL, xtide_write, NULL, NULL, xtide);
return xtide;
}
static void *xtide_at_ps2_init(void)
{
xtide_t *xtide = malloc(sizeof(xtide_t));
memset(xtide, 0, sizeof(xtide_t));
rom_init(&xtide->bios_rom, L"roms/hdd/xtide/ide_at_1_1_5.bin", 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
ide_init();
return xtide;
}
static void xtide_close(void *p)
{
xtide_t *xtide = (xtide_t *)p;
free(xtide);
}
static int xtide_available(void)
{
return rom_present(L"roms/hdd/xtide/ide_xt.bin");
}
static int xtide_at_available(void)
{
return rom_present(L"roms/hdd/xtide/ide_at.bin");
}
static int xtide_ps2_available(void)
{
return rom_present(L"roms/hdd/xtide/SIDE1V12.BIN");
}
static int xtide_at_ps2_available(void)
{
return rom_present(L"roms/hdd/xtide/ide_at_1_1_5.bin");
}
device_t xtide_device =
{
"XTIDE",
0,
xtide_init,
xtide_close,
xtide_available,
NULL,
NULL,
NULL,
NULL
};
device_t xtide_at_device =
{
"XTIDE (AT)",
DEVICE_AT,
xtide_at_init,
xtide_close,
xtide_at_available,
NULL,
NULL,
NULL,
NULL
};
device_t xtide_ps2_device =
{
"XTIDE (Acculogic)",
0,
xtide_ps2_init,
xtide_close,
xtide_ps2_available,
NULL,
NULL,
NULL,
NULL
};
device_t xtide_at_ps2_device =
{
"XTIDE (AT) (1.1.5)",
DEVICE_PS2,
xtide_at_ps2_init,
xtide_close,
xtide_at_ps2_available,
NULL,
NULL,
NULL,
NULL
};

View File

@@ -1,28 +0,0 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* XT IDE controller emulation.
*
* Version: @(#)xtide.h 1.0.2 2017/08/23
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
*/
#ifndef EMU_XTIDE_H
# define EMU_XTIDE_H
extern device_t xtide_device;
extern device_t xtide_at_device;
extern device_t xtide_ps2_device;
extern device_t xtide_at_ps2_device;
#endif /*EMU_XTIDE_H*/

View File

@@ -9,8 +9,8 @@
#include <wchar.h>
#include <errno.h>
#include "../ibm.h"
#include "hdd_image.h"
#include "hdd_ide_at.h"
#include "hdd.h"
//#include "hdc_ide.h"
typedef struct
@@ -22,11 +22,13 @@ typedef struct
uint8_t loaded;
} hdd_image_t;
hdd_image_t hdd_images[HDC_NUM];
hdd_image_t hdd_images[HDD_NUM];
static char empty_sector[512];
static char *empty_sector_1mb;
int hdd_image_do_log = 0;
void hdd_image_log(const char *format, ...)
@@ -43,6 +45,7 @@ void hdd_image_log(const char *format, ...)
#endif
}
int image_is_hdi(const wchar_t *s)
{
int len;
@@ -64,7 +67,9 @@ int image_is_hdi(const wchar_t *s)
}
}
int image_is_hdx(const wchar_t *s, int check_signature)
int
image_is_hdx(const wchar_t *s, int check_signature)
{
int len;
FILE *f;
@@ -116,6 +121,7 @@ int image_is_hdx(const wchar_t *s, int check_signature)
}
}
int hdd_image_load(int id)
{
uint32_t sector_size = 512;
@@ -125,7 +131,7 @@ int hdd_image_load(int id)
uint64_t spt = 0, hpc = 0, tracks = 0;
int c;
uint64_t i = 0, s = 0, t = 0;
wchar_t *fn = hdc[id].fn;
wchar_t *fn = hdd[id].fn;
int is_hdx[2] = { 0, 0 };
memset(empty_sector, 0, sizeof(empty_sector));
@@ -146,7 +152,7 @@ int hdd_image_load(int id)
if (fn[0] == '.')
{
hdd_image_log("File name starts with .\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
hdd_images[id].file = _wfopen(fn, L"rb+");
@@ -157,10 +163,10 @@ int hdd_image_load(int id)
{
/* Failed because it does not exist,
so try to create new file */
if (hdc[id].wp)
if (hdd[id].wp)
{
hdd_image_log("A write-protected image must exist\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
@@ -168,23 +174,23 @@ int hdd_image_load(int id)
if (hdd_images[id].file == NULL)
{
hdd_image_log("Unable to open image\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
else
{
if (image_is_hdi(fn))
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
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(&(hdc[id].spt), 1, 4, hdd_images[id].file);
fwrite(&(hdc[id].hpc), 1, 4, hdd_images[id].file);
fwrite(&(hdc[id].tracks), 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);
@@ -193,14 +199,14 @@ int hdd_image_load(int id)
}
else if (is_hdx[0])
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
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(&(hdc[id].spt), 1, 4, hdd_images[id].file);
fwrite(&(hdc[id].hpc), 1, 4, hdd_images[id].file);
fwrite(&(hdc[id].tracks), 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;
@@ -212,7 +218,7 @@ int hdd_image_load(int id)
hdd_images[id].last_sector = 0;
}
s = full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
s = full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512;
goto prepare_new_hard_disk;
}
@@ -220,7 +226,7 @@ int hdd_image_load(int id)
{
/* Failed for another reason */
hdd_image_log("Failed for another reason\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
}
@@ -241,26 +247,26 @@ int hdd_image_load(int id)
hdd_image_log("HDI: Sector size is not 512\n");
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
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 (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE)
if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE)
{
if ((spt != hdc[id].spt) || (hpc != hdc[id].hpc) || (tracks != hdc[id].tracks))
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(hdc[id].fn, 0, sizeof(hdc[id].fn));
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
}
hdc[id].spt = spt;
hdc[id].hpc = hpc;
hdc[id].tracks = tracks;
hdd[id].spt = spt;
hdd[id].hpc = hpc;
hdd[id].tracks = tracks;
hdd_images[id].type = 1;
}
else if (is_hdx[1])
@@ -276,33 +282,33 @@ int hdd_image_load(int id)
hdd_image_log("HDX: Sector size is not 512\n");
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
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 (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE)
if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE)
{
if ((spt != hdc[id].spt) || (hpc != hdc[id].hpc) || (tracks != hdc[id].tracks))
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(hdc[id].fn, 0, sizeof(hdc[id].fn));
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
return 0;
}
}
hdc[id].spt = spt;
hdc[id].hpc = hpc;
hdc[id].tracks = tracks;
fread(&(hdc[id].at_spt), 1, 4, hdd_images[id].file);
fread(&(hdc[id].at_hpc), 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 = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512;
hdd_images[id].type = 0;
}
}
@@ -341,8 +347,14 @@ prepare_new_hard_disk:
hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1;
#ifdef WALTJE
hdd_images[id].loaded = 1;
pclog("HDD: disk %d image '%S' file 0x%08lx\n", id, hdd[id].fn, hdd_images[id].file);
return 1;
#else
return 1;
hdd_images[id].loaded = 1;
#endif
}
void hdd_image_seek(uint8_t id, uint32_t sector)
@@ -358,6 +370,7 @@ void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer
{
count <<= 9;
pclog("HDD: read_image(id=%d sector=%lu cnt=%d, bufp=%08lx) fp=%08lx\n",id,sector,count,buffer,hdd_images[id].file);
hdd_image_seek(id, sector);
memset(buffer, 0, count);
fread(buffer, 1, count, hdd_images[id].file);
@@ -479,17 +492,17 @@ void hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt)
{
if (hdd_images[id].type == 2)
{
hdc[id].at_hpc = hpc;
hdc[id].at_spt = spt;
hdd[id].at_hpc = hpc;
hdd[id].at_spt = spt;
fseeko64(hdd_images[id].file, 0x20, SEEK_SET);
fwrite(&(hdc[id].at_spt), 1, 4, hdd_images[id].file);
fwrite(&(hdc[id].at_hpc), 1, 4, hdd_images[id].file);
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(hdc[id].fn) == 0)
if (wcslen(hdd[id].fn) == 0)
{
return;
}
@@ -505,13 +518,13 @@ void hdd_image_unload(uint8_t id, int fn_preserve)
hdd_images[id].last_sector = -1;
memset(hdc[id].prev_fn, 0, sizeof(hdc[id].prev_fn));
memset(hdd[id].prev_fn, 0, sizeof(hdd[id].prev_fn));
if (fn_preserve)
{
wcscpy(hdc[id].prev_fn, hdc[id].fn);
wcscpy(hdd[id].prev_fn, hdd[id].fn);
}
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
}
void hdd_image_close(uint8_t id)

View File

@@ -1,20 +0,0 @@
#ifndef EMU_HDD_IMAGE_H
# define EMU_HDD_IMAGE_H
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);
extern int hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
extern void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
extern int hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
extern void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count);
extern int hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count);
extern uint32_t hdd_image_get_last_sector(uint8_t id);
extern uint8_t hdd_image_get_type(uint8_t id);
extern void hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt);
extern void hdd_image_unload(uint8_t id, int fn_preserve);
extern void hdd_image_close(uint8_t id);
#endif /*EMU_HDD_IMAGE_H*/

View File

@@ -1 +0,0 @@
extern device_t mfm_at_device;

View File

@@ -1,919 +0,0 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../ibm.h"
#include "../device.h"
#include "../dma.h"
#include "../io.h"
#include "../mem.h"
#include "../pic.h"
#include "../rom.h"
#include "../timer.h"
#include "hdd_image.h"
#include "hdd_mfm_xebec.h"
#define XEBEC_TIME (2000 * TIMER_USEC)
enum
{
STATE_IDLE,
STATE_RECEIVE_COMMAND,
STATE_START_COMMAND,
STATE_RECEIVE_DATA,
STATE_RECEIVED_DATA,
STATE_SEND_DATA,
STATE_SENT_DATA,
STATE_COMPLETION_BYTE,
STATE_DUNNO
};
typedef struct mfm_drive_t
{
int spt, hpc;
int tracks;
int cfg_spt;
int cfg_hpc;
int cfg_cyl;
int current_cylinder;
int present;
int hdc_num;
} mfm_drive_t;
typedef struct xebec_t
{
rom_t bios_rom;
int callback;
int state;
uint8_t status;
uint8_t command[6];
int command_pos;
uint8_t data[512];
int data_pos, data_len;
uint8_t sector_buf[512];
uint8_t irq_dma_mask;
uint8_t completion_byte;
uint8_t error;
int drive_sel;
mfm_drive_t drives[2];
int sector, head, cylinder;
int sector_count;
uint8_t switches;
} xebec_t;
#define STAT_IRQ 0x20
#define STAT_DRQ 0x10
#define STAT_BSY 0x08
#define STAT_CD 0x04
#define STAT_IO 0x02
#define STAT_REQ 0x01
#define IRQ_ENA 0x02
#define DMA_ENA 0x01
#define CMD_TEST_DRIVE_READY 0x00
#define CMD_RECALIBRATE 0x01
#define CMD_READ_STATUS 0x03
#define CMD_VERIFY_SECTORS 0x05
#define CMD_FORMAT_TRACK 0x06
#define CMD_READ_SECTORS 0x08
#define CMD_WRITE_SECTORS 0x0a
#define CMD_SEEK 0x0b
#define CMD_INIT_DRIVE_PARAMS 0x0c
#define CMD_WRITE_SECTOR_BUFFER 0x0f
#define CMD_BUFFER_DIAGNOSTIC 0xe0
#define CMD_CONTROLLER_DIAGNOSTIC 0xe4
#define CMD_DTC_GET_DRIVE_PARAMS 0xfb
#define CMD_DTC_SET_STEP_RATE 0xfc
#define CMD_DTC_SET_GEOMETRY 0xfe
#define CMD_DTC_GET_GEOMETRY 0xff
#define ERR_NOT_READY 0x04
#define ERR_SEEK_ERROR 0x15
#define ERR_ILLEGAL_SECTOR_ADDRESS 0x21
static uint8_t xebec_read(uint16_t port, void *p)
{
xebec_t *xebec = (xebec_t *)p;
uint8_t temp = 0xff;
switch (port)
{
case 0x320: /*Read data*/
xebec->status &= ~STAT_IRQ;
switch (xebec->state)
{
case STATE_COMPLETION_BYTE:
if ((xebec->status & 0xf) != (STAT_CD | STAT_IO | STAT_REQ | STAT_BSY))
fatal("Read data STATE_COMPLETION_BYTE, status=%02x\n", xebec->status);
temp = xebec->completion_byte;
xebec->status = 0;
xebec->state = STATE_IDLE;
break;
case STATE_SEND_DATA:
if ((xebec->status & 0xf) != (STAT_IO | STAT_REQ | STAT_BSY))
fatal("Read data STATE_COMPLETION_BYTE, status=%02x\n", xebec->status);
if (xebec->data_pos >= xebec->data_len)
fatal("Data write with full data!\n");
temp = xebec->data[xebec->data_pos++];
if (xebec->data_pos == xebec->data_len)
{
xebec->status = STAT_BSY;
xebec->state = STATE_SENT_DATA;
xebec->callback = XEBEC_TIME;
}
break;
default:
fatal("Read data register - %i, %02x\n", xebec->state, xebec->status);
}
break;
case 0x321: /*Read status*/
temp = xebec->status;
break;
case 0x322: /*Read option jumpers*/
temp = xebec->switches;
break;
}
return temp;
}
static void xebec_write(uint16_t port, uint8_t val, void *p)
{
xebec_t *xebec = (xebec_t *)p;
switch (port)
{
case 0x320: /*Write data*/
switch (xebec->state)
{
case STATE_RECEIVE_COMMAND:
if ((xebec->status & 0xf) != (STAT_BSY | STAT_CD | STAT_REQ))
fatal("Bad write data state - STATE_START_COMMAND, status=%02x\n", xebec->status);
if (xebec->command_pos >= 6)
fatal("Command write with full command!\n");
/*Command data*/
xebec->command[xebec->command_pos++] = val;
if (xebec->command_pos == 6)
{
xebec->status = STAT_BSY;
xebec->state = STATE_START_COMMAND;
xebec->callback = XEBEC_TIME;
}
break;
case STATE_RECEIVE_DATA:
if ((xebec->status & 0xf) != (STAT_BSY | STAT_REQ))
fatal("Bad write data state - STATE_RECEIVE_DATA, status=%02x\n", xebec->status);
if (xebec->data_pos >= xebec->data_len)
fatal("Data write with full data!\n");
/*Command data*/
xebec->data[xebec->data_pos++] = val;
if (xebec->data_pos == xebec->data_len)
{
xebec->status = STAT_BSY;
xebec->state = STATE_RECEIVED_DATA;
xebec->callback = XEBEC_TIME;
}
break;
default:
fatal("Write data unknown state - %i %02x\n", xebec->state, xebec->status);
}
break;
case 0x321: /*Controller reset*/
xebec->status = 0;
break;
case 0x322: /*Generate controller-select-pulse*/
xebec->status = STAT_BSY | STAT_CD | STAT_REQ;
xebec->command_pos = 0;
xebec->state = STATE_RECEIVE_COMMAND;
break;
case 0x323: /*DMA/IRQ mask register*/
xebec->irq_dma_mask = val;
break;
}
}
static void xebec_complete(xebec_t *xebec)
{
xebec->status = STAT_REQ | STAT_CD | STAT_IO | STAT_BSY;
xebec->state = STATE_COMPLETION_BYTE;
if (xebec->irq_dma_mask & IRQ_ENA)
{
xebec->status |= STAT_IRQ;
picint(1 << 5);
}
}
static void xebec_error(xebec_t *xebec, uint8_t error)
{
xebec->completion_byte |= 0x02;
xebec->error = error;
pclog("xebec_error - %02x\n", xebec->error);
}
static int xebec_get_sector(xebec_t *xebec, off64_t *addr)
{
mfm_drive_t *drive = &xebec->drives[xebec->drive_sel];
int heads = drive->cfg_hpc;
if (drive->current_cylinder != xebec->cylinder)
{
pclog("mfm_get_sector: wrong cylinder\n");
xebec->error = ERR_ILLEGAL_SECTOR_ADDRESS;
return 1;
}
if (xebec->head > heads)
{
pclog("mfm_get_sector: past end of configured heads\n");
xebec->error = ERR_ILLEGAL_SECTOR_ADDRESS;
return 1;
}
if (xebec->head > drive->hpc)
{
pclog("mfm_get_sector: past end of heads\n");
xebec->error = ERR_ILLEGAL_SECTOR_ADDRESS;
return 1;
}
if (xebec->sector >= 17)
{
pclog("mfm_get_sector: past end of sectors\n");
xebec->error = ERR_ILLEGAL_SECTOR_ADDRESS;
return 1;
}
*addr = ((((off64_t) xebec->cylinder * heads) + xebec->head) *
17) + xebec->sector;
return 0;
}
static void xebec_next_sector(xebec_t *xebec)
{
mfm_drive_t *drive = &xebec->drives[xebec->drive_sel];
xebec->sector++;
if (xebec->sector >= 17)
{
xebec->sector = 0;
xebec->head++;
if (xebec->head >= drive->cfg_hpc)
{
xebec->head = 0;
xebec->cylinder++;
drive->current_cylinder++;
if (drive->current_cylinder >= drive->cfg_cyl)
drive->current_cylinder = drive->cfg_cyl-1;
}
}
}
static void xebec_callback(void *p)
{
off64_t addr;
xebec_t *xebec = (xebec_t *)p;
mfm_drive_t *drive;
xebec->callback = 0;
xebec->drive_sel = (xebec->command[1] & 0x20) ? 1 : 0;
xebec->completion_byte = xebec->drive_sel & 0x20;
drive = &xebec->drives[xebec->drive_sel];
switch (xebec->command[0])
{
case CMD_TEST_DRIVE_READY:
if (!drive->present)
xebec_error(xebec, ERR_NOT_READY);
xebec_complete(xebec);
break;
case CMD_RECALIBRATE:
if (!drive->present)
xebec_error(xebec, ERR_NOT_READY);
else
{
xebec->cylinder = 0;
drive->current_cylinder = 0;
}
xebec_complete(xebec);
break;
case CMD_READ_STATUS:
switch (xebec->state)
{
case STATE_START_COMMAND:
xebec->state = STATE_SEND_DATA;
xebec->data_pos = 0;
xebec->data_len = 4;
xebec->status = STAT_BSY | STAT_IO | STAT_REQ;
xebec->data[0] = xebec->error;
xebec->data[1] = xebec->drive_sel ? 0x20 : 0;
xebec->data[2] = xebec->data[3] = 0;
xebec->error = 0;
break;
case STATE_SENT_DATA:
xebec_complete(xebec);
break;
}
break;
case CMD_VERIFY_SECTORS:
switch (xebec->state)
{
case STATE_START_COMMAND:
xebec->cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2);
drive->current_cylinder = (xebec->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : xebec->cylinder;
xebec->head = xebec->command[1] & 0x1f;
xebec->sector = xebec->command[2] & 0x1f;
xebec->sector_count = xebec->command[4];
do
{
if (xebec_get_sector(xebec, &addr))
{
pclog("xebec_get_sector failed\n");
xebec_error(xebec, xebec->error);
xebec_complete(xebec);
return;
}
xebec_next_sector(xebec);
xebec->sector_count = (xebec->sector_count-1) & 0xff;
} while (xebec->sector_count);
xebec_complete(xebec);
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
break;
default:
fatal("CMD_VERIFY_SECTORS: bad state %i\n", xebec->state);
}
break;
case CMD_FORMAT_TRACK:
{
xebec->cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2);
drive->current_cylinder = (xebec->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : xebec->cylinder;
xebec->head = xebec->command[1] & 0x1f;
if (xebec_get_sector(xebec, &addr))
{
pclog("xebec_get_sector failed\n");
xebec_error(xebec, xebec->error);
xebec_complete(xebec);
return;
}
hdd_image_zero(drive->hdc_num, addr, 17);
xebec_complete(xebec);
}
break;
case CMD_READ_SECTORS:
switch (xebec->state)
{
case STATE_START_COMMAND:
xebec->cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2);
drive->current_cylinder = (xebec->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : xebec->cylinder;
xebec->head = xebec->command[1] & 0x1f;
xebec->sector = xebec->command[2] & 0x1f;
xebec->sector_count = xebec->command[4];
xebec->state = STATE_SEND_DATA;
xebec->data_pos = 0;
xebec->data_len = 512;
{
if (xebec_get_sector(xebec, &addr))
{
xebec_error(xebec, xebec->error);
xebec_complete(xebec);
return;
}
hdd_image_read(drive->hdc_num, addr, 1, (uint8_t *) xebec->sector_buf);
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
}
if (xebec->irq_dma_mask & DMA_ENA)
xebec->callback = XEBEC_TIME;
else
{
xebec->status = STAT_BSY | STAT_IO | STAT_REQ;
memcpy(xebec->data, xebec->sector_buf, 512);
}
break;
case STATE_SEND_DATA:
xebec->status = STAT_BSY;
if (xebec->irq_dma_mask & DMA_ENA)
{
for (; xebec->data_pos < 512; xebec->data_pos++)
{
int val = dma_channel_write(3, xebec->sector_buf[xebec->data_pos]);
if (val == DMA_NODATA)
{
pclog("CMD_READ_SECTORS out of data!\n");
xebec->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ;
xebec->callback = XEBEC_TIME;
return;
}
}
xebec->state = STATE_SENT_DATA;
xebec->callback = XEBEC_TIME;
}
else
fatal("Read sectors no DMA! - shouldn't get here\n");
break;
case STATE_SENT_DATA:
xebec_next_sector(xebec);
xebec->data_pos = 0;
xebec->sector_count = (xebec->sector_count-1) & 0xff;
if (xebec->sector_count)
{
if (xebec_get_sector(xebec, &addr))
{
xebec_error(xebec, xebec->error);
xebec_complete(xebec);
return;
}
hdd_image_read(drive->hdc_num, addr, 1, (uint8_t *) xebec->sector_buf);
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
xebec->state = STATE_SEND_DATA;
if (xebec->irq_dma_mask & DMA_ENA)
xebec->callback = XEBEC_TIME;
else
{
xebec->status = STAT_BSY | STAT_IO | STAT_REQ;
memcpy(xebec->data, xebec->sector_buf, 512);
}
}
else
{
xebec_complete(xebec);
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 0);
}
break;
default:
fatal("CMD_READ_SECTORS: bad state %i\n", xebec->state);
}
break;
case CMD_WRITE_SECTORS:
switch (xebec->state)
{
case STATE_START_COMMAND:
xebec->cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2);
drive->current_cylinder = (xebec->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : xebec->cylinder;
xebec->head = xebec->command[1] & 0x1f;
xebec->sector = xebec->command[2] & 0x1f;
xebec->sector_count = xebec->command[4];
xebec->state = STATE_RECEIVE_DATA;
xebec->data_pos = 0;
xebec->data_len = 512;
if (xebec->irq_dma_mask & DMA_ENA)
xebec->callback = XEBEC_TIME;
else
xebec->status = STAT_BSY | STAT_REQ;
break;
case STATE_RECEIVE_DATA:
xebec->status = STAT_BSY;
if (xebec->irq_dma_mask & DMA_ENA)
{
for (; xebec->data_pos < 512; xebec->data_pos++)
{
int val = dma_channel_read(3);
if (val == DMA_NODATA)
{
pclog("CMD_WRITE_SECTORS out of data!\n");
xebec->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ;
xebec->callback = XEBEC_TIME;
return;
}
xebec->sector_buf[xebec->data_pos] = val & 0xff;
}
xebec->state = STATE_RECEIVED_DATA;
xebec->callback = XEBEC_TIME;
}
else
fatal("Write sectors no DMA! - should never get here\n");
break;
case STATE_RECEIVED_DATA:
if (!(xebec->irq_dma_mask & DMA_ENA))
memcpy(xebec->sector_buf, xebec->data, 512);
{
if (xebec_get_sector(xebec, &addr))
{
xebec_error(xebec, xebec->error);
xebec_complete(xebec);
return;
}
hdd_image_write(drive->hdc_num, addr, 1, (uint8_t *) xebec->sector_buf);
}
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
xebec_next_sector(xebec);
xebec->data_pos = 0;
xebec->sector_count = (xebec->sector_count-1) & 0xff;
if (xebec->sector_count)
{
xebec->state = STATE_RECEIVE_DATA;
if (xebec->irq_dma_mask & DMA_ENA)
xebec->callback = XEBEC_TIME;
else
xebec->status = STAT_BSY | STAT_REQ;
}
else
xebec_complete(xebec);
break;
default:
fatal("CMD_WRITE_SECTORS: bad state %i\n", xebec->state);
}
break;
case CMD_SEEK:
if (!drive->present)
xebec_error(xebec, ERR_NOT_READY);
else
{
int cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2);
drive->current_cylinder = (cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : cylinder;
if (cylinder != drive->current_cylinder)
xebec_error(xebec, ERR_SEEK_ERROR);
}
xebec_complete(xebec);
break;
case CMD_INIT_DRIVE_PARAMS:
switch (xebec->state)
{
case STATE_START_COMMAND:
xebec->state = STATE_RECEIVE_DATA;
xebec->data_pos = 0;
xebec->data_len = 8;
xebec->status = STAT_BSY | STAT_REQ;
break;
case STATE_RECEIVED_DATA:
drive->cfg_cyl = xebec->data[1] | (xebec->data[0] << 8);
drive->cfg_hpc = xebec->data[2];
pclog("Drive %i: cylinders=%i, heads=%i\n", xebec->drive_sel, drive->cfg_cyl, drive->cfg_hpc);
xebec_complete(xebec);
break;
default:
fatal("CMD_INIT_DRIVE_PARAMS bad state %i\n", xebec->state);
}
break;
case CMD_WRITE_SECTOR_BUFFER:
switch (xebec->state)
{
case STATE_START_COMMAND:
xebec->state = STATE_RECEIVE_DATA;
xebec->data_pos = 0;
xebec->data_len = 512;
if (xebec->irq_dma_mask & DMA_ENA)
xebec->callback = XEBEC_TIME;
else
xebec->status = STAT_BSY | STAT_REQ;
break;
case STATE_RECEIVE_DATA:
if (xebec->irq_dma_mask & DMA_ENA)
{
xebec->status = STAT_BSY;
for (; xebec->data_pos < 512; xebec->data_pos++)
{
int val = dma_channel_read(3);
if (val == DMA_NODATA)
{
pclog("CMD_WRITE_SECTOR_BUFFER out of data!\n");
xebec->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ;
xebec->callback = XEBEC_TIME;
return;
}
xebec->data[xebec->data_pos] = val & 0xff;
}
xebec->state = STATE_RECEIVED_DATA;
xebec->callback = XEBEC_TIME;
}
else
fatal("CMD_WRITE_SECTOR_BUFFER - should never get here!\n");
break;
case STATE_RECEIVED_DATA:
memcpy(xebec->sector_buf, xebec->data, 512);
xebec_complete(xebec);
break;
default:
fatal("CMD_WRITE_SECTOR_BUFFER bad state %i\n", xebec->state);
}
break;
case CMD_BUFFER_DIAGNOSTIC:
case CMD_CONTROLLER_DIAGNOSTIC:
xebec_complete(xebec);
break;
case 0xfa:
xebec_complete(xebec);
break;
case CMD_DTC_SET_STEP_RATE:
xebec_complete(xebec);
break;
case CMD_DTC_GET_DRIVE_PARAMS:
switch (xebec->state)
{
case STATE_START_COMMAND:
xebec->state = STATE_SEND_DATA;
xebec->data_pos = 0;
xebec->data_len = 4;
xebec->status = STAT_BSY | STAT_IO | STAT_REQ;
memset(xebec->data, 0, 4);
xebec->data[0] = drive->tracks & 0xff;
xebec->data[1] = 17 | ((drive->tracks >> 2) & 0xc0);
xebec->data[2] = drive->hpc-1;
pclog("Get drive params %02x %02x %02x %i\n", xebec->data[0], xebec->data[1], xebec->data[2], drive->tracks);
break;
case STATE_SENT_DATA:
xebec_complete(xebec);
break;
default:
fatal("CMD_INIT_DRIVE_PARAMS bad state %i\n", xebec->state);
}
break;
case CMD_DTC_GET_GEOMETRY:
switch (xebec->state)
{
case STATE_START_COMMAND:
xebec->state = STATE_SEND_DATA;
xebec->data_pos = 0;
xebec->data_len = 16;
xebec->status = STAT_BSY | STAT_IO | STAT_REQ;
memset(xebec->data, 0, 16);
xebec->data[0x4] = drive->tracks & 0xff;
xebec->data[0x5] = (drive->tracks >> 8) & 0xff;
xebec->data[0xa] = drive->hpc;
break;
case STATE_SENT_DATA:
xebec_complete(xebec);
break;
}
break;
case CMD_DTC_SET_GEOMETRY:
switch (xebec->state)
{
case STATE_START_COMMAND:
xebec->state = STATE_RECEIVE_DATA;
xebec->data_pos = 0;
xebec->data_len = 16;
xebec->status = STAT_BSY | STAT_REQ;
break;
case STATE_RECEIVED_DATA:
/*Bit of a cheat here - we always report the actual geometry of the drive in use*/
xebec_complete(xebec);
break;
}
break;
default:
fatal("Unknown Xebec command - %02x %02x %02x %02x %02x %02x\n",
xebec->command[0], xebec->command[1],
xebec->command[2], xebec->command[3],
xebec->command[4], xebec->command[5]);
}
}
static void loadhd(xebec_t *xebec, int c, int d, const wchar_t *fn)
{
mfm_drive_t *drive = &xebec->drives[d];
int ret = 0;
ret = hdd_image_load(d);
if (!ret)
{
drive->present = 0;
return;
}
drive->spt = hdc[c].spt;
drive->hpc = hdc[c].hpc;
drive->tracks = hdc[c].tracks;
drive->hdc_num = c;
drive->present = 1;
}
static struct
{
int tracks, hpc;
} xebec_hd_types[4] =
{
{306, 4}, /*Type 0*/
{612, 4}, /*Type 16*/
{615, 4}, /*Type 2*/
{306, 8} /*Type 13*/
};
static void xebec_set_switches(xebec_t *xebec)
{
int c, d;
xebec->switches = 0;
for (d = 0; d < 2; d++)
{
mfm_drive_t *drive = &xebec->drives[d];
if (!drive->present)
continue;
for (c = 0; c < 4; c++)
{
if (drive->spt == 17 &&
drive->hpc == xebec_hd_types[c].hpc &&
drive->tracks == xebec_hd_types[c].tracks)
{
xebec->switches |= (c << (d ? 0 : 2));
break;
}
}
if (c == 4)
pclog("WARNING: Drive %c: has format not supported by Fixed Disk Adapter", d ? 'D' : 'C');
}
}
static void *xebec_init()
{
int i = 0;
int c = 0;
xebec_t *xebec = malloc(sizeof(xebec_t));
memset(xebec, 0, sizeof(xebec_t));
for (i = 0; i < HDC_NUM; i++)
{
if ((hdc[i].bus == HDD_BUS_MFM) && (hdc[i].mfm_channel < MFM_NUM))
{
loadhd(xebec, i, hdc[i].mfm_channel, hdc[i].fn);
c++;
if (c > MFM_NUM) break;
}
}
xebec_set_switches(xebec);
rom_init(&xebec->bios_rom, L"roms/hdd/mfm_xebec/ibm_xebec_62x0822_1985.bin", 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
io_sethandler(0x0320, 0x0004, xebec_read, NULL, NULL, xebec_write, NULL, NULL, xebec);
timer_add(xebec_callback, &xebec->callback, &xebec->callback, xebec);
return xebec;
}
static void xebec_close(void *p)
{
xebec_t *xebec = (xebec_t *)p;
int d;
for (d = 0; d < 2; d++)
{
mfm_drive_t *drive = &xebec->drives[d];
hdd_image_close(drive->hdc_num);
}
free(xebec);
}
static int xebec_available()
{
return rom_present(L"roms/hdd/mfm_xebec/ibm_xebec_62x0822_1985.bin");
}
device_t mfm_xebec_device =
{
"IBM PC Fixed Disk Adapter",
0,
xebec_init,
xebec_close,
xebec_available,
NULL,
NULL,
NULL,
NULL
};
static void *dtc_5150x_init()
{
int i = 0;
int c = 0;
xebec_t *xebec = malloc(sizeof(xebec_t));
memset(xebec, 0, sizeof(xebec_t));
for (i = 0; i < HDC_NUM; i++)
{
if ((hdc[i].bus == HDD_BUS_MFM) && (hdc[i].mfm_channel < MFM_NUM))
{
loadhd(xebec, i, hdc[i].mfm_channel, hdc[i].fn);
c++;
if (c > MFM_NUM) break;
}
}
xebec->switches = 0xff;
xebec->drives[0].cfg_cyl = xebec->drives[0].tracks;
xebec->drives[0].cfg_hpc = xebec->drives[0].hpc;
xebec->drives[1].cfg_cyl = xebec->drives[1].tracks;
xebec->drives[1].cfg_hpc = xebec->drives[1].hpc;
rom_init(&xebec->bios_rom, L"roms/hdd/mfm_xebec/dtc_cxd21a.bin", 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
io_sethandler(0x0320, 0x0004, xebec_read, NULL, NULL, xebec_write, NULL, NULL, xebec);
timer_add(xebec_callback, &xebec->callback, &xebec->callback, xebec);
return xebec;
}
static int dtc_5150x_available()
{
return rom_present(L"roms/hdd/mfm_xebec/dtc_cxd21a.bin");
}
device_t dtc_5150x_device =
{
"DTC 5150X",
0,
dtc_5150x_init,
xebec_close,
dtc_5150x_available,
NULL,
NULL,
NULL,
NULL
};

View File

@@ -1,2 +0,0 @@
extern device_t mfm_xebec_device;
extern device_t dtc_5150x_device;

178
src/hdd/hdd_table.c Normal file
View File

@@ -0,0 +1,178 @@
/*
* 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 IDE emulation for hard disks and ATAPI
* CD-ROM devices.
*
* Version: @(#)hdd_table.c 1.0.2 2017/09/29
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* TheCollector1995, <mariogplayer8@gmail.com>
* Copyright 2008-2017 Sarah Walker.
* Copyright 2016,2017 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
#include <wchar.h>
#include "../86box.h"
#include "../ibm.h"
#include "../io.h"
#include "../pic.h"
#include "../pci.h"
#include "../timer.h"
#include "hdd.h"
uint64_t hdd_table[128][3] = {
{ 306, 4, 17 }, /* 0 - 7 */
{ 615, 2, 17 },
{ 306, 4, 26 },
{ 1024, 2, 17 },
{ 697, 3, 17 },
{ 306, 8, 17 },
{ 614, 4, 17 },
{ 615, 4, 17 },
{ 670, 4, 17 }, /* 8 - 15 */
{ 697, 4, 17 },
{ 987, 3, 17 },
{ 820, 4, 17 },
{ 670, 5, 17 },
{ 697, 5, 17 },
{ 733, 5, 17 },
{ 615, 6, 17 },
{ 462, 8, 17 }, /* 016-023 */
{ 306, 8, 26 },
{ 615, 4, 26 },
{ 1024, 4, 17 },
{ 855, 5, 17 },
{ 925, 5, 17 },
{ 932, 5, 17 },
{ 1024, 2, 40 },
{ 809, 6, 17 }, /* 024-031 */
{ 976, 5, 17 },
{ 977, 5, 17 },
{ 698, 7, 17 },
{ 699, 7, 17 },
{ 981, 5, 17 },
{ 615, 8, 17 },
{ 989, 5, 17 },
{ 820, 4, 26 }, /* 032-039 */
{ 1024, 5, 17 },
{ 733, 7, 17 },
{ 754, 7, 17 },
{ 733, 5, 26 },
{ 940, 6, 17 },
{ 615, 6, 26 },
{ 462, 8, 26 },
{ 830, 7, 17 }, /* 040-047 */
{ 855, 7, 17 },
{ 751, 8, 17 },
{ 1024, 4, 26 },
{ 918, 7, 17 },
{ 925, 7, 17 },
{ 855, 5, 26 },
{ 977, 7, 17 },
{ 987, 7, 17 }, /* 048-055 */
{ 1024, 7, 17 },
{ 823, 4, 38 },
{ 925, 8, 17 },
{ 809, 6, 26 },
{ 976, 5, 26 },
{ 977, 5, 26 },
{ 698, 7, 26 },
{ 699, 7, 26 }, /* 056-063 */
{ 940, 8, 17 },
{ 615, 8, 26 },
{ 1024, 5, 26 },
{ 733, 7, 26 },
{ 1024, 8, 17 },
{ 823, 10, 17 },
{ 754, 11, 17 },
{ 830, 10, 17 }, /* 064-071 */
{ 925, 9, 17 },
{ 1224, 7, 17 },
{ 940, 6, 26 },
{ 855, 7, 26 },
{ 751, 8, 26 },
{ 1024, 9, 17 },
{ 965, 10, 17 },
{ 969, 5, 34 }, /* 072-079 */
{ 980, 10, 17 },
{ 960, 5, 35 },
{ 918, 11, 17 },
{ 1024, 10, 17 },
{ 977, 7, 26 },
{ 1024, 7, 26 },
{ 1024, 11, 17 },
{ 940, 8, 26 }, /* 080-087 */
{ 776, 8, 33 },
{ 755, 16, 17 },
{ 1024, 12, 17 },
{ 1024, 8, 26 },
{ 823, 10, 26 },
{ 830, 10, 26 },
{ 925, 9, 26 },
{ 960, 9, 26 }, /* 088-095 */
{ 1024, 13, 17 },
{ 1224, 11, 17 },
{ 900, 15, 17 },
{ 969, 7, 34 },
{ 917, 15, 17 },
{ 918, 15, 17 },
{ 1524, 4, 39 },
{ 1024, 9, 26 }, /* 096-103 */
{ 1024, 14, 17 },
{ 965, 10, 26 },
{ 980, 10, 26 },
{ 1020, 15, 17 },
{ 1023, 15, 17 },
{ 1024, 15, 17 },
{ 1024, 16, 17 },
{ 1224, 15, 17 }, /* 104-111 */
{ 755, 16, 26 },
{ 903, 8, 46 },
{ 984, 10, 34 },
{ 900, 15, 26 },
{ 917, 15, 26 },
{ 1023, 15, 26 },
{ 684, 16, 38 },
{ 1930, 4, 62 }, /* 112-119 */
{ 967, 16, 31 },
{ 1013, 10, 63 },
{ 1218, 15, 36 },
{ 654, 16, 63 },
{ 659, 16, 63 },
{ 702, 16, 63 },
{ 1002, 13, 63 },
{ 854, 16, 63 }, /* 119-127 */
{ 987, 16, 63 },
{ 995, 16, 63 },
{ 1024, 16, 63 },
{ 1036, 16, 63 },
{ 1120, 16, 59 },
{ 1054, 16, 63 },
{ 0, 0, 0 }
};

View File

@@ -8,7 +8,9 @@
*
* General include file.
*
* Version: @(#)ibm.h 1.0.5 2017/09/24
* !!!NOTE!!! The goal is to GET RID of this file. Do NOT add stuff !!
*
* Version: @(#)ibm.h 1.0.6 2017/09/29
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -481,57 +483,6 @@ extern wchar_t cfg_path[1024];
extern wchar_t nvr_path[1024];
/*Hard disk*/
enum
{
HDD_BUS_DISABLED = 0,
HDD_BUS_MFM,
HDD_BUS_XTIDE,
HDD_BUS_ESDI,
HDD_BUS_IDE_PIO_ONLY,
HDD_BUS_IDE_PIO_AND_DMA,
HDD_BUS_SCSI,
HDD_BUS_SCSI_REMOVABLE,
HDD_BUS_USB
};
#define HDC_NUM 30
#define MFM_NUM 2
#define ESDI_NUM 2
#define XTIDE_NUM 2
#define IDE_NUM 8
#define SCSI_NUM 16 /* Theoretically the controller can have at least 64 devices, or even 128 in case of a wide bus, but
let's not exaggerate with them - 16 ought to be enough for everyone. */
#pragma pack(push,1)
typedef struct {
FILE *f;
uint64_t spt,hpc; /*Sectors per track, heads per cylinder*/
uint64_t tracks;
int is_hdi;
int wp;
uint32_t base;
uint64_t at_spt,at_hpc; /*[Translation] Sectors per track, heads per cylinder*/
unsigned int bus;
unsigned int mfm_channel;
unsigned int esdi_channel;
unsigned int xtide_channel;
unsigned int ide_channel;
unsigned int scsi_id;
unsigned int scsi_lun;
wchar_t fn[260];
wchar_t prev_fn[260];
} hard_disk_t;
#pragma pack(pop)
extern hard_disk_t hdc[HDC_NUM];
uint64_t hdt[128][3];
uint64_t hdt_mfm[128][3];
int image_is_hdi(const wchar_t *s);
int image_is_hdx(const wchar_t *s, int check_signature);
/*Keyboard*/
extern int keybsenddelay;

View File

@@ -13,7 +13,8 @@
#include "../gameport.h"
#include "../keyboard_at.h"
#include "../lpt.h"
#include "../hdd/hdd_ide_at.h"
#include "../hdd/hdd.h"
#include "../hdd/hdc_ide.h"
#include "machine_common.h"
#include "machine_at.h"

View File

@@ -9,7 +9,8 @@
#include "../cpu/cpu.h"
#include "../io.h"
#include "../mem.h"
#include "../hdd/hdd_ide_at.h"
#include "../hdd/hdd.h"
#include "../hdd/hdc_ide.h"
#include "machine_at.h"
#include "machine_at_ali1429.h"

View File

@@ -9,7 +9,7 @@
* SiS sis85c471 Super I/O Chip
* Used by DTK PKM-0038S E-2
*
* Version: @(#)sis85c471.c 1.0.5 2017/09/24
* Version: @(#)sis85c471.c 1.0.6 2017/09/29
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2017 Miran Grca.
@@ -26,7 +26,8 @@
#include "../floppy/floppy.h"
#include "../floppy/fdc.h"
#include "../floppy/fdd.h"
#include "../hdd/hdd_ide_at.h"
#include "../hdd/hdd.h"
#include "../hdd/hdc_ide.h"
#include "machine_at.h"
#include "machine_at_sis_85c471.h"

View File

@@ -22,7 +22,8 @@
#include "../floppy/floppy.h"
#include "../floppy/fdd.h"
#include "../floppy/fdc.h"
#include "../hdd/hdd_ide_at.h"
#include "../hdd/hdd.h"
#include "../hdd/hdc_ide.h"
#include "../sound/snd_ps1.h"
#include "machine_common.h"
#include "machine_ps1.h"

View File

@@ -8,7 +8,7 @@
*
* Emulation core dispatcher.
*
* Version: @(#)pc.c 1.0.12 2017/09/24
* Version: @(#)pc.c 1.0.13 2017/09/29
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -45,7 +45,8 @@
#include "cdrom/cdrom_ioctl.h"
#include "cdrom/cdrom_null.h"
#include "hdd/hdd.h"
#include "hdd/hdd_ide_at.h"
#include "hdd/hdc.h"
#include "hdd/hdc_ide.h"
#include "keyboard.h"
#include "keyboard_at.h"
#include "lpt.h"
@@ -401,6 +402,7 @@ usage:
append_filename_w(config_file_default,
cfg_path,
config_file, 511);
config_file = NULL;
} else {
append_filename_w(config_file_default, cfg_path, CONFIG_FILE_W, 511);
}
@@ -473,7 +475,9 @@ void initmodules(void)
loadnvr();
sound_init();
#if 0
resetide();
#endif
scsi_card_init();
fullspeed();
@@ -562,6 +566,7 @@ void resetpchard_init(void)
fdc_init();
floppy_reset();
hdc_init(hdc_name);
#ifndef WALTJE
serial_init();
#endif
@@ -583,7 +588,9 @@ void resetpchard_init(void)
ide_qua_init();
}
#if 0
resetide();
#endif
scsi_card_init();
#ifdef USE_NETWORK
network_reset();
@@ -600,7 +607,6 @@ void resetpchard_init(void)
device_add(&ssi2001_device);
if (voodoo_enabled)
device_add(&voodoo_device);
hdd_controller_init(hdd_controller_name);
pc_reset();
mouse_emu_init();

View File

@@ -11,7 +11,8 @@
#include "keyboard_at.h"
#include "floppy/floppy.h"
#include "floppy/fdc.h"
#include "hdd/hdd_ide_at.h"
#include "hdd/hdd.h"
#include "hdd/hdc_ide.h"
#include "cdrom/cdrom.h"

View File

@@ -12,7 +12,7 @@
* word 0 - base address
* word 1 - bits 1 - 15 = byte count, bit 31 = end of transfer
*
* Version: @(#)piix.c 1.0.3 2017/09/24
* Version: @(#)piix.c 1.0.4 2017/09/29
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -29,7 +29,8 @@
#include "keyboard_at.h"
#include "mem.h"
#include "pci.h"
#include "hdd/hdd_ide_at.h"
#include "hdd/hdd.h"
#include "hdd/hdc_ide.h"
#include "piix.h"

View File

@@ -8,7 +8,7 @@
*
* Handling of the SCSI controllers.
*
* Version: @(#)scsi.c 1.0.5 2017/09/24
* Version: @(#)scsi.c 1.0.6 2017/09/29
*
* Authors: TheCollector1995, <mariogplayer@gmail.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -26,6 +26,7 @@
#include "../timer.h"
#include "../device.h"
#include "../cdrom/cdrom.h"
#include "../hdd/hdd.h"
#include "scsi.h"
#include "scsi_aha154x.h"
#include "scsi_buslogic.h"

View File

@@ -8,7 +8,7 @@
*
* The generic SCSI device command handler.
*
* Version: @(#)scsi_device.c 1.0.3 2017/09/24
* Version: @(#)scsi_device.c 1.0.4 2017/09/29
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -21,6 +21,7 @@
#include <wchar.h>
#include "../ibm.h"
#include "../cdrom/cdrom.h"
#include "../hdd/hdd.h"
#include "scsi.h"
#include "scsi_disk.h"
@@ -174,7 +175,7 @@ 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 = (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? 0x80 : 0x00;
*rmb = (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? 0x80 : 0x00;
break;
case SCSI_CDROM:
*type = 0x05;

View File

@@ -6,7 +6,7 @@
*
* Emulation of SCSI fixed and removable disks.
*
* Version: @(#)scsi_disk.c 1.0.8 2017/09/24
* Version: @(#)scsi_disk.c 1.0.9 2017/09/29
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2017 Miran Grca.
@@ -22,8 +22,8 @@
#include "../timer.h"
#include "../piix.h"
#include "../cdrom/cdrom.h"
#include "../hdd/hdd_image.h"
#include "../hdd/hdd_ide_at.h"
#include "../hdd/hdd.h"
#include "../hdd/hdc_ide.h"
#include "../win/plat_iodev.h"
#include "scsi.h"
#include "scsi_disk.h"
@@ -49,8 +49,8 @@
#define scsi_hd_ascq shdc[id].sense[13]
scsi_hard_disk_t shdc[HDC_NUM];
FILE *shdf[HDC_NUM];
scsi_hard_disk_t shdc[HDD_NUM];
FILE *shdf[HDD_NUM];
uint8_t scsi_hard_disks[16][8] = {
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
@@ -190,21 +190,21 @@ int scsi_hd_phase_to_scsi(uint8_t id)
}
int find_hdc_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun)
int find_hdd_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun)
{
uint8_t i = 0;
for (i = 0; i < HDC_NUM; i++)
for (i = 0; i < HDD_NUM; i++)
{
if ((wcslen(hdc[i].fn) == 0) && (hdc[i].bus != HDD_BUS_SCSI_REMOVABLE))
if ((wcslen(hdd[i].fn) == 0) && (hdd[i].bus != HDD_BUS_SCSI_REMOVABLE))
{
continue;
}
if (((hdc[i].spt == 0) || (hdc[i].hpc == 0) || (hdc[i].tracks == 0)) && (hdc[i].bus != HDD_BUS_SCSI_REMOVABLE))
if (((hdd[i].spt == 0) || (hdd[i].hpc == 0) || (hdd[i].tracks == 0)) && (hdd[i].bus != HDD_BUS_SCSI_REMOVABLE))
{
continue;
}
if (((hdc[i].bus == HDD_BUS_SCSI) || (hdc[i].bus == HDD_BUS_SCSI_REMOVABLE)) && (hdc[i].scsi_id == scsi_id) && (hdc[i].scsi_lun == scsi_lun))
if (((hdd[i].bus == HDD_BUS_SCSI) || (hdd[i].bus == HDD_BUS_SCSI_REMOVABLE)) && (hdd[i].scsi_id == scsi_id) && (hdd[i].scsi_lun == scsi_lun))
{
return i;
}
@@ -215,19 +215,14 @@ int find_hdc_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun)
void scsi_disk_insert(uint8_t id)
{
shdc[id].unit_attention = (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0;
shdc[id].unit_attention = (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0;
}
void scsi_loadhd(int scsi_id, int scsi_lun, int id)
{
int ret = 0;
ret = hdd_image_load(id);
if (!ret)
{
if (hdc[id].bus != HDD_BUS_SCSI_REMOVABLE)
if (! hdd_image_load(id)) {
if (hdd[id].bus != HDD_BUS_SCSI_REMOVABLE)
{
scsi_hard_disks[scsi_id][scsi_lun] = 0xff;
}
@@ -243,14 +238,14 @@ void scsi_reloadhd(int id)
{
int ret = 0;
if(wcslen(hdc[id].prev_fn) == 0)
if (wcslen(hdd[id].prev_fn) == 0)
{
return;
}
else
{
wcscpy(hdc[id].fn, hdc[id].prev_fn);
memset(hdc[id].prev_fn, 0, sizeof(hdc[id].prev_fn));
wcscpy(hdd[id].fn, hdd[id].prev_fn);
memset(hdd[id].prev_fn, 0, sizeof(hdd[id].prev_fn));
}
ret = hdd_image_load(id);
@@ -282,11 +277,11 @@ void build_scsi_hd_map(void)
{
for (j = 0; j < 8; j++)
{
scsi_hard_disks[i][j] = find_hdc_for_scsi_id(i, j);
scsi_hard_disks[i][j] = find_hdd_for_scsi_id(i, j);
if (scsi_hard_disks[i][j] != 0xff)
{
memset(&(shdc[scsi_hard_disks[i][j]]), 0, sizeof(shdc[scsi_hard_disks[i][j]]));
if (wcslen(hdc[scsi_hard_disks[i][j]].fn) > 0)
if (wcslen(hdd[scsi_hard_disks[i][j]].fn) > 0)
{
scsi_loadhd(i, j, scsi_hard_disks[i][j]);
}
@@ -414,14 +409,14 @@ void scsi_hd_data_command_finish(uint8_t id, int len, int block_len, int alloc_l
}
if (len == 0)
{
SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength = 0;
SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].InitLength = 0;
scsi_hd_command_complete(id);
}
else
{
if (direction == 0)
{
SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength = alloc_len;
SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].InitLength = alloc_len;
scsi_hd_command_read_dma(id);
}
else
@@ -548,7 +543,7 @@ int scsi_hd_pre_execution_check(uint8_t id, uint8_t *cdb)
{
int ready = 1;
if (((shdc[id].request_length >> 5) & 7) != hdc[id].scsi_lun)
if (((shdc[id].request_length >> 5) & 7) != hdd[id].scsi_lun)
{
scsi_hd_log("SCSI HD %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", id, ((shdc[id].request_length >> 5) & 7));
scsi_hd_invalid_lun(id);
@@ -563,10 +558,10 @@ int scsi_hd_pre_execution_check(uint8_t id, uint8_t *cdb)
return 0;
}
if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE)
if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE)
{
/* Removable disk, set ready state. */
if (wcslen(hdc[id].fn) > 0)
if (wcslen(hdd[id].fn) > 0)
{
ready = 1;
}
@@ -697,10 +692,10 @@ void scsi_hd_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_l
{
int ready = 1;
if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE)
if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE)
{
/* Removable disk, set ready state. */
if (wcslen(hdc[id].fn) > 0)
if (wcslen(hdd[id].fn) > 0)
{
ready = 1;
}
@@ -732,7 +727,7 @@ void scsi_hd_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_l
void scsi_hd_command(uint8_t id, uint8_t *cdb)
{
/* uint8_t *hdbufferb = (uint8_t *) shdc[id].buffer; */
uint8_t *hdbufferb = SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].CmdBuffer;
uint8_t *hdbufferb = SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].CmdBuffer;
uint32_t len;
int pos=0;
int max_len;
@@ -764,7 +759,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
device_identify_ex[12] = EMU_VERSION[2];
device_identify_ex[13] = EMU_VERSION[3];
if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE)
if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE)
{
device_identify[4] = 'R';
@@ -814,9 +809,9 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
case GPCMD_REQUEST_SENSE:
/* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE
should forget about the not ready, and report unit attention straight away. */
if (SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength < cdb[4])
if (SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].InitLength < cdb[4])
{
cdb[4] = SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength;
cdb[4] = SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].InitLength;
}
scsi_hd_request_sense(id, hdbufferb, cdb[4]);
scsi_hd_data_command_finish(id, 18, 18, cdb[4], 0);
@@ -856,7 +851,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
return;
}
if ((!shdc[id].sector_len) || (SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength == 0))
if ((!shdc[id].sector_len) || (SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].InitLength == 0))
{
/* scsi_hd_log("SCSI HD %i: All done - callback set\n", id); */
shdc[id].packet_status = CDROM_PHASE_COMPLETE;
@@ -869,11 +864,11 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
alloc_length = shdc[id].packet_len = max_len << 9;
if ((shdc[id].requested_blocks > 0) && (SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength > 0))
if ((shdc[id].requested_blocks > 0) && (SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].InitLength > 0))
{
if (alloc_length > SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength)
if (alloc_length > SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].InitLength)
{
hdd_image_read(id, shdc[id].sector_pos, SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength >> 9, hdbufferb);
hdd_image_read(id, shdc[id].sector_pos, SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].InitLength >> 9, hdbufferb);
}
else
{
@@ -892,18 +887,18 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
shdc[id].all_blocks_total = shdc[id].block_total;
if (shdc[id].packet_status != CDROM_PHASE_COMPLETE)
{
update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 1);
update_status_bar_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 1);
}
else
{
update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
update_status_bar_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
}
return;
case GPCMD_WRITE_6:
case GPCMD_WRITE_10:
case GPCMD_WRITE_12:
if ((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) && hdc[id].wp)
if ((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) && hdd[id].wp)
{
scsi_hd_write_protected(id);
return;
@@ -932,7 +927,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
return;
}
if ((!shdc[id].sector_len) || (SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength == 0))
if ((!shdc[id].sector_len) || (SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].InitLength == 0))
{
/* scsi_hd_log("SCSI HD %i: All done - callback set\n", id); */
shdc[id].packet_status = CDROM_PHASE_COMPLETE;
@@ -945,11 +940,11 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
alloc_length = shdc[id].packet_len = max_len << 9;
if ((shdc[id].requested_blocks > 0) && (SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength > 0))
if ((shdc[id].requested_blocks > 0) && (SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].InitLength > 0))
{
if (alloc_length > SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength)
if (alloc_length > SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].InitLength)
{
hdd_image_write(id, shdc[id].sector_pos, SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength >> 9, hdbufferb);
hdd_image_write(id, shdc[id].sector_pos, SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].InitLength >> 9, hdbufferb);
}
else
{
@@ -968,16 +963,16 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
shdc[id].all_blocks_total = shdc[id].block_total;
if (shdc[id].packet_status != CDROM_PHASE_COMPLETE)
{
update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 1);
update_status_bar_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 1);
}
else
{
update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
update_status_bar_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
}
return;
case GPCMD_START_STOP_UNIT:
if (hdc[id].bus != HDD_BUS_SCSI_REMOVABLE)
if (hdd[id].bus != HDD_BUS_SCSI_REMOVABLE)
{
scsi_hd_illegal_opcode(id);
break;
@@ -1004,7 +999,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
max_len <<= 8;
max_len |= cdb[4];
if ((!max_len) || (SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength == 0))
if ((!max_len) || (SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].InitLength == 0))
{
/* scsi_hd_log("SCSI HD %i: All done - callback set\n", id); */
shdc[id].packet_status = CDROM_PHASE_COMPLETE;
@@ -1073,7 +1068,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
memset(tempbuffer, 0, 8);
tempbuffer[0] = 0; /*SCSI HD*/
if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE)
if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE)
{
tempbuffer[1] = 0x80; /*Removable*/
}
@@ -1100,9 +1095,9 @@ atapi_out:
len = max_len;
}
if (len > SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength)
if (len > SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].InitLength)
{
len = SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength;
len = SCSIDevices[hdd[id].scsi_id][hdd[id].scsi_lun].InitLength;
}
memcpy(hdbufferb, tempbuffer, len);
@@ -1166,7 +1161,7 @@ void scsi_hd_callback(uint8_t id)
shdc[id].status = READY_STAT;
shdc[id].phase = 3;
shdc[id].packet_status = 0xFF;
update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
update_status_bar_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
return;
case CDROM_PHASE_DATA_OUT:
scsi_hd_log("SCSI HD %i: PHASE_DATA_OUT\n", id);
@@ -1178,7 +1173,7 @@ void scsi_hd_callback(uint8_t id)
shdc[id].packet_status = CDROM_PHASE_COMPLETE;
shdc[id].status = READY_STAT;
shdc[id].phase = 3;
update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
update_status_bar_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
return;
case CDROM_PHASE_DATA_IN:
scsi_hd_log("SCSI HD %i: PHASE_DATA_IN\n", id);
@@ -1190,7 +1185,7 @@ void scsi_hd_callback(uint8_t id)
shdc[id].packet_status = CDROM_PHASE_COMPLETE;
shdc[id].status = READY_STAT;
shdc[id].phase = 3;
update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
update_status_bar_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
return;
case CDROM_PHASE_ERROR:
scsi_hd_log("SCSI HD %i: PHASE_ERROR\n", id);

View File

@@ -6,13 +6,13 @@
*
* Emulation of SCSI fixed and removable disks.
*
* Version: @(#)scsi_disk.h 1.0.1 2017/08/23
* Version: @(#)scsi_disk.h 1.0.2 2017/09/29
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2017 Miran Grca.
*/
#pragma pack(push,1)
typedef struct {
/* Stuff for SCSI hard disks. */
uint8_t cdb[16];
@@ -42,15 +42,15 @@ typedef struct {
int request_pos;
uint8_t hd_cdb[16];
} scsi_hard_disk_t;
#pragma pack(pop)
extern scsi_hard_disk_t shdc[HDC_NUM];
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);
extern FILE *shdf[HDC_NUM];
int scsi_hd_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len);

View File

@@ -8,7 +8,7 @@
*
* Implementation of the SMC FDC37C665 Super I/O Chip.
*
* Version: @(#)sio_fdc37c665.c 1.0.5 2017/09/24
* Version: @(#)sio_fdc37c665.c 1.0.6 2017/09/29
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -26,7 +26,8 @@
#include "floppy/floppy.h"
#include "floppy/fdc.h"
#include "floppy/fdd.h"
#include "hdd/hdd_ide_at.h"
#include "hdd/hdd.h"
#include "hdd/hdc_ide.h"
#include "sio.h"

View File

@@ -8,7 +8,7 @@
*
* Implementation of the SMC FDC37C669 Super I/O Chip.
*
* Version: @(#)sio_fdc37c669.c 1.0.3 2017/09/24
* Version: @(#)sio_fdc37c669.c 1.0.4 2017/09/29
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016,2017 Miran Grca.
@@ -24,7 +24,8 @@
#include "floppy/floppy.h"
#include "floppy/fdc.h"
#include "floppy/fdd.h"
#include "hdd/hdd_ide_at.h"
#include "hdd/hdd.h"
#include "hdd/hdc_ide.h"
#include "sio.h"

View File

@@ -8,7 +8,7 @@
*
* Implementation of the SMC FDC37C932FR Super I/O Chip.
*
* Version: @(#)sio_fdc37c932fr.c 1.0.4 2017/09/24
* Version: @(#)sio_fdc37c932fr.c 1.0.5 2017/09/29
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016,2017 Miran Grca.
@@ -24,7 +24,8 @@
#include "floppy/floppy.h"
#include "floppy/fdc.h"
#include "floppy/fdd.h"
#include "hdd/hdd_ide_at.h"
#include "hdd/hdd.h"
#include "hdd/hdc_ide.h"
#include "sio.h"

View File

@@ -8,7 +8,7 @@
*
* Emulation of the NatSemi PC87306 Super I/O chip.
*
* Version: @(#)sio_pc87306.c 1.0.4 2017/09/24
* Version: @(#)sio_pc87306.c 1.0.5 2017/09/29
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016,2017 Miran Grca.
@@ -24,7 +24,8 @@
#include "floppy/floppy.h"
#include "floppy/fdc.h"
#include "floppy/fdd.h"
#include "hdd/hdd_ide_at.h"
#include "hdd/hdd.h"
#include "hdd/hdc_ide.h"
#include "sio.h"

View File

@@ -8,7 +8,7 @@
*
* The Emulator's Windows core.
*
* Version: @(#)win.c 1.0.12 2017/09/25
* Version: @(#)win.c 1.0.13 2017/09/29
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -46,7 +46,8 @@
#include "../floppy/floppy.h"
#include "../floppy/fdd.h"
#include "../hdd/hdd.h"
#include "../hdd/hdd_ide_at.h"
#include "../hdd/hdc.h"
#include "../hdd/hdc_ide.h"
#include "../scsi/scsi.h"
#include "../scsi/scsi_disk.h"
#ifdef USE_NETWORK
@@ -731,15 +732,17 @@ int fdd_type_to_icon(int type)
}
}
int count_hard_disks(int bus)
/* FIXME: should be hdd_count() in hdd.c */
int hdd_count(int bus)
{
int i = 0;
int c = 0;
for (i = 0; i < HDC_NUM; i++)
for (i = 0; i < HDD_NUM; i++)
{
if (hdc[i].bus == bus)
if (hdd[i].bus == bus)
{
c++;
}
@@ -748,6 +751,7 @@ int count_hard_disks(int bus)
return c;
}
int find_status_bar_part(int tag)
{
int i = 0;
@@ -900,13 +904,13 @@ void create_removable_hd_tip(int part)
int drive = sb_part_meanings[part] & 0x1f;
if (wcslen(hdc[drive].fn) == 0)
if (wcslen(hdd[drive].fn) == 0)
{
_swprintf(tempTip, win_language_get_string_from_id(IDS_4115), drive, win_language_get_string_from_id(IDS_2057));
}
else
{
_swprintf(tempTip, win_language_get_string_from_id(IDS_4115), drive, hdc[drive].fn);
_swprintf(tempTip, win_language_get_string_from_id(IDS_4115), drive, hdd[drive].fn);
}
if (sbTips[part] != NULL)
@@ -1122,12 +1126,12 @@ void update_status_bar_panes(HWND hwnds)
sb_ready = 0;
c_mfm = count_hard_disks(HDD_BUS_MFM);
c_esdi = count_hard_disks(HDD_BUS_ESDI);
c_xtide = count_hard_disks(HDD_BUS_XTIDE);
c_ide_pio = count_hard_disks(HDD_BUS_IDE_PIO_ONLY);
c_ide_dma = count_hard_disks(HDD_BUS_IDE_PIO_AND_DMA);
c_scsi = count_hard_disks(HDD_BUS_SCSI);
c_mfm = hdd_count(HDD_BUS_MFM);
c_esdi = hdd_count(HDD_BUS_ESDI);
c_xtide = hdd_count(HDD_BUS_XTIDE);
c_ide_pio = hdd_count(HDD_BUS_IDE_PIO_ONLY);
c_ide_dma = hdd_count(HDD_BUS_IDE_PIO_AND_DMA);
c_scsi = hdd_count(HDD_BUS_SCSI);
#ifdef USE_NETWORK
do_net = display_network_icon();
@@ -1195,22 +1199,22 @@ void update_status_bar_panes(HWND hwnds)
sb_parts++;
}
}
for (i = 0; i < HDC_NUM; i++)
for (i = 0; i < HDD_NUM; i++)
{
if ((hdc[i].bus == HDD_BUS_SCSI_REMOVABLE) && (scsi_card_current != 0))
if ((hdd[i].bus == HDD_BUS_SCSI_REMOVABLE) && (scsi_card_current != 0))
{
sb_parts++;
}
}
if (c_mfm && !(machines[machine].flags & MACHINE_HAS_IDE) && !!memcmp(hdd_controller_name, "none", 4) && !!memcmp(hdd_controller_name, "xtide", 5) && !!memcmp(hdd_controller_name, "esdi", 4))
if (c_mfm && !(machines[machine].flags & MACHINE_HAS_IDE) && !!memcmp(hdc_name, "none", 4) && !!memcmp(hdc_name, "xtide", 5) && !!memcmp(hdc_name, "esdi", 4))
{
sb_parts++;
}
if (c_esdi && !memcmp(hdd_controller_name, "esdi", 4))
if (c_esdi && !memcmp(hdc_name, "esdi", 4))
{
sb_parts++;
}
if (c_xtide && !memcmp(hdd_controller_name, "xtide", 5))
if (c_xtide && !memcmp(hdc_name, "xtide", 5))
{
sb_parts++;
}
@@ -1283,9 +1287,9 @@ void update_status_bar_panes(HWND hwnds)
sb_parts++;
}
}
for (i = 0; i < HDC_NUM; i++)
for (i = 0; i < HDD_NUM; i++)
{
if ((hdc[i].bus == HDD_BUS_SCSI_REMOVABLE) && (scsi_card_current != 0))
if ((hdd[i].bus == HDD_BUS_SCSI_REMOVABLE) && (scsi_card_current != 0))
{
edge += SB_ICON_WIDTH;
iStatusWidths[sb_parts] = edge;
@@ -1293,21 +1297,21 @@ void update_status_bar_panes(HWND hwnds)
sb_parts++;
}
}
if (c_mfm && !(machines[machine].flags & MACHINE_HAS_IDE) && !!memcmp(hdd_controller_name, "none", 4) && !!memcmp(hdd_controller_name, "xtide", 5) && !!memcmp(hdd_controller_name, "esdi", 4))
if (c_mfm && !(machines[machine].flags & MACHINE_HAS_IDE) && !!memcmp(hdc_name, "none", 4) && !!memcmp(hdc_name, "xtide", 5) && !!memcmp(hdc_name, "esdi", 4))
{
edge += SB_ICON_WIDTH;
iStatusWidths[sb_parts] = edge;
sb_part_meanings[sb_parts] = SB_HDD | HDD_BUS_MFM;
sb_parts++;
}
if (c_esdi && !memcmp(hdd_controller_name, "esdi", 4))
if (c_esdi && !memcmp(hdc_name, "esdi", 4))
{
edge += SB_ICON_WIDTH;
iStatusWidths[sb_parts] = edge;
sb_part_meanings[sb_parts] = SB_HDD | HDD_BUS_ESDI;
sb_parts++;
}
if (c_xtide && !memcmp(hdd_controller_name, "xtide", 5))
if (c_xtide && !memcmp(hdc_name, "xtide", 5))
{
edge += SB_ICON_WIDTH;
iStatusWidths[sb_parts] = edge;
@@ -1390,7 +1394,7 @@ void update_status_bar_panes(HWND hwnds)
break;
case SB_RDISK:
/* Removable hard disk */
sb_icon_flags[i] = (wcslen(hdc[sb_part_meanings[i] & 0x1f].fn) == 0) ? 256 : 0;
sb_icon_flags[i] = (wcslen(hdd[sb_part_meanings[i] & 0x1f].fn) == 0) ? 256 : 0;
sb_part_icons[i] = 176 + sb_icon_flags[i];
sb_menu_handles[i] = create_popup_menu(i);
create_removable_disk_submenu(sb_menu_handles[i], sb_part_meanings[i] & 0x1f);
@@ -2755,16 +2759,16 @@ LRESULT CALLBACK StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPAR
case IDM_RDISK_IMAGE:
case IDM_RDISK_IMAGE_WP:
id = item_params & 0x001f;
ret = file_dlg_w_st(hwnd, IDS_4106, hdc[id].fn, id);
ret = file_dlg_w_st(hwnd, IDS_4106, hdd[id].fn, id);
if (!ret)
{
removable_disk_unload(id);
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
wcscpy(hdc[id].fn, wopenfilestring);
hdc[id].wp = (item_id == IDM_RDISK_IMAGE_WP) ? 1 : 0;
scsi_loadhd(hdc[id].scsi_id, hdc[id].scsi_lun, id);
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
wcscpy(hdd[id].fn, wopenfilestring);
hdd[id].wp = (item_id == IDM_RDISK_IMAGE_WP) ? 1 : 0;
scsi_loadhd(hdd[id].scsi_id, hdd[id].scsi_lun, id);
scsi_disk_insert(id);
if (wcslen(hdc[id].fn) > 0)
if (wcslen(hdd[id].fn) > 0)
{
update_status_bar_icon_state(SB_RDISK | id, 0);
EnableMenuItem(sb_menu_handles[part], IDM_RDISK_EJECT | id, MF_BYCOMMAND | MF_ENABLED);

View File

@@ -8,7 +8,7 @@
*
* Windows IO device menu handler.
*
* Version: @(#)win_iodev.c 1.0.3 2017/09/24
* Version: @(#)win_iodev.c 1.0.4 2017/09/29
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016,2017 Miran Grca.
@@ -36,6 +36,7 @@
#include "../cdrom/cdrom_image.h"
#include "../cdrom/cdrom_ioctl.h"
#include "../cdrom/cdrom_null.h"
#include "../hdd/hdd.h"
#include "../scsi/scsi_disk.h"
#include "plat_iodev.h"
#include "win.h"
@@ -146,12 +147,12 @@ void cdrom_reload(uint8_t id)
void removable_disk_unload(uint8_t id)
{
if (wcslen(hdc[id].fn) == 0)
if (wcslen(hdd[id].fn) == 0)
{
/* Switch from empty to empty. Do nothing. */
return;
}
scsi_unloadhd(hdc[id].scsi_id, hdc[id].scsi_lun, id);
scsi_unloadhd(hdd[id].scsi_id, hdd[id].scsi_lun, id);
scsi_disk_insert(id);
}
@@ -186,17 +187,17 @@ void removable_disk_reload(uint8_t id)
return;
}
if (wcslen(hdc[id].fn) != 0)
if (wcslen(hdd[id].fn) != 0)
{
/* Attempting to reload while an image is already loaded. Do nothing. */
return;
}
scsi_reloadhd(id);
/* scsi_disk_insert(id); */
update_status_bar_icon_state(SB_RDISK | id, wcslen(hdc[id].fn) ? 0 : 1);
EnableMenuItem(sb_menu_handles[part], IDM_RDISK_EJECT | id, MF_BYCOMMAND | (wcslen(hdc[id].fn) ? MF_ENABLED : MF_GRAYED));
update_status_bar_icon_state(SB_RDISK | id, wcslen(hdd[id].fn) ? 0 : 1);
EnableMenuItem(sb_menu_handles[part], IDM_RDISK_EJECT | id, MF_BYCOMMAND | (wcslen(hdd[id].fn) ? MF_ENABLED : MF_GRAYED));
EnableMenuItem(sb_menu_handles[part], IDM_RDISK_RELOAD | id, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem(sb_menu_handles[part], IDM_RDISK_SEND_CHANGE | id, MF_BYCOMMAND | (wcslen(hdc[id].fn) ? MF_ENABLED : MF_GRAYED));
EnableMenuItem(sb_menu_handles[part], IDM_RDISK_SEND_CHANGE | id, MF_BYCOMMAND | (wcslen(hdd[id].fn) ? MF_ENABLED : MF_GRAYED));
update_tip(SB_RDISK | id);
config_save();
}

View File

@@ -8,7 +8,7 @@
*
* Windows 86Box Settings dialog handler.
*
* Version: @(#)win_settings.c 1.0.13 2017/09/24
* Version: @(#)win_settings.c 1.0.14 2017/09/29
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016,2017 Miran Grca.
@@ -39,7 +39,8 @@
#include "../floppy/floppy.h"
#include "../floppy/fdd.h"
#include "../hdd/hdd.h"
#include "../hdd/hdd_ide_at.h"
#include "../hdd/hdc.h"
#include "../hdd/hdc_ide.h"
#include "../scsi/scsi.h"
#ifdef USE_NETWORK
#include "../network/network.h"
@@ -82,11 +83,10 @@ static int temp_serial[2], temp_lpt;
/* Peripherals category */
static int temp_scsi_card, hdc_ignore, temp_ide_ter, temp_ide_ter_irq, temp_ide_qua, temp_ide_qua_irq;
static int temp_bugger;
static char temp_hdc_name[16];
/* Hard disks category */
static hard_disk_t temp_hdc[HDC_NUM];
static hard_disk_t temp_hdd[HDD_NUM];
/* Removable devices category */
static int temp_fdd_types[FDD_NUM];
@@ -109,7 +109,7 @@ static int settings_scsi_to_list[20], settings_list_to_scsi[20];
#ifdef USE_NETWORK
static int settings_network_to_list[20], settings_list_to_network[20];
#endif
static char *hdd_names[16];
static char *hdc_names[16];
/* This does the initial read of global variables into the temporary ones. */
@@ -164,7 +164,7 @@ static void win_settings_init(void)
/* Peripherals category */
temp_scsi_card = scsi_card_current;
strncpy(temp_hdc_name, hdd_controller_name, sizeof(temp_hdc_name) - 1);
strncpy(temp_hdc_name, hdc_name, sizeof(temp_hdc_name) - 1);
temp_ide_ter = ide_enable[2];
temp_ide_ter_irq = ide_irq[2];
temp_ide_qua = ide_enable[3];
@@ -172,7 +172,7 @@ static void win_settings_init(void)
temp_bugger = bugger_enabled;
/* Hard disks category */
memcpy(temp_hdc, hdc, HDC_NUM * sizeof(hard_disk_t));
memcpy(temp_hdd, hdd, HDD_NUM * sizeof(hard_disk_t));
/* Removable devices category */
for (i = 0; i < FDD_NUM; i++)
@@ -236,7 +236,7 @@ static int win_settings_changed(void)
/* Peripherals category */
i = i || (scsi_card_current != temp_scsi_card);
i = i || strncmp(temp_hdc_name, hdd_controller_name, sizeof(temp_hdc_name) - 1);
i = i || strncmp(temp_hdc_name, hdc_name, sizeof(temp_hdc_name) - 1);
i = i || (temp_ide_ter != ide_enable[2]);
i = i || (temp_ide_ter_irq != ide_irq[2]);
i = i || (temp_ide_qua != ide_enable[3]);
@@ -244,7 +244,7 @@ static int win_settings_changed(void)
i = i || (temp_bugger != bugger_enabled);
/* Hard disks category */
i = i || memcmp(hdc, temp_hdc, HDC_NUM * sizeof(hard_disk_t));
i = i || memcmp(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t));
/* Removable devices category */
for (j = 0; j < FDD_NUM; j++)
@@ -345,7 +345,7 @@ static void win_settings_save(void)
/* Peripherals category */
scsi_card_current = temp_scsi_card;
strncpy(hdd_controller_name, temp_hdc_name, sizeof(temp_hdc_name) - 1);
strncpy(hdc_name, temp_hdc_name, sizeof(temp_hdc_name) - 1);
ide_enable[2] = temp_ide_ter;
ide_irq[2] = temp_ide_ter_irq;
ide_enable[3] = temp_ide_qua;
@@ -353,7 +353,7 @@ static void win_settings_save(void)
bugger_enabled = temp_bugger;
/* Hard disks category */
memcpy(hdc, temp_hdc, HDC_NUM * sizeof(hard_disk_t));
memcpy(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t));
/* Removable devices category */
for (i = 0; i < FDD_NUM; i++)
@@ -1385,7 +1385,7 @@ static BOOL CALLBACK win_settings_ports_proc(HWND hdlg, UINT message, WPARAM wPa
}
static void recalc_hdd_list(HWND hdlg, int machine, int use_selected_hdd)
static void recalc_hdd_list(HWND hdlg, int machine, int use_selected_hdc)
{
HWND h;
@@ -1415,13 +1415,13 @@ static void recalc_hdd_list(HWND hdlg, int machine, int use_selected_hdd)
valid = 0;
if (use_selected_hdd)
if (use_selected_hdc)
{
c = SendMessage(h, CB_GETCURSEL, 0, 0);
if (c != -1 && hdd_names[c])
if (c != -1 && hdc_names[c])
{
strncpy(old_name, hdd_names[c], sizeof(old_name) - 1);
strncpy(old_name, hdc_names[c], sizeof(old_name) - 1);
}
else
{
@@ -1437,27 +1437,27 @@ static void recalc_hdd_list(HWND hdlg, int machine, int use_selected_hdd)
c = d = 0;
while (1)
{
s = hdd_controller_get_name(c);
s = hdc_get_name(c);
if (s[0] == 0)
{
break;
}
if ((hdd_controller_get_flags(c) & DEVICE_AT) && !(machines[machine].flags & MACHINE_AT))
if ((hdc_get_flags(c) & DEVICE_AT) && !(machines[machine].flags & MACHINE_AT))
{
c++;
continue;
}
if ((hdd_controller_get_flags(c) & DEVICE_PS2) && !(machines[machine].flags & MACHINE_PS2_HDD))
if ((hdc_get_flags(c) & DEVICE_PS2) && !(machines[machine].flags & MACHINE_PS2_HDD))
{
c++;
continue;
}
if ((hdd_controller_get_flags(c) & DEVICE_MCA) && !(machines[machine].flags & MACHINE_MCA))
if ((hdc_get_flags(c) & DEVICE_MCA) && !(machines[machine].flags & MACHINE_MCA))
{
c++;
continue;
}
if (!hdd_controller_available(c))
if (!hdc_available(c))
{
c++;
continue;
@@ -1471,8 +1471,8 @@ static void recalc_hdd_list(HWND hdlg, int machine, int use_selected_hdd)
mbstowcs(lptsTemp, s, strlen(s) + 1);
SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp);
}
hdd_names[d] = hdd_controller_get_internal_name(c);
if (!strcmp(old_name, hdd_names[d]))
hdc_names[d] = hdc_get_internal_name(c);
if (!strcmp(old_name, hdc_names[d]))
{
SendMessage(h, CB_SETCURSEL, d, 0);
valid = 1;
@@ -1650,9 +1650,9 @@ static BOOL CALLBACK win_settings_peripherals_proc(HWND hdlg, UINT message, WPAR
{
h = GetDlgItem(hdlg, IDC_COMBO_HDC);
c = SendMessage(h, CB_GETCURSEL, 0, 0);
if (hdd_names[c])
if (hdc_names[c])
{
strncpy(temp_hdc_name, hdd_names[c], sizeof(temp_hdc_name) - 1);
strncpy(temp_hdc_name, hdc_names[c], sizeof(temp_hdc_name) - 1);
}
else
{
@@ -1921,28 +1921,28 @@ int next_free_id = 0;
static void normalize_hd_list()
{
hard_disk_t ihdc[HDC_NUM];
hard_disk_t ihdd[HDD_NUM];
int i, j;
j = 0;
memset(ihdc, 0, HDC_NUM * sizeof(hard_disk_t));
memset(ihdd, 0, HDD_NUM * sizeof(hard_disk_t));
for (i = 0; i < HDC_NUM; i++)
for (i = 0; i < HDD_NUM; i++)
{
if (temp_hdc[i].bus != HDD_BUS_DISABLED)
if (temp_hdd[i].bus != HDD_BUS_DISABLED)
{
memcpy(&(ihdc[j]), &(temp_hdc[i]), sizeof(hard_disk_t));
memcpy(&(ihdd[j]), &(temp_hdd[i]), sizeof(hard_disk_t));
j++;
}
}
memcpy(temp_hdc, ihdc, HDC_NUM * sizeof(hard_disk_t));
memcpy(temp_hdd, ihdd, HDD_NUM * sizeof(hard_disk_t));
}
int hdc_id_to_listview_index[HDC_NUM];
int hdc_id_to_listview_index[HDD_NUM];
int hd_listview_items;
hard_disk_t new_hdc;
hard_disk_t new_hdd;
int hdlv_current_sel;
static int get_selected_hard_disk(HWND hdlg)
@@ -2060,7 +2060,7 @@ static void recalc_location_controls(HWND hdlg, int is_add_dlg)
h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL);
ShowWindow(h, SW_SHOW);
EnableWindow(h, TRUE);
SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdc.mfm_channel : temp_hdc[hdlv_current_sel].mfm_channel, 0);
SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.mfm_channel : temp_hdd[hdlv_current_sel].mfm_channel, 0);
break;
case HDD_BUS_XTIDE: /* XT IDE */
h = GetDlgItem(hdlg, IDT_1722);
@@ -2070,7 +2070,7 @@ static void recalc_location_controls(HWND hdlg, int is_add_dlg)
h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL);
ShowWindow(h, SW_SHOW);
EnableWindow(h, TRUE);
SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdc.xtide_channel : temp_hdc[hdlv_current_sel].xtide_channel, 0);
SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.xtide_channel : temp_hdd[hdlv_current_sel].xtide_channel, 0);
break;
case HDD_BUS_ESDI: /* ESDI */
h = GetDlgItem(hdlg, IDT_1722);
@@ -2080,7 +2080,7 @@ static void recalc_location_controls(HWND hdlg, int is_add_dlg)
h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL);
ShowWindow(h, SW_SHOW);
EnableWindow(h, TRUE);
SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdc.esdi_channel : temp_hdc[hdlv_current_sel].esdi_channel, 0);
SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.esdi_channel : temp_hdd[hdlv_current_sel].esdi_channel, 0);
break;
case HDD_BUS_IDE_PIO_ONLY: /* IDE (PIO-only) */
case HDD_BUS_IDE_PIO_AND_DMA: /* IDE (PIO and DMA) */
@@ -2091,7 +2091,7 @@ static void recalc_location_controls(HWND hdlg, int is_add_dlg)
h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE);
ShowWindow(h, SW_SHOW);
EnableWindow(h, TRUE);
SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdc.ide_channel : temp_hdc[hdlv_current_sel].ide_channel, 0);
SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.ide_channel : temp_hdd[hdlv_current_sel].ide_channel, 0);
break;
case HDD_BUS_SCSI: /* SCSI */
case HDD_BUS_SCSI_REMOVABLE: /* SCSI (removable) */
@@ -2105,12 +2105,12 @@ static void recalc_location_controls(HWND hdlg, int is_add_dlg)
h = GetDlgItem(hdlg, IDC_COMBO_HD_ID);
ShowWindow(h, SW_SHOW);
EnableWindow(h, TRUE);
SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdc.scsi_id : temp_hdc[hdlv_current_sel].scsi_id, 0);
SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.scsi_id : temp_hdd[hdlv_current_sel].scsi_id, 0);
h = GetDlgItem(hdlg, IDC_COMBO_HD_LUN);
ShowWindow(h, SW_SHOW);
EnableWindow(h, TRUE);
SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdc.scsi_lun : temp_hdc[hdlv_current_sel].scsi_lun, 0);
SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.scsi_lun : temp_hdd[hdlv_current_sel].scsi_lun, 0);
break;
}
}
@@ -2151,41 +2151,41 @@ static void recalc_next_free_id(HWND hdlg)
next_free_id = -1;
for (i = 0; i < HDC_NUM; i++)
for (i = 0; i < HDD_NUM; i++)
{
if (temp_hdc[i].bus == HDD_BUS_MFM)
if (temp_hdd[i].bus == HDD_BUS_MFM)
{
c_mfm++;
}
else if (temp_hdc[i].bus == HDD_BUS_ESDI)
else if (temp_hdd[i].bus == HDD_BUS_ESDI)
{
c_esdi++;
}
else if (temp_hdc[i].bus == HDD_BUS_XTIDE)
else if (temp_hdd[i].bus == HDD_BUS_XTIDE)
{
c_xtide++;
}
else if (temp_hdc[i].bus == HDD_BUS_IDE_PIO_ONLY)
else if (temp_hdd[i].bus == HDD_BUS_IDE_PIO_ONLY)
{
c_ide_pio++;
}
else if (temp_hdc[i].bus == HDD_BUS_IDE_PIO_AND_DMA)
else if (temp_hdd[i].bus == HDD_BUS_IDE_PIO_AND_DMA)
{
c_ide_dma++;
}
else if (temp_hdc[i].bus == HDD_BUS_SCSI)
else if (temp_hdd[i].bus == HDD_BUS_SCSI)
{
c_scsi++;
}
else if (temp_hdc[i].bus == HDD_BUS_SCSI_REMOVABLE)
else if (temp_hdd[i].bus == HDD_BUS_SCSI_REMOVABLE)
{
c_scsi++;
}
}
for (i = 0; i < HDC_NUM; i++)
for (i = 0; i < HDD_NUM; i++)
{
if (temp_hdc[i].bus == HDD_BUS_DISABLED)
if (temp_hdd[i].bus == HDD_BUS_DISABLED)
{
next_free_id = i;
break;
@@ -2246,59 +2246,59 @@ static void win_settings_hard_disks_update_item(HWND hwndList, int i, int column
if (column == 0)
{
switch(temp_hdc[i].bus)
switch(temp_hdd[i].bus)
{
case HDD_BUS_MFM:
wsprintf(szText, win_language_get_string_from_id(IDS_4608), temp_hdc[i].mfm_channel >> 1, temp_hdc[i].mfm_channel & 1);
wsprintf(szText, win_language_get_string_from_id(IDS_4608), temp_hdd[i].mfm_channel >> 1, temp_hdd[i].mfm_channel & 1);
break;
case HDD_BUS_XTIDE:
wsprintf(szText, win_language_get_string_from_id(IDS_4609), temp_hdc[i].xtide_channel >> 1, temp_hdc[i].xtide_channel & 1);
wsprintf(szText, win_language_get_string_from_id(IDS_4609), temp_hdd[i].xtide_channel >> 1, temp_hdd[i].xtide_channel & 1);
break;
case HDD_BUS_ESDI:
wsprintf(szText, win_language_get_string_from_id(IDS_4610), temp_hdc[i].esdi_channel >> 1, temp_hdc[i].esdi_channel & 1);
wsprintf(szText, win_language_get_string_from_id(IDS_4610), temp_hdd[i].esdi_channel >> 1, temp_hdd[i].esdi_channel & 1);
break;
case HDD_BUS_IDE_PIO_ONLY:
wsprintf(szText, win_language_get_string_from_id(IDS_4611), temp_hdc[i].ide_channel >> 1, temp_hdc[i].ide_channel & 1);
wsprintf(szText, win_language_get_string_from_id(IDS_4611), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1);
break;
case HDD_BUS_IDE_PIO_AND_DMA:
wsprintf(szText, win_language_get_string_from_id(IDS_4612), temp_hdc[i].ide_channel >> 1, temp_hdc[i].ide_channel & 1);
wsprintf(szText, win_language_get_string_from_id(IDS_4612), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1);
break;
case HDD_BUS_SCSI:
wsprintf(szText, win_language_get_string_from_id(IDS_4613), temp_hdc[i].scsi_id, temp_hdc[i].scsi_lun);
wsprintf(szText, win_language_get_string_from_id(IDS_4613), temp_hdd[i].scsi_id, temp_hdd[i].scsi_lun);
break;
case HDD_BUS_SCSI_REMOVABLE:
wsprintf(szText, win_language_get_string_from_id(IDS_4614), temp_hdc[i].scsi_id, temp_hdc[i].scsi_lun);
wsprintf(szText, win_language_get_string_from_id(IDS_4614), temp_hdd[i].scsi_id, temp_hdd[i].scsi_lun);
break;
}
lvI.pszText = szText;
lvI.iImage = (temp_hdc[i].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0;
lvI.iImage = (temp_hdd[i].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0;
}
else if (column == 1)
{
lvI.pszText = temp_hdc[i].fn;
lvI.pszText = temp_hdd[i].fn;
lvI.iImage = 0;
}
else if (column == 2)
{
wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdc[i].tracks);
wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdd[i].tracks);
lvI.pszText = szText;
lvI.iImage = 0;
}
else if (column == 3)
{
wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdc[i].hpc);
wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdd[i].hpc);
lvI.pszText = szText;
lvI.iImage = 0;
}
else if (column == 4)
{
wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdc[i].spt);
wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdd[i].spt);
lvI.pszText = szText;
lvI.iImage = 0;
}
else if (column == 5)
{
wsprintf(szText, win_language_get_string_from_id(IDS_4098), (temp_hdc[i].tracks * temp_hdc[i].hpc * temp_hdc[i].spt) >> 11);
wsprintf(szText, win_language_get_string_from_id(IDS_4098), (temp_hdd[i].tracks * temp_hdd[i].hpc * temp_hdd[i].spt) >> 11);
lvI.pszText = szText;
lvI.iImage = 0;
}
@@ -2324,39 +2324,39 @@ static BOOL win_settings_hard_disks_recalc_list(HWND hwndList)
lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
lvI.stateMask = lvI.iSubItem = lvI.state = 0;
for (i = 0; i < HDC_NUM; i++)
for (i = 0; i < HDD_NUM; i++)
{
if (temp_hdc[i].bus > 0)
if (temp_hdd[i].bus > 0)
{
hdc_id_to_listview_index[i] = j;
lvI.iSubItem = 0;
switch(temp_hdc[i].bus)
switch(temp_hdd[i].bus)
{
case HDD_BUS_MFM:
wsprintf(szText, win_language_get_string_from_id(IDS_4608), temp_hdc[i].mfm_channel >> 1, temp_hdc[i].mfm_channel & 1);
wsprintf(szText, win_language_get_string_from_id(IDS_4608), temp_hdd[i].mfm_channel >> 1, temp_hdd[i].mfm_channel & 1);
break;
case HDD_BUS_XTIDE:
wsprintf(szText, win_language_get_string_from_id(IDS_4609), temp_hdc[i].xtide_channel >> 1, temp_hdc[i].xtide_channel & 1);
wsprintf(szText, win_language_get_string_from_id(IDS_4609), temp_hdd[i].xtide_channel >> 1, temp_hdd[i].xtide_channel & 1);
break;
case HDD_BUS_ESDI:
wsprintf(szText, win_language_get_string_from_id(IDS_4610), temp_hdc[i].esdi_channel >> 1, temp_hdc[i].esdi_channel & 1);
wsprintf(szText, win_language_get_string_from_id(IDS_4610), temp_hdd[i].esdi_channel >> 1, temp_hdd[i].esdi_channel & 1);
break;
case HDD_BUS_IDE_PIO_ONLY:
wsprintf(szText, win_language_get_string_from_id(IDS_4611), temp_hdc[i].ide_channel >> 1, temp_hdc[i].ide_channel & 1);
wsprintf(szText, win_language_get_string_from_id(IDS_4611), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1);
break;
case HDD_BUS_IDE_PIO_AND_DMA:
wsprintf(szText, win_language_get_string_from_id(IDS_4612), temp_hdc[i].ide_channel >> 1, temp_hdc[i].ide_channel & 1);
wsprintf(szText, win_language_get_string_from_id(IDS_4612), temp_hdd[i].ide_channel >> 1, temp_hdd[i].ide_channel & 1);
break;
case HDD_BUS_SCSI:
wsprintf(szText, win_language_get_string_from_id(IDS_4613), temp_hdc[i].scsi_id, temp_hdc[i].scsi_lun);
wsprintf(szText, win_language_get_string_from_id(IDS_4613), temp_hdd[i].scsi_id, temp_hdd[i].scsi_lun);
break;
case HDD_BUS_SCSI_REMOVABLE:
wsprintf(szText, win_language_get_string_from_id(IDS_4614), temp_hdc[i].scsi_id, temp_hdc[i].scsi_lun);
wsprintf(szText, win_language_get_string_from_id(IDS_4614), temp_hdd[i].scsi_id, temp_hdd[i].scsi_lun);
break;
}
lvI.pszText = szText;
lvI.iItem = j;
lvI.iImage = (temp_hdc[i].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0;
lvI.iImage = (temp_hdd[i].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0;
if (ListView_InsertItem(hwndList, &lvI) == -1)
{
@@ -2364,7 +2364,7 @@ static BOOL win_settings_hard_disks_recalc_list(HWND hwndList)
}
lvI.iSubItem = 1;
lvI.pszText = temp_hdc[i].fn;
lvI.pszText = temp_hdd[i].fn;
lvI.iItem = j;
lvI.iImage = 0;
@@ -2374,7 +2374,7 @@ static BOOL win_settings_hard_disks_recalc_list(HWND hwndList)
}
lvI.iSubItem = 2;
wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdc[i].tracks);
wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdd[i].tracks);
lvI.pszText = szText;
lvI.iItem = j;
lvI.iImage = 0;
@@ -2385,7 +2385,7 @@ static BOOL win_settings_hard_disks_recalc_list(HWND hwndList)
}
lvI.iSubItem = 3;
wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdc[i].hpc);
wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdd[i].hpc);
lvI.pszText = szText;
lvI.iItem = j;
lvI.iImage = 0;
@@ -2396,7 +2396,7 @@ static BOOL win_settings_hard_disks_recalc_list(HWND hwndList)
}
lvI.iSubItem = 4;
wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdc[i].spt);
wsprintf(szText, win_language_get_string_from_id(IDS_4098), temp_hdd[i].spt);
lvI.pszText = szText;
lvI.iItem = j;
lvI.iImage = 0;
@@ -2407,7 +2407,7 @@ static BOOL win_settings_hard_disks_recalc_list(HWND hwndList)
}
lvI.iSubItem = 5;
wsprintf(szText, win_language_get_string_from_id(IDS_4098), (temp_hdc[i].tracks * temp_hdc[i].hpc * temp_hdc[i].spt) >> 11);
wsprintf(szText, win_language_get_string_from_id(IDS_4098), (temp_hdd[i].tracks * temp_hdd[i].hpc * temp_hdd[i].spt) >> 11);
lvI.pszText = szText;
lvI.iItem = j;
lvI.iImage = 0;
@@ -2523,7 +2523,7 @@ uint64_t selection = 127;
uint64_t spt, hpc, tracks, size;
wchar_t hd_file_name[512];
static hard_disk_t *hdc_ptr;
static hard_disk_t *hdd_ptr;
static int hdconf_initialize_hdt_combo(HWND hdlg)
{
@@ -2538,11 +2538,11 @@ static int hdconf_initialize_hdt_combo(HWND hdlg)
h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE);
for (i = 0; i < 127; i++)
{
temp_size = hdt[i][0] * hdt[i][1] * hdt[i][2];
temp_size = hdd_table[i][0] * hdd_table[i][1] * hdd_table[i][2];
size_mb = temp_size >> 11;
wsprintf(szText, win_language_get_string_from_id(IDS_2157), size_mb, hdt[i][0], hdt[i][1], hdt[i][2]);
wsprintf(szText, win_language_get_string_from_id(IDS_2157), size_mb, hdd_table[i][0], hdd_table[i][1], hdd_table[i][2]);
SendMessage(h, CB_ADDSTRING, 0, (LPARAM) szText);
if ((tracks == hdt[i][0]) && (hpc == hdt[i][1]) && (spt == hdt[i][2]))
if ((tracks == hdd_table[i][0]) && (hpc == hdd_table[i][1]) && (spt == hdd_table[i][2]))
{
selection = i;
}
@@ -2562,7 +2562,7 @@ static void recalc_selection(HWND hdlg)
h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE);
for (i = 0; i < 127; i++)
{
if ((tracks == hdt[i][0]) && (hpc == hdt[i][1]) && (spt == hdt[i][2]))
if ((tracks == hdd_table[i][0]) && (hpc == hdd_table[i][1]) && (spt == hdd_table[i][2]))
{
selection = i;
}
@@ -2599,11 +2599,11 @@ static BOOL CALLBACK win_settings_hard_disks_add_proc(HWND hdlg, UINT message, W
if (existing & 2)
{
next_free_id = (existing >> 3) & 0x1f;
hdc_ptr = &(hdc[next_free_id]);
hdd_ptr = &(hdd[next_free_id]);
}
else
{
hdc_ptr = &(temp_hdc[next_free_id]);
hdd_ptr = &(temp_hdd[next_free_id]);
}
SetWindowText(hdlg, win_language_get_string_from_id((existing & 1) ? IDS_4103 : IDS_4102));
@@ -2640,17 +2640,17 @@ static BOOL CALLBACK win_settings_hard_disks_add_proc(HWND hdlg, UINT message, W
h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS);
if (existing & 2)
{
hdc_ptr->bus = HDD_BUS_SCSI_REMOVABLE;
hdd_ptr->bus = HDD_BUS_SCSI_REMOVABLE;
max_spt = 99;
max_hpc = 255;
}
else
{
hdc_ptr->bus = HDD_BUS_IDE_PIO_ONLY;
hdd_ptr->bus = HDD_BUS_IDE_PIO_ONLY;
max_spt = 63;
max_hpc = 16;
}
SendMessage(h, CB_SETCURSEL, hdc_ptr->bus, 0);
SendMessage(h, CB_SETCURSEL, hdd_ptr->bus, 0);
max_tracks = 266305;
recalc_location_controls(hdlg, 1);
if (existing & 2)
@@ -2675,7 +2675,7 @@ static BOOL CALLBACK win_settings_hard_disks_add_proc(HWND hdlg, UINT message, W
/* Set the file name edit box contents to our existing parameters. */
h = GetDlgItem(hdlg, IDC_EDIT_HD_FILE_NAME);
SendMessage(h, WM_SETTEXT, 0, (LPARAM) hdc[next_free_id].fn);
SendMessage(h, WM_SETTEXT, 0, (LPARAM) hdd[next_free_id].fn);
}
else
{
@@ -2700,73 +2700,73 @@ static BOOL CALLBACK win_settings_hard_disks_add_proc(HWND hdlg, UINT message, W
if (!(existing & 2))
{
h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS);
hdc_ptr->bus = SendMessage(h, CB_GETCURSEL, 0, 0) + 1;
hdd_ptr->bus = SendMessage(h, CB_GETCURSEL, 0, 0) + 1;
}
/* Make sure no file name is allowed with removable SCSI hard disks. */
if ((wcslen(hd_file_name) == 0) && (hdc_ptr->bus != HDD_BUS_SCSI_REMOVABLE))
if ((wcslen(hd_file_name) == 0) && (hdd_ptr->bus != HDD_BUS_SCSI_REMOVABLE))
{
hdc_ptr->bus = HDD_BUS_DISABLED;
hdd_ptr->bus = HDD_BUS_DISABLED;
msgbox_error(hwndParentDialog, IDS_4112);
return TRUE;
}
else if ((wcslen(hd_file_name) == 0) && (hdc_ptr->bus == HDD_BUS_SCSI_REMOVABLE))
else if ((wcslen(hd_file_name) == 0) && (hdd_ptr->bus == HDD_BUS_SCSI_REMOVABLE))
{
/* Mark hard disk added but return empty - it will signify the disk was ejected. */
hdc_ptr->spt = hdc_ptr->hpc = hdc_ptr->tracks = 0;
memset(hdc_ptr->fn, 0, sizeof(hdc_ptr->fn));
hdd_ptr->spt = hdd_ptr->hpc = hdd_ptr->tracks = 0;
memset(hdd_ptr->fn, 0, sizeof(hdd_ptr->fn));
goto hd_add_ok_common;
}
get_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, &(hdc_ptr->spt));
get_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, &(hdc_ptr->hpc));
get_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, &(hdc_ptr->tracks));
spt = hdc_ptr->spt;
hpc = hdc_ptr->hpc;
tracks = hdc_ptr->tracks;
get_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, &(hdd_ptr->spt));
get_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, &(hdd_ptr->hpc));
get_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, &(hdd_ptr->tracks));
spt = hdd_ptr->spt;
hpc = hdd_ptr->hpc;
tracks = hdd_ptr->tracks;
if (existing & 2)
{
if (hdc_ptr->bus == HDD_BUS_SCSI_REMOVABLE)
if (hdd_ptr->bus == HDD_BUS_SCSI_REMOVABLE)
{
memset(hdc_ptr->prev_fn, 0, sizeof(hdc_ptr->prev_fn));
wcscpy(hdc_ptr->prev_fn, hdc_ptr->fn);
memset(hdd_ptr->prev_fn, 0, sizeof(hdd_ptr->prev_fn));
wcscpy(hdd_ptr->prev_fn, hdd_ptr->fn);
}
}
else
{
switch(hdc_ptr->bus)
switch(hdd_ptr->bus)
{
case HDD_BUS_MFM:
h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL);
hdc_ptr->mfm_channel = SendMessage(h, CB_GETCURSEL, 0, 0);
hdd_ptr->mfm_channel = SendMessage(h, CB_GETCURSEL, 0, 0);
break;
case HDD_BUS_ESDI:
h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL);
hdc_ptr->esdi_channel = SendMessage(h, CB_GETCURSEL, 0, 0);
hdd_ptr->esdi_channel = SendMessage(h, CB_GETCURSEL, 0, 0);
break;
case HDD_BUS_XTIDE:
h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL);
hdc_ptr->xtide_channel = SendMessage(h, CB_GETCURSEL, 0, 0);
hdd_ptr->xtide_channel = SendMessage(h, CB_GETCURSEL, 0, 0);
break;
case HDD_BUS_IDE_PIO_ONLY:
case HDD_BUS_IDE_PIO_AND_DMA:
h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE);
hdc_ptr->ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0);
hdd_ptr->ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0);
break;
case HDD_BUS_SCSI:
case HDD_BUS_SCSI_REMOVABLE:
h = GetDlgItem(hdlg, IDC_COMBO_HD_ID);
hdc_ptr->scsi_id = SendMessage(h, CB_GETCURSEL, 0, 0);
hdd_ptr->scsi_id = SendMessage(h, CB_GETCURSEL, 0, 0);
h = GetDlgItem(hdlg, IDC_COMBO_HD_LUN);
hdc_ptr->scsi_lun = SendMessage(h, CB_GETCURSEL, 0, 0);
hdd_ptr->scsi_lun = SendMessage(h, CB_GETCURSEL, 0, 0);
break;
}
}
memset(hdc_ptr->fn, 0, sizeof(hdc_ptr->fn));
wcscpy(hdc_ptr->fn, hd_file_name);
memset(hdd_ptr->fn, 0, sizeof(hdd_ptr->fn));
wcscpy(hdd_ptr->fn, hd_file_name);
sector_size = 512;
@@ -2854,7 +2854,7 @@ hd_add_ok_common:
hard_disk_added = 0;
if (!(existing & 2))
{
hdc_ptr->bus = HDD_BUS_DISABLED;
hdd_ptr->bus = HDD_BUS_DISABLED;
}
EndDialog(hdlg, 0);
return TRUE;
@@ -3103,9 +3103,9 @@ hdd_add_file_open_error:
if ((temp != selection) && (temp != 127) && (temp != 128))
{
selection = temp;
tracks = hdt[selection][0];
hpc = hdt[selection][1];
spt = hdt[selection][2];
tracks = hdd_table[selection][0];
hpc = hdd_table[selection][1];
spt = hdd_table[selection][2];
size = (tracks * hpc * spt) << 9;
set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks);
set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc);
@@ -3167,14 +3167,14 @@ hdd_add_file_open_error:
recalc_location_controls(hdlg, 1);
h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS);
b = SendMessage(h,CB_GETCURSEL,0,0) + 1;
if (b == hdc_ptr->bus)
if (b == hdd_ptr->bus)
{
goto hd_add_bus_skip;
}
hdc_ptr->bus = b;
hdd_ptr->bus = b;
switch(hdc_ptr->bus)
switch(hdd_ptr->bus)
{
case HDD_BUS_DISABLED:
default:
@@ -3226,7 +3226,7 @@ hdd_add_file_open_error:
break;
}
if ((hdc_ptr->bus == HDD_BUS_SCSI_REMOVABLE) && !chs_enabled)
if ((hdd_ptr->bus == HDD_BUS_SCSI_REMOVABLE) && !chs_enabled)
{
h = GetDlgItem(hdlg, IDC_EDIT_HD_SPT);
EnableWindow(h, TRUE);
@@ -3239,7 +3239,7 @@ hdd_add_file_open_error:
h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE);
EnableWindow(h, TRUE);
}
else if ((hdc_ptr->bus != HDD_BUS_SCSI_REMOVABLE) && !chs_enabled)
else if ((hdd_ptr->bus != HDD_BUS_SCSI_REMOVABLE) && !chs_enabled)
{
h = GetDlgItem(hdlg, IDC_EDIT_HD_SPT);
EnableWindow(h, FALSE);
@@ -3330,7 +3330,7 @@ static BOOL CALLBACK win_settings_hard_disks_proc(HWND hdlg, UINT message, WPARA
ListView_SetItemState(h, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x000F);
hdlv_current_sel = 0;
h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS);
SendMessage(h, CB_SETCURSEL, temp_hdc[0].bus - 1, 0);
SendMessage(h, CB_SETCURSEL, temp_hdd[0].bus - 1, 0);
}
else
{
@@ -3365,7 +3365,7 @@ static BOOL CALLBACK win_settings_hard_disks_proc(HWND hdlg, UINT message, WPARA
}
ignore_change = 1;
h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS);
SendMessage(h, CB_SETCURSEL, temp_hdc[hdlv_current_sel].bus - 1, 0);
SendMessage(h, CB_SETCURSEL, temp_hdd[hdlv_current_sel].bus - 1, 0);
recalc_location_controls(hdlg, 0);
ignore_change = 0;
}
@@ -3383,11 +3383,11 @@ static BOOL CALLBACK win_settings_hard_disks_proc(HWND hdlg, UINT message, WPARA
ignore_change = 1;
h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS);
b = SendMessage(h, CB_GETCURSEL, 0, 0) + 1;
if (b == temp_hdc[hdlv_current_sel].bus)
if (b == temp_hdd[hdlv_current_sel].bus)
{
goto hd_bus_skip;
}
temp_hdc[hdlv_current_sel].bus = b;
temp_hdd[hdlv_current_sel].bus = b;
recalc_location_controls(hdlg, 0);
h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS);
win_settings_hard_disks_update_item(h, hdlv_current_sel, 0);
@@ -3403,17 +3403,17 @@ hd_bus_skip:
ignore_change = 1;
h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL);
if (temp_hdc[hdlv_current_sel].bus == HDD_BUS_MFM)
if (temp_hdd[hdlv_current_sel].bus == HDD_BUS_MFM)
{
temp_hdc[hdlv_current_sel].mfm_channel = SendMessage(h, CB_GETCURSEL, 0, 0);
temp_hdd[hdlv_current_sel].mfm_channel = SendMessage(h, CB_GETCURSEL, 0, 0);
}
else if (temp_hdc[hdlv_current_sel].bus == HDD_BUS_ESDI)
else if (temp_hdd[hdlv_current_sel].bus == HDD_BUS_ESDI)
{
temp_hdc[hdlv_current_sel].esdi_channel = SendMessage(h, CB_GETCURSEL, 0, 0);
temp_hdd[hdlv_current_sel].esdi_channel = SendMessage(h, CB_GETCURSEL, 0, 0);
}
else if (temp_hdc[hdlv_current_sel].bus == HDD_BUS_XTIDE)
else if (temp_hdd[hdlv_current_sel].bus == HDD_BUS_XTIDE)
{
temp_hdc[hdlv_current_sel].xtide_channel = SendMessage(h, CB_GETCURSEL, 0, 0);
temp_hdd[hdlv_current_sel].xtide_channel = SendMessage(h, CB_GETCURSEL, 0, 0);
}
h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS);
win_settings_hard_disks_update_item(h, hdlv_current_sel, 0);
@@ -3428,7 +3428,7 @@ hd_bus_skip:
ignore_change = 1;
h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE);
temp_hdc[hdlv_current_sel].ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0);
temp_hdd[hdlv_current_sel].ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0);
h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS);
win_settings_hard_disks_update_item(h, hdlv_current_sel, 0);
ignore_change = 0;
@@ -3442,7 +3442,7 @@ hd_bus_skip:
ignore_change = 1;
h = GetDlgItem(hdlg, IDC_COMBO_HD_ID);
temp_hdc[hdlv_current_sel].scsi_id = SendMessage(h, CB_GETCURSEL, 0, 0);
temp_hdd[hdlv_current_sel].scsi_id = SendMessage(h, CB_GETCURSEL, 0, 0);
h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS);
win_settings_hard_disks_update_item(h, hdlv_current_sel, 0);
ignore_change = 0;
@@ -3456,7 +3456,7 @@ hd_bus_skip:
ignore_change = 1;
h = GetDlgItem(hdlg, IDC_COMBO_HD_LUN);
temp_hdc[hdlv_current_sel].scsi_lun = SendMessage(h, CB_GETCURSEL, 0, 0);
temp_hdd[hdlv_current_sel].scsi_lun = SendMessage(h, CB_GETCURSEL, 0, 0);
h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS);
win_settings_hard_disks_update_item(h, hdlv_current_sel, 0);
ignore_change = 0;
@@ -3487,8 +3487,8 @@ hd_bus_skip:
return FALSE;
case IDC_BUTTON_HDD_REMOVE:
memcpy(temp_hdc[hdlv_current_sel].fn, L"", 4);
temp_hdc[hdlv_current_sel].bus = HDD_BUS_DISABLED; /* Only set the bus to zero, the list normalize code below will take care of turning this entire entry to a complete zero. */
memcpy(temp_hdd[hdlv_current_sel].fn, L"", 4);
temp_hdd[hdlv_current_sel].bus = HDD_BUS_DISABLED; /* Only set the bus to zero, the list normalize code below will take care of turning this entire entry to a complete zero. */
normalize_hd_list(); /* Normalize the hard disks so that non-disabled hard disks start from index 0, and so they are contiguous. */
ignore_change = 1;
h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS);
@@ -3499,7 +3499,7 @@ hd_bus_skip:
ListView_SetItemState(h, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x000F);
hdlv_current_sel = 0;
h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS);
SendMessage(h, CB_SETCURSEL, temp_hdc[0].bus - 1, 0);
SendMessage(h, CB_SETCURSEL, temp_hdd[0].bus - 1, 0);
}
else
{