From c07b76dc8e9ea9a85c2eb53c23b2040e5f52e968 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 3 Mar 2018 21:32:24 +0000 Subject: [PATCH] ATAPI sector accesses can not be split over multiple transfers. Fixes Windows XP installer. --- src/ide.c | 4 ++-- src/ide_atapi.c | 6 ++++++ src/ide_atapi.h | 1 + src/scsi.c | 5 +++-- src/scsi.h | 6 ++++-- src/scsi_cd.c | 9 ++++++++- src/scsi_zip.c | 9 ++++++++- 7 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/ide.c b/src/ide.c index 0661db5..3f8a6a7 100644 --- a/src/ide.c +++ b/src/ide.c @@ -277,12 +277,12 @@ void resetide(void) if (cdrom_channel == d) { ide_drives[d].type = IDE_CDROM; - scsi_bus_atapi_init(&ide_drives[d].atapi.bus, &scsi_cd, d); + scsi_bus_atapi_init(&ide_drives[d].atapi.bus, &scsi_cd, d, &ide_drives[d].atapi); } else if (zip_channel == d) { ide_drives[d].type = IDE_CDROM; - scsi_bus_atapi_init(&ide_drives[d].atapi.bus, &scsi_zip, d); + scsi_bus_atapi_init(&ide_drives[d].atapi.bus, &scsi_zip, d, &ide_drives[d].atapi); } else { diff --git a/src/ide_atapi.c b/src/ide_atapi.c index 7ac20a2..0570eba 100644 --- a/src/ide_atapi.c +++ b/src/ide_atapi.c @@ -134,6 +134,12 @@ uint8_t atapi_read_drq(atapi_device_t *atapi_dev) return atapi_dev->bus_state & BUS_REQ; } +void atapi_set_transfer_granularity(atapi_device_t *atapi_dev, int size) +{ + if (atapi_dev->max_transfer_len > size) + atapi_dev->max_transfer_len -= (atapi_dev->max_transfer_len % size); +} + void atapi_process_packet(atapi_device_t *atapi_dev) { // pclog("atapi_process_packet: state=%i\n", atapi_dev->state); diff --git a/src/ide_atapi.h b/src/ide_atapi.h index 43ca829..517417a 100644 --- a/src/ide_atapi.h +++ b/src/ide_atapi.h @@ -61,5 +61,6 @@ void atapi_command_start(atapi_device_t *atapi); uint8_t atapi_read_iir(atapi_device_t *atapi_dev); uint8_t atapi_read_drq(atapi_device_t *atapi_dev); void atapi_process_packet(atapi_device_t *atapi_dev); +void atapi_set_transfer_granularity(atapi_device_t *atapi_dev, int size); #endif diff --git a/src/scsi.c b/src/scsi.c index 09b53b7..df4b8a8 100644 --- a/src/scsi.c +++ b/src/scsi.c @@ -1,5 +1,6 @@ #include "ibm.h" #include "ide.h" +#include "ide_atapi.h" #include "scsi.h" #include "scsi_cd.h" #include "scsi_hd.h" @@ -323,13 +324,13 @@ void scsi_bus_kick(scsi_bus_t *bus) scsi_bus_update(bus, 0); } -void scsi_bus_atapi_init(scsi_bus_t *bus, scsi_device_t *device, int id) +void scsi_bus_atapi_init(scsi_bus_t *bus, scsi_device_t *device, int id, atapi_device_t *atapi_dev) { memset(bus->devices, 0, sizeof(bus->devices)); memset(bus->device_data, 0, sizeof(bus->device_data)); bus->devices[0] = device; - bus->device_data[0] = bus->devices[0]->atapi_init(bus, id); + bus->device_data[0] = bus->devices[0]->atapi_init(bus, id, atapi_dev); if (!bus->device_data[0]) bus->devices[0] = NULL; diff --git a/src/scsi.h b/src/scsi.h index b290aec..a89010c 100644 --- a/src/scsi.h +++ b/src/scsi.h @@ -2,11 +2,12 @@ #define _SCSI_H_ struct scsi_bus_t; +struct atapi_device_t; typedef struct scsi_device_t { void *(*init)(struct scsi_bus_t *bus, int id); - void *(*atapi_init)(struct scsi_bus_t *bus, int id); + void *(*atapi_init)(struct scsi_bus_t *bus, int id, struct atapi_device_t *atapi_dev); void (*close)(void *p); void (*start_command)(void *p); @@ -104,7 +105,8 @@ int scsi_bus_match(scsi_bus_t *bus, int bus_assert); void scsi_bus_kick(scsi_bus_t *bus); void scsi_bus_init(scsi_bus_t *bus); void scsi_bus_close(scsi_bus_t *bus); -void scsi_bus_atapi_init(scsi_bus_t *bus, scsi_device_t *device, int id); + +void scsi_bus_atapi_init(scsi_bus_t *bus, scsi_device_t *device, int id, struct atapi_device_t *atapi_dev); #define KEY_NONE 0 #define KEY_NOT_READY 2 diff --git a/src/scsi_cd.c b/src/scsi_cd.c index 9a33674..718c3a9 100644 --- a/src/scsi_cd.c +++ b/src/scsi_cd.c @@ -193,6 +193,7 @@ typedef struct scsi_cd_data_t uint8_t page_current; int is_atapi; + atapi_device_t *atapi_dev; } scsi_cd_data_t; static void scsi_add_data(scsi_cd_data_t *data, uint8_t val) @@ -283,11 +284,12 @@ static void *scsi_cd_init(scsi_bus_t *bus, int id) return data; } -static void *scsi_cd_atapi_init(scsi_bus_t *bus, int id) +static void *scsi_cd_atapi_init(scsi_bus_t *bus, int id, atapi_device_t *atapi_dev) { scsi_cd_data_t *data = scsi_cd_init(bus, id); data->is_atapi = 1; + data->atapi_dev = atapi_dev; return data; } @@ -625,6 +627,10 @@ static int scsi_cd_command(uint8_t *cdb, void *p) data->cmd_pos = CMD_POS_TRANSFER; data->bytes_expected = data->cdlen * ((rcdmode == 0x10) ? 2048 : 2352); + if (rcdmode == 0x10) + atapi_set_transfer_granularity(data->atapi_dev, 2048); + else + atapi_set_transfer_granularity(data->atapi_dev, 2352); } if (!data->cdlen) { @@ -689,6 +695,7 @@ static int scsi_cd_command(uint8_t *cdb, void *p) data->cmd_pos = CMD_POS_TRANSFER; data->bytes_expected = data->cdlen * 2048; + atapi_set_transfer_granularity(data->atapi_dev, 2048); } if (!data->cdlen) diff --git a/src/scsi_zip.c b/src/scsi_zip.c index 8af34d9..e6bb291 100644 --- a/src/scsi_zip.c +++ b/src/scsi_zip.c @@ -4,6 +4,7 @@ #include #include "ibm.h" #include "hdd_file.h" +#include "ide_atapi.h" #include "scsi.h" #include "scsi_zip.h" #include "timer.h" @@ -69,6 +70,7 @@ typedef struct scsi_zip_data scsi_bus_t *bus; int is_atapi; + atapi_device_t *atapi_dev; int read_only; } scsi_zip_data; @@ -193,11 +195,12 @@ static void *scsi_zip_init(scsi_bus_t *bus, int id) return data; } -static void *scsi_zip_atapi_init(scsi_bus_t *bus, int id) +static void *scsi_zip_atapi_init(scsi_bus_t *bus, int id, atapi_device_t *atapi_dev) { scsi_zip_data *data = scsi_zip_init(bus, id); data->is_atapi = 1; + data->atapi_dev = atapi_dev; return data; } @@ -686,6 +689,7 @@ static int scsi_zip_command(uint8_t *cdb, void *p) data->sector_pos = 0; bus_state = BUS_CD; + atapi_set_transfer_granularity(data->atapi_dev, 512); break; } // else @@ -746,6 +750,7 @@ static int scsi_zip_command(uint8_t *cdb, void *p) data->sector_pos = 0; bus_state = BUS_CD; + atapi_set_transfer_granularity(data->atapi_dev, 512); break; } // else @@ -814,6 +819,7 @@ static int scsi_zip_command(uint8_t *cdb, void *p) data->sector_pos = 0; bus_state = BUS_CD; + atapi_set_transfer_granularity(data->atapi_dev, 512); break; } if (data->cmd_pos == CMD_POS_TRANSFER && data->bytes_received != data->bytes_required) @@ -881,6 +887,7 @@ static int scsi_zip_command(uint8_t *cdb, void *p) data->sector_pos = 0; bus_state = BUS_CD; + atapi_set_transfer_granularity(data->atapi_dev, 512); break; } if (data->cmd_pos == CMD_POS_TRANSFER && data->bytes_received != data->bytes_required)