Fixed some CD-ROM-related bugs;

Added sanity checks to the device close functions of the Hercules family graphics cards;
Cleaned up, fixed the bugs in, and reworked the implementation of the Adaptec/BusLogic BIOS command handler;
Removed some scsi_device.c functions that have now become useless;
Removed some excess stuff from pc_init_modules().
This commit is contained in:
OBattler
2018-10-11 10:34:12 +02:00
parent defada30d4
commit b8d3992c07
8 changed files with 283 additions and 281 deletions

View File

@@ -8,7 +8,7 @@
* *
* Generic CD-ROM drive core. * Generic CD-ROM drive core.
* *
* Version: @(#)cdrom.c 1.0.0 2018/10/09 * Version: @(#)cdrom.c 1.0.1 2018/10/11
* *
* Author: Miran Grca, <mgrca8@gmail.com> * Author: Miran Grca, <mgrca8@gmail.com>
* *
@@ -160,6 +160,9 @@ void
cdrom_seek(cdrom_drive_t *dev, uint32_t pos) cdrom_seek(cdrom_drive_t *dev, uint32_t pos)
{ {
/* cdrom_log("CD-ROM %i: Seek %08X\n", dev->id, pos); */ /* cdrom_log("CD-ROM %i: Seek %08X\n", dev->id, pos); */
if (!dev)
return;
dev->seek_pos = pos; dev->seek_pos = pos;
if (dev->handler && dev->handler->stop) if (dev->handler && dev->handler->stop)
dev->handler->stop(dev->id); dev->handler->stop(dev->id);
@@ -234,6 +237,9 @@ cdrom_close_handler(uint8_t id)
{ {
cdrom_drive_t *dev = &cdrom_drives[id]; cdrom_drive_t *dev = &cdrom_drives[id];
if (!dev)
return;
switch (dev->host_drive) { switch (dev->host_drive) {
case 200: case 200:
image_close(id); image_close(id);
@@ -242,6 +248,8 @@ cdrom_close_handler(uint8_t id)
null_close(id); null_close(id);
break; break;
} }
dev->handler = NULL;
} }

View File

@@ -8,7 +8,7 @@
* *
* Main emulator module where most things are controlled. * Main emulator module where most things are controlled.
* *
* Version: @(#)pc.c 1.0.81 2018/10/10 * Version: @(#)pc.c 1.0.82 2018/10/11
* *
* 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>
@@ -640,7 +640,6 @@ again2:
} }
} }
// cpuspeed2 = (AT) ? 2 : 1;
cpuspeed2 = (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286) ? 2 : 1; cpuspeed2 = (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286) ? 2 : 1;
atfullspeed = 0; atfullspeed = 0;
@@ -665,15 +664,6 @@ again2:
hdc_init(hdc_name); hdc_init(hdc_name);
scsi_card_init();
/* These now come after as they now attach to the bus. */
scsi_disk_hard_reset();
cdrom_hard_reset();
zip_hard_reset();
pc_full_speed(); pc_full_speed();
shadowbios = 0; shadowbios = 0;

View File

@@ -8,7 +8,7 @@
* *
* The generic SCSI device command handler. * The generic SCSI device command handler.
* *
* Version: @(#)scsi_device.c 1.0.19 2018/10/10 * Version: @(#)scsi_device.c 1.0.20 2018/10/11
* *
* 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>
@@ -99,22 +99,6 @@ void scsi_device_reset(scsi_device_t *dev)
} }
void scsi_device_type_data(scsi_device_t *dev, uint8_t *type, uint8_t *rmb)
{
*rmb = dev->type >> 8;
*type = dev->type & 0xff;
}
int scsi_device_read_capacity(scsi_device_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len)
{
if (dev->read_capacity)
return dev->read_capacity(dev->p, cdb, buffer, len);
else
return 0;
}
int scsi_device_present(scsi_device_t *dev) int scsi_device_present(scsi_device_t *dev)
{ {
if (dev->type == SCSI_NONE) if (dev->type == SCSI_NONE)

View File

@@ -8,7 +8,7 @@
* *
* Definitions for the generic SCSI device command handler. * Definitions for the generic SCSI device command handler.
* *
* Version: @(#)scsi_device.h 1.0.11 2018/10/09 * Version: @(#)scsi_device.h 1.0.12 2018/10/11
* *
* 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>
@@ -129,6 +129,7 @@
#define SENSE_UNIT_ATTENTION 6 #define SENSE_UNIT_ATTENTION 6
/* SCSI Additional Sense Codes */ /* SCSI Additional Sense Codes */
#define ASC_NONE 0x00
#define ASC_AUDIO_PLAY_OPERATION 0x00 #define ASC_AUDIO_PLAY_OPERATION 0x00
#define ASC_NOT_READY 0x04 #define ASC_NOT_READY 0x04
#define ASC_ILLEGAL_OPCODE 0x20 #define ASC_ILLEGAL_OPCODE 0x20
@@ -144,6 +145,7 @@
#define ASC_DATA_PHASE_ERROR 0x4b #define ASC_DATA_PHASE_ERROR 0x4b
#define ASC_ILLEGAL_MODE_FOR_THIS_TRACK 0x64 #define ASC_ILLEGAL_MODE_FOR_THIS_TRACK 0x64
#define ASCQ_NONE 0x00
#define ASCQ_UNIT_IN_PROCESS_OF_BECOMING_READY 0x01 #define ASCQ_UNIT_IN_PROCESS_OF_BECOMING_READY 0x01
#define ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02 #define ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02
#define ASCQ_CAPACITY_DATA_CHANGED 0x09 #define ASCQ_CAPACITY_DATA_CHANGED 0x09
@@ -360,13 +362,10 @@ extern int mode_select_terminate(int force);
extern int mode_select_write(uint8_t val); extern int mode_select_write(uint8_t val);
extern uint8_t *scsi_device_sense(scsi_device_t *dev); extern uint8_t *scsi_device_sense(scsi_device_t *dev);
extern void scsi_device_type_data(scsi_device_t *dev, uint8_t *type, uint8_t *rmb);
extern int64_t scsi_device_get_callback(scsi_device_t *dev); extern int64_t scsi_device_get_callback(scsi_device_t *dev);
extern void scsi_device_request_sense(scsi_device_t *dev, uint8_t *buffer, extern void scsi_device_request_sense(scsi_device_t *dev, uint8_t *buffer,
uint8_t alloc_length); uint8_t alloc_length);
extern void scsi_device_reset(scsi_device_t *dev); extern void scsi_device_reset(scsi_device_t *dev);
extern int scsi_device_read_capacity(scsi_device_t *dev, uint8_t *cdb,
uint8_t *buffer, uint32_t *len);
extern int scsi_device_present(scsi_device_t *dev); extern int scsi_device_present(scsi_device_t *dev);
extern int scsi_device_valid(scsi_device_t *dev); extern int scsi_device_valid(scsi_device_t *dev);
extern int scsi_device_cdb_length(scsi_device_t *dev); extern int scsi_device_cdb_length(scsi_device_t *dev);

View File

@@ -11,7 +11,7 @@
* series of SCSI Host Adapters made by Mylex. * series of SCSI Host Adapters made by Mylex.
* These controllers were designed for various buses. * These controllers were designed for various buses.
* *
* Version: @(#)scsi_x54x.c 1.0.23 2018/10/09 * Version: @(#)scsi_x54x.c 1.0.24 2018/10/11
* *
* Authors: TheCollector1995, <mariogplayer@gmail.com> * Authors: TheCollector1995, <mariogplayer@gmail.com>
* Miran Grca, <mgrca8@gmail.com> * Miran Grca, <mgrca8@gmail.com>
@@ -163,31 +163,48 @@ target_check(uint8_t id)
static uint8_t static uint8_t
completion_code(uint8_t *sense) completion_code(uint8_t *sense)
{ {
switch (sense[12]) { uint8_t ret = 0xff;
case 0x00:
return(0x00);
case 0x20: switch (sense[12]) {
return(0x01); case ASC_NONE:
ret = 0x00;
break;
case ASC_ILLEGAL_OPCODE:
case ASC_INV_FIELD_IN_CMD_PACKET:
case ASC_INV_FIELD_IN_PARAMETER_LIST:
case ASC_DATA_PHASE_ERROR:
ret = 0x01;
break;
case 0x12: case 0x12:
case 0x21: case ASC_LBA_OUT_OF_RANGE:
return(0x02); ret = 0x02;
break;
case 0x27: case ASC_WRITE_PROTECTED:
return(0x03); ret = 0x03;
break;
case 0x14: case 0x14:
case 0x16: case 0x16:
return(0x04); ret = 0x04;
break;
case ASC_INCOMPATIBLE_FORMAT:
case ASC_ILLEGAL_MODE_FOR_THIS_TRACK:
ret = 0x0c;
break;
case 0x10: case 0x10:
case 0x11: case 0x11:
return(0x10); ret = 0x10;
break;
case 0x17: case 0x17:
case 0x18: case 0x18:
return(0x11); ret = 0x11;
break;
case 0x01: case 0x01:
case 0x03: case 0x03:
@@ -209,38 +226,126 @@ completion_code(uint8_t *sense)
case 0x47: case 0x47:
case 0x48: case 0x48:
case 0x49: case 0x49:
return(0x20); ret = 0x20;
break;
case 0x15: case 0x15:
case 0x02: case 0x02:
return(0x40); ret = 0x40;
break;
case 0x04: case 0x25:
case 0x28: ret = 0x80;
break;
case ASC_NOT_READY:
case ASC_MEDIUM_MAY_HAVE_CHANGED:
case 0x29: case 0x29:
case 0x2a: case ASC_CAPACITY_DATA_CHANGED:
return(0xaa); case ASC_MEDIUM_NOT_PRESENT:
ret = 0xaa;
default:
break; break;
}; };
return(0xff); return(ret);
} }
static uint8_t static uint8_t
x54x_bios_command_08(uint8_t id, uint8_t *buffer) x54x_bios_scsi_command(scsi_device_t *dev, uint8_t *cdb, uint8_t *buf, int len, uint32_t addr)
{ {
uint8_t cdb[12] = { GPCMD_READ_CDROM_CAPACITY, 0,0,0,0,0,0,0,0,0,0,0 }; dev->buffer_length = -1;
uint8_t rcbuf[8] = { 0,0,0,0,0,0,0,0 };
uint32_t len = 0;
int i, ret, sc;
scsi_device_t *sd = &scsi_devices[id];
ret = scsi_device_read_capacity(sd, cdb, rcbuf, &len); scsi_device_command_phase0(dev, cdb);
sc = completion_code(scsi_device_sense(sd));
if (ret == 0) return(sc); if (dev->phase == SCSI_PHASE_STATUS)
return(completion_code(scsi_device_sense(dev)));
dev->cmd_buffer = (uint8_t *)malloc(dev->buffer_length);
if (dev->phase == SCSI_PHASE_DATA_IN) {
scsi_device_command_phase1(dev);
if (len > 0) {
if (buf)
memcpy(buf, dev->cmd_buffer, dev->buffer_length);
else
DMAPageWrite(addr, dev->cmd_buffer, dev->buffer_length);
}
} else if (dev->phase == SCSI_PHASE_DATA_OUT) {
if (len > 0) {
if (buf)
memcpy(dev->cmd_buffer, buf, dev->buffer_length);
else
DMAPageRead(addr, dev->cmd_buffer, dev->buffer_length);
}
scsi_device_command_phase1(dev);
}
if (dev->cmd_buffer != NULL) {
free(dev->cmd_buffer);
dev->cmd_buffer = NULL;
}
return(completion_code(scsi_device_sense(dev)));
}
static uint8_t
x54x_bios_read_capacity(scsi_device_t *sd, uint8_t *buf)
{
uint8_t *cdb;
uint8_t ret;
cdb = (uint8_t *) malloc(12);
memset(cdb, 0, 12);
cdb[0] = GPCMD_READ_CDROM_CAPACITY;
memset(buf, 0, 8);
ret = x54x_bios_scsi_command(sd, cdb, buf, 8, 0);
free(cdb);
return(ret);
}
static uint8_t
x54x_bios_inquiry(scsi_device_t *sd, uint8_t *buf)
{
uint8_t *cdb;
uint8_t ret;
cdb = (uint8_t *) malloc(12);
memset(cdb, 0, 12);
cdb[0] = GPCMD_INQUIRY;
cdb[4] = 36;
memset(buf, 0, 36);
ret = x54x_bios_scsi_command(sd, cdb, buf, 36, 0);
free(cdb);
return(ret);
}
static uint8_t
x54x_bios_command_08(scsi_device_t *sd, uint8_t *buffer)
{
uint8_t *rcbuf;
uint8_t ret;
int i;
memset(buffer, 0x00, 6);
rcbuf = (uint8_t *) malloc(8);
ret = x54x_bios_read_capacity(sd, rcbuf);
if (ret) {
free(rcbuf);
return(ret);
}
memset(buffer, 0x00, 6); memset(buffer, 0x00, 6);
for (i=0; i<4; i++) for (i=0; i<4; i++)
@@ -250,32 +355,49 @@ x54x_bios_command_08(uint8_t id, uint8_t *buffer)
x54x_log("BIOS Command 0x08: %02X %02X %02X %02X %02X %02X\n", x54x_log("BIOS Command 0x08: %02X %02X %02X %02X %02X %02X\n",
buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]);
free(rcbuf);
return(0); return(0);
} }
static int static int
x54x_bios_command_15(uint8_t id, uint8_t *buffer) x54x_bios_command_15(scsi_device_t *sd, uint8_t *buffer)
{ {
uint8_t cdb[12] = { GPCMD_READ_CDROM_CAPACITY, 0,0,0,0,0,0,0,0,0,0,0 }; uint8_t *inqbuf, *rcbuf;
uint8_t rcbuf[8] = { 0,0,0,0,0,0,0,0 }; uint8_t ret;
uint32_t len = 0; int i;
int i, ret, sc;
scsi_device_t *sd = &scsi_devices[id];
ret = scsi_device_read_capacity(sd, cdb, rcbuf, &len);
sc = completion_code(scsi_device_sense(sd));
memset(buffer, 0x00, 6); memset(buffer, 0x00, 6);
for (i=0; i<4; i++)
buffer[i] = (ret == 0) ? 0 : rcbuf[i];
scsi_device_type_data(sd, &(buffer[4]), &(buffer[5])); inqbuf = (uint8_t *) malloc(36);
ret = x54x_bios_inquiry(sd, inqbuf);
if (ret) {
free(inqbuf);
return(ret);
}
buffer[4] = inqbuf[0];
buffer[5] = inqbuf[1];
rcbuf = (uint8_t *) malloc(8);
ret = x54x_bios_read_capacity(sd, rcbuf);
if (ret) {
free(rcbuf);
free(inqbuf);
return(ret);
}
for (i = 0; i < 4; i++)
buffer[i] = rcbuf[i];
x54x_log("BIOS Command 0x15: %02X %02X %02X %02X %02X %02X\n", x54x_log("BIOS Command 0x15: %02X %02X %02X %02X %02X %02X\n",
buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]);
return(sc); free(rcbuf);
free(inqbuf);
return(0);
} }
@@ -283,12 +405,16 @@ x54x_bios_command_15(uint8_t id, uint8_t *buffer)
static uint8_t static uint8_t
x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
{ {
uint8_t cdb[12] = { 0,0,0,0,0,0,0,0,0,0,0,0 }; const int bios_cmd_to_scsi[18] = { 0, 0, GPCMD_READ_10, GPCMD_WRITE_10, GPCMD_VERIFY_10, 0, 0,
scsi_device_t *dev; GPCMD_FORMAT_UNIT, 0, 0, 0, 0, GPCMD_SEEK_10, 0, 0, 0,
uint32_t dma_address; GPCMD_TEST_UNIT_READY, GPCMD_REZERO_UNIT };
uint8_t cdb[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
uint8_t *buf;
scsi_device_t *dev = NULL;
uint32_t dma_address = 0;
uint32_t lba; uint32_t lba;
int sector_len = cmd->secount; int sector_len = cmd->secount;
uint8_t ret; uint8_t ret = 0x00;
if (islba) if (islba)
lba = lba32_blk(cmd); lba = lba32_blk(cmd);
@@ -300,41 +426,44 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
if ((cmd->id > max_id) || (cmd->lun > 7)) { if ((cmd->id > max_id) || (cmd->lun > 7)) {
x54x_log("BIOS Target ID %i or LUN %i are above maximum\n", x54x_log("BIOS Target ID %i or LUN %i are above maximum\n",
cmd->id, cmd->lun); cmd->id, cmd->lun);
return(0x80); ret = 0x80;
} }
if (cmd->lun) { if (cmd->lun) {
x54x_log("BIOS Target LUN is not 0\n"); x54x_log("BIOS Target LUN is not 0\n");
return(0x80); ret = 0x80;
} }
/* Get pointer to selected device. */ if (!ret) {
dev = &scsi_devices[cmd->id]; /* Get pointer to selected device. */
dev->buffer_length = 0; dev = &scsi_devices[cmd->id];
dev->buffer_length = 0;
if (! scsi_device_present(dev)) { if (dev->cmd_buffer != NULL) {
x54x_log("BIOS Target ID %i has no device attached\n", cmd->id); free(dev->cmd_buffer);
return(0x80); dev->cmd_buffer = NULL;
}
if (! scsi_device_present(dev)) {
x54x_log("BIOS Target ID %i has no device attached\n", cmd->id);
ret = 0x80;
} else {
if ((dev->type == SCSI_REMOVABLE_CDROM) && !x54x->cdrom_boot) {
x54x_log("BIOS Target ID %i is CD-ROM on unsupported BIOS\n", cmd->id);
return(0x80);
} else {
dma_address = ADDR_TO_U32(cmd->dma_address);
x54x_log("BIOS Data Buffer write: length %d, pointer 0x%04X\n",
sector_len, dma_address);
}
}
} }
if ((dev->type == SCSI_REMOVABLE_CDROM) && !x54x->cdrom_boot) { if (!ret) switch(cmd->command) {
x54x_log("BIOS Target ID %i is CD-ROM on unsupported BIOS\n", cmd->id);
return(0x80);
}
dma_address = ADDR_TO_U32(cmd->dma_address);
x54x_log("BIOS Data Buffer write: length %d, pointer 0x%04X\n",
sector_len, dma_address);
if (dev->cmd_buffer != NULL) {
free(dev->cmd_buffer);
dev->cmd_buffer = NULL;
}
switch(cmd->command) {
case 0x00: /* Reset Disk System, in practice it's a nop */ case 0x00: /* Reset Disk System, in practice it's a nop */
return(0); ret = 0x00;
break;
case 0x01: /* Read Status of Last Operation */ case 0x01: /* Read Status of Last Operation */
target_check(cmd->id); target_check(cmd->id);
@@ -355,194 +484,70 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
scsi_device_sense(dev), 14); scsi_device_sense(dev), 14);
} }
if (dev->cmd_buffer != NULL) { if (dev && (dev->cmd_buffer != NULL)) {
free(dev->cmd_buffer); free(dev->cmd_buffer);
dev->cmd_buffer = NULL; dev->cmd_buffer = NULL;
} }
return(0); return(0);
break;
case 0x02: /* Read Desired Sectors to Memory */ case 0x02: /* Read Desired Sectors to Memory */
target_check(cmd->id);
dev->buffer_length = -1;
cdb[0] = GPCMD_READ_10;
cdb[1] = (cmd->lun & 7) << 5;
cdb[2] = (lba >> 24) & 0xff;
cdb[3] = (lba >> 16) & 0xff;
cdb[4] = (lba >> 8) & 0xff;
cdb[5] = lba & 0xff;
cdb[7] = 0;
cdb[8] = sector_len;
#if 0
x54x_log("BIOS CMD(READ, %08lx, %d)\n", lba, cmd->secount);
#endif
scsi_device_command_phase0(dev, cdb);
if (dev->phase == SCSI_PHASE_STATUS)
goto skip_read_phase1;
dev->cmd_buffer = (uint8_t *)malloc(dev->buffer_length);
scsi_device_command_phase1(dev);
if (sector_len > 0) {
x54x_log("BIOS DMA: Reading %i bytes at %08X\n",
dev->buffer_length, dma_address);
DMAPageWrite(dma_address,
dev->cmd_buffer, dev->buffer_length);
}
skip_read_phase1:
if (dev->cmd_buffer != NULL) {
free(dev->cmd_buffer);
dev->cmd_buffer = NULL;
}
return(completion_code(scsi_device_sense(dev)));
case 0x03: /* Write Desired Sectors from Memory */ case 0x03: /* Write Desired Sectors from Memory */
target_check(cmd->id);
dev->buffer_length = -1;
cdb[0] = GPCMD_WRITE_10;
cdb[1] = (cmd->lun & 7) << 5;
cdb[2] = (lba >> 24) & 0xff;
cdb[3] = (lba >> 16) & 0xff;
cdb[4] = (lba >> 8) & 0xff;
cdb[5] = lba & 0xff;
cdb[7] = 0;
cdb[8] = sector_len;
#if 0
x54x_log("BIOS CMD(WRITE, %08lx, %d)\n", lba, cmd->secount);
#endif
scsi_device_command_phase0(dev, cdb);
if (dev->phase == SCSI_PHASE_STATUS)
goto skip_write_phase1;
dev->cmd_buffer = (uint8_t *)malloc(dev->buffer_length);
if (sector_len > 0) {
x54x_log("BIOS DMA: Reading %i bytes at %08X\n",
dev->buffer_length, dma_address);
DMAPageRead(dma_address,
dev->cmd_buffer, dev->buffer_length);
}
scsi_device_command_phase1(dev);
skip_write_phase1:
if (dev->cmd_buffer != NULL) {
free(dev->cmd_buffer);
dev->cmd_buffer = NULL;
}
return(completion_code(scsi_device_sense(dev)));
case 0x04: /* Verify Desired Sectors */ case 0x04: /* Verify Desired Sectors */
target_check(cmd->id);
cdb[0] = GPCMD_VERIFY_10;
cdb[1] = (cmd->lun & 7) << 5;
cdb[2] = (lba >> 24) & 0xff;
cdb[3] = (lba >> 16) & 0xff;
cdb[4] = (lba >> 8) & 0xff;
cdb[5] = lba & 0xff;
cdb[7] = 0;
cdb[8] = sector_len;
scsi_device_command_phase0(dev, cdb);
return(completion_code(scsi_device_sense(dev)));
case 0x05: /* Format Track, invalid since SCSI has no tracks */
//FIXME: add a longer delay here --FvK
return(1);
case 0x06: /* Identify SCSI Devices, in practice it's a nop */
//FIXME: add a longer delay here --FvK
return(0);
case 0x07: /* Format Unit */
target_check(cmd->id);
cdb[0] = GPCMD_FORMAT_UNIT;
cdb[1] = (cmd->lun & 7) << 5;
scsi_device_command_phase0(dev, cdb);
return(completion_code(scsi_device_sense(dev)));
case 0x08: /* Read Drive Parameters */
target_check(cmd->id);
dev->buffer_length = 6;
dev->cmd_buffer = (uint8_t *)malloc(dev->buffer_length);
memset(dev->cmd_buffer, 0x00, dev->buffer_length);
ret = x54x_bios_command_08(cmd->id, dev->cmd_buffer);
x54x_log("BIOS DMA: Reading 6 bytes at %08X\n", dma_address);
DMAPageWrite(dma_address,
dev->cmd_buffer, 4 /* dev->buffer_length */);
if (dev->cmd_buffer != NULL) {
free(dev->cmd_buffer);
dev->cmd_buffer = NULL;
}
return(ret);
case 0x09: /* Initialize Drive Pair Characteristics, in practice it's a nop */
//FIXME: add a longer delay here --FvK
return(0);
case 0x0c: /* Seek */ case 0x0c: /* Seek */
target_check(cmd->id); target_check(cmd->id);
cdb[0] = GPCMD_SEEK_10; cdb[0] = bios_cmd_to_scsi[cmd->command];
cdb[1] = (cmd->lun & 7) << 5; cdb[1] = (cmd->lun & 7) << 5;
cdb[2] = (lba >> 24) & 0xff; cdb[2] = (lba >> 24) & 0xff;
cdb[3] = (lba >> 16) & 0xff; cdb[3] = (lba >> 16) & 0xff;
cdb[4] = (lba >> 8) & 0xff; cdb[4] = (lba >> 8) & 0xff;
cdb[5] = lba & 0xff; cdb[5] = lba & 0xff;
if (cmd->command != 0x0c)
cdb[8] = sector_len;
#if 0
x54x_log("BIOS CMD(READ/WRITE/VERIFY, %08lx, %d)\n", lba, cmd->secount);
#endif
scsi_device_command_phase0(dev, cdb); ret = x54x_bios_scsi_command(dev, cdb, NULL, sector_len, dma_address);
if (cmd->command == 0x0c)
ret = !!ret;
break;
return((dev->status == SCSI_STATUS_OK) ? 1 : 0); default:
x54x_log("BIOS: Unimplemented command: %02X\n", cmd->command);
case 0x0d: /* Alternate Disk Reset, in practice it's a nop */ case 0x05: /* Format Track, invalid since SCSI has no tracks */
case 0x0a: /* ???? */
case 0x0b: /* ???? */
case 0x12: /* ???? */
case 0x13: /* ???? */
//FIXME: add a longer delay here --FvK //FIXME: add a longer delay here --FvK
return(0); ret = 0x01;
break;
case 0x06: /* Identify SCSI Devices, in practice it's a nop */
case 0x09: /* Initialize Drive Pair Characteristics, in practice it's a nop */
case 0x0d: /* Alternate Disk Reset, in practice it's a nop */
case 0x0e: /* Read Sector Buffer */
case 0x0f: /* Write Sector Buffer */
case 0x14: /* Controller Diagnostic */
//FIXME: add a longer delay here --FvK
ret = 0x00;
break;
case 0x07: /* Format Unit */
case 0x10: /* Test Drive Ready */ case 0x10: /* Test Drive Ready */
target_check(cmd->id);
cdb[0] = GPCMD_TEST_UNIT_READY;
cdb[1] = (cmd->lun & 7) << 5;
scsi_device_command_phase0(dev, cdb);
return(completion_code(scsi_device_sense(dev)));
case 0x11: /* Recalibrate */ case 0x11: /* Recalibrate */
target_check(cmd->id); target_check(cmd->id);
cdb[0] = GPCMD_REZERO_UNIT; cdb[0] = bios_cmd_to_scsi[cmd->command];
cdb[1] = (cmd->lun & 7) << 5; cdb[1] = (cmd->lun & 7) << 5;
scsi_device_command_phase0(dev, cdb); ret = x54x_bios_scsi_command(dev, cdb, NULL, sector_len, dma_address);
break;
return(completion_code(scsi_device_sense(dev)));
case 0x14: /* Controller Diagnostic */
//FIXME: add a longer delay here --FvK
return(0);
case 0x08: /* Read Drive Parameters */
case 0x15: /* Read DASD Type */ case 0x15: /* Read DASD Type */
target_check(cmd->id); target_check(cmd->id);
@@ -550,25 +555,26 @@ skip_write_phase1:
dev->cmd_buffer = (uint8_t *)malloc(dev->buffer_length); dev->cmd_buffer = (uint8_t *)malloc(dev->buffer_length);
memset(dev->cmd_buffer, 0x00, dev->buffer_length); memset(dev->cmd_buffer, 0x00, dev->buffer_length);
ret = x54x_bios_command_15(cmd->id, dev->cmd_buffer); buf = (uint8_t *) malloc(6);
if (cmd->command == 0x08)
ret = x54x_bios_command_08(dev, buf);
else
ret = x54x_bios_command_15(dev, buf);
x54x_log("BIOS DMA: Reading 6 bytes at %08X\n", dma_address); x54x_log("BIOS DMA: Reading 6 bytes at %08X\n", dma_address);
DMAPageWrite(dma_address, DMAPageWrite(dma_address, buf, 4);
dev->cmd_buffer, 4 /* dev->buffer_length */); free(buf);
if (dev->cmd_buffer != NULL) { if (dev->cmd_buffer != NULL) {
free(dev->cmd_buffer); free(dev->cmd_buffer);
dev->cmd_buffer = NULL; dev->cmd_buffer = NULL;
} }
return(ret); break;
default:
x54x_log("BIOS: Unimplemented command: %02X\n", cmd->command);
return(1);
} }
x54x_log("BIOS Request complete\n"); x54x_log("BIOS Request %02X complete: %02X\n", cmd->command, ret);
return(ret);
} }

View File

@@ -8,7 +8,7 @@
* *
* Hercules emulation. * Hercules emulation.
* *
* Version: @(#)vid_hercules.c 1.0.13 2018/10/10 * Version: @(#)vid_hercules.c 1.0.14 2018/10/11
* *
* 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>
@@ -430,7 +430,12 @@ hercules_close(void *priv)
{ {
hercules_t *dev = (hercules_t *)priv; hercules_t *dev = (hercules_t *)priv;
free(dev->vram); if (!dev)
return;
if (dev->vram)
free(dev->vram);
free(dev); free(dev);
} }

View File

@@ -8,7 +8,7 @@
* *
* Hercules Plus emulation. * Hercules Plus emulation.
* *
* Version: @(#)vid_herculesplus.c 1.0.11 2018/10/10 * Version: @(#)vid_herculesplus.c 1.0.12 2018/10/11
* *
* 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>
@@ -653,7 +653,12 @@ herculesplus_close(void *priv)
{ {
herculesplus_t *dev = (herculesplus_t *)priv; herculesplus_t *dev = (herculesplus_t *)priv;
free(dev->vram); if (!dev)
return;
if (dev->vram)
free(dev->vram);
free(dev); free(dev);
} }

View File

@@ -8,7 +8,7 @@
* *
* Hercules InColor emulation. * Hercules InColor emulation.
* *
* Version: @(#)vid_incolor.c 1.0.12 2018/10/10 * Version: @(#)vid_incolor.c 1.0.13 2018/10/11
* *
* 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>
@@ -1061,7 +1061,12 @@ incolor_close(void *priv)
{ {
incolor_t *dev = (incolor_t *)priv; incolor_t *dev = (incolor_t *)priv;
free(dev->vram); if (!dev)
return;
if (dev->vram)
free(dev->vram);
free(dev); free(dev);
} }