Hard disk image handling is now unified in hdd_image.c/h;

Fixed some bugs regarding the Winbond W83877F Super I/O Chip and serial ports;
Added the President Award 430FX PCI machine, thank you ashenone for the BIOS.
This commit is contained in:
OBattler
2017-06-16 03:18:59 +02:00
parent 15b25157ee
commit 8dcc7176a9
19 changed files with 717 additions and 991 deletions

View File

@@ -8,7 +8,7 @@
# #
# Modified Makefile for Win32 (MinGW32) environment. # Modified Makefile for Win32 (MinGW32) environment.
# #
# Version: @(#)Makefile.mingw 1.0.28 2017/06/14 # Version: @(#)Makefile.mingw 1.0.29 2017/06/16
# #
# Authors: Miran Grca, <mgrca8@gmail.com> # Authors: Miran Grca, <mgrca8@gmail.com>
# Fred N. van Kempen, <decwiz@yahoo.com> # Fred N. van Kempen, <decwiz@yahoo.com>
@@ -143,6 +143,7 @@ SYSOBJ = model.o \
olivetti_m24.o ps1.o ps2.o ps2_mca.o \ olivetti_m24.o ps1.o ps2.o ps2_mca.o \
tandy_eeprom.o tandy_rom.o tandy_eeprom.o tandy_rom.o
DEVOBJ = bugger.o lpt.o serial.o \ DEVOBJ = bugger.o lpt.o serial.o \
fdc37c665.o fdc37c669.o fdc37c932fr.o \
pc87306.o sis85c471.o w83877f.o \ pc87306.o sis85c471.o w83877f.o \
keyboard.o \ keyboard.o \
keyboard_xt.o keyboard_at.o keyboard_pcjr.o \ keyboard_xt.o keyboard_at.o keyboard_pcjr.o \
@@ -151,9 +152,8 @@ DEVOBJ = bugger.o lpt.o serial.o \
joystick_standard.o joystick_ch_flightstick_pro.o \ joystick_standard.o joystick_ch_flightstick_pro.o \
joystick_sw_pad.o joystick_tm_fcs.o \ joystick_sw_pad.o joystick_tm_fcs.o \
mouse.o mouse_serial.o mouse_ps2.o mouse_bus.o \ mouse.o mouse_serial.o mouse_ps2.o mouse_bus.o \
fdd.o fdc.o \ fdd.o fdc.o fdi2raw.o \
fdc37c665.o fdc37c669.o fdc37c932fr.o fdi2raw.o \ hdd.o hdd_image.o \
hdd.o \
mfm_at.o mfm_xebec.o hdd_esdi.o ide.o xtide.o piix.o \ mfm_at.o mfm_xebec.o hdd_esdi.o ide.o xtide.o piix.o \
disc.o \ disc.o \
disc_86f.o disc_fdi.o disc_imd.o disc_img.o \ disc_86f.o disc_fdi.o disc_imd.o disc_img.o \
@@ -338,8 +338,10 @@ gameport.o: ibm.h cpu/cpu.h device.h io.h timer.h gameport.h \
hdd.o: ibm.h cpu/cpu.h device.h hdd.h model.h hdd_esdi.h \ hdd.o: ibm.h cpu/cpu.h device.h hdd.h model.h hdd_esdi.h \
mfm_at.h mfm_xebec.h xtide.h mfm_at.h mfm_xebec.h xtide.h
hdd_esdi.o: ibm.h device.h dma.h io.h mca.h mem.h pic.h rom.h \ hdd_image.o: ibm.h ide.h hdd_image.h
timer.h hdd_esdi.h
hdd_esdi.o: ibm.h device.h dma.h hdd_image.h io.h mca.h mem.h \
pic.h rom.h timer.h hdd_esdi.h
headland.o: ibm.h cpu/cpu.h io.h mem.h headland.h headland.o: ibm.h cpu/cpu.h io.h mem.h headland.h
@@ -357,7 +359,7 @@ i440fx.o: ibm.h io.h mem.h pci.h i440fx.h
i82335.o: ibm.h io.h mem.h i82335.o: ibm.h io.h mem.h
ide.o: 86box.h cdrom.h ibm.h io.h pic.h timer.h cdrom.h scsi.h ide.h ide.o: 86box.h cdrom.h hdd_image.h ibm.h io.h pic.h timer.h cdrom.h scsi.h ide.h
intel.o: ibm.h cpu/cpu.h io.h mem.h pit.h timer.h intel.h intel.o: ibm.h cpu/cpu.h io.h mem.h pit.h timer.h intel.h
@@ -410,9 +412,9 @@ mem.o: ibm.h cpu/cpu.h cpu/x86_ops.h cpu/x86.h config.h \
memregs.o: ibm.h io.h memregs.h memregs.o: ibm.h io.h memregs.h
mfm_at.o: ibm.h device.h io.h pic.h timer.h mfm_at.h mfm_at.o: ibm.h device.h hdd_image.h io.h pic.h timer.h mfm_at.h
mfm_xebec.o: ibm.h device.h dma.h io.h mem.h pic.h rom.h timer.h mfm_xebec.h mfm_xebec.o: ibm.h device.h dma.h hdd_image.h io.h mem.h pic.h rom.h timer.h mfm_xebec.h
model.o: ibm.h cpu/cpu.h io.h mem.h rom.h device.h model.h mouse.h \ model.o: ibm.h cpu/cpu.h io.h mem.h rom.h device.h model.h mouse.h \
mouse_ps2.h cdrom.h acerm3a.h ali1429.h amstrad.h compaq.h \ mouse_ps2.h cdrom.h acerm3a.h ali1429.h amstrad.h compaq.h \
@@ -497,8 +499,8 @@ scsi_aha154x.o: ibm.h io.h mca.h mem.h mca.h rom.h dma.h pic.h timer.h \
scsi_buslogic.o: ibm.h io.h mem.h rom.h dma.h pic.h pci.h timer.h \ scsi_buslogic.o: ibm.h io.h mem.h rom.h dma.h pic.h pci.h timer.h \
device.h scsi.h scsi_disk.h cdrom.h scsi_buslogic.h device.h scsi.h scsi_disk.h cdrom.h scsi_buslogic.h
scsi_disk.o: 86box.h cdrom.h ibm.h ide.h piix.h scsi.h scsi_disk.h \ scsi_disk.o: 86box.h cdrom.h hdd_image.h ibm.h ide.h piix.h scsi.h \
timer.h win/plat_iodev.h scsi_disk.h timer.h win/plat_iodev.h
serial.o: ibm.h io.h pic.h timer.h serial.h plat_serial.h serial.o: ibm.h io.h pic.h timer.h serial.h plat_serial.h

View File

@@ -45,6 +45,7 @@ static void write_lock(uint8_t val)
static void ide_handler() static void ide_handler()
{ {
#if 0
uint16_t or_value = 0; uint16_t or_value = 0;
if ((romset == ROM_440FX) || (romset == ROM_R418) || (romset == ROM_MB500N)) if ((romset == ROM_440FX) || (romset == ROM_R418) || (romset == ROM_MB500N))
{ {
@@ -65,6 +66,7 @@ static void ide_handler()
ide_set_side(0, 0x376 | or_value); ide_set_side(0, 0x376 | or_value);
ide_pri_enable_ex(); ide_pri_enable_ex();
} }
#endif
} }
static void set_com34_addr() static void set_com34_addr()

View File

@@ -1,17 +1,9 @@
#define _LARGEFILE_SOURCE #include <malloc.h>
#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include "ibm.h" #include "ibm.h"
#include "device.h" #include "device.h"
#include "dma.h" #include "dma.h"
#include "hdd_image.h"
#include "io.h" #include "io.h"
#include "mca.h" #include "mca.h"
#include "mem.h" #include "mem.h"
@@ -30,7 +22,8 @@ typedef struct esdi_drive_t
int spt, hpc; int spt, hpc;
int tracks; int tracks;
int sectors; int sectors;
FILE *hdfile; int present;
int hdc_num;
} esdi_drive_t; } esdi_drive_t;
typedef struct esdi_t typedef struct esdi_t
@@ -395,7 +388,7 @@ static void esdi_callback(void *p)
case CMD_READ: case CMD_READ:
ESDI_DRIVE_ONLY(); ESDI_DRIVE_ONLY();
if (!drive->hdfile) if (!drive->present)
{ {
device_not_present(esdi); device_not_present(esdi);
return; return;
@@ -431,8 +424,7 @@ static void esdi_callback(void *p)
{ {
if (esdi->rba >= drive->sectors) if (esdi->rba >= drive->sectors)
fatal("Read past end of drive\n"); fatal("Read past end of drive\n");
fseek(drive->hdfile, esdi->rba * 512, SEEK_SET); hdd_image_read(drive->hdc_num, esdi->rba, 1, (uint8_t *) esdi->data);
fread(esdi->data, 512, 1, drive->hdfile);
update_status_bar_icon(SB_HDD | HDD_BUS_RLL, 1); update_status_bar_icon(SB_HDD | HDD_BUS_RLL, 1);
} }
while (esdi->data_pos < 256) while (esdi->data_pos < 256)
@@ -471,7 +463,7 @@ static void esdi_callback(void *p)
case CMD_WRITE_VERIFY: case CMD_WRITE_VERIFY:
ESDI_DRIVE_ONLY(); ESDI_DRIVE_ONLY();
if (!drive->hdfile) if (!drive->present)
{ {
device_not_present(esdi); device_not_present(esdi);
return; return;
@@ -518,8 +510,7 @@ static void esdi_callback(void *p)
if (esdi->rba >= drive->sectors) if (esdi->rba >= drive->sectors)
fatal("Write past end of drive\n"); fatal("Write past end of drive\n");
fseek(drive->hdfile, esdi->rba * 512, SEEK_SET); hdd_image_write(drive->hdc_num, esdi->rba, 1, (uint8_t *) esdi->data);
fwrite(esdi->data, 512, 1, drive->hdfile);
esdi->rba++; esdi->rba++;
esdi->sector_pos++; esdi->sector_pos++;
update_status_bar_icon(SB_HDD | HDD_BUS_RLL, 1); update_status_bar_icon(SB_HDD | HDD_BUS_RLL, 1);
@@ -545,7 +536,7 @@ static void esdi_callback(void *p)
case CMD_READ_VERIFY: case CMD_READ_VERIFY:
ESDI_DRIVE_ONLY(); ESDI_DRIVE_ONLY();
if (!drive->hdfile) if (!drive->present)
{ {
device_not_present(esdi); device_not_present(esdi);
return; return;
@@ -560,7 +551,7 @@ static void esdi_callback(void *p)
case CMD_SEEK: case CMD_SEEK:
ESDI_DRIVE_ONLY(); ESDI_DRIVE_ONLY();
if (!drive->hdfile) if (!drive->present)
{ {
device_not_present(esdi); device_not_present(esdi);
return; return;
@@ -575,7 +566,7 @@ static void esdi_callback(void *p)
case CMD_GET_DEV_CONFIG: case CMD_GET_DEV_CONFIG:
ESDI_DRIVE_ONLY(); ESDI_DRIVE_ONLY();
if (!drive->hdfile) if (!drive->present)
{ {
device_not_present(esdi); device_not_present(esdi);
return; return;
@@ -799,40 +790,22 @@ static void esdi_mca_write(int port, uint8_t val, void *p)
static void loadhd(esdi_t *esdi, int hdc_num, int d, const wchar_t *fn) static void loadhd(esdi_t *esdi, int hdc_num, int d, const wchar_t *fn)
{ {
esdi_drive_t *drive = &esdi->drives[d]; esdi_drive_t *drive = &esdi->drives[d];
int ret = 0;
if (drive->hdfile == NULL) ret = hdd_image_load(hdc_num);
{
/* Try to open existing hard disk image */ if (!ret)
drive->hdfile = _wfopen(fn, L"rb+"); {
if (drive->hdfile == NULL) drive->present = 0;
{ return;
/* Failed to open existing hard disk image */
if (errno == ENOENT)
{
/* Failed because it does not exist,
so try to create new file */
drive->hdfile = _wfopen(fn, L"wb+");
if (drive->hdfile == NULL)
{
pclog("Cannot create file '%s': %s",
fn, strerror(errno));
return;
}
}
else
{
/* Failed for another reason */
pclog("Cannot open file '%s': %s",
fn, strerror(errno));
return;
}
}
} }
drive->spt = hdc[hdc_num].spt; drive->spt = hdc[hdc_num].spt;
drive->hpc = hdc[hdc_num].hpc; drive->hpc = hdc[hdc_num].hpc;
drive->tracks = hdc[hdc_num].tracks; drive->tracks = hdc[hdc_num].tracks;
drive->sectors = hdc[hdc_num].spt * hdc[hdc_num].hpc * hdc[hdc_num].tracks; drive->sectors = hdc[hdc_num].spt * hdc[hdc_num].hpc * hdc[hdc_num].tracks;
drive->hdc_num = hdc_num;
drive->present = 1;
} }
static void *esdi_init() static void *esdi_init()
@@ -879,8 +852,7 @@ static void esdi_close(void *p)
{ {
esdi_drive_t *drive = &esdi->drives[d]; esdi_drive_t *drive = &esdi->drives[d];
if (drive->hdfile != NULL) hdd_image_close(drive->hdc_num);
fclose(drive->hdfile);
} }
free(esdi); free(esdi);

441
src/hdd_image.c Normal file
View File

@@ -0,0 +1,441 @@
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "ibm.h"
#include "ide.h"
#include "hdd_image.h"
typedef struct
{
FILE *file;
uint32_t base;
uint32_t last_sector;
uint8_t type;
uint8_t loaded;
} hdd_image_t;
hdd_image_t hdd_images[HDC_NUM];
static char empty_sector[512];
static char *empty_sector_1mb;
int hdd_image_do_log = 0;
void hdd_image_log(const char *format, ...)
{
#ifdef ENABLE_HDD_IMAGE_LOG
if (hdd_image_do_log)
{
va_list ap;
va_start(ap, format);
vprintf(format, ap);
va_end(ap);
fflush(stdout);
}
#endif
}
int image_is_hdi(const wchar_t *s)
{
int len;
wchar_t ext[5] = { 0, 0, 0, 0, 0 };
char *ws = (char *) s;
len = wcslen(s);
if ((len < 4) || (s[0] == L'.'))
{
return 0;
}
memcpy(ext, ws + ((len - 4) << 1), 8);
if (wcsicmp(ext, L".HDI") == 0)
{
return 1;
}
else
{
return 0;
}
}
int image_is_hdx(const wchar_t *s, int check_signature)
{
int len;
FILE *f;
uint64_t filelen;
uint64_t signature;
char *ws = (char *) s;
wchar_t ext[5] = { 0, 0, 0, 0, 0 };
len = wcslen(s);
if ((len < 4) || (s[0] == L'.'))
{
return 0;
}
memcpy(ext, ws + ((len - 4) << 1), 8);
if (wcsicmp(ext, L".HDX") == 0)
{
if (check_signature)
{
f = _wfopen(s, L"rb");
if (!f)
{
return 0;
}
fseeko64(f, 0, SEEK_END);
filelen = ftello64(f);
fseeko64(f, 0, SEEK_SET);
if (filelen < 44)
{
return 0;
}
fread(&signature, 1, 8, f);
fclose(f);
if (signature == 0xD778A82044445459ll)
{
return 1;
}
else
{
return 0;
}
}
else
{
return 1;
}
}
else
{
return 0;
}
}
int hdd_image_load(int id)
{
uint32_t sector_size = 512;
uint32_t zero = 0;
uint64_t signature = 0xD778A82044445459ll;
uint64_t full_size = 0;
uint64_t spt = 0, hpc = 0, tracks = 0;
int c;
uint64_t i = 0, s = 0, t = 0;
wchar_t *fn = hdc[id].fn;
memset(empty_sector, 0, sizeof(empty_sector));
hdd_images[id].base = 0;
hdd_images[id].loaded = 0;
if (hdd_images[id].file != NULL)
{
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
}
/* Try to open existing hard disk image */
if (fn[0] == '.')
{
hdd_image_log("File name starts with .\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
return 0;
}
hdd_images[id].file = _wfopen(fn, L"rb+");
if (hdd_images[id].file == NULL)
{
/* Failed to open existing hard disk image */
if (errno == ENOENT)
{
/* Failed because it does not exist,
so try to create new file */
if (hdc[id].wp)
{
hdd_image_log("A write-protected image must exist\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
return 0;
}
hdd_images[id].file = _wfopen(fn, L"wb+");
if (hdd_images[id].file == NULL)
{
hdd_image_log("Unable to open image\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
return 0;
}
else
{
if (image_is_hdi(fn))
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[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);
for (c = 0; c < 0x3f8; c++)
{
fwrite(&zero, 1, 4, hdd_images[id].file);
}
hdd_images[id].type = 1;
}
else if (image_is_hdx(fn, 0))
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[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(&zero, 1, 4, hdd_images[id].file);
fwrite(&zero, 1, 4, hdd_images[id].file);
hdd_images[id].type = 2;
}
else
{
hdd_images[id].type = 0;
}
hdd_images[id].last_sector = 0;
}
s = full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
goto prepare_new_hard_disk;
}
else
{
/* Failed for another reason */
hdd_image_log("Failed for another reason\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
return 0;
}
}
else
{
if (image_is_hdi(fn))
{
fseeko64(hdd_images[id].file, 0x8, SEEK_SET);
fread(&(hdd_images[id].base), 1, 4, hdd_images[id].file);
fseeko64(hdd_images[id].file, 0xC, SEEK_SET);
full_size = 0;
fread(&full_size, 1, 4, hdd_images[id].file);
fseeko64(hdd_images[id].file, 0x10, SEEK_SET);
fread(&sector_size, 1, 4, hdd_images[id].file);
if (sector_size != 512)
{
/* Sector size is not 512 */
hdd_image_log("HDI: Sector size is not 512\n");
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
memset(hdc[id].fn, 0, sizeof(hdc[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 ((spt != hdc[id].spt) || (hpc != hdc[id].hpc) || (tracks != hdc[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));
return 0;
}
}
hdc[id].spt = spt;
hdc[id].hpc = hpc;
hdc[id].tracks = tracks;
hdd_images[id].type = 1;
}
else if (image_is_hdx(fn, 1))
{
hdd_images[id].base = 0x28;
fseeko64(hdd_images[id].file, 8, SEEK_SET);
fread(&full_size, 1, 8, hdd_images[id].file);
fseeko64(hdd_images[id].file, 0x10, SEEK_SET);
fread(&sector_size, 1, 4, hdd_images[id].file);
if (sector_size != 512)
{
/* Sector size is not 512 */
hdd_image_log("HDX: Sector size is not 512\n");
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
memset(hdc[id].fn, 0, sizeof(hdc[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 ((spt != hdc[id].spt) || (hpc != hdc[id].hpc) || (tracks != hdc[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));
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_images[id].type = 2;
}
else
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
hdd_images[id].type = 0;
}
}
fseeko64(hdd_images[id].file, 0, SEEK_END);
if (ftello64(hdd_images[id].file) < (full_size + hdd_images[id].base))
{
s = (full_size + hdd_images[id].base) - ftello64(hdd_images[id].file);
prepare_new_hard_disk:
s >>= 9;
t = (s >> 11) << 11;
s -= t;
t >>= 11;
empty_sector_1mb = (char *) malloc(1048576);
memset(empty_sector_1mb, 0, 1048576);
if (s > 0)
{
for (i = 0; i < s; i++)
{
fwrite(empty_sector, 1, 512, hdd_images[id].file);
}
}
if (t > 0)
{
for (i = 0; i < t; i++)
{
fwrite(empty_sector_1mb, 1, 1045876, hdd_images[id].file);
}
}
free(empty_sector_1mb);
}
hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1;
return 1;
hdd_images[id].loaded = 1;
}
void hdd_image_seek(uint8_t id, uint32_t sector)
{
uint64_t addr = sector;
addr <<= 9;
addr += hdd_images[id].base;
fseeko64(hdd_images[id].file, addr, SEEK_SET);
}
void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
{
count <<= 9;
hdd_image_seek(id, sector);
memset(buffer, 0, count);
fread(buffer, 1, count, hdd_images[id].file);
}
void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
{
count <<= 9;
hdd_image_seek(id, sector);
fwrite(buffer, 1, count, hdd_images[id].file);
}
void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count)
{
int i = 0;
uint8_t *b;
b = (uint8_t *) malloc(512);
memset(b, 0, 512);
hdd_image_seek(id, sector);
for (i = 0; i < count; i++)
{
fwrite(b, 1, 512, hdd_images[id].file);
}
free(b);
}
uint32_t hdd_image_get_last_sector(uint8_t id)
{
return hdd_images[id].last_sector;
}
uint8_t hdd_image_get_type(uint8_t id)
{
return hdd_images[id].type;
}
void hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt)
{
if (hdd_images[id].type == 2)
{
hdc[id].at_hpc = hpc;
hdc[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);
}
}
void hdd_image_unload(uint8_t id, int fn_preserve)
{
if (wcslen(hdc[id].fn) == 0)
{
return;
}
if (hdd_images[id].loaded)
{
if (hdd_images[id].file != NULL)
{
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
}
}
hdd_images[id].last_sector = -1;
memset(hdc[id].prev_fn, 0, sizeof(hdc[id].prev_fn));
if (fn_preserve)
{
wcscpy(hdc[id].prev_fn, hdc[id].fn);
}
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
}
void hdd_image_close(uint8_t id)
{
if (hdd_images[id].file != NULL)
{
fclose(hdd_images[id].file);
hdd_images[id].file = NULL;
}
}

10
src/hdd_image.h Normal file
View File

@@ -0,0 +1,10 @@
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 void hdd_image_write(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 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);

View File

@@ -471,6 +471,8 @@ enum
ROM_S1668, /*Tyan Titan-Pro ATX / 440FX / AMI BIOS / SMC FDC37C669*/ ROM_S1668, /*Tyan Titan-Pro ATX / 440FX / AMI BIOS / SMC FDC37C669*/
ROM_IBMPS1_2133, ROM_IBMPS1_2133,
ROM_PRESIDENT, /*President Award 430FX PCI / 430FX / Award BIOS / Unknown Super I/O chip*/
ROM_MAX ROM_MAX
}; };

271
src/ide.c
View File

@@ -9,7 +9,7 @@
* Implementation of the IDE emulation for hard disks and ATAPI * Implementation of the IDE emulation for hard disks and ATAPI
* CD-ROM devices. * CD-ROM devices.
* *
* Version: @(#)ide.c 1.0.1 2017/06/03 * Version: @(#)ide.c 1.0.2 2017/06/16
* *
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/> * Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com> * Miran Grca, <mgrca8@gmail.com>
@@ -18,23 +18,14 @@
* Copyright 2016-2017 Miran Grca. * Copyright 2016-2017 Miran Grca.
* Copyright 2016-2017 TheCollector1995. * Copyright 2016-2017 TheCollector1995.
*/ */
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
#include <errno.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <wchar.h> #include <wchar.h>
#include "86box.h" #include "86box.h"
#include "cdrom.h" #include "cdrom.h"
#include "ibm.h" #include "ibm.h"
#include "hdd_image.h"
#include "io.h" #include "io.h"
#include "pic.h" #include "pic.h"
#include "timer.h" #include "timer.h"
@@ -163,79 +154,6 @@ int ide_drive_is_cdrom(IDE *ide)
} }
} }
int image_is_hdi(const wchar_t *s)
{
int len;
wchar_t ext[5] = { 0, 0, 0, 0, 0 };
char *ws = (char *) s;
len = wcslen(s);
if ((len < 4) || (s[0] == L'.'))
{
return 0;
}
memcpy(ext, ws + ((len - 4) << 1), 8);
if (wcsicmp(ext, L".HDI") == 0)
{
return 1;
}
else
{
return 0;
}
}
int image_is_hdx(const wchar_t *s, int check_signature)
{
int len;
FILE *f;
uint64_t filelen;
uint64_t signature;
char *ws = (char *) s;
wchar_t ext[5] = { 0, 0, 0, 0, 0 };
len = wcslen(s);
if ((len < 4) || (s[0] == L'.'))
{
return 0;
}
memcpy(ext, ws + ((len - 4) << 1), 8);
if (wcsicmp(ext, L".HDX") == 0)
{
if (check_signature)
{
f = _wfopen(s, L"rb");
if (!f)
{
return 0;
}
fseeko64(f, 0, SEEK_END);
filelen = ftello64(f);
fseeko64(f, 0, SEEK_SET);
if (filelen < 44)
{
return 0;
}
fread(&signature, 1, 8, f);
fclose(f);
if (signature == 0xD778A82044445459ll)
{
return 1;
}
else
{
return 0;
}
}
else
{
return 1;
}
}
else
{
return 0;
}
}
int ide_enable[5] = { 1, 1, 0, 0, 1 }; int ide_enable[5] = { 1, 1, 0, 0, 1 };
int ide_irq[5] = { 14, 15, 10, 11, 0 }; int ide_irq[5] = { 14, 15, 10, 11, 0 };
@@ -525,126 +443,22 @@ static void ide_next_sector(IDE *ide)
static void loadhd(IDE *ide, int d, const wchar_t *fn) static void loadhd(IDE *ide, int d, const wchar_t *fn)
{ {
uint32_t sector_size = 512; int ret = 0;
uint32_t zero = 0;
uint64_t signature = 0xD778A82044445459ll; ret = hdd_image_load(d);
uint64_t full_size = 0;
int c; if (!ret)
ide->base = 0;
ide->hdi = 0;
if (ide->hdfile == NULL)
{ {
/* Try to open existing hard disk image */ ide->type = IDE_NONE;
if (fn[0] == L'.') return;
{
ide->type = IDE_NONE;
return;
}
ide->hdfile = _wfopen(fn, L"rb+");
if (ide->hdfile == NULL)
{
/* Failed to open existing hard disk image */
if (errno == ENOENT)
{
/* Failed because it does not exist,
so try to create new file */
ide->hdfile = _wfopen(fn, L"wb+");
if (ide->hdfile == NULL)
{
ide->type = IDE_NONE;
return;
}
else
{
if (image_is_hdi(fn))
{
full_size = hdc[d].spt * hdc[d].hpc * hdc[d].tracks * 512;
ide->base = 0x1000;
ide->hdi = 1;
fwrite(&zero, 1, 4, ide->hdfile);
fwrite(&zero, 1, 4, ide->hdfile);
fwrite(&(ide->base), 1, 4, ide->hdfile);
fwrite(&full_size, 1, 4, ide->hdfile);
fwrite(&sector_size, 1, 4, ide->hdfile);
fwrite(&(hdc[d].spt), 1, 4, ide->hdfile);
fwrite(&(hdc[d].hpc), 1, 4, ide->hdfile);
fwrite(&(hdc[d].tracks), 1, 4, ide->hdfile);
for (c = 0; c < 0x3f8; c++)
{
fwrite(&zero, 1, 4, ide->hdfile);
}
}
else if (image_is_hdx(fn, 0))
{
full_size = hdc[d].spt * hdc[d].hpc * hdc[d].tracks * 512;
ide->base = 0x28;
ide->hdi = 2;
fwrite(&signature, 1, 8, ide->hdfile);
fwrite(&full_size, 1, 8, ide->hdfile);
fwrite(&sector_size, 1, 4, ide->hdfile);
fwrite(&(hdc[d].spt), 1, 4, ide->hdfile);
fwrite(&(hdc[d].hpc), 1, 4, ide->hdfile);
fwrite(&(hdc[d].tracks), 1, 4, ide->hdfile);
fwrite(&zero, 1, 4, ide->hdfile);
fwrite(&zero, 1, 4, ide->hdfile);
}
ide->hdc_num = d;
}
}
else
{
/* Failed for another reason */
ide->type = IDE_NONE;
return;
}
}
else
{
if (image_is_hdi(fn))
{
fseeko64(ide->hdfile, 0x8, SEEK_SET);
fread(&(ide->base), 1, 4, ide->hdfile);
fseeko64(ide->hdfile, 0x10, SEEK_SET);
fread(&sector_size, 1, 4, ide->hdfile);
if (sector_size != 512)
{
/* Sector size is not 512 */
fclose(ide->hdfile);
ide->type = IDE_NONE;
return;
}
fread(&(hdc[d].spt), 1, 4, ide->hdfile);
fread(&(hdc[d].hpc), 1, 4, ide->hdfile);
fread(&(hdc[d].tracks), 1, 4, ide->hdfile);
ide->hdi = 1;
}
else if (image_is_hdx(fn, 1))
{
ide->base = 0x28;
fseeko64(ide->hdfile, 0x10, SEEK_SET);
fread(&sector_size, 1, 4, ide->hdfile);
if (sector_size != 512)
{
/* Sector size is not 512 */
fclose(ide->hdfile);
ide->type = IDE_NONE;
return;
}
fread(&(hdc[d].spt), 1, 4, ide->hdfile);
fread(&(hdc[d].hpc), 1, 4, ide->hdfile);
fread(&(hdc[d].tracks), 1, 4, ide->hdfile);
fread(&(hdc[d].at_spt), 1, 4, ide->hdfile);
fread(&(hdc[d].at_hpc), 1, 4, ide->hdfile);
ide->hdi = 2;
}
}
} }
ide->spt = hdc[d].spt; ide->spt = hdc[d].spt;
ide->hpc = hdc[d].hpc; ide->hpc = hdc[d].hpc;
ide->tracks = hdc[d].tracks; ide->tracks = hdc[d].tracks;
ide->type = IDE_HDD; ide->type = IDE_HDD;
ide->hdc_num = d; ide->hdc_num = d;
ide->hdi = hdd_image_get_type(d);
} }
void ide_set_signature(IDE *ide) void ide_set_signature(IDE *ide)
@@ -771,11 +585,7 @@ void resetide(void)
{ {
ide_drives[d].channel = d; ide_drives[d].channel = d;
ide_drives[d].type = IDE_NONE; ide_drives[d].type = IDE_NONE;
if (ide_drives[d].hdfile != NULL) hdd_image_close(ide_drives[d].hdc_num);
{
fclose(ide_drives[d].hdfile);
ide_drives[d].hdfile = NULL;
}
if (ide_drive_is_cdrom(&ide_drives[d])) if (ide_drive_is_cdrom(&ide_drives[d]))
{ {
cdrom[atapi_cdrom_drives[d]].status = READY_STAT | DSC_STAT; cdrom[atapi_cdrom_drives[d]].status = READY_STAT | DSC_STAT;
@@ -856,13 +666,6 @@ void ide_write_data(int ide_board, uint32_t val, int length)
uint16_t *idebufferw = ide->buffer; uint16_t *idebufferw = ide->buffer;
uint32_t *idebufferl = (uint32_t *) ide->buffer; uint32_t *idebufferl = (uint32_t *) ide->buffer;
#if 0
if (ide_drive_is_cdrom(ide))
{
ide_log("CD-ROM write data: %04X\n", val);
}
#endif
if (ide->command == WIN_PACKETCMD) if (ide->command == WIN_PACKETCMD)
{ {
ide->pos = 0; ide->pos = 0;
@@ -1621,8 +1424,6 @@ int times30=0;
void callbackide(int ide_board) void callbackide(int ide_board)
{ {
IDE *ide, *ide_other; IDE *ide, *ide_other;
off64_t addr;
int c;
int64_t snum; int64_t snum;
int cdrom_id; int cdrom_id;
uint64_t full_size = 0; uint64_t full_size = 0;
@@ -1760,10 +1561,8 @@ void callbackide(int ide_board)
{ {
goto id_not_found; goto id_not_found;
} }
addr = ide_get_sector(ide) * 512;
fseeko64(ide->hdfile, ide->base + addr, SEEK_SET); hdd_image_read(ide->hdc_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
fread(ide->buffer, 512, 1, ide->hdfile);
ide->pos=0; ide->pos=0;
ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
@@ -1781,9 +1580,7 @@ void callbackide(int ide_board)
{ {
goto id_not_found; goto id_not_found;
} }
addr = ide_get_sector(ide) * 512; hdd_image_read(ide->hdc_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
fseeko64(ide->hdfile, addr, SEEK_SET);
fread(ide->buffer, 512, 1, ide->hdfile);
ide->pos=0; ide->pos=0;
if (ide_bus_master_read) if (ide_bus_master_read)
@@ -1831,9 +1628,7 @@ void callbackide(int ide_board)
goto id_not_found; goto id_not_found;
} }
addr = ide_get_sector(ide) * 512; hdd_image_read(ide->hdc_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
fseeko64(ide->hdfile, ide->base + addr, SEEK_SET);
fread(ide->buffer, 512, 1, ide->hdfile);
ide->pos=0; ide->pos=0;
ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
if (!ide->blockcount) if (!ide->blockcount)
@@ -1859,9 +1654,7 @@ void callbackide(int ide_board)
{ {
goto id_not_found; goto id_not_found;
} }
addr = ide_get_sector(ide) * 512; hdd_image_write(ide->hdc_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
fseeko64(ide->hdfile, ide->base + addr, SEEK_SET);
fwrite(ide->buffer, 512, 1, ide->hdfile);
ide_irq_raise(ide); ide_irq_raise(ide);
ide->secount = (ide->secount - 1) & 0xff; ide->secount = (ide->secount - 1) & 0xff;
if (ide->secount) if (ide->secount)
@@ -1898,9 +1691,7 @@ void callbackide(int ide_board)
else else
{ {
/*DMA successful*/ /*DMA successful*/
addr = ide_get_sector(ide) * 512; hdd_image_write(ide->hdc_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
fseeko64(ide->hdfile, ide->base + addr, SEEK_SET);
fwrite(ide->buffer, 512, 1, ide->hdfile);
ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
@@ -1931,9 +1722,7 @@ void callbackide(int ide_board)
{ {
goto id_not_found; goto id_not_found;
} }
addr = ide_get_sector(ide) * 512; hdd_image_write(ide->hdc_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
fseeko64(ide->hdfile, ide->base + addr, SEEK_SET);
fwrite(ide->buffer, 512, 1, ide->hdfile);
ide->blockcount++; ide->blockcount++;
if (ide->blockcount >= ide->blocksize || ide->secount == 1) if (ide->blockcount >= ide->blocksize || ide->secount == 1)
{ {
@@ -1980,13 +1769,8 @@ void callbackide(int ide_board)
{ {
goto id_not_found; goto id_not_found;
} }
addr = ide_get_sector(ide) * 512; hdd_image_zero(ide->hdc_num, ide_get_sector(ide), ide->secount);
fseeko64(ide->hdfile, ide->base + addr, SEEK_SET);
memset(ide->buffer, 0, 512);
for (c=0;c<ide->secount;c++)
{
fwrite(ide->buffer, 512, 1, ide->hdfile);
}
ide->atastat = READY_STAT | DSC_STAT; ide->atastat = READY_STAT | DSC_STAT;
ide_irq_raise(ide); ide_irq_raise(ide);
@@ -2019,14 +1803,7 @@ void callbackide(int ide_board)
full_size /= (ide->head+1); full_size /= (ide->head+1);
full_size /= ide->secount; full_size /= ide->secount;
ide->specify_success = 1; ide->specify_success = 1;
if (ide->hdi == 2) hdd_image_specify(ide->hdc_num, ide->head + 1, ide->secount);
{
hdc[ide->hdc_num].at_hpc = ide->head+1;
hdc[ide->hdc_num].at_spt = ide->secount;
fseeko64(ide->hdfile, 0x20, SEEK_SET);
fwrite(&(hdc[ide->hdc_num].at_spt), 1, 4, ide->hdfile);
fwrite(&(hdc[ide->hdc_num].at_hpc), 1, 4, ide->hdfile);
}
ide->spt=ide->secount; ide->spt=ide->secount;
ide->hpc=ide->head+1; ide->hpc=ide->head+1;
ide->atastat = READY_STAT | DSC_STAT; ide->atastat = READY_STAT | DSC_STAT;

View File

@@ -38,7 +38,6 @@ typedef struct {
int packetstatus; int packetstatus;
uint8_t asc; uint8_t asc;
int reset; int reset;
FILE *hdfile;
uint16_t buffer[65536]; uint16_t buffer[65536];
int irqstat; int irqstat;
int service; int service;

View File

@@ -700,6 +700,14 @@ int loadbios()
biosmask = 0x1ffff; biosmask = 0x1ffff;
return 1; return 1;
case ROM_PRESIDENT:
f = romfopen(L"roms/president/BIOS.BIN", L"rb");
if (!f) break;
fread(rom, 0x20000, 1, f);
fclose(f);
biosmask = 0x1ffff;
return 1;
case ROM_P54TP4XE: case ROM_P54TP4XE:
f = romfopen(L"roms/p54tp4xe/T15I0302.AWD", L"rb"); f = romfopen(L"roms/p54tp4xe/T15I0302.AWD", L"rb");
if (!f) break; if (!f) break;

View File

@@ -1,16 +1,7 @@
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
#include <errno.h>
#include <malloc.h> #include <malloc.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <wchar.h>
#include "ibm.h" #include "ibm.h"
#include "hdd_image.h"
#include "device.h" #include "device.h"
#include "io.h" #include "io.h"
#include "pic.h" #include "pic.h"
@@ -53,7 +44,8 @@ typedef struct mfm_drive_t
int cfg_spt; int cfg_spt;
int cfg_hpc; int cfg_hpc;
int current_cylinder; int current_cylinder;
FILE *hdfile; int present;
int hdc_num;
} mfm_drive_t; } mfm_drive_t;
typedef struct mfm_t typedef struct mfm_t
@@ -163,39 +155,21 @@ static void mfm_next_sector(mfm_t *mfm)
static void loadhd(mfm_t *mfm, int c, int d, const wchar_t *fn) static void loadhd(mfm_t *mfm, int c, int d, const wchar_t *fn)
{ {
mfm_drive_t *drive = &mfm->drives[c]; mfm_drive_t *drive = &mfm->drives[c];
int ret = 0;
if (drive->hdfile == NULL) ret = hdd_image_load(d);
{
/* Try to open existing hard disk image */ if (!ret)
drive->hdfile = _wfopen(fn, L"rb+"); {
if (drive->hdfile == NULL) drive->present = 0;
{ return;
/* Failed to open existing hard disk image */
if (errno == ENOENT)
{
/* Failed because it does not exist,
so try to create new file */
drive->hdfile = _wfopen(fn, L"wb+");
if (drive->hdfile == NULL)
{
pclog("Cannot create file '%s': %s",
fn, strerror(errno));
return;
}
}
else
{
/* Failed for another reason */
pclog("Cannot open file '%s': %s",
fn, strerror(errno));
return;
}
}
} }
drive->spt = hdc[d].spt; drive->spt = hdc[d].spt;
drive->hpc = hdc[d].hpc; drive->hpc = hdc[d].hpc;
drive->tracks = hdc[d].tracks; drive->tracks = hdc[d].tracks;
drive->hdc_num = d;
drive->present = 1;
} }
@@ -233,14 +207,14 @@ void mfm_write(uint16_t port, uint8_t val, void *p)
case 0x1F6: /* Drive/Head */ case 0x1F6: /* Drive/Head */
mfm->head = val & 0xF; mfm->head = val & 0xF;
mfm->drive_sel = (val & 0x10) ? 1 : 0; mfm->drive_sel = (val & 0x10) ? 1 : 0;
if (mfm->drives[mfm->drive_sel].hdfile == NULL) if (mfm->drives[mfm->drive_sel].present)
mfm->status = 0;
else
mfm->status = STAT_READY | STAT_DSC; mfm->status = STAT_READY | STAT_DSC;
else
mfm->status = 0;
return; return;
case 0x1F7: /* Command register */ case 0x1F7: /* Command register */
if (mfm->drives[mfm->drive_sel].hdfile == NULL) if (!mfm->drives[mfm->drive_sel].present)
fatal("Command on non-present drive\n"); fatal("Command on non-present drive\n");
mfm_irq_lower(mfm); mfm_irq_lower(mfm);
@@ -462,7 +436,6 @@ void mfm_callback(void *p)
mfm_t *mfm = (mfm_t *)p; mfm_t *mfm = (mfm_t *)p;
mfm_drive_t *drive = &mfm->drives[mfm->drive_sel]; mfm_drive_t *drive = &mfm->drives[mfm->drive_sel];
off64_t addr; off64_t addr;
int c;
mfm->callback = 0; mfm->callback = 0;
if (mfm->reset) if (mfm->reset)
@@ -500,8 +473,7 @@ void mfm_callback(void *p)
break; break;
} }
fseeko64(drive->hdfile, addr * 512, SEEK_SET); hdd_image_read(drive->hdc_num, addr, 1, (uint8_t *) mfm->buffer);
fread(mfm->buffer, 512, 1, drive->hdfile);
mfm->pos = 0; mfm->pos = 0;
mfm->status = STAT_DRQ | STAT_READY | STAT_DSC; mfm->status = STAT_DRQ | STAT_READY | STAT_DSC;
mfm_irq_raise(mfm); mfm_irq_raise(mfm);
@@ -517,8 +489,7 @@ void mfm_callback(void *p)
mfm_irq_raise(mfm); mfm_irq_raise(mfm);
break; break;
} }
fseeko64(drive->hdfile, addr * 512, SEEK_SET); hdd_image_write(drive->hdc_num, addr, 1, (uint8_t *) mfm->buffer);
fwrite(mfm->buffer, 512, 1, drive->hdfile);
mfm_irq_raise(mfm); mfm_irq_raise(mfm);
mfm->secount = (mfm->secount - 1) & 0xff; mfm->secount = (mfm->secount - 1) & 0xff;
if (mfm->secount) if (mfm->secount)
@@ -552,12 +523,7 @@ void mfm_callback(void *p)
mfm_irq_raise(mfm); mfm_irq_raise(mfm);
break; break;
} }
fseeko64(drive->hdfile, addr * 512, SEEK_SET); hdd_image_zero(drive->hdc_num, addr, mfm->secount);
memset(mfm->buffer, 0, 512);
for (c = 0; c < mfm->secount; c++)
{
fwrite(mfm->buffer, 512, 1, drive->hdfile);
}
mfm->status = STAT_READY | STAT_DSC; mfm->status = STAT_READY | STAT_DSC;
mfm_irq_raise(mfm); mfm_irq_raise(mfm);
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1); update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
@@ -625,8 +591,7 @@ void mfm_close(void *p)
{ {
mfm_drive_t *drive = &mfm->drives[d]; mfm_drive_t *drive = &mfm->drives[d];
if (drive->hdfile != NULL) hdd_image_close(drive->hdc_num);
fclose(drive->hdfile);
} }
free(mfm); free(mfm);

View File

@@ -1,17 +1,10 @@
#define _LARGEFILE_SOURCE #include <malloc.h>
#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h> #include <sys/types.h>
#include "ibm.h" #include "ibm.h"
#include "device.h" #include "device.h"
#include "dma.h" #include "dma.h"
#include "hdd_image.h"
#include "io.h" #include "io.h"
#include "mem.h" #include "mem.h"
#include "pic.h" #include "pic.h"
@@ -43,7 +36,8 @@ typedef struct mfm_drive_t
int cfg_hpc; int cfg_hpc;
int cfg_cyl; int cfg_cyl;
int current_cylinder; int current_cylinder;
FILE *hdfile; int present;
int hdc_num;
} mfm_drive_t; } mfm_drive_t;
typedef struct xebec_t typedef struct xebec_t
@@ -297,6 +291,8 @@ static void xebec_next_sector(xebec_t *xebec)
static void xebec_callback(void *p) static void xebec_callback(void *p)
{ {
off64_t addr;
xebec_t *xebec = (xebec_t *)p; xebec_t *xebec = (xebec_t *)p;
mfm_drive_t *drive; mfm_drive_t *drive;
@@ -310,13 +306,13 @@ static void xebec_callback(void *p)
switch (xebec->command[0]) switch (xebec->command[0])
{ {
case CMD_TEST_DRIVE_READY: case CMD_TEST_DRIVE_READY:
if (!drive->hdfile) if (!drive->present)
xebec_error(xebec, ERR_NOT_READY); xebec_error(xebec, ERR_NOT_READY);
xebec_complete(xebec); xebec_complete(xebec);
break; break;
case CMD_RECALIBRATE: case CMD_RECALIBRATE:
if (!drive->hdfile) if (!drive->present)
xebec_error(xebec, ERR_NOT_READY); xebec_error(xebec, ERR_NOT_READY);
else else
{ {
@@ -357,8 +353,6 @@ static void xebec_callback(void *p)
xebec->sector_count = xebec->command[4]; xebec->sector_count = xebec->command[4];
do do
{ {
off64_t addr;
if (xebec_get_sector(xebec, &addr)) if (xebec_get_sector(xebec, &addr))
{ {
pclog("xebec_get_sector failed\n"); pclog("xebec_get_sector failed\n");
@@ -384,9 +378,6 @@ static void xebec_callback(void *p)
case CMD_FORMAT_TRACK: case CMD_FORMAT_TRACK:
{ {
off64_t addr;
int c;
xebec->cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2); xebec->cylinder = xebec->command[3] | ((xebec->command[2] & 0xc0) << 2);
drive->current_cylinder = (xebec->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : xebec->cylinder; drive->current_cylinder = (xebec->cylinder >= drive->cfg_cyl) ? drive->cfg_cyl-1 : xebec->cylinder;
xebec->head = xebec->command[1] & 0x1f; xebec->head = xebec->command[1] & 0x1f;
@@ -399,9 +390,7 @@ static void xebec_callback(void *p)
return; return;
} }
fseeko64(drive->hdfile, addr * 512, SEEK_SET); hdd_image_zero(drive->hdc_num, addr, 17);
for (c = 0; c < 17; c++)
fwrite(xebec->sector_buf, 512, 1, drive->hdfile);
xebec_complete(xebec); xebec_complete(xebec);
} }
@@ -420,8 +409,6 @@ static void xebec_callback(void *p)
xebec->data_pos = 0; xebec->data_pos = 0;
xebec->data_len = 512; xebec->data_len = 512;
{ {
off64_t addr;
if (xebec_get_sector(xebec, &addr)) if (xebec_get_sector(xebec, &addr))
{ {
xebec_error(xebec, xebec->error); xebec_error(xebec, xebec->error);
@@ -429,8 +416,7 @@ static void xebec_callback(void *p)
return; return;
} }
fseeko64(drive->hdfile, addr * 512, SEEK_SET); hdd_image_read(drive->hdc_num, addr, 1, (uint8_t *) xebec->sector_buf);
fread(xebec->sector_buf, 512, 1, drive->hdfile);
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1); update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
} }
if (xebec->irq_dma_mask & DMA_ENA) if (xebec->irq_dma_mask & DMA_ENA)
@@ -474,8 +460,6 @@ static void xebec_callback(void *p)
if (xebec->sector_count) if (xebec->sector_count)
{ {
off64_t addr;
if (xebec_get_sector(xebec, &addr)) if (xebec_get_sector(xebec, &addr))
{ {
xebec_error(xebec, xebec->error); xebec_error(xebec, xebec->error);
@@ -483,8 +467,7 @@ static void xebec_callback(void *p)
return; return;
} }
fseeko64(drive->hdfile, addr * 512, SEEK_SET); hdd_image_read(drive->hdc_num, addr, 1, (uint8_t *) xebec->sector_buf);
fread(xebec->sector_buf, 512, 1, drive->hdfile);
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1); update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
xebec->state = STATE_SEND_DATA; xebec->state = STATE_SEND_DATA;
@@ -559,8 +542,6 @@ static void xebec_callback(void *p)
memcpy(xebec->sector_buf, xebec->data, 512); memcpy(xebec->sector_buf, xebec->data, 512);
{ {
off64_t addr;
if (xebec_get_sector(xebec, &addr)) if (xebec_get_sector(xebec, &addr))
{ {
xebec_error(xebec, xebec->error); xebec_error(xebec, xebec->error);
@@ -568,8 +549,7 @@ static void xebec_callback(void *p)
return; return;
} }
fseeko64(drive->hdfile, addr * 512, SEEK_SET); hdd_image_write(drive->hdc_num, addr, 1, (uint8_t *) xebec->sector_buf);
fwrite(xebec->sector_buf, 512, 1, drive->hdfile);
} }
update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1); update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
@@ -596,7 +576,7 @@ static void xebec_callback(void *p)
break; break;
case CMD_SEEK: case CMD_SEEK:
if (!drive->hdfile) if (!drive->present)
xebec_error(xebec, ERR_NOT_READY); xebec_error(xebec, ERR_NOT_READY);
else else
{ {
@@ -766,39 +746,21 @@ static void xebec_callback(void *p)
static void loadhd(xebec_t *xebec, int c, int d, const wchar_t *fn) static void loadhd(xebec_t *xebec, int c, int d, const wchar_t *fn)
{ {
mfm_drive_t *drive = &xebec->drives[d]; mfm_drive_t *drive = &xebec->drives[d];
int ret = 0;
if (drive->hdfile == NULL) ret = hdd_image_load(d);
{
/* Try to open existing hard disk image */ if (!ret)
drive->hdfile = _wfopen(fn, L"rb+"); {
if (drive->hdfile == NULL) drive->present = 0;
{ return;
/* Failed to open existing hard disk image */
if (errno == ENOENT)
{
/* Failed because it does not exist,
so try to create new file */
drive->hdfile = _wfopen(fn, L"wb+");
if (drive->hdfile == NULL)
{
pclog("Cannot create file '%s': %s",
fn, strerror(errno));
return;
}
}
else
{
/* Failed for another reason */
pclog("Cannot open file '%s': %s",
fn, strerror(errno));
return;
}
}
} }
drive->spt = hdc[c].spt; drive->spt = hdc[c].spt;
drive->hpc = hdc[c].hpc; drive->hpc = hdc[c].hpc;
drive->tracks = hdc[c].tracks; drive->tracks = hdc[c].tracks;
drive->hdc_num = c;
drive->present = 1;
} }
static struct static struct
@@ -822,7 +784,7 @@ static void xebec_set_switches(xebec_t *xebec)
{ {
mfm_drive_t *drive = &xebec->drives[d]; mfm_drive_t *drive = &xebec->drives[d];
if (!drive->hdfile) if (!drive->present)
continue; continue;
for (c = 0; c < 4; c++) for (c = 0; c < 4; c++)
@@ -879,8 +841,7 @@ static void xebec_close(void *p)
{ {
mfm_drive_t *drive = &xebec->drives[d]; mfm_drive_t *drive = &xebec->drives[d];
if (drive->hdfile != NULL) hdd_image_close(drive->hdc_num);
fclose(drive->hdfile);
} }
free(xebec); free(xebec);

View File

@@ -82,6 +82,9 @@
#include "sound/snd_ps1.h" #include "sound/snd_ps1.h"
#include "sound/snd_pssj.h" #include "sound/snd_pssj.h"
#include "sound/snd_sn76489.h" #include "sound/snd_sn76489.h"
#if 0
#include "superio_detect.h"
#endif
#include "tandy_eeprom.h" #include "tandy_eeprom.h"
#include "tandy_rom.h" #include "tandy_rom.h"
#if 0 #if 0
@@ -120,12 +123,16 @@ extern void at_ali1429_init(void);
extern void at_headland_init(void); extern void at_headland_init(void);
extern void at_opti495_init(void); extern void at_opti495_init(void);
extern void at_batman_init(void); extern void at_batman_init(void);
#if 0
extern void at_586mc1_init(void);
#endif
extern void at_endeavor_init(void); extern void at_endeavor_init(void);
extern void at_dtk486_init(void); extern void at_dtk486_init(void);
extern void at_r418_init(void); extern void at_r418_init(void);
extern void at_plato_init(void); extern void at_plato_init(void);
extern void at_mb500n_init(void); extern void at_mb500n_init(void);
extern void at_president_init(void);
extern void at_p54tp4xe_init(void); extern void at_p54tp4xe_init(void);
extern void at_ap53_init(void); extern void at_ap53_init(void);
extern void at_p55t2s_init(void); extern void at_p55t2s_init(void);
@@ -203,13 +210,17 @@ MODEL models[] =
{"DTK PKM-0038S E-2", ROM_DTK486, "dtk486", { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486, "", NULL, "", NULL}, 0, MODEL_AT | MODEL_HAS_IDE, 1, 64, 1, 127, at_dtk486_init, NULL}, {"DTK PKM-0038S E-2", ROM_DTK486, "dtk486", { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486, "", NULL, "", NULL}, 0, MODEL_AT | MODEL_HAS_IDE, 1, 64, 1, 127, at_dtk486_init, NULL},
{"Rise Computer R418", ROM_R418, "r418", { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486, "", NULL, "", NULL}, 0, MODEL_AT | MODEL_HAS_IDE | MODEL_PCI, 1, 64, 1, 127, at_r418_init, NULL}, {"Rise Computer R418", ROM_R418, "r418", { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486, "", NULL, "", NULL}, 0, MODEL_AT | MODEL_HAS_IDE | MODEL_PCI, 1, 64, 1, 127, at_r418_init, NULL},
{"Intel Premiere/PCI", ROM_REVENGE, "revenge", { "Intel", cpus_Pentium5V, "", NULL, "", NULL, "", NULL, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 128, 1, 127, at_batman_init, NULL}, {"Intel Premiere/PCI", ROM_REVENGE, "revenge", { "Intel", cpus_Pentium5V, "", NULL, "", NULL, "", NULL, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 128, 1, 127, at_batman_init, NULL},
#if 0
{"Micro Star 586MC1", ROM_586MC1, "586mc1", { "Intel", cpus_Pentium5V50, "", NULL, "", NULL, "", NULL, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 128, 1, 127, at_586mc1_init, NULL},
#endif
{"Intel Premiere/PCI II", ROM_PLATO, "plato", { "Intel", cpus_PentiumS5, "IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 128, 1, 127, at_plato_init, NULL}, {"Intel Premiere/PCI II", ROM_PLATO, "plato", { "Intel", cpus_PentiumS5, "IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 128, 1, 127, at_plato_init, NULL},
{"Intel Advanced/EV", ROM_ENDEAVOR, "endeavor", { "Intel", cpus_PentiumS5, "IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 128, 1, 127, at_endeavor_init, NULL}, {"Intel Advanced/EV", ROM_ENDEAVOR, "endeavor", { "Intel", cpus_PentiumS5, "IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 128, 1, 127, at_endeavor_init, NULL},
{"Intel Advanced/ZP", ROM_ZAPPA, "zappa", { "Intel", cpus_PentiumS5, "IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 128, 1, 127, at_endeavor_init, NULL}, {"Intel Advanced/ZP", ROM_ZAPPA, "zappa", { "Intel", cpus_PentiumS5, "IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 128, 1, 127, at_endeavor_init, NULL},
{"PC Partner MB500N", ROM_MB500N, "mb500n", { "Intel", cpus_PentiumS5, "IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 128, 1, 127, at_mb500n_init, NULL}, {"PC Partner MB500N", ROM_MB500N, "mb500n", { "Intel", cpus_PentiumS5, "IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 128, 1, 127, at_mb500n_init, NULL},
{"President Award 430FX PCI", ROM_PRESIDENT, "president", { "Intel", cpus_PentiumS5, "IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL, "", NULL}, 0, MODEL_AT | MODEL_HAS_IDE | MODEL_PCI, 1, 128, 1, 127, at_president_init, NULL},
{"ASUS P/I-P54TP4XE", ROM_P54TP4XE, "p54tp4xe", { "Intel", cpus_PentiumS5, "IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 256, 1, 127, at_p54tp4xe_init, NULL},
{"Intel Advanced/ATX", ROM_THOR, "thor", { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 256, 1, 127, at_endeavor_init, NULL}, {"Intel Advanced/ATX", ROM_THOR, "thor", { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 256, 1, 127, at_endeavor_init, NULL},
{"MR Intel Advanced/ATX", ROM_MRTHOR, "mrthor", { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 256, 1, 127, at_endeavor_init, NULL}, {"MR Intel Advanced/ATX", ROM_MRTHOR, "mrthor", { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 256, 1, 127, at_endeavor_init, NULL},
{"ASUS P/I-P54TP4XE", ROM_P54TP4XE, "p54tp4xe", { "Intel", cpus_PentiumS5, "IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 256, 1, 127, at_p54tp4xe_init, NULL},
{"AOpen AP53", ROM_AP53, "ap53", { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 256, 1, 127, at_ap53_init, NULL}, {"AOpen AP53", ROM_AP53, "ap53", { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 256, 1, 127, at_ap53_init, NULL},
{"ASUS P/I-P55T2S", ROM_P55T2S, "p55t2s", { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 256, 1, 127, at_p55t2s_init, NULL}, {"ASUS P/I-P55T2S", ROM_P55T2S, "p55t2s", { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 256, 1, 127, at_p55t2s_init, NULL},
{"Acer M3a", ROM_ACERM3A, "acerm3a", { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 256, 1, 127, at_acerm3a_init, NULL}, {"Acer M3a", ROM_ACERM3A, "acerm3a", { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, MODEL_AT | MODEL_PS2 | MODEL_HAS_IDE | MODEL_PCI, 1, 256, 1, 127, at_acerm3a_init, NULL},
@@ -648,7 +659,7 @@ void at_premiere_common_init(void)
pci_slot(0xc); pci_slot(0xc);
pci_slot(0xe); pci_slot(0xe);
pci_slot(0x6); pci_slot(0x6);
sio_init(2, 0xc, 0xe, 0x6, 0); sio_init(1, 0xc, 0xe, 0x6, 0);
fdc37c665_init(); fdc37c665_init();
intel_batman_init(); intel_batman_init();
device_add(&intel_flash_bxt_ami_device); device_add(&intel_flash_bxt_ami_device);
@@ -670,7 +681,7 @@ void at_586mc1_init(void)
pci_slot(0xc); pci_slot(0xc);
pci_slot(0xe); pci_slot(0xe);
pci_slot(0x6); pci_slot(0x6);
sio_init(2, 0xc, 0xe, 0x6, 0); sio_init(1, 0xc, 0xe, 0x6, 0);
device_add(&intel_flash_bxt_device); device_add(&intel_flash_bxt_device);
secondary_ide_check(); secondary_ide_check();
} }
@@ -716,6 +727,24 @@ void at_mb500n_init(void)
device_add(&intel_flash_bxt_device); device_add(&intel_flash_bxt_device);
} }
void at_president_init(void)
{
at_ide_init();
memregs_init();
pci_init(PCI_CONFIG_TYPE_1);
pci_slot(8);
pci_slot(9);
pci_slot(10);
pci_slot(11);
i430fx_init();
piix_init(7, 8, 9, 10, 11);
#if 0
superio_detect_init();
#endif
w83877f_init();
device_add(&intel_flash_bxt_device);
}
void at_p54tp4xe_init(void) void at_p54tp4xe_init(void)
{ {
at_ide_init(); at_ide_init();

View File

@@ -1796,12 +1796,12 @@ aha_disk_cmd(aha_t *dev)
pclog("SCSI Cdb[%i]=%i\n", i, req->CmdBlock.common.Cdb[i]); pclog("SCSI Cdb[%i]=%i\n", i, req->CmdBlock.common.Cdb[i]);
} }
memset(temp_cdb, 0, shdc[hdc_id].cdb_len); memset(temp_cdb, 0, 12);
if (req->CmdBlock.common.CdbLength <= shdc[hdc_id].cdb_len) { if (req->CmdBlock.common.CdbLength <= 12) {
memcpy(temp_cdb, req->CmdBlock.common.Cdb, memcpy(temp_cdb, req->CmdBlock.common.Cdb,
req->CmdBlock.common.CdbLength); req->CmdBlock.common.CdbLength);
} else { } else {
memcpy(temp_cdb, req->CmdBlock.common.Cdb, shdc[hdc_id].cdb_len); memcpy(temp_cdb, req->CmdBlock.common.Cdb, 12);
} }
/* /*

View File

@@ -1685,12 +1685,12 @@ BuslogicHDCommand(Buslogic_t *bl)
pclog("SCSI Cdb[%i]=%i\n", i, req->CmdBlock.common.Cdb[i]); pclog("SCSI Cdb[%i]=%i\n", i, req->CmdBlock.common.Cdb[i]);
} }
memset(temp_cdb, 0, shdc[hdc_id].cdb_len); memset(temp_cdb, 0, 12);
if (req->CmdBlock.common.CdbLength <= shdc[hdc_id].cdb_len) { if (req->CmdBlock.common.CdbLength <= 12) {
memcpy(temp_cdb, req->CmdBlock.common.Cdb, memcpy(temp_cdb, req->CmdBlock.common.Cdb,
req->CmdBlock.common.CdbLength); req->CmdBlock.common.CdbLength);
} else { } else {
memcpy(temp_cdb, req->CmdBlock.common.Cdb, shdc[hdc_id].cdb_len); memcpy(temp_cdb, req->CmdBlock.common.Cdb, 12);
} }
/* /*

View File

@@ -6,26 +6,19 @@
* *
* Emulation of SCSI fixed and removable disks. * Emulation of SCSI fixed and removable disks.
* *
* Version: @(#)scsi_disk.c 1.0.1 2017/06/03 * Version: @(#)scsi_disk.c 1.0.2 2017/06/16
* *
* Author: Miran Grca, <mgrca8@gmail.com> * Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2017-2017 Miran Grca. * Copyright 2017-2017 Miran Grca.
*/ */
#define _LARGEFILE_SOURCE #include <malloc.h>
#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
#include <inttypes.h>
#include <sys/types.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <stdio.h>
#include "86box.h" #include "86box.h"
#include "cdrom.h" #include "cdrom.h"
#include "ibm.h" #include "ibm.h"
#include "hdd_image.h"
#include "ide.h" #include "ide.h"
#include "piix.h" #include "piix.h"
#include "scsi.h" #include "scsi.h"
@@ -213,278 +206,28 @@ void scsi_disk_insert(uint8_t id)
shdc[id].unit_attention = (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0; shdc[id].unit_attention = (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0;
} }
static char empty_sector[512];
static char *empty_sector_1mb;
void scsi_loadhd(int scsi_id, int scsi_lun, int id) void scsi_loadhd(int scsi_id, int scsi_lun, int id)
{ {
uint32_t sector_size = 512; int ret = 0;
uint32_t zero = 0;
uint64_t signature = 0xD778A82044445459ll;
uint64_t full_size = 0;
uint64_t spt = 0, hpc = 0, tracks = 0;
int c;
uint64_t i = 0, s = 0, t = 0;
wchar_t *fn = hdc[id].fn;
memset(empty_sector, 0, sizeof(empty_sector)); ret = hdd_image_load(id);
shdc[id].base = 0; if (!ret)
if (shdf[id] != NULL)
{ {
fclose(shdf[id]);
shdf[id] = NULL;
}
/* Try to open existing hard disk image */
if (fn[0] == '.')
{
scsi_hd_log("File name starts with .\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
if (hdc[id].bus != HDD_BUS_SCSI_REMOVABLE) if (hdc[id].bus != HDD_BUS_SCSI_REMOVABLE)
{ {
scsi_hard_disks[scsi_id][scsi_lun] = 0xff; scsi_hard_disks[scsi_id][scsi_lun] = 0xff;
} }
else
{
shdc[id].cdb_len = 12;
}
return;
}
shdf[id] = _wfopen(fn, L"rb+");
if (shdf[id] == NULL)
{
/* Failed to open existing hard disk image */
if (errno == ENOENT)
{
/* Failed because it does not exist,
so try to create new file */
if (hdc[id].wp)
{
scsi_hd_log("A write-protected image must exist\n");
goto scsi_hd_load_error;
}
shdf[id] = _wfopen(fn, L"wb+");
if (shdf[id] == NULL)
{
scsi_hd_load_error:
scsi_hd_log("Unable to open image\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
if (hdc[id].bus != HDD_BUS_SCSI_REMOVABLE)
{
scsi_hard_disks[scsi_id][scsi_lun] = 0xff;
}
else
{
shdc[id].cdb_len = 12;
}
return;
}
else
{
memset(&(shdc[id]), 0, sizeof(scsi_hard_disk_t));
if (image_is_hdi(fn))
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
shdc[id].base = 0x1000;
fwrite(&zero, 1, 4, shdf[id]);
fwrite(&zero, 1, 4, shdf[id]);
fwrite(&(shdc[id].base), 1, 4, shdf[id]);
fwrite(&full_size, 1, 4, shdf[id]);
fwrite(&sector_size, 1, 4, shdf[id]);
fwrite(&(hdc[id].spt), 1, 4, shdf[id]);
fwrite(&(hdc[id].hpc), 1, 4, shdf[id]);
fwrite(&(hdc[id].tracks), 1, 4, shdf[id]);
for (c = 0; c < 0x3f8; c++)
{
fwrite(&zero, 1, 4, shdf[id]);
}
}
else if (image_is_hdx(fn, 0))
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
shdc[id].base = 0x28;
fwrite(&signature, 1, 8, shdf[id]);
fwrite(&full_size, 1, 8, shdf[id]);
fwrite(&sector_size, 1, 4, shdf[id]);
fwrite(&(hdc[id].spt), 1, 4, shdf[id]);
fwrite(&(hdc[id].hpc), 1, 4, shdf[id]);
fwrite(&(hdc[id].tracks), 1, 4, shdf[id]);
fwrite(&zero, 1, 4, shdf[id]);
fwrite(&zero, 1, 4, shdf[id]);
}
shdc[id].last_sector = 0;
shdc[id].cdb_len = 12;
}
scsi_disk_insert(id);
s = full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
goto prepare_new_hard_disk;
}
else
{
/* Failed for another reason */
scsi_hd_log("Failed for another reason\n");
if (hdc[id].bus != HDD_BUS_SCSI_REMOVABLE)
{
scsi_hard_disks[scsi_id][scsi_lun] = 0xff;
}
else
{
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
shdc[id].cdb_len = 12;
}
return;
}
} }
else else
{ {
memset(&(shdc[id]), 0, sizeof(scsi_hard_disk_t));
if (image_is_hdi(fn))
{
fseeko64(shdf[id], 0x8, SEEK_SET);
fread(&(shdc[id].base), 1, 4, shdf[id]);
fseeko64(shdf[id], 0xC, SEEK_SET);
full_size = 0;
fread(&full_size, 1, 4, shdf[id]);
fseeko64(shdf[id], 0x10, SEEK_SET);
fread(&sector_size, 1, 4, shdf[id]);
if (sector_size != 512)
{
/* Sector size is not 512 */
scsi_hd_log("HDI: Sector size is not 512\n");
fclose(shdf[id]);
if (hdc[id].bus != HDD_BUS_SCSI_REMOVABLE)
{
scsi_hard_disks[scsi_id][scsi_lun] = 0xff;
}
else
{
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
shdc[id].cdb_len = 12;
}
return;
}
fread(&spt, 1, 4, shdf[id]);
fread(&hpc, 1, 4, shdf[id]);
fread(&tracks, 1, 4, shdf[id]);
if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE)
{
if ((spt != hdc[id].spt) || (hpc != hdc[id].hpc) || (tracks != hdc[id].tracks))
{
fclose(shdf[id]);
shdf[id] = NULL;
goto scsi_hd_load_error;
}
}
hdc[id].spt = spt;
hdc[id].hpc = hpc;
hdc[id].tracks = tracks;
}
else if (image_is_hdx(fn, 1))
{
shdc[id].base = 0x28;
fseeko64(shdf[id], 8, SEEK_SET);
fread(&full_size, 1, 8, shdf[id]);
fseeko64(shdf[id], 0x10, SEEK_SET);
fread(&sector_size, 1, 4, shdf[id]);
if (sector_size != 512)
{
/* Sector size is not 512 */
scsi_hd_log("HDX: Sector size is not 512\n");
fclose(shdf[id]);
if (hdc[id].bus != HDD_BUS_SCSI_REMOVABLE)
{
scsi_hard_disks[scsi_id][scsi_lun] = 0xff;
}
else
{
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
shdc[id].cdb_len = 12;
}
return;
}
fread(&spt, 1, 4, shdf[id]);
fread(&hpc, 1, 4, shdf[id]);
fread(&tracks, 1, 4, shdf[id]);
if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE)
{
if ((spt != hdc[id].spt) || (hpc != hdc[id].hpc) || (tracks != hdc[id].tracks))
{
fclose(shdf[id]);
shdf[id] = NULL;
goto scsi_hd_load_error;
}
}
hdc[id].spt = spt;
hdc[id].hpc = hpc;
hdc[id].tracks = tracks;
fread(&(hdc[id].at_spt), 1, 4, shdf[id]);
fread(&(hdc[id].at_hpc), 1, 4, shdf[id]);
}
else
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
}
shdc[id].cdb_len = 12;
scsi_disk_insert(id); scsi_disk_insert(id);
} }
fseeko64(shdf[id], 0, SEEK_END);
if (ftello64(shdf[id]) < (full_size + shdc[id].base))
{
s = (full_size + shdc[id].base) - ftello64(shdf[id]);
prepare_new_hard_disk:
s >>= 9;
t = (s >> 11) << 11;
s -= t;
t >>= 11;
empty_sector_1mb = (char *) malloc(1048576);
memset(empty_sector_1mb, 0, 1048576);
if (s > 0)
{
for (i = 0; i < s; i++)
{
fwrite(empty_sector, 1, 512, shdf[id]);
}
}
if (t > 0)
{
for (i = 0; i < t; i++)
{
fwrite(empty_sector_1mb, 1, 1045876, shdf[id]);
}
}
free(empty_sector_1mb);
}
shdc[id].last_sector = (uint32_t) (full_size >> 9) - 1;
#if 0
fclose(shdf[id]);
#endif
} }
void scsi_reloadhd(int id) void scsi_reloadhd(int id)
{ {
uint32_t sector_size = 512; int ret = 0;
uint32_t zero = 0;
uint64_t signature = 0xD778A82044445459ll;
uint64_t full_size = 0;
uint64_t spt = 0, hpc = 0, tracks = 0;
int c;
uint64_t i = 0, s = 0, t = 0;
wchar_t *fn = hdc[id].fn;
memset(empty_sector, 0, sizeof(empty_sector));
if(hdc[id].prev_fn == NULL) if(hdc[id].prev_fn == NULL)
{ {
@@ -496,232 +239,17 @@ void scsi_reloadhd(int id)
memset(hdc[id].prev_fn, 0, sizeof(hdc[id].prev_fn)); memset(hdc[id].prev_fn, 0, sizeof(hdc[id].prev_fn));
} }
shdc[id].base = 0; ret = hdd_image_load(id);
if (shdf[id] != NULL) if (ret)
{ {
fclose(shdf[id]);
shdf[id] = NULL;
}
/* Try to open existing hard disk image */
if (fn[0] == '.')
{
scsi_hd_log("File name starts with .\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
shdc[id].cdb_len = 12;
return;
}
shdf[id] = _wfopen(fn, L"rb+");
if (shdf[id] == NULL)
{
/* Failed to open existing hard disk image */
if (errno == ENOENT)
{
/* Failed because it does not exist,
so try to create new file */
if (hdc[id].wp)
{
scsi_hd_log("A write-protected image must exist\n");
goto scsi_hd_reload_error;
}
shdf[id] = _wfopen(fn, L"wb+");
if (shdf[id] == NULL)
{
scsi_hd_reload_error:
scsi_hd_log("Unable to open image\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
shdc[id].cdb_len = 12;
return;
}
else
{
memset(&(shdc[id]), 0, sizeof(scsi_hard_disk_t));
if (image_is_hdi(fn))
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
shdc[id].base = 0x1000;
fwrite(&zero, 1, 4, shdf[id]);
fwrite(&zero, 1, 4, shdf[id]);
fwrite(&(shdc[id].base), 1, 4, shdf[id]);
fwrite(&full_size, 1, 4, shdf[id]);
fwrite(&sector_size, 1, 4, shdf[id]);
fwrite(&(hdc[id].spt), 1, 4, shdf[id]);
fwrite(&(hdc[id].hpc), 1, 4, shdf[id]);
fwrite(&(hdc[id].tracks), 1, 4, shdf[id]);
for (c = 0; c < 0x3f8; c++)
{
fwrite(&zero, 1, 4, shdf[id]);
}
}
else if (image_is_hdx(fn, 0))
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
shdc[id].base = 0x28;
fwrite(&signature, 1, 8, shdf[id]);
fwrite(&full_size, 1, 8, shdf[id]);
fwrite(&sector_size, 1, 4, shdf[id]);
fwrite(&(hdc[id].spt), 1, 4, shdf[id]);
fwrite(&(hdc[id].hpc), 1, 4, shdf[id]);
fwrite(&(hdc[id].tracks), 1, 4, shdf[id]);
fwrite(&zero, 1, 4, shdf[id]);
fwrite(&zero, 1, 4, shdf[id]);
}
shdc[id].last_sector = 0;
shdc[id].cdb_len = 12;
}
scsi_disk_insert(id);
s = full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
goto reload_prepare_new_hard_disk;
}
else
{
/* Failed for another reason */
scsi_hd_log("Failed for another reason\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
shdc[id].cdb_len = 12;
return;
}
}
else
{
memset(&(shdc[id]), 0, sizeof(scsi_hard_disk_t));
if (image_is_hdi(fn))
{
fseeko64(shdf[id], 0x8, SEEK_SET);
fread(&(shdc[id].base), 1, 4, shdf[id]);
fseeko64(shdf[id], 0xC, SEEK_SET);
full_size = 0;
fread(&full_size, 1, 4, shdf[id]);
fseeko64(shdf[id], 0x10, SEEK_SET);
fread(&sector_size, 1, 4, shdf[id]);
if (sector_size != 512)
{
/* Sector size is not 512 */
scsi_hd_log("HDI: Sector size is not 512\n");
fclose(shdf[id]);
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
shdc[id].cdb_len = 12;
return;
}
fread(&spt, 1, 4, shdf[id]);
fread(&hpc, 1, 4, shdf[id]);
fread(&tracks, 1, 4, shdf[id]);
if ((spt != hdc[id].spt) || (hpc != hdc[id].hpc) || (tracks != hdc[id].tracks))
{
fclose(shdf[id]);
shdf[id] = NULL;
goto scsi_hd_reload_error;
}
hdc[id].spt = spt;
hdc[id].hpc = hpc;
hdc[id].tracks = tracks;
}
else if (image_is_hdx(fn, 1))
{
shdc[id].base = 0x28;
fseeko64(shdf[id], 8, SEEK_SET);
fread(&full_size, 1, 8, shdf[id]);
fseeko64(shdf[id], 0x10, SEEK_SET);
fread(&sector_size, 1, 4, shdf[id]);
if (sector_size != 512)
{
/* Sector size is not 512 */
scsi_hd_log("HDX: Sector size is not 512\n");
fclose(shdf[id]);
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
shdc[id].cdb_len = 12;
return;
}
fread(&spt, 1, 4, shdf[id]);
fread(&hpc, 1, 4, shdf[id]);
fread(&tracks, 1, 4, shdf[id]);
if ((spt != hdc[id].spt) || (hpc != hdc[id].hpc) || (tracks != hdc[id].tracks))
{
fclose(shdf[id]);
shdf[id] = NULL;
goto scsi_hd_reload_error;
}
hdc[id].spt = spt;
hdc[id].hpc = hpc;
hdc[id].tracks = tracks;
fread(&(hdc[id].at_spt), 1, 4, shdf[id]);
fread(&(hdc[id].at_hpc), 1, 4, shdf[id]);
}
else
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
}
shdc[id].cdb_len = 12;
scsi_disk_insert(id); scsi_disk_insert(id);
} }
fseeko64(shdf[id], 0, SEEK_END);
if (ftello64(shdf[id]) < (full_size + shdc[id].base))
{
s = (full_size + shdc[id].base) - ftello64(shdf[id]);
reload_prepare_new_hard_disk:
s >>= 9;
t = (s >> 11) << 11;
s -= t;
t >>= 11;
empty_sector_1mb = (char *) malloc(1048576);
memset(empty_sector_1mb, 0, 1048576);
if (s > 0)
{
for (i = 0; i < s; i++)
{
fwrite(empty_sector, 1, 512, shdf[id]);
}
}
if (t > 0)
{
for (i = 0; i < t; i++)
{
fwrite(empty_sector_1mb, 1, 1045876, shdf[id]);
}
}
free(empty_sector_1mb);
}
shdc[id].last_sector = (uint32_t) (full_size >> 9) - 1;
#if 0
fclose(shdf[id]);
#endif
} }
void scsi_unloadhd(int scsi_id, int scsi_lun, int id) void scsi_unloadhd(int scsi_id, int scsi_lun, int id)
{ {
if (wcslen(hdc[id].fn) == 0) hdd_image_unload(id, 1);
{
return;
}
if (shdf[id] != NULL)
{
fclose(shdf[id]);
shdf[id] = NULL;
}
shdc[id].last_sector = -1;
memset(hdc[id].prev_fn, 0, sizeof(hdc[id].prev_fn));
wcscpy(hdc[id].prev_fn, hdc[id].fn);
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
shdc[id].cdb_len = 12;
fclose(shdf[id]);
} }
void build_scsi_hd_map() void build_scsi_hd_map()
@@ -746,10 +274,6 @@ void build_scsi_hd_map()
{ {
scsi_loadhd(i, j, scsi_hard_disks[i][j]); scsi_loadhd(i, j, scsi_hard_disks[i][j]);
} }
else
{
shdc[scsi_hard_disks[i][j]].cdb_len = 12;
}
} }
} }
} }
@@ -759,7 +283,7 @@ int scsi_hd_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *l
{ {
int size = 0; int size = 0;
size = shdc[id].last_sector; size = hdd_image_get_last_sector(id);
memset(buffer, 0, 8); memset(buffer, 0, 8);
buffer[0] = (size >> 24) & 0xff; buffer[0] = (size >> 24) & 0xff;
buffer[1] = (size >> 16) & 0xff; buffer[1] = (size >> 16) & 0xff;
@@ -771,16 +295,6 @@ int scsi_hd_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *l
return 1; return 1;
} }
void scsi_hd_set_cdb_len(int id, int cdb_len)
{
shdc[id].cdb_len = cdb_len;
}
void scsi_hd_reset_cdb_len(int id)
{
shdc[id].cdb_len = 12;
}
void scsi_hd_update_request_length(uint8_t id, int len, int block_len) void scsi_hd_update_request_length(uint8_t id, int len, int block_len)
{ {
/* For media access commands, make sure the requested DRQ length matches the block length. */ /* For media access commands, make sure the requested DRQ length matches the block length. */
@@ -1080,7 +594,7 @@ int scsi_hd_pre_execution_check(uint8_t id, uint8_t *cdb)
static void scsi_hd_seek(uint8_t id, uint32_t pos) static void scsi_hd_seek(uint8_t id, uint32_t pos)
{ {
/* scsi_hd_log("SCSI HD %i: Seek %08X\n", id, pos); */ /* scsi_hd_log("SCSI HD %i: Seek %08X\n", id, pos); */
shdc[id].seek_pos = pos; hdd_image_seek(id, pos);
} }
static void scsi_hd_rezero(uint8_t id) static void scsi_hd_rezero(uint8_t id)
@@ -1179,14 +693,16 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
unsigned size_idx; unsigned size_idx;
unsigned preamble_len; unsigned preamble_len;
uint32_t alloc_length; uint32_t alloc_length;
uint64_t pos64;
char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 };
char device_identify_ex[15] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; char device_identify_ex[15] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 };
char *tempbuffer; uint8_t *tempbuffer;
uint32_t last_sector = 0;
#if 0 #if 0
int CdbLength; int CdbLength;
#endif #endif
last_sector = hdd_image_get_last_sector(id);
shdc[id].status &= ~ERR_STAT; shdc[id].status &= ~ERR_STAT;
shdc[id].packet_len = 0; shdc[id].packet_len = 0;
@@ -1210,7 +726,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
shdc[id].data_pos = 0; shdc[id].data_pos = 0;
memcpy(shdc[id].current_cdb, cdb, shdc[id].cdb_len); memcpy(shdc[id].current_cdb, cdb, 12);
if (cdb[0] != 0) if (cdb[0] != 0)
{ {
@@ -1218,7 +734,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
scsi_hd_log("SCSI HD %i: Request length: %04X\n", id, shdc[id].request_length); scsi_hd_log("SCSI HD %i: Request length: %04X\n", id, shdc[id].request_length);
#if 0 #if 0
for (CdbLength = 1; CdbLength < shdc[id].cdb_len; CdbLength++) for (CdbLength = 1; CdbLength < 12; CdbLength++)
{ {
scsi_hd_log("SCSI HD %i: CDB[%d] = 0x%02X\n", id, CdbLength, cdb[CdbLength]); scsi_hd_log("SCSI HD %i: CDB[%d] = 0x%02X\n", id, CdbLength, cdb[CdbLength]);
} }
@@ -1284,7 +800,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
break; break;
} }
if ((shdc[id].sector_pos > shdc[id].last_sector) || ((shdc[id].sector_pos + shdc[id].sector_len - 1) > shdc[id].last_sector)) if ((shdc[id].sector_pos > last_sector) || ((shdc[id].sector_pos + shdc[id].sector_len - 1) > last_sector))
{ {
scsi_hd_lba_out_of_range(id); scsi_hd_lba_out_of_range(id);
return; return;
@@ -1301,27 +817,18 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
max_len = shdc[id].sector_len; max_len = shdc[id].sector_len;
shdc[id].requested_blocks = max_len; shdc[id].requested_blocks = max_len;
pos64 = (uint64_t) shdc[id].sector_pos;
alloc_length = shdc[id].packet_len = max_len << 9; 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[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength > 0))
{ {
#if 0
shdf[id] = _wfopen(hdc[id].fn, L"rb+");
#endif
fseeko64(shdf[id], shdc[id].base + (pos64 << 9), SEEK_SET);
if (alloc_length > SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength) if (alloc_length > SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength)
{ {
fread(hdbufferb, 1, SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength, shdf[id]); hdd_image_read(id, shdc[id].sector_pos, SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength >> 9, hdbufferb);
} }
else else
{ {
fread(hdbufferb, 1, alloc_length, shdf[id]); hdd_image_read(id, shdc[id].sector_pos, max_len, hdbufferb);
} }
#if 0
fclose(shdf[id]);
#endif
} }
if (shdc[id].requested_blocks > 1) if (shdc[id].requested_blocks > 1)
@@ -1369,7 +876,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
break; break;
} }
if ((shdc[id].sector_pos > shdc[id].last_sector) || ((shdc[id].sector_pos + shdc[id].sector_len - 1) > shdc[id].last_sector)) if ((shdc[id].sector_pos > last_sector) || ((shdc[id].sector_pos + shdc[id].sector_len - 1) > last_sector))
{ {
scsi_hd_lba_out_of_range(id); scsi_hd_lba_out_of_range(id);
return; return;
@@ -1386,27 +893,18 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
max_len = shdc[id].sector_len; max_len = shdc[id].sector_len;
shdc[id].requested_blocks = max_len; shdc[id].requested_blocks = max_len;
pos64 = (uint64_t) shdc[id].sector_pos;
alloc_length = shdc[id].packet_len = max_len << 9; 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[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength > 0))
{ {
#if 0
shdf[id] = _wfopen(hdc[id].fn, L"rb+");
#endif
fseeko64(shdf[id], shdc[id].base + (pos64 << 9), SEEK_SET);
if (alloc_length > SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength) if (alloc_length > SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength)
{ {
fwrite(hdbufferb, 1, SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength, shdf[id]); hdd_image_write(id, shdc[id].sector_pos, SCSIDevices[hdc[id].scsi_id][hdc[id].scsi_lun].InitLength >> 9, hdbufferb);
} }
else else
{ {
fwrite(hdbufferb, 1, alloc_length, shdf[id]); hdd_image_write(id, shdc[id].sector_pos, max_len, hdbufferb);
} }
#if 0
fclose(shdf[id]);
#endif
} }
if (shdc[id].requested_blocks > 1) if (shdc[id].requested_blocks > 1)

View File

@@ -36,14 +36,10 @@ typedef struct {
uint8_t error; uint8_t error;
uint32_t sector_pos; uint32_t sector_pos;
uint32_t sector_len; uint32_t sector_len;
uint32_t last_sector;
uint32_t seek_pos; uint32_t seek_pos;
int data_pos; int data_pos;
int old_len; int old_len;
int cdb_len_setting;
int cdb_len;
int request_pos; int request_pos;
uint64_t base;
uint8_t hd_cdb[16]; uint8_t hd_cdb[16];
} scsi_hard_disk_t; } scsi_hard_disk_t;
#pragma pack(pop) #pragma pack(pop)

52
src/superio_detect.c Normal file
View File

@@ -0,0 +1,52 @@
/*
SMSC SMC FDC37C665 Super I/O Chip
Used by Batman's Revenge
*/
#include "ibm.h"
#include "io.h"
#include "disc.h"
#include "fdd.h"
#include "fdc.h"
#include "superio_detect.h"
static int fdc37c665_locked;
static int fdc37c665_curreg = 0;
static uint8_t detect_regs[2];
static uint8_t tries;
void superio_detect_write(uint16_t port, uint8_t val, void *priv)
{
uint8_t index = (port & 1) ? 0 : 1;
uint8_t valxor = 0;
int temp;
pclog("superio_detect_write : port=%04x = %02X\n", port, val);
detect_regs[port & 1] = val;
return;
}
uint8_t superio_detect_read(uint16_t port, void *priv)
{
pclog("superio_detect_read : port=%04x = %02X\n", port, detect_regs[port & 1]);
return detect_regs[port & 1];
}
void superio_detect_init()
{
fdc_remove();
fdc_add_for_superio();
io_sethandler(0x24, 0x0002, superio_detect_read, NULL, NULL, superio_detect_write, NULL, NULL, NULL);
io_sethandler(0x26, 0x0002, superio_detect_read, NULL, NULL, superio_detect_write, NULL, NULL, NULL);
io_sethandler(0x2e, 0x0002, superio_detect_read, NULL, NULL, superio_detect_write, NULL, NULL, NULL);
io_sethandler(0x44, 0x0002, superio_detect_read, NULL, NULL, superio_detect_write, NULL, NULL, NULL);
io_sethandler(0x46, 0x0002, superio_detect_read, NULL, NULL, superio_detect_write, NULL, NULL, NULL);
io_sethandler(0x4e, 0x0002, superio_detect_read, NULL, NULL, superio_detect_write, NULL, NULL, NULL);
io_sethandler(0x108, 0x0002, superio_detect_read, NULL, NULL, superio_detect_write, NULL, NULL, NULL);
io_sethandler(0x250, 0x0002, superio_detect_read, NULL, NULL, superio_detect_write, NULL, NULL, NULL);
io_sethandler(0x370, 0x0002, superio_detect_read, NULL, NULL, superio_detect_write, NULL, NULL, NULL);
io_sethandler(0x3f0, 0x0002, superio_detect_read, NULL, NULL, superio_detect_write, NULL, NULL, NULL);
}

1
src/superio_detect.h Normal file
View File

@@ -0,0 +1 @@
extern void superio_detect_init();

View File

@@ -216,6 +216,7 @@ static void w83877f_remap()
winbond_port = (HEFRAS ? 0x3f0 : 0x250); winbond_port = (HEFRAS ? 0x3f0 : 0x250);
winbond_key_times = HEFRAS + 1; winbond_key_times = HEFRAS + 1;
winbond_key = (HEFRAS ? 0x86 : 0x88) | HEFERE; winbond_key = (HEFRAS ? 0x86 : 0x88) | HEFERE;
pclog("W83877F: Remapped to port %04X, key %02X\n", winbond_port, winbond_key);
} }
static uint8_t is_in_array(uint16_t *port_array, uint8_t max, uint16_t port) static uint8_t is_in_array(uint16_t *port_array, uint8_t max, uint16_t port)
@@ -282,6 +283,24 @@ static uint16_t make_port(uint8_t reg)
return p; return p;
} }
void w83877f_serial_handler(int id)
{
int reg_mask = (id - 1) ? 0x10 : 0x20;
int reg_id = (id - 1) ? 0x24 : 0x25;
int irq_mask = (id - 1) ? 0xF : 0xF0;
/* pclog("Registers (%i): %02X %02X %02X\n", id, w83877f_regs[4], w83877f_regs[reg_id], w83877f_regs[0x28]); */
if ((w83877f_regs[4] & reg_mask) || !(w83877f_regs[reg_id] & 0xc0))
{
serial_remove(id);
}
else
{
serial_setup(id, make_port(reg_id), w83877f_regs[0x28] & irq_mask);
}
}
void w83877f_write(uint16_t port, uint8_t val, void *priv) void w83877f_write(uint16_t port, uint8_t val, void *priv)
{ {
uint8_t index = (port & 1) ? 0 : 1; uint8_t index = (port & 1) ? 0 : 1;
@@ -353,16 +372,11 @@ process_value:
case 4: case 4:
if (valxor & 0x10) if (valxor & 0x10)
{ {
serial_remove(2); w83877f_serial_handler(2);
if (!(w83877f_regs[2] & 0x10)) serial_setup(2, make_port(0x25), w83877f_regs[0x28] & 0xF);
} }
if (valxor & 0x20) if (valxor & 0x20)
{ {
serial_remove(1); w83877f_serial_handler(1);
if (!(w83877f_regs[4] & 0x20))
{
serial_setup(1, make_port(0x24), (w83877f_regs[0x28] & 0xF0) >> 8);
}
} }
if (valxor & 0x80) if (valxor & 0x80)
{ {
@@ -418,16 +432,13 @@ process_value:
case 0x24: case 0x24:
if (valxor & 0xfe) if (valxor & 0xfe)
{ {
if (!(w83877f_regs[4] & 0x20)) w83877f_serial_handler(1);
{
serial_setup(1, make_port(0x24), (w83877f_regs[0x28] & 0xF0) >> 8);
}
} }
break; break;
case 0x25: case 0x25:
if (valxor & 0xfe) if (valxor & 0xfe)
{ {
if (!(w83877f_regs[2] & 0x10)) serial_setup(2, make_port(0x25), w83877f_regs[0x28] & 0xF); w83877f_serial_handler(2);
} }
break; break;
case 0x28: case 0x28:
@@ -486,7 +497,7 @@ void w83877f_reset(void)
w83877f_regs[0xA] = 0x1F; w83877f_regs[0xA] = 0x1F;
w83877f_regs[0xC] = 0x28; w83877f_regs[0xC] = 0x28;
w83877f_regs[0xD] = 0xA3; w83877f_regs[0xD] = 0xA3;
w83877f_regs[0x16] = 5; w83877f_regs[0x16] = (romset == ROM_PRESIDENT) ? 4 : 5;
w83877f_regs[0x1E] = 0x81; w83877f_regs[0x1E] = 0x81;
w83877f_regs[0x20] = (0x3f0 >> 2) & 0xfc; w83877f_regs[0x20] = (0x3f0 >> 2) & 0xfc;
w83877f_regs[0x21] = (0x1f0 >> 2) & 0xfc; w83877f_regs[0x21] = (0x1f0 >> 2) & 0xfc;