Applied all relevant PCem commits;
Extensively cleaned up and changed the CD-ROM code; Removed CD-ROM IOCTTL (it was causing performance and stability issues); Turned a lot of things into device_t's; Added the PS/1 Model 2011 XTA and standalone XTA hard disk controllers, ported from Varcem; Numerous FDC fixes for the PS/1 Model 2121; NVR changes ported from Varcem; The PCap code no longer requires libpcap to be compiled; Numerous fixes to various SCSI controllers; Updated NukedOPL to 1.8; Fixes to OpenAL initialization and closing, should give less Audio issues now; Revorked parts of the common (S)VGA code (also based on code from QEMU); Removed the Removable SCSI hard disks (they were a never finished experiment so there was no need to keep them there); Cleaned up the SCSI hard disk and Iomega ZIP code (but more cleanups of that are coming in the future); In some occasions (IDE hard disks in multiple sector mode and SCSI hard disks) the status bar icon is no longer updated, should improve performance a bit; Redid the way the tertiary and quaternary IDE controllers are configured (and they are now device_t's); Extensively reworked the IDE code and fixed quite a few bugs; Fixes to XT MFM, AT MFM, and AT ESDI code; Some changes to XTIDE and MCA ESDI code; Some fixes to the CD-ROM image handler.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Common code to handle all sorts of disk controllers.
|
||||
*
|
||||
* Version: @(#)hdc.c 1.0.12 2018/03/19
|
||||
* Version: @(#)hdc.c 1.0.13 2018/04/04
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "../device.h"
|
||||
#include "hdc.h"
|
||||
#include "hdc_ide.h"
|
||||
#include "hdd.h"
|
||||
|
||||
|
||||
char *hdc_name; /* configured HDC name */
|
||||
@@ -106,6 +107,9 @@ static const struct {
|
||||
{ "[ISA] [IDE] PS/2 AT XTIDE (1.1.5)", "xtide_at_ps2",
|
||||
&xtide_at_ps2_device },
|
||||
|
||||
{ "[ISA] [IDE] WDXT-150 IDE (XTA) Adapter", "xta_wdxt150",
|
||||
&xta_wdxt150_device },
|
||||
|
||||
{ "[ISA] [XT IDE] Acculogic XT IDE", "xtide_acculogic",
|
||||
&xtide_acculogic_device },
|
||||
|
||||
@@ -146,6 +150,9 @@ hdc_init(char *name)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Zero all the hard disk image arrays. */
|
||||
hdd_image_init();
|
||||
}
|
||||
|
||||
|
||||
@@ -154,20 +161,17 @@ void
|
||||
hdc_reset(void)
|
||||
{
|
||||
pclog("HDC: reset(current=%d, internal=%d)\n",
|
||||
hdc_current, (machines[machine].flags & MACHINE_HDC)?1:0);
|
||||
hdc_current, (machines[machine].flags & MACHINE_HDC) ? 1 : 0);
|
||||
|
||||
/* If we have a valid controller, add its device. */
|
||||
if (hdc_current > 1)
|
||||
device_add(controllers[hdc_current].device);
|
||||
|
||||
/* Reconfire and reset the IDE layer. */
|
||||
ide_ter_disable();
|
||||
ide_qua_disable();
|
||||
if (ide_enable[2])
|
||||
ide_ter_init();
|
||||
if (ide_enable[3])
|
||||
ide_qua_init();
|
||||
ide_reset_hard();
|
||||
/* Now, add the tertiary and/or quaternary IDE controllers. */
|
||||
if (ide_ter_enabled)
|
||||
device_add(&ide_ter_device);
|
||||
if (ide_qua_enabled)
|
||||
device_add(&ide_qua_device);
|
||||
}
|
||||
|
||||
|
||||
@@ -185,6 +189,22 @@ hdc_get_internal_name(int hdc)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hdc_get_from_internal_name(char *s)
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
while (strlen((char *) controllers[c].internal_name))
|
||||
{
|
||||
if (!strcmp((char *) controllers[c].internal_name, s))
|
||||
return c;
|
||||
c++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const device_t *
|
||||
hdc_get_device(int hdc)
|
||||
{
|
||||
@@ -192,6 +212,19 @@ hdc_get_device(int hdc)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hdc_has_config(int hdc)
|
||||
{
|
||||
const device_t *dev = hdc_get_device(hdc);
|
||||
|
||||
if (dev == NULL) return(0);
|
||||
|
||||
if (dev->config == NULL) return(0);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hdc_get_flags(int hdc)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Definitions for the common disk controller handler.
|
||||
*
|
||||
* Version: @(#)hdc.h 1.0.7 2018/03/19
|
||||
* Version: @(#)hdc.h 1.0.8 2018/04/05
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
#define MFM_NUM 2 /* 2 drives per controller supported */
|
||||
#define ESDI_NUM 2 /* 2 drives per controller supported */
|
||||
#define XTIDE_NUM 2 /* 2 drives per controller supported */
|
||||
#define XTA_NUM 2 /* 2 drives per controller supported */
|
||||
#define IDE_NUM 8
|
||||
#define SCSI_NUM 16 /* theoretically the controller can have at
|
||||
* least 7 devices, with each device being
|
||||
@@ -47,6 +47,12 @@ extern const device_t ide_vlb_2ch_device; /* vlb_ide_2ch */
|
||||
extern const device_t ide_pci_device; /* pci_ide */
|
||||
extern const device_t ide_pci_2ch_device; /* pci_ide_2ch */
|
||||
|
||||
extern const device_t ide_ter_device;
|
||||
extern const device_t ide_qua_device;
|
||||
|
||||
extern const device_t xta_wdxt150_device; /* xta_wdxt150 */
|
||||
extern const device_t xta_hd20_device; /* EuroPC internal */
|
||||
|
||||
extern const device_t xtide_device; /* xtide_xt */
|
||||
extern const device_t xtide_at_device; /* xtide_at */
|
||||
extern const device_t xtide_acculogic_device; /* xtide_ps2 */
|
||||
@@ -58,6 +64,8 @@ extern void hdc_reset(void);
|
||||
|
||||
extern char *hdc_get_name(int hdc);
|
||||
extern char *hdc_get_internal_name(int hdc);
|
||||
extern int hdc_get_from_internal_name(char *s);
|
||||
extern int hdc_has_config(int hdc);
|
||||
extern const device_t *hdc_get_device(int hdc);
|
||||
extern int hdc_get_flags(int hdc);
|
||||
extern int hdc_available(int hdc);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Driver for the ESDI controller (WD1007-vse1) for PC/AT.
|
||||
*
|
||||
* Version: @(#)hdc_esdi_at.c 1.0.9 2018/03/18
|
||||
* Version: @(#)hdc_esdi_at.c 1.0.10 2018/04/17
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -104,35 +104,28 @@ typedef struct {
|
||||
} esdi_t;
|
||||
|
||||
|
||||
static __inline void irq_raise(esdi_t *esdi)
|
||||
static inline void
|
||||
irq_raise(esdi_t *esdi)
|
||||
{
|
||||
/* If not already pending.. */
|
||||
if (! esdi->irqstat) {
|
||||
/* If enabled in the control register.. */
|
||||
if (! (esdi->fdisk & 0x02)) {
|
||||
/* .. raise IRQ14. */
|
||||
picint(1<<14);
|
||||
}
|
||||
if (!(esdi->fdisk&2))
|
||||
picint(1 << 14);
|
||||
|
||||
/* Remember this. */
|
||||
esdi->irqstat = 1;
|
||||
}
|
||||
esdi->irqstat=1;
|
||||
}
|
||||
|
||||
|
||||
static __inline void irq_lower(esdi_t *esdi)
|
||||
static inline void
|
||||
irq_lower(esdi_t *esdi)
|
||||
{
|
||||
/* If raised.. */
|
||||
if (esdi->irqstat) {
|
||||
/* If enabled in the control register.. */
|
||||
if (! (esdi->fdisk & 0x02)) {
|
||||
/* .. drop IRQ14. */
|
||||
picintc(1<<14);
|
||||
}
|
||||
picintc(1 << 14);
|
||||
}
|
||||
|
||||
/* Remember this. */
|
||||
esdi->irqstat = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
irq_update(esdi_t *esdi)
|
||||
{
|
||||
if (esdi->irqstat && !((pic2.pend|pic2.ins)&0x40) && !(esdi->fdisk & 2))
|
||||
picint(1 << 14);
|
||||
}
|
||||
|
||||
|
||||
@@ -384,6 +377,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
||||
esdi->status = STAT_BUSY;
|
||||
}
|
||||
esdi->fdisk = val;
|
||||
irq_update(esdi);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
* however, are auto-configured by the system software as
|
||||
* shown above.
|
||||
*
|
||||
* Version: @(#)hdc_esdi_mca.c 1.0.9 2018/03/18
|
||||
* Version: @(#)hdc_esdi_mca.c 1.0.11 2018/04/17
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -101,8 +101,6 @@ typedef struct esdi_drive {
|
||||
} drive_t;
|
||||
|
||||
typedef struct esdi {
|
||||
uint16_t base;
|
||||
int8_t irq;
|
||||
int8_t dma;
|
||||
|
||||
uint32_t bios;
|
||||
@@ -190,6 +188,7 @@ typedef struct esdi {
|
||||
#define CMD_GET_POS_INFO 0x0a
|
||||
|
||||
#define STATUS_LEN(x) ((x) << 8)
|
||||
#define STATUS_DEVICE(x) ((x) << 5)
|
||||
#define STATUS_DEVICE_HOST_ADAPTER (7 << 5)
|
||||
|
||||
|
||||
@@ -197,14 +196,14 @@ static __inline void
|
||||
set_irq(esdi_t *dev)
|
||||
{
|
||||
if (dev->basic_ctrl & CTRL_IRQ_ENA)
|
||||
picint(1 << dev->irq);
|
||||
picint(1 << 14);
|
||||
}
|
||||
|
||||
|
||||
static __inline void
|
||||
clear_irq(esdi_t *dev)
|
||||
{
|
||||
picintc(1 << dev->irq);
|
||||
picintc(1 << 14);
|
||||
}
|
||||
|
||||
|
||||
@@ -250,23 +249,42 @@ device_not_present(esdi_t *dev)
|
||||
set_irq(dev);
|
||||
}
|
||||
|
||||
static void rba_out_of_range(esdi_t *dev)
|
||||
{
|
||||
dev->status_len = 9;
|
||||
dev->status_data[0] = dev->command | STATUS_LEN(9) | dev->cmd_dev;
|
||||
dev->status_data[1] = 0x0e01; /*Command block error, invalid parameter*/
|
||||
dev->status_data[2] = 0x0007; /*RBA out of range*/
|
||||
dev->status_data[3] = 0;
|
||||
dev->status_data[4] = 0;
|
||||
dev->status_data[5] = 0;
|
||||
dev->status_data[6] = 0;
|
||||
dev->status_data[7] = 0;
|
||||
dev->status_data[8] = 0;
|
||||
|
||||
dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL;
|
||||
dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_FAILURE;
|
||||
dev->irq_in_progress = 1;
|
||||
set_irq(dev);
|
||||
static void
|
||||
rba_out_of_range(esdi_t *dev)
|
||||
{
|
||||
dev->status_len = 9;
|
||||
dev->status_data[0] = dev->command | STATUS_LEN(9) | dev->cmd_dev;
|
||||
dev->status_data[1] = 0x0e01; /*Command block error, invalid parameter*/
|
||||
dev->status_data[2] = 0x0007; /*RBA out of range*/
|
||||
dev->status_data[3] = 0;
|
||||
dev->status_data[4] = 0;
|
||||
dev->status_data[5] = 0;
|
||||
dev->status_data[6] = 0;
|
||||
dev->status_data[7] = 0;
|
||||
dev->status_data[8] = 0;
|
||||
|
||||
dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL;
|
||||
dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_FAILURE;
|
||||
dev->irq_in_progress = 1;
|
||||
set_irq(dev);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
complete_command_status(esdi_t *dev)
|
||||
{
|
||||
dev->status_len = 7;
|
||||
if (dev->cmd_dev == ATTN_DEVICE_0)
|
||||
dev->status_data[0] = CMD_READ | STATUS_LEN(7) | STATUS_DEVICE(0);
|
||||
else
|
||||
dev->status_data[0] = CMD_READ | STATUS_LEN(7) | STATUS_DEVICE(1);
|
||||
dev->status_data[1] = 0x0000; /*Error bits*/
|
||||
dev->status_data[2] = 0x1900; /*Device status*/
|
||||
dev->status_data[3] = 0; /*Number of blocks left to do*/
|
||||
dev->status_data[4] = (dev->rba-1) & 0xffff; /*Last RBA processed*/
|
||||
dev->status_data[5] = (dev->rba-1) >> 8;
|
||||
dev->status_data[6] = 0; /*Number of blocks requiring error recovery*/
|
||||
}
|
||||
|
||||
#define ESDI_ADAPTER_ONLY() do \
|
||||
@@ -377,7 +395,8 @@ esdi_callback(void *priv)
|
||||
break;
|
||||
|
||||
case 2:
|
||||
dev->status = STATUS_IRQ;
|
||||
complete_command_status(dev);
|
||||
dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL;
|
||||
dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS;
|
||||
dev->irq_in_progress = 1;
|
||||
set_irq(dev);
|
||||
@@ -438,11 +457,11 @@ esdi_callback(void *priv)
|
||||
hdd_image_write(drive->hdd_num, dev->rba, 1, (uint8_t *)dev->data);
|
||||
dev->rba++;
|
||||
dev->sector_pos++;
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI,
|
||||
dev->cmd_dev == ATTN_DEVICE_0 ? 0 : 1);
|
||||
|
||||
dev->data_pos = 0;
|
||||
}
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
|
||||
dev->status = STATUS_CMD_IN_PROGRESS;
|
||||
dev->cmd_state = 2;
|
||||
@@ -450,7 +469,8 @@ esdi_callback(void *priv)
|
||||
break;
|
||||
|
||||
case 2:
|
||||
dev->status = STATUS_IRQ;
|
||||
complete_command_status(dev);
|
||||
dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL;
|
||||
dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS;
|
||||
dev->irq_in_progress = 1;
|
||||
set_irq(dev);
|
||||
@@ -471,7 +491,9 @@ esdi_callback(void *priv)
|
||||
return;
|
||||
}
|
||||
|
||||
dev->status = STATUS_IRQ;
|
||||
dev->rba += dev->sector_count;
|
||||
complete_command_status(dev);
|
||||
dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL;
|
||||
dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS;
|
||||
dev->irq_in_progress = 1;
|
||||
set_irq(dev);
|
||||
@@ -485,7 +507,8 @@ esdi_callback(void *priv)
|
||||
return;
|
||||
}
|
||||
|
||||
dev->status = STATUS_IRQ;
|
||||
complete_command_status(dev);
|
||||
dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL;
|
||||
dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS;
|
||||
dev->irq_in_progress = 1;
|
||||
set_irq(dev);
|
||||
@@ -499,8 +522,6 @@ esdi_callback(void *priv)
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev->status_pos)
|
||||
fatal("Status send in progress\n");
|
||||
if ((dev->status & STATUS_IRQ) || dev->irq_in_progress)
|
||||
fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress);
|
||||
|
||||
@@ -529,8 +550,6 @@ esdi_callback(void *priv)
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev->status_pos)
|
||||
fatal("Status send in progress\n");
|
||||
if ((dev->status & STATUS_IRQ) || dev->irq_in_progress)
|
||||
fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress);
|
||||
|
||||
@@ -557,8 +576,7 @@ esdi_callback(void *priv)
|
||||
|
||||
case CMD_GET_POS_INFO:
|
||||
ESDI_ADAPTER_ONLY();
|
||||
if (dev->status_pos)
|
||||
fatal("Status send in progress\n");
|
||||
|
||||
if ((dev->status & STATUS_IRQ) || dev->irq_in_progress)
|
||||
fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress);
|
||||
|
||||
@@ -567,8 +585,8 @@ esdi_callback(void *priv)
|
||||
dev->status_data[1] = 0xffdd; /*MCA ID*/
|
||||
dev->status_data[2] = dev->pos_regs[3] |
|
||||
(dev->pos_regs[2] << 8);
|
||||
dev->status_data[3] = 0xffff;
|
||||
dev->status_data[4] = 0xffff;
|
||||
dev->status_data[3] = 0xff;
|
||||
dev->status_data[4] = 0xff;
|
||||
|
||||
dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL;
|
||||
dev->irq_status = IRQ_HOST_ADAPTER | IRQ_CMD_COMPLETE_SUCCESS;
|
||||
@@ -688,8 +706,6 @@ esdi_callback(void *priv)
|
||||
|
||||
case 0x12:
|
||||
ESDI_ADAPTER_ONLY();
|
||||
if (dev->status_pos)
|
||||
fatal("Status send in progress\n");
|
||||
if ((dev->status & STATUS_IRQ) || dev->irq_in_progress)
|
||||
fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress);
|
||||
|
||||
@@ -715,7 +731,7 @@ esdi_read(uint16_t port, void *priv)
|
||||
esdi_t *dev = (esdi_t *)priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
switch (port-dev->base) {
|
||||
switch (port & 7) {
|
||||
case 2: /*Basic status register*/
|
||||
ret = dev->status;
|
||||
break;
|
||||
@@ -739,9 +755,9 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
||||
esdi_t *dev = (esdi_t *)priv;
|
||||
|
||||
#if 0
|
||||
pclog("ESDI: wr(%04x, %02x)\n", port-dev->base, val);
|
||||
pclog("ESDI: wr(%04x, %02x)\n", port & 7, val);
|
||||
#endif
|
||||
switch (port-dev->base) {
|
||||
switch (port & 7) {
|
||||
case 2: /*Basic control register*/
|
||||
if ((dev->basic_ctrl & CTRL_RESET) && !(val & CTRL_RESET)) {
|
||||
dev->in_reset = 1;
|
||||
@@ -751,7 +767,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
||||
dev->basic_ctrl = val;
|
||||
|
||||
if (! (dev->basic_ctrl & CTRL_IRQ_ENA))
|
||||
picintc(1 << dev->irq);
|
||||
picintc(1 << 14);
|
||||
break;
|
||||
|
||||
case 3: /*Attention register*/
|
||||
@@ -765,6 +781,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
||||
dev->cmd_dev = ATTN_HOST_ADAPTER;
|
||||
dev->status |= STATUS_BUSY;
|
||||
dev->cmd_pos = 0;
|
||||
dev->status_pos = 0;
|
||||
break;
|
||||
|
||||
case ATTN_EOI:
|
||||
@@ -793,6 +810,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
||||
dev->cmd_dev = ATTN_DEVICE_0;
|
||||
dev->status |= STATUS_BUSY;
|
||||
dev->cmd_pos = 0;
|
||||
dev->status_pos = 0;
|
||||
break;
|
||||
|
||||
case ATTN_EOI:
|
||||
@@ -815,6 +833,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
||||
dev->cmd_dev = ATTN_DEVICE_1;
|
||||
dev->status |= STATUS_BUSY;
|
||||
dev->cmd_pos = 0;
|
||||
dev->status_pos = 0;
|
||||
break;
|
||||
|
||||
case ATTN_EOI:
|
||||
@@ -845,12 +864,11 @@ esdi_readw(uint16_t port, void *priv)
|
||||
esdi_t *dev = (esdi_t *)priv;
|
||||
uint16_t ret = 0xffff;
|
||||
|
||||
switch (port-dev->base) {
|
||||
switch (port & 7) {
|
||||
case 0: /*Status Interface Register*/
|
||||
if (dev->status_pos >= dev->status_len)
|
||||
return(0);
|
||||
ret = dev->status_data[dev->status_pos++];
|
||||
if (dev->status_pos >= dev->status_len) {
|
||||
ret = dev->status_data[dev->status_pos++]; if (dev->status_pos >= dev->status_len) {
|
||||
dev->status &= ~STATUS_STATUS_OUT_FULL;
|
||||
dev->status_pos = dev->status_len = 0;
|
||||
}
|
||||
@@ -870,9 +888,9 @@ esdi_writew(uint16_t port, uint16_t val, void *priv)
|
||||
esdi_t *dev = (esdi_t *)priv;
|
||||
|
||||
#if 0
|
||||
pclog("ESDI: wrw(%04x, %04x)\n", port-dev->base, val);
|
||||
pclog("ESDI: wrw(%04x, %04x)\n", port & 7, val);
|
||||
#endif
|
||||
switch (port-dev->base) {
|
||||
switch (port & 7) {
|
||||
case 0: /*Command Interface Register*/
|
||||
if (dev->cmd_pos >= 4)
|
||||
fatal("CIR pos 4\n");
|
||||
@@ -919,123 +937,55 @@ esdi_mca_write(int port, uint8_t val, void *priv)
|
||||
pclog("ESDI: mcawr(%04x, %02x) pos[2]=%02x pos[3]=%02x\n",
|
||||
port, val, dev->pos_regs[2], dev->pos_regs[3]);
|
||||
#endif
|
||||
if (port < 0x102) return;
|
||||
|
||||
/*
|
||||
* The PS/2 Model 80 BIOS always enables a card if it finds one,
|
||||
* even if no resources were assigned yet (because we only added
|
||||
* the card, but have not run AutoConfig yet...)
|
||||
*
|
||||
* So, remove current address, if any.
|
||||
*
|
||||
* Note by Kotori: Moved this to the beginning of esdi_mca_write,
|
||||
* so the *old* base is removed rather than the
|
||||
* new base.
|
||||
*/
|
||||
io_removehandler(dev->base, 8,
|
||||
esdi_read, esdi_readw, NULL,
|
||||
esdi_write, esdi_writew, NULL, dev);
|
||||
mem_mapping_disable(&dev->bios_rom.mapping);
|
||||
if (port < 0x102)
|
||||
return;
|
||||
|
||||
/* Save the new value. */
|
||||
dev->pos_regs[port & 7] = val;
|
||||
|
||||
/* Extract the new I/O base. */
|
||||
switch(dev->pos_regs[2] & 0x02) {
|
||||
case 0x00: /* PRIMARY [0]=XXxx xx0X 0x3510 */
|
||||
dev->base = ESDI_IOADDR_PRI;
|
||||
break;
|
||||
io_removehandler(ESDI_IOADDR_PRI, 8,
|
||||
esdi_read, esdi_readw, NULL,
|
||||
esdi_write, esdi_writew, NULL, dev);
|
||||
mem_mapping_disable(&dev->bios_rom.mapping);
|
||||
|
||||
case 0x02: /* SECONDARY [0]=XXxx xx1X 0x3518 */
|
||||
dev->base = ESDI_IOADDR_SEC;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Extract the new DMA channel. */
|
||||
switch(dev->pos_regs[2] & 0x3c) {
|
||||
case 0x14: /* DMA 5 [0]=XX01 01XX */
|
||||
case 0x14:
|
||||
dev->dma = 5;
|
||||
break;
|
||||
|
||||
case 0x18: /* DMA 6 [0]=XX01 10XX */
|
||||
case 0x18:
|
||||
dev->dma = 6;
|
||||
break;
|
||||
|
||||
case 0x1c: /* DMA 7 [0]=XX01 11XX */
|
||||
case 0x1c:
|
||||
dev->dma = 7;
|
||||
break;
|
||||
|
||||
case 0x00: /* DMA 0 [0]=XX00 00XX */
|
||||
case 0x00:
|
||||
dev->dma = 0;
|
||||
break;
|
||||
|
||||
case 0x01: /* DMA 1 [0]=XX00 01XX */
|
||||
case 0x04:
|
||||
dev->dma = 1;
|
||||
break;
|
||||
|
||||
case 0x04: /* DMA 3 [0]=XX00 11XX */
|
||||
case 0x0c:
|
||||
dev->dma = 3;
|
||||
break;
|
||||
|
||||
case 0x10: /* DMA 4 [0]=XX01 00XX */
|
||||
case 0x10:
|
||||
dev->dma = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Extract the new BIOS address. */
|
||||
if (! (dev->pos_regs[3] & 0x08)) switch(dev->pos_regs[3] & 0x0f) {
|
||||
case 0: /* ROM C000 [1]=XXXX 0000 */
|
||||
dev->bios = 0xC0000;
|
||||
break;
|
||||
|
||||
case 1: /* ROM C400 [1]=XXXX 0001 */
|
||||
dev->bios = 0xC4000;
|
||||
break;
|
||||
|
||||
case 2: /* ROM C800 [1]=XXXX 0010 */
|
||||
dev->bios = 0xC8000;
|
||||
break;
|
||||
|
||||
case 3: /* ROM CC00 [1]=XXXX 0011 */
|
||||
dev->bios = 0xCC000;
|
||||
break;
|
||||
|
||||
case 4: /* ROM D000 [1]=XXXX 0100 */
|
||||
dev->bios = 0xD0000;
|
||||
break;
|
||||
|
||||
case 5: /* ROM D400 [1]=XXXX 0101 */
|
||||
dev->bios = 0xD4000;
|
||||
break;
|
||||
|
||||
case 6: /* ROM D800 [1]=XXXX 0110 */
|
||||
dev->bios = 0xD8000;
|
||||
break;
|
||||
|
||||
case 7: /* ROM DC00 [1]=XXXX 0111 */
|
||||
dev->bios = 0xDC000;
|
||||
break;
|
||||
} else {
|
||||
/* BIOS ROM disabled. */
|
||||
dev->bios = 0x000000;
|
||||
}
|
||||
|
||||
if (dev->pos_regs[2] & 0x01) {
|
||||
/* Card enabled; register (new) I/O handler. */
|
||||
io_sethandler(dev->base, 8,
|
||||
if (dev->pos_regs[2] & 1) {
|
||||
io_sethandler(ESDI_IOADDR_PRI, 8,
|
||||
esdi_read, esdi_readw, NULL,
|
||||
esdi_write, esdi_writew, NULL, dev);
|
||||
|
||||
/* Enable or disable the BIOS ROM. */
|
||||
if (dev->bios != 0x000000) {
|
||||
if (!(dev->pos_regs[3] & 8)) {
|
||||
mem_mapping_enable(&dev->bios_rom.mapping);
|
||||
mem_mapping_set_addr(&dev->bios_rom.mapping,
|
||||
dev->bios, 0x4000);
|
||||
((dev->pos_regs[3] & 7) * 0x4000) + 0xc0000, 0x4000);
|
||||
}
|
||||
|
||||
/* Say hello. */
|
||||
pclog("ESDI: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X\n",
|
||||
dev->base, dev->irq, dev->dma, dev->bios);
|
||||
pclog("ESDI: I/O=3510, IRQ=14, DMA=%d, BIOS @%05X\n",
|
||||
dev->dma, dev->bios);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1054,9 +1004,6 @@ esdi_init(const device_t *info)
|
||||
/* Mark as unconfigured. */
|
||||
dev->irq_status = 0xff;
|
||||
|
||||
/* This is hardwired. */
|
||||
dev->irq = ESDI_IRQCHAN;
|
||||
|
||||
rom_init_interleaved(&dev->bios_rom,
|
||||
BIOS_FILE_H, BIOS_FILE_L,
|
||||
0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
@@ -1080,7 +1027,7 @@ esdi_init(const device_t *info)
|
||||
drive->spt = hdd[i].spt;
|
||||
drive->hpc = hdd[i].hpc;
|
||||
drive->tracks = hdd[i].tracks;
|
||||
drive->sectors = hdd[i].spt*hdd[i].hpc*hdd[i].tracks;
|
||||
drive->sectors = hdd_image_get_last_sector(i) + 1;
|
||||
drive->hdd_num = i;
|
||||
|
||||
/* Mark drive as present. */
|
||||
|
||||
4859
src/disk/hdc_ide.c
4859
src/disk/hdc_ide.c
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@
|
||||
* Implementation of the IDE emulation for hard disks and ATAPI
|
||||
* CD-ROM devices.
|
||||
*
|
||||
* Version: @(#)hdd_ide.h 1.0.8 2018/03/20
|
||||
* Version: @(#)hdd_ide.h 1.0.9 2018/03/26
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -21,59 +21,53 @@
|
||||
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
int board;
|
||||
uint8_t atastat;
|
||||
uint8_t error;
|
||||
int secount,sector,cylinder,head,drive,cylprecomp;
|
||||
uint8_t command;
|
||||
uint8_t fdisk;
|
||||
int pos;
|
||||
int packlen;
|
||||
int spt,hpc;
|
||||
int t_spt,t_hpc;
|
||||
int tracks;
|
||||
int packetstatus;
|
||||
uint8_t asc;
|
||||
int reset;
|
||||
uint8_t atastat, error,
|
||||
command, fdisk;
|
||||
int type, board,
|
||||
irqstat, service,
|
||||
blocksize, blockcount,
|
||||
hdd_num, channel,
|
||||
pos, sector_pos,
|
||||
lba, skip512,
|
||||
reset, specify_success,
|
||||
mdma_mode, do_initial_read,
|
||||
spt, hpc,
|
||||
tracks;
|
||||
uint32_t secount, sector,
|
||||
cylinder, head,
|
||||
drive, cylprecomp,
|
||||
t_spt, t_hpc,
|
||||
lba_addr;
|
||||
|
||||
uint16_t *buffer;
|
||||
int irqstat;
|
||||
int service;
|
||||
int lba;
|
||||
int channel;
|
||||
uint32_t lba_addr;
|
||||
int skip512;
|
||||
int blocksize, blockcount;
|
||||
uint16_t dma_identify_data[3];
|
||||
int hdi,base;
|
||||
int hdd_num;
|
||||
uint8_t specify_success;
|
||||
int mdma_mode;
|
||||
uint8_t *sector_buffer;
|
||||
int do_initial_read;
|
||||
int sector_pos;
|
||||
} IDE;
|
||||
} ide_t;
|
||||
|
||||
|
||||
extern int ideboard;
|
||||
extern int ide_ter_enabled, ide_qua_enabled;
|
||||
|
||||
extern int ide_enable[5];
|
||||
extern int ide_irq[5];
|
||||
|
||||
extern IDE ide_drives[IDE_NUM + XTIDE_NUM];
|
||||
extern ide_t *ide_drives[IDE_NUM];
|
||||
extern int64_t idecallback[5];
|
||||
|
||||
|
||||
extern void ide_irq_raise(IDE *ide);
|
||||
extern void ide_irq_lower(IDE *ide);
|
||||
extern void ide_irq_raise(ide_t *ide);
|
||||
extern void ide_irq_lower(ide_t *ide);
|
||||
|
||||
extern void writeide(int ide_board, uint16_t addr, uint8_t val);
|
||||
extern void writeidew(int ide_board, uint16_t val);
|
||||
extern uint8_t readide(int ide_board, uint16_t addr);
|
||||
extern uint16_t readidew(int ide_board);
|
||||
extern void callbackide(int ide_board);
|
||||
extern void * ide_xtide_init(void);
|
||||
extern void ide_xtide_close(void);
|
||||
|
||||
extern void ide_set_bus_master(int (*read)(int channel, uint8_t *data, int transfer_length), int (*write)(int channel, uint8_t *data, int transfer_length), void (*set_irq)(int channel));
|
||||
extern void ide_writew(uint16_t addr, uint16_t val, void *priv);
|
||||
extern void ide_write_devctl(uint16_t addr, uint8_t val, void *priv);
|
||||
extern void ide_writeb(uint16_t addr, uint8_t val, void *priv);
|
||||
extern uint8_t ide_readb(uint16_t addr, void *priv);
|
||||
extern uint8_t ide_read_alt_status(uint16_t addr, void *priv);
|
||||
extern uint16_t ide_readw(uint16_t addr, void *priv);
|
||||
|
||||
extern void ide_set_bus_master(int (*read)(int channel, uint8_t *data, int transfer_length, void *priv),
|
||||
int (*write)(int channel, uint8_t *data, int transfer_length, void *priv),
|
||||
void (*set_irq)(int channel, void *priv),
|
||||
void *priv0, void *priv1);
|
||||
|
||||
extern void win_cdrom_eject(uint8_t id);
|
||||
extern void win_cdrom_reload(uint8_t id);
|
||||
@@ -81,36 +75,20 @@ extern void win_cdrom_reload(uint8_t id);
|
||||
extern void ide_set_base(int controller, uint16_t port);
|
||||
extern void ide_set_side(int controller, uint16_t port);
|
||||
|
||||
extern void ide_init_first(void);
|
||||
|
||||
extern void ide_reset(void);
|
||||
extern void ide_reset_hard(void);
|
||||
|
||||
extern void ide_set_all_signatures(void);
|
||||
|
||||
extern void ide_xtide_init(void);
|
||||
|
||||
extern void ide_pri_enable(void);
|
||||
extern void ide_pri_enable_ex(void);
|
||||
extern void ide_pri_disable(void);
|
||||
extern void ide_sec_enable(void);
|
||||
extern void ide_sec_disable(void);
|
||||
extern void ide_ter_enable(void);
|
||||
extern void ide_ter_disable(void);
|
||||
extern void ide_ter_init(void);
|
||||
extern void ide_qua_enable(void);
|
||||
extern void ide_qua_disable(void);
|
||||
extern void ide_qua_init(void);
|
||||
|
||||
extern void ide_set_callback(uint8_t channel, int64_t callback);
|
||||
extern void secondary_ide_check(void);
|
||||
|
||||
extern void ide_padstr8(uint8_t *buf, int buf_size, const char *src);
|
||||
extern void ide_destroy_buffers(void);
|
||||
|
||||
extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length);
|
||||
extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length);
|
||||
extern void (*ide_bus_master_set_irq)(int channel);
|
||||
extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length, void *priv);
|
||||
extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length, void *priv);
|
||||
extern void (*ide_bus_master_set_irq)(int channel, void *priv);
|
||||
extern void *ide_bus_master_priv[2];
|
||||
|
||||
|
||||
#endif /*EMU_IDE_H*/
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* based design. Most cards were WD1003-WA2 or -WAH, where the
|
||||
* -WA2 cards had a floppy controller as well (to save space.)
|
||||
*
|
||||
* Version: @(#)hdc_mfm_at.c 1.0.13 2018/03/18
|
||||
* Version: @(#)hdc_mfm_at.c 1.0.14 2018/04/16
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -110,35 +110,28 @@ typedef struct {
|
||||
} mfm_t;
|
||||
|
||||
|
||||
static __inline void irq_raise(mfm_t *mfm)
|
||||
static inline void
|
||||
irq_raise(mfm_t *mfm)
|
||||
{
|
||||
/* If not already pending.. */
|
||||
if (! mfm->irqstat) {
|
||||
/* If enabled in the control register.. */
|
||||
if (! (mfm->fdisk&0x02)) {
|
||||
/* .. raise IRQ14. */
|
||||
picint(1<<14);
|
||||
}
|
||||
if (!(mfm->fdisk&2))
|
||||
picint(1 << 14);
|
||||
|
||||
/* Remember this. */
|
||||
mfm->irqstat = 1;
|
||||
}
|
||||
mfm->irqstat=1;
|
||||
}
|
||||
|
||||
|
||||
static __inline void irq_lower(mfm_t *mfm)
|
||||
static inline void
|
||||
irq_lower(mfm_t *mfm)
|
||||
{
|
||||
/* If raised.. */
|
||||
if (mfm->irqstat) {
|
||||
/* If enabled in the control register.. */
|
||||
if (! (mfm->fdisk&0x02)) {
|
||||
/* .. drop IRQ14. */
|
||||
picintc(1<<14);
|
||||
}
|
||||
picintc(1 << 14);
|
||||
}
|
||||
|
||||
/* Remember this. */
|
||||
mfm->irqstat = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
irq_update(mfm_t *mfm)
|
||||
{
|
||||
if (mfm->irqstat && !((pic2.pend|pic2.ins)&0x40) && !(mfm->fdisk & 2))
|
||||
picint(1 << 14);
|
||||
}
|
||||
|
||||
|
||||
@@ -233,6 +226,7 @@ mfm_cmd(mfm_t *mfm, uint8_t val)
|
||||
}
|
||||
|
||||
irq_lower(mfm);
|
||||
mfm->command = val;
|
||||
mfm->error = 0;
|
||||
|
||||
switch (val & 0xf0) {
|
||||
@@ -244,13 +238,13 @@ mfm_cmd(mfm_t *mfm, uint8_t val)
|
||||
#endif
|
||||
drive->curcyl = 0;
|
||||
mfm->status = STAT_READY|STAT_DSC;
|
||||
mfm->command = 0x00;
|
||||
mfm->command &= 0xf0;
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
|
||||
case CMD_SEEK:
|
||||
drive->steprate = (val & 0x0f);
|
||||
mfm->command = (val & 0xf0);
|
||||
mfm->command &= 0xf0;
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_clock();
|
||||
mfm->callback = 200LL*MFM_TIME;
|
||||
@@ -258,6 +252,7 @@ mfm_cmd(mfm_t *mfm, uint8_t val)
|
||||
break;
|
||||
|
||||
default:
|
||||
mfm->command = val;
|
||||
switch (val) {
|
||||
case CMD_READ:
|
||||
case CMD_READ+1:
|
||||
@@ -267,7 +262,7 @@ mfm_cmd(mfm_t *mfm, uint8_t val)
|
||||
pclog("WD1003(%d) read, opt=%d\n",
|
||||
mfm->drvsel, val&0x03);
|
||||
#endif
|
||||
mfm->command = (val & 0xf0);
|
||||
mfm->command &= 0xfc;
|
||||
if (val & 2)
|
||||
fatal("WD1003: READ with ECC\n");
|
||||
mfm->status = STAT_BUSY;
|
||||
@@ -284,7 +279,7 @@ mfm_cmd(mfm_t *mfm, uint8_t val)
|
||||
pclog("WD1003(%d) write, opt=%d\n",
|
||||
mfm->drvsel, val & 0x03);
|
||||
#endif
|
||||
mfm->command = (val & 0xf0);
|
||||
mfm->command &= 0xfc;
|
||||
if (val & 2)
|
||||
fatal("WD1003: WRITE with ECC\n");
|
||||
mfm->status = STAT_DRQ|STAT_DSC;
|
||||
@@ -293,7 +288,7 @@ mfm_cmd(mfm_t *mfm, uint8_t val)
|
||||
|
||||
case CMD_VERIFY:
|
||||
case CMD_VERIFY+1:
|
||||
mfm->command = (val & 0xfe);
|
||||
mfm->command &= 0xfe;
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_clock();
|
||||
mfm->callback = 200LL*MFM_TIME;
|
||||
@@ -301,13 +296,11 @@ mfm_cmd(mfm_t *mfm, uint8_t val)
|
||||
break;
|
||||
|
||||
case CMD_FORMAT:
|
||||
mfm->command = val;
|
||||
mfm->status = STAT_DRQ|STAT_BUSY;
|
||||
mfm->pos = 0;
|
||||
break;
|
||||
|
||||
case CMD_DIAGNOSE:
|
||||
mfm->command = val;
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_clock();
|
||||
mfm->callback = 200LL*MFM_TIME;
|
||||
@@ -417,7 +410,7 @@ mfm_write(uint16_t port, uint8_t val, void *priv)
|
||||
mfm->drvsel = (val & 0x10) ? 1 : 0;
|
||||
if (mfm->drives[mfm->drvsel].present)
|
||||
mfm->status = STAT_READY|STAT_DSC;
|
||||
else
|
||||
else
|
||||
mfm->status = 0;
|
||||
return;
|
||||
|
||||
@@ -428,21 +421,22 @@ mfm_write(uint16_t port, uint8_t val, void *priv)
|
||||
case 0x03f6: /* device control */
|
||||
val &= 0x0f;
|
||||
if ((mfm->fdisk & 0x04) && !(val & 0x04)) {
|
||||
mfm->status = STAT_BUSY;
|
||||
mfm->reset = 1;
|
||||
timer_clock();
|
||||
mfm->callback = 500LL*MFM_TIME;
|
||||
timer_update_outstanding();
|
||||
mfm->reset = 1;
|
||||
mfm->status = STAT_BUSY;
|
||||
}
|
||||
|
||||
if (val & 0x04) {
|
||||
/* Drive held in reset. */
|
||||
mfm->status = STAT_BUSY;
|
||||
mfm->callback = 0LL;
|
||||
timer_clock();
|
||||
mfm->callback = 0LL;
|
||||
timer_update_outstanding();
|
||||
mfm->status = STAT_BUSY;
|
||||
}
|
||||
mfm->fdisk = val;
|
||||
irq_update(mfm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -619,19 +613,18 @@ do_callback(void *priv)
|
||||
}
|
||||
|
||||
hdd_image_write(drive->hdd_num, addr, 1,(uint8_t *)mfm->buffer);
|
||||
irq_raise(mfm);
|
||||
mfm->secount = (mfm->secount - 1) & 0xff;
|
||||
|
||||
mfm->status = STAT_READY|STAT_DSC;
|
||||
mfm->secount = (mfm->secount - 1) & 0xff;
|
||||
if (mfm->secount) {
|
||||
/* More sectors to do.. */
|
||||
mfm->status |= STAT_DRQ;
|
||||
mfm->pos = 0;
|
||||
next_sector(mfm);
|
||||
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 1);
|
||||
} else {
|
||||
} else
|
||||
ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0);
|
||||
}
|
||||
irq_raise(mfm);
|
||||
break;
|
||||
|
||||
case CMD_VERIFY:
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
* Since all controllers (including the ones made by DTC) use
|
||||
* (mostly) the same API, we keep them all in this module.
|
||||
*
|
||||
* Version: @(#)hdc_mfm_xt.c 1.0.14 2018/03/18
|
||||
* Version: @(#)hdc_mfm_xt.c 1.0.15 2018/04/18
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -71,7 +71,8 @@
|
||||
#include "hdd.h"
|
||||
|
||||
|
||||
#define MFM_TIME (2000LL*TIMER_USEC)
|
||||
// #define MFM_TIME (2000LL*TIMER_USEC)
|
||||
#define MFM_TIME (50LL*TIMER_USEC)
|
||||
#define XEBEC_BIOS_FILE L"roms/hdd/mfm_xebec/ibm_xebec_62x0822_1985.bin"
|
||||
#define DTC_BIOS_FILE L"roms/hdd/mfm_xebec/dtc_cxd21a.bin"
|
||||
|
||||
@@ -429,7 +430,7 @@ mfm_callback(void *priv)
|
||||
}
|
||||
|
||||
hdd_image_zero(drive->hdd_num, addr, 17);
|
||||
|
||||
|
||||
mfm_complete(mfm);
|
||||
break;
|
||||
|
||||
@@ -757,7 +758,7 @@ loadhd(mfm_t *mfm, int c, int d, const wchar_t *fn)
|
||||
{
|
||||
drive_t *drive = &mfm->drives[d];
|
||||
|
||||
if (! hdd_image_load(d)) {
|
||||
if (! hdd_image_load(c)) {
|
||||
drive->present = 0;
|
||||
return;
|
||||
}
|
||||
@@ -859,7 +860,7 @@ mfm_close(void *priv)
|
||||
static int
|
||||
xebec_available(void)
|
||||
{
|
||||
return(rom_present(XEBEC_BIOS_FILE));
|
||||
return(rom_present(XEBEC_BIOS_FILE));
|
||||
}
|
||||
|
||||
|
||||
@@ -884,7 +885,7 @@ dtc5150x_init(const device_t *info)
|
||||
pclog("MFM: looking for disks..\n");
|
||||
for (i=0; i<HDD_NUM; i++) {
|
||||
if ((hdd[i].bus == HDD_BUS_MFM) && (hdd[i].mfm_channel < MFM_NUM)) {
|
||||
pclog("Found MFM hard disk on channel %i\n", hdd[i].mfm_channel);
|
||||
pclog("Found MFM hard disk on channel %i (%ls)\n", hdd[i].mfm_channel, hdd[i].fn);
|
||||
loadhd(dtc, i, hdd[i].mfm_channel, hdd[i].fn);
|
||||
|
||||
if (++c > MFM_NUM) break;
|
||||
|
||||
1200
src/disk/hdc_xta.c
Normal file
1200
src/disk/hdc_xta.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,7 @@
|
||||
* already on their way out, the newer IDE standard based on the
|
||||
* PC/AT controller and 16b design became the IDE we now know.
|
||||
*
|
||||
* Version: @(#)hdc_xtide.c 1.0.11 2018/03/18
|
||||
* Version: @(#)hdc_xtide.c 1.0.12 2018/04/05
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -52,6 +52,7 @@
|
||||
|
||||
|
||||
typedef struct {
|
||||
void *ide_board;
|
||||
uint8_t data_high;
|
||||
rom_t bios_rom;
|
||||
} xtide_t;
|
||||
@@ -64,7 +65,7 @@ xtide_write(uint16_t port, uint8_t val, void *priv)
|
||||
|
||||
switch (port & 0xf) {
|
||||
case 0x0:
|
||||
writeidew(4, val | (xtide->data_high << 8));
|
||||
ide_writew(0x0, val | (xtide->data_high << 8), xtide->ide_board);
|
||||
return;
|
||||
|
||||
case 0x1:
|
||||
@@ -74,7 +75,7 @@ xtide_write(uint16_t port, uint8_t val, void *priv)
|
||||
case 0x5:
|
||||
case 0x6:
|
||||
case 0x7:
|
||||
writeide(4, (port & 0xf) | 0x1f0, val);
|
||||
ide_writeb((port & 0xf), val, xtide->ide_board);
|
||||
return;
|
||||
|
||||
case 0x8:
|
||||
@@ -82,7 +83,7 @@ xtide_write(uint16_t port, uint8_t val, void *priv)
|
||||
return;
|
||||
|
||||
case 0xe:
|
||||
writeide(4, 0x3f6, val);
|
||||
ide_write_devctl(0x0, val, xtide->ide_board);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -96,7 +97,7 @@ xtide_read(uint16_t port, void *priv)
|
||||
|
||||
switch (port & 0xf) {
|
||||
case 0x0:
|
||||
tempw = readidew(4);
|
||||
tempw = ide_readw(0x0, xtide->ide_board);
|
||||
xtide->data_high = tempw >> 8;
|
||||
break;
|
||||
|
||||
@@ -107,7 +108,7 @@ xtide_read(uint16_t port, void *priv)
|
||||
case 0x5:
|
||||
case 0x6:
|
||||
case 0x7:
|
||||
tempw = readide(4, (port & 0xf) | 0x1f0);
|
||||
tempw = ide_readb((port & 0xf), xtide->ide_board);
|
||||
break;
|
||||
|
||||
case 0x8:
|
||||
@@ -115,7 +116,7 @@ xtide_read(uint16_t port, void *priv)
|
||||
break;
|
||||
|
||||
case 0xe:
|
||||
tempw = readide(4, 0x3f6);
|
||||
tempw = ide_read_alt_status(0x0, xtide->ide_board);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -136,7 +137,7 @@ xtide_init(const device_t *info)
|
||||
rom_init(&xtide->bios_rom, ROM_PATH_XT,
|
||||
0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
|
||||
ide_xtide_init();
|
||||
xtide->ide_board = ide_xtide_init();
|
||||
|
||||
io_sethandler(0x0300, 16,
|
||||
xtide_read, NULL, NULL,
|
||||
@@ -186,7 +187,7 @@ xtide_acculogic_init(const device_t *info)
|
||||
rom_init(&xtide->bios_rom, ROM_PATH_PS2,
|
||||
0xc8000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
|
||||
ide_xtide_init();
|
||||
xtide->ide_board = ide_xtide_init();
|
||||
|
||||
io_sethandler(0x0360, 16,
|
||||
xtide_read, NULL, NULL,
|
||||
@@ -203,6 +204,17 @@ xtide_acculogic_available(void)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
xtide_close(void *priv)
|
||||
{
|
||||
xtide_t *xtide = (xtide_t *)priv;
|
||||
|
||||
free(xtide);
|
||||
|
||||
ide_xtide_close();
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
xtide_at_ps2_init(const device_t *info)
|
||||
{
|
||||
@@ -227,7 +239,7 @@ xtide_at_ps2_available(void)
|
||||
|
||||
|
||||
static void
|
||||
xtide_close(void *priv)
|
||||
xtide_at_close(void *priv)
|
||||
{
|
||||
xtide_t *xtide = (xtide_t *)priv;
|
||||
|
||||
@@ -248,7 +260,7 @@ const device_t xtide_at_device = {
|
||||
"XTIDE (AT)",
|
||||
DEVICE_ISA | DEVICE_AT,
|
||||
0,
|
||||
xtide_at_init, xtide_close, NULL,
|
||||
xtide_at_init, xtide_at_close, NULL,
|
||||
xtide_at_available, NULL, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
@@ -266,7 +278,7 @@ const device_t xtide_at_ps2_device = {
|
||||
"XTIDE (AT) (1.1.5)",
|
||||
DEVICE_ISA | DEVICE_PS2,
|
||||
0,
|
||||
xtide_at_ps2_init, xtide_close, NULL,
|
||||
xtide_at_ps2_init, xtide_at_close, NULL,
|
||||
xtide_at_ps2_available, NULL, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
*
|
||||
* Common code to handle all sorts of hard disk images.
|
||||
*
|
||||
* Version: @(#)hdd.c 1.0.7 2017/11/18
|
||||
* Version: @(#)hdd.c 1.0.8 2018/04/24
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
* Copyright 2017 Fred N. van Kempen.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
@@ -63,53 +63,35 @@ no_cdrom:
|
||||
}
|
||||
|
||||
if (! strcmp(str, "ide_pio_only"))
|
||||
return(HDD_BUS_IDE_PIO_ONLY);
|
||||
return(HDD_BUS_IDE);
|
||||
|
||||
if (! strcmp(str, "ide"))
|
||||
return(HDD_BUS_IDE_PIO_ONLY);
|
||||
return(HDD_BUS_IDE);
|
||||
|
||||
if (! strcmp(str, "atapi_pio_only"))
|
||||
return(HDD_BUS_IDE_PIO_ONLY);
|
||||
return(HDD_BUS_IDE);
|
||||
|
||||
if (! strcmp(str, "atapi"))
|
||||
return(HDD_BUS_IDE_PIO_ONLY);
|
||||
return(HDD_BUS_IDE);
|
||||
|
||||
if (! strcmp(str, "eide"))
|
||||
return(HDD_BUS_IDE_PIO_ONLY);
|
||||
return(HDD_BUS_IDE);
|
||||
|
||||
if (! strcmp(str, "xtide"))
|
||||
return(HDD_BUS_XTIDE);
|
||||
if (! strcmp(str, "xta"))
|
||||
return(HDD_BUS_XTA);
|
||||
|
||||
if (! strcmp(str, "atide"))
|
||||
return(HDD_BUS_IDE_PIO_ONLY);
|
||||
return(HDD_BUS_IDE);
|
||||
|
||||
if (! strcmp(str, "ide_pio_and_dma"))
|
||||
return(HDD_BUS_IDE_PIO_AND_DMA);
|
||||
return(HDD_BUS_IDE);
|
||||
|
||||
if (! strcmp(str, "atapi_pio_and_dma"))
|
||||
return(HDD_BUS_IDE_PIO_AND_DMA);
|
||||
return(HDD_BUS_IDE);
|
||||
|
||||
if (! strcmp(str, "scsi"))
|
||||
return(HDD_BUS_SCSI);
|
||||
|
||||
if (! strcmp(str, "removable")) {
|
||||
if (cdrom) goto no_cdrom;
|
||||
|
||||
return(HDD_BUS_SCSI_REMOVABLE);
|
||||
}
|
||||
|
||||
if (! strcmp(str, "scsi_removable")) {
|
||||
if (cdrom) goto no_cdrom;
|
||||
|
||||
return(HDD_BUS_SCSI_REMOVABLE);
|
||||
}
|
||||
|
||||
if (! strcmp(str, "removable_scsi")) {
|
||||
if (cdrom) goto no_cdrom;
|
||||
|
||||
return(HDD_BUS_SCSI_REMOVABLE);
|
||||
}
|
||||
|
||||
if (! strcmp(str, "usb"))
|
||||
ui_msgbox(MBX_ERROR, (wchar_t *)IDS_4110);
|
||||
|
||||
@@ -131,29 +113,21 @@ hdd_bus_to_string(int bus, int cdrom)
|
||||
s = "mfm";
|
||||
break;
|
||||
|
||||
case HDD_BUS_XTIDE:
|
||||
s = "xtide";
|
||||
case HDD_BUS_XTA:
|
||||
s = "xta";
|
||||
break;
|
||||
|
||||
case HDD_BUS_ESDI:
|
||||
s = "esdi";
|
||||
break;
|
||||
|
||||
case HDD_BUS_IDE_PIO_ONLY:
|
||||
s = cdrom ? "atapi_pio_only" : "ide_pio_only";
|
||||
break;
|
||||
|
||||
case HDD_BUS_IDE_PIO_AND_DMA:
|
||||
s = cdrom ? "atapi_pio_and_dma" : "ide_pio_and_dma";
|
||||
case HDD_BUS_IDE:
|
||||
s = cdrom ? "atapi" : "ide";
|
||||
break;
|
||||
|
||||
case HDD_BUS_SCSI:
|
||||
s = "scsi";
|
||||
break;
|
||||
|
||||
case HDD_BUS_SCSI_REMOVABLE:
|
||||
s = "scsi_removable";
|
||||
break;
|
||||
}
|
||||
|
||||
return(s);
|
||||
@@ -163,12 +137,14 @@ hdd_bus_to_string(int bus, int cdrom)
|
||||
int
|
||||
hdd_is_valid(int c)
|
||||
{
|
||||
if (hdd[c].bus == HDD_BUS_DISABLED) return(0);
|
||||
if (hdd[c].bus == HDD_BUS_DISABLED)
|
||||
return(0);
|
||||
|
||||
if ((wcslen(hdd[c].fn) == 0) &&
|
||||
(hdd[c].bus != HDD_BUS_SCSI_REMOVABLE)) return(0);
|
||||
if (wcslen(hdd[c].fn) == 0)
|
||||
return(0);
|
||||
|
||||
if ((hdd[c].tracks==0) || (hdd[c].hpc==0) || (hdd[c].spt==0)) return(0);
|
||||
if ((hdd[c].tracks==0) || (hdd[c].hpc==0) || (hdd[c].spt==0))
|
||||
return(0);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
*
|
||||
* Definitions for the hard disk image handler.
|
||||
*
|
||||
* Version: @(#)hdd.h 1.0.3 2017/10/05
|
||||
* Version: @(#)hdd.h 1.0.4 2018/03/29
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
* Copyright 2017 Fred N. van Kempen.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*/
|
||||
#ifndef EMU_HDD_H
|
||||
# define EMU_HDD_H
|
||||
@@ -23,17 +23,53 @@
|
||||
|
||||
|
||||
/* Hard Disk bus types. */
|
||||
#if 0
|
||||
/* Bit 4 = DMA supported (0 = no, 1 yes) - used for IDE and ATAPI only;
|
||||
Bit 5 = Removable (0 = no, 1 yes). */
|
||||
|
||||
enum {
|
||||
BUS_DISABLED = 0x00,
|
||||
|
||||
BUS_MFM = 0x01, /* These four are for hard disk only. */
|
||||
BUS_XIDE = 0x02,
|
||||
BUS_XTA = 0x03,
|
||||
BUS_ESDI = 0x04,
|
||||
|
||||
BUS_PANASONIC = 0x21, / These four are for CD-ROM only. */
|
||||
BUS_PHILIPS = 0x22,
|
||||
BUS_SONY = 0x23,
|
||||
BUS_MITSUMI = 0x24,
|
||||
|
||||
BUS_IDE_PIO_ONLY = 0x05,
|
||||
BUS_IDE_PIO_AND_DMA = 0x15,
|
||||
BUS_IDE_R_PIO_ONLY = 0x25,
|
||||
BUS_IDE_R_PIO_AND_DMA = 0x35,
|
||||
|
||||
BUS_ATAPI_PIO_ONLY = 0x06,
|
||||
BUS_ATAPI_PIO_AND_DMA = 0x16,
|
||||
BUS_ATAPI_R_PIO_ONLY = 0x26,
|
||||
BUS_ATAPI_R_PIO_AND_DMA = 0x36,
|
||||
|
||||
BUS_SASI = 0x07,
|
||||
BUS_SASI_R = 0x27,
|
||||
|
||||
BUS_SCSI = 0x08,
|
||||
BUS_SCSI_R = 0x28,
|
||||
|
||||
BUS_USB = 0x09,
|
||||
BUS_USB_R = 0x29
|
||||
};
|
||||
#else
|
||||
enum {
|
||||
HDD_BUS_DISABLED = 0,
|
||||
HDD_BUS_MFM,
|
||||
HDD_BUS_XTIDE,
|
||||
HDD_BUS_XTA,
|
||||
HDD_BUS_ESDI,
|
||||
HDD_BUS_IDE_PIO_ONLY,
|
||||
HDD_BUS_IDE_PIO_AND_DMA,
|
||||
HDD_BUS_IDE,
|
||||
HDD_BUS_SCSI,
|
||||
HDD_BUS_SCSI_REMOVABLE,
|
||||
HDD_BUS_USB
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the virtual Hard Disk. */
|
||||
@@ -45,18 +81,16 @@ typedef struct {
|
||||
|
||||
uint8_t mfm_channel; /* should rename and/or unionize */
|
||||
uint8_t esdi_channel;
|
||||
uint8_t xtide_channel;
|
||||
uint8_t xta_channel;
|
||||
uint8_t ide_channel;
|
||||
uint8_t scsi_id;
|
||||
uint8_t scsi_lun;
|
||||
|
||||
uint32_t base;
|
||||
|
||||
uint64_t spt,
|
||||
uint32_t base,
|
||||
spt,
|
||||
hpc, /* physical geometry parameters */
|
||||
tracks;
|
||||
|
||||
uint64_t at_spt, /* [Translation] parameters */
|
||||
tracks,
|
||||
at_spt, /* [Translation] parameters */
|
||||
at_hpc;
|
||||
|
||||
FILE *f; /* current file handle to image */
|
||||
@@ -67,7 +101,7 @@ typedef struct {
|
||||
|
||||
|
||||
extern hard_disk_t hdd[HDD_NUM];
|
||||
extern uint64_t hdd_table[128][3];
|
||||
extern unsigned int hdd_table[128][3];
|
||||
|
||||
|
||||
extern int hdd_init(void);
|
||||
@@ -75,6 +109,7 @@ extern int hdd_string_to_bus(char *str, int cdrom);
|
||||
extern char *hdd_bus_to_string(int bus, int cdrom);
|
||||
extern int hdd_is_valid(int c);
|
||||
|
||||
extern void hdd_image_init(void);
|
||||
extern int hdd_image_load(int id);
|
||||
extern void hdd_image_seek(uint8_t id, uint32_t sector);
|
||||
extern void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Handling of hard disk image files.
|
||||
*
|
||||
* Version: @(#)hdd_image.c 1.0.13 2018/03/19
|
||||
* Version: @(#)hdd_image.c 1.0.14 2018/03/28
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -34,11 +34,11 @@
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FILE *file;
|
||||
uint32_t base;
|
||||
uint32_t last_sector;
|
||||
uint8_t type;
|
||||
uint8_t loaded;
|
||||
FILE *file;
|
||||
uint32_t base;
|
||||
uint32_t last_sector;
|
||||
uint8_t type;
|
||||
uint8_t loaded;
|
||||
} hdd_image_t;
|
||||
|
||||
|
||||
@@ -69,393 +69,442 @@ hdd_image_log(const char *fmt, ...)
|
||||
}
|
||||
|
||||
|
||||
int image_is_hdi(const wchar_t *s)
|
||||
int
|
||||
image_is_hdi(const wchar_t *s)
|
||||
{
|
||||
int len;
|
||||
wchar_t ext[5] = { 0, 0, 0, 0, 0 };
|
||||
char *ws = (char *) s;
|
||||
len = wcslen(s);
|
||||
if ((len < 4) || (s[0] == L'.'))
|
||||
return 0;
|
||||
memcpy(ext, ws + ((len - 4) << 1), 8);
|
||||
if (! wcscasecmp(ext, L".HDI"))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
int len;
|
||||
wchar_t ext[5] = { 0, 0, 0, 0, 0 };
|
||||
char *ws = (char *) s;
|
||||
len = wcslen(s);
|
||||
if ((len < 4) || (s[0] == L'.'))
|
||||
return 0;
|
||||
memcpy(ext, ws + ((len - 4) << 1), 8);
|
||||
if (! wcscasecmp(ext, L".HDI"))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
image_is_hdx(const wchar_t *s, int check_signature)
|
||||
{
|
||||
int len;
|
||||
FILE *f;
|
||||
uint64_t filelen;
|
||||
uint64_t signature;
|
||||
char *ws = (char *) s;
|
||||
wchar_t ext[5] = { 0, 0, 0, 0, 0 };
|
||||
len = wcslen(s);
|
||||
if ((len < 4) || (s[0] == L'.'))
|
||||
return 0;
|
||||
memcpy(ext, ws + ((len - 4) << 1), 8);
|
||||
if (wcscasecmp(ext, L".HDX") == 0) {
|
||||
if (check_signature) {
|
||||
f = plat_fopen((wchar_t *)s, L"rb");
|
||||
if (!f)
|
||||
return 0;
|
||||
fseeko64(f, 0, SEEK_END);
|
||||
filelen = ftello64(f);
|
||||
fseeko64(f, 0, SEEK_SET);
|
||||
if (filelen < 44)
|
||||
return 0;
|
||||
fread(&signature, 1, 8, f);
|
||||
fclose(f);
|
||||
if (signature == 0xD778A82044445459ll)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
int len;
|
||||
FILE *f;
|
||||
uint64_t filelen;
|
||||
uint64_t signature;
|
||||
char *ws = (char *) s;
|
||||
wchar_t ext[5] = { 0, 0, 0, 0, 0 };
|
||||
len = wcslen(s);
|
||||
if ((len < 4) || (s[0] == L'.'))
|
||||
return 0;
|
||||
memcpy(ext, ws + ((len - 4) << 1), 8);
|
||||
if (wcscasecmp(ext, L".HDX") == 0) {
|
||||
if (check_signature) {
|
||||
f = plat_fopen((wchar_t *)s, L"rb");
|
||||
if (!f)
|
||||
return 0;
|
||||
fseeko64(f, 0, SEEK_END);
|
||||
filelen = ftello64(f);
|
||||
fseeko64(f, 0, SEEK_SET);
|
||||
if (filelen < 44)
|
||||
return 0;
|
||||
fread(&signature, 1, 8, f);
|
||||
fclose(f);
|
||||
if (signature == 0xD778A82044445459ll)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hdd_image_load(int id)
|
||||
static int
|
||||
prepare_new_hard_disk(uint8_t id, uint64_t full_size)
|
||||
{
|
||||
uint32_t sector_size = 512;
|
||||
uint32_t zero = 0;
|
||||
uint64_t signature = 0xD778A82044445459ll;
|
||||
uint64_t full_size = 0;
|
||||
uint64_t spt = 0, hpc = 0, tracks = 0;
|
||||
int c;
|
||||
uint64_t i = 0, s = 0, t = 0;
|
||||
wchar_t *fn = hdd[id].fn;
|
||||
int is_hdx[2] = { 0, 0 };
|
||||
uint64_t target_size = (full_size + hdd_images[id].base) - ftello64(hdd_images[id].file);
|
||||
|
||||
memset(empty_sector, 0, sizeof(empty_sector));
|
||||
uint32_t size;
|
||||
uint32_t t, i;
|
||||
|
||||
hdd_images[id].base = 0;
|
||||
t = (uint32_t) (target_size >> 20); /* Amount of 1 MB blocks. */
|
||||
size = (uint32_t) (target_size & 0xfffff); /* 1 MB mask. */
|
||||
|
||||
if (hdd_images[id].loaded) {
|
||||
if (hdd_images[id].file) {
|
||||
fclose(hdd_images[id].file);
|
||||
hdd_images[id].file = NULL;
|
||||
}
|
||||
hdd_images[id].loaded = 0;
|
||||
empty_sector_1mb = (char *) malloc(1048576);
|
||||
memset(empty_sector_1mb, 0, 1048576);
|
||||
|
||||
/* Temporarily switch off suppression of seen messages so that the
|
||||
progress gets displayed. */
|
||||
pclog_toggle_suppr();
|
||||
pclog("Writing image sectors: [");
|
||||
|
||||
/* First, write all the 1 MB blocks. */
|
||||
if (t > 0) {
|
||||
for (i = 0; i < t; i++) {
|
||||
fwrite(empty_sector_1mb, 1, 1045876, hdd_images[id].file);
|
||||
pclog("#");
|
||||
}
|
||||
}
|
||||
|
||||
is_hdx[0] = image_is_hdx(fn, 0);
|
||||
is_hdx[1] = image_is_hdx(fn, 1);
|
||||
/* Then, write the remainder. */
|
||||
fwrite(empty_sector_1mb, 1, size, hdd_images[id].file);
|
||||
pclog("#]\n");
|
||||
/* Switch the suppression of seen messages back on. */
|
||||
pclog_toggle_suppr();
|
||||
|
||||
/* Try to open existing hard disk image */
|
||||
if (fn[0] == '.') {
|
||||
hdd_image_log("File name starts with .\n");
|
||||
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
||||
return 0;
|
||||
free(empty_sector_1mb);
|
||||
|
||||
hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1;
|
||||
|
||||
hdd_images[id].loaded = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
hdd_image_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < HDD_NUM; i++)
|
||||
memset(&hdd_images[i], 0, sizeof(hdd_image_t));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hdd_image_load(int id)
|
||||
{
|
||||
uint32_t sector_size = 512;
|
||||
uint32_t zero = 0;
|
||||
uint64_t signature = 0xD778A82044445459ll;
|
||||
uint64_t full_size = 0;
|
||||
uint64_t spt = 0, hpc = 0, tracks = 0;
|
||||
int c;
|
||||
uint64_t s = 0;
|
||||
wchar_t *fn = hdd[id].fn;
|
||||
int is_hdx[2] = { 0, 0 };
|
||||
|
||||
memset(empty_sector, 0, sizeof(empty_sector));
|
||||
|
||||
hdd_images[id].base = 0;
|
||||
|
||||
if (hdd_images[id].loaded) {
|
||||
if (hdd_images[id].file) {
|
||||
fclose(hdd_images[id].file);
|
||||
hdd_images[id].file = NULL;
|
||||
}
|
||||
hdd_images[id].file = plat_fopen(fn, L"rb+");
|
||||
if (hdd_images[id].file == NULL) {
|
||||
/* Failed to open existing hard disk image */
|
||||
if (errno == ENOENT) {
|
||||
/* Failed because it does not exist,
|
||||
so try to create new file */
|
||||
if (hdd[id].wp) {
|
||||
hdd_image_log("A write-protected image must exist\n");
|
||||
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
||||
return 0;
|
||||
}
|
||||
hdd_images[id].loaded = 0;
|
||||
}
|
||||
|
||||
hdd_images[id].file = plat_fopen(fn, L"wb+");
|
||||
if (hdd_images[id].file == NULL) {
|
||||
hdd_image_log("Unable to open image\n");
|
||||
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
||||
return 0;
|
||||
} else {
|
||||
if (image_is_hdi(fn)) {
|
||||
full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512;
|
||||
hdd_images[id].base = 0x1000;
|
||||
fwrite(&zero, 1, 4, hdd_images[id].file);
|
||||
fwrite(&zero, 1, 4, hdd_images[id].file);
|
||||
fwrite(&(hdd_images[id].base), 1, 4, hdd_images[id].file);
|
||||
fwrite(&full_size, 1, 4, hdd_images[id].file);
|
||||
fwrite(§or_size, 1, 4, hdd_images[id].file);
|
||||
fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file);
|
||||
fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file);
|
||||
fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file);
|
||||
for (c = 0; c < 0x3f8; c++)
|
||||
fwrite(&zero, 1, 4, hdd_images[id].file);
|
||||
hdd_images[id].type = 1;
|
||||
} else if (is_hdx[0]) {
|
||||
full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512;
|
||||
hdd_images[id].base = 0x28;
|
||||
fwrite(&signature, 1, 8, hdd_images[id].file);
|
||||
fwrite(&full_size, 1, 8, hdd_images[id].file);
|
||||
fwrite(§or_size, 1, 4, hdd_images[id].file);
|
||||
fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file);
|
||||
fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file);
|
||||
fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file);
|
||||
fwrite(&zero, 1, 4, hdd_images[id].file);
|
||||
fwrite(&zero, 1, 4, hdd_images[id].file);
|
||||
hdd_images[id].type = 2;
|
||||
}
|
||||
else
|
||||
hdd_images[id].type = 0;
|
||||
hdd_images[id].last_sector = 0;
|
||||
}
|
||||
is_hdx[0] = image_is_hdx(fn, 0);
|
||||
is_hdx[1] = image_is_hdx(fn, 1);
|
||||
|
||||
s = full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512;
|
||||
|
||||
goto prepare_new_hard_disk;
|
||||
} else {
|
||||
/* Failed for another reason */
|
||||
hdd_image_log("Failed for another reason\n");
|
||||
/* Try to open existing hard disk image */
|
||||
if (fn[0] == '.') {
|
||||
hdd_image_log("File name starts with .\n");
|
||||
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
||||
return 0;
|
||||
}
|
||||
hdd_images[id].file = plat_fopen(fn, L"rb+");
|
||||
if (hdd_images[id].file == NULL) {
|
||||
/* Failed to open existing hard disk image */
|
||||
if (errno == ENOENT) {
|
||||
/* Failed because it does not exist,
|
||||
so try to create new file */
|
||||
if (hdd[id].wp) {
|
||||
hdd_image_log("A write-protected image must exist\n");
|
||||
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (image_is_hdi(fn)) {
|
||||
fseeko64(hdd_images[id].file, 0x8, SEEK_SET);
|
||||
fread(&(hdd_images[id].base), 1, 4, hdd_images[id].file);
|
||||
fseeko64(hdd_images[id].file, 0xC, SEEK_SET);
|
||||
full_size = 0;
|
||||
fread(&full_size, 1, 4, hdd_images[id].file);
|
||||
fseeko64(hdd_images[id].file, 0x10, SEEK_SET);
|
||||
fread(§or_size, 1, 4, hdd_images[id].file);
|
||||
if (sector_size != 512) {
|
||||
/* Sector size is not 512 */
|
||||
hdd_image_log("HDI: Sector size is not 512\n");
|
||||
fclose(hdd_images[id].file);
|
||||
hdd_images[id].file = NULL;
|
||||
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
||||
return 0;
|
||||
}
|
||||
fread(&spt, 1, 4, hdd_images[id].file);
|
||||
fread(&hpc, 1, 4, hdd_images[id].file);
|
||||
fread(&tracks, 1, 4, hdd_images[id].file);
|
||||
if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) {
|
||||
if ((spt != hdd[id].spt) || (hpc != hdd[id].hpc) || (tracks != hdd[id].tracks)) {
|
||||
hdd_image_log("HDI: Geometry mismatch\n");
|
||||
fclose(hdd_images[id].file);
|
||||
hdd_images[id].file = NULL;
|
||||
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
hdd[id].spt = spt;
|
||||
hdd[id].hpc = hpc;
|
||||
hdd[id].tracks = tracks;
|
||||
hdd_images[id].type = 1;
|
||||
}
|
||||
else if (is_hdx[1]) {
|
||||
hdd_images[id].base = 0x28;
|
||||
fseeko64(hdd_images[id].file, 8, SEEK_SET);
|
||||
fread(&full_size, 1, 8, hdd_images[id].file);
|
||||
fseeko64(hdd_images[id].file, 0x10, SEEK_SET);
|
||||
fread(§or_size, 1, 4, hdd_images[id].file);
|
||||
if (sector_size != 512) {
|
||||
/* Sector size is not 512 */
|
||||
hdd_image_log("HDX: Sector size is not 512\n");
|
||||
fclose(hdd_images[id].file);
|
||||
hdd_images[id].file = NULL;
|
||||
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
||||
return 0;
|
||||
}
|
||||
fread(&spt, 1, 4, hdd_images[id].file);
|
||||
fread(&hpc, 1, 4, hdd_images[id].file);
|
||||
fread(&tracks, 1, 4, hdd_images[id].file);
|
||||
if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) {
|
||||
if ((spt != hdd[id].spt) || (hpc != hdd[id].hpc) || (tracks != hdd[id].tracks)) {
|
||||
hdd_image_log("HDX: Geometry mismatch\n");
|
||||
fclose(hdd_images[id].file);
|
||||
hdd_images[id].file = NULL;
|
||||
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
hdd[id].spt = spt;
|
||||
hdd[id].hpc = hpc;
|
||||
hdd[id].tracks = tracks;
|
||||
fread(&(hdd[id].at_spt), 1, 4, hdd_images[id].file);
|
||||
fread(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file);
|
||||
hdd_images[id].type = 2;
|
||||
|
||||
hdd_images[id].file = plat_fopen(fn, L"wb+");
|
||||
if (hdd_images[id].file == NULL) {
|
||||
hdd_image_log("Unable to open image\n");
|
||||
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
||||
return 0;
|
||||
} else {
|
||||
full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512;
|
||||
hdd_images[id].type = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fseeko64(hdd_images[id].file, 0, SEEK_END);
|
||||
if (ftello64(hdd_images[id].file) < (full_size + hdd_images[id].base)) {
|
||||
s = (full_size + hdd_images[id].base) - ftello64(hdd_images[id].file);
|
||||
prepare_new_hard_disk:
|
||||
t = s >> 20; /* Amount of 1 MB blocks. */
|
||||
s &= 0xfffff; /* 1 MB mask. */
|
||||
|
||||
empty_sector_1mb = (char *) malloc(1048576);
|
||||
memset(empty_sector_1mb, 0, 1048576);
|
||||
|
||||
/* Temporarily switch off suppression of seen messages so that the
|
||||
progress gets displayed. */
|
||||
pclog_toggle_suppr();
|
||||
pclog("Writing image sectors: [");
|
||||
|
||||
/* First, write all the 1 MB blocks. */
|
||||
if (t > 0) {
|
||||
for (i = 0; i < t; i++) {
|
||||
fwrite(empty_sector_1mb, 1, 1045876, hdd_images[id].file);
|
||||
pclog("#");
|
||||
if (image_is_hdi(fn)) {
|
||||
full_size = ((uint64_t) hdd[id].spt) *
|
||||
((uint64_t) hdd[id].hpc) *
|
||||
((uint64_t) hdd[id].tracks) << 9LL;
|
||||
hdd_images[id].base = 0x1000;
|
||||
fwrite(&zero, 1, 4, hdd_images[id].file);
|
||||
fwrite(&zero, 1, 4, hdd_images[id].file);
|
||||
fwrite(&(hdd_images[id].base), 1, 4, hdd_images[id].file);
|
||||
fwrite(&full_size, 1, 4, hdd_images[id].file);
|
||||
fwrite(§or_size, 1, 4, hdd_images[id].file);
|
||||
fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file);
|
||||
fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file);
|
||||
fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file);
|
||||
for (c = 0; c < 0x3f8; c++)
|
||||
fwrite(&zero, 1, 4, hdd_images[id].file);
|
||||
hdd_images[id].type = 1;
|
||||
} else if (is_hdx[0]) {
|
||||
full_size = ((uint64_t) hdd[id].spt) *
|
||||
((uint64_t) hdd[id].hpc) *
|
||||
((uint64_t) hdd[id].tracks) << 9LL;
|
||||
hdd_images[id].base = 0x28;
|
||||
fwrite(&signature, 1, 8, hdd_images[id].file);
|
||||
fwrite(&full_size, 1, 8, hdd_images[id].file);
|
||||
fwrite(§or_size, 1, 4, hdd_images[id].file);
|
||||
fwrite(&(hdd[id].spt), 1, 4, hdd_images[id].file);
|
||||
fwrite(&(hdd[id].hpc), 1, 4, hdd_images[id].file);
|
||||
fwrite(&(hdd[id].tracks), 1, 4, hdd_images[id].file);
|
||||
fwrite(&zero, 1, 4, hdd_images[id].file);
|
||||
fwrite(&zero, 1, 4, hdd_images[id].file);
|
||||
hdd_images[id].type = 2;
|
||||
}
|
||||
else
|
||||
hdd_images[id].type = 0;
|
||||
hdd_images[id].last_sector = 0;
|
||||
}
|
||||
|
||||
/* Then, write the remainder. */
|
||||
fwrite(empty_sector_1mb, 1, s, hdd_images[id].file);
|
||||
pclog("#]\n");
|
||||
pclog_toggle_suppr();
|
||||
s = full_size = ((uint64_t) hdd[id].spt) *
|
||||
((uint64_t) hdd[id].hpc) *
|
||||
((uint64_t) hdd[id].tracks) << 9LL;
|
||||
|
||||
free(empty_sector_1mb);
|
||||
return prepare_new_hard_disk(id, full_size);
|
||||
} else {
|
||||
/* Failed for another reason */
|
||||
hdd_image_log("Failed for another reason\n");
|
||||
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
||||
return 0;
|
||||
}
|
||||
|
||||
hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1;
|
||||
|
||||
hdd_images[id].loaded = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void hdd_image_seek(uint8_t id, uint32_t sector)
|
||||
{
|
||||
off64_t addr = sector;
|
||||
addr = (uint64_t)sector * 512;
|
||||
|
||||
fseeko64(hdd_images[id].file, addr + hdd_images[id].base, SEEK_SET);
|
||||
}
|
||||
|
||||
void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
||||
{
|
||||
fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET);
|
||||
fread(buffer, 1, count * 512, hdd_images[id].file);
|
||||
}
|
||||
|
||||
uint32_t hdd_sectors(uint8_t id)
|
||||
{
|
||||
fseeko64(hdd_images[id].file, 0, SEEK_END);
|
||||
return (uint32_t) (ftello64(hdd_images[id].file) >> 9);
|
||||
}
|
||||
|
||||
int hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
||||
{
|
||||
uint32_t transfer_sectors = count;
|
||||
uint32_t sectors = hdd_sectors(id);
|
||||
|
||||
if ((sectors - sector) < transfer_sectors)
|
||||
transfer_sectors = sectors - sector;
|
||||
|
||||
fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET);
|
||||
fread(buffer, 1, transfer_sectors * 512, hdd_images[id].file);
|
||||
|
||||
if (count != transfer_sectors)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
||||
{
|
||||
fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET);
|
||||
fwrite(buffer, count * 512, 1, hdd_images[id].file);
|
||||
}
|
||||
|
||||
int hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
||||
{
|
||||
uint32_t transfer_sectors = count;
|
||||
uint32_t sectors = hdd_sectors(id);
|
||||
|
||||
if ((sectors - sector) < transfer_sectors)
|
||||
transfer_sectors = sectors - sector;
|
||||
|
||||
fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET);
|
||||
fwrite(buffer, transfer_sectors * 512, 1, hdd_images[id].file);
|
||||
|
||||
if (count != transfer_sectors)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET);
|
||||
for (i = 0; i < count; i++)
|
||||
fwrite(empty_sector, 512, 1, hdd_images[id].file);
|
||||
}
|
||||
|
||||
int hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
uint32_t transfer_sectors = count;
|
||||
uint32_t sectors = hdd_sectors(id);
|
||||
|
||||
if ((sectors - sector) < transfer_sectors)
|
||||
transfer_sectors = sectors - sector;
|
||||
|
||||
fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET);
|
||||
for (i = 0; i < transfer_sectors; i++)
|
||||
fwrite(empty_sector, 1, 512, hdd_images[id].file);
|
||||
|
||||
if (count != transfer_sectors)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t hdd_image_get_last_sector(uint8_t id)
|
||||
{
|
||||
return hdd_images[id].last_sector;
|
||||
}
|
||||
|
||||
uint8_t hdd_image_get_type(uint8_t id)
|
||||
{
|
||||
return hdd_images[id].type;
|
||||
}
|
||||
|
||||
void hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt)
|
||||
{
|
||||
if (hdd_images[id].type == 2)
|
||||
{
|
||||
hdd[id].at_hpc = hpc;
|
||||
hdd[id].at_spt = spt;
|
||||
fseeko64(hdd_images[id].file, 0x20, SEEK_SET);
|
||||
fwrite(&(hdd[id].at_spt), 1, 4, hdd_images[id].file);
|
||||
fwrite(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file);
|
||||
}
|
||||
}
|
||||
|
||||
void hdd_image_unload(uint8_t id, int fn_preserve)
|
||||
{
|
||||
if (wcslen(hdd[id].fn) == 0)
|
||||
return;
|
||||
|
||||
if (hdd_images[id].loaded) {
|
||||
if (hdd_images[id].file != NULL) {
|
||||
} else {
|
||||
if (image_is_hdi(fn)) {
|
||||
fseeko64(hdd_images[id].file, 0x8, SEEK_SET);
|
||||
fread(&(hdd_images[id].base), 1, 4, hdd_images[id].file);
|
||||
fseeko64(hdd_images[id].file, 0xC, SEEK_SET);
|
||||
full_size = 0LL;
|
||||
fread(&full_size, 1, 4, hdd_images[id].file);
|
||||
fseeko64(hdd_images[id].file, 0x10, SEEK_SET);
|
||||
fread(§or_size, 1, 4, hdd_images[id].file);
|
||||
if (sector_size != 512) {
|
||||
/* Sector size is not 512 */
|
||||
hdd_image_log("HDI: Sector size is not 512\n");
|
||||
fclose(hdd_images[id].file);
|
||||
hdd_images[id].file = NULL;
|
||||
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
||||
return 0;
|
||||
}
|
||||
hdd_images[id].loaded = 0;
|
||||
fread(&spt, 1, 4, hdd_images[id].file);
|
||||
fread(&hpc, 1, 4, hdd_images[id].file);
|
||||
fread(&tracks, 1, 4, hdd_images[id].file);
|
||||
hdd[id].spt = spt;
|
||||
hdd[id].hpc = hpc;
|
||||
hdd[id].tracks = tracks;
|
||||
hdd_images[id].type = 1;
|
||||
} else if (is_hdx[1]) {
|
||||
hdd_images[id].base = 0x28;
|
||||
fseeko64(hdd_images[id].file, 8, SEEK_SET);
|
||||
fread(&full_size, 1, 8, hdd_images[id].file);
|
||||
fseeko64(hdd_images[id].file, 0x10, SEEK_SET);
|
||||
fread(§or_size, 1, 4, hdd_images[id].file);
|
||||
if (sector_size != 512) {
|
||||
/* Sector size is not 512 */
|
||||
hdd_image_log("HDX: Sector size is not 512\n");
|
||||
fclose(hdd_images[id].file);
|
||||
hdd_images[id].file = NULL;
|
||||
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
||||
return 0;
|
||||
}
|
||||
fread(&spt, 1, 4, hdd_images[id].file);
|
||||
fread(&hpc, 1, 4, hdd_images[id].file);
|
||||
fread(&tracks, 1, 4, hdd_images[id].file);
|
||||
hdd[id].spt = spt;
|
||||
hdd[id].hpc = hpc;
|
||||
hdd[id].tracks = tracks;
|
||||
fread(&(hdd[id].at_spt), 1, 4, hdd_images[id].file);
|
||||
fread(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file);
|
||||
hdd_images[id].type = 2;
|
||||
} else {
|
||||
full_size = ((uint64_t) hdd[id].spt) *
|
||||
((uint64_t) hdd[id].hpc) *
|
||||
((uint64_t) hdd[id].tracks) << 9LL;
|
||||
hdd_images[id].type = 0;
|
||||
}
|
||||
}
|
||||
|
||||
hdd_images[id].last_sector = -1;
|
||||
|
||||
memset(hdd[id].prev_fn, 0, sizeof(hdd[id].prev_fn));
|
||||
if (fn_preserve)
|
||||
wcscpy(hdd[id].prev_fn, hdd[id].fn);
|
||||
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
||||
fseeko64(hdd_images[id].file, 0, SEEK_END);
|
||||
s = ftello64(hdd_images[id].file);
|
||||
if (s < (full_size + hdd_images[id].base))
|
||||
return prepare_new_hard_disk(id, full_size);
|
||||
else {
|
||||
hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1;
|
||||
hdd_images[id].loaded = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void hdd_image_close(uint8_t id)
|
||||
|
||||
void
|
||||
hdd_image_seek(uint8_t id, uint32_t sector)
|
||||
{
|
||||
off64_t addr = sector;
|
||||
addr = (uint64_t)sector * 512;
|
||||
|
||||
fseeko64(hdd_images[id].file, addr + hdd_images[id].base, SEEK_SET);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
||||
{
|
||||
fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET);
|
||||
fread(buffer, 1, count << 9, hdd_images[id].file);
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
hdd_sectors(uint8_t id)
|
||||
{
|
||||
fseeko64(hdd_images[id].file, 0, SEEK_END);
|
||||
return (uint32_t) ((ftello64(hdd_images[id].file) - hdd_images[id].base) >> 9);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
||||
{
|
||||
uint32_t transfer_sectors = count;
|
||||
uint32_t sectors = hdd_sectors(id);
|
||||
|
||||
if ((sectors - sector) < transfer_sectors)
|
||||
transfer_sectors = sectors - sector;
|
||||
|
||||
fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET);
|
||||
fread(buffer, 1, transfer_sectors << 9, hdd_images[id].file);
|
||||
|
||||
if (count != transfer_sectors)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
||||
{
|
||||
fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET);
|
||||
fwrite(buffer, count << 9, 1, hdd_images[id].file);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
||||
{
|
||||
uint32_t transfer_sectors = count;
|
||||
uint32_t sectors = hdd_sectors(id);
|
||||
|
||||
if ((sectors - sector) < transfer_sectors)
|
||||
transfer_sectors = sectors - sector;
|
||||
|
||||
fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET);
|
||||
fwrite(buffer, transfer_sectors << 9, 1, hdd_images[id].file);
|
||||
|
||||
if (count != transfer_sectors)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
|
||||
fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET);
|
||||
for (i = 0; i < count; i++)
|
||||
fwrite(empty_sector, 512, 1, hdd_images[id].file);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
|
||||
uint32_t transfer_sectors = count;
|
||||
uint32_t sectors = hdd_sectors(id);
|
||||
|
||||
if ((sectors - sector) < transfer_sectors)
|
||||
transfer_sectors = sectors - sector;
|
||||
|
||||
fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET);
|
||||
for (i = 0; i < transfer_sectors; i++)
|
||||
fwrite(empty_sector, 1, 512, hdd_images[id].file);
|
||||
|
||||
if (count != transfer_sectors)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
hdd_image_get_last_sector(uint8_t id)
|
||||
{
|
||||
return hdd_images[id].last_sector;
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
hdd_image_get_type(uint8_t id)
|
||||
{
|
||||
return hdd_images[id].type;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt)
|
||||
{
|
||||
if (hdd_images[id].type == 2) {
|
||||
hdd[id].at_hpc = hpc;
|
||||
hdd[id].at_spt = spt;
|
||||
fseeko64(hdd_images[id].file, 0x20, SEEK_SET);
|
||||
fwrite(&(hdd[id].at_spt), 1, 4, hdd_images[id].file);
|
||||
fwrite(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
hdd_image_unload(uint8_t id, int fn_preserve)
|
||||
{
|
||||
if (wcslen(hdd[id].fn) == 0)
|
||||
return;
|
||||
|
||||
if (hdd_images[id].loaded) {
|
||||
if (hdd_images[id].file != NULL) {
|
||||
fclose(hdd_images[id].file);
|
||||
hdd_images[id].file = NULL;
|
||||
}
|
||||
hdd_images[id].loaded = 0;
|
||||
}
|
||||
|
||||
hdd_images[id].last_sector = -1;
|
||||
|
||||
memset(hdd[id].prev_fn, 0, sizeof(hdd[id].prev_fn));
|
||||
if (fn_preserve)
|
||||
wcscpy(hdd[id].prev_fn, hdd[id].fn);
|
||||
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
hdd_image_close(uint8_t id)
|
||||
{
|
||||
hdd_image_log("hdd_image_close(%i)\n", id);
|
||||
|
||||
if (!hdd_images[id].loaded)
|
||||
return;
|
||||
|
||||
if (hdd_images[id].file != NULL) {
|
||||
fclose(hdd_images[id].file);
|
||||
hdd_images[id].file = NULL;
|
||||
}
|
||||
memset(&hdd_images[id], 0, sizeof(hdd_image_t));
|
||||
hdd_images[id].loaded = 0;
|
||||
}
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
* Implementation of the IDE emulation for hard disks and ATAPI
|
||||
* CD-ROM devices.
|
||||
*
|
||||
* Version: @(#)hdd_table.c 1.0.5 2017/11/01
|
||||
* Version: @(#)hdd_table.c 1.0.5 2018/04/08
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
* Copyright 2017 Fred N. van Kempen.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
@@ -26,7 +26,7 @@
|
||||
#include "hdd.h"
|
||||
|
||||
|
||||
uint64_t hdd_table[128][3] = {
|
||||
unsigned int hdd_table[128][3] = {
|
||||
{ 306, 4, 17 }, /* 0 - 7 */
|
||||
{ 615, 2, 17 },
|
||||
{ 306, 4, 26 },
|
||||
|
||||
4569
src/disk/zip.c
4569
src/disk/zip.c
File diff suppressed because it is too large
Load Diff
165
src/disk/zip.h
165
src/disk/zip.h
@@ -9,7 +9,7 @@
|
||||
* Implementation of the Iomega ZIP drive with SCSI(-like)
|
||||
* commands, for both ATAPI and SCSI usage.
|
||||
*
|
||||
* Version: @(#)zip.h 1.0.4 2018/03/20
|
||||
* Version: @(#)zip.h 1.0.5 2018/03/26
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
@@ -19,15 +19,15 @@
|
||||
#define EMU_ZIP_H
|
||||
|
||||
|
||||
#define ZIP_NUM 4
|
||||
#define ZIP_NUM 4
|
||||
|
||||
#define ZIP_PHASE_IDLE 0
|
||||
#define ZIP_PHASE_COMMAND 1
|
||||
#define ZIP_PHASE_COMPLETE 2
|
||||
#define ZIP_PHASE_DATA_IN 3
|
||||
#define ZIP_PHASE_DATA_IN_DMA 4
|
||||
#define ZIP_PHASE_DATA_OUT 5
|
||||
#define ZIP_PHASE_DATA_OUT_DMA 6
|
||||
#define ZIP_PHASE_IDLE 0x00
|
||||
#define ZIP_PHASE_COMMAND 0x01
|
||||
#define ZIP_PHASE_COMPLETE 0x02
|
||||
#define ZIP_PHASE_DATA_IN 0x03
|
||||
#define ZIP_PHASE_DATA_IN_DMA 0x04
|
||||
#define ZIP_PHASE_DATA_OUT 0x05
|
||||
#define ZIP_PHASE_DATA_OUT_DMA 0x06
|
||||
#define ZIP_PHASE_ERROR 0x80
|
||||
|
||||
#define BUF_SIZE 32768
|
||||
@@ -42,134 +42,81 @@
|
||||
|
||||
enum {
|
||||
ZIP_BUS_DISABLED = 0,
|
||||
ZIP_BUS_ATAPI_PIO_ONLY = 4,
|
||||
ZIP_BUS_ATAPI_PIO_AND_DMA,
|
||||
ZIP_BUS_ATAPI = 4,
|
||||
ZIP_BUS_SCSI,
|
||||
ZIP_BUS_USB = 8
|
||||
ZIP_BUS_USB
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t previous_command;
|
||||
uint8_t previous_command, error,
|
||||
features, status,
|
||||
phase, *buffer,
|
||||
atapi_cdb[16],
|
||||
current_cdb[16],
|
||||
sense[256];
|
||||
|
||||
int toctimes;
|
||||
int media_status;
|
||||
uint16_t request_length, max_transfer_len;
|
||||
|
||||
int is_dma;
|
||||
int toctimes, media_status,
|
||||
is_dma, requested_blocks,
|
||||
current_page_len, current_page_pos,
|
||||
total_length, written_length,
|
||||
mode_select_phase, do_page_save,
|
||||
callback, data_pos,
|
||||
packet_status, unit_attention,
|
||||
cdb_len_setting, cdb_len,
|
||||
request_pos, total_read,
|
||||
block_total, all_blocks_total,
|
||||
old_len, block_descriptor_len,
|
||||
init_length;
|
||||
|
||||
int requested_blocks; /* This will be set to something other than 1 when block reads are implemented. */
|
||||
uint32_t sector_pos, sector_len,
|
||||
packet_len, pos,
|
||||
seek_pos;
|
||||
|
||||
uint64_t current_page_code;
|
||||
int current_page_len;
|
||||
|
||||
int current_page_pos;
|
||||
|
||||
int mode_select_phase;
|
||||
|
||||
int total_length;
|
||||
int written_length;
|
||||
|
||||
int do_page_save;
|
||||
|
||||
uint8_t error;
|
||||
uint8_t features;
|
||||
uint16_t request_length;
|
||||
uint16_t max_transfer_len;
|
||||
uint8_t status;
|
||||
uint8_t phase;
|
||||
|
||||
uint32_t sector_pos;
|
||||
uint32_t sector_len;
|
||||
|
||||
uint32_t packet_len;
|
||||
int packet_status;
|
||||
|
||||
uint8_t atapi_cdb[16];
|
||||
uint8_t current_cdb[16];
|
||||
|
||||
uint32_t pos;
|
||||
|
||||
int callback;
|
||||
|
||||
int data_pos;
|
||||
|
||||
int cdb_len_setting;
|
||||
int cdb_len;
|
||||
|
||||
int cd_status;
|
||||
int prev_status;
|
||||
|
||||
int unit_attention;
|
||||
uint8_t sense[256];
|
||||
|
||||
int request_pos;
|
||||
|
||||
uint8_t *buffer;
|
||||
|
||||
int times;
|
||||
|
||||
uint32_t seek_pos;
|
||||
|
||||
int total_read;
|
||||
|
||||
int block_total;
|
||||
int all_blocks_total;
|
||||
|
||||
int old_len;
|
||||
int block_descriptor_len;
|
||||
|
||||
int init_length;
|
||||
uint64_t current_page_code;
|
||||
} zip_t;
|
||||
|
||||
typedef struct {
|
||||
int host_drive;
|
||||
int prev_host_drive;
|
||||
unsigned int bus_type; /* 0 = ATAPI, 1 = SCSI */
|
||||
uint8_t ide_channel,
|
||||
bus_mode; /* Bit 0 = PIO suported;
|
||||
Bit 1 = DMA supportd. */
|
||||
|
||||
unsigned int bus_type; /* 0 = ATAPI, 1 = SCSI */
|
||||
uint8_t bus_mode; /* Bit 0 = PIO suported;
|
||||
Bit 1 = DMA supportd. */
|
||||
unsigned int scsi_device_id, scsi_device_lun,
|
||||
is_250;
|
||||
|
||||
uint8_t ide_channel;
|
||||
wchar_t image_path[1024],
|
||||
prev_image_path[1024];
|
||||
|
||||
unsigned int scsi_device_id;
|
||||
unsigned int scsi_device_lun;
|
||||
|
||||
unsigned int is_250;
|
||||
unsigned int atapi_dma;
|
||||
int read_only, ui_writeprot;
|
||||
|
||||
wchar_t image_path[1024];
|
||||
wchar_t prev_image_path[1024];
|
||||
uint32_t medium_size, base;
|
||||
|
||||
uint32_t medium_size;
|
||||
|
||||
int read_only;
|
||||
int ui_writeprot;
|
||||
|
||||
uint32_t base;
|
||||
|
||||
FILE *f;
|
||||
FILE *f;
|
||||
} zip_drive_t;
|
||||
|
||||
|
||||
extern zip_t zip[ZIP_NUM];
|
||||
extern zip_t *zip[ZIP_NUM];
|
||||
extern zip_drive_t zip_drives[ZIP_NUM];
|
||||
extern uint8_t atapi_zip_drives[8];
|
||||
extern uint8_t scsi_zip_drives[16][8];
|
||||
|
||||
#define zip_sense_error zip[id].sense[0]
|
||||
#define zip_sense_key zip[id].sense[2]
|
||||
#define zip_asc zip[id].sense[12]
|
||||
#define zip_ascq zip[id].sense[13]
|
||||
#define zip_drive zip_drives[id].host_drive
|
||||
#define zip_sense_error zip[id]->sense[0]
|
||||
#define zip_sense_key zip[id]->sense[2]
|
||||
#define zip_asc zip[id]->sense[12]
|
||||
#define zip_ascq zip[id]->sense[13]
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length);
|
||||
extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length);
|
||||
extern void (*ide_bus_master_set_irq)(int channel);
|
||||
extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length, void *priv);
|
||||
extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length, void *priv);
|
||||
extern void (*ide_bus_master_set_irq)(int channel, void *priv);
|
||||
extern void *ide_bus_master_priv[2];
|
||||
extern void ioctl_close(uint8_t id);
|
||||
|
||||
extern uint32_t zip_mode_sense_get_channel(uint8_t id, int channel);
|
||||
@@ -183,8 +130,6 @@ extern void zip_phase_callback(uint8_t id);
|
||||
extern uint32_t zip_read(uint8_t channel, int length);
|
||||
extern void zip_write(uint8_t channel, uint32_t val, int length);
|
||||
|
||||
extern int zip_lba_to_msf_accurate(int lba);
|
||||
|
||||
extern void zip_close(uint8_t id);
|
||||
extern void zip_disk_reload(uint8_t id);
|
||||
extern void zip_reset(uint8_t id);
|
||||
@@ -200,6 +145,8 @@ extern void zip_global_init(void);
|
||||
extern void zip_hard_reset(void);
|
||||
|
||||
extern int zip_load(uint8_t id, wchar_t *fn);
|
||||
|
||||
extern void zip_destroy_drives(void);
|
||||
extern void zip_close(uint8_t id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
Reference in New Issue
Block a user