Extensive rework of SCSI and ATAPI devices and numerous bug fixes and cleanups;
Extensive rework of CD-ROM image handling; The settings save code now forces some devices' (SCSI disk, CD-ROM, etc.) pointers to NULL before resetting the machine - fixes segmentation faults after changing settings; Added the NCR 53c825A and 53c875 SCSI controllers; Fixed IDE/ATAPI DMA; Slight changed to PCI IDE bus master operation.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Generic CD-ROM drive core.
|
||||
*
|
||||
* Version: @(#)cdrom.c 1.0.5 2018/10/26
|
||||
* Version: @(#)cdrom.c 1.0.6 2018/10/28
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
@@ -30,10 +30,66 @@
|
||||
#include "../sound/sound.h"
|
||||
|
||||
|
||||
/* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong:
|
||||
there is a seeming 2 seconds in which audio plays but counter does not move, while a data track before audio jumps to 2 seconds before the actual start
|
||||
of the audio while audio still plays. With an absolute conversion, the counter is fine. */
|
||||
#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f)
|
||||
|
||||
#define RAW_SECTOR_SIZE 2352
|
||||
#define COOKED_SECTOR_SIZE 2048
|
||||
|
||||
#define MIN_SEEK 2000
|
||||
#define MAX_SEEK 333333
|
||||
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
uint8_t user_data[2048],
|
||||
ecc[288];
|
||||
} m1_data_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t sub_header[8],
|
||||
user_data[2328];
|
||||
} m2_data_t;
|
||||
|
||||
typedef union {
|
||||
m1_data_t m1_data;
|
||||
m2_data_t m2_data;
|
||||
uint8_t raw_data[2336];
|
||||
} sector_data_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t sync[12];
|
||||
uint8_t header[4];
|
||||
sector_data_t data;
|
||||
} sector_raw_data_t;
|
||||
|
||||
typedef union {
|
||||
sector_raw_data_t sector_data;
|
||||
uint8_t raw_data[2352];
|
||||
} sector_t;
|
||||
|
||||
typedef struct {
|
||||
sector_t sector;
|
||||
uint8_t c2[296];
|
||||
uint8_t subchannel_raw[96];
|
||||
uint8_t subchannel_q[16];
|
||||
uint8_t subchannel_rw[96];
|
||||
} cdrom_sector_t;
|
||||
|
||||
typedef union {
|
||||
cdrom_sector_t cdrom_sector;
|
||||
uint8_t buffer[2856];
|
||||
} sector_buffer_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
static int cdrom_sector_size;
|
||||
static uint8_t raw_buffer[2856]; /* Needs to be the same size as sector_buffer_t in the structs. */
|
||||
static uint8_t extra_buffer[296];
|
||||
|
||||
|
||||
cdrom_t cdrom[CDROM_NUM];
|
||||
|
||||
|
||||
@@ -157,36 +213,751 @@ cdrom_seek_time(cdrom_t *dev)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cdrom_stop(cdrom_t *dev)
|
||||
{
|
||||
if (dev->cd_status > CD_STATUS_DATA_ONLY)
|
||||
dev->cd_status = CD_STATUS_STOPPED;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cdrom_seek(cdrom_t *dev, uint32_t pos)
|
||||
{
|
||||
/* cdrom_log("CD-ROM %i: Seek %08X\n", dev->id, pos); */
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
cdrom_log("CD-ROM %i: Seek to LBA %08X\n", dev->id, pos);
|
||||
|
||||
dev->seek_pos = pos;
|
||||
if (dev->ops && dev->ops->stop)
|
||||
dev->ops->stop(dev);
|
||||
cdrom_stop(dev);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cdrom_playing_completed(cdrom_t *dev)
|
||||
cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len)
|
||||
{
|
||||
dev->prev_status = dev->cd_status;
|
||||
int ret = 1;
|
||||
|
||||
if (dev->ops && dev->ops->status)
|
||||
dev->cd_status = dev->ops->status(dev);
|
||||
else {
|
||||
dev->cd_status = CD_STATUS_EMPTY;
|
||||
if (!dev->sound_on || (dev->cd_status != CD_STATUS_PLAYING)) {
|
||||
cdrom_log("CD-ROM %i: Audio callback while not playing\n", dev->id);
|
||||
if (dev->cd_status == CD_STATUS_PLAYING)
|
||||
dev->seek_pos += (len >> 11);
|
||||
memset(output, 0, len * 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (((dev->prev_status == CD_STATUS_PLAYING) || (dev->prev_status == CD_STATUS_PAUSED)) &&
|
||||
((dev->cd_status != CD_STATUS_PLAYING) && (dev->cd_status != CD_STATUS_PAUSED)))
|
||||
return 1;
|
||||
while (dev->cd_buflen < len) {
|
||||
if (dev->seek_pos < dev->cd_end) {
|
||||
if (dev->ops->read_sector(dev, CD_READ_AUDIO,
|
||||
(uint8_t *) &(dev->cd_buffer[dev->cd_buflen]),
|
||||
dev->seek_pos)) {
|
||||
cdrom_log("CD-ROM %i: Read LBA %08X successful\n", dev->id, dev->seek_pos);
|
||||
dev->seek_pos++;
|
||||
dev->cd_buflen += (RAW_SECTOR_SIZE / 2);
|
||||
ret = 1;
|
||||
} else {
|
||||
cdrom_log("CD-ROM %i: Read LBA %08X failed\n", dev->id, dev->seek_pos);
|
||||
memset(&(dev->cd_buffer[dev->cd_buflen]),
|
||||
0x00, (BUF_SIZE - dev->cd_buflen) * 2);
|
||||
dev->cd_status = CD_STATUS_STOPPED;
|
||||
dev->cd_buflen = len;
|
||||
ret = 0;
|
||||
}
|
||||
} else {
|
||||
cdrom_log("CD-ROM %i: Playing completed\n", dev->id);
|
||||
memset(&dev->cd_buffer[dev->cd_buflen],
|
||||
0x00, (BUF_SIZE - dev->cd_buflen) * 2);
|
||||
dev->cd_status = CD_STATUS_PLAYING_COMPLETED;
|
||||
dev->cd_buflen = len;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(output, dev->cd_buffer, len * 2);
|
||||
memmove(dev->cd_buffer, &dev->cd_buffer[len], (BUF_SIZE - len) * 2);
|
||||
dev->cd_buflen -= len;
|
||||
|
||||
cdrom_log("CD-ROM %i: Audio callback returning %i\n", dev->id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf)
|
||||
{
|
||||
track_info_t ti;
|
||||
int m = 0, s = 0, f = 0;
|
||||
|
||||
if (dev->cd_status == CD_STATUS_DATA_ONLY)
|
||||
return 0;
|
||||
|
||||
cdrom_log("CD-ROM %i: Play audio - %08X %08X %i\n", dev->id, pos, len, ismsf);
|
||||
if (ismsf == 2) {
|
||||
dev->ops->get_track_info(dev, pos, 0, &ti);
|
||||
pos = MSFtoLBA(ti.m, ti.s, ti.f) - 150;
|
||||
/* We have to end at the *end* of the specified track,
|
||||
not at the beginning. */
|
||||
dev->ops->get_track_info(dev, len, 1, &ti);
|
||||
len = MSFtoLBA(ti.m, ti.s, ti.f) - 150;
|
||||
} else if (ismsf == 1) {
|
||||
m = (pos >> 16) & 0xff;
|
||||
s = (pos >> 8) & 0xff;
|
||||
f = pos & 0xff;
|
||||
|
||||
if (pos == 0xffffff) {
|
||||
cdrom_log("CD-ROM %i: Playing from current position (MSF)\n", dev->id);
|
||||
pos = dev->seek_pos;
|
||||
} else
|
||||
pos = MSFtoLBA(m, s, f) - 150;
|
||||
|
||||
m = (len >> 16) & 0xff;
|
||||
s = (len >> 8) & 0xff;
|
||||
f = len & 0xff;
|
||||
len = MSFtoLBA(m, s, f) - 150;
|
||||
|
||||
cdrom_log("CD-ROM %i: MSF - pos = %08X len = %08X\n", dev->id, pos, len);
|
||||
} else if (ismsf == 0) {
|
||||
if (pos == 0xffffffff) {
|
||||
cdrom_log("CD-ROM %i: Playing from current position\n", dev->id);
|
||||
pos = dev->seek_pos;
|
||||
}
|
||||
len += pos;
|
||||
}
|
||||
|
||||
/* Do this at this point, since it's at this point that we know the
|
||||
actual LBA position to start playing from. */
|
||||
if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) {
|
||||
pclog("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos);
|
||||
cdrom_stop(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev->seek_pos = pos;
|
||||
dev->cd_end = len;
|
||||
dev->cd_status = CD_STATUS_PLAYING;
|
||||
dev->cd_buflen = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cdrom_audio_pause_resume(cdrom_t *dev, uint8_t resume)
|
||||
{
|
||||
if ((dev->cd_status == CD_STATUS_PLAYING) || (dev->cd_status == CD_STATUS_PAUSED))
|
||||
dev->cd_status = (dev->cd_status & 0xfe) | (resume & 0x01);
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf)
|
||||
{
|
||||
uint8_t ret;
|
||||
subchannel_t subc;
|
||||
int pos = 0;
|
||||
|
||||
dev->ops->get_subchannel(dev, dev->seek_pos, &subc);
|
||||
cdrom_log("CD-ROM %i: Returned subchannel at %02i:%02i.%02i\n", subc.abs_m, subc.abs_s, subc.abs_f);
|
||||
|
||||
if (dev->cd_status == CD_STATUS_DATA_ONLY)
|
||||
ret = 0x15;
|
||||
else {
|
||||
if (dev->cd_status == CD_STATUS_PLAYING)
|
||||
ret = 0x11;
|
||||
else if (dev->cd_status == CD_STATUS_PAUSED)
|
||||
ret = 0x12;
|
||||
else
|
||||
ret = 0x13;
|
||||
}
|
||||
|
||||
b[pos++] = subc.attr;
|
||||
b[pos++] = subc.track;
|
||||
b[pos++] = subc.index;
|
||||
|
||||
if (msf) {
|
||||
b[pos] = 0;
|
||||
b[pos + 1] = subc.abs_m;
|
||||
b[pos + 2] = subc.abs_s;
|
||||
b[pos + 3] = subc.abs_f;
|
||||
pos += 4;
|
||||
b[pos] = 0;
|
||||
b[pos + 1] = subc.rel_m;
|
||||
b[pos + 2] = subc.rel_s;
|
||||
b[pos + 3] = subc.rel_f;
|
||||
pos += 4;
|
||||
} else {
|
||||
uint32_t dat = MSFtoLBA(subc.abs_m, subc.abs_s, subc.abs_f) - 150;
|
||||
b[pos++] = (dat >> 24) & 0xff;
|
||||
b[pos++] = (dat >> 16) & 0xff;
|
||||
b[pos++] = (dat >> 8) & 0xff;
|
||||
b[pos++] = dat & 0xff;
|
||||
dat = MSFtoLBA(subc.rel_m, subc.rel_s, subc.rel_f);
|
||||
b[pos++] = (dat >> 24) & 0xff;
|
||||
b[pos++] = (dat >> 16) & 0xff;
|
||||
b[pos++] = (dat >> 8) & 0xff;
|
||||
b[pos++] = dat & 0xff;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
read_toc_normal(cdrom_t *dev, unsigned char *b, unsigned char start_track, int msf)
|
||||
{
|
||||
track_info_t ti;
|
||||
int len = 4;
|
||||
int c, d, first_track, last_track;
|
||||
uint32_t temp;
|
||||
|
||||
dev->ops->get_tracks(dev, &first_track, &last_track);
|
||||
|
||||
b[2] = first_track;
|
||||
b[3] = last_track;
|
||||
|
||||
d = 0;
|
||||
for (c = 0; c <= last_track; c++) {
|
||||
dev->ops->get_track_info(dev, c + 1, 0, &ti);
|
||||
if (ti.number >= start_track) {
|
||||
d = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (start_track != 0xAA) {
|
||||
dev->ops->get_track_info(dev, c + 1, 0, &ti);
|
||||
b[2] = ti.number;
|
||||
}
|
||||
|
||||
for (c = d; c <= last_track; c++) {
|
||||
dev->ops->get_track_info(dev, c + 1, 0, &ti);
|
||||
|
||||
b[len++] = 0; /* reserved */
|
||||
b[len++] = ti.attr;
|
||||
b[len++] = ti.number; /* track number */
|
||||
b[len++] = 0; /* reserved */
|
||||
|
||||
if (msf) {
|
||||
b[len++] = 0;
|
||||
b[len++] = ti.m;
|
||||
b[len++] = ti.s;
|
||||
b[len++] = ti.f;
|
||||
} else {
|
||||
temp = MSFtoLBA(ti.m, ti.s, ti.f) - 150;
|
||||
b[len++] = temp >> 24;
|
||||
b[len++] = temp >> 16;
|
||||
b[len++] = temp >> 8;
|
||||
b[len++] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
read_toc_session(cdrom_t *dev, unsigned char *b, int msf)
|
||||
{
|
||||
track_info_t ti;
|
||||
int len = 4;
|
||||
uint32_t temp;
|
||||
|
||||
dev->ops->get_track_info(dev, 1, 0, &ti);
|
||||
|
||||
if (ti.number == 0)
|
||||
ti.number = 1;
|
||||
|
||||
b[2] = b[3] = 1;
|
||||
b[len++] = 0; /* reserved */
|
||||
b[len++] = ti.attr;
|
||||
b[len++] = ti.number; /* track number */
|
||||
b[len++] = 0; /* reserved */
|
||||
if (msf) {
|
||||
b[len++] = 0;
|
||||
b[len++] = ti.m;
|
||||
b[len++] = ti.s;
|
||||
b[len++] = ti.f;
|
||||
} else {
|
||||
temp = MSFtoLBA(ti.m, ti.s, ti.f) - 150; /* Do the - 150. */
|
||||
b[len++] = temp >> 24;
|
||||
b[len++] = temp >> 16;
|
||||
b[len++] = temp >> 8;
|
||||
b[len++] = temp;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
read_toc_raw(cdrom_t *dev, unsigned char *b)
|
||||
{
|
||||
track_info_t ti;
|
||||
int first_track, last_track;
|
||||
int track, len = 4;
|
||||
|
||||
dev->ops->get_tracks(dev, &first_track, &last_track);
|
||||
|
||||
b[2] = first_track;
|
||||
b[3] = last_track;
|
||||
|
||||
for (track = first_track; track <= last_track; track++) {
|
||||
dev->ops->get_track_info(dev, track, 0, &ti);
|
||||
|
||||
b[len++] = track;
|
||||
b[len++] = ti.attr;
|
||||
b[len++] = 0;
|
||||
b[len++] = 0;
|
||||
b[len++] = 0;
|
||||
b[len++] = 0;
|
||||
b[len++] = 0;
|
||||
b[len++] = 0;
|
||||
b[len++] = ti.m;
|
||||
b[len++] = ti.s;
|
||||
b[len++] = ti.f;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cdrom_read_toc(cdrom_t *dev, unsigned char *b, int type, unsigned char start_track, int msf, int max_len)
|
||||
{
|
||||
int len;
|
||||
|
||||
switch(type) {
|
||||
case CD_TOC_NORMAL:
|
||||
len = read_toc_normal(dev, b, start_track, msf);
|
||||
break;
|
||||
case CD_TOC_SESSION:
|
||||
len = read_toc_session(dev, b, msf);
|
||||
break;
|
||||
case CD_TOC_RAW:
|
||||
len = read_toc_raw(dev, b);
|
||||
break;
|
||||
default:
|
||||
cdrom_log("CD-ROM %i: Unknown TOC read type: %i\n", dev->id, type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = MIN(len, max_len);
|
||||
|
||||
b[0] = (uint8_t) (((len - 2) >> 8) & 0xff);
|
||||
b[1] = (uint8_t) ((len - 2) & 0xff);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
track_type_is_valid(uint8_t id, int type, int flags, int audio, int mode2)
|
||||
{
|
||||
if (!(flags & 0x70)) { /* 0x00/0x08/0x80/0x88 are illegal modes */
|
||||
cdrom_log("CD-ROM %i: [Any Mode] 0x00/0x08/0x80/0x88 are illegal modes\n", id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((type != 1) && !audio) {
|
||||
if (!(flags & 0x70)) { /* 0x00/0x08/0x80/0x88 are illegal modes */
|
||||
cdrom_log("CD-ROM %i: [Any Data Mode] 0x00/0x08/0x80/0x88 are illegal modes\n", id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((flags & 0x06) == 0x06) {
|
||||
cdrom_log("CD-ROM %i: [Any Data Mode] Invalid error flags\n", id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (((flags & 0x700) == 0x300) || ((flags & 0x700) > 0x400)) {
|
||||
cdrom_log("CD-ROM %i: [Any Data Mode] Invalid subchannel data flags (%02X)\n", id, flags & 0x700);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((flags & 0x18) == 0x08) { /* EDC/ECC without user data is an illegal mode */
|
||||
cdrom_log("CD-ROM %i: [Any Data Mode] EDC/ECC without user data is an illegal mode\n", id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (((flags & 0xf0) == 0x90) || ((flags & 0xf0) == 0xc0)) { /* 0x90/0x98/0xC0/0xC8 are illegal modes */
|
||||
cdrom_log("CD-ROM %i: [Any Data Mode] 0x90/0x98/0xC0/0xC8 are illegal modes\n", id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (((type > 3) && (type != 8)) || (mode2 && (mode2 & 0x03))) {
|
||||
if ((flags & 0xf0) == 0x30) { /* 0x30/0x38 are illegal modes */
|
||||
cdrom_log("CD-ROM %i: [Any XA Mode 2] 0x30/0x38 are illegal modes\n", id);
|
||||
return 0;
|
||||
}
|
||||
if (((flags & 0xf0) == 0xb0) || ((flags & 0xf0) == 0xd0)) { /* 0xBx and 0xDx are illegal modes */
|
||||
cdrom_log("CD-ROM %i: [Any XA Mode 2] 0xBx and 0xDx are illegal modes\n", id);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
read_sector_to_buffer(cdrom_t *dev, uint8_t *rbuf, uint32_t msf, uint32_t lba, int mode2, int len)
|
||||
{
|
||||
uint8_t *bb = rbuf;
|
||||
|
||||
dev->ops->read_sector(dev, CD_READ_DATA, rbuf + 16, lba);
|
||||
|
||||
/* Sync bytes */
|
||||
bb[0] = 0;
|
||||
memset(bb + 1, 0xff, 10);
|
||||
bb[11] = 0;
|
||||
bb += 12;
|
||||
|
||||
/* Sector header */
|
||||
bb[0] = (msf >> 16) & 0xff;
|
||||
bb[1] = (msf >> 8) & 0xff;
|
||||
bb[2] = msf & 0xff;
|
||||
|
||||
bb[3] = 1; /* mode 1 data */
|
||||
bb += mode2 ? 12 : 4;
|
||||
bb += len;
|
||||
if (mode2 && ((mode2 & 0x03) == 1))
|
||||
memset(bb, 0, 280);
|
||||
else if (!mode2)
|
||||
memset(bb, 0, 288);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
read_audio(cdrom_t *dev, uint32_t lba, uint8_t *b)
|
||||
{
|
||||
dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba);
|
||||
|
||||
memcpy(b, raw_buffer, 2352);
|
||||
|
||||
cdrom_sector_size = 2352;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
read_mode1(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b)
|
||||
{
|
||||
if ((dev->cd_status == CD_STATUS_DATA_ONLY) || (dev->ops->sector_size(dev, lba) == 2048))
|
||||
read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2048);
|
||||
else
|
||||
dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba);
|
||||
|
||||
cdrom_sector_size = 0;
|
||||
|
||||
if (cdrom_sector_flags & 0x80) { /* Sync */
|
||||
cdrom_log("CD-ROM %i: [Mode 1] Sync\n", dev->id);
|
||||
memcpy(b, raw_buffer, 12);
|
||||
cdrom_sector_size += 12;
|
||||
b += 12;
|
||||
}
|
||||
|
||||
if (cdrom_sector_flags & 0x20) { /* Header */
|
||||
cdrom_log("CD-ROM %i: [Mode 1] Header\n", dev->id);
|
||||
memcpy(b, raw_buffer + 12, 4);
|
||||
cdrom_sector_size += 4;
|
||||
b += 4;
|
||||
}
|
||||
|
||||
if (cdrom_sector_flags & 0x40) { /* Sub-header */
|
||||
if (!(cdrom_sector_flags & 0x10)) { /* No user data */
|
||||
cdrom_log("CD-ROM %i: [Mode 1] Sub-header\n", dev->id);
|
||||
memcpy(b, raw_buffer + 16, 8);
|
||||
cdrom_sector_size += 8;
|
||||
b += 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (cdrom_sector_flags & 0x10) { /* User data */
|
||||
cdrom_log("CD-ROM %i: [Mode 1] User data\n", dev->id);
|
||||
memcpy(b, raw_buffer + 16, 2048);
|
||||
cdrom_sector_size += 2048;
|
||||
b += 2048;
|
||||
}
|
||||
|
||||
if (cdrom_sector_flags & 0x08) { /* EDC/ECC */
|
||||
cdrom_log("CD-ROM %i: [Mode 1] EDC/ECC\n", dev->id);
|
||||
memcpy(b, raw_buffer + 2064, 288);
|
||||
cdrom_sector_size += 288;
|
||||
b += 288;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
read_mode2_non_xa(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b)
|
||||
{
|
||||
if ((dev->cd_status == CD_STATUS_DATA_ONLY) || (dev->ops->sector_size(dev, lba) == 2336))
|
||||
read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2336);
|
||||
else
|
||||
dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba);
|
||||
|
||||
cdrom_sector_size = 0;
|
||||
|
||||
if (cdrom_sector_flags & 0x80) { /* Sync */
|
||||
cdrom_log("CD-ROM %i: [Mode 2 Formless] Sync\n", dev->id);
|
||||
memcpy(b, raw_buffer, 12);
|
||||
cdrom_sector_size += 12;
|
||||
b += 12;
|
||||
}
|
||||
|
||||
if (cdrom_sector_flags & 0x20) { /* Header */
|
||||
cdrom_log("CD-ROM %i: [Mode 2 Formless] Header\n", dev->id);
|
||||
memcpy(b, raw_buffer + 12, 4);
|
||||
cdrom_sector_size += 4;
|
||||
b += 4;
|
||||
}
|
||||
|
||||
/* Mode 1 sector, expected type is 1 type. */
|
||||
if (cdrom_sector_flags & 0x40) { /* Sub-header */
|
||||
cdrom_log("CD-ROM %i: [Mode 2 Formless] Sub-header\n", dev->id);
|
||||
memcpy(b, raw_buffer + 16, 8);
|
||||
cdrom_sector_size += 8;
|
||||
b += 8;
|
||||
}
|
||||
|
||||
if (cdrom_sector_flags & 0x10) { /* User data */
|
||||
cdrom_log("CD-ROM %i: [Mode 2 Formless] User data\n", dev->id);
|
||||
memcpy(b, raw_buffer + 24, 2336);
|
||||
cdrom_sector_size += 2336;
|
||||
b += 2336;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
read_mode2_xa_form1(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b)
|
||||
{
|
||||
if ((dev->cd_status == CD_STATUS_DATA_ONLY) || (dev->ops->sector_size(dev, lba) == 2048))
|
||||
read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2048);
|
||||
else
|
||||
dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba);
|
||||
|
||||
cdrom_sector_size = 0;
|
||||
|
||||
if (cdrom_sector_flags & 0x80) { /* Sync */
|
||||
cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] Sync\n", dev->id);
|
||||
memcpy(b, raw_buffer, 12);
|
||||
cdrom_sector_size += 12;
|
||||
b += 12;
|
||||
}
|
||||
|
||||
if (cdrom_sector_flags & 0x20) { /* Header */
|
||||
cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] Header\n", dev->id);
|
||||
memcpy(b, raw_buffer + 12, 4);
|
||||
cdrom_sector_size += 4;
|
||||
b += 4;
|
||||
}
|
||||
|
||||
if (cdrom_sector_flags & 0x40) { /* Sub-header */
|
||||
cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] Sub-header\n", dev->id);
|
||||
memcpy(b, raw_buffer + 16, 8);
|
||||
cdrom_sector_size += 8;
|
||||
b += 8;
|
||||
}
|
||||
|
||||
if (cdrom_sector_flags & 0x10) { /* User data */
|
||||
cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] User data\n", dev->id);
|
||||
memcpy(b, raw_buffer + 24, 2048);
|
||||
cdrom_sector_size += 2048;
|
||||
b += 2048;
|
||||
}
|
||||
|
||||
if (cdrom_sector_flags & 0x08) { /* EDC/ECC */
|
||||
cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] EDC/ECC\n", dev->id);
|
||||
memcpy(b, raw_buffer + 2072, 280);
|
||||
cdrom_sector_size += 280;
|
||||
b += 280;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
read_mode2_xa_form2(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b)
|
||||
{
|
||||
if ((dev->cd_status == CD_STATUS_DATA_ONLY) || (dev->ops->sector_size(dev, lba) == 2324))
|
||||
read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2324);
|
||||
else
|
||||
dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba);
|
||||
|
||||
cdrom_sector_size = 0;
|
||||
|
||||
if (cdrom_sector_flags & 0x80) { /* Sync */
|
||||
cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] Sync\n", dev->id);
|
||||
memcpy(b, raw_buffer, 12);
|
||||
cdrom_sector_size += 12;
|
||||
b += 12;
|
||||
}
|
||||
|
||||
if (cdrom_sector_flags & 0x20) { /* Header */
|
||||
cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] Header\n", dev->id);
|
||||
memcpy(b, raw_buffer + 12, 4);
|
||||
cdrom_sector_size += 4;
|
||||
b += 4;
|
||||
}
|
||||
|
||||
if (cdrom_sector_flags & 0x40) { /* Sub-header */
|
||||
cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] Sub-header\n", dev->id);
|
||||
memcpy(b, raw_buffer + 16, 8);
|
||||
cdrom_sector_size += 8;
|
||||
b += 8;
|
||||
}
|
||||
|
||||
if (cdrom_sector_flags & 0x10) { /* User data */
|
||||
cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] User data\n", dev->id);
|
||||
memcpy(b, raw_buffer + 24, 2328);
|
||||
cdrom_sector_size += 2328;
|
||||
b += 2328;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type,
|
||||
int cdrom_sector_flags, int *len)
|
||||
{
|
||||
uint8_t *b, *temp_b;
|
||||
uint32_t msf, lba;
|
||||
int audio = 0, mode2 = 0;
|
||||
int m, s, f;
|
||||
|
||||
if (dev->cd_status == CD_STATUS_EMPTY)
|
||||
return 0;
|
||||
|
||||
b = temp_b = buffer;
|
||||
|
||||
*len = 0;
|
||||
|
||||
if (ismsf) {
|
||||
m = (sector >> 16) & 0xff;
|
||||
s = (sector >> 8) & 0xff;
|
||||
f = sector & 0xff;
|
||||
lba = MSFtoLBA(m, s, f) - 150;
|
||||
msf = sector;
|
||||
} else {
|
||||
lba = sector;
|
||||
msf = cdrom_lba_to_msf_accurate(sector);
|
||||
}
|
||||
|
||||
if (dev->ops->track_type)
|
||||
audio = dev->ops->track_type(dev, lba);
|
||||
|
||||
mode2 = audio & ~CD_TRACK_AUDIO;
|
||||
audio &= CD_TRACK_AUDIO;
|
||||
|
||||
memset(raw_buffer, 0, 2448);
|
||||
memset(extra_buffer, 0, 296);
|
||||
|
||||
if (!(cdrom_sector_flags & 0xf0)) { /* 0x00 and 0x08 are illegal modes */
|
||||
cdrom_log("CD-ROM %i: [Mode 1] 0x00 and 0x08 are illegal modes\n", dev->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!track_type_is_valid(dev->id, cdrom_sector_type, cdrom_sector_flags, audio, mode2))
|
||||
return 0;
|
||||
|
||||
if ((cdrom_sector_type > 5) && (cdrom_sector_type != 8)) {
|
||||
cdrom_log("CD-ROM %i: Attempting to read an unrecognized sector type from an image\n", dev->id);
|
||||
return 0;
|
||||
} else if (cdrom_sector_type == 1) {
|
||||
if (!audio || (dev->cd_status == CD_STATUS_DATA_ONLY)) {
|
||||
cdrom_log("CD-ROM %i: [Audio] Attempting to read an audio sector from a data image\n", dev->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
read_audio(dev, lba, temp_b);
|
||||
} else if (cdrom_sector_type == 2) {
|
||||
if (audio || mode2) {
|
||||
cdrom_log("CD-ROM %i: [Mode 1] Attempting to read a sector of another type\n", dev->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
|
||||
} else if (cdrom_sector_type == 3) {
|
||||
if (audio || !mode2 || (mode2 & 0x03)) {
|
||||
cdrom_log("CD-ROM %i: [Mode 2 Formless] Attempting to read a sector of another type\n", dev->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
read_mode2_non_xa(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
|
||||
} else if (cdrom_sector_type == 4) {
|
||||
if (audio || !mode2 || ((mode2 & 0x03) != 1)) {
|
||||
cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] Attempting to read a sector of another type\n", dev->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
|
||||
} else if (cdrom_sector_type == 5) {
|
||||
if (audio || !mode2 || ((mode2 & 0x03) != 2)) {
|
||||
cdrom_log("CD-ROM %i: [XA Mode 2 Form 2] Attempting to read a sector of another type\n", dev->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
read_mode2_xa_form2(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
|
||||
} else if (cdrom_sector_type == 8) {
|
||||
if (audio) {
|
||||
cdrom_log("CD-ROM %i: [Any Data] Attempting to read a data sector from an audio track\n", dev->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mode2 && ((mode2 & 0x03) == 1))
|
||||
read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
|
||||
else if (!mode2)
|
||||
read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
|
||||
else {
|
||||
cdrom_log("CD-ROM %i: [Any Data] Attempting to read a data sector whose cooked size is not 2048 bytes\n", dev->id);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (mode2) {
|
||||
if ((mode2 & 0x03) == 0x01)
|
||||
read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
|
||||
else if ((mode2 & 0x03) == 0x02)
|
||||
read_mode2_xa_form2(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
|
||||
else
|
||||
read_mode2_non_xa(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
|
||||
} else {
|
||||
if (audio)
|
||||
read_audio(dev, lba, temp_b);
|
||||
else
|
||||
read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
|
||||
}
|
||||
}
|
||||
|
||||
if ((cdrom_sector_flags & 0x06) == 0x02) {
|
||||
/* Add error flags. */
|
||||
cdrom_log("CD-ROM %i: Error flags\n", dev->id);
|
||||
memcpy(b + cdrom_sector_size, extra_buffer, 294);
|
||||
cdrom_sector_size += 294;
|
||||
} else if ((cdrom_sector_flags & 0x06) == 0x04) {
|
||||
/* Add error flags. */
|
||||
cdrom_log("CD-ROM %i: Full error flags\n", dev->id);
|
||||
memcpy(b + cdrom_sector_size, extra_buffer, 296);
|
||||
cdrom_sector_size += 296;
|
||||
}
|
||||
|
||||
if ((cdrom_sector_flags & 0x700) == 0x100) {
|
||||
cdrom_log("CD-ROM %i: Raw subchannel data\n", dev->id);
|
||||
memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96);
|
||||
cdrom_sector_size += 96;
|
||||
} else if ((cdrom_sector_flags & 0x700) == 0x200) {
|
||||
cdrom_log("CD-ROM %i: Q subchannel data\n", dev->id);
|
||||
memcpy(b + cdrom_sector_size, raw_buffer + 2352, 16);
|
||||
cdrom_sector_size += 16;
|
||||
} else if ((cdrom_sector_flags & 0x700) == 0x400) {
|
||||
cdrom_log("CD-ROM %i: R/W subchannel data\n", dev->id);
|
||||
memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96);
|
||||
cdrom_sector_size += 96;
|
||||
}
|
||||
|
||||
*len = cdrom_sector_size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -219,7 +990,7 @@ cdrom_hard_reset(void)
|
||||
for (i = 0; i < CDROM_NUM; i++) {
|
||||
dev = &cdrom[i];
|
||||
if (dev->bus_type) {
|
||||
cdrom_log("CDROM %i: hard_reset\n", i);
|
||||
cdrom_log("CD-ROM %i: Hard reset\n", i);
|
||||
|
||||
dev->id = i;
|
||||
|
||||
@@ -235,11 +1006,10 @@ cdrom_hard_reset(void)
|
||||
break;
|
||||
}
|
||||
|
||||
dev->cd_status = CD_STATUS_EMPTY;
|
||||
|
||||
if (dev->host_drive == 200) {
|
||||
if (dev->host_drive == 200)
|
||||
cdrom_image_open(dev, dev->image_path);
|
||||
cdrom_image_reset(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,14 +1026,13 @@ cdrom_close(void)
|
||||
for (i = 0; i < CDROM_NUM; i++) {
|
||||
dev = &cdrom[i];
|
||||
|
||||
if (dev->close)
|
||||
dev->close(dev->priv);
|
||||
|
||||
if (dev->ops && dev->ops->exit)
|
||||
dev->ops->exit(dev);
|
||||
|
||||
dev->ops = NULL;
|
||||
|
||||
if (dev->close)
|
||||
dev->close(dev->priv);
|
||||
|
||||
dev->priv = NULL;
|
||||
|
||||
cdrom_drive_reset(dev);
|
||||
@@ -296,15 +1065,8 @@ cdrom_eject(uint8_t id)
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev->prev_image_path) {
|
||||
free(dev->prev_image_path);
|
||||
dev->prev_image_path = NULL;
|
||||
}
|
||||
|
||||
if (dev->host_drive == 200) {
|
||||
dev->prev_image_path = (wchar_t *) malloc(1024 * sizeof(wchar_t));
|
||||
if (dev->host_drive == 200)
|
||||
wcscpy(dev->prev_image_path, dev->image_path);
|
||||
}
|
||||
|
||||
dev->prev_host_drive = dev->host_drive;
|
||||
dev->host_drive = 0;
|
||||
@@ -341,8 +1103,6 @@ cdrom_reload(uint8_t id)
|
||||
if (dev->prev_host_drive == 200) {
|
||||
/* Reload a previous image. */
|
||||
wcscpy(dev->image_path, dev->prev_image_path);
|
||||
free(dev->prev_image_path);
|
||||
dev->prev_image_path = NULL;
|
||||
cdrom_image_open(dev, dev->image_path);
|
||||
|
||||
cdrom_insert(id);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Generic CD-ROM drive core header.
|
||||
*
|
||||
* Version: @(#)cdrom.h 1.0.16 2018/10/26
|
||||
* Version: @(#)cdrom.h 1.0.17 2018/10/28
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
@@ -22,9 +22,24 @@
|
||||
|
||||
#define CD_STATUS_EMPTY 0
|
||||
#define CD_STATUS_DATA_ONLY 1
|
||||
#define CD_STATUS_PLAYING 2
|
||||
#define CD_STATUS_PAUSED 3
|
||||
#define CD_STATUS_PAUSED 2
|
||||
#define CD_STATUS_PLAYING 3
|
||||
#define CD_STATUS_STOPPED 4
|
||||
#define CD_STATUS_PLAYING_COMPLETED 5
|
||||
|
||||
/* Medium changed flag. */
|
||||
#define CD_STATUS_MEDIUM_CHANGED 0x80
|
||||
|
||||
#define CD_TRACK_AUDIO 0x08
|
||||
#define CD_TRACK_MODE2 0x04
|
||||
|
||||
#define CD_READ_DATA 0
|
||||
#define CD_READ_AUDIO 1
|
||||
#define CD_READ_RAW 2
|
||||
|
||||
#define CD_TOC_NORMAL 0
|
||||
#define CD_TOC_SESSION 1
|
||||
#define CD_TOC_RAW 2
|
||||
|
||||
#define BUF_SIZE 32768
|
||||
|
||||
@@ -51,61 +66,63 @@ enum {
|
||||
struct cdrom;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t attr, track,
|
||||
index,
|
||||
abs_m, abs_s, abs_f,
|
||||
rel_m, rel_s, rel_f;
|
||||
} subchannel_t;
|
||||
|
||||
typedef struct {
|
||||
int number;
|
||||
uint8_t attr, m, s, f;
|
||||
} track_info_t;
|
||||
|
||||
/* Define the various CD-ROM drive operations (ops). */
|
||||
typedef struct {
|
||||
int (*ready)(struct cdrom *dev);
|
||||
int (*medium_changed)(struct cdrom *dev);
|
||||
int (*media_type_id)(struct cdrom *dev);
|
||||
|
||||
int (*audio_callback)(struct cdrom *dev, int16_t *output, int len);
|
||||
void (*audio_stop)(struct cdrom *dev);
|
||||
int (*readtoc)(struct cdrom *dev, uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single);
|
||||
int (*readtoc_session)(struct cdrom *dev, uint8_t *b, int msf, int maxlen);
|
||||
int (*readtoc_raw)(struct cdrom *dev, uint8_t *b, int maxlen);
|
||||
uint8_t (*getcurrentsubchannel)(struct cdrom *dev, uint8_t *b, int msf);
|
||||
int (*readsector_raw)(struct cdrom *dev, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len);
|
||||
uint8_t (*playaudio)(struct cdrom *dev, uint32_t pos, uint32_t len, int ismsf);
|
||||
void (*pause)(struct cdrom *dev);
|
||||
void (*resume)(struct cdrom *dev);
|
||||
uint32_t (*size)(struct cdrom *dev);
|
||||
int (*status)(struct cdrom *dev);
|
||||
void (*stop)(struct cdrom *dev);
|
||||
void (*get_tracks)(struct cdrom *dev, int *first, int *last);
|
||||
void (*get_track_info)(struct cdrom *dev, uint32_t track, int end, track_info_t *ti);
|
||||
void (*get_subchannel)(struct cdrom *dev, uint32_t lba, subchannel_t *subc);
|
||||
int (*sector_size)(struct cdrom *dev, uint32_t lba);
|
||||
int (*read_sector)(struct cdrom *dev, int type, uint8_t *b, uint32_t lba);
|
||||
int (*track_type)(struct cdrom *dev, uint32_t lba);
|
||||
void (*exit)(struct cdrom *dev);
|
||||
} cdrom_ops_t;
|
||||
|
||||
typedef struct cdrom {
|
||||
uint8_t id,
|
||||
speed, cur_speed,
|
||||
res, res0, /* Reserved for other ID's. */
|
||||
res1,
|
||||
ide_channel, scsi_device_id,
|
||||
bus_type, /* 0 = ATAPI, 1 = SCSI */
|
||||
bus_mode, /* Bit 0 = PIO suported;
|
||||
Bit 1 = DMA supportd. */
|
||||
sound_on;
|
||||
cd_status, /* Struct variable reserved for
|
||||
media status. */
|
||||
speed, cur_speed;
|
||||
|
||||
FILE* img_fp;
|
||||
int img_is_iso,
|
||||
host_drive, prev_host_drive,
|
||||
cd_status, prev_status,
|
||||
cd_buflen, cd_state;
|
||||
void *priv;
|
||||
|
||||
uint32_t seek_pos, seek_diff,
|
||||
cd_end,
|
||||
cdrom_capacity;
|
||||
wchar_t image_path[1024],
|
||||
prev_image_path[1024];
|
||||
|
||||
uint32_t sound_on, cdrom_capacity,
|
||||
pad, seek_pos,
|
||||
seek_diff, cd_end;
|
||||
|
||||
int host_drive, prev_host_drive,
|
||||
cd_buflen;
|
||||
|
||||
const cdrom_ops_t *ops;
|
||||
|
||||
void *image;
|
||||
|
||||
void *priv;
|
||||
|
||||
void (*insert)(void *p);
|
||||
void (*close)(void *p);
|
||||
uint32_t (*get_volume)(void *p, int channel);
|
||||
uint32_t (*get_channel)(void *p, int channel);
|
||||
|
||||
wchar_t image_path[1024],
|
||||
*prev_image_path;
|
||||
|
||||
int16_t cd_buffer[BUF_SIZE];
|
||||
} cdrom_t;
|
||||
|
||||
@@ -114,8 +131,16 @@ extern cdrom_t cdrom[CDROM_NUM];
|
||||
|
||||
extern int cdrom_lba_to_msf_accurate(int lba);
|
||||
extern double cdrom_seek_time(cdrom_t *dev);
|
||||
extern void cdrom_stop(cdrom_t *dev);
|
||||
extern int cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len);
|
||||
extern uint8_t cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf);
|
||||
extern void cdrom_audio_pause_resume(cdrom_t *dev, uint8_t resume);
|
||||
extern uint8_t cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf);
|
||||
extern int cdrom_read_toc(cdrom_t *dev, unsigned char *b, int type,
|
||||
unsigned char start_track, int msf, int max_len);
|
||||
extern int cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf,
|
||||
int cdrom_sector_type, int cdrom_sector_flags, int *len);
|
||||
extern void cdrom_seek(cdrom_t *dev, uint32_t pos);
|
||||
extern int cdrom_playing_completed(cdrom_t *dev);
|
||||
|
||||
extern void cdrom_close_handler(uint8_t id);
|
||||
extern void cdrom_insert(uint8_t id);
|
||||
|
||||
@@ -135,6 +135,15 @@ bool CDROM_Interface_Image::GetAudioTrackInfo(int track, int& track_number, TMSF
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDROM_Interface_Image::GetAudioTrackEndInfo(int track, int& track_number, TMSF& start, unsigned char& attr)
|
||||
{
|
||||
if (track < 1 || track > (int)tracks.size()) return false;
|
||||
FRAMES_TO_MSF(tracks[track - 1].start + tracks[track - 1].length + 150, &start.min, &start.sec, &start.fr);
|
||||
track_number = tracks[track - 1].track_number;
|
||||
attr = tracks[track - 1].attr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDROM_Interface_Image::GetAudioSub(int sector, unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos)
|
||||
{
|
||||
int cur_track = GetTrack(sector);
|
||||
|
||||
@@ -83,6 +83,7 @@ public:
|
||||
|
||||
virtual bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut) = 0;
|
||||
virtual bool GetAudioTrackInfo (int track, int& number, TMSF& start, unsigned char& attr) = 0;
|
||||
virtual bool GetAudioTrackEndInfo (int track, int& number, TMSF& start, unsigned char& attr) = 0;
|
||||
virtual bool GetAudioSub (int sector, unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) = 0;
|
||||
virtual bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen) = 0;
|
||||
|
||||
@@ -136,6 +137,7 @@ public:
|
||||
bool GetUPC (unsigned char& attr, char* upc);
|
||||
bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut);
|
||||
bool GetAudioTrackInfo (int track, int& number, TMSF& start, unsigned char& attr);
|
||||
bool GetAudioTrackEndInfo (int track, int& number, TMSF& start, unsigned char& attr);
|
||||
bool GetAudioSub (int sector, unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos);
|
||||
bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen);
|
||||
bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num);
|
||||
|
||||
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: @(#)hdc_ide.c 1.0.55 2018/10/25
|
||||
* Version: @(#)hdc_ide.c 1.0.56 2018/10/28
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -109,7 +109,7 @@
|
||||
#define FEATURE_DISABLE_IRQ_OVERLAPPED 0xdd
|
||||
#define FEATURE_DISABLE_IRQ_SERVICE 0xde
|
||||
|
||||
#define IDE_PCI (PCI && pio_override && (ide->board < 2))
|
||||
#define IDE_PCI (PCI && !pio_override && (ide->board < 2))
|
||||
|
||||
|
||||
typedef struct {
|
||||
@@ -379,7 +379,7 @@ static int
|
||||
ide_get_max(ide_t *ide, int type)
|
||||
{
|
||||
if (ide_drive_is_atapi(ide))
|
||||
return ide->get_max(!IDE_PCI, type);
|
||||
return ide->get_max(IDE_PCI, type);
|
||||
|
||||
switch(type) {
|
||||
case TYPE_PIO: /* PIO */
|
||||
@@ -413,7 +413,7 @@ static int
|
||||
ide_get_timings(ide_t *ide, int type)
|
||||
{
|
||||
if (ide_drive_is_atapi(ide))
|
||||
return ide->get_timings(!IDE_PCI, type);
|
||||
return ide->get_timings(IDE_PCI, type);
|
||||
|
||||
switch(type) {
|
||||
case TIMINGS_DMA:
|
||||
@@ -551,6 +551,8 @@ ide_identify(ide_t *ide)
|
||||
max_sdma = ide_get_max(ide, TYPE_SDMA);
|
||||
max_mdma = ide_get_max(ide, TYPE_MDMA);
|
||||
max_udma = ide_get_max(ide, TYPE_UDMA);
|
||||
ide_log("IDE %i: max_pio = %i, max_sdma = %i, max_mdma = %i, max_udma = %i\n",
|
||||
ide->channel, max_pio, max_sdma, max_mdma, max_udma);
|
||||
|
||||
if (ide_boards[ide->board]->bit32)
|
||||
ide->buffer[48] |= 1; /*Dword transfers supported*/
|
||||
@@ -669,15 +671,14 @@ loadhd(ide_t *ide, int d, const wchar_t *fn)
|
||||
void
|
||||
ide_set_signature(ide_t *ide)
|
||||
{
|
||||
scsi_device_data_t *atapi = (scsi_device_data_t *) ide->p;
|
||||
|
||||
ide->sector=1;
|
||||
ide->head=0;
|
||||
|
||||
if (ide_drive_is_atapi(ide)) {
|
||||
ide->set_signature(ide->p);
|
||||
ide->secount = atapi->phase;
|
||||
ide->cylinder = atapi->request_length;
|
||||
ide->sc->phase = 1;
|
||||
ide->sc->request_length = 0xEB14;
|
||||
ide->secount = ide->sc->phase;
|
||||
ide->cylinder = ide->sc->request_length;
|
||||
} else {
|
||||
ide->secount = 1;
|
||||
ide->cylinder = ((ide->type == IDE_HDD) ? 0 : 0xFFFF);
|
||||
@@ -813,7 +814,6 @@ ide_board_close(int board)
|
||||
{
|
||||
ide_t *dev;
|
||||
int c, d;
|
||||
scsi_device_data_t *atapi;
|
||||
|
||||
/* Close hard disk image files (if previously open) */
|
||||
for (d = 0; d < 2; d++) {
|
||||
@@ -824,10 +824,8 @@ ide_board_close(int board)
|
||||
hdd_image_close(dev->hdd_num);
|
||||
|
||||
if (board < 4) {
|
||||
if (ide_drive_is_atapi(dev)) {
|
||||
atapi = (scsi_device_data_t *) dev->p;
|
||||
atapi->status = DRDY_STAT | DSC_STAT;
|
||||
}
|
||||
if (ide_drive_is_atapi(dev))
|
||||
dev->sc->status = DRDY_STAT | DSC_STAT;
|
||||
}
|
||||
|
||||
if (dev->buffer)
|
||||
@@ -943,6 +941,164 @@ ide_set_callback(uint8_t board, int64_t callback)
|
||||
}
|
||||
|
||||
|
||||
/* This is the general ATAPI PIO request function. */
|
||||
static void
|
||||
ide_atapi_pio_request(ide_t *ide, uint8_t out)
|
||||
{
|
||||
scsi_common_t *dev = ide->sc;
|
||||
|
||||
ide_irq_lower(ide_drives[ide->board]);
|
||||
|
||||
dev->status = BSY_STAT;
|
||||
|
||||
if (dev->pos >= dev->packet_len) {
|
||||
ide_log("%i bytes %s, command done\n", dev->pos, out ? "written" : "read");
|
||||
|
||||
dev->pos = dev->request_pos = 0;
|
||||
if (out && ide->phase_data_out)
|
||||
ide->phase_data_out(dev);
|
||||
else if (ide->command_stop)
|
||||
ide->command_stop(dev);
|
||||
} else {
|
||||
ide_log("%i bytes %s, %i bytes are still left\n", dev->pos,
|
||||
out ? "written" : "read", dev->packet_len - dev->pos);
|
||||
|
||||
/* If less than (packet length) bytes are remaining, update packet length
|
||||
accordingly. */
|
||||
if ((dev->packet_len - dev->pos) < (dev->max_transfer_len))
|
||||
dev->max_transfer_len = dev->packet_len - dev->pos;
|
||||
ide_log("CD-ROM %i: Packet length %i, request length %i\n", dev->id, dev->packet_len,
|
||||
dev->max_transfer_len);
|
||||
|
||||
dev->packet_status = out ? PHASE_DATA_OUT : PHASE_DATA_IN;
|
||||
|
||||
dev->status = BSY_STAT;
|
||||
dev->phase = 1;
|
||||
if (ide->packet_callback)
|
||||
ide->packet_callback(dev);
|
||||
dev->callback = 0LL;
|
||||
ide_set_callback(ide->board >> 1, dev->callback);
|
||||
|
||||
dev->request_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
ide_atapi_packet_read(ide_t *ide, int length)
|
||||
{
|
||||
scsi_common_t *dev = ide->sc;
|
||||
|
||||
uint16_t *bufferw;
|
||||
uint32_t *bufferl;
|
||||
|
||||
uint32_t temp = 0;
|
||||
|
||||
if (!dev || !dev->temp_buffer || (dev->packet_status != PHASE_DATA_IN))
|
||||
return 0;
|
||||
|
||||
bufferw = (uint16_t *) dev->temp_buffer;
|
||||
bufferl = (uint32_t *) dev->temp_buffer;
|
||||
|
||||
/* Make sure we return a 0 and don't attempt to read from the buffer if we're transferring bytes beyond it,
|
||||
which can happen when issuing media access commands with an allocated length below minimum request length
|
||||
(which is 1 sector = 2048 bytes). */
|
||||
switch(length) {
|
||||
case 1:
|
||||
temp = (dev->pos < dev->packet_len) ? dev->temp_buffer[dev->pos] : 0;
|
||||
dev->pos++;
|
||||
dev->request_pos++;
|
||||
break;
|
||||
case 2:
|
||||
temp = (dev->pos < dev->packet_len) ? bufferw[dev->pos >> 1] : 0;
|
||||
dev->pos += 2;
|
||||
dev->request_pos += 2;
|
||||
break;
|
||||
case 4:
|
||||
temp = (dev->pos < dev->packet_len) ? bufferl[dev->pos >> 2] : 0;
|
||||
dev->pos += 4;
|
||||
dev->request_pos += 4;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dev->packet_status == PHASE_DATA_IN) {
|
||||
if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) {
|
||||
/* Time for a DRQ. */
|
||||
ide_atapi_pio_request(ide, 0);
|
||||
}
|
||||
return temp;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ide_atapi_packet_write(ide_t *ide, uint32_t val, int length)
|
||||
{
|
||||
scsi_common_t *dev = ide->sc;
|
||||
|
||||
uint8_t *bufferb;
|
||||
uint16_t *bufferw;
|
||||
uint32_t *bufferl;
|
||||
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
if (dev->packet_status == PHASE_IDLE)
|
||||
bufferb = dev->atapi_cdb;
|
||||
else {
|
||||
if (dev->temp_buffer)
|
||||
bufferb = dev->temp_buffer;
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
bufferw = (uint16_t *) bufferb;
|
||||
bufferl = (uint32_t *) bufferb;
|
||||
|
||||
switch(length) {
|
||||
case 1:
|
||||
bufferb[dev->pos] = val & 0xff;
|
||||
dev->pos++;
|
||||
dev->request_pos++;
|
||||
break;
|
||||
case 2:
|
||||
bufferw[dev->pos >> 1] = val & 0xffff;
|
||||
dev->pos += 2;
|
||||
dev->request_pos += 2;
|
||||
break;
|
||||
case 4:
|
||||
bufferl[dev->pos >> 2] = val;
|
||||
dev->pos += 4;
|
||||
dev->request_pos += 4;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev->packet_status == PHASE_DATA_OUT) {
|
||||
if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) {
|
||||
/* Time for a DRQ. */
|
||||
ide_atapi_pio_request(ide, 1);
|
||||
}
|
||||
return;
|
||||
} else if (dev->packet_status == PHASE_IDLE) {
|
||||
if (dev->pos >= 12) {
|
||||
dev->pos = 0;
|
||||
dev->status = BSY_STAT;
|
||||
dev->packet_status = PHASE_COMMAND;
|
||||
timer_process();
|
||||
if (ide->packet_callback)
|
||||
ide->packet_callback(dev);
|
||||
timer_update_outstanding();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ide_write_data(ide_t *ide, uint32_t val, int length)
|
||||
{
|
||||
@@ -957,7 +1113,7 @@ ide_write_data(ide_t *ide, uint32_t val, int length)
|
||||
return;
|
||||
|
||||
if (ide_drive_is_atapi(ide))
|
||||
ide->packet_write(ide->p, val, length);
|
||||
ide_atapi_packet_write(ide, val, length);
|
||||
return;
|
||||
} else {
|
||||
switch(length) {
|
||||
@@ -1048,7 +1204,6 @@ void
|
||||
ide_write_devctl(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
ide_board_t *dev = (ide_board_t *) priv;
|
||||
scsi_device_data_t *atapi;
|
||||
|
||||
ide_t *ide, *ide_other;
|
||||
int ch;
|
||||
@@ -1060,11 +1215,9 @@ ide_write_devctl(uint16_t addr, uint8_t val, void *priv)
|
||||
ide_log("ide_write_devctl %04X %02X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc);
|
||||
|
||||
if ((ide->fdisk & 4) && !(val&4) && (ide->type != IDE_NONE || ide_other->type != IDE_NONE)) {
|
||||
atapi = (scsi_device_data_t *) ide->p;
|
||||
|
||||
timer_process();
|
||||
if (ide_drive_is_atapi(ide))
|
||||
atapi->callback = 0LL;
|
||||
ide->sc->callback = 0LL;
|
||||
ide_set_callback(ide->board, 500LL * IDE_TIME);
|
||||
timer_update_outstanding();
|
||||
|
||||
@@ -1073,7 +1226,7 @@ ide_write_devctl(uint16_t addr, uint8_t val, void *priv)
|
||||
if (ide_other->type != IDE_NONE)
|
||||
ide->reset = 1;
|
||||
if (ide_drive_is_atapi(ide))
|
||||
atapi->status = BSY_STAT;
|
||||
ide->sc->status = BSY_STAT;
|
||||
ide->atastat = ide_other->atastat = BSY_STAT;
|
||||
}
|
||||
|
||||
@@ -1093,7 +1246,6 @@ void
|
||||
ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
ide_board_t *dev = (ide_board_t *) priv;
|
||||
scsi_device_data_t *atapi, *atapi_other;
|
||||
|
||||
ide_t *ide, *ide_other;
|
||||
int ch;
|
||||
@@ -1109,9 +1261,6 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
||||
if ((ide->type == IDE_NONE) && ((addr == 0x0) || (addr == 0x7)))
|
||||
return;
|
||||
|
||||
atapi = (scsi_device_data_t *) ide->p;
|
||||
atapi_other = (scsi_device_data_t *) ide_other->p;
|
||||
|
||||
switch (addr) {
|
||||
case 0x0: /* Data */
|
||||
ide_write_data(ide, val | (val << 8), 2);
|
||||
@@ -1121,25 +1270,25 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
||||
case 0x1: /* Features */
|
||||
if (ide_drive_is_atapi(ide)) {
|
||||
ide_log("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO");
|
||||
atapi->features = val;
|
||||
ide->sc->features = val;
|
||||
}
|
||||
ide->cylprecomp = val;
|
||||
|
||||
if (ide_drive_is_atapi(ide_other))
|
||||
atapi_other->features = val;
|
||||
ide_other->sc->features = val;
|
||||
ide_other->cylprecomp = val;
|
||||
return;
|
||||
|
||||
case 0x2: /* Sector count */
|
||||
if (ide_drive_is_atapi(ide)) {
|
||||
ide_log("Sector count write: %i\n", val);
|
||||
atapi->phase = val;
|
||||
ide->sc->phase = val;
|
||||
}
|
||||
ide->secount = val;
|
||||
|
||||
if (ide_drive_is_atapi(ide_other)) {
|
||||
ide_log("Other sector count write: %i\n", val);
|
||||
atapi_other->phase = val;
|
||||
ide_other->sc->phase = val;
|
||||
}
|
||||
ide_other->secount = val;
|
||||
return;
|
||||
@@ -1153,15 +1302,15 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
||||
|
||||
case 0x4: /* Cylinder low */
|
||||
if (ide_drive_is_atapi(ide)) {
|
||||
atapi->request_length &= 0xFF00;
|
||||
atapi->request_length |= val;
|
||||
ide->sc->request_length &= 0xFF00;
|
||||
ide->sc->request_length |= val;
|
||||
}
|
||||
ide->cylinder = (ide->cylinder & 0xFF00) | val;
|
||||
ide->lba_addr = (ide->lba_addr & 0xFFF00FF) | (val << 8);
|
||||
|
||||
if (ide_drive_is_atapi(ide_other)) {
|
||||
atapi_other->request_length &= 0xFF00;
|
||||
atapi_other->request_length |= val;
|
||||
ide_other->sc->request_length &= 0xFF00;
|
||||
ide_other->sc->request_length |= val;
|
||||
}
|
||||
ide_other->cylinder = (ide_other->cylinder & 0xFF00) | val;
|
||||
ide_other->lba_addr = (ide_other->lba_addr & 0xFFF00FF) | (val << 8);
|
||||
@@ -1169,15 +1318,15 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
||||
|
||||
case 0x5: /* Cylinder high */
|
||||
if (ide_drive_is_atapi(ide)) {
|
||||
atapi->request_length &= 0xFF;
|
||||
atapi->request_length |= (val << 8);
|
||||
ide->sc->request_length &= 0xFF;
|
||||
ide->sc->request_length |= (val << 8);
|
||||
}
|
||||
ide->cylinder = (ide->cylinder & 0xFF) | (val << 8);
|
||||
ide->lba_addr = (ide->lba_addr & 0xF00FFFF) | (val << 16);
|
||||
|
||||
if (ide_drive_is_atapi(ide_other)) {
|
||||
atapi_other->request_length &= 0xFF;
|
||||
atapi_other->request_length |= (val << 8);
|
||||
ide_other->sc->request_length &= 0xFF;
|
||||
ide_other->sc->request_length |= (val << 8);
|
||||
}
|
||||
ide_other->cylinder = (ide_other->cylinder & 0xFF) | (val << 8);
|
||||
ide_other->lba_addr = (ide_other->lba_addr & 0xF00FFFF) | (val << 16);
|
||||
@@ -1198,20 +1347,20 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
||||
ide->reset = ide_other->reset = 0;
|
||||
|
||||
if (ide_drive_is_atapi(ide)) {
|
||||
atapi->status = DRDY_STAT | DSC_STAT;
|
||||
atapi->error = 1;
|
||||
atapi->phase = 1;
|
||||
atapi->request_length = 0xEB14;
|
||||
atapi->callback = 0LL;
|
||||
ide->sc->status = DRDY_STAT | DSC_STAT;
|
||||
ide->sc->error = 1;
|
||||
ide->sc->phase = 1;
|
||||
ide->sc->request_length = 0xEB14;
|
||||
ide->sc->callback = 0LL;
|
||||
ide->cylinder = 0xEB14;
|
||||
}
|
||||
|
||||
if (ide_drive_is_atapi(ide_other)) {
|
||||
atapi_other->status = DRDY_STAT | DSC_STAT;
|
||||
atapi_other->error = 1;
|
||||
atapi_other->phase = 1;
|
||||
atapi_other->request_length = 0xEB14;
|
||||
atapi_other->callback = 0LL;
|
||||
ide_other->sc->status = DRDY_STAT | DSC_STAT;
|
||||
ide_other->sc->error = 1;
|
||||
ide_other->sc->phase = 1;
|
||||
ide_other->sc->request_length = 0xEB14;
|
||||
ide_other->sc->callback = 0LL;
|
||||
ide->cylinder = 0xEB14;
|
||||
}
|
||||
|
||||
@@ -1241,17 +1390,17 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
||||
|
||||
ide->error=0;
|
||||
if (ide_drive_is_atapi(ide))
|
||||
atapi->error = 0;
|
||||
ide->sc->error = 0;
|
||||
|
||||
if (((val >= WIN_RECAL) && (val <= 0x1F)) || ((val >= WIN_SEEK) && (val <= 0x7F))) {
|
||||
if (ide_drive_is_atapi(ide))
|
||||
atapi->status = DRDY_STAT;
|
||||
ide->sc->status = DRDY_STAT;
|
||||
else
|
||||
ide->atastat = BSY_STAT;
|
||||
timer_process();
|
||||
|
||||
if (ide_drive_is_atapi(ide))
|
||||
atapi->callback = 100LL * IDE_TIME;
|
||||
ide->sc->callback = 100LL * IDE_TIME;
|
||||
ide_set_callback(ide->board, 100LL * IDE_TIME);
|
||||
timer_update_outstanding();
|
||||
return;
|
||||
@@ -1260,13 +1409,13 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
||||
switch (val) {
|
||||
case WIN_SRST: /* ATAPI Device Reset */
|
||||
if (ide_drive_is_atapi(ide))
|
||||
atapi->status = BSY_STAT;
|
||||
ide->sc->status = BSY_STAT;
|
||||
else
|
||||
ide->atastat = DRDY_STAT;
|
||||
timer_process();
|
||||
|
||||
if (ide_drive_is_atapi(ide))
|
||||
atapi->callback = 100LL * IDE_TIME;
|
||||
ide->sc->callback = 100LL * IDE_TIME;
|
||||
ide_set_callback(ide->board, 100LL * IDE_TIME);
|
||||
timer_update_outstanding();
|
||||
return;
|
||||
@@ -1287,13 +1436,13 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
||||
case WIN_READ_DMA:
|
||||
case WIN_READ_DMA_ALT:
|
||||
if (ide_drive_is_atapi(ide))
|
||||
atapi->status = BSY_STAT;
|
||||
ide->sc->status = BSY_STAT;
|
||||
else
|
||||
ide->atastat = BSY_STAT;
|
||||
timer_process();
|
||||
|
||||
if (ide_drive_is_atapi(ide))
|
||||
atapi->callback = 200LL * IDE_TIME;
|
||||
ide->sc->callback = 200LL * IDE_TIME;
|
||||
|
||||
if (ide->type == IDE_HDD) {
|
||||
if ((val == WIN_READ_DMA) || (val == WIN_READ_DMA_ALT)) {
|
||||
@@ -1320,8 +1469,8 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
||||
case WIN_WRITE:
|
||||
case WIN_WRITE_NORETRY:
|
||||
if (ide_drive_is_atapi(ide)) {
|
||||
atapi->status = DRQ_STAT | DSC_STAT | DRDY_STAT;
|
||||
atapi->pos = 0;
|
||||
ide->sc->status = DRQ_STAT | DSC_STAT | DRDY_STAT;
|
||||
ide->sc->pos = 0;
|
||||
} else {
|
||||
ide->atastat = DRQ_STAT | DSC_STAT | DRDY_STAT;
|
||||
ide->pos=0;
|
||||
@@ -1336,13 +1485,13 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
||||
case WIN_SET_FEATURES: /* Set Features */
|
||||
case WIN_READ_NATIVE_MAX:
|
||||
if (ide_drive_is_atapi(ide))
|
||||
atapi->status = BSY_STAT;
|
||||
ide->sc->status = BSY_STAT;
|
||||
else
|
||||
ide->atastat = BSY_STAT;
|
||||
timer_process();
|
||||
|
||||
if (ide_drive_is_atapi(ide))
|
||||
atapi->callback = 200LL * IDE_TIME;
|
||||
ide->sc->callback = 200LL * IDE_TIME;
|
||||
if ((ide->type == IDE_HDD) &&
|
||||
((val == WIN_WRITE_DMA) || (val == WIN_WRITE_DMA_ALT))) {
|
||||
if (ide->secount)
|
||||
@@ -1368,31 +1517,31 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
||||
|
||||
case WIN_SPECIFY: /* Initialize Drive Parameters */
|
||||
if (ide_drive_is_atapi(ide))
|
||||
atapi->status = BSY_STAT;
|
||||
ide->sc->status = BSY_STAT;
|
||||
else
|
||||
ide->atastat = BSY_STAT;
|
||||
timer_process();
|
||||
|
||||
if (ide_drive_is_atapi(ide))
|
||||
atapi->callback = 30LL * IDE_TIME;
|
||||
ide->sc->callback = 30LL * IDE_TIME;
|
||||
ide_set_callback(ide->board, 30LL * IDE_TIME);
|
||||
timer_update_outstanding();
|
||||
return;
|
||||
|
||||
case WIN_DRIVE_DIAGNOSTICS: /* Execute Drive Diagnostics */
|
||||
if (ide_drive_is_atapi(ide))
|
||||
atapi->status = BSY_STAT;
|
||||
ide->sc->status = BSY_STAT;
|
||||
else
|
||||
ide->atastat = BSY_STAT;
|
||||
|
||||
if (ide_drive_is_atapi(ide_other))
|
||||
atapi_other->status = BSY_STAT;
|
||||
ide_other->sc->status = BSY_STAT;
|
||||
else
|
||||
ide_other->atastat = BSY_STAT;
|
||||
|
||||
timer_process();
|
||||
if (ide_drive_is_atapi(ide))
|
||||
atapi->callback = 200LL * IDE_TIME;
|
||||
ide->sc->callback = 200LL * IDE_TIME;
|
||||
ide_set_callback(ide->board, 200LL * IDE_TIME);
|
||||
timer_update_outstanding();
|
||||
return;
|
||||
@@ -1406,7 +1555,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
||||
case WIN_CHECKPOWERMODE1:
|
||||
case WIN_SLEEP1:
|
||||
if (ide_drive_is_atapi(ide))
|
||||
atapi->status = BSY_STAT;
|
||||
ide->sc->status = BSY_STAT;
|
||||
else
|
||||
ide->atastat = BSY_STAT;
|
||||
timer_process();
|
||||
@@ -1417,10 +1566,10 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
||||
case WIN_PACKETCMD: /* ATAPI Packet */
|
||||
/* Skip the command callback wait, and process immediately. */
|
||||
if (ide_drive_is_atapi(ide)) {
|
||||
atapi->packet_status = PHASE_IDLE;
|
||||
atapi->pos = 0;
|
||||
atapi->phase = 1;
|
||||
atapi->status = DRDY_STAT | DRQ_STAT;
|
||||
ide->sc->packet_status = PHASE_IDLE;
|
||||
ide->sc->pos = 0;
|
||||
ide->sc->phase = 1;
|
||||
ide->sc->status = DRDY_STAT | DRQ_STAT;
|
||||
if (ide->interrupt_drq)
|
||||
ide_irq_raise(ide); /* Interrupt DRQ, requires IRQ on any DRQ. */
|
||||
} else {
|
||||
@@ -1436,8 +1585,8 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
||||
default:
|
||||
ide_bad_command:
|
||||
if (ide_drive_is_atapi(ide)) {
|
||||
atapi->status = DRDY_STAT | ERR_STAT | DSC_STAT;
|
||||
atapi->error = ABRT_ERR;
|
||||
ide->sc->status = DRDY_STAT | ERR_STAT | DSC_STAT;
|
||||
ide->sc->error = ABRT_ERR;
|
||||
} else {
|
||||
ide->atastat = DRDY_STAT | ERR_STAT | DSC_STAT;
|
||||
ide->error = ABRT_ERR;
|
||||
@@ -1453,7 +1602,6 @@ ide_bad_command:
|
||||
static uint32_t
|
||||
ide_read_data(ide_t *ide, int length)
|
||||
{
|
||||
scsi_device_data_t *atapi = (scsi_device_data_t *) ide->p;
|
||||
uint32_t temp = 0;
|
||||
|
||||
if (!ide->buffer) {
|
||||
@@ -1476,7 +1624,7 @@ ide_read_data(ide_t *ide, int length)
|
||||
if (ide->command == WIN_PACKETCMD) {
|
||||
ide->pos = 0;
|
||||
if (ide_drive_is_atapi(ide))
|
||||
temp = ide->packet_read(ide->p, length);
|
||||
temp = ide_atapi_packet_read(ide, length);
|
||||
else {
|
||||
ide_log("Drive not ATAPI (position: %i)\n", ide->pos);
|
||||
return 0;
|
||||
@@ -1503,8 +1651,8 @@ ide_read_data(ide_t *ide, int length)
|
||||
ide->pos = 0;
|
||||
ide->atastat = DRDY_STAT | DSC_STAT;
|
||||
if (ide_drive_is_atapi(ide)) {
|
||||
atapi->status = DRDY_STAT | DSC_STAT;
|
||||
atapi->packet_status = PHASE_IDLE;
|
||||
ide->sc->status = DRDY_STAT | DSC_STAT;
|
||||
ide->sc->packet_status = PHASE_IDLE;
|
||||
}
|
||||
if ((ide->command == WIN_READ) || (ide->command == WIN_READ_NORETRY) || (ide->command == WIN_READ_MULTIPLE)) {
|
||||
ide->secount = (ide->secount - 1) & 0xff;
|
||||
@@ -1517,12 +1665,10 @@ ide_read_data(ide_t *ide, int length)
|
||||
else
|
||||
ide_set_callback(ide->board, ide_get_period(ide, 512));
|
||||
timer_update_outstanding();
|
||||
} else {
|
||||
if (ide->command != WIN_READ_MULTIPLE)
|
||||
} else if (ide->command != WIN_READ_MULTIPLE)
|
||||
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
@@ -1531,13 +1677,11 @@ ide_read_data(ide_t *ide, int length)
|
||||
static uint8_t
|
||||
ide_status(ide_t *ide, int ch)
|
||||
{
|
||||
scsi_device_data_t *atapi = (scsi_device_data_t *) ide->p;
|
||||
|
||||
if (ide->type == IDE_NONE)
|
||||
return 0;
|
||||
else {
|
||||
if (ide_drive_is_atapi(ide))
|
||||
return (atapi->status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0);
|
||||
return (ide->sc->status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0);
|
||||
else
|
||||
return ide->atastat;
|
||||
}
|
||||
@@ -1547,7 +1691,6 @@ ide_status(ide_t *ide, int ch)
|
||||
uint8_t
|
||||
ide_readb(uint16_t addr, void *priv)
|
||||
{
|
||||
scsi_device_data_t *atapi;
|
||||
ide_board_t *dev = (ide_board_t *) priv;
|
||||
|
||||
int ch;
|
||||
@@ -1555,7 +1698,6 @@ ide_readb(uint16_t addr, void *priv)
|
||||
|
||||
ch = dev->cur_dev;
|
||||
ide = ide_drives[ch];
|
||||
atapi = (scsi_device_data_t *) ide->p;
|
||||
|
||||
uint8_t temp = 0xff;
|
||||
uint16_t tempw;
|
||||
@@ -1577,7 +1719,7 @@ ide_readb(uint16_t addr, void *priv)
|
||||
temp = 0;
|
||||
else {
|
||||
if (ide_drive_is_atapi(ide))
|
||||
temp = atapi->error;
|
||||
temp = ide->sc->error;
|
||||
else
|
||||
temp = ide->error;
|
||||
}
|
||||
@@ -1598,7 +1740,7 @@ ide_readb(uint16_t addr, void *priv)
|
||||
1 0 1 Status. */
|
||||
case 0x2: /* Sector count */
|
||||
if (ide_drive_is_atapi(ide))
|
||||
temp = atapi->phase;
|
||||
temp = ide->sc->phase;
|
||||
else
|
||||
temp = ide->secount;
|
||||
break;
|
||||
@@ -1612,7 +1754,7 @@ ide_readb(uint16_t addr, void *priv)
|
||||
temp = 0xFF;
|
||||
else {
|
||||
if (ide_drive_is_atapi(ide))
|
||||
temp = atapi->request_length & 0xff;
|
||||
temp = ide->sc->request_length & 0xff;
|
||||
else
|
||||
temp = ide->cylinder & 0xff;
|
||||
}
|
||||
@@ -1623,7 +1765,7 @@ ide_readb(uint16_t addr, void *priv)
|
||||
temp = 0xFF;
|
||||
else {
|
||||
if (ide_drive_is_atapi(ide))
|
||||
temp = atapi->request_length >> 8;
|
||||
temp = ide->sc->request_length >> 8;
|
||||
else
|
||||
temp = ide->cylinder >> 8;
|
||||
}
|
||||
@@ -1725,13 +1867,10 @@ ide_callback(void *priv)
|
||||
int snum, ret, ch;
|
||||
|
||||
ide_board_t *dev = (ide_board_t *) priv;
|
||||
scsi_device_data_t *atapi, *atapi_other;
|
||||
ch = dev->cur_dev;
|
||||
|
||||
ide = ide_drives[ch];
|
||||
atapi = (scsi_device_data_t *) ide->p;
|
||||
ide_other = ide_drives[ch ^ 1];
|
||||
atapi_other = (scsi_device_data_t *) ide_other->p;
|
||||
|
||||
ide_set_callback(ide->board, 0LL);
|
||||
|
||||
@@ -1752,18 +1891,18 @@ ide_callback(void *priv)
|
||||
|
||||
ide_set_signature(ide);
|
||||
if (ide_drive_is_atapi(ide)) {
|
||||
atapi->status = DRDY_STAT | DSC_STAT;
|
||||
atapi->error = 1;
|
||||
ide->sc->status = DRDY_STAT | DSC_STAT;
|
||||
ide->sc->error = 1;
|
||||
if (ide->stop)
|
||||
ide->stop(ide->p);
|
||||
ide->stop(ide->sc);
|
||||
}
|
||||
|
||||
ide_set_signature(ide_other);
|
||||
if (ide_drive_is_atapi(ide_other)) {
|
||||
atapi_other->status = DRDY_STAT | DSC_STAT;
|
||||
atapi_other->error = 1;
|
||||
ide_other->sc->status = DRDY_STAT | DSC_STAT;
|
||||
ide_other->sc->error = 1;
|
||||
if (ide_other->stop)
|
||||
ide_other->stop(ide_other->p);
|
||||
ide_other->stop(ide_other->sc);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -1798,10 +1937,10 @@ ide_callback(void *priv)
|
||||
ide_set_signature(ide);
|
||||
|
||||
if (ide_drive_is_atapi(ide)) {
|
||||
atapi->status = DRDY_STAT | DSC_STAT;
|
||||
atapi->error = 1;
|
||||
ide->sc->status = DRDY_STAT | DSC_STAT;
|
||||
ide->sc->error = 1;
|
||||
if (ide->device_reset)
|
||||
ide->device_reset(ide->p);
|
||||
ide->device_reset(ide->sc);
|
||||
}
|
||||
ide_irq_raise(ide);
|
||||
if (ide_drive_is_atapi(ide))
|
||||
@@ -1813,7 +1952,7 @@ ide_callback(void *priv)
|
||||
case WIN_IDLENOW1:
|
||||
case WIN_SETIDLE1:
|
||||
if (ide_drive_is_atapi(ide))
|
||||
atapi->status = DRDY_STAT | DSC_STAT;
|
||||
ide->sc->status = DRDY_STAT | DSC_STAT;
|
||||
else
|
||||
ide->atastat = DRDY_STAT | DSC_STAT;
|
||||
ide_irq_raise(ide);
|
||||
@@ -1822,8 +1961,8 @@ ide_callback(void *priv)
|
||||
case WIN_CHECKPOWERMODE1:
|
||||
case WIN_SLEEP1:
|
||||
if (ide_drive_is_atapi(ide)) {
|
||||
atapi->phase = 0xFF;
|
||||
atapi->status = DRDY_STAT | DSC_STAT;
|
||||
ide->sc->phase = 0xFF;
|
||||
ide->sc->status = DRDY_STAT | DSC_STAT;
|
||||
}
|
||||
ide->secount = 0xFF;
|
||||
ide->atastat = DRDY_STAT | DSC_STAT;
|
||||
@@ -1891,10 +2030,6 @@ ide_callback(void *priv)
|
||||
ide_set_callback(ide->board, 6LL * IDE_TIME);
|
||||
return;
|
||||
} else if (ret == 1) {
|
||||
/* Bus master DMAS error, abort the command. */
|
||||
ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel);
|
||||
goto abort_cmd;
|
||||
} else {
|
||||
/*DMA successful*/
|
||||
ide_log("IDE %i: DMA read successful\n", ide->channel);
|
||||
|
||||
@@ -1902,6 +2037,10 @@ ide_callback(void *priv)
|
||||
|
||||
ide_irq_raise(ide);
|
||||
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
|
||||
} else {
|
||||
/* Bus master DMAS error, abort the command. */
|
||||
ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel);
|
||||
goto abort_cmd;
|
||||
}
|
||||
} else {
|
||||
ide_log("IDE %i: DMA read aborted (no bus master)\n", ide->channel);
|
||||
@@ -1974,7 +2113,7 @@ ide_callback(void *priv)
|
||||
goto id_not_found;
|
||||
}
|
||||
|
||||
if (ide_bus_master_read) {
|
||||
if (ide_bus_master_write) {
|
||||
if (ide->secount)
|
||||
ide->sector_pos = ide->secount;
|
||||
else
|
||||
@@ -1990,10 +2129,6 @@ ide_callback(void *priv)
|
||||
ide_set_callback(ide->board, 6LL * IDE_TIME);
|
||||
return;
|
||||
} else if (ret == 1) {
|
||||
/* Bus master DMA error, abort the command. */
|
||||
ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel);
|
||||
goto abort_cmd;
|
||||
} else {
|
||||
/*DMA successful*/
|
||||
ide_log("IDE %i: DMA write successful\n", ide->channel);
|
||||
|
||||
@@ -2003,6 +2138,10 @@ ide_callback(void *priv)
|
||||
|
||||
ide_irq_raise(ide);
|
||||
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
|
||||
} else {
|
||||
/* Bus master DMA error, abort the command. */
|
||||
ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel);
|
||||
goto abort_cmd;
|
||||
}
|
||||
} else {
|
||||
ide_log("IDE %i: DMA write aborted (no bus master)\n", ide->channel);
|
||||
@@ -2063,8 +2202,8 @@ ide_callback(void *priv)
|
||||
ide->error = 1; /*No error detected*/
|
||||
|
||||
if (ide_drive_is_atapi(ide)) {
|
||||
atapi->status = 0;
|
||||
atapi->error = 1;
|
||||
ide->sc->status = 0;
|
||||
ide->sc->error = 1;
|
||||
ide_irq_raise(ide);
|
||||
} else {
|
||||
ide->atastat = DRDY_STAT | DSC_STAT;
|
||||
@@ -2076,8 +2215,8 @@ ide_callback(void *priv)
|
||||
ide_other->error = 1; /*No error detected*/
|
||||
|
||||
if (ide_drive_is_atapi(ide_other)) {
|
||||
atapi_other->status = 0;
|
||||
atapi_other->error = 1;
|
||||
ide_other->sc->status = 0;
|
||||
ide_other->sc->error = 1;
|
||||
} else {
|
||||
ide_other->atastat = DRDY_STAT | DSC_STAT;
|
||||
ide_other->error = 1;
|
||||
@@ -2105,10 +2244,10 @@ ide_callback(void *priv)
|
||||
if (ide_drive_is_atapi(ide)) {
|
||||
ide_identify(ide);
|
||||
ide->pos = 0;
|
||||
atapi->phase = 2;
|
||||
atapi->pos = 0;
|
||||
atapi->error = 0;
|
||||
atapi->status = DRQ_STAT | DRDY_STAT | DSC_STAT;
|
||||
ide->sc->phase = 2;
|
||||
ide->sc->pos = 0;
|
||||
ide->sc->error = 0;
|
||||
ide->sc->status = DRQ_STAT | DRDY_STAT | DSC_STAT;
|
||||
ide_irq_raise(ide);
|
||||
return;
|
||||
}
|
||||
@@ -2123,19 +2262,16 @@ ide_callback(void *priv)
|
||||
return;
|
||||
|
||||
case WIN_SET_FEATURES:
|
||||
if (ide->type == IDE_NONE)
|
||||
if ((ide->type == IDE_NONE) || !ide_set_features(ide))
|
||||
goto abort_cmd;
|
||||
|
||||
if (!ide_set_features(ide))
|
||||
goto abort_cmd;
|
||||
else {
|
||||
if (ide_drive_is_atapi(ide)) {
|
||||
atapi->status = DRDY_STAT | DSC_STAT;
|
||||
atapi->pos = 0;
|
||||
ide->sc->status = DRDY_STAT | DSC_STAT;
|
||||
ide->sc->pos = 0;
|
||||
}
|
||||
|
||||
ide->atastat = DRDY_STAT | DSC_STAT;
|
||||
ide_irq_raise(ide);
|
||||
}
|
||||
return;
|
||||
|
||||
case WIN_READ_NATIVE_MAX:
|
||||
@@ -2165,7 +2301,7 @@ ide_callback(void *priv)
|
||||
if (!ide_drive_is_atapi(ide) || !ide->packet_callback)
|
||||
goto abort_cmd;
|
||||
|
||||
ide->packet_callback(ide->p);
|
||||
ide->packet_callback(ide->sc);
|
||||
return;
|
||||
|
||||
case 0xFF:
|
||||
@@ -2175,9 +2311,9 @@ ide_callback(void *priv)
|
||||
abort_cmd:
|
||||
ide->command = 0;
|
||||
if (ide_drive_is_atapi(ide)) {
|
||||
atapi->status = DRDY_STAT | ERR_STAT | DSC_STAT;
|
||||
atapi->error = ABRT_ERR;
|
||||
atapi->pos = 0;
|
||||
ide->sc->status = DRDY_STAT | ERR_STAT | DSC_STAT;
|
||||
ide->sc->error = ABRT_ERR;
|
||||
ide->sc->pos = 0;
|
||||
} else {
|
||||
ide->atastat = DRDY_STAT | ERR_STAT | DSC_STAT;
|
||||
ide->error = ABRT_ERR;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* Implementation of the IDE emulation for hard disks and ATAPI
|
||||
* CD-ROM devices.
|
||||
*
|
||||
* Version: @(#)hdd_ide.h 1.0.12 2018/10/10
|
||||
* Version: @(#)hdd_ide.h 1.0.13 2018/10/28
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -27,7 +27,8 @@ enum
|
||||
IDE_ATAPI
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
#ifdef SCSI_DEVICE_H
|
||||
typedef struct ide_s {
|
||||
uint8_t atastat, error,
|
||||
command, fdisk;
|
||||
int type, board,
|
||||
@@ -49,19 +50,19 @@ typedef struct {
|
||||
uint8_t *sector_buffer;
|
||||
|
||||
/* Stuff mostly used by ATAPI */
|
||||
void *p;
|
||||
scsi_common_t *sc;
|
||||
int interrupt_drq;
|
||||
|
||||
int (*get_max)(int ide_has_dma, int type);
|
||||
int (*get_timings)(int ide_has_dma, int type);
|
||||
void (*identify)(void *p, int ide_has_dma);
|
||||
void (*set_signature)(void *p);
|
||||
void (*packet_write)(void *p, uint32_t val, int length);
|
||||
uint32_t (*packet_read)(void *p, int length);
|
||||
void (*stop)(void *p);
|
||||
void (*packet_callback)(void *p);
|
||||
void (*device_reset)(void *p);
|
||||
void (*identify)(struct ide_s *ide, int ide_has_dma);
|
||||
void (*stop)(scsi_common_t *sc);
|
||||
void (*packet_callback)(scsi_common_t *sc);
|
||||
void (*device_reset)(scsi_common_t *sc);
|
||||
uint8_t (*phase_data_out)(scsi_common_t *sc);
|
||||
void (*command_stop)(scsi_common_t *sc);
|
||||
} ide_t;
|
||||
#endif
|
||||
|
||||
/* Type:
|
||||
0 = PIO,
|
||||
@@ -95,12 +96,18 @@ enum {
|
||||
extern int ideboard;
|
||||
extern int ide_ter_enabled, ide_qua_enabled;
|
||||
|
||||
#ifdef SCSI_DEVICE_H
|
||||
extern ide_t *ide_drives[IDE_NUM];
|
||||
#endif
|
||||
extern int64_t idecallback[5];
|
||||
|
||||
|
||||
#ifdef SCSI_DEVICE_H
|
||||
extern void ide_irq_raise(ide_t *ide);
|
||||
extern void ide_irq_lower(ide_t *ide);
|
||||
extern void ide_allocate_buffer(ide_t *dev);
|
||||
extern void ide_atapi_attach(ide_t *dev);
|
||||
#endif
|
||||
|
||||
extern void * ide_xtide_init(void);
|
||||
extern void ide_xtide_close(void);
|
||||
@@ -140,8 +147,6 @@ extern void (*ide_bus_master_set_irq)(int channel, void *priv);
|
||||
extern void *ide_bus_master_priv[2];
|
||||
|
||||
extern void ide_enable_pio_override(void);
|
||||
extern void ide_allocate_buffer(ide_t *dev);
|
||||
extern void ide_atapi_attach(ide_t *dev);
|
||||
|
||||
|
||||
#endif /*EMU_IDE_H*/
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Definitions for the hard disk image handler.
|
||||
*
|
||||
* Version: @(#)hdd.h 1.0.7 2018/10/26
|
||||
* Version: @(#)hdd.h 1.0.8 2018/10/28
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -74,30 +74,28 @@ enum {
|
||||
|
||||
/* Define the virtual Hard Disk. */
|
||||
typedef struct {
|
||||
int8_t is_hdi; /* image type (should rename) */
|
||||
int8_t wp; /* disk has been mounted READ-ONLY */
|
||||
|
||||
uint8_t bus;
|
||||
|
||||
uint8_t mfm_channel; /* should rename and/or unionize */
|
||||
uint8_t id;
|
||||
uint8_t mfm_channel; /* Should rename and/or unionize */
|
||||
uint8_t esdi_channel;
|
||||
uint8_t xta_channel;
|
||||
uint8_t ide_channel;
|
||||
uint8_t scsi_id;
|
||||
uint8_t bus,
|
||||
res; /* Reserved for bus mode */
|
||||
uint8_t wp; /* Disk has been mounted READ-ONLY */
|
||||
uint8_t pad, pad0;
|
||||
|
||||
uint32_t base,
|
||||
spt,
|
||||
hpc, /* physical geometry parameters */
|
||||
tracks,
|
||||
at_spt, /* [Translation] parameters */
|
||||
at_hpc;
|
||||
|
||||
FILE *f; /* Current file handle to image */
|
||||
void *priv;
|
||||
|
||||
FILE *f; /* current file handle to image */
|
||||
wchar_t fn[1024], /* Name of current image file */
|
||||
prev_fn[1024]; /* Name of previous image file */
|
||||
|
||||
wchar_t fn[260]; /* name of current image file */
|
||||
wchar_t prev_fn[260]; /* name of previous image file */
|
||||
uint32_t res0, pad1,
|
||||
base,
|
||||
spt,
|
||||
hpc, /* Physical geometry parameters */
|
||||
tracks;
|
||||
} hard_disk_t;
|
||||
|
||||
|
||||
@@ -147,7 +145,6 @@ extern int hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count);
|
||||
extern uint32_t hdd_image_get_last_sector(uint8_t id);
|
||||
extern uint32_t hdd_image_get_pos(uint8_t id);
|
||||
extern uint8_t hdd_image_get_type(uint8_t id);
|
||||
extern void hdd_image_specify(uint8_t id, uint64_t hpc, uint64_t spt);
|
||||
extern void hdd_image_unload(uint8_t id, int fn_preserve);
|
||||
extern void hdd_image_close(uint8_t id);
|
||||
extern void hdd_image_calc_chs(uint32_t *c, uint32_t *h, uint32_t *s, uint32_t size);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Handling of hard disk image files.
|
||||
*
|
||||
* Version: @(#)hdd_image.c 1.0.19 2018/10/17
|
||||
* Version: @(#)hdd_image.c 1.0.20 2018/10/28
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -498,6 +498,25 @@ hdd_image_init(void)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
hdd_image_gen_vft(int id, vhd_footer_t **vft, uint64_t full_size)
|
||||
{
|
||||
/* Generate new footer. */
|
||||
new_vhd_footer(vft);
|
||||
(*vft)->orig_size = (*vft)->curr_size = full_size;
|
||||
(*vft)->geom.cyl = hdd[id].tracks;
|
||||
(*vft)->geom.heads = hdd[id].hpc;
|
||||
(*vft)->geom.spt = hdd[id].spt;
|
||||
generate_vhd_checksum(*vft);
|
||||
vhd_footer_to_bytes((uint8_t *) empty_sector, *vft);
|
||||
fseeko64(hdd_images[id].file, 0, SEEK_END);
|
||||
fwrite(empty_sector, 1, 512, hdd_images[id].file);
|
||||
free(*vft);
|
||||
*vft = NULL;
|
||||
hdd_images[id].type = 3;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hdd_image_load(int id)
|
||||
{
|
||||
@@ -601,23 +620,7 @@ hdd_image_load(int id)
|
||||
|
||||
if (is_vhd[0]) {
|
||||
/* VHD image. */
|
||||
/* Generate new footer. */
|
||||
empty_sector_1mb = (char *) malloc(512);
|
||||
new_vhd_footer(&vft);
|
||||
vft->orig_size = vft->curr_size = full_size;
|
||||
vft->geom.cyl = hdd[id].tracks;
|
||||
vft->geom.heads = hdd[id].hpc;
|
||||
vft->geom.spt = hdd[id].spt;
|
||||
generate_vhd_checksum(vft);
|
||||
memset(empty_sector_1mb, 0, 512);
|
||||
vhd_footer_to_bytes((uint8_t *) empty_sector_1mb, vft);
|
||||
fseeko64(hdd_images[id].file, 0, SEEK_END);
|
||||
fwrite(empty_sector_1mb, 1, 512, hdd_images[id].file);
|
||||
free(vft);
|
||||
vft = NULL;
|
||||
free(empty_sector_1mb);
|
||||
empty_sector_1mb = NULL;
|
||||
hdd_images[id].type = 3;
|
||||
hdd_image_gen_vft(id, &vft, full_size);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -671,23 +674,17 @@ hdd_image_load(int id)
|
||||
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 if (is_vhd[1]) {
|
||||
empty_sector_1mb = (char *) malloc(512);
|
||||
memset(empty_sector_1mb, 0, 512);
|
||||
fseeko64(hdd_images[id].file, -512, SEEK_END);
|
||||
fread(empty_sector_1mb, 1, 512, hdd_images[id].file);
|
||||
fread(empty_sector, 1, 512, hdd_images[id].file);
|
||||
new_vhd_footer(&vft);
|
||||
vhd_footer_from_bytes(vft, (uint8_t *) empty_sector_1mb);
|
||||
vhd_footer_from_bytes(vft, (uint8_t *) empty_sector);
|
||||
if (vft->type != 2) {
|
||||
/* VHD is not fixed size */
|
||||
hdd_image_log("VHD: Image is not fixed size\n");
|
||||
free(vft);
|
||||
vft = NULL;
|
||||
free(empty_sector_1mb);
|
||||
empty_sector_1mb = NULL;
|
||||
fclose(hdd_images[id].file);
|
||||
hdd_images[id].file = NULL;
|
||||
memset(hdd[id].fn, 0, sizeof(hdd[id].fn));
|
||||
@@ -699,8 +696,6 @@ hdd_image_load(int id)
|
||||
hdd[id].spt = vft->geom.spt;
|
||||
free(vft);
|
||||
vft = NULL;
|
||||
free(empty_sector_1mb);
|
||||
empty_sector_1mb = NULL;
|
||||
hdd_images[id].type = 3;
|
||||
/* If we're here, this means there is a valid VHD footer in the
|
||||
image, which means that by definition, all valid sectors
|
||||
@@ -731,22 +726,7 @@ hdd_image_load(int id)
|
||||
s = ftello64(hdd_images[id].file);
|
||||
if (s == (full_size + hdd_images[id].base)) {
|
||||
/* VHD image. */
|
||||
/* Generate new footer. */
|
||||
empty_sector_1mb = (char *) malloc(512);
|
||||
new_vhd_footer(&vft);
|
||||
vft->orig_size = vft->curr_size = full_size;
|
||||
vft->geom.cyl = hdd[id].tracks;
|
||||
vft->geom.heads = hdd[id].hpc;
|
||||
vft->geom.spt = hdd[id].spt;
|
||||
generate_vhd_checksum(vft);
|
||||
memset(empty_sector_1mb, 0, 512);
|
||||
vhd_footer_to_bytes((uint8_t *) empty_sector_1mb, vft);
|
||||
fwrite(empty_sector_1mb, 1, 512, hdd_images[id].file);
|
||||
free(vft);
|
||||
vft = NULL;
|
||||
free(empty_sector_1mb);
|
||||
empty_sector_1mb = NULL;
|
||||
hdd_images[id].type = 3;
|
||||
hdd_image_gen_vft(id, &vft, full_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -791,9 +771,7 @@ hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
||||
if ((sectors - sector) < transfer_sectors)
|
||||
transfer_sectors = sectors - sector;
|
||||
|
||||
hdd_images[id].pos = 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);
|
||||
hdd_image_read(id, sector, transfer_sectors, buffer);
|
||||
|
||||
if (count != transfer_sectors)
|
||||
return 1;
|
||||
@@ -819,9 +797,7 @@ hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer)
|
||||
if ((sectors - sector) < transfer_sectors)
|
||||
transfer_sectors = sectors - sector;
|
||||
|
||||
hdd_images[id].pos = 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);
|
||||
hdd_image_write(id, sector, transfer_sectors, buffer);
|
||||
|
||||
if (count != transfer_sectors)
|
||||
return 1;
|
||||
@@ -836,6 +812,7 @@ hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count)
|
||||
|
||||
hdd_images[id].pos = sector;
|
||||
fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET);
|
||||
memset(empty_sector, 0, 512);
|
||||
for (i = 0; i < count; i++)
|
||||
fwrite(empty_sector, 512, 1, hdd_images[id].file);
|
||||
}
|
||||
@@ -844,18 +821,13 @@ hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count)
|
||||
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;
|
||||
|
||||
hdd_images[id].pos = 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);
|
||||
hdd_image_zero(id, sector, transfer_sectors);
|
||||
|
||||
if (count != transfer_sectors)
|
||||
return 1;
|
||||
@@ -884,19 +856,6 @@ hdd_image_get_type(uint8_t id)
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
659
src/disk/zip.c
659
src/disk/zip.c
@@ -9,7 +9,7 @@
|
||||
* Implementation of the Iomega ZIP drive with SCSI(-like)
|
||||
* commands, for both ATAPI and SCSI usage.
|
||||
*
|
||||
* Version: @(#)zip.c 1.0.34 2018/10/27
|
||||
* Version: @(#)zip.c 1.0.34 2018/10/28
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
@@ -36,19 +36,6 @@
|
||||
#include "zip.h"
|
||||
|
||||
|
||||
/* Bits of 'status' */
|
||||
#define ERR_STAT 0x01
|
||||
#define DRQ_STAT 0x08 /* Data request */
|
||||
#define DSC_STAT 0x10
|
||||
#define SERVICE_STAT 0x10
|
||||
#define READY_STAT 0x40
|
||||
#define BUSY_STAT 0x80
|
||||
|
||||
/* Bits of 'error' */
|
||||
#define ABRT_ERR 0x04 /* Command aborted */
|
||||
#define MCR_ERR 0x08 /* Media change request */
|
||||
|
||||
|
||||
zip_drive_t zip_drives[ZIP_NUM];
|
||||
|
||||
|
||||
@@ -450,7 +437,7 @@ static const mode_sense_pages_t zip_250_mode_sense_pages_changeable =
|
||||
static void zip_command_complete(zip_t *dev);
|
||||
static void zip_init(zip_t *dev);
|
||||
|
||||
static void zip_callback(void *p);
|
||||
static void zip_callback(scsi_common_t *sc);
|
||||
|
||||
|
||||
#ifdef ENABLE_ZIP_LOG
|
||||
@@ -486,18 +473,35 @@ find_zip_for_channel(uint8_t channel)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
zip_load_abort(zip_t *dev)
|
||||
{
|
||||
if (dev->drv->f)
|
||||
fclose(dev->drv->f);
|
||||
dev->drv->f = NULL;
|
||||
dev->drv->medium_size = 0;
|
||||
zip_eject(dev->id); /* Make sure the host OS knows we've rejected (and ejected) the image. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
zip_load(zip_t *dev, wchar_t *fn)
|
||||
{
|
||||
int read_only = dev->drv->ui_writeprot;
|
||||
int size = 0;
|
||||
|
||||
dev->drv->f = plat_fopen(fn, dev->drv->ui_writeprot ? L"rb" : L"rb+");
|
||||
if (!dev->drv->ui_writeprot && !dev->drv->f) {
|
||||
dev->drv->f = plat_fopen(fn, dev->drv->read_only ? L"rb" : L"rb+");
|
||||
if (!dev->drv->f) {
|
||||
if (!dev->drv->read_only) {
|
||||
dev->drv->f = plat_fopen(fn, L"rb");
|
||||
read_only = 1;
|
||||
if (dev->drv->f)
|
||||
dev->drv->read_only = 1;
|
||||
else
|
||||
return zip_load_abort(dev);
|
||||
} else
|
||||
return zip_load_abort(dev);
|
||||
}
|
||||
if (dev->drv->f) {
|
||||
|
||||
fseek(dev->drv->f, 0, SEEK_END);
|
||||
size = ftell(dev->drv->f);
|
||||
|
||||
@@ -512,21 +516,13 @@ zip_load(zip_t *dev, wchar_t *fn)
|
||||
if ((size != (ZIP_250_SECTORS << 9)) && (size != (ZIP_SECTORS << 9))) {
|
||||
zip_log("File is incorrect size for a ZIP image\nMust be exactly %i or %i bytes\n",
|
||||
ZIP_250_SECTORS << 9, ZIP_SECTORS << 9);
|
||||
fclose(dev->drv->f);
|
||||
dev->drv->f = NULL;
|
||||
dev->drv->medium_size = 0;
|
||||
zip_eject(dev->id); /* Make sure the host OS knows we've rejected (and ejected) the image. */
|
||||
return 0;
|
||||
return zip_load_abort(dev);
|
||||
}
|
||||
} else {
|
||||
if (size != (ZIP_SECTORS << 9)) {
|
||||
zip_log("File is incorrect size for a ZIP image\nMust be exactly %i bytes\n",
|
||||
ZIP_SECTORS << 9);
|
||||
fclose(dev->drv->f);
|
||||
dev->drv->f = NULL;
|
||||
dev->drv->medium_size = 0;
|
||||
zip_eject(dev->id); /* Make sure the host OS knows we've rejected (and ejected) the image. */
|
||||
return 0;
|
||||
return zip_load_abort(dev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -536,14 +532,9 @@ zip_load(zip_t *dev, wchar_t *fn)
|
||||
|
||||
memcpy(dev->drv->image_path, fn, sizeof(dev->drv->image_path));
|
||||
|
||||
dev->drv->read_only = read_only;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
zip_disk_reload(zip_t *dev)
|
||||
@@ -592,18 +583,6 @@ zip_set_callback(zip_t *dev)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
zip_set_signature(void *p)
|
||||
{
|
||||
zip_t *dev = (zip_t *) p;
|
||||
|
||||
if (dev->id >= ZIP_NUM)
|
||||
return;
|
||||
dev->phase = 1;
|
||||
dev->request_length = 0xEB14;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
zip_init(zip_t *dev)
|
||||
{
|
||||
@@ -619,8 +598,10 @@ zip_init(zip_t *dev)
|
||||
if (dev->drv->bus_type < ZIP_BUS_SCSI)
|
||||
dev->drv->bus_mode |= 1;
|
||||
zip_log("ZIP %i: Bus type %i, bus mode %i\n", dev->id, dev->drv->bus_type, dev->drv->bus_mode);
|
||||
if (dev->drv->bus_type < ZIP_BUS_SCSI)
|
||||
zip_set_signature(dev);
|
||||
if (dev->drv->bus_type < ZIP_BUS_SCSI) {
|
||||
dev->phase = 1;
|
||||
dev->request_length = 0xEB14;
|
||||
}
|
||||
dev->status = READY_STAT | DSC_STAT;
|
||||
dev->pos = 0;
|
||||
dev->packet_status = 0xff;
|
||||
@@ -663,19 +644,6 @@ zip_current_mode(zip_t *dev)
|
||||
}
|
||||
|
||||
|
||||
/* Translates ATAPI status (ERR_STAT flag) to SCSI status. */
|
||||
static int
|
||||
zip_err_stat_to_scsi(void *p)
|
||||
{
|
||||
zip_t *dev = (zip_t *) p;
|
||||
|
||||
if (dev->status & ERR_STAT)
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
else
|
||||
return SCSI_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Translates ATAPI phase (DRQ, I/O, C/D) to SCSI phase (MSG, C/D, I/O). */
|
||||
int
|
||||
zip_atapi_phase_to_scsi(zip_t *dev)
|
||||
@@ -753,25 +721,6 @@ zip_mode_sense_save(zip_t *dev)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
zip_read_capacity(void *p, uint8_t *cdb, uint8_t *buffer, uint32_t *len)
|
||||
{
|
||||
zip_t *dev = (zip_t *) p;
|
||||
int size = 0;
|
||||
|
||||
size = dev->drv->medium_size - 1; /* IMPORTANT: What's returned is the last LBA block. */
|
||||
memset(buffer, 0, 8);
|
||||
buffer[0] = (size >> 24) & 0xff;
|
||||
buffer[1] = (size >> 16) & 0xff;
|
||||
buffer[2] = (size >> 8) & 0xff;
|
||||
buffer[3] = size & 0xff;
|
||||
buffer[6] = 2; /* 512 = 0x0200 */
|
||||
*len = 8;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*SCSI Mode Sense 6/10*/
|
||||
static uint8_t
|
||||
zip_mode_sense_read(zip_t *dev, uint8_t page_control, uint8_t page, uint8_t pos)
|
||||
@@ -927,7 +876,7 @@ zip_command_common(zip_t *dev)
|
||||
dev->phase = 1;
|
||||
dev->pos = 0;
|
||||
if (dev->packet_status == PHASE_COMPLETE) {
|
||||
zip_callback((void *) dev);
|
||||
zip_callback((scsi_common_t *) dev);
|
||||
dev->callback = 0LL;
|
||||
} else {
|
||||
if (dev->drv->bus_type == ZIP_BUS_SCSI) {
|
||||
@@ -1322,15 +1271,16 @@ zip_rezero(zip_t *dev)
|
||||
|
||||
|
||||
void
|
||||
zip_reset(void *p)
|
||||
zip_reset(scsi_common_t *sc)
|
||||
{
|
||||
zip_t *dev = (zip_t *) p;
|
||||
zip_t *dev = (zip_t *) sc;
|
||||
|
||||
zip_rezero(dev);
|
||||
dev->status = 0;
|
||||
dev->callback = 0LL;
|
||||
zip_set_callback(dev);
|
||||
zip_set_signature(dev);
|
||||
dev->phase = 1;
|
||||
dev->request_length = 0xEB14;
|
||||
dev->packet_status = 0xff;
|
||||
dev->unit_attention = 0;
|
||||
}
|
||||
@@ -1373,9 +1323,9 @@ zip_request_sense(zip_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc)
|
||||
|
||||
|
||||
static void
|
||||
zip_request_sense_for_scsi(void *p, uint8_t *buffer, uint8_t alloc_length)
|
||||
zip_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length)
|
||||
{
|
||||
zip_t *dev = (zip_t *) p;
|
||||
zip_t *dev = (zip_t *) sc;
|
||||
int ready = 0;
|
||||
|
||||
ready = (dev->drv->f != NULL);
|
||||
@@ -1412,6 +1362,7 @@ static void
|
||||
zip_buf_alloc(zip_t *dev, uint32_t len)
|
||||
{
|
||||
zip_log("ZIP %i: Allocated buffer length: %i\n", dev->id, len);
|
||||
if (!dev->buffer)
|
||||
dev->buffer = (uint8_t *) malloc(len);
|
||||
}
|
||||
|
||||
@@ -1428,9 +1379,9 @@ zip_buf_free(zip_t *dev)
|
||||
|
||||
|
||||
static void
|
||||
zip_command(void *p, uint8_t *cdb)
|
||||
zip_command(scsi_common_t *sc, uint8_t *cdb)
|
||||
{
|
||||
zip_t *dev = (zip_t *) p;
|
||||
zip_t *dev = (zip_t *) sc;
|
||||
int pos = 0, block_desc = 0;
|
||||
int ret;
|
||||
int32_t len, max_len;
|
||||
@@ -1555,10 +1506,9 @@ zip_command(void *p, uint8_t *cdb)
|
||||
|
||||
case GPCMD_MECHANISM_STATUS:
|
||||
zip_set_phase(dev, SCSI_PHASE_DATA_IN);
|
||||
len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
|
||||
len = (cdb[8] << 8) | cdb[9];
|
||||
|
||||
zip_buf_alloc(dev, 8);
|
||||
|
||||
zip_set_buf_len(dev, BufLen, &len);
|
||||
|
||||
memset(dev->buffer, 0, 8);
|
||||
@@ -1609,6 +1559,10 @@ zip_command(void *p, uint8_t *cdb)
|
||||
|
||||
ret = zip_blocks(dev, &alloc_length, 1, 0);
|
||||
if (ret <= 0) {
|
||||
zip_set_phase(dev, SCSI_PHASE_STATUS);
|
||||
dev->packet_status = PHASE_COMPLETE;
|
||||
dev->callback = 20LL * ZIP_TIME;
|
||||
zip_set_callback(dev);
|
||||
zip_buf_free(dev);
|
||||
return;
|
||||
}
|
||||
@@ -1705,7 +1659,6 @@ zip_command(void *p, uint8_t *cdb)
|
||||
return;
|
||||
|
||||
case GPCMD_WRITE_SAME_10:
|
||||
zip_set_phase(dev, SCSI_PHASE_DATA_OUT);
|
||||
alloc_length = 512;
|
||||
|
||||
if ((cdb[1] & 6) == 6) {
|
||||
@@ -1736,20 +1689,17 @@ zip_command(void *p, uint8_t *cdb)
|
||||
break;
|
||||
}
|
||||
|
||||
max_len = dev->sector_len;
|
||||
dev->requested_blocks = max_len; /* If we're writing all blocks in one go for DMA, why not also for PIO, it should NOT
|
||||
matter anyway, this step should be identical and only the way the read dat is
|
||||
transferred to the host should be different. */
|
||||
|
||||
dev->packet_len = max_len * alloc_length;
|
||||
zip_buf_alloc(dev, dev->packet_len);
|
||||
|
||||
dev->requested_blocks = max_len;
|
||||
dev->packet_len = alloc_length;
|
||||
|
||||
zip_buf_alloc(dev, alloc_length);
|
||||
zip_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len);
|
||||
|
||||
zip_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1);
|
||||
max_len = 1;
|
||||
dev->requested_blocks = 1;
|
||||
|
||||
dev->packet_len = alloc_length;
|
||||
|
||||
zip_set_phase(dev, SCSI_PHASE_DATA_OUT);
|
||||
|
||||
zip_data_command_finish(dev, 512, 512, alloc_length, 1);
|
||||
|
||||
if (dev->packet_status != PHASE_COMPLETE)
|
||||
ui_sb_update_icon(SB_ZIP | dev->id, 1);
|
||||
@@ -1986,10 +1936,14 @@ atapi_out:
|
||||
|
||||
zip_buf_alloc(dev, 8);
|
||||
|
||||
if (zip_read_capacity(dev, dev->current_cdb, dev->buffer, (uint32_t *) &len) == 0) {
|
||||
zip_buf_free(dev);
|
||||
return;
|
||||
}
|
||||
max_len = dev->drv->medium_size - 1; /* IMPORTANT: What's returned is the last LBA block. */
|
||||
memset(dev->buffer, 0, 8);
|
||||
dev->buffer[0] = (max_len >> 24) & 0xff;
|
||||
dev->buffer[1] = (max_len >> 16) & 0xff;
|
||||
dev->buffer[2] = (max_len >> 8) & 0xff;
|
||||
dev->buffer[3] = max_len & 0xff;
|
||||
dev->buffer[6] = 2; /* 512 = 0x0200 */
|
||||
len = 8;
|
||||
|
||||
zip_set_buf_len(dev, BufLen, &len);
|
||||
|
||||
@@ -2082,10 +2036,22 @@ atapi_out:
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
zip_command_stop(scsi_common_t *sc)
|
||||
{
|
||||
zip_t *dev = (zip_t *) sc;
|
||||
|
||||
zip_command_complete(dev);
|
||||
zip_buf_free(dev);
|
||||
}
|
||||
|
||||
|
||||
/* The command second phase function, needed for Mode Select. */
|
||||
static uint8_t
|
||||
zip_phase_data_out(zip_t *dev)
|
||||
zip_phase_data_out(scsi_common_t *sc)
|
||||
{
|
||||
zip_t *dev = (zip_t *) sc;
|
||||
|
||||
uint16_t block_desc_len;
|
||||
uint16_t pos;
|
||||
|
||||
@@ -2202,402 +2168,132 @@ zip_phase_data_out(zip_t *dev)
|
||||
}
|
||||
|
||||
if (error) {
|
||||
zip_buf_free(dev);
|
||||
zip_invalid_field_pl(dev);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* This is the general ATAPI PIO request function. */
|
||||
static void
|
||||
zip_pio_request(zip_t *dev, uint8_t out)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (dev->drv->bus_type < ZIP_BUS_SCSI) {
|
||||
zip_log("ZIP %i: Lowering IDE IRQ\n", dev->id);
|
||||
ide_irq_lower(ide_drives[dev->drv->ide_channel]);
|
||||
}
|
||||
|
||||
dev->status = BUSY_STAT;
|
||||
|
||||
if (dev->pos >= dev->packet_len) {
|
||||
zip_log("ZIP %i: %i bytes %s, command done\n", dev->id, dev->pos, out ? "written" : "read");
|
||||
|
||||
dev->pos = dev->request_pos = 0;
|
||||
if (out) {
|
||||
ret = zip_phase_data_out(dev);
|
||||
/* If ret = 0 (phase 1 error), then we do not do anything else other than
|
||||
free the buffer, as the phase and callback have already been set by the
|
||||
error function. */
|
||||
if (ret)
|
||||
zip_command_complete(dev);
|
||||
} else
|
||||
zip_command_complete(dev);
|
||||
zip_buf_free(dev);
|
||||
} else {
|
||||
zip_log("ZIP %i: %i bytes %s, %i bytes are still left\n", dev->id, dev->pos,
|
||||
out ? "written" : "read", dev->packet_len - dev->pos);
|
||||
|
||||
/* If less than (packet length) bytes are remaining, update packet length
|
||||
accordingly. */
|
||||
if ((dev->packet_len - dev->pos) < (dev->max_transfer_len))
|
||||
dev->max_transfer_len = dev->packet_len - dev->pos;
|
||||
zip_log("ZIP %i: Packet length %i, request length %i\n", dev->id, dev->packet_len,
|
||||
dev->max_transfer_len);
|
||||
|
||||
dev->packet_status = out ? PHASE_DATA_OUT : PHASE_DATA_IN;
|
||||
|
||||
dev->status = BUSY_STAT;
|
||||
dev->phase = 1;
|
||||
zip_callback((void *) dev);
|
||||
dev->callback = 0LL;
|
||||
zip_set_callback(dev);
|
||||
|
||||
dev->request_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
zip_read_from_ide_dma(zip_t *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!dev)
|
||||
return 0;
|
||||
|
||||
if (ide_bus_master_write) {
|
||||
ret = ide_bus_master_write(dev->drv->ide_channel >> 1,
|
||||
dev->buffer, dev->packet_len,
|
||||
ide_bus_master_priv[dev->drv->ide_channel >> 1]);
|
||||
if (ret == 2) /* DMA not enabled, wait for it to be enabled. */
|
||||
return 2;
|
||||
else if (ret == 1) { /* DMA error. */
|
||||
zip_bus_master_error(dev);
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
zip_read_from_scsi_dma(uint8_t scsi_id)
|
||||
{
|
||||
zip_t *dev = (zip_t *) scsi_devices[scsi_id].p;
|
||||
int32_t *BufLen = &scsi_devices[scsi_id].buffer_length;
|
||||
|
||||
if (!dev)
|
||||
return 0;
|
||||
|
||||
zip_log("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen);
|
||||
memcpy(dev->buffer, scsi_devices[scsi_id].cmd_buffer, *BufLen);
|
||||
zip_command_stop((scsi_common_t *) dev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
zip_irq_raise(zip_t *dev)
|
||||
zip_irq_raise(scsi_common_t *sc)
|
||||
{
|
||||
if (dev->drv->bus_type < ZIP_BUS_SCSI)
|
||||
zip_t *dev = (zip_t *) sc;
|
||||
|
||||
if (dev->drv && (dev->drv->bus_type < ZIP_BUS_SCSI))
|
||||
ide_irq_raise(ide_drives[dev->drv->ide_channel]);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
zip_read_from_dma(zip_t *dev)
|
||||
zip_dma(zip_t *dev, int out)
|
||||
{
|
||||
#ifdef ENABLE_ZIP_LOG
|
||||
int32_t *BufLen = &scsi_devices[dev->drv->scsi_device_id].buffer_length;
|
||||
#endif
|
||||
int ret = 0;
|
||||
int ret = 1;
|
||||
|
||||
if (dev->drv->bus_type == ZIP_BUS_SCSI)
|
||||
ret = zip_read_from_scsi_dma(dev->drv->scsi_device_id);
|
||||
else
|
||||
ret = zip_read_from_ide_dma(dev);
|
||||
if (dev->drv->bus_type == ZIP_BUS_ATAPI) {
|
||||
ret = 0;
|
||||
|
||||
if (ret != 1)
|
||||
return ret;
|
||||
|
||||
if (dev->drv->bus_type == ZIP_BUS_SCSI)
|
||||
zip_log("ZIP %i: SCSI Input data length: %i\n", dev->id, *BufLen);
|
||||
else
|
||||
zip_log("ZIP %i: ATAPI Input data length: %i\n", dev->id, dev->packet_len);
|
||||
|
||||
ret = zip_phase_data_out(dev);
|
||||
|
||||
if (ret)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
zip_write_to_ide_dma(zip_t *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!dev)
|
||||
return 0;
|
||||
|
||||
if (ide_bus_master_read) {
|
||||
if (out && dev && ide_bus_master_write) {
|
||||
ret = ide_bus_master_write(dev->drv->ide_channel >> 1,
|
||||
dev->buffer, dev->packet_len,
|
||||
ide_bus_master_priv[dev->drv->ide_channel >> 1]);
|
||||
} else if (!out && dev && ide_bus_master_read) {
|
||||
ret = ide_bus_master_read(dev->drv->ide_channel >> 1,
|
||||
dev->buffer, dev->packet_len,
|
||||
ide_bus_master_priv[dev->drv->ide_channel >> 1]);
|
||||
if (ret == 2) /* DMA not enabled, wait for it to be enabled. */
|
||||
return 2;
|
||||
else if (ret == 1) { /* DMA error. */
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
zip_buf_free(dev);
|
||||
zip_bus_master_error(dev);
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
zip_write_to_scsi_dma(uint8_t scsi_id)
|
||||
{
|
||||
zip_t *dev = (zip_t *) scsi_devices[scsi_id].p;
|
||||
int32_t *BufLen = &scsi_devices[scsi_id].buffer_length;
|
||||
|
||||
if (!dev)
|
||||
return 0;
|
||||
|
||||
zip_log("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen);
|
||||
memcpy(scsi_devices[scsi_id].cmd_buffer, dev->buffer, *BufLen);
|
||||
zip_log("ZIP %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id,
|
||||
dev->buffer[0], dev->buffer[1], dev->buffer[2], dev->buffer[3], dev->buffer[4], dev->buffer[5],
|
||||
dev->buffer[6], dev->buffer[7]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
zip_write_to_dma(zip_t *dev)
|
||||
{
|
||||
#ifdef ENABLE_ZIP_LOG
|
||||
int32_t *BufLen = &scsi_devices[dev->drv->scsi_device_id].buffer_length;
|
||||
#endif
|
||||
int ret = 0;
|
||||
|
||||
if (dev->drv->bus_type == ZIP_BUS_SCSI) {
|
||||
zip_log("Write to SCSI DMA: (ID %02X)\n", dev->drv->scsi_device_id);
|
||||
ret = zip_write_to_scsi_dma(dev->drv->scsi_device_id);
|
||||
} else
|
||||
ret = zip_write_to_ide_dma(dev);
|
||||
|
||||
if (dev->drv->bus_type == ZIP_BUS_SCSI)
|
||||
zip_log("ZIP %i: SCSI Output data length: %i\n", dev->id, *BufLen);
|
||||
} else if (ret == 1) {
|
||||
if (out)
|
||||
ret = zip_phase_data_out((scsi_common_t *) dev);
|
||||
else
|
||||
zip_log("ZIP %i: ATAPI Output data length: %i\n", dev->id, dev->packet_len);
|
||||
zip_command_stop((scsi_common_t *) dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
zip_callback(void *p)
|
||||
zip_callback(scsi_common_t *sc)
|
||||
{
|
||||
zip_t *dev = (zip_t *) p;
|
||||
zip_t *dev = (zip_t *) sc;
|
||||
int ret;
|
||||
|
||||
switch(dev->packet_status) {
|
||||
switch(sc->packet_status) {
|
||||
case PHASE_IDLE:
|
||||
zip_log("ZIP %i: PHASE_IDLE\n", dev->id);
|
||||
dev->pos = 0;
|
||||
dev->phase = 1;
|
||||
dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT);
|
||||
zip_log("ZIP %i: PHASE_IDLE\n", sc->id);
|
||||
sc->pos = 0;
|
||||
sc->phase = 1;
|
||||
sc->status = READY_STAT | DRQ_STAT | (sc->status & ERR_STAT);
|
||||
return;
|
||||
case PHASE_COMMAND:
|
||||
zip_log("ZIP %i: PHASE_COMMAND\n", dev->id);
|
||||
dev->status = BUSY_STAT | (dev->status & ERR_STAT);
|
||||
memcpy(dev->atapi_cdb, dev->buffer, 12);
|
||||
zip_command(dev, dev->atapi_cdb);
|
||||
zip_log("ZIP %i: PHASE_COMMAND\n", sc->id);
|
||||
sc->status = BUSY_STAT | (sc->status & ERR_STAT);
|
||||
zip_command(sc, sc->atapi_cdb);
|
||||
return;
|
||||
case PHASE_COMPLETE:
|
||||
zip_log("ZIP %i: PHASE_COMPLETE\n", dev->id);
|
||||
dev->status = READY_STAT;
|
||||
dev->phase = 3;
|
||||
dev->packet_status = 0xFF;
|
||||
ui_sb_update_icon(SB_ZIP | dev->id, 0);
|
||||
zip_irq_raise(dev);
|
||||
zip_log("ZIP %i: PHASE_COMPLETE\n", sc->id);
|
||||
sc->status = READY_STAT;
|
||||
sc->phase = 3;
|
||||
sc->packet_status = 0xFF;
|
||||
ui_sb_update_icon(SB_ZIP | sc->id, 0);
|
||||
zip_irq_raise(sc);
|
||||
return;
|
||||
case PHASE_DATA_OUT:
|
||||
zip_log("ZIP %i: PHASE_DATA_OUT\n", dev->id);
|
||||
dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT);
|
||||
dev->phase = 0;
|
||||
zip_irq_raise(dev);
|
||||
zip_log("ZIP %i: PHASE_DATA_OUT\n", sc->id);
|
||||
sc->status = READY_STAT | DRQ_STAT | (sc->status & ERR_STAT);
|
||||
sc->phase = 0;
|
||||
zip_irq_raise(sc);
|
||||
return;
|
||||
case PHASE_DATA_OUT_DMA:
|
||||
zip_log("ZIP %i: PHASE_DATA_OUT_DMA\n", dev->id);
|
||||
ret = zip_read_from_dma(dev);
|
||||
ret = zip_dma(dev, 1);
|
||||
|
||||
if ((ret == 1) || (dev->drv->bus_type == ZIP_BUS_SCSI)) {
|
||||
zip_log("ZIP %i: DMA data out phase done\n");
|
||||
zip_buf_free(dev);
|
||||
zip_command_complete(dev);
|
||||
} else if (ret == 2) {
|
||||
zip_log("ZIP %i: DMA out not enabled, wait\n");
|
||||
if (ret == 2) {
|
||||
zip_log("ZIP %i: DMA out not enabled, wait\n", sc->id);
|
||||
zip_command_bus(dev);
|
||||
#ifdef ENABLE_ZIP_LOG
|
||||
} else {
|
||||
zip_log("ZIP %i: DMA data out phase failure\n");
|
||||
zip_buf_free(dev);
|
||||
zip_log("ZIP %i: DMA data out phase %s\n", sc->id, ret ? "done" : "failure");
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
case PHASE_DATA_IN:
|
||||
zip_log("ZIP %i: PHASE_DATA_IN\n", dev->id);
|
||||
dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT);
|
||||
dev->phase = 2;
|
||||
zip_irq_raise(dev);
|
||||
zip_log("ZIP %i: PHASE_DATA_IN\n", sc->id);
|
||||
sc->status = READY_STAT | DRQ_STAT | (sc->status & ERR_STAT);
|
||||
sc->phase = 2;
|
||||
zip_irq_raise(sc);
|
||||
return;
|
||||
case PHASE_DATA_IN_DMA:
|
||||
zip_log("ZIP %i: PHASE_DATA_IN_DMA\n", dev->id);
|
||||
ret = zip_write_to_dma(dev);
|
||||
zip_log("ZIP %i: PHASE_DATA_IN_DMA\n", sc->id);
|
||||
ret = zip_dma(dev, 0);
|
||||
|
||||
if ((ret == 1) || (dev->drv->bus_type == ZIP_BUS_SCSI)) {
|
||||
zip_log("ZIP %i: DMA data in phase done\n", dev->id);
|
||||
zip_buf_free(dev);
|
||||
zip_command_complete(dev);
|
||||
} else if (ret == 2) {
|
||||
zip_log("ZIP %i: DMA in not enabled, wait\n", dev->id);
|
||||
if (ret == 2) {
|
||||
zip_log("ZIP %i: DMA in not enabled, wait\n", sc->id);
|
||||
zip_command_bus(dev);
|
||||
#ifdef ENABLE_ZIP_LOG
|
||||
} else {
|
||||
zip_log("ZIP %i: DMA data in phase failure\n", dev->id);
|
||||
zip_buf_free(dev);
|
||||
zip_log("ZIP %i: DMA data in phase %s\n", sc->id, ret ? "done" : "failure");
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
case PHASE_ERROR:
|
||||
zip_log("ZIP %i: PHASE_ERROR\n", dev->id);
|
||||
dev->status = READY_STAT | ERR_STAT;
|
||||
dev->phase = 3;
|
||||
dev->packet_status = 0xFF;
|
||||
zip_irq_raise(dev);
|
||||
ui_sb_update_icon(SB_ZIP | dev->id, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
zip_packet_read(void *p, int length)
|
||||
{
|
||||
zip_t *dev = (zip_t *) p;
|
||||
|
||||
uint16_t *zipbufferw;
|
||||
uint32_t *zipbufferl;
|
||||
|
||||
uint32_t temp = 0;
|
||||
|
||||
if (!dev)
|
||||
return 0;
|
||||
|
||||
zipbufferw = (uint16_t *) dev->buffer;
|
||||
zipbufferl = (uint32_t *) dev->buffer;
|
||||
|
||||
if (!dev->buffer)
|
||||
return 0;
|
||||
|
||||
/* Make sure we return a 0 and don't attempt to read from the buffer if we're transferring bytes beyond it,
|
||||
which can happen when issuing media access commands with an allocated length below minimum request length
|
||||
(which is 1 sector = 512 bytes). */
|
||||
switch(length) {
|
||||
case 1:
|
||||
temp = (dev->pos < dev->packet_len) ? dev->buffer[dev->pos] : 0;
|
||||
dev->pos++;
|
||||
dev->request_pos++;
|
||||
break;
|
||||
case 2:
|
||||
temp = (dev->pos < dev->packet_len) ? zipbufferw[dev->pos >> 1] : 0;
|
||||
dev->pos += 2;
|
||||
dev->request_pos += 2;
|
||||
break;
|
||||
case 4:
|
||||
temp = (dev->pos < dev->packet_len) ? zipbufferl[dev->pos >> 2] : 0;
|
||||
dev->pos += 4;
|
||||
dev->request_pos += 4;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dev->packet_status == PHASE_DATA_IN) {
|
||||
if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) {
|
||||
/* Time for a DRQ. */
|
||||
zip_pio_request(dev, 0);
|
||||
}
|
||||
return temp;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
zip_packet_write(void *p, uint32_t val, int length)
|
||||
{
|
||||
zip_t *dev = (zip_t *) p;
|
||||
|
||||
uint16_t *zipbufferw;
|
||||
uint32_t *zipbufferl;
|
||||
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
if (dev->packet_status == PHASE_IDLE) {
|
||||
if (!dev->buffer)
|
||||
zip_buf_alloc(dev, 12);
|
||||
}
|
||||
|
||||
zipbufferw = (uint16_t *) dev->buffer;
|
||||
zipbufferl = (uint32_t *) dev->buffer;
|
||||
|
||||
if (!dev->buffer)
|
||||
return;
|
||||
|
||||
switch(length) {
|
||||
case 1:
|
||||
dev->buffer[dev->pos] = val & 0xff;
|
||||
dev->pos++;
|
||||
dev->request_pos++;
|
||||
break;
|
||||
case 2:
|
||||
zipbufferw[dev->pos >> 1] = val & 0xffff;
|
||||
dev->pos += 2;
|
||||
dev->request_pos += 2;
|
||||
break;
|
||||
case 4:
|
||||
zipbufferl[dev->pos >> 2] = val;
|
||||
dev->pos += 4;
|
||||
dev->request_pos += 4;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev->packet_status == PHASE_DATA_OUT) {
|
||||
if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) {
|
||||
/* Time for a DRQ. */
|
||||
zip_pio_request(dev, 1);
|
||||
}
|
||||
return;
|
||||
} else if (dev->packet_status == PHASE_IDLE) {
|
||||
if (dev->pos >= 12) {
|
||||
dev->pos = 0;
|
||||
dev->status = BUSY_STAT;
|
||||
dev->packet_status = PHASE_COMMAND;
|
||||
timer_process();
|
||||
zip_callback((void *) dev);
|
||||
timer_update_outstanding();
|
||||
}
|
||||
zip_log("ZIP %i: PHASE_ERROR\n", sc->id);
|
||||
sc->status = READY_STAT | ERR_STAT;
|
||||
sc->phase = 3;
|
||||
sc->packet_status = 0xFF;
|
||||
zip_irq_raise(sc);
|
||||
ui_sb_update_icon(SB_ZIP | sc->id, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2612,27 +2308,6 @@ zip_global_init(void)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
zip_100_identify(ide_t *ide)
|
||||
{
|
||||
ide_padstr((char *) (ide->buffer + 23), "E.08", 8); /* Firmware */
|
||||
ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 100 ATAPI", 40); /* Model */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
zip_250_identify(ide_t *ide, int ide_has_dma)
|
||||
{
|
||||
ide_padstr((char *) (ide->buffer + 23), "42.S", 8); /* Firmware */
|
||||
ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 250 ATAPI", 40); /* Model */
|
||||
|
||||
if (ide_has_dma) {
|
||||
ide->buffer[80] = 0x30; /*Supported ATA versions : ATA/ATAPI-4 ATA/ATAPI-5*/
|
||||
ide->buffer[81] = 0x15; /*Maximum ATA revision supported : ATA/ATAPI-5 T13 1321D revision 1*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
zip_get_max(int ide_has_dma, int type)
|
||||
{
|
||||
@@ -2647,10 +2322,10 @@ zip_get_max(int ide_has_dma, int type)
|
||||
ret = -1;
|
||||
break;
|
||||
case TYPE_MDMA:
|
||||
ret = ide_has_dma ? -1 : 1;
|
||||
ret = ide_has_dma ? 1 : -1;
|
||||
break;
|
||||
case TYPE_UDMA:
|
||||
ret = ide_has_dma ? -1 : 2;
|
||||
ret = ide_has_dma ? 2 : -1;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2683,16 +2358,38 @@ zip_get_timings(int ide_has_dma, int type)
|
||||
|
||||
|
||||
static void
|
||||
zip_identify(void *p, int ide_has_dma)
|
||||
zip_100_identify(ide_t *ide)
|
||||
{
|
||||
ide_padstr((char *) (ide->buffer + 23), "E.08", 8); /* Firmware */
|
||||
ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 100 ATAPI", 40); /* Model */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
zip_250_identify(ide_t *ide, int ide_has_dma)
|
||||
{
|
||||
ide_padstr((char *) (ide->buffer + 23), "42.S", 8); /* Firmware */
|
||||
ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 250 ATAPI", 40); /* Model */
|
||||
|
||||
if (ide_has_dma) {
|
||||
ide->buffer[80] = 0x30; /*Supported ATA versions : ATA/ATAPI-4 ATA/ATAPI-5*/
|
||||
ide->buffer[81] = 0x15; /*Maximum ATA revision supported : ATA/ATAPI-5 T13 1321D revision 1*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
zip_identify(ide_t *ide, int ide_has_dma)
|
||||
{
|
||||
ide_t *ide = (ide_t *) p;
|
||||
zip_t *zip;
|
||||
|
||||
zip = (zip_t *) ide->p;
|
||||
zip = (zip_t *) ide->sc;
|
||||
|
||||
/* Using (2<<5) below makes the ASUS P/I-P54TP4XE misdentify the ZIP drive
|
||||
/* ATAPI device, direct-access device, removable media, interrupt DRQ:
|
||||
|
||||
Using (2 << 5) below makes the ASUS P/I-P54TP4XE misdentify the ZIP drive
|
||||
as a LS-120. */
|
||||
ide->buffer[0] = 0x8000 | (0<<8) | 0x80 | (1<<5); /* ATAPI device, direct-access device, removable media, interrupt DRQ */
|
||||
ide->buffer[0] = 0x8000 | (0 << 8) | 0x80 | (1 << 5);
|
||||
ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */
|
||||
ide->buffer[49] = 0x200; /* LBA supported */
|
||||
ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */
|
||||
@@ -2724,13 +2421,12 @@ zip_drive_reset(int c)
|
||||
/* SCSI ZIP, attach to the SCSI bus. */
|
||||
sd = &scsi_devices[zip_drives[c].scsi_device_id];
|
||||
|
||||
sd->p = dev;
|
||||
sd->sc = (scsi_common_t *) dev;
|
||||
sd->command = zip_command;
|
||||
sd->callback = zip_callback;
|
||||
sd->err_stat_to_scsi = zip_err_stat_to_scsi;
|
||||
sd->request_sense = zip_request_sense_for_scsi;
|
||||
sd->reset = zip_reset;
|
||||
sd->read_capacity = zip_read_capacity;
|
||||
sd->command_stop = zip_command_stop;
|
||||
sd->type = SCSI_REMOVABLE_DISK;
|
||||
} else if (zip_drives[c].bus_type == ZIP_BUS_ATAPI) {
|
||||
/* ATAPI CD-ROM, attach to the IDE bus. */
|
||||
@@ -2739,16 +2435,15 @@ zip_drive_reset(int c)
|
||||
otherwise, we do nothing - it's going to be a drive
|
||||
that's not attached to anything. */
|
||||
if (id) {
|
||||
id->p = dev;
|
||||
id->sc = (scsi_common_t *) dev;
|
||||
id->get_max = zip_get_max;
|
||||
id->get_timings = zip_get_timings;
|
||||
id->identify = zip_identify;
|
||||
id->set_signature = zip_set_signature;
|
||||
id->packet_write = zip_packet_write;
|
||||
id->packet_read = zip_packet_read;
|
||||
id->stop = NULL;
|
||||
id->packet_callback = zip_callback;
|
||||
id->device_reset = zip_reset;
|
||||
id->phase_data_out = zip_phase_data_out;
|
||||
id->command_stop = zip_command_stop;
|
||||
id->interrupt_drq = 1;
|
||||
|
||||
ide_atapi_attach(id);
|
||||
|
||||
@@ -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.7 2018/10/26
|
||||
* Version: @(#)zip.h 1.0.8 2018/10/28
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
@@ -39,22 +39,25 @@ enum {
|
||||
|
||||
|
||||
typedef struct {
|
||||
unsigned int bus_type; /* 0 = ATAPI, 1 = SCSI */
|
||||
uint8_t ide_channel,
|
||||
bus_mode; /* Bit 0 = PIO suported;
|
||||
uint8_t id,
|
||||
res, res0, /* Reserved for other ID's. */
|
||||
res1,
|
||||
ide_channel, scsi_device_id,
|
||||
bus_type, /* 0 = ATAPI, 1 = SCSI */
|
||||
bus_mode, /* Bit 0 = PIO suported;
|
||||
Bit 1 = DMA supportd. */
|
||||
read_only, /* Struct variable reserved for
|
||||
media status. */
|
||||
pad, pad0;
|
||||
|
||||
unsigned int scsi_device_id, is_250;
|
||||
FILE *f;
|
||||
void *priv;
|
||||
|
||||
wchar_t image_path[1024],
|
||||
prev_image_path[1024];
|
||||
|
||||
int read_only, ui_writeprot;
|
||||
|
||||
uint32_t medium_size, base;
|
||||
|
||||
FILE *f;
|
||||
void *priv;
|
||||
uint32_t is_250, medium_size,
|
||||
base;
|
||||
} zip_drive_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -76,16 +79,13 @@ typedef struct {
|
||||
|
||||
int requested_blocks, packet_status,
|
||||
total_length, do_page_save,
|
||||
unit_attention;
|
||||
unit_attention, request_pos,
|
||||
old_len, pad3;
|
||||
|
||||
uint32_t sector_pos, sector_len,
|
||||
packet_len, pos;
|
||||
|
||||
int64_t callback;
|
||||
|
||||
int request_pos, old_len;
|
||||
|
||||
uint32_t seek_pos;
|
||||
} zip_t;
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ extern void zip_insert(zip_t *dev);
|
||||
extern void zip_global_init(void);
|
||||
extern void zip_hard_reset(void);
|
||||
|
||||
extern void zip_reset(void *p);
|
||||
extern void zip_reset(scsi_common_t *sc);
|
||||
extern int zip_load(zip_t *dev, wchar_t *fn);
|
||||
extern void zip_close();
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* word 0 - base address
|
||||
* word 1 - bits 1-15 = byte count, bit 31 = end of transfer
|
||||
*
|
||||
* Version: @(#)intel_piix.c 1.0.20 2018/10/26
|
||||
* Version: @(#)intel_piix.c 1.0.21 2018/10/28
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -652,27 +652,28 @@ piix_bus_master_dma_op(int channel, uint8_t *data, int transfer_length, int out,
|
||||
if (force_end) {
|
||||
piix_log("Total transfer length smaller than sum of all blocks, partial block\n");
|
||||
dev->status &= ~2;
|
||||
return 0; /* This block has exhausted the data to transfer and it was smaller than the count, break. */
|
||||
return 1; /* This block has exhausted the data to transfer and it was smaller than the count, break. */
|
||||
} else {
|
||||
if (!transfer_length && !dev->eot) {
|
||||
piix_log("Total transfer length smaller than sum of all blocks, full block\n");
|
||||
dev->status &= ~2;
|
||||
return 0; /* We have exhausted the data to transfer but there's more blocks left, break. */
|
||||
return 1; /* We have exhausted the data to transfer but there's more blocks left, break. */
|
||||
} else if (transfer_length && dev->eot) {
|
||||
piix_log("Total transfer length greater than sum of all blocks\n");
|
||||
dev->status |= 2;
|
||||
return 1; /* There is data left to transfer but we have reached EOT - return with error. */
|
||||
return 0; /* There is data left to transfer but we have reached EOT - return with error. */
|
||||
} else if (dev->eot) {
|
||||
piix_log("Regular EOT\n");
|
||||
dev->status &= ~3;
|
||||
return 0; /* We have regularly reached EOT - clear status and break. */
|
||||
return 1; /* We have regularly reached EOT - clear status and break. */
|
||||
} else {
|
||||
/* We have more to transfer and there are blocks left, get next block. */
|
||||
piix_bus_master_next_addr(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -832,11 +833,11 @@ piix_reset(void *p)
|
||||
|
||||
for (i = 0; i < CDROM_NUM; i++) {
|
||||
if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && cdrom[i].priv)
|
||||
scsi_cdrom_reset(cdrom[i].priv);
|
||||
scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv);
|
||||
}
|
||||
for (i = 0; i < ZIP_NUM; i++) {
|
||||
if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && zip_drives[i].priv)
|
||||
zip_reset(zip_drives[i].priv);
|
||||
zip_reset((scsi_common_t *) zip_drives[i].priv);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
15
src/pc.c
15
src/pc.c
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Main emulator module where most things are controlled.
|
||||
*
|
||||
* Version: @(#)pc.c 1.0.87 2018/10/26
|
||||
* Version: @(#)pc.c 1.0.88 2018/10/28
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -651,10 +651,8 @@ again2:
|
||||
|
||||
keyboard_init();
|
||||
joystick_init();
|
||||
video_init();
|
||||
device_init();
|
||||
|
||||
timer_reset();
|
||||
video_init();
|
||||
|
||||
fdd_init();
|
||||
|
||||
@@ -662,9 +660,6 @@ again2:
|
||||
|
||||
hdc_init(hdc_name);
|
||||
|
||||
pc_full_speed();
|
||||
shadowbios = 0;
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
@@ -723,6 +718,8 @@ pc_reset_hard_close(void)
|
||||
|
||||
device_close_all();
|
||||
|
||||
scsi_device_close_all();
|
||||
|
||||
midi_close();
|
||||
|
||||
cdrom_close();
|
||||
@@ -834,6 +831,8 @@ pc_reset_hard_init(void)
|
||||
pic_reset();
|
||||
cpu_cache_int_enabled = cpu_cache_ext_enabled = 0;
|
||||
|
||||
pc_full_speed();
|
||||
|
||||
if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286)
|
||||
setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed);
|
||||
else
|
||||
@@ -908,6 +907,8 @@ pc_close(thread_t *ptr)
|
||||
|
||||
device_close_all();
|
||||
|
||||
scsi_device_close_all();
|
||||
|
||||
midi_close();
|
||||
|
||||
network_close();
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Handling of the SCSI controllers.
|
||||
*
|
||||
* Version: @(#)scsi.c 1.0.22 2018/10/10
|
||||
* Version: @(#)scsi.c 1.0.24 2018/10/30
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -37,7 +37,7 @@
|
||||
#include "scsi_aha154x.h"
|
||||
#include "scsi_buslogic.h"
|
||||
#include "scsi_ncr5380.h"
|
||||
#include "scsi_ncr53c810.h"
|
||||
#include "scsi_ncr53c8xx.h"
|
||||
#ifdef WALTJE
|
||||
# include "scsi_wd33c93.h"
|
||||
#endif
|
||||
@@ -72,6 +72,8 @@ static SCSI_CARD scsi_cards[] = {
|
||||
{ "[MCA] BusLogic BT-640A", "bt640a", &buslogic_640a_device, },
|
||||
{ "[PCI] BusLogic BT-958D", "bt958d", &buslogic_pci_device, },
|
||||
{ "[PCI] NCR 53C810", "ncr53c810", &ncr53c810_pci_device, },
|
||||
{ "[PCI] NCR 53C825A", "ncr53c825a", &ncr53c825a_pci_device, },
|
||||
{ "[PCI] NCR 53C875", "ncr53c875", &ncr53c875_pci_device, },
|
||||
{ "[VLB] BusLogic BT-445S", "bt445s", &buslogic_445s_device, },
|
||||
{ "", "", NULL, },
|
||||
};
|
||||
@@ -129,17 +131,16 @@ int scsi_card_get_from_internal_name(char *s)
|
||||
void scsi_card_init(void)
|
||||
{
|
||||
int i;
|
||||
scsi_device_t *dev;
|
||||
|
||||
if (!scsi_cards[scsi_card_current].device)
|
||||
return;
|
||||
|
||||
for (i = 0; i < SCSI_ID_MAX; i++) {
|
||||
if (scsi_devices[i].cmd_buffer)
|
||||
free(scsi_devices[i].cmd_buffer);
|
||||
scsi_devices[i].cmd_buffer = NULL;
|
||||
dev = &(scsi_devices[i]);
|
||||
|
||||
memset(&scsi_devices[i], 0, sizeof(scsi_device_t));
|
||||
scsi_devices[i].type = SCSI_NONE;
|
||||
memset(dev, 0, sizeof(scsi_device_t));
|
||||
dev->type = SCSI_NONE;
|
||||
}
|
||||
|
||||
device_add(scsi_cards[scsi_card_current].device);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 1 - BT-545S ISA;
|
||||
* 2 - BT-958D PCI
|
||||
*
|
||||
* Version: @(#)scsi_buslogic.c 1.0.42 2018/10/19
|
||||
* Version: @(#)scsi_buslogic.c 1.0.43 2018/10/28
|
||||
*
|
||||
* Authors: TheCollector1995, <mariogplayer@gmail.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -574,10 +574,10 @@ BuslogicSCSIBIOSDMATransfer(ESCMD *ESCSICmd, uint8_t TargetID, int dir)
|
||||
|
||||
if (dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_OUT) || (ESCSICmd->DataDirection == 0x00))) {
|
||||
buslogic_log("BusLogic BIOS DMA: Reading %i bytes from %08X\n", TransferLength, Address);
|
||||
DMAPageRead(Address, (uint8_t *)dev->cmd_buffer, TransferLength);
|
||||
DMAPageRead(Address, (uint8_t *)dev->sc->temp_buffer, TransferLength);
|
||||
} else if (!dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_IN) || (ESCSICmd->DataDirection == 0x00))) {
|
||||
buslogic_log("BusLogic BIOS DMA: Writing %i bytes at %08X\n", TransferLength, Address);
|
||||
DMAPageWrite(Address, (uint8_t *)dev->cmd_buffer, TransferLength);
|
||||
DMAPageWrite(Address, (uint8_t *)dev->sc->temp_buffer, TransferLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -624,8 +624,6 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u
|
||||
}
|
||||
}
|
||||
|
||||
x54x_buf_alloc(ESCSICmd->TargetId, ESCSICmd->DataLength);
|
||||
|
||||
target_cdb_len = 12;
|
||||
|
||||
if (!scsi_device_valid(sd)) fatal("SCSI target on ID %02i has disappeared\n", ESCSICmd->TargetId);
|
||||
@@ -645,19 +643,15 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u
|
||||
}
|
||||
|
||||
sd->buffer_length = ESCSICmd->DataLength;
|
||||
|
||||
scsi_device_command_phase0(sd, temp_cdb);
|
||||
|
||||
phase = sd->phase;
|
||||
if (phase != SCSI_PHASE_STATUS) {
|
||||
if (phase == SCSI_PHASE_DATA_IN)
|
||||
scsi_device_command_phase1(sd);
|
||||
BuslogicSCSIBIOSDMATransfer(ESCSICmd, ESCSICmd->TargetId, (phase == SCSI_PHASE_DATA_OUT));
|
||||
if (phase == SCSI_PHASE_DATA_OUT)
|
||||
scsi_device_command_phase1(sd);
|
||||
}
|
||||
|
||||
x54x_buf_free(ESCSICmd->TargetId);
|
||||
|
||||
buslogic_log("BIOS Request complete\n");
|
||||
|
||||
if (sd->status == SCSI_STATUS_OK) {
|
||||
@@ -1155,7 +1149,8 @@ BuslogicPCIRead(int func, int addr, void *p)
|
||||
case 0x13:
|
||||
return buslogic_pci_bar[0].addr_regs[3];
|
||||
case 0x14:
|
||||
return (buslogic_pci_bar[1].addr_regs[0] & 0xe0); /*Memory space*/
|
||||
// return (buslogic_pci_bar[1].addr_regs[0] & 0xe0); /*Memory space*/
|
||||
return 0x00;
|
||||
case 0x15:
|
||||
return buslogic_pci_bar[1].addr_regs[1];
|
||||
case 0x16:
|
||||
@@ -1255,7 +1250,10 @@ BuslogicPCIWrite(int func, int addr, uint8_t val, void *p)
|
||||
/* Then let's set the PCI regs. */
|
||||
buslogic_pci_bar[1].addr_regs[addr & 3] = val;
|
||||
/* Then let's calculate the new I/O base. */
|
||||
bl->MMIOBase = buslogic_pci_bar[1].addr & 0xffffffe0;
|
||||
// bl->MMIOBase = buslogic_pci_bar[1].addr & 0xffffffe0;
|
||||
/* Give it a 4 kB alignment as that's this emulator's granularity. */
|
||||
buslogic_pci_bar[1].addr &= 0xffffc000;
|
||||
bl->MMIOBase = buslogic_pci_bar[1].addr & 0xffffc000;
|
||||
/* Log the new base. */
|
||||
buslogic_log("BusLogic PCI: New MMIO base is %04X\n" , bl->MMIOBase);
|
||||
/* We're done, so get out of the here. */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -43,19 +43,13 @@ typedef struct {
|
||||
|
||||
int requested_blocks, packet_status,
|
||||
total_length, do_page_save,
|
||||
unit_attention;
|
||||
unit_attention, request_pos,
|
||||
old_len, media_status;
|
||||
|
||||
uint32_t sector_pos, sector_len,
|
||||
packet_len, pos;
|
||||
|
||||
int64_t callback;
|
||||
|
||||
int media_status, data_pos,
|
||||
request_pos, total_read,
|
||||
old_len;
|
||||
|
||||
uint8_t previous_command,
|
||||
pad3, pad4, pad5;
|
||||
} scsi_cdrom_t;
|
||||
#endif
|
||||
|
||||
@@ -69,7 +63,7 @@ extern scsi_cdrom_t *scsi_cdrom[CDROM_NUM];
|
||||
#define scsi_cdrom_drive cdrom_drives[id].host_drive
|
||||
|
||||
|
||||
extern void scsi_cdrom_reset(void *p);
|
||||
extern void scsi_cdrom_reset(scsi_common_t *sc);
|
||||
|
||||
|
||||
#endif /*EMU_SCSI_CDROM_H*/
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* The generic SCSI device command handler.
|
||||
*
|
||||
* Version: @(#)scsi_device.c 1.0.21 2018/10/13
|
||||
* Version: @(#)scsi_device.c 1.0.22 2018/10/28
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -35,71 +35,81 @@ uint8_t scsi_null_device_sense[18] = { 0x70,0,SENSE_ILLEGAL_REQUEST,0,0,0,0,0,0,
|
||||
static uint8_t
|
||||
scsi_device_target_command(scsi_device_t *dev, uint8_t *cdb)
|
||||
{
|
||||
if (dev->command && dev->err_stat_to_scsi) {
|
||||
dev->command(dev->p, cdb);
|
||||
return dev->err_stat_to_scsi(dev->p);
|
||||
if (dev->command) {
|
||||
dev->command(dev->sc, cdb);
|
||||
|
||||
if (dev->sc->status & ERR_STAT)
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
else
|
||||
return SCSI_STATUS_OK;
|
||||
} else
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
}
|
||||
|
||||
|
||||
static void scsi_device_target_callback(scsi_device_t *dev)
|
||||
static void
|
||||
scsi_device_target_callback(scsi_device_t *dev)
|
||||
{
|
||||
if (dev->callback)
|
||||
dev->callback(dev->p);
|
||||
dev->callback(dev->sc);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static int scsi_device_target_err_stat_to_scsi(scsi_device_t *dev)
|
||||
static int
|
||||
scsi_device_target_err_stat_to_scsi(scsi_device_t *dev)
|
||||
{
|
||||
if (dev->err_stat_to_scsi)
|
||||
return dev->err_stat_to_scsi(dev->p);
|
||||
if (dev->sc)
|
||||
if (dev->sc->status & ERR_STAT)
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
else
|
||||
return SCSI_STATUS_OK;
|
||||
else
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
}
|
||||
|
||||
|
||||
int64_t scsi_device_get_callback(scsi_device_t *dev)
|
||||
int64_t
|
||||
scsi_device_get_callback(scsi_device_t *dev)
|
||||
{
|
||||
scsi_device_data_t *sdd = (scsi_device_data_t *) dev->p;
|
||||
|
||||
if (sdd)
|
||||
return sdd->callback;
|
||||
if (dev->sc)
|
||||
return dev->sc->callback;
|
||||
else
|
||||
return -1LL;
|
||||
}
|
||||
|
||||
|
||||
uint8_t *scsi_device_sense(scsi_device_t *dev)
|
||||
uint8_t *
|
||||
scsi_device_sense(scsi_device_t *dev)
|
||||
{
|
||||
scsi_device_data_t *sdd = (scsi_device_data_t *) dev->p;
|
||||
|
||||
if (sdd)
|
||||
return sdd->sense;
|
||||
if (dev->sc)
|
||||
return dev->sc->sense;
|
||||
else
|
||||
return scsi_null_device_sense;
|
||||
}
|
||||
|
||||
|
||||
void scsi_device_request_sense(scsi_device_t *dev, uint8_t *buffer, uint8_t alloc_length)
|
||||
void
|
||||
scsi_device_request_sense(scsi_device_t *dev, uint8_t *buffer, uint8_t alloc_length)
|
||||
{
|
||||
if (dev->request_sense)
|
||||
dev->request_sense(dev->p, buffer, alloc_length);
|
||||
dev->request_sense(dev->sc, buffer, alloc_length);
|
||||
else
|
||||
memcpy(buffer, scsi_null_device_sense, alloc_length);
|
||||
}
|
||||
|
||||
|
||||
void scsi_device_reset(scsi_device_t *dev)
|
||||
void
|
||||
scsi_device_reset(scsi_device_t *dev)
|
||||
{
|
||||
if (dev->reset)
|
||||
dev->reset(dev->p);
|
||||
dev->reset(dev->sc);
|
||||
}
|
||||
|
||||
|
||||
int scsi_device_present(scsi_device_t *dev)
|
||||
int
|
||||
scsi_device_present(scsi_device_t *dev)
|
||||
{
|
||||
if (dev->type == SCSI_NONE)
|
||||
return 0;
|
||||
@@ -108,25 +118,28 @@ int scsi_device_present(scsi_device_t *dev)
|
||||
}
|
||||
|
||||
|
||||
int scsi_device_valid(scsi_device_t *dev)
|
||||
int
|
||||
scsi_device_valid(scsi_device_t *dev)
|
||||
{
|
||||
if (dev->p)
|
||||
if (dev->sc)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int scsi_device_cdb_length(scsi_device_t *dev)
|
||||
int
|
||||
scsi_device_cdb_length(scsi_device_t *dev)
|
||||
{
|
||||
/* Right now, it's 12 for all devices. */
|
||||
return 12;
|
||||
}
|
||||
|
||||
|
||||
void scsi_device_command_phase0(scsi_device_t *dev, uint8_t *cdb)
|
||||
void
|
||||
scsi_device_command_phase0(scsi_device_t *dev, uint8_t *cdb)
|
||||
{
|
||||
if (!dev->p) {
|
||||
if (!dev->sc) {
|
||||
dev->phase = SCSI_PHASE_STATUS;
|
||||
dev->status = SCSI_STATUS_CHECK_CONDITION;
|
||||
return;
|
||||
@@ -143,9 +156,11 @@ void scsi_device_command_phase0(scsi_device_t *dev, uint8_t *cdb)
|
||||
/* If the phase is DATA IN or DATA OUT, finish this here. */
|
||||
}
|
||||
|
||||
void scsi_device_command_phase1(scsi_device_t *dev)
|
||||
|
||||
void
|
||||
scsi_device_command_phase1(scsi_device_t *dev)
|
||||
{
|
||||
if (!dev->p)
|
||||
if (!dev->sc)
|
||||
return;
|
||||
|
||||
/* Call the second phase. */
|
||||
@@ -155,7 +170,25 @@ void scsi_device_command_phase1(scsi_device_t *dev)
|
||||
scsi_device_target_callback(dev);
|
||||
}
|
||||
|
||||
int32_t *scsi_device_get_buf_len(scsi_device_t *dev)
|
||||
|
||||
void
|
||||
scsi_device_command_stop(scsi_device_t *dev)
|
||||
{
|
||||
return &dev->buffer_length;
|
||||
if (!dev->command_stop)
|
||||
dev->command_stop(dev->sc);
|
||||
scsi_device_target_callback(dev);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
scsi_device_close_all(void)
|
||||
{
|
||||
int i;
|
||||
scsi_device_t *dev;
|
||||
|
||||
for (i = 0; i < SCSI_ID_MAX; i++) {
|
||||
dev = &(scsi_devices[i]);
|
||||
if (dev->command_stop && dev->sc)
|
||||
dev->command_stop(dev->sc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Definitions for the generic SCSI device command handler.
|
||||
*
|
||||
* Version: @(#)scsi_device.h 1.0.12 2018/10/11
|
||||
* Version: @(#)scsi_device.h 1.0.14 2018/10/28
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -28,6 +28,18 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* Bits of 'status' */
|
||||
#define ERR_STAT 0x01
|
||||
#define DRQ_STAT 0x08 /* Data request */
|
||||
#define DSC_STAT 0x10
|
||||
#define SERVICE_STAT 0x10
|
||||
#define READY_STAT 0x40
|
||||
#define BUSY_STAT 0x80
|
||||
|
||||
/* Bits of 'error' */
|
||||
#define ABRT_ERR 0x04 /* Command aborted */
|
||||
#define MCR_ERR 0x08 /* Media change request */
|
||||
|
||||
/* SCSI commands. */
|
||||
#define GPCMD_TEST_UNIT_READY 0x00
|
||||
#define GPCMD_REZERO_UNIT 0x01
|
||||
@@ -291,59 +303,55 @@ typedef struct
|
||||
} scsi_bus_t;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint8_t *cmd_buffer;
|
||||
|
||||
int32_t buffer_length;
|
||||
|
||||
uint8_t status, phase;
|
||||
uint16_t type;
|
||||
|
||||
void *p;
|
||||
|
||||
void (*command)(void *p, uint8_t *cdb);
|
||||
void (*callback)(void *p);
|
||||
int (*err_stat_to_scsi)(void *p);
|
||||
void (*request_sense)(void *p, uint8_t *buffer, uint8_t alloc_length);
|
||||
void (*reset)(void *p);
|
||||
int (*read_capacity)(void *p, uint8_t *cdb, uint8_t *buffer, uint32_t *len);
|
||||
} scsi_device_t;
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
uint8_t pages[0x40][0x40];
|
||||
} mode_sense_pages_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
/* This is so we can access the common elements to all SCSI device structs
|
||||
without knowing the device type. */
|
||||
typedef struct {
|
||||
typedef struct scsi_common_s {
|
||||
mode_sense_pages_t ms_pages_saved;
|
||||
|
||||
void *p;
|
||||
|
||||
uint8_t *temp_buffer,
|
||||
pad[16], /* This is atapi_cdb in ATAPI-supporting devices,
|
||||
atapi_cdb[16], /* This is atapi_cdb in ATAPI-supporting devices,
|
||||
and pad in SCSI-only devices. */
|
||||
current_cdb[16],
|
||||
sense[256];
|
||||
|
||||
uint8_t status, phase,
|
||||
error, id,
|
||||
features, pad0,
|
||||
pad1, pad2;
|
||||
features, pad,
|
||||
pad0, pad1;
|
||||
|
||||
uint16_t request_length, max_transfer_len;
|
||||
|
||||
int requested_blocks, packet_status,
|
||||
total_length, do_page_save,
|
||||
unit_attention;
|
||||
unit_attention, request_pos,
|
||||
old_len, media_status;
|
||||
|
||||
uint32_t sector_pos, sector_len,
|
||||
packet_len, pos;
|
||||
|
||||
int64_t callback;
|
||||
} scsi_device_data_t;
|
||||
} scsi_common_t;
|
||||
|
||||
typedef struct {
|
||||
int32_t buffer_length;
|
||||
|
||||
uint8_t status, phase;
|
||||
uint16_t type;
|
||||
|
||||
scsi_common_t *sc;
|
||||
|
||||
void (*command)(scsi_common_t *sc, uint8_t *cdb);
|
||||
void (*callback)(scsi_common_t *sc);
|
||||
void (*request_sense)(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length);
|
||||
void (*reset)(scsi_common_t *sc);
|
||||
void (*command_stop)(scsi_common_t *sc);
|
||||
} scsi_device_t;
|
||||
|
||||
/* These are based on the INQUIRY values. */
|
||||
#define SCSI_NONE 0x0060
|
||||
@@ -371,6 +379,7 @@ extern int scsi_device_valid(scsi_device_t *dev);
|
||||
extern int scsi_device_cdb_length(scsi_device_t *dev);
|
||||
extern void scsi_device_command_phase0(scsi_device_t *dev, uint8_t *cdb);
|
||||
extern void scsi_device_command_phase1(scsi_device_t *dev);
|
||||
extern int32_t *scsi_device_get_buf_len(scsi_device_t *dev);
|
||||
extern void scsi_device_command_stop(scsi_device_t *dev);
|
||||
extern void scsi_device_close_all(void);
|
||||
|
||||
#endif /*SCSI_DEVICE_H*/
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*
|
||||
* Emulation of SCSI fixed disks.
|
||||
*
|
||||
* Version: @(#)scsi_disk.c 1.0.27 2018/10/27
|
||||
* Version: @(#)scsi_disk.c 1.0.28 2018/10/28
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
@@ -26,27 +26,13 @@
|
||||
#include "../piix.h"
|
||||
#include "../disk/hdd.h"
|
||||
#include "../disk/hdc.h"
|
||||
#include "scsi_device.h"
|
||||
#include "../disk/hdc_ide.h"
|
||||
#include "../plat.h"
|
||||
#include "../ui.h"
|
||||
#include "scsi_device.h"
|
||||
#include "scsi_disk.h"
|
||||
|
||||
|
||||
/* Bits of 'status' */
|
||||
#define ERR_STAT 0x01
|
||||
#define DRQ_STAT 0x08 /* Data request */
|
||||
#define DSC_STAT 0x10
|
||||
#define SERVICE_STAT 0x10
|
||||
#define READY_STAT 0x40
|
||||
#define BUSY_STAT 0x80
|
||||
|
||||
/* Bits of 'error' */
|
||||
#define ABRT_ERR 0x04 /* Command aborted */
|
||||
#define MCR_ERR 0x08 /* Media change request */
|
||||
|
||||
#define MAX_BLOCKS_AT_ONCE 340
|
||||
|
||||
#define scsi_disk_sense_error dev->sense[0]
|
||||
#define scsi_disk_sense_key dev->sense[2]
|
||||
#define scsi_disk_asc dev->sense[12]
|
||||
@@ -136,7 +122,7 @@ static const mode_sense_pages_t scsi_disk_mode_sense_pages_changeable =
|
||||
} };
|
||||
|
||||
|
||||
static void scsi_disk_callback(void *p);
|
||||
static void scsi_disk_callback(scsi_common_t *sc);
|
||||
|
||||
|
||||
#ifdef ENABLE_SCSI_DISK_LOG
|
||||
@@ -159,19 +145,6 @@ scsi_disk_log(const char *fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
/* Translates ATAPI status (ERR_STAT flag) to SCSI status. */
|
||||
static int
|
||||
scsi_disk_err_stat_to_scsi(void *p)
|
||||
{
|
||||
scsi_disk_t *dev = (scsi_disk_t *) p;
|
||||
|
||||
if (dev->status & ERR_STAT)
|
||||
return SCSI_STATUS_CHECK_CONDITION;
|
||||
else
|
||||
return SCSI_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
scsi_disk_mode_sense_load(scsi_disk_t *dev)
|
||||
{
|
||||
@@ -206,25 +179,6 @@ scsi_disk_mode_sense_save(scsi_disk_t *dev)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
scsi_disk_read_capacity(void *p, uint8_t *cdb, uint8_t *buffer, uint32_t *len)
|
||||
{
|
||||
scsi_disk_t *dev = (scsi_disk_t *) p;
|
||||
int size = 0;
|
||||
|
||||
size = hdd_image_get_last_sector(dev->id);
|
||||
memset(buffer, 0, 8);
|
||||
buffer[0] = (size >> 24) & 0xff;
|
||||
buffer[1] = (size >> 16) & 0xff;
|
||||
buffer[2] = (size >> 8) & 0xff;
|
||||
buffer[3] = size & 0xff;
|
||||
buffer[6] = 2; /* 512 = 0x0200 */
|
||||
*len = 8;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*SCSI Mode Sense 6/10*/
|
||||
uint8_t
|
||||
scsi_disk_mode_sense_read(scsi_disk_t *dev, uint8_t page_control, uint8_t page, uint8_t pos)
|
||||
@@ -292,7 +246,7 @@ scsi_disk_command_common(scsi_disk_t *dev)
|
||||
dev->status = BUSY_STAT;
|
||||
dev->phase = 1;
|
||||
if (dev->packet_status == PHASE_COMPLETE) {
|
||||
scsi_disk_callback((void *) dev);
|
||||
scsi_disk_callback((scsi_common_t *) dev);
|
||||
dev->callback = 0LL;
|
||||
} else
|
||||
dev->callback = -1LL; /* Speed depends on SCSI controller */
|
||||
@@ -485,9 +439,9 @@ scsi_disk_rezero(scsi_disk_t *dev)
|
||||
|
||||
|
||||
static void
|
||||
scsi_disk_reset(void *p)
|
||||
scsi_disk_reset(scsi_common_t *sc)
|
||||
{
|
||||
scsi_disk_t *dev = (scsi_disk_t *) p;
|
||||
scsi_disk_t *dev = (scsi_disk_t *) sc;
|
||||
|
||||
scsi_disk_rezero(dev);
|
||||
dev->status = 0;
|
||||
@@ -522,9 +476,9 @@ scsi_disk_request_sense(scsi_disk_t *dev, uint8_t *buffer, uint8_t alloc_length,
|
||||
|
||||
|
||||
static void
|
||||
scsi_disk_request_sense_for_scsi(void *p, uint8_t *buffer, uint8_t alloc_length)
|
||||
scsi_disk_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length)
|
||||
{
|
||||
scsi_disk_t *dev = (scsi_disk_t *) p;
|
||||
scsi_disk_t *dev = (scsi_disk_t *) sc;
|
||||
|
||||
scsi_disk_request_sense(dev, buffer, alloc_length, 0);
|
||||
}
|
||||
@@ -544,9 +498,29 @@ scsi_disk_set_buf_len(scsi_disk_t *dev, int32_t *BufLen, int32_t *src_len)
|
||||
|
||||
|
||||
static void
|
||||
scsi_disk_command(void *p, uint8_t *cdb)
|
||||
scsi_disk_buf_alloc(scsi_disk_t *dev, uint32_t len)
|
||||
{
|
||||
scsi_disk_t *dev = (scsi_disk_t *) p;
|
||||
scsi_disk_log("SCSI HD %i: Allocated buffer length: %i\n", dev->id, len);
|
||||
if (!dev->temp_buffer)
|
||||
dev->temp_buffer = (uint8_t *) malloc(len);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_disk_buf_free(scsi_disk_t *dev)
|
||||
{
|
||||
if (dev->temp_buffer) {
|
||||
scsi_disk_log("SCSI HD %i: Freeing buffer...\n", dev->id);
|
||||
free(dev->temp_buffer);
|
||||
dev->temp_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_disk_command(scsi_common_t *sc, uint8_t *cdb)
|
||||
{
|
||||
scsi_disk_t *dev = (scsi_disk_t *) sc;
|
||||
#ifdef ENABLE_SCSI_DISK_LOG
|
||||
uint8_t *hdbufferb;
|
||||
#endif
|
||||
@@ -631,6 +605,7 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
break;
|
||||
}
|
||||
|
||||
scsi_disk_buf_alloc(dev, 256);
|
||||
scsi_disk_set_buf_len(dev, BufLen, &len);
|
||||
|
||||
if (*BufLen < cdb[4])
|
||||
@@ -638,14 +613,21 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
|
||||
len = (cdb[1] & 1) ? 8 : 18;
|
||||
|
||||
scsi_disk_request_sense(dev, dev->temp_buffer, *BufLen, cdb[1] & 1);
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN);
|
||||
scsi_disk_data_command_finish(dev, len, len, cdb[4], 0);
|
||||
break;
|
||||
|
||||
case GPCMD_MECHANISM_STATUS:
|
||||
len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
|
||||
scsi_disk_set_buf_len(dev, BufLen, &len);
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN);
|
||||
len = (cdb[8] << 8) | cdb[9];
|
||||
|
||||
scsi_disk_buf_alloc(dev, 8);
|
||||
scsi_disk_set_buf_len(dev, BufLen, &len);
|
||||
|
||||
memset(dev->temp_buffer, 0, 8);
|
||||
dev->temp_buffer[5] = 1;
|
||||
|
||||
scsi_disk_data_command_finish(dev, 8, 8, len, 0);
|
||||
break;
|
||||
|
||||
@@ -684,10 +666,17 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
dev->requested_blocks = max_len;
|
||||
|
||||
alloc_length = dev->packet_len = max_len << 9;
|
||||
|
||||
scsi_disk_buf_alloc(dev, dev->packet_len);
|
||||
scsi_disk_set_buf_len(dev, BufLen, &alloc_length);
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN);
|
||||
|
||||
if ((dev->requested_blocks > 0) && (*BufLen > 0)) {
|
||||
if (dev->packet_len > (uint32_t) *BufLen)
|
||||
hdd_image_read(dev->id, dev->sector_pos, *BufLen >> 9, dev->temp_buffer);
|
||||
else
|
||||
hdd_image_read(dev->id, dev->sector_pos, dev->requested_blocks, dev->temp_buffer);
|
||||
}
|
||||
|
||||
if (dev->requested_blocks > 1)
|
||||
scsi_disk_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, alloc_length, 0);
|
||||
else
|
||||
@@ -748,6 +737,7 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
dev->requested_blocks = max_len;
|
||||
|
||||
alloc_length = dev->packet_len = max_len << 9;
|
||||
scsi_disk_buf_alloc(dev, dev->packet_len);
|
||||
|
||||
scsi_disk_set_buf_len(dev, BufLen, &alloc_length);
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT);
|
||||
@@ -759,6 +749,9 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
return;
|
||||
|
||||
case GPCMD_WRITE_SAME_10:
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT);
|
||||
alloc_length = 512;
|
||||
|
||||
if ((cdb[1] & 6) == 6) {
|
||||
scsi_disk_invalid_field(dev);
|
||||
return;
|
||||
@@ -766,7 +759,6 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
|
||||
dev->sector_len = (cdb[7] << 8) | cdb[8];
|
||||
dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5];
|
||||
scsi_disk_log("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos);
|
||||
|
||||
if ((dev->sector_pos > last_sector) ||
|
||||
((dev->sector_pos + dev->sector_len - 1) > last_sector)) {
|
||||
@@ -782,18 +774,15 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
break;
|
||||
}
|
||||
|
||||
max_len = 1;
|
||||
dev->requested_blocks = max_len;
|
||||
|
||||
alloc_length = dev->packet_len = max_len << 9;
|
||||
|
||||
scsi_disk_buf_alloc(dev, alloc_length);
|
||||
scsi_disk_set_buf_len(dev, BufLen, &alloc_length);
|
||||
|
||||
max_len = 1;
|
||||
dev->requested_blocks = 1;
|
||||
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT);
|
||||
|
||||
if (dev->requested_blocks > 1)
|
||||
scsi_disk_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, alloc_length, 1);
|
||||
else
|
||||
scsi_disk_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 1);
|
||||
scsi_disk_data_command_finish(dev, 512, 512, alloc_length, 1);
|
||||
return;
|
||||
|
||||
case GPCMD_MODE_SENSE_6:
|
||||
@@ -802,16 +791,17 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
|
||||
block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1;
|
||||
|
||||
if (cdb[0] == GPCMD_MODE_SENSE_6)
|
||||
if (cdb[0] == GPCMD_MODE_SENSE_6) {
|
||||
len = cdb[4];
|
||||
else
|
||||
scsi_disk_buf_alloc(dev, 256);
|
||||
} else {
|
||||
len = (cdb[8] | (cdb[7] << 8));
|
||||
scsi_disk_buf_alloc(dev, 65536);
|
||||
}
|
||||
|
||||
memset(dev->temp_buffer, 0, len);
|
||||
alloc_length = len;
|
||||
|
||||
dev->temp_buffer = (uint8_t *) malloc(65536);
|
||||
memset(dev->temp_buffer, 0, 65536);
|
||||
|
||||
if (cdb[0] == GPCMD_MODE_SENSE_6) {
|
||||
len = scsi_disk_mode_sense(dev, dev->temp_buffer, 4, cdb[2], block_desc);
|
||||
if (len > alloc_length)
|
||||
@@ -848,10 +838,13 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
case GPCMD_MODE_SELECT_10:
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT);
|
||||
|
||||
if (cdb[0] == GPCMD_MODE_SELECT_6)
|
||||
if (cdb[0] == GPCMD_MODE_SELECT_6) {
|
||||
len = cdb[4];
|
||||
else
|
||||
scsi_disk_buf_alloc(dev, 256);
|
||||
} else {
|
||||
len = (cdb[7] << 8) | cdb[8];
|
||||
scsi_disk_buf_alloc(dev, 65536);
|
||||
}
|
||||
|
||||
scsi_disk_set_buf_len(dev, BufLen, &len);
|
||||
dev->total_length = len;
|
||||
@@ -872,7 +865,7 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
break;
|
||||
}
|
||||
|
||||
dev->temp_buffer = malloc(1024);
|
||||
scsi_disk_buf_alloc(dev, 65536);
|
||||
|
||||
if (cdb[1] & 1) {
|
||||
preamble_len = 4;
|
||||
@@ -891,8 +884,7 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
break;
|
||||
case 0x83:
|
||||
if (idx + 24 > max_len) {
|
||||
free(dev->temp_buffer);
|
||||
dev->temp_buffer = NULL;
|
||||
scsi_disk_buf_free(dev);
|
||||
scsi_disk_data_phase_error(dev);
|
||||
return;
|
||||
}
|
||||
@@ -919,9 +911,8 @@ scsi_disk_command(void *p, uint8_t *cdb)
|
||||
break;
|
||||
default:
|
||||
scsi_disk_log("INQUIRY: Invalid page: %02X\n", cdb[2]);
|
||||
free(dev->temp_buffer);
|
||||
dev->temp_buffer = NULL;
|
||||
scsi_disk_invalid_field(dev);
|
||||
scsi_disk_buf_free(dev);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -988,12 +979,16 @@ atapi_out:
|
||||
break;
|
||||
|
||||
case GPCMD_READ_CDROM_CAPACITY:
|
||||
dev->temp_buffer = (uint8_t *) malloc(8);
|
||||
scsi_disk_buf_alloc(dev, 8);
|
||||
|
||||
if (scsi_disk_read_capacity(dev, dev->current_cdb, dev->temp_buffer, (uint32_t *) &len) == 0) {
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_STATUS);
|
||||
return;
|
||||
}
|
||||
max_len = hdd_image_get_last_sector(dev->id);
|
||||
memset(dev->temp_buffer, 0, 8);
|
||||
dev->temp_buffer[0] = (max_len >> 24) & 0xff;
|
||||
dev->temp_buffer[1] = (max_len >> 16) & 0xff;
|
||||
dev->temp_buffer[2] = (max_len >> 8) & 0xff;
|
||||
dev->temp_buffer[3] = max_len & 0xff;
|
||||
dev->temp_buffer[6] = 2;
|
||||
len = 8;
|
||||
|
||||
scsi_disk_set_buf_len(dev, BufLen, &len);
|
||||
|
||||
@@ -1011,62 +1006,19 @@ atapi_out:
|
||||
|
||||
|
||||
static void
|
||||
scsi_disk_phase_data_in(scsi_disk_t *dev)
|
||||
scsi_disk_command_stop(scsi_common_t *sc)
|
||||
{
|
||||
uint8_t *hdbufferb = scsi_devices[dev->drv->scsi_id].cmd_buffer;
|
||||
int32_t *BufLen = &scsi_devices[dev->drv->scsi_id].buffer_length;
|
||||
scsi_disk_t *dev = (scsi_disk_t *) sc;
|
||||
|
||||
if (!*BufLen) {
|
||||
scsi_disk_log("scsi_disk_phase_data_in(): Buffer length is 0\n");
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_STATUS);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch (dev->current_cdb[0]) {
|
||||
case GPCMD_REQUEST_SENSE:
|
||||
scsi_disk_log("SCSI HDD %i: %08X, %08X\n", dev->id, hdbufferb, *BufLen);
|
||||
scsi_disk_request_sense(dev, hdbufferb, *BufLen, dev->current_cdb[1] & 1);
|
||||
break;
|
||||
case GPCMD_MECHANISM_STATUS:
|
||||
memset(hdbufferb, 0, *BufLen);
|
||||
hdbufferb[5] = 1;
|
||||
break;
|
||||
case GPCMD_READ_6:
|
||||
case GPCMD_READ_10:
|
||||
case GPCMD_READ_12:
|
||||
if ((dev->requested_blocks > 0) && (*BufLen > 0)) {
|
||||
if (dev->packet_len > (uint32_t) *BufLen)
|
||||
hdd_image_read(dev->id, dev->sector_pos, *BufLen >> 9, hdbufferb);
|
||||
else
|
||||
hdd_image_read(dev->id, dev->sector_pos, dev->requested_blocks, hdbufferb);
|
||||
}
|
||||
break;
|
||||
case GPCMD_MODE_SENSE_6:
|
||||
case GPCMD_MODE_SENSE_10:
|
||||
case GPCMD_INQUIRY:
|
||||
case GPCMD_READ_CDROM_CAPACITY:
|
||||
scsi_disk_log("scsi_disk_phase_data_in(): Filling buffer (%08X, %08X)\n", hdbufferb, dev->temp_buffer);
|
||||
memcpy(hdbufferb, dev->temp_buffer, *BufLen);
|
||||
free(dev->temp_buffer);
|
||||
dev->temp_buffer = NULL;
|
||||
scsi_disk_log("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
hdbufferb[0], hdbufferb[1], hdbufferb[2], hdbufferb[3], hdbufferb[4], hdbufferb[5], hdbufferb[6], hdbufferb[7],
|
||||
hdbufferb[8], hdbufferb[9], hdbufferb[10], hdbufferb[11], hdbufferb[12], hdbufferb[13], hdbufferb[14], hdbufferb[15]);
|
||||
break;
|
||||
default:
|
||||
fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", dev->id, dev->current_cdb[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_STATUS);
|
||||
scsi_disk_command_complete(dev);
|
||||
scsi_disk_buf_free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_disk_phase_data_out(scsi_disk_t *dev)
|
||||
scsi_disk_phase_data_out(scsi_common_t *sc)
|
||||
{
|
||||
uint8_t *hdbufferb = scsi_devices[dev->drv->scsi_id].cmd_buffer;
|
||||
scsi_disk_t *dev = (scsi_disk_t *) sc;
|
||||
int i;
|
||||
int32_t *BufLen = &scsi_devices[dev->drv->scsi_id].buffer_length;
|
||||
uint32_t last_sector = hdd_image_get_last_sector(dev->id);
|
||||
@@ -1093,9 +1045,9 @@ scsi_disk_phase_data_out(scsi_disk_t *dev)
|
||||
case GPCMD_WRITE_AND_VERIFY_12:
|
||||
if ((dev->requested_blocks > 0) && (*BufLen > 0)) {
|
||||
if (dev->packet_len > (uint32_t) *BufLen)
|
||||
hdd_image_write(dev->id, dev->sector_pos, *BufLen >> 9, hdbufferb);
|
||||
hdd_image_write(dev->id, dev->sector_pos, *BufLen >> 9, dev->temp_buffer);
|
||||
else
|
||||
hdd_image_write(dev->id, dev->sector_pos, dev->requested_blocks, hdbufferb);
|
||||
hdd_image_write(dev->id, dev->sector_pos, dev->requested_blocks, dev->temp_buffer);
|
||||
}
|
||||
break;
|
||||
case GPCMD_WRITE_SAME_10:
|
||||
@@ -1106,24 +1058,24 @@ scsi_disk_phase_data_out(scsi_disk_t *dev)
|
||||
|
||||
for (i = dev->sector_pos; i <= (int) last_to_write; i++) {
|
||||
if (dev->current_cdb[1] & 2) {
|
||||
hdbufferb[0] = (i >> 24) & 0xff;
|
||||
hdbufferb[1] = (i >> 16) & 0xff;
|
||||
hdbufferb[2] = (i >> 8) & 0xff;
|
||||
hdbufferb[3] = i & 0xff;
|
||||
dev->temp_buffer[0] = (i >> 24) & 0xff;
|
||||
dev->temp_buffer[1] = (i >> 16) & 0xff;
|
||||
dev->temp_buffer[2] = (i >> 8) & 0xff;
|
||||
dev->temp_buffer[3] = i & 0xff;
|
||||
} else if (dev->current_cdb[1] & 4) {
|
||||
s = (i % dev->drv->spt);
|
||||
h = ((i - s) / dev->drv->spt) % dev->drv->hpc;
|
||||
c = ((i - s) / dev->drv->spt) / dev->drv->hpc;
|
||||
hdbufferb[0] = (c >> 16) & 0xff;
|
||||
hdbufferb[1] = (c >> 8) & 0xff;
|
||||
hdbufferb[2] = c & 0xff;
|
||||
hdbufferb[3] = h & 0xff;
|
||||
hdbufferb[4] = (s >> 24) & 0xff;
|
||||
hdbufferb[5] = (s >> 16) & 0xff;
|
||||
hdbufferb[6] = (s >> 8) & 0xff;
|
||||
hdbufferb[7] = s & 0xff;
|
||||
dev->temp_buffer[0] = (c >> 16) & 0xff;
|
||||
dev->temp_buffer[1] = (c >> 8) & 0xff;
|
||||
dev->temp_buffer[2] = c & 0xff;
|
||||
dev->temp_buffer[3] = h & 0xff;
|
||||
dev->temp_buffer[4] = (s >> 24) & 0xff;
|
||||
dev->temp_buffer[5] = (s >> 16) & 0xff;
|
||||
dev->temp_buffer[6] = (s >> 8) & 0xff;
|
||||
dev->temp_buffer[7] = s & 0xff;
|
||||
}
|
||||
hdd_image_write(dev->id, i, 1, hdbufferb);
|
||||
hdd_image_write(dev->id, i, 1, dev->temp_buffer);
|
||||
}
|
||||
break;
|
||||
case GPCMD_MODE_SELECT_6:
|
||||
@@ -1134,20 +1086,20 @@ scsi_disk_phase_data_out(scsi_disk_t *dev)
|
||||
hdr_len = 4;
|
||||
|
||||
if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) {
|
||||
block_desc_len = hdbufferb[2];
|
||||
block_desc_len = dev->temp_buffer[2];
|
||||
block_desc_len <<= 8;
|
||||
block_desc_len |= hdbufferb[3];
|
||||
block_desc_len |= dev->temp_buffer[3];
|
||||
} else {
|
||||
block_desc_len = hdbufferb[6];
|
||||
block_desc_len = dev->temp_buffer[6];
|
||||
block_desc_len <<= 8;
|
||||
block_desc_len |= hdbufferb[7];
|
||||
block_desc_len |= dev->temp_buffer[7];
|
||||
}
|
||||
|
||||
pos = hdr_len + block_desc_len;
|
||||
|
||||
while(1) {
|
||||
page = hdbufferb[pos] & 0x3F;
|
||||
page_len = hdbufferb[pos + 1];
|
||||
page = dev->temp_buffer[pos] & 0x3F;
|
||||
page_len = dev->temp_buffer[pos + 1];
|
||||
|
||||
pos += 2;
|
||||
|
||||
@@ -1156,7 +1108,7 @@ scsi_disk_phase_data_out(scsi_disk_t *dev)
|
||||
else {
|
||||
for (i = 0; i < page_len; i++) {
|
||||
ch = scsi_disk_mode_sense_pages_changeable.pages[page][i + 2];
|
||||
val = hdbufferb[pos + i];
|
||||
val = dev->temp_buffer[pos + i];
|
||||
old_val = dev->ms_pages_saved.pages[page][i + 2];
|
||||
if (val != old_val) {
|
||||
if (ch)
|
||||
@@ -1177,54 +1129,48 @@ scsi_disk_phase_data_out(scsi_disk_t *dev)
|
||||
break;
|
||||
}
|
||||
|
||||
if (error)
|
||||
if (error) {
|
||||
scsi_disk_buf_free(dev);
|
||||
scsi_disk_invalid_field_pl(dev);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", dev->id, dev->current_cdb[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
scsi_disk_set_phase(dev, SCSI_PHASE_STATUS);
|
||||
scsi_disk_command_stop((scsi_common_t *) dev);
|
||||
}
|
||||
|
||||
|
||||
/* If the result is 1, issue an IRQ, otherwise not. */
|
||||
static void
|
||||
scsi_disk_callback(void *p)
|
||||
scsi_disk_callback(scsi_common_t *sc)
|
||||
{
|
||||
scsi_disk_t *dev = (scsi_disk_t *) p;
|
||||
|
||||
switch(dev->packet_status) {
|
||||
switch(sc->packet_status) {
|
||||
case PHASE_IDLE:
|
||||
scsi_disk_log("SCSI HD %i: PHASE_IDLE\n", dev->id);
|
||||
dev->phase = 1;
|
||||
dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT);
|
||||
sc->phase = 1;
|
||||
sc->status = READY_STAT | DRQ_STAT | (sc->status & ERR_STAT);
|
||||
return;
|
||||
case PHASE_COMPLETE:
|
||||
scsi_disk_log("SCSI HD %i: PHASE_COMPLETE\n", dev->id);
|
||||
dev->status = READY_STAT;
|
||||
dev->phase = 3;
|
||||
dev->packet_status = 0xFF;
|
||||
sc->status = READY_STAT;
|
||||
sc->phase = 3;
|
||||
sc->packet_status = 0xFF;
|
||||
return;
|
||||
case PHASE_DATA_OUT_DMA:
|
||||
scsi_disk_log("SCSI HD %i: PHASE_DATA_OUT_DMA\n", dev->id);
|
||||
scsi_disk_phase_data_out(dev);
|
||||
dev->packet_status = PHASE_COMPLETE;
|
||||
dev->status = READY_STAT;
|
||||
dev->phase = 3;
|
||||
scsi_disk_phase_data_out(sc);
|
||||
return;
|
||||
case PHASE_DATA_IN_DMA:
|
||||
scsi_disk_log("SCSI HD %i: PHASE_DATA_IN_DMA\n", dev->id);
|
||||
scsi_disk_phase_data_in(dev);
|
||||
dev->packet_status = PHASE_COMPLETE;
|
||||
dev->status = READY_STAT;
|
||||
dev->phase = 3;
|
||||
scsi_disk_command_stop(sc);
|
||||
return;
|
||||
case PHASE_ERROR:
|
||||
scsi_disk_log("SCSI HD %i: PHASE_ERROR\n", dev->id);
|
||||
dev->status = READY_STAT | ERR_STAT;
|
||||
dev->phase = 3;
|
||||
sc->status = READY_STAT | ERR_STAT;
|
||||
sc->phase = 3;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1263,13 +1209,12 @@ scsi_disk_hard_reset(void)
|
||||
/* SCSI disk, attach to the SCSI bus. */
|
||||
sd = &scsi_devices[hdd[c].scsi_id];
|
||||
|
||||
sd->p = dev;
|
||||
sd->sc = (scsi_common_t *) dev;
|
||||
sd->command = scsi_disk_command;
|
||||
sd->callback = scsi_disk_callback;
|
||||
sd->err_stat_to_scsi = scsi_disk_err_stat_to_scsi;
|
||||
sd->request_sense = scsi_disk_request_sense_for_scsi;
|
||||
sd->reset = scsi_disk_reset;
|
||||
sd->read_capacity = scsi_disk_read_capacity;
|
||||
sd->command_stop = scsi_disk_command_stop;
|
||||
sd->type = SCSI_FIXED_DISK;
|
||||
|
||||
dev->id = c;
|
||||
@@ -1290,13 +1235,15 @@ scsi_disk_close(void)
|
||||
int c;
|
||||
|
||||
for (c = 0; c < HDD_NUM; c++) {
|
||||
if (hdd[c].bus == HDD_BUS_SCSI) {
|
||||
hdd_image_close(c);
|
||||
|
||||
dev = hdd[c].priv;
|
||||
|
||||
if (dev) {
|
||||
hdd_image_close(c);
|
||||
|
||||
free(dev);
|
||||
hdd[c].priv = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,8 @@ typedef struct {
|
||||
|
||||
int requested_blocks, packet_status,
|
||||
total_length, do_page_save,
|
||||
unit_attention;
|
||||
unit_attention, pad5,
|
||||
pad6, pad7;
|
||||
|
||||
uint32_t sector_pos, sector_len,
|
||||
packet_len, pos;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* Implementation of the NCR 5380 series of SCSI Host Adapters
|
||||
* made by NCR. These controllers were designed for the ISA bus.
|
||||
*
|
||||
* Version: @(#)scsi_ncr5380.c 1.0.23 2018/10/18
|
||||
* Version: @(#)scsi_ncr5380.c 1.0.24 2018/10/28
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* TheCollector1995, <mariogplayer@gmail.com>
|
||||
@@ -286,7 +286,7 @@ ncr_wait_process(ncr5380_t *ncr_dev)
|
||||
|
||||
if (ncr->new_phase == SCSI_PHASE_DATA_IN) {
|
||||
ncr_log("Data In bus phase\n");
|
||||
ncr->tx_data = dev->cmd_buffer[ncr->data_pos++];
|
||||
ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++];
|
||||
ncr->state = STATE_DATAIN;
|
||||
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP;
|
||||
} else if (ncr->new_phase == SCSI_PHASE_STATUS) {
|
||||
@@ -963,8 +963,6 @@ ncr_callback(void *priv)
|
||||
|
||||
/*If the SCSI phase is Data In or Data Out, allocate the SCSI buffer based on the transfer length of the command*/
|
||||
if (dev->buffer_length && (dev->phase == SCSI_PHASE_DATA_IN || dev->phase == SCSI_PHASE_DATA_OUT)) {
|
||||
dev->cmd_buffer = (uint8_t *) malloc(dev->buffer_length);
|
||||
|
||||
p = scsi_device_get_callback(dev);
|
||||
req_len = MIN(64, dev->buffer_length);
|
||||
if (p <= 0LL)
|
||||
@@ -982,10 +980,6 @@ ncr_callback(void *priv)
|
||||
} else {
|
||||
/* Other command - execute immediately. */
|
||||
ncr->new_phase = dev->phase;
|
||||
|
||||
if (ncr->new_phase == SCSI_PHASE_DATA_IN)
|
||||
scsi_device_command_phase1(dev);
|
||||
|
||||
ncr->wait_data = 4;
|
||||
}
|
||||
}
|
||||
@@ -995,17 +989,13 @@ ncr_callback(void *priv)
|
||||
ncr_log("Data In ACK=%02x\n", ncr->bus_host & BUS_ACK);
|
||||
if (ncr->bus_host & BUS_ACK) {
|
||||
if (ncr->data_pos >= dev->buffer_length) {
|
||||
if (dev->cmd_buffer != NULL) {
|
||||
free(dev->cmd_buffer);
|
||||
dev->cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
scsi_device_command_phase1(dev);
|
||||
ncr->cur_bus &= ~BUS_REQ;
|
||||
ncr->new_phase = SCSI_PHASE_STATUS;
|
||||
ncr->wait_data = 4;
|
||||
ncr->wait_complete = 8;
|
||||
} else {
|
||||
ncr->tx_data = dev->cmd_buffer[ncr->data_pos++];
|
||||
ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++];
|
||||
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ;
|
||||
ncr->clear_req = 3;
|
||||
ncr->cur_bus &= ~BUS_REQ;
|
||||
@@ -1017,16 +1007,10 @@ ncr_callback(void *priv)
|
||||
|
||||
ncr_log("Data Out ACK=%02x\n", ncr->bus_host & BUS_ACK);
|
||||
if (ncr->bus_host & BUS_ACK) {
|
||||
dev->cmd_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host);
|
||||
dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host);
|
||||
|
||||
if (ncr->data_pos >= dev->buffer_length) {
|
||||
scsi_device_command_phase1(dev);
|
||||
|
||||
if (dev->cmd_buffer != NULL) {
|
||||
free(dev->cmd_buffer);
|
||||
dev->cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
ncr->cur_bus &= ~BUS_REQ;
|
||||
ncr_log("CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus);
|
||||
ncr->new_phase = SCSI_PHASE_STATUS;
|
||||
@@ -1076,17 +1060,13 @@ ncr_callback(void *priv)
|
||||
ncr->bus_host = get_bus_host(ncr);
|
||||
|
||||
if (ncr->data_pos >= dev->buffer_length) {
|
||||
if (dev->cmd_buffer != NULL) {
|
||||
free(dev->cmd_buffer);
|
||||
dev->cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
scsi_device_command_phase1(dev);
|
||||
ncr->cur_bus &= ~BUS_REQ;
|
||||
ncr->new_phase = SCSI_PHASE_STATUS;
|
||||
ncr->wait_data = 4;
|
||||
ncr->wait_complete = 8;
|
||||
} else {
|
||||
ncr->tx_data = dev->cmd_buffer[ncr->data_pos++];
|
||||
ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++];
|
||||
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ;
|
||||
ncr->clear_req = 3;
|
||||
ncr->cur_bus &= ~BUS_REQ;
|
||||
@@ -1141,16 +1121,10 @@ ncr_callback(void *priv)
|
||||
ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK;
|
||||
ncr->bus_host |= BUS_SETDATA(data);
|
||||
|
||||
dev->cmd_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host);
|
||||
dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host);
|
||||
|
||||
if (ncr->data_pos >= dev->buffer_length) {
|
||||
scsi_device_command_phase1(dev);
|
||||
|
||||
if (dev->cmd_buffer != NULL) {
|
||||
free(dev->cmd_buffer);
|
||||
dev->cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
ncr->cur_bus &= ~BUS_REQ;
|
||||
ncr_log("CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus);
|
||||
ncr->new_phase = SCSI_PHASE_STATUS;
|
||||
@@ -1199,17 +1173,13 @@ ncr_callback(void *priv)
|
||||
ncr->bus_host = get_bus_host(ncr);
|
||||
|
||||
if (ncr->data_pos >= dev->buffer_length) {
|
||||
if (dev->cmd_buffer != NULL) {
|
||||
free(dev->cmd_buffer);
|
||||
dev->cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
scsi_device_command_phase1(dev);
|
||||
ncr->cur_bus &= ~BUS_REQ;
|
||||
ncr->new_phase = SCSI_PHASE_STATUS;
|
||||
ncr->wait_data = 4;
|
||||
ncr->wait_complete = 8;
|
||||
} else {
|
||||
ncr->tx_data = dev->cmd_buffer[ncr->data_pos++];
|
||||
ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++];
|
||||
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ;
|
||||
ncr->clear_req = 3;
|
||||
ncr->cur_bus &= ~BUS_REQ;
|
||||
@@ -1250,16 +1220,10 @@ ncr_callback(void *priv)
|
||||
ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK;
|
||||
ncr->bus_host |= BUS_SETDATA(data);
|
||||
|
||||
dev->cmd_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host);
|
||||
dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host);
|
||||
|
||||
if (ncr->data_pos >= dev->buffer_length) {
|
||||
scsi_device_command_phase1(dev);
|
||||
|
||||
if (dev->cmd_buffer != NULL) {
|
||||
free(dev->cmd_buffer);
|
||||
dev->cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
ncr->cur_bus &= ~BUS_REQ;
|
||||
ncr_log("CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus);
|
||||
ncr->new_phase = SCSI_PHASE_STATUS;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,11 +6,11 @@
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the NCR 53C810 SCSI Host Adapter made by
|
||||
* NCR and later Symbios and LSI. This controller was designed
|
||||
* for the PCI bus.
|
||||
* Implementation of the NCR 53C810 and 53C875 SCSI Host
|
||||
* Adapters made by NCR and later Symbios and LSI. These
|
||||
* controllers were designed for the PCI bus.
|
||||
*
|
||||
* Version: @(#)scsi_ncr53c810.c 1.0.1 2018/03/18
|
||||
* Version: @(#)scsi_ncr53c8xx.c 1.0.2 2018/10/30
|
||||
*
|
||||
* Authors: TheCollector1995, <mariogplayer@gmail.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -21,11 +21,13 @@
|
||||
* Copyright 2009-2018 Artyom Tarasenko.
|
||||
* Copyright 2017,2018 Miran Grca.
|
||||
*/
|
||||
#ifndef SCSI_NCR5C3810_H
|
||||
# define SCSI_NCR53C810_H
|
||||
#ifndef SCSI_NCR5C38XX_H
|
||||
# define SCSI_NCR53C8XX_H
|
||||
|
||||
|
||||
extern const device_t ncr53c810_pci_device;
|
||||
extern const device_t ncr53c825a_pci_device;
|
||||
extern const device_t ncr53c875_pci_device;
|
||||
|
||||
|
||||
#endif /*SCSI_NCR53C810_H*/
|
||||
#endif /*SCSI_NCR53C8XX_H*/
|
||||
@@ -11,7 +11,7 @@
|
||||
* series of SCSI Host Adapters made by Mylex.
|
||||
* These controllers were designed for various buses.
|
||||
*
|
||||
* Version: @(#)scsi_x54x.c 1.0.25 2018/10/18
|
||||
* Version: @(#)scsi_x54x.c 1.0.26 2018/10/28
|
||||
*
|
||||
* Authors: TheCollector1995, <mariogplayer@gmail.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -261,32 +261,21 @@ x54x_bios_scsi_command(scsi_device_t *dev, uint8_t *cdb, uint8_t *buf, int len,
|
||||
if (dev->phase == SCSI_PHASE_STATUS)
|
||||
return(completion_code(scsi_device_sense(dev)));
|
||||
|
||||
dev->cmd_buffer = (uint8_t *)malloc(dev->buffer_length);
|
||||
|
||||
if (len > 0) {
|
||||
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);
|
||||
memcpy(buf, dev->sc->temp_buffer, dev->buffer_length);
|
||||
else
|
||||
DMAPageWrite(addr, dev->cmd_buffer, dev->buffer_length);
|
||||
}
|
||||
DMAPageWrite(addr, dev->sc->temp_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);
|
||||
memcpy(dev->sc->temp_buffer, buf, dev->buffer_length);
|
||||
else
|
||||
DMAPageRead(addr, dev->cmd_buffer, dev->buffer_length);
|
||||
DMAPageRead(addr, dev->sc->temp_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)));
|
||||
}
|
||||
@@ -439,11 +428,6 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
|
||||
dev = &scsi_devices[cmd->id];
|
||||
dev->buffer_length = 0;
|
||||
|
||||
if (dev->cmd_buffer != NULL) {
|
||||
free(dev->cmd_buffer);
|
||||
dev->cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
if (! scsi_device_present(dev)) {
|
||||
x54x_log("BIOS Target ID %i has no device attached\n", cmd->id);
|
||||
ret = 0x80;
|
||||
@@ -473,10 +457,6 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
|
||||
* length for SCSI sense, and no command-specific
|
||||
* indication is given.
|
||||
*/
|
||||
dev->buffer_length = 14;
|
||||
dev->cmd_buffer = (uint8_t *)malloc(14);
|
||||
memset(dev->cmd_buffer, 0x00, 14);
|
||||
|
||||
if (sector_len > 0) {
|
||||
x54x_log("BIOS DMA: Reading 14 bytes at %08X\n",
|
||||
dma_address);
|
||||
@@ -484,11 +464,6 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
|
||||
scsi_device_sense(dev), 14);
|
||||
}
|
||||
|
||||
if (dev && (dev->cmd_buffer != NULL)) {
|
||||
free(dev->cmd_buffer);
|
||||
dev->cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
return(0);
|
||||
break;
|
||||
|
||||
@@ -506,9 +481,6 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
|
||||
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
|
||||
|
||||
ret = x54x_bios_scsi_command(dev, cdb, NULL, sector_len, dma_address);
|
||||
if (cmd->command == 0x0c)
|
||||
@@ -552,8 +524,6 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
|
||||
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);
|
||||
|
||||
buf = (uint8_t *) malloc(6);
|
||||
if (cmd->command == 0x08)
|
||||
@@ -565,11 +535,6 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
|
||||
DMAPageWrite(dma_address, buf, 4);
|
||||
free(buf);
|
||||
|
||||
if (dev->cmd_buffer != NULL) {
|
||||
free(dev->cmd_buffer);
|
||||
dev->cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -831,11 +796,11 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir)
|
||||
|
||||
if (read_from_host && DataToTransfer) {
|
||||
x54x_log("Reading S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address);
|
||||
DMAPageRead(Address, &(scsi_devices[req->TargetID].cmd_buffer[sg_pos]), DataToTransfer);
|
||||
DMAPageRead(Address, &(scsi_devices[req->TargetID].sc->temp_buffer[sg_pos]), DataToTransfer);
|
||||
}
|
||||
else if (write_to_host && DataToTransfer) {
|
||||
x54x_log("Writing S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address);
|
||||
DMAPageWrite(Address, &(scsi_devices[req->TargetID].cmd_buffer[sg_pos]), DataToTransfer);
|
||||
DMAPageWrite(Address, &(scsi_devices[req->TargetID].sc->temp_buffer[sg_pos]), DataToTransfer);
|
||||
}
|
||||
else
|
||||
x54x_log("No action on S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address);
|
||||
@@ -855,39 +820,15 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir)
|
||||
|
||||
if ((DataLength > 0) && (BufLen > 0) && (req->CmdBlock.common.ControlByte < 0x03)) {
|
||||
if (read_from_host)
|
||||
DMAPageRead(Address, scsi_devices[req->TargetID].cmd_buffer, MIN(BufLen, (int) DataLength));
|
||||
DMAPageRead(Address, scsi_devices[req->TargetID].sc->temp_buffer, MIN(BufLen, (int) DataLength));
|
||||
else if (write_to_host)
|
||||
DMAPageWrite(Address, scsi_devices[req->TargetID].cmd_buffer, MIN(BufLen, (int) DataLength));
|
||||
DMAPageWrite(Address, scsi_devices[req->TargetID].sc->temp_buffer, MIN(BufLen, (int) DataLength));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
x54x_buf_alloc(uint8_t id, int length)
|
||||
{
|
||||
if (scsi_devices[id].cmd_buffer != NULL) {
|
||||
free(scsi_devices[id].cmd_buffer);
|
||||
scsi_devices[id].cmd_buffer = NULL;
|
||||
}
|
||||
|
||||
x54x_log("Allocating data buffer (%i bytes)\n", length);
|
||||
scsi_devices[id].cmd_buffer = (uint8_t *) malloc(length);
|
||||
memset(scsi_devices[id].cmd_buffer, 0, length);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
x54x_buf_free(uint8_t id)
|
||||
{
|
||||
if (scsi_devices[id].cmd_buffer != NULL) {
|
||||
free(scsi_devices[id].cmd_buffer);
|
||||
scsi_devices[id].cmd_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
ConvertSenseLength(uint8_t RequestSenseLength)
|
||||
{
|
||||
@@ -959,7 +900,6 @@ x54x_scsi_cmd(x54x_t *dev)
|
||||
uint8_t temp_cdb[12];
|
||||
uint32_t i, SenseBufferAddress;
|
||||
int target_data_len, target_cdb_len = 12;
|
||||
int32_t *BufLen;
|
||||
int64_t p;
|
||||
scsi_device_t *sd;
|
||||
|
||||
@@ -995,10 +935,7 @@ x54x_scsi_cmd(x54x_t *dev)
|
||||
|
||||
dev->Residue = 0;
|
||||
|
||||
BufLen = scsi_device_get_buf_len(sd);
|
||||
*BufLen = target_data_len;
|
||||
|
||||
x54x_log("Command buffer: %08X\n", scsi_devices[id].cmd_buffer);
|
||||
sd->buffer_length = target_data_len;
|
||||
|
||||
scsi_device_command_phase0(sd, temp_cdb);
|
||||
|
||||
@@ -1009,26 +946,21 @@ x54x_scsi_cmd(x54x_t *dev)
|
||||
if (phase != SCSI_PHASE_STATUS) {
|
||||
if ((temp_cdb[0] == 0x03) && (req->CmdBlock.common.ControlByte == 0x03)) {
|
||||
/* Request sense in non-data mode - sense goes to sense buffer. */
|
||||
*BufLen = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength);
|
||||
x54x_buf_alloc(id, *BufLen);
|
||||
scsi_device_command_phase1(sd);
|
||||
if ((sd->status != SCSI_STATUS_OK) && (*BufLen > 0)) {
|
||||
sd->buffer_length = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength);
|
||||
if ((sd->status != SCSI_STATUS_OK) && (sd->buffer_length > 0)) {
|
||||
SenseBufferAddress = SenseBufferPointer(req);
|
||||
DMAPageWrite(SenseBufferAddress, scsi_devices[id].cmd_buffer, *BufLen);
|
||||
x54x_add_to_period(*BufLen);
|
||||
DMAPageWrite(SenseBufferAddress, scsi_devices[id].sc->temp_buffer, sd->buffer_length);
|
||||
x54x_add_to_period(sd->buffer_length);
|
||||
}
|
||||
scsi_device_command_phase1(sd);
|
||||
} else {
|
||||
p = scsi_device_get_callback(sd);
|
||||
if (p <= 0LL)
|
||||
x54x_add_to_period(*BufLen);
|
||||
x54x_add_to_period(sd->buffer_length);
|
||||
else
|
||||
dev->media_period += p;
|
||||
x54x_buf_alloc(id, MIN(target_data_len, *BufLen));
|
||||
if (phase == SCSI_PHASE_DATA_OUT)
|
||||
x54x_buf_dma_transfer(req, bit24, target_data_len, 1);
|
||||
x54x_buf_dma_transfer(req, bit24, target_data_len, (phase == SCSI_PHASE_DATA_OUT));
|
||||
scsi_device_command_phase1(sd);
|
||||
if (phase == SCSI_PHASE_DATA_IN)
|
||||
x54x_buf_dma_transfer(req, bit24, target_data_len, 0);
|
||||
|
||||
SenseBufferFree(req, (sd->status != SCSI_STATUS_OK));
|
||||
}
|
||||
@@ -1037,8 +969,6 @@ x54x_scsi_cmd(x54x_t *dev)
|
||||
|
||||
x54x_set_residue(req, target_data_len);
|
||||
|
||||
x54x_buf_free(id);
|
||||
|
||||
x54x_log("Request complete\n");
|
||||
|
||||
if (sd->status == SCSI_STATUS_OK) {
|
||||
@@ -1378,9 +1308,6 @@ x54x_in(uint16_t port, void *priv)
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
x54x_log("%s: Read Port 0x%02X, Value %02X\n", dev->name, port, ret);
|
||||
#endif
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* of SCSI Host Adapters made by Mylex.
|
||||
* These controllers were designed for various buses.
|
||||
*
|
||||
* Version: @(#)scsi_x54x.h 1.0.9 2018/10/21
|
||||
* Version: @(#)scsi_x54x.h 1.0.10 2018/10/28
|
||||
*
|
||||
* Authors: TheCollector1995, <mariogplayer@gmail.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -500,8 +500,6 @@ typedef struct {
|
||||
|
||||
|
||||
extern void x54x_reset_ctrl(x54x_t *dev, uint8_t Reset);
|
||||
extern void x54x_buf_alloc(uint8_t id, int length);
|
||||
extern void x54x_buf_free(uint8_t id);
|
||||
extern uint8_t x54x_mbo_process(x54x_t *dev);
|
||||
extern void x54x_wait_for_poll(void);
|
||||
extern void x54x_io_set(x54x_t *dev, uint32_t base, uint8_t len);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Sound emulation core.
|
||||
*
|
||||
* Version: @(#)sound.c 1.0.24 2018/10/26
|
||||
* Version: @(#)sound.c 1.0.25 2018/10/28
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -205,9 +205,9 @@ static void
|
||||
sound_cd_clean_buffers(void)
|
||||
{
|
||||
if (sound_is_float)
|
||||
memset(cd_out_buffer, 0, 2 * sizeof(float));
|
||||
memset(cd_out_buffer, 0, (CD_BUFLEN * 2) * sizeof(float));
|
||||
else
|
||||
memset(cd_out_buffer_int16, 0, 2 * sizeof(int16_t));
|
||||
memset(cd_out_buffer_int16, 0, (CD_BUFLEN * 2) * sizeof(int16_t));
|
||||
}
|
||||
|
||||
|
||||
@@ -230,14 +230,12 @@ sound_cd_thread(void *param)
|
||||
sound_cd_clean_buffers();
|
||||
|
||||
for (i = 0; i < CDROM_NUM; i++) {
|
||||
if ((cdrom[i].bus_type == CDROM_BUS_DISABLED) || !cdrom[i].ops)
|
||||
if ((cdrom[i].bus_type == CDROM_BUS_DISABLED) ||
|
||||
(cdrom[i].cd_status == CD_STATUS_EMPTY))
|
||||
continue;
|
||||
if (cdrom[i].ops->audio_callback) {
|
||||
r = cdrom[i].ops->audio_callback(&(cdrom[i]), cd_buffer[i], CD_BUFLEN * 2);
|
||||
r = cdrom_audio_callback(&(cdrom[i]), cd_buffer[i], CD_BUFLEN * 2);
|
||||
if (!cdrom[i].bus_type || !cdrom[i].sound_on || !r)
|
||||
continue;
|
||||
} else
|
||||
continue;
|
||||
|
||||
if (cdrom[i].get_volume) {
|
||||
audio_vol_l = (float) (cdrom[i].get_volume(cdrom[i].priv, 0));
|
||||
@@ -480,8 +478,7 @@ sound_cd_thread_reset(void)
|
||||
int available_cdrom_drives = 0;
|
||||
|
||||
for (i = 0; i < CDROM_NUM; i++) {
|
||||
if (cdrom[i].ops && cdrom[i].ops->audio_stop)
|
||||
cdrom[i].ops->audio_stop(&(cdrom[i]));
|
||||
cdrom_stop(&(cdrom[i]));
|
||||
|
||||
if (cdrom[i].bus_type != CDROM_BUS_DISABLED)
|
||||
available_cdrom_drives++;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#
|
||||
# Makefile for Win32 (MinGW32) environment.
|
||||
#
|
||||
# Version: @(#)Makefile.mingw 1.0.133 2018/10/22
|
||||
# Version: @(#)Makefile.mingw 1.0.134 2018/10/26
|
||||
#
|
||||
# Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
# Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -483,7 +483,7 @@ SCSIOBJ := scsi.o scsi_device.o \
|
||||
scsi_cdrom.o scsi_disk.o \
|
||||
scsi_x54x.o \
|
||||
scsi_aha154x.o scsi_buslogic.o \
|
||||
scsi_ncr5380.o scsi_ncr53c810.o
|
||||
scsi_ncr5380.o scsi_ncr53c8xx.o
|
||||
|
||||
NETOBJ := network.o \
|
||||
net_pcap.o \
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Windows 86Box Settings dialog handler.
|
||||
*
|
||||
* Version: @(#)win_settings.c 1.0.72 2018/10/26
|
||||
* Version: @(#)win_settings.c 1.0.73 2018/10/30
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
@@ -477,6 +477,10 @@ win_settings_save(void)
|
||||
|
||||
/* Hard disks category */
|
||||
memcpy(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t));
|
||||
for (i = 0; i < HDD_NUM; i++) {
|
||||
hdd[i].f = NULL;
|
||||
hdd[i].priv = NULL;
|
||||
}
|
||||
|
||||
/* Floppy drives category */
|
||||
for (i = 0; i < FDD_NUM; i++) {
|
||||
@@ -487,7 +491,21 @@ win_settings_save(void)
|
||||
|
||||
/* Removable devices category */
|
||||
memcpy(cdrom, temp_cdrom, CDROM_NUM * sizeof(cdrom_t));
|
||||
for (i = 0; i < CDROM_NUM; i++) {
|
||||
cdrom[i].img_fp = NULL;
|
||||
cdrom[i].priv = NULL;
|
||||
cdrom[i].ops = NULL;
|
||||
cdrom[i].image = NULL;
|
||||
cdrom[i].insert = NULL;
|
||||
cdrom[i].close = NULL;
|
||||
cdrom[i].get_volume = NULL;
|
||||
cdrom[i].get_channel = NULL;
|
||||
}
|
||||
memcpy(zip_drives, temp_zip_drives, ZIP_NUM * sizeof(zip_drive_t));
|
||||
for (i = 0; i < ZIP_NUM; i++) {
|
||||
zip_drives[i].f = NULL;
|
||||
zip_drives[i].priv = NULL;
|
||||
}
|
||||
|
||||
/* Mark configuration as changed. */
|
||||
config_changed = 1;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Implement the application's Status Bar.
|
||||
*
|
||||
* Version: @(#)win_stbar.c 1.0.23 2018/10/26
|
||||
* Version: @(#)win_stbar.c 1.0.24 2018/10/28
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
@@ -780,7 +780,7 @@ ui_sb_mount_zip_img(uint8_t id, int part, uint8_t wp, wchar_t *file_name)
|
||||
zip_t *dev = (zip_t *) zip_drives[id].priv;
|
||||
|
||||
zip_disk_close(dev);
|
||||
zip_drives[id].ui_writeprot = wp;
|
||||
zip_drives[id].read_only = wp;
|
||||
zip_load(dev, file_name);
|
||||
zip_insert(dev);
|
||||
if (sb_ready) {
|
||||
@@ -906,8 +906,6 @@ StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
if (!file_dlg_w_st(hwnd, IDS_2075, cdrom[id].image_path, 0)) {
|
||||
cdrom[id].prev_host_drive = cdrom[id].host_drive;
|
||||
wcscpy(temp_path, wopenfilestring);
|
||||
if (!cdrom[id].prev_image_path)
|
||||
cdrom[id].prev_image_path = (wchar_t *) malloc(1024 * sizeof(wchar_t));
|
||||
wcscpy(cdrom[id].prev_image_path, cdrom[id].image_path);
|
||||
if (cdrom[id].ops && cdrom[id].ops->exit)
|
||||
cdrom[id].ops->exit(&(cdrom[id]));
|
||||
|
||||
@@ -870,7 +870,7 @@ ui_init(int nCmdShow)
|
||||
plat_resize(scrnsz_x, scrnsz_y);
|
||||
|
||||
/* Fire up the machine. */
|
||||
pc_reset_hard();
|
||||
pc_reset_hard_init();
|
||||
|
||||
/* Set the PAUSE mode depending on the renderer. */
|
||||
plat_pause(0);
|
||||
|
||||
Reference in New Issue
Block a user