Split generic CD-ROM from SCSI-style CD-ROM;

Redid the way SCSI and ATAPI devices are handled;
Slight timings change in the NCR 5380;
Devices are now closed by device_close_all() in the reverse order of the one in which they were started;
Slight changes to some code in win/;
Added the WM_HARDRESET and WM_SHUTDOWN window messages for configuration manager purposes.
This commit is contained in:
OBattler
2018-10-10 22:33:24 +02:00
parent 173b1f7694
commit 6155802b59
36 changed files with 4557 additions and 4792 deletions

View File

@@ -106,8 +106,7 @@ STUFF :=
# -DENABLE_BUSLOGIC_LOG=N sets logging level at N.
# -DENABLE_NCR5380_LOG=N sets logging level at N.
# -DENABLE_NCR53C810_LOG=N sets logging level at N.
# -DENABLE_SCSI_LOG=N sets logging level at N.
# -DENABLE_SCSI_BUS_LOG=N sets logging level at N.
# -DENABLE_SCSI_CDROM_LOG=N sets logging level at N.
# -DENABLE_SCSI_DISK_LOG=N sets logging level at N.
# -DENABLE_X54X_LOG=N sets logging level at N.
# sound/ logging:

File diff suppressed because it is too large Load Diff

View File

@@ -6,10 +6,9 @@
*
* This file is part of the 86Box distribution.
*
* Implementation of the CD-ROM drive with SCSI(-like)
* commands, for both ATAPI and SCSI usage.
* Generic CD-ROM drive core header.
*
* Version: @(#)cdrom.h 1.0.13 2018/06/18
* Version: @(#)cdrom.h 1.0.14 2018/10/09
*
* Author: Miran Grca, <mgrca8@gmail.com>
*
@@ -27,21 +26,10 @@
#define CD_STATUS_PAUSED 3
#define CD_STATUS_STOPPED 4
#define CDROM_PHASE_IDLE 0x00
#define CDROM_PHASE_COMMAND 0x01
#define CDROM_PHASE_COMPLETE 0x02
#define CDROM_PHASE_DATA_IN 0x03
#define CDROM_PHASE_DATA_IN_DMA 0x04
#define CDROM_PHASE_DATA_OUT 0x05
#define CDROM_PHASE_DATA_OUT_DMA 0x06
#define CDROM_PHASE_ERROR 0x80
#define BUF_SIZE 32768
#define CDROM_IMAGE 200
#define CDROM_TIME (5LL * 100LL * (1LL << TIMER_SHIFT))
enum {
CDROM_BUS_DISABLED = 0,
@@ -73,116 +61,67 @@ typedef struct {
} CDROM;
typedef struct {
int host_drive;
int prev_host_drive;
CDROM *handler;
unsigned int bus_type; /* 0 = ATAPI, 1 = SCSI */
int16_t cd_buffer[BUF_SIZE];
uint8_t speed, ide_channel,
bus_mode; /* Bit 0 = PIO suported;
pad, bus_mode; /* Bit 0 = PIO suported;
Bit 1 = DMA supportd. */
int host_drive, prev_host_drive,
cd_status, prev_status,
cd_buflen, cd_state,
handler_inited, cur_speed,
id;
unsigned int scsi_device_id, sound_on;
unsigned int bus_type, /* 0 = ATAPI, 1 = SCSI */
scsi_device_id, sound_on;
uint32_t seek_pos, seek_diff,
cd_end, cdrom_capacity;
void *p;
void (*insert)(void *p);
uint32_t (*get_volume)(void *p, int channel);
uint32_t (*get_channel)(void *p, int channel);
void (*close)(void *p);
} cdrom_drive_t;
typedef struct {
mode_sense_pages_t ms_pages_saved;
CDROM *handler;
cdrom_drive_t *drv;
uint8_t previous_command,
error, features,
status, phase,
id, *buffer,
atapi_cdb[16],
current_cdb[16],
sense[256];
uint16_t request_length, max_transfer_len;
int16_t cd_buffer[BUF_SIZE];
int media_status, is_dma,
packet_status, requested_blocks,
current_page_len, current_page_pos,
mode_select_phase, do_page_save,
total_length, written_length,
callback, data_pos,
cd_status, prev_status,
unit_attention, request_pos,
total_read, cur_speed,
block_total, all_blocks_total,
old_len, block_descriptor_len,
init_length, last_subchannel_pos,
cd_buflen, cd_state,
handler_inited, disc_changed;
uint32_t sector_pos, sector_len,
seek_pos, seek_diff,
pos, packet_len,
cdb_len, cd_end,
cdrom_capacity;
uint64_t current_page_code;
} cdrom_t;
typedef struct {
int image_is_iso;
wchar_t image_path[1024],
*prev_image_path;
FILE* image;
int image_is_iso;
} cdrom_image_t;
extern cdrom_t *cdrom[CDROM_NUM];
extern cdrom_drive_t cdrom_drives[CDROM_NUM];
extern cdrom_image_t cdrom_image[CDROM_NUM];
extern uint8_t atapi_cdrom_drives[8];
extern uint8_t scsi_cdrom_drives[16];
#define cdrom_sense_error dev->sense[0]
#define cdrom_sense_key dev->sense[2]
#define cdrom_asc dev->sense[12]
#define cdrom_ascq dev->sense[13]
#define cdrom_drive cdrom_drives[id].host_drive
#ifdef __cplusplus
extern "C" {
#endif
extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length, void *priv);
extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length, void *priv);
extern void (*ide_bus_master_set_irq)(int channel, void *priv);
extern void *ide_bus_master_priv[2];
extern uint32_t cdrom_mode_sense_get_channel(cdrom_t *dev, int channel);
extern uint32_t cdrom_mode_sense_get_volume(cdrom_t *dev, int channel);
extern void build_atapi_cdrom_map(void);
extern void build_scsi_cdrom_map(void);
extern int cdrom_CDROM_PHASE_to_scsi(cdrom_t *dev);
extern int cdrom_atapi_phase_to_scsi(cdrom_t *dev);
extern void cdrom_command(cdrom_t *dev, uint8_t *cdb);
extern void cdrom_phase_callback(cdrom_t *dev);
extern uint32_t cdrom_read(uint8_t channel, int length);
extern void cdrom_write(uint8_t channel, uint32_t val, int length);
extern int cdrom_lba_to_msf_accurate(int lba);
extern double cdrom_get_short_seek(cdrom_drive_t *dev);
extern double cdrom_get_long_seek(cdrom_drive_t *dev);
extern double cdrom_seek_time(cdrom_drive_t *dev);
extern void cdrom_seek(cdrom_drive_t *dev, uint32_t pos);
extern int cdrom_playing_completed(cdrom_drive_t *dev);
extern void cdrom_close_handler(uint8_t id);
extern void cdrom_close(void);
extern void cdrom_reset(cdrom_t *dev);
extern void cdrom_set_signature(cdrom_t *dev);
extern void cdrom_request_sense_for_scsi(cdrom_t *dev, uint8_t *buffer, uint8_t alloc_length);
extern void cdrom_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks);
extern void cdrom_insert(cdrom_t *dev);
extern int find_cdrom_for_scsi_id(uint8_t scsi_id);
extern int cdrom_read_capacity(cdrom_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len);
extern void cdrom_global_init(void);
extern void cdrom_global_reset(void);
extern void cdrom_hard_reset(void);
extern void scsi_cdrom_drive_reset(int c);
#ifdef __cplusplus
}

View File

@@ -8,7 +8,7 @@
*
* CD-ROM image support.
*
* Version: @(#)cdrom_image.cc 1.0.1 2018/10/02
* Version: @(#)cdrom_image.cc 1.0.2 2018/10/09
*
* Author: RichardG867,
* Miran Grca, <mgrca8@gmail.com>
@@ -138,10 +138,10 @@ cdrom_image_log(const char *format, ...)
int
image_audio_callback(uint8_t id, int16_t *output, int len)
{
cdrom_t *dev = cdrom[id];
cdrom_drive_t *dev = &cdrom_drives[id];
int ret = 1;
if (!cdrom_drives[id].sound_on || (dev->cd_state != CD_PLAYING) || cdrom_image[id].image_is_iso) {
if (!dev->sound_on || (dev->cd_state != CD_PLAYING) || cdrom_image[id].image_is_iso) {
cdrom_image_log("image_audio_callback(i): Not playing\n", id);
if (dev->cd_state == CD_PLAYING)
dev->seek_pos += (len >> 11);
@@ -179,7 +179,7 @@ image_audio_callback(uint8_t id, int16_t *output, int len)
void
image_audio_stop(uint8_t id)
{
cdrom_t *dev = cdrom[id];
cdrom_drive_t *dev = &cdrom_drives[id];
dev->cd_state = CD_STOPPED;
}
@@ -188,7 +188,7 @@ image_audio_stop(uint8_t id)
static uint8_t
image_playaudio(uint8_t id, uint32_t pos, uint32_t len, int ismsf)
{
cdrom_t *dev = cdrom[id];
cdrom_drive_t *dev = &cdrom_drives[id];
if (!cdimg[id])
return 0;
int number;
@@ -245,7 +245,7 @@ image_playaudio(uint8_t id, uint32_t pos, uint32_t len, int ismsf)
static void
image_pause(uint8_t id)
{
cdrom_t *dev = cdrom[id];
cdrom_drive_t *dev = &cdrom_drives[id];
if (!cdimg[id] || cdrom_image[id].image_is_iso) return;
if (dev->cd_state == CD_PLAYING)
@@ -256,7 +256,7 @@ image_pause(uint8_t id)
static void
image_resume(uint8_t id)
{
cdrom_t *dev = cdrom[id];
cdrom_drive_t *dev = &cdrom_drives[id];
if (!cdimg[id] || cdrom_image[id].image_is_iso)
return;
@@ -268,7 +268,7 @@ image_resume(uint8_t id)
static void
image_stop(uint8_t id)
{
cdrom_t *dev = cdrom[id];
cdrom_drive_t *dev = &cdrom_drives[id];
if (!cdimg[id] || cdrom_image[id].image_is_iso)
return;
@@ -322,7 +322,7 @@ image_medium_changed(uint8_t id)
static uint8_t
image_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf)
{
cdrom_t *dev = cdrom[id];
cdrom_drive_t *dev = &cdrom_drives[id];
uint8_t ret;
int pos = 0;
uint32_t cdpos;
@@ -837,7 +837,7 @@ image_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdr
static uint32_t
image_size(uint8_t id)
{
cdrom_t *dev = cdrom[id];
cdrom_drive_t *dev = &cdrom_drives[id];
return dev->cdrom_capacity;
}
@@ -987,7 +987,7 @@ image_readtoc_raw(uint8_t id, unsigned char *b, int maxlen)
static int
image_status(uint8_t id)
{
cdrom_t *dev = cdrom[id];
cdrom_drive_t *dev = &cdrom_drives[id];
if (!cdimg[id])
return CD_STATUS_EMPTY;
@@ -1021,7 +1021,7 @@ image_reset(UNUSED(uint8_t id))
void
image_close(uint8_t id)
{
cdrom_t *dev = cdrom[id];
cdrom_drive_t *dev = &cdrom_drives[id];
dev->cd_state = CD_STOPPED;
if (cdimg[id]) {
@@ -1034,7 +1034,7 @@ image_close(uint8_t id)
int
image_open(uint8_t id, wchar_t *fn)
{
cdrom_t *dev = cdrom[id];
cdrom_drive_t *dev = &cdrom_drives[id];
wcscpy(cdrom_image[id].image_path, fn);
@@ -1049,14 +1049,14 @@ image_open(uint8_t id, wchar_t *fn)
if (!cdimg[id]->SetDevice(afn, false)) {
image_close(id);
cdrom_set_null_handler(id);
cdrom_image_log("[f] image_open(): cdrom[%i]->handler = %08X\n", id, cdrom[id]->handler);
cdrom_image_log("[f] image_open(): cdrom_drives[%i].handler = %08X\n", id, cdrom_drives[id].handler);
return 1;
}
dev->cd_state = CD_STOPPED;
dev->seek_pos = 0;
dev->cd_buflen = 0;
dev->cdrom_capacity = image_get_last_block(id) + 1;
cdrom[id]->handler = &image_cdrom;
cdrom_drives[id].handler = &image_cdrom;
return 0;
}
@@ -1065,7 +1065,7 @@ image_open(uint8_t id, wchar_t *fn)
static void
image_exit(uint8_t id)
{
cdrom_t *dev = cdrom[id];
cdrom_drive_t *dev = &cdrom_drives[id];
dev->handler_inited = 0;
}

View File

@@ -9,7 +9,7 @@
* Implementation of the CD-ROM null interface for unmounted
* guest CD-ROM drives.
*
* Version: @(#)cdrom_null.c 1.0.8 2018/10/02
* Version: @(#)cdrom_null.c 1.0.9 2018/10/09
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -134,7 +134,7 @@ null_media_type_id(uint8_t id)
void
cdrom_set_null_handler(uint8_t id)
{
cdrom[id]->handler = &null_cdrom;
cdrom_drives[id].handler = &null_cdrom;
cdrom_drives[id].host_drive = 0;
memset(cdrom_image[id].image_path, 0, sizeof(cdrom_image[id].image_path));
}

View File

@@ -9,7 +9,7 @@
* Implementation of the generic device interface to handle
* all devices attached to the emulator.
*
* Version: @(#)device.c 1.0.17 2018/10/02
* Version: @(#)device.c 1.0.18 2018/10/10
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -217,8 +217,10 @@ device_close_all(void)
{
int c;
for (c = 0; c < DEVICE_MAX; c++) {
for (c = (DEVICE_MAX - 1); c >= 0; c--) {
if (devices[c] != NULL) {
if (devices[c]->name)
devicelog("Closing device: \"%s\"...\n", devices[c]->name);
if (devices[c]->close != NULL)
devices[c]->close(device_priv[c]);
devices[c] = device_priv[c] = NULL;

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,7 @@
* Implementation of the IDE emulation for hard disks and ATAPI
* CD-ROM devices.
*
* Version: @(#)hdd_ide.h 1.0.11 2018/09/15
* Version: @(#)hdd_ide.h 1.0.12 2018/10/10
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -20,28 +20,77 @@
# define EMU_IDE_H
typedef struct {
uint8_t atastat, error,
command, fdisk;
int type, board,
irqstat, service,
blocksize, blockcount,
hdd_num, channel,
pos, sector_pos,
lba, skip512,
reset, mdma_mode,
do_initial_read;
uint32_t secount, sector,
cylinder, head,
drive, cylprecomp,
cfg_spt, cfg_hpc,
lba_addr, tracks,
spt, hpc;
enum
{
IDE_NONE = 0,
IDE_HDD,
IDE_ATAPI
};
uint16_t *buffer;
uint8_t *sector_buffer;
typedef struct {
uint8_t atastat, error,
command, fdisk;
int type, board,
irqstat, service,
blocksize, blockcount,
hdd_num, channel,
pos, sector_pos,
lba, skip512,
reset, mdma_mode,
do_initial_read;
uint32_t secount, sector,
cylinder, head,
drive, cylprecomp,
cfg_spt, cfg_hpc,
lba_addr, tracks,
spt, hpc;
uint16_t *buffer;
uint8_t *sector_buffer;
/* Stuff mostly used by ATAPI */
void *p;
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);
} ide_t;
/* Type:
0 = PIO,
1 = SDMA,
2 = MDMA,
3 = UDMA
Return:
-1 = Not supported,
Anything else = maximum mode
This will eventually be hookable. */
enum {
TYPE_PIO = 0,
TYPE_SDMA,
TYPE_MDMA,
TYPE_UDMA
};
/* Return:
0 = Not supported,
Anything else = timings
This will eventually be hookable. */
enum {
TIMINGS_DMA = 0,
TIMINGS_PIO,
TIMINGS_PIO_FC
};
extern int ideboard;
extern int ide_ter_enabled, ide_qua_enabled;
@@ -82,6 +131,7 @@ extern void ide_sec_disable(void);
extern void ide_set_callback(uint8_t channel, int64_t callback);
extern void secondary_ide_check(void);
extern void ide_padstr(char *str, const char *src, int len);
extern void ide_padstr8(uint8_t *buf, int buf_size, const char *src);
extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length, void *priv);
@@ -90,6 +140,8 @@ 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*/

View File

@@ -51,11 +51,8 @@
#define zipbufferb dev->buffer
zip_t *zip[ZIP_NUM];
zip_t *zip[ZIP_NUM] = { NULL, NULL, NULL, NULL };
zip_drive_t zip_drives[ZIP_NUM];
uint8_t atapi_zip_drives[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
uint8_t scsi_zip_drives[16] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
/* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */
@@ -456,7 +453,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);
void zip_phase_callback(zip_t *dev);
static void zip_callback(void *p);
#ifdef ENABLE_ZIP_LOG
@@ -581,43 +578,6 @@ zip_disk_close(zip_t *dev)
}
void
build_atapi_zip_map()
{
uint8_t i = 0;
memset(atapi_zip_drives, 0xff, 8);
for (i = 0; i < 8; i++)
atapi_zip_drives[i] = find_zip_for_channel(i);
}
int
find_zip_for_scsi_id(uint8_t scsi_id)
{
uint8_t i = 0;
for (i = 0; i < ZIP_NUM; i++) {
if ((zip_drives[i].bus_type == ZIP_BUS_SCSI) && (zip_drives[i].scsi_device_id == scsi_id))
return i;
}
return 0xff;
}
void
build_scsi_zip_map()
{
uint8_t i = 0;
memset(scsi_zip_drives, 0xff, 16);
for (i = 0; i < 16; i++)
scsi_zip_drives[i] = find_zip_for_scsi_id(i);
}
static void
zip_set_callback(zip_t *dev)
{
@@ -626,9 +586,11 @@ zip_set_callback(zip_t *dev)
}
void
zip_set_signature(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;
@@ -696,9 +658,11 @@ zip_current_mode(zip_t *dev)
/* Translates ATAPI status (ERR_STAT flag) to SCSI status. */
int
zip_ZIP_PHASE_to_scsi(zip_t *dev)
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
@@ -795,9 +759,10 @@ zip_mode_sense_save(zip_t *dev)
}
int
zip_read_capacity(zip_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len)
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;
if (dev->drv->is_250)
@@ -855,10 +820,10 @@ zip_mode_sense_read(zip_t *dev, uint8_t page_control, uint8_t page, uint8_t pos)
static uint32_t
zip_mode_sense(zip_t *dev, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len)
zip_mode_sense(zip_t *dev, uint8_t *buf, uint32_t pos, uint8_t page, uint8_t block_descriptor_len)
{
uint64_t pf;
uint8_t page_control = (type >> 6) & 3;
uint8_t page_control = (page >> 6) & 3;
if (dev->drv->is_250)
pf = zip_250_mode_sense_page_flags;
@@ -870,7 +835,7 @@ zip_mode_sense(zip_t *dev, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t blo
uint8_t msplen;
type &= 0x3f;
page &= 0x3f;
if (block_descriptor_len) {
if (dev->drv->is_250) {
@@ -891,8 +856,8 @@ zip_mode_sense(zip_t *dev, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t blo
}
for (i = 0; i < 0x40; i++) {
if ((type == GPMODE_ALL_PAGES) || (type == i)) {
if (pf & (1LL << dev->current_page_code)) {
if ((page == GPMODE_ALL_PAGES) || (page == i)) {
if (pf & (1LL << ((uint64_t) page))) {
buf[pos++] = zip_mode_sense_read(dev, page_control, i, 0);
msplen = zip_mode_sense_read(dev, page_control, i, 1);
buf[pos++] = msplen;
@@ -976,8 +941,8 @@ zip_command_common(zip_t *dev)
dev->status = BUSY_STAT;
dev->phase = 1;
dev->pos = 0;
if (dev->packet_status == ZIP_PHASE_COMPLETE) {
zip_phase_callback(dev);
if (dev->packet_status == PHASE_COMPLETE) {
zip_callback((void *) dev);
dev->callback = 0LL;
} else {
if (dev->drv->bus_type == ZIP_BUS_SCSI) {
@@ -1003,7 +968,7 @@ zip_command_common(zip_t *dev)
static void
zip_command_complete(zip_t *dev)
{
dev->packet_status = ZIP_PHASE_COMPLETE;
dev->packet_status = PHASE_COMPLETE;
zip_command_common(dev);
}
@@ -1011,25 +976,23 @@ zip_command_complete(zip_t *dev)
static void
zip_command_read(zip_t *dev)
{
dev->packet_status = ZIP_PHASE_DATA_IN;
dev->packet_status = PHASE_DATA_IN;
zip_command_common(dev);
dev->total_read = 0;
}
static void
zip_command_read_dma(zip_t *dev)
{
dev->packet_status = ZIP_PHASE_DATA_IN_DMA;
dev->packet_status = PHASE_DATA_IN_DMA;
zip_command_common(dev);
dev->total_read = 0;
}
static void
zip_command_write(zip_t *dev)
{
dev->packet_status = ZIP_PHASE_DATA_OUT;
dev->packet_status = PHASE_DATA_OUT;
zip_command_common(dev);
}
@@ -1037,7 +1000,7 @@ zip_command_write(zip_t *dev)
static void
zip_command_write_dma(zip_t *dev)
{
dev->packet_status = ZIP_PHASE_DATA_OUT_DMA;
dev->packet_status = PHASE_DATA_OUT_DMA;
zip_command_common(dev);
}
@@ -1088,7 +1051,6 @@ zip_data_command_finish(zip_t *dev, int len, int block_len, int alloc_len, int d
static void
zip_sense_clear(zip_t *dev, int command)
{
dev->previous_command = command;
zip_sense_key = zip_asc = zip_ascq = 0;
}
@@ -1101,7 +1063,7 @@ zip_set_phase(zip_t *dev, uint8_t phase)
if (dev->drv->bus_type != ZIP_BUS_SCSI)
return;
SCSIDevices[scsi_id].Phase = phase;
scsi_devices[scsi_id].phase = phase;
}
@@ -1232,8 +1194,6 @@ zip_data_phase_error(zip_t *dev)
static int
zip_blocks(zip_t *dev, int32_t *len, int first_batch, int out)
{
dev->data_pos = 0;
*len = 0;
if (!dev->sector_len) {
@@ -1348,11 +1308,6 @@ zip_pre_execution_check(zip_t *dev, uint8_t *cdb)
zip_sense_clear(dev, cdb[0]);
/* Next it's time for NOT READY. */
if (!ready)
dev->media_status = MEC_MEDIA_REMOVAL;
else
dev->media_status = (dev->unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE;
if ((zip_command_flags[cdb[0]] & CHECK_READY) && !ready) {
zip_log("ZIP %i: Not ready (%02X)\n", dev->id, cdb[0]);
zip_not_ready(dev);
@@ -1382,8 +1337,10 @@ zip_rezero(zip_t *dev)
void
zip_reset(zip_t *dev)
zip_reset(void *p)
{
zip_t *dev = (zip_t *) p;
zip_rezero(dev);
dev->status = 0;
dev->callback = 0LL;
@@ -1429,9 +1386,10 @@ zip_request_sense(zip_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc)
}
void
zip_request_sense_for_scsi(zip_t *dev, uint8_t *buffer, uint8_t alloc_length)
static void
zip_request_sense_for_scsi(void *p, uint8_t *buffer, uint8_t alloc_length)
{
zip_t *dev = (zip_t *) p;
int ready = 0;
ready = (dev->drv->f != NULL);
@@ -1483,9 +1441,10 @@ zip_buf_free(zip_t *dev)
}
void
zip_command(zip_t *dev, uint8_t *cdb)
static void
zip_command(void *p, uint8_t *cdb)
{
zip_t *dev = (zip_t *) p;
int pos = 0, block_desc = 0;
int ret;
int32_t len, max_len;
@@ -1497,7 +1456,7 @@ zip_command(zip_t *dev, uint8_t *cdb)
int32_t *BufLen;
if (dev->drv->bus_type == ZIP_BUS_SCSI) {
BufLen = &SCSIDevices[dev->drv->scsi_device_id].BufferLength;
BufLen = &scsi_devices[dev->drv->scsi_device_id].buffer_length;
dev->status &= ~ERR_STAT;
} else {
BufLen = &blen;
@@ -1507,8 +1466,6 @@ zip_command(zip_t *dev, uint8_t *cdb)
dev->packet_len = 0;
dev->request_pos = 0;
dev->data_pos = 0;
memcpy(dev->current_cdb, cdb, 12);
if (cdb[0] != 0) {
@@ -1597,7 +1554,7 @@ zip_command(zip_t *dev, uint8_t *cdb)
if (!max_len) {
zip_set_phase(dev, SCSI_PHASE_STATUS);
dev->packet_status = ZIP_PHASE_COMPLETE;
dev->packet_status = PHASE_COMPLETE;
dev->callback = 20LL * ZIP_TIME;
zip_set_callback(dev);
break;
@@ -1650,7 +1607,7 @@ zip_command(zip_t *dev, uint8_t *cdb)
if (!dev->sector_len) {
zip_set_phase(dev, SCSI_PHASE_STATUS);
/* zip_log("ZIP %i: All done - callback set\n", dev->id); */
dev->packet_status = ZIP_PHASE_COMPLETE;
dev->packet_status = PHASE_COMPLETE;
dev->callback = 20LL * ZIP_TIME;
zip_set_callback(dev);
break;
@@ -1677,8 +1634,7 @@ zip_command(zip_t *dev, uint8_t *cdb)
zip_data_command_finish(dev, alloc_length, 512, alloc_length, 0);
dev->all_blocks_total = dev->block_total;
if (dev->packet_status != ZIP_PHASE_COMPLETE)
if (dev->packet_status != PHASE_COMPLETE)
ui_sb_update_icon(SB_ZIP | dev->id, 1);
else
ui_sb_update_icon(SB_ZIP | dev->id, 0);
@@ -1743,7 +1699,7 @@ zip_command(zip_t *dev, uint8_t *cdb)
if (!dev->sector_len) {
zip_set_phase(dev, SCSI_PHASE_STATUS);
/* zip_log("ZIP %i: All done - callback set\n", dev->id); */
dev->packet_status = ZIP_PHASE_COMPLETE;
dev->packet_status = PHASE_COMPLETE;
dev->callback = 20LL * ZIP_TIME;
zip_set_callback(dev);
break;
@@ -1764,8 +1720,7 @@ zip_command(zip_t *dev, uint8_t *cdb)
zip_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1);
dev->all_blocks_total = dev->block_total;
if (dev->packet_status != ZIP_PHASE_COMPLETE)
if (dev->packet_status != PHASE_COMPLETE)
ui_sb_update_icon(SB_ZIP | dev->id, 1);
else
ui_sb_update_icon(SB_ZIP | dev->id, 0);
@@ -1805,7 +1760,7 @@ zip_command(zip_t *dev, uint8_t *cdb)
if (!dev->sector_len) {
zip_set_phase(dev, SCSI_PHASE_STATUS);
/* zip_log("ZIP %i: All done - callback set\n", dev->id); */
dev->packet_status = ZIP_PHASE_COMPLETE;
dev->packet_status = PHASE_COMPLETE;
dev->callback = 20LL * ZIP_TIME;
zip_set_callback(dev);
break;
@@ -1826,8 +1781,7 @@ zip_command(zip_t *dev, uint8_t *cdb)
zip_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1);
dev->all_blocks_total = dev->block_total;
if (dev->packet_status != ZIP_PHASE_COMPLETE)
if (dev->packet_status != PHASE_COMPLETE)
ui_sb_update_icon(SB_ZIP | dev->id, 1);
else
ui_sb_update_icon(SB_ZIP | dev->id, 0);
@@ -1850,10 +1804,7 @@ zip_command(zip_t *dev, uint8_t *cdb)
zip_buf_alloc(dev, 65536);
}
dev->current_page_code = cdb[2] & 0x3F;
zip_log("Mode sense page: %02X\n", dev->current_page_code);
if (!(zip_mode_sense_page_flags & (1LL << dev->current_page_code))) {
if (!(zip_mode_sense_page_flags & (1LL << (uint64_t) (cdb[2] & 0x3f)))) {
zip_invalid_field(dev);
zip_buf_free(dev);
return;
@@ -1905,8 +1856,6 @@ zip_command(zip_t *dev, uint8_t *cdb)
dev->total_length = len;
dev->do_page_save = cdb[1] & 1;
dev->current_page_pos = 0;
zip_data_command_finish(dev, len, len, len, 1);
return;
@@ -2335,11 +2284,11 @@ zip_pio_request(zip_t *dev, uint8_t out)
zip_log("ZIP %i: Packet length %i, request length %i\n", dev->id, dev->packet_len,
dev->max_transfer_len);
dev->packet_status = out ? ZIP_PHASE_DATA_OUT : ZIP_PHASE_DATA_IN;
dev->packet_status = out ? PHASE_DATA_OUT : PHASE_DATA_IN;
dev->status = BUSY_STAT;
dev->phase = 1;
zip_phase_callback(dev);
zip_callback((void *) dev);
dev->callback = 0LL;
zip_set_callback(dev);
@@ -2349,22 +2298,17 @@ zip_pio_request(zip_t *dev, uint8_t out)
static int
zip_read_from_ide_dma(uint8_t channel)
zip_read_from_ide_dma(zip_t *dev)
{
zip_t *dev;
uint8_t id = atapi_zip_drives[channel];
int ret;
if (id > ZIP_NUM)
if (!dev)
return 0;
dev = zip[id];
if (ide_bus_master_write) {
ret = ide_bus_master_write(channel >> 1,
ret = ide_bus_master_write(dev->drv->ide_channel >> 1,
zipbufferb, dev->packet_len,
ide_bus_master_priv[channel >> 1]);
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. */
@@ -2380,18 +2324,14 @@ zip_read_from_ide_dma(uint8_t channel)
static int
zip_read_from_scsi_dma(uint8_t scsi_id)
{
zip_t *dev;
zip_t *dev = (zip_t *) scsi_devices[scsi_id].p;
int32_t *BufLen = &scsi_devices[scsi_id].buffer_length;
uint8_t id = scsi_zip_drives[scsi_id];
int32_t *BufLen = &SCSIDevices[scsi_id].BufferLength;
if (id > ZIP_NUM)
if (!dev)
return 0;
dev = zip[id];
zip_log("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen);
memcpy(zipbufferb, SCSIDevices[scsi_id].CmdBuffer, *BufLen);
memcpy(zipbufferb, scsi_devices[scsi_id].cmd_buffer, *BufLen);
return 1;
}
@@ -2407,13 +2347,13 @@ zip_irq_raise(zip_t *dev)
static int
zip_read_from_dma(zip_t *dev)
{
int32_t *BufLen = &SCSIDevices[dev->drv->scsi_device_id].BufferLength;
int32_t *BufLen = &scsi_devices[dev->drv->scsi_device_id].buffer_length;
int ret = 0;
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->drv->ide_channel);
ret = zip_read_from_ide_dma(dev);
if (ret != 1)
return ret;
@@ -2433,24 +2373,17 @@ zip_read_from_dma(zip_t *dev)
static int
zip_write_to_ide_dma(uint8_t channel)
zip_write_to_ide_dma(zip_t *dev)
{
zip_t *dev;
uint8_t id = atapi_zip_drives[channel];
int ret;
if (id > ZIP_NUM) {
zip_log("ZIP %i: Drive not found\n", id);
if (!dev)
return 0;
}
dev = zip[id];
if (ide_bus_master_read) {
ret = ide_bus_master_read(channel >> 1,
ret = ide_bus_master_read(dev->drv->ide_channel >> 1,
zipbufferb, dev->packet_len,
ide_bus_master_priv[channel >> 1]);
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. */
@@ -2466,26 +2399,17 @@ zip_write_to_ide_dma(uint8_t channel)
static int
zip_write_to_scsi_dma(uint8_t scsi_id)
{
zip_t *dev;
zip_t *dev = (zip_t *) scsi_devices[scsi_id].p;
int32_t *BufLen = &scsi_devices[scsi_id].buffer_length;
uint8_t id = scsi_zip_drives[scsi_id];
int32_t *BufLen = &SCSIDevices[scsi_id].BufferLength;
if (id > ZIP_NUM)
if (!dev)
return 0;
dev = zip[id];
zip_log("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen);
memcpy(SCSIDevices[scsi_id].CmdBuffer, zipbufferb, *BufLen);
zip_log("ZIP %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", id,
memcpy(scsi_devices[scsi_id].cmd_buffer, zipbufferb, *BufLen);
zip_log("ZIP %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id,
zipbufferb[0], zipbufferb[1], zipbufferb[2], zipbufferb[3], zipbufferb[4], zipbufferb[5],
zipbufferb[6], zipbufferb[7]);
zip_log("ZIP %i: Data from SCSI DMA : %02X %02X %02X %02X %02X %02X %02X %02X\n", id,
SCSIDevices[scsi_id].CmdBuffer[0], SCSIDevices[scsi_id].CmdBuffer[1],
SCSIDevices[scsi_id].CmdBuffer[2], SCSIDevices[scsi_id].CmdBuffer[3],
SCSIDevices[scsi_id].CmdBuffer[4], SCSIDevices[scsi_id].CmdBuffer[5],
SCSIDevices[scsi_id].CmdBuffer[6], SCSIDevices[scsi_id].CmdBuffer[7]);
return 1;
}
@@ -2493,14 +2417,14 @@ zip_write_to_scsi_dma(uint8_t scsi_id)
static int
zip_write_to_dma(zip_t *dev)
{
int32_t *BufLen = &SCSIDevices[dev->drv->scsi_device_id].BufferLength;
int32_t *BufLen = &scsi_devices[dev->drv->scsi_device_id].buffer_length;
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->drv->ide_channel);
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);
@@ -2511,40 +2435,41 @@ zip_write_to_dma(zip_t *dev)
}
void
zip_phase_callback(zip_t *dev)
static void
zip_callback(void *p)
{
zip_t *dev = (zip_t *) p;
int ret;
switch(dev->packet_status) {
case ZIP_PHASE_IDLE:
zip_log("ZIP %i: ZIP_PHASE_IDLE\n", dev->id);
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);
return;
case ZIP_PHASE_COMMAND:
zip_log("ZIP %i: ZIP_PHASE_COMMAND\n", dev->id);
case PHASE_COMMAND:
zip_log("ZIP %i: PHASE_COMMAND\n", dev->id);
dev->status = BUSY_STAT | (dev->status & ERR_STAT);
memcpy(dev->atapi_cdb, zipbufferb, 12);
zip_command(dev, dev->atapi_cdb);
return;
case ZIP_PHASE_COMPLETE:
zip_log("ZIP %i: ZIP_PHASE_COMPLETE\n", dev->id);
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);
return;
case ZIP_PHASE_DATA_OUT:
zip_log("ZIP %i: ZIP_PHASE_DATA_OUT\n", dev->id);
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);
return;
case ZIP_PHASE_DATA_OUT_DMA:
zip_log("ZIP %i: ZIP_PHASE_DATA_OUT_DMA\n", dev->id);
case PHASE_DATA_OUT_DMA:
zip_log("ZIP %i: PHASE_DATA_OUT_DMA\n", dev->id);
ret = zip_read_from_dma(dev);
if ((ret == 1) || (dev->drv->bus_type == ZIP_BUS_SCSI)) {
@@ -2559,14 +2484,14 @@ zip_phase_callback(zip_t *dev)
zip_buf_free(dev);
}
return;
case ZIP_PHASE_DATA_IN:
zip_log("ZIP %i: ZIP_PHASE_DATA_IN\n", dev->id);
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);
return;
case ZIP_PHASE_DATA_IN_DMA:
zip_log("ZIP %i: ZIP_PHASE_DATA_IN_DMA\n", dev->id);
case PHASE_DATA_IN_DMA:
zip_log("ZIP %i: PHASE_DATA_IN_DMA\n", dev->id);
ret = zip_write_to_dma(dev);
if ((ret == 1) || (dev->drv->bus_type == ZIP_BUS_SCSI)) {
@@ -2581,8 +2506,8 @@ zip_phase_callback(zip_t *dev)
zip_buf_free(dev);
}
return;
case ZIP_PHASE_ERROR:
zip_log("ZIP %i: ZIP_PHASE_ERROR\n", dev->id);
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;
@@ -2593,23 +2518,19 @@ zip_phase_callback(zip_t *dev)
}
uint32_t
zip_read(uint8_t channel, int length)
static uint32_t
zip_packet_read(void *p, int length)
{
zip_t *dev;
zip_t *dev = (zip_t *) p;
uint16_t *zipbufferw;
uint32_t *zipbufferl;
uint8_t id = atapi_zip_drives[channel];
uint32_t temp = 0;
if (id > ZIP_NUM)
if (!dev)
return 0;
dev = zip[id];
zipbufferw = (uint16_t *) zipbufferb;
zipbufferl = (uint32_t *) zipbufferb;
@@ -2639,39 +2560,29 @@ zip_read(uint8_t channel, int length)
return 0;
}
if (dev->packet_status == ZIP_PHASE_DATA_IN) {
zip_log("ZIP %i: Returning: %04X (buffer position: %05i, request position: %05i)\n",
id, temp, (dev->pos - 2) & 0xffff, (dev->request_pos - 2) & 0xffff);
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_log("ZIP %i: Issuing read callback\n", id);
zip_pio_request(dev, 0);
}
return temp;
} else {
zip_log("ZIP %i: Returning: 0000 (buffer position: %05i, request position: %05i)\n",
id, (dev->pos - 2) & 0xffff, (dev->request_pos - 2) & 0xffff);
} else
return 0;
}
}
void
zip_write(uint8_t channel, uint32_t val, int length)
static void
zip_packet_write(void *p, uint32_t val, int length)
{
zip_t *dev;
zip_t *dev = (zip_t *) p;
uint16_t *zipbufferw;
uint32_t *zipbufferl;
uint8_t id = atapi_zip_drives[channel];
if (id > ZIP_NUM)
if (!dev)
return;
dev = zip[id];
if (dev->packet_status == ZIP_PHASE_IDLE) {
if (dev->packet_status == PHASE_IDLE) {
if (!zipbufferb)
zip_buf_alloc(dev, 12);
}
@@ -2702,19 +2613,19 @@ zip_write(uint8_t channel, uint32_t val, int length)
return;
}
if (dev->packet_status == ZIP_PHASE_DATA_OUT) {
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 == ZIP_PHASE_IDLE) {
} else if (dev->packet_status == PHASE_IDLE) {
if (dev->pos >= 12) {
dev->pos = 0;
dev->status = BUSY_STAT;
dev->packet_status = ZIP_PHASE_COMMAND;
dev->packet_status = PHASE_COMMAND;
timer_process();
zip_phase_callback(dev);
zip_callback((void *) dev);
timer_update_outstanding();
}
return;
@@ -2732,19 +2643,168 @@ 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)
{
int ret;
switch(type) {
case TYPE_PIO:
ret = ide_has_dma ? 3 : 0;
break;
case TYPE_SDMA:
default:
ret = -1;
break;
case TYPE_MDMA:
ret = ide_has_dma ? -1 : 1;
break;
case TYPE_UDMA:
ret = ide_has_dma ? -1 : 2;
break;
}
return ret;
}
static int
zip_get_timings(int ide_has_dma, int type)
{
int ret;
switch(type) {
case TIMINGS_DMA:
ret = ide_has_dma ? 0x96 : 0;
break;
case TIMINGS_PIO:
ret = ide_has_dma ? 0xb4 : 0;
break;
case TIMINGS_PIO_FC:
ret = ide_has_dma ? 0xb4 : 0;
break;
default:
ret = 0;
break;
}
return ret;
}
static void
zip_identify(void *p, int ide_has_dma)
{
ide_t *ide = (ide_t *) p;
zip_t *zip;
zip = (zip_t *) ide->p;
/* 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_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 */
if (zip_drives[zip->id].is_250)
zip_250_identify(ide, ide_has_dma);
else
zip_100_identify(ide);
}
static zip_t *
zip_drive_reset(int c)
{
scsi_device_t *sd;
ide_t *id;
if (!zip[c]) {
zip[c] = (zip_t *) malloc(sizeof(zip_t));
memset(zip[c], 0, sizeof(zip_t));
}
zip[c]->id = c;
if (zip_drives[c].bus_type == ZIP_BUS_SCSI) {
/* SCSI ZIP, attach to the SCSI bus. */
sd = &scsi_devices[zip_drives[c].scsi_device_id];
sd->p = zip[c];
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->type = SCSI_REMOVABLE_DISK;
} else if (zip_drives[c].bus_type == ZIP_BUS_ATAPI) {
/* ATAPI CD-ROM, attach to the IDE bus. */
id = ide_drives[zip_drives[c].ide_channel];
/* If the IDE channel is initialized, we attach to it,
otherwise, we do nothing - it's going to be a drive
that's not attached to anything. */
if (id) {
id->p = zip[c];
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->interrupt_drq = 1;
ide_atapi_attach(id);
}
}
return zip[c];
}
void
zip_hard_reset(void)
{
int c;
for (c = 0; c < ZIP_NUM; c++) {
if (zip_drives[c].bus_type) {
if ((zip_drives[c].bus_type == ZIP_BUS_ATAPI) || (zip_drives[c].bus_type == ZIP_BUS_SCSI)) {
zip_log("ZIP hard_reset drive=%d\n", c);
if (!zip[c]) {
zip[c] = (zip_t *) malloc(sizeof(zip_t));
memset(zip[c], 0, sizeof(zip_t));
}
/* Make sure to ignore any SCSI ZIP drive that has an out of range ID. */
if ((zip_drives[c].bus_type == ZIP_BUS_SCSI) && (zip_drives[c].scsi_device_id > SCSI_ID_MAX))
continue;
/* Make sure to ignore any ATAPI ZIP drive that has an out of range IDE channel. */
if ((zip_drives[c].bus_type == ZIP_BUS_ATAPI) && (zip_drives[c].ide_channel > 7))
continue;
zip[c] = zip_drive_reset(c);
zip[c]->id = c;
zip[c]->drv = &zip_drives[c];
@@ -2755,10 +2815,13 @@ zip_hard_reset(void)
zip_load(zip[c], zip_drives[c].image_path);
zip_mode_sense_load(zip[c]);
if (zip_drives[c].bus_type == ZIP_BUS_SCSI)
zip_log("SCSI ZIP drive %i attached to SCSI ID %i\n", c, zip_drives[c].scsi_device_id);
else if (zip_drives[c].bus_type == ZIP_BUS_ATAPI)
zip_log("ATAPI ZIP drive %i attached to IDE channel %i\n", c, zip_drives[c].ide_channel);
}
}
build_atapi_zip_map();
}

View File

@@ -21,15 +21,6 @@
#define ZIP_NUM 4
#define ZIP_PHASE_IDLE 0x00
#define ZIP_PHASE_COMMAND 0x01
#define ZIP_PHASE_COMPLETE 0x02
#define ZIP_PHASE_DATA_IN 0x03
#define ZIP_PHASE_DATA_IN_DMA 0x04
#define ZIP_PHASE_DATA_OUT 0x05
#define ZIP_PHASE_DATA_OUT_DMA 0x06
#define ZIP_PHASE_ERROR 0x80
#define BUF_SIZE 32768
#define ZIP_TIME (5LL * 100LL * (1LL << TIMER_SHIFT))
@@ -70,34 +61,30 @@ typedef struct {
zip_drive_t *drv;
uint8_t previous_command,
error, features,
status, phase,
id, *buffer,
uint8_t *buffer,
atapi_cdb[16],
current_cdb[16],
sense[256];
uint8_t status, phase,
error, id,
features, pad0,
pad1, pad2;
uint16_t request_length, max_transfer_len;
int toctimes, media_status,
is_dma, requested_blocks,
current_page_len, current_page_pos,
total_length, written_length,
mode_select_phase, do_page_save,
callback, data_pos,
packet_status, unit_attention,
cdb_len_setting, cdb_len,
request_pos, total_read,
block_total, all_blocks_total,
old_len, block_descriptor_len,
init_length;
int requested_blocks, packet_status,
total_length, do_page_save,
unit_attention;
uint32_t sector_pos, sector_len,
packet_len, pos,
seek_pos;
packet_len, pos;
uint64_t current_page_code;
int64_t callback;
int request_pos, old_len;
uint32_t seek_pos;
} zip_t;
@@ -121,29 +108,14 @@ extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_leng
extern void (*ide_bus_master_set_irq)(int channel, void *priv);
extern void *ide_bus_master_priv[2];
extern void build_atapi_zip_map(void);
extern void build_scsi_zip_map(void);
extern int zip_ZIP_PHASE_to_scsi(zip_t *dev);
extern int zip_atapi_phase_to_scsi(zip_t *dev);
extern void zip_command(zip_t *dev, uint8_t *cdb);
extern void zip_phase_callback(zip_t *dev);
extern uint32_t zip_read(uint8_t channel, int length);
extern void zip_write(uint8_t channel, uint32_t val, int length);
extern void zip_disk_close(zip_t *dev);
extern void zip_disk_reload(zip_t *dev);
extern void zip_reset(zip_t *dev);
extern void zip_set_signature(zip_t *dev);
extern void zip_request_sense_for_scsi(zip_t *dev, uint8_t *buffer, uint8_t alloc_length);
extern void zip_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks);
extern void zip_insert(zip_t *dev);
extern int find_zip_for_scsi_id(uint8_t scsi_id);
extern int zip_read_capacity(zip_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len);
extern void zip_global_init(void);
extern void zip_hard_reset(void);
extern void zip_reset(void *p);
extern int zip_load(zip_t *dev, wchar_t *fn);
extern void zip_close();

View File

@@ -26,8 +26,9 @@
#include <wchar.h>
#define HAVE_STDARG_H
#include "86box.h"
#include "scsi/scsi_device.h"
#include "cdrom/cdrom.h"
#include "scsi/scsi_device.h"
#include "scsi/scsi_cdrom.h"
#include "dma.h"
#include "io.h"
#include "device.h"
@@ -825,7 +826,7 @@ piix_reset(void *p)
for (i = 0; i < CDROM_NUM; i++) {
if (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI)
cdrom_reset(cdrom[i]);
scsi_cdrom_reset(scsi_cdrom[i]);
}
for (i = 0; i < ZIP_NUM; i++) {
if (zip_drives[i].bus_type == ZIP_BUS_ATAPI)

View File

@@ -8,7 +8,7 @@
*
* Main emulator module where most things are controlled.
*
* Version: @(#)pc.c 1.0.80 2018/10/02
* Version: @(#)pc.c 1.0.81 2018/10/10
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -665,14 +665,15 @@ again2:
hdc_init(hdc_name);
scsi_card_init();
/* These now come after as they now attach to the bus. */
scsi_disk_hard_reset();
cdrom_hard_reset();
zip_hard_reset();
scsi_disk_hard_reset();
scsi_card_init();
pc_full_speed();
shadowbios = 0;
@@ -736,6 +737,10 @@ pc_reset_hard_close(void)
cdrom_close();
zip_close();
scsi_disk_close();
closeal();
}
@@ -766,15 +771,12 @@ pc_reset_hard_init(void)
/* This is needed to initialize the serial timer. */
serial_init();
cdrom_hard_reset();
zip_hard_reset();
scsi_disk_hard_reset();
/* Initialize the actual machine and its basic modules. */
machine_init();
/* Reset and reconfigure the Sound Card layer. */
sound_card_reset();
/* Reset any ISA memory cards. */
isamem_reset();
@@ -811,8 +813,11 @@ pc_reset_hard_init(void)
/* Reset and reconfigure the SCSI layer. */
scsi_card_init();
/* Reset and reconfigure the Sound Card layer. */
sound_card_reset();
cdrom_hard_reset();
zip_hard_reset();
scsi_disk_hard_reset();
/* Reset and reconfigure the Network Card layer. */
network_reset();
@@ -917,6 +922,7 @@ pc_close(thread_t *ptr)
network_close();
sound_cd_thread_end();
cdrom_close();
zip_close();

View File

@@ -8,7 +8,7 @@
*
* Handling of the SCSI controllers.
*
* Version: @(#)scsi.c 1.0.21 2018/10/02
* Version: @(#)scsi.c 1.0.22 2018/10/10
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -43,15 +43,9 @@
#endif
scsi_device_t SCSIDevices[SCSI_ID_MAX];
char scsi_fn[SCSI_NUM][512];
uint16_t scsi_disk_location[SCSI_NUM];
int scsi_card_current = 0;
int scsi_card_last = 0;
uint32_t SCSI_BufferLength;
typedef const struct {
const char *name;
@@ -83,26 +77,6 @@ static SCSI_CARD scsi_cards[] = {
};
#ifdef ENABLE_SCSI_LOG
int scsi_do_log = ENABLE_SCSI_LOG;
#endif
static void
scsi_log(const char *fmt, ...)
{
#ifdef ENABLE_SCSI_LOG
va_list ap;
if (scsi_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
#endif
}
int scsi_card_available(int card)
{
if (scsi_cards[card].device)
@@ -159,25 +133,13 @@ void scsi_card_init(void)
if (!scsi_cards[scsi_card_current].device)
return;
scsi_log("Building SCSI hard disk map...\n");
build_scsi_disk_map();
scsi_log("Building SCSI CD-ROM map...\n");
build_scsi_cdrom_map();
scsi_log("Building SCSI ZIP map...\n");
build_scsi_zip_map();
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;
for (i=0; i<SCSI_ID_MAX; i++) {
if (scsi_disks[i] != 0xff)
SCSIDevices[i].LunType = SCSI_DISK;
else if (scsi_cdrom_drives[i] != 0xff)
SCSIDevices[i].LunType = SCSI_CDROM;
else if (scsi_zip_drives[i] != 0xff)
SCSIDevices[i].LunType = SCSI_ZIP;
else
SCSIDevices[i].LunType = SCSI_NONE;
if (SCSIDevices[i].CmdBuffer)
free(SCSIDevices[i].CmdBuffer);
SCSIDevices[i].CmdBuffer = NULL;
memset(&scsi_devices[i], 0, sizeof(scsi_device_t));
scsi_devices[i].type = SCSI_NONE;
}
device_add(scsi_cards[scsi_card_current].device);

View File

@@ -11,7 +11,7 @@
* 1 - BT-545S ISA;
* 2 - BT-958D PCI
*
* Version: @(#)scsi_buslogic.c 1.0.39 2018/06/11
* Version: @(#)scsi_buslogic.c 1.0.40 2018/10/09
*
* Authors: TheCollector1995, <mariogplayer@gmail.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -556,6 +556,7 @@ BuslogicSCSIBIOSDMATransfer(ESCMD *ESCSICmd, uint8_t TargetID, int dir)
int DataLength = ESCSICmd->DataLength;
uint32_t Address;
uint32_t TransferLength;
scsi_device_t *dev = &scsi_devices[TargetID];
if (ESCSICmd->DataDirection == 0x03) {
/* Non-data command. */
@@ -567,16 +568,16 @@ BuslogicSCSIBIOSDMATransfer(ESCMD *ESCSICmd, uint8_t TargetID, int dir)
/* If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without
checking its length, so do this procedure for both read/write commands. */
if ((DataLength > 0) && (SCSIDevices[TargetID].BufferLength > 0)) {
if ((DataLength > 0) && (dev->buffer_length > 0)) {
Address = DataPointer;
TransferLength = MIN(DataLength, SCSIDevices[TargetID].BufferLength);
TransferLength = MIN(DataLength, dev->buffer_length);
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 *)SCSIDevices[TargetID].CmdBuffer, TransferLength);
DMAPageRead(Address, (uint8_t *)dev->cmd_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 *)SCSIDevices[TargetID].CmdBuffer, TransferLength);
DMAPageWrite(Address, (uint8_t *)dev->cmd_buffer, TransferLength);
}
}
}
@@ -591,6 +592,7 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u
int target_cdb_len = 12;
uint8_t target_id = 0;
int phase;
scsi_device_t *sd = &scsi_devices[ESCSICmd->TargetId];
DataInBuf[0] = DataInBuf[1] = 0;
@@ -602,9 +604,9 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u
buslogic_log("Scanning SCSI Target ID %i\n", ESCSICmd->TargetId);
SCSIDevices[ESCSICmd->TargetId].Status = SCSI_STATUS_OK;
sd->status = SCSI_STATUS_OK;
if (!scsi_device_present(ESCSICmd->TargetId)) {
if (!scsi_device_present(sd)) {
buslogic_log("SCSI Target ID %i has no device attached\n", ESCSICmd->TargetId);
DataInBuf[2] = CCB_SELECTION_TIMEOUT;
DataInBuf[3] = SCSI_STATUS_OK;
@@ -623,7 +625,7 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u
target_cdb_len = 12;
if (!scsi_device_valid(ESCSICmd->TargetId)) fatal("SCSI target on ID %02i has disappeared\n", ESCSICmd->TargetId);
if (!scsi_device_valid(sd)) fatal("SCSI target on ID %02i has disappeared\n", ESCSICmd->TargetId);
buslogic_log("SCSI target command being executed on: SCSI ID %i, SCSI LUN %i, Target %i\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit, target_id);
@@ -639,26 +641,26 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u
memcpy(temp_cdb, ESCSICmd->CDB, target_cdb_len);
}
SCSIDevices[ESCSICmd->TargetId].BufferLength = ESCSICmd->DataLength;
scsi_device_command_phase0(ESCSICmd->TargetId, temp_cdb);
sd->buffer_length = ESCSICmd->DataLength;
scsi_device_command_phase0(sd, temp_cdb);
phase = SCSIDevices[ESCSICmd->TargetId].Phase;
phase = sd->phase;
if (phase != SCSI_PHASE_STATUS) {
if (phase == SCSI_PHASE_DATA_IN)
scsi_device_command_phase1(ESCSICmd->TargetId);
scsi_device_command_phase1(sd);
BuslogicSCSIBIOSDMATransfer(ESCSICmd, ESCSICmd->TargetId, (phase == SCSI_PHASE_DATA_OUT));
if (phase == SCSI_PHASE_DATA_OUT)
scsi_device_command_phase1(ESCSICmd->TargetId);
scsi_device_command_phase1(sd);
}
x54x_buf_free(ESCSICmd->TargetId);
buslogic_log("BIOS Request complete\n");
if (SCSIDevices[ESCSICmd->TargetId].Status == SCSI_STATUS_OK) {
if (sd->status == SCSI_STATUS_OK) {
DataInBuf[2] = CCB_COMPLETE;
DataInBuf[3] = SCSI_STATUS_OK;
} else if (SCSIDevices[ESCSICmd->TargetId].Status == SCSI_STATUS_CHECK_CONDITION) {
} else if (scsi_devices[ESCSICmd->TargetId].status == SCSI_STATUS_CHECK_CONDITION) {
DataInBuf[2] = CCB_COMPLETE;
DataInBuf[3] = SCSI_STATUS_CHECK_CONDITION;
}
@@ -697,15 +699,15 @@ buslogic_cmds(void *p)
case 0x23:
memset(dev->DataBuf, 0, 8);
for (i = 8; i < 15; i++) {
dev->DataBuf[i-8] = 0;
if (scsi_device_present(i) && (i != buslogic_get_host_id(dev)))
dev->DataBuf[i-8] |= 1;
dev->DataBuf[i - 8] = 0;
if (scsi_device_present(&scsi_devices[i]) && (i != buslogic_get_host_id(dev)))
dev->DataBuf[i - 8] |= 1;
}
dev->DataReplyLeft = 8;
break;
case 0x24:
for (i=0; i<15; i++) {
if (scsi_device_present(i) && (i != buslogic_get_host_id(dev)))
for (i = 0; i < 15; i++) {
if (scsi_device_present(&scsi_devices[i]) && (i != buslogic_get_host_id(dev)))
TargetsPresentMask |= (1 << i);
}
dev->DataBuf[0] = TargetsPresentMask & 0xFF;

3091
src/scsi/scsi_cdrom.c Normal file

File diff suppressed because it is too large Load Diff

75
src/scsi/scsi_cdrom.h Normal file
View File

@@ -0,0 +1,75 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the CD-ROM drive with SCSI(-like)
* commands, for both ATAPI and SCSI usage.
*
* Version: @(#)scsi_cdrom.h 1.0.0 2018/10/09
*
* Author: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2018 Miran Grca.
*/
#ifndef EMU_SCSI_CDROM_H
#define EMU_SCSI_CDROM_H
#define CDROM_TIME (5LL * 100LL * (1LL << TIMER_SHIFT))
#ifdef SCSI_DEVICE_H
typedef struct {
/* Common block. */
mode_sense_pages_t ms_pages_saved;
cdrom_drive_t *drv;
uint8_t *buffer,
atapi_cdb[16],
current_cdb[16],
sense[256];
uint8_t status, phase,
error, id,
features, pad0,
pad1, pad2;
uint16_t request_length, max_transfer_len;
int requested_blocks, packet_status,
total_length, do_page_save,
unit_attention;
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
extern scsi_cdrom_t *scsi_cdrom[CDROM_NUM];
#define scsi_cdrom_sense_error dev->sense[0]
#define scsi_cdrom_sense_key dev->sense[2]
#define scsi_cdrom_asc dev->sense[12]
#define scsi_cdrom_ascq dev->sense[13]
#define scsi_cdrom_drive cdrom_drives[id].host_drive
extern void scsi_cdrom_reset(void *p);
#endif /*EMU_SCSI_CDROM_H*/

View File

@@ -8,7 +8,7 @@
*
* The generic SCSI device command handler.
*
* Version: @(#)scsi_device.c 1.0.17 2018/06/02
* Version: @(#)scsi_device.c 1.0.18 2018/10/10
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -25,325 +25,153 @@
#include "../disk/hdd.h"
#include "scsi.h"
#include "scsi_device.h"
#include "../cdrom/cdrom.h"
#include "../disk/zip.h"
#include "scsi_disk.h"
scsi_device_t scsi_devices[SCSI_ID_MAX];
uint8_t scsi_null_device_sense[18] = { 0x70,0,SENSE_ILLEGAL_REQUEST,0,0,0,0,0,0,0,0,0,ASC_INV_LUN,0,0,0,0,0 };
static uint8_t
scsi_device_target_command(int lun_type, uint8_t id, uint8_t *cdb)
scsi_device_target_command(scsi_device_t *dev, uint8_t *cdb)
{
switch(lun_type) {
case SCSI_DISK:
scsi_disk_command(scsi_disk[id], cdb);
return scsi_disk_err_stat_to_scsi(scsi_disk[id]);
case SCSI_CDROM:
cdrom_command(cdrom[id], cdb);
return cdrom_CDROM_PHASE_to_scsi(cdrom[id]);
case SCSI_ZIP:
zip_command(zip[id], cdb);
return zip_ZIP_PHASE_to_scsi(zip[id]);
default:
return SCSI_STATUS_CHECK_CONDITION;
}
if (dev->command && dev->err_stat_to_scsi) {
dev->command(dev->p, cdb);
return dev->err_stat_to_scsi(dev->p);
} else
return SCSI_STATUS_CHECK_CONDITION;
}
static void scsi_device_target_phase_callback(int lun_type, uint8_t id)
static void scsi_device_target_callback(scsi_device_t *dev)
{
switch(lun_type) {
case SCSI_DISK:
scsi_disk_callback(scsi_disk[id]);
break;
case SCSI_CDROM:
cdrom_phase_callback(cdrom[id]);
break;
case SCSI_ZIP:
zip_phase_callback(zip[id]);
break;
}
if (dev->callback)
dev->callback(dev->p);
return;
}
static int scsi_device_target_err_stat_to_scsi(int lun_type, uint8_t id)
static int scsi_device_target_err_stat_to_scsi(scsi_device_t *dev)
{
switch(lun_type) {
case SCSI_DISK:
return scsi_disk_err_stat_to_scsi(scsi_disk[id]);
case SCSI_CDROM:
return cdrom_CDROM_PHASE_to_scsi(cdrom[id]);
case SCSI_ZIP:
return zip_ZIP_PHASE_to_scsi(zip[id]);
default:
return SCSI_STATUS_CHECK_CONDITION;
}
if (dev->err_stat_to_scsi)
return dev->err_stat_to_scsi(dev->p);
else
return SCSI_STATUS_CHECK_CONDITION;
}
int64_t scsi_device_get_callback(uint8_t scsi_id)
int64_t scsi_device_get_callback(scsi_device_t *dev)
{
uint8_t lun_type = SCSIDevices[scsi_id].LunType;
scsi_device_data_t *sdd = (scsi_device_data_t *) dev->p;
uint8_t id = 0;
switch (lun_type)
{
case SCSI_DISK:
id = scsi_disks[scsi_id];
return scsi_disk[id]->callback;
break;
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id];
return cdrom[id]->callback;
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id];
return zip[id]->callback;
break;
default:
return -1LL;
break;
}
if (sdd)
return sdd->callback;
else
return -1LL;
}
uint8_t *scsi_device_sense(uint8_t scsi_id)
uint8_t *scsi_device_sense(scsi_device_t *dev)
{
uint8_t lun_type = SCSIDevices[scsi_id].LunType;
scsi_device_data_t *sdd = (scsi_device_data_t *) dev->p;
uint8_t id = 0;
switch (lun_type)
{
case SCSI_DISK:
id = scsi_disks[scsi_id];
return scsi_disk[id]->sense;
break;
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id];
return cdrom[id]->sense;
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id];
return zip[id]->sense;
break;
default:
return scsi_null_device_sense;
break;
}
if (sdd)
return sdd->sense;
else
return scsi_null_device_sense;
}
void scsi_device_request_sense(uint8_t scsi_id, uint8_t *buffer, uint8_t alloc_length)
void scsi_device_request_sense(scsi_device_t *dev, uint8_t *buffer, uint8_t alloc_length)
{
uint8_t lun_type = SCSIDevices[scsi_id].LunType;
uint8_t id = 0;
switch (lun_type)
{
case SCSI_DISK:
id = scsi_disks[scsi_id];
scsi_disk_request_sense_for_scsi(scsi_disk[id], buffer, alloc_length);
break;
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id];
cdrom_request_sense_for_scsi(cdrom[id], buffer, alloc_length);
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id];
zip_request_sense_for_scsi(zip[id], buffer, alloc_length);
break;
default:
memcpy(buffer, scsi_null_device_sense, alloc_length);
break;
}
if (dev->request_sense)
dev->request_sense(dev, buffer, alloc_length);
else
memcpy(buffer, scsi_null_device_sense, alloc_length);
}
void scsi_device_reset(uint8_t scsi_id)
void scsi_device_reset(scsi_device_t *dev)
{
uint8_t lun_type = SCSIDevices[scsi_id].LunType;
uint8_t id = 0;
switch (lun_type)
{
case SCSI_DISK:
id = scsi_disks[scsi_id];
scsi_disk_reset(scsi_disk[id]);
break;
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id];
cdrom_reset(cdrom[id]);
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id];
zip_reset(zip[id]);
break;
}
if (dev->reset)
dev->reset(dev->p);
}
void scsi_device_type_data(uint8_t scsi_id, uint8_t *type, uint8_t *rmb)
void scsi_device_type_data(scsi_device_t *dev, uint8_t *type, uint8_t *rmb)
{
uint8_t lun_type = SCSIDevices[scsi_id].LunType;
switch (lun_type)
{
case SCSI_DISK:
*type = *rmb = 0x00;
break;
case SCSI_CDROM:
*type = 0x05;
*rmb = 0x80;
break;
case SCSI_ZIP:
*type = 0x00;
*rmb = 0x80;
break;
default:
*type = *rmb = 0xff;
break;
}
*rmb = dev->type >> 8;
*type = dev->type & 0xff;
}
int scsi_device_read_capacity(uint8_t scsi_id, uint8_t *cdb, uint8_t *buffer, uint32_t *len)
int scsi_device_read_capacity(scsi_device_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len)
{
uint8_t lun_type = SCSIDevices[scsi_id].LunType;
uint8_t id = 0;
switch (lun_type)
{
case SCSI_DISK:
id = scsi_disks[scsi_id];
return scsi_disk_read_capacity(scsi_disk[id], cdb, buffer, len);
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id];
return cdrom_read_capacity(cdrom[id], cdb, buffer, len);
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id];
return zip_read_capacity(zip[id], cdb, buffer, len);
default:
return 0;
}
if (dev->read_capacity)
return dev->read_capacity(dev->p, cdb, buffer, len);
else
return 0;
}
int scsi_device_present(uint8_t scsi_id)
int scsi_device_present(scsi_device_t *dev)
{
uint8_t lun_type = SCSIDevices[scsi_id].LunType;
switch (lun_type)
{
case SCSI_NONE:
return 0;
default:
return 1;
}
if (dev->type == SCSI_NONE)
return 0;
else
return 1;
}
int scsi_device_valid(uint8_t scsi_id)
int scsi_device_valid(scsi_device_t *dev)
{
uint8_t lun_type = SCSIDevices[scsi_id].LunType;
uint8_t id = 0;
switch (lun_type)
{
case SCSI_DISK:
id = scsi_disks[scsi_id];
break;
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id];
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id];
break;
default:
id = 0;
break;
}
return (id == 0xFF) ? 0 : 1;
if (dev->p)
return 0;
else
return 1;
}
int scsi_device_cdb_length(uint8_t scsi_id)
int scsi_device_cdb_length(scsi_device_t *dev)
{
/* Right now, it's 12 for all devices. */
return 12;
}
void scsi_device_command_phase0(uint8_t scsi_id, uint8_t *cdb)
void scsi_device_command_phase0(scsi_device_t *dev, uint8_t *cdb)
{
uint8_t id = 0;
uint8_t lun_type = SCSIDevices[scsi_id].LunType;
switch (lun_type) {
case SCSI_DISK:
id = scsi_disks[scsi_id];
break;
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id];
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id];
break;
default:
id = 0;
SCSIDevices[scsi_id].Phase = SCSI_PHASE_STATUS;
SCSIDevices[scsi_id].Status = SCSI_STATUS_CHECK_CONDITION;
return;
if (!dev->p) {
dev->phase = SCSI_PHASE_STATUS;
dev->status = SCSI_STATUS_CHECK_CONDITION;
return;
}
/* Finally, execute the SCSI command immediately and get the transfer length. */
SCSIDevices[scsi_id].Phase = SCSI_PHASE_COMMAND;
SCSIDevices[scsi_id].Status = scsi_device_target_command(lun_type, id, cdb);
dev->phase = SCSI_PHASE_COMMAND;
dev->status = scsi_device_target_command(dev, cdb);
if (SCSIDevices[scsi_id].Phase == SCSI_PHASE_STATUS) {
if (dev->phase == SCSI_PHASE_STATUS) {
/* Command completed (either OK or error) - call the phase callback to complete the command. */
scsi_device_target_phase_callback(lun_type, id);
scsi_device_target_callback(dev);
}
/* If the phase is DATA IN or DATA OUT, finish this here. */
}
void scsi_device_command_phase1(uint8_t scsi_id)
void scsi_device_command_phase1(scsi_device_t *dev)
{
uint8_t id = 0;
uint8_t lun_type = SCSIDevices[scsi_id].LunType;
switch (lun_type) {
case SCSI_DISK:
id = scsi_disks[scsi_id];
break;
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id];
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id];
break;
default:
id = 0;
return;
}
if (!dev->p)
return;
/* Call the second phase. */
scsi_device_target_phase_callback(lun_type, id);
SCSIDevices[scsi_id].Status = scsi_device_target_err_stat_to_scsi(lun_type, id);
scsi_device_target_callback(dev);
dev->status = scsi_device_target_err_stat_to_scsi(dev);
/* Command second phase complete - call the callback to complete the command. */
scsi_device_target_phase_callback(lun_type, id);
scsi_device_target_callback(dev);
}
int32_t *scsi_device_get_buf_len(uint8_t scsi_id)
int32_t *scsi_device_get_buf_len(scsi_device_t *dev)
{
return &SCSIDevices[scsi_id].BufferLength;
return &dev->buffer_length;
}

View File

@@ -8,7 +8,7 @@
*
* Definitions for the generic SCSI device command handler.
*
* Version: @(#)scsi_device.h 1.0.10 2018/10/07
* Version: @(#)scsi_device.h 1.0.11 2018/10/09
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -250,6 +250,15 @@
#define BUS_IDLE (1 << 31)
#define PHASE_IDLE 0x00
#define PHASE_COMMAND 0x01
#define PHASE_COMPLETE 0x02
#define PHASE_DATA_IN 0x03
#define PHASE_DATA_IN_DMA 0x04
#define PHASE_DATA_OUT 0x05
#define PHASE_DATA_OUT_DMA 0x06
#define PHASE_ERROR 0x80
#define SCSI_PHASE_DATA_OUT 0
#define SCSI_PHASE_DATA_IN BUS_IO
#define SCSI_PHASE_COMMAND BUS_CD
@@ -264,28 +273,38 @@
#define MODE_SELECT_PHASE_PAGE 4
/* This is probably no longer needed. */
#if 0
typedef struct
{
int state;
int new_state;
int clear_req;
uint32_t bus_in, bus_out;
int dev_id;
uint8_t command[20];
int command_pos;
uint8_t command[20];
int data_pos;
int change_state_delay;
int new_req_delay;
int state, new_state,
clear_req, dev_id,
command_pos, data_pos,
change_state_delay,
new_req_delay;
uint32_t bus_in, bus_out;
} scsi_bus_t;
#endif
typedef struct {
uint8_t *CmdBuffer;
int LunType;
int32_t BufferLength;
uint8_t Status;
uint8_t Phase;
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)
@@ -294,15 +313,43 @@ typedef struct {
} mode_sense_pages_t;
#pragma pack(pop)
enum {
SCSI_NONE = 0,
SCSI_DISK,
SCSI_CDROM,
SCSI_ZIP
};
/* This is so we can access the common elements to all SCSI device structs
without knowing the device type. */
typedef struct {
mode_sense_pages_t ms_pages_saved;
void *p;
extern scsi_device_t SCSIDevices[SCSI_ID_MAX];
uint8_t *temp_buffer,
pad[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;
uint16_t request_length, max_transfer_len;
int requested_blocks, packet_status,
total_length, do_page_save,
unit_attention;
uint32_t sector_pos, sector_len,
packet_len, pos;
int64_t callback;
} scsi_device_data_t;
/* These are based on the INQUIRY values. */
#define SCSI_NONE 0x0060
#define SCSI_FIXED_DISK 0x0000
#define SCSI_REMOVABLE_DISK 0x8000
#define SCSI_REMOVABLE_CDROM 0x8005
extern scsi_device_t scsi_devices[SCSI_ID_MAX];
extern int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type);
@@ -312,20 +359,19 @@ extern int mode_select_init(uint8_t command, uint16_t pl_length, uint8_t do_save
extern int mode_select_terminate(int force);
extern int mode_select_write(uint8_t val);
extern uint8_t *scsi_device_sense(uint8_t id);
extern void scsi_device_type_data(uint8_t id, uint8_t *type, uint8_t *rmb);
extern int64_t scsi_device_get_callback(uint8_t scsi_id);
extern void scsi_device_request_sense(uint8_t scsi_id, uint8_t *buffer,
extern uint8_t *scsi_device_sense(scsi_device_t *dev);
extern void scsi_device_type_data(scsi_device_t *dev, uint8_t *type, uint8_t *rmb);
extern int64_t scsi_device_get_callback(scsi_device_t *dev);
extern void scsi_device_request_sense(scsi_device_t *dev, uint8_t *buffer,
uint8_t alloc_length);
extern void scsi_device_reset(uint8_t scsi_id);
extern int scsi_device_read_capacity(uint8_t id, uint8_t *cdb,
extern void scsi_device_reset(scsi_device_t *dev);
extern int scsi_device_read_capacity(scsi_device_t *dev, uint8_t *cdb,
uint8_t *buffer, uint32_t *len);
extern int scsi_device_present(uint8_t id);
extern int scsi_device_valid(uint8_t id);
extern int scsi_device_cdb_length(uint8_t id);
extern void scsi_device_command(uint8_t id, int cdb_len, uint8_t *cdb);
extern void scsi_device_command_phase0(uint8_t scsi_id, uint8_t *cdb);
extern void scsi_device_command_phase1(uint8_t scsi_id);
extern int32_t *scsi_device_get_buf_len(uint8_t scsi_id);
extern int scsi_device_present(scsi_device_t *dev);
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);
#endif /*SCSI_DEVICE_H*/

View File

@@ -30,7 +30,6 @@
#include "../plat.h"
#include "../ui.h"
#include "scsi_device.h"
#include "../cdrom/cdrom.h"
#include "scsi_disk.h"
@@ -54,12 +53,8 @@
#define scsi_disk_ascq dev->sense[13]
scsi_disk_t *scsi_disk[HDD_NUM];
uint8_t scsi_disks[16] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
scsi_disk_t *scsi_disk[HDD_NUM] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
/* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */
@@ -145,6 +140,9 @@ static const mode_sense_pages_t scsi_disk_mode_sense_pages_changeable =
} };
static void scsi_disk_callback(void *p);
#ifdef ENABLE_SCSI_DISK_LOG
int scsi_disk_do_log = ENABLE_SCSI_DISK_LOG;
#endif
@@ -166,9 +164,11 @@ scsi_disk_log(const char *fmt, ...)
/* Translates ATAPI status (ERR_STAT flag) to SCSI status. */
int
scsi_disk_err_stat_to_scsi(scsi_disk_t *dev)
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
@@ -176,48 +176,6 @@ scsi_disk_err_stat_to_scsi(scsi_disk_t *dev)
}
int
find_hdd_for_scsi_id(uint8_t scsi_id)
{
uint8_t i = 0;
for (i = 0; i < HDD_NUM; i++) {
if (wcslen(hdd[i].fn) == 0)
continue;
if ((hdd[i].spt == 0) || (hdd[i].hpc == 0) || (hdd[i].tracks == 0))
continue;
if ((hdd[i].bus == HDD_BUS_SCSI) && (hdd[i].scsi_id == scsi_id))
return i;
}
return 0xff;
}
void
scsi_loadhd(int scsi_id, int id)
{
if (! hdd_image_load(id))
scsi_disks[scsi_id] = 0xff;
}
void
build_scsi_disk_map(void)
{
uint8_t i = 0;
memset(scsi_disks, 0xff, 16);
for (i = 0; i < 16; i++) {
scsi_disks[i] = find_hdd_for_scsi_id(i);
if (scsi_disks[i] != 0xff) {
if (wcslen(hdd[scsi_disks[i]].fn) > 0)
scsi_loadhd(i, scsi_disks[i]);
}
}
}
void
scsi_disk_mode_sense_load(scsi_disk_t *dev)
{
@@ -256,9 +214,10 @@ scsi_disk_mode_sense_save(scsi_disk_t *dev)
}
int
scsi_disk_read_capacity(scsi_disk_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len)
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);
@@ -296,14 +255,14 @@ scsi_disk_mode_sense_read(scsi_disk_t *dev, uint8_t page_control, uint8_t page,
uint32_t
scsi_disk_mode_sense(scsi_disk_t *dev, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len)
scsi_disk_mode_sense(scsi_disk_t *dev, uint8_t *buf, uint32_t pos, uint8_t page, uint8_t block_descriptor_len)
{
uint8_t msplen, page_control = (type >> 6) & 3;
uint8_t msplen, page_control = (page >> 6) & 3;
int i = 0, j = 0;
int size = 0;
type &= 0x3f;
page &= 0x3f;
size = hdd_image_get_last_sector(dev->id);
@@ -319,8 +278,8 @@ scsi_disk_mode_sense(scsi_disk_t *dev, uint8_t *buf, uint32_t pos, uint8_t type,
}
for (i = 0; i < 0x40; i++) {
if ((type == GPMODE_ALL_PAGES) || (type == i)) {
if (scsi_disk_mode_sense_page_flags & (1LL << dev->current_page_code)) {
if ((page == GPMODE_ALL_PAGES) || (page == i)) {
if (scsi_disk_mode_sense_page_flags & (1LL << (uint64_t) page)) {
buf[pos++] = scsi_disk_mode_sense_read(dev, page_control, i, 0);
msplen = scsi_disk_mode_sense_read(dev, page_control, i, 1);
buf[pos++] = msplen;
@@ -340,8 +299,8 @@ scsi_disk_command_common(scsi_disk_t *dev)
{
dev->status = BUSY_STAT;
dev->phase = 1;
if (dev->packet_status == CDROM_PHASE_COMPLETE) {
scsi_disk_callback(dev);
if (dev->packet_status == PHASE_COMPLETE) {
scsi_disk_callback((void *) dev);
dev->callback = 0LL;
} else
dev->callback = -1LL; /* Speed depends on SCSI controller */
@@ -351,7 +310,7 @@ scsi_disk_command_common(scsi_disk_t *dev)
static void
scsi_disk_command_complete(scsi_disk_t *dev)
{
dev->packet_status = CDROM_PHASE_COMPLETE;
dev->packet_status = PHASE_COMPLETE;
scsi_disk_command_common(dev);
}
@@ -359,7 +318,7 @@ scsi_disk_command_complete(scsi_disk_t *dev)
static void
scsi_disk_command_read_dma(scsi_disk_t *dev)
{
dev->packet_status = CDROM_PHASE_DATA_IN_DMA;
dev->packet_status = PHASE_DATA_IN_DMA;
scsi_disk_command_common(dev);
}
@@ -367,7 +326,7 @@ scsi_disk_command_read_dma(scsi_disk_t *dev)
static void
scsi_disk_command_write_dma(scsi_disk_t *dev)
{
dev->packet_status = CDROM_PHASE_DATA_OUT_DMA;
dev->packet_status = PHASE_DATA_OUT_DMA;
scsi_disk_command_common(dev);
}
@@ -407,7 +366,7 @@ scsi_disk_set_phase(scsi_disk_t *dev, uint8_t phase)
if (dev->drv->bus != HDD_BUS_SCSI)
return;
SCSIDevices[scsi_id].Phase = phase;
scsi_devices[scsi_id].phase = phase;
}
@@ -533,9 +492,11 @@ scsi_disk_rezero(scsi_disk_t *dev)
}
void
scsi_disk_reset(scsi_disk_t *dev)
static void
scsi_disk_reset(void *p)
{
scsi_disk_t *dev = (scsi_disk_t *) p;
scsi_disk_rezero(dev);
dev->status = 0;
dev->callback = 0;
@@ -568,9 +529,11 @@ scsi_disk_request_sense(scsi_disk_t *dev, uint8_t *buffer, uint8_t alloc_length,
}
void
scsi_disk_request_sense_for_scsi(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_t *dev = (scsi_disk_t *) p;
scsi_disk_request_sense(dev, buffer, alloc_length, 0);
}
@@ -588,9 +551,10 @@ scsi_disk_set_buf_len(scsi_disk_t *dev, int32_t *BufLen, int32_t *src_len)
}
void
scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb)
static void
scsi_disk_command(void *p, uint8_t *cdb)
{
scsi_disk_t *dev = (scsi_disk_t *) p;
uint8_t *hdbufferb;
int32_t *BufLen;
int32_t len, max_len, alloc_length;
@@ -602,8 +566,8 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb)
char device_identify_ex[15] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 };
int block_desc = 0;
hdbufferb = SCSIDevices[dev->drv->scsi_id].CmdBuffer;
BufLen = &SCSIDevices[dev->drv->scsi_id].BufferLength;
hdbufferb = scsi_devices[dev->drv->scsi_id].cmd_buffer;
BufLen = &scsi_devices[dev->drv->scsi_id].buffer_length;
last_sector = hdd_image_get_last_sector(dev->id);
@@ -666,7 +630,7 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb)
if (!len) {
scsi_disk_set_phase(dev, SCSI_PHASE_STATUS);
dev->packet_status = CDROM_PHASE_COMPLETE;
dev->packet_status = PHASE_COMPLETE;
dev->callback = 20 * SCSI_TIME;
break;
}
@@ -715,7 +679,7 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb)
if ((!dev->sector_len) || (*BufLen == 0)) {
scsi_disk_set_phase(dev, SCSI_PHASE_STATUS);
scsi_disk_log("SCSI HD %i: All done - callback set\n", dev);
dev->packet_status = CDROM_PHASE_COMPLETE;
dev->packet_status = PHASE_COMPLETE;
dev->callback = 20 * SCSI_TIME;
break;
}
@@ -779,7 +743,7 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb)
if ((!dev->sector_len) || (*BufLen == 0)) {
scsi_disk_set_phase(dev, SCSI_PHASE_STATUS);
scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id);
dev->packet_status = CDROM_PHASE_COMPLETE;
dev->packet_status = PHASE_COMPLETE;
dev->callback = 20 * SCSI_TIME;
break;
}
@@ -817,7 +781,7 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb)
if ((!dev->sector_len) || (*BufLen == 0)) {
scsi_disk_set_phase(dev, SCSI_PHASE_STATUS);
scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id);
dev->packet_status = CDROM_PHASE_COMPLETE;
dev->packet_status = PHASE_COMPLETE;
dev->callback = 20 * SCSI_TIME;
break;
}
@@ -847,8 +811,6 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb)
else
len = (cdb[8] | (cdb[7] << 8));
dev->current_page_code = cdb[2] & 0x3F;
alloc_length = len;
dev->temp_buffer = (uint8_t *) malloc(65536);
@@ -909,7 +871,7 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb)
if ((!max_len) || (*BufLen == 0)) {
scsi_disk_set_phase(dev, SCSI_PHASE_STATUS);
/* scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); */
dev->packet_status = CDROM_PHASE_COMPLETE;
dev->packet_status = PHASE_COMPLETE;
dev->callback = 20 * SCSI_TIME;
break;
}
@@ -1055,8 +1017,8 @@ atapi_out:
static void
scsi_disk_phase_data_in(scsi_disk_t *dev)
{
uint8_t *hdbufferb = SCSIDevices[dev->drv->scsi_id].CmdBuffer;
int32_t *BufLen = &SCSIDevices[dev->drv->scsi_id].BufferLength;
uint8_t *hdbufferb = scsi_devices[dev->drv->scsi_id].cmd_buffer;
int32_t *BufLen = &scsi_devices[dev->drv->scsi_id].buffer_length;
if (!*BufLen) {
scsi_disk_log("scsi_disk_phase_data_in(): Buffer length is 0\n");
@@ -1108,9 +1070,9 @@ scsi_disk_phase_data_in(scsi_disk_t *dev)
static void
scsi_disk_phase_data_out(scsi_disk_t *dev)
{
uint8_t *hdbufferb = SCSIDevices[dev->drv->scsi_id].CmdBuffer;
uint8_t *hdbufferb = scsi_devices[dev->drv->scsi_id].cmd_buffer;
int i;
int32_t *BufLen = &SCSIDevices[dev->drv->scsi_id].BufferLength;
int32_t *BufLen = &scsi_devices[dev->drv->scsi_id].buffer_length;
uint32_t last_sector = hdd_image_get_last_sector(dev->id);
uint32_t c, h, s, last_to_write = 0;
uint16_t block_desc_len, pos;
@@ -1232,36 +1194,38 @@ scsi_disk_phase_data_out(scsi_disk_t *dev)
/* If the result is 1, issue an IRQ, otherwise not. */
void
scsi_disk_callback(scsi_disk_t *dev)
static void
scsi_disk_callback(void *p)
{
scsi_disk_t *dev = (scsi_disk_t *) p;
switch(dev->packet_status) {
case CDROM_PHASE_IDLE:
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);
return;
case CDROM_PHASE_COMPLETE:
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;
return;
case CDROM_PHASE_DATA_OUT_DMA:
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 = CDROM_PHASE_COMPLETE;
dev->packet_status = PHASE_COMPLETE;
dev->status = READY_STAT;
dev->phase = 3;
return;
case CDROM_PHASE_DATA_IN_DMA:
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 = CDROM_PHASE_COMPLETE;
dev->packet_status = PHASE_COMPLETE;
dev->status = READY_STAT;
dev->phase = 3;
return;
case CDROM_PHASE_ERROR:
case PHASE_ERROR:
scsi_disk_log("SCSI HD %i: PHASE_ERROR\n", dev->id);
dev->status = READY_STAT | ERR_STAT;
dev->phase = 3;
@@ -1283,20 +1247,47 @@ void
scsi_disk_hard_reset(void)
{
int c;
scsi_device_t *sd;
for (c = 0; c < HDD_NUM; c++) {
if (hdd[c].bus == HDD_BUS_SCSI) {
scsi_disk_log("SCSI disk hard_reset drive=%d\n", c);
/* Make sure to ignore any SCSI disk that has an out of range ID. */
if (hdd[c].scsi_id > SCSI_ID_MAX)
continue;
/* Make sure to ignore any SCSI disk whose image file name is empty. */
if (wcslen(hdd[c].fn) == 0)
continue;
/* Make sure to ignore any SCSI disk whose image fails to load. */
if (! hdd_image_load(c))
continue;
if (!scsi_disk[c]) {
scsi_disk[c] = (scsi_disk_t *) malloc(sizeof(scsi_disk_t));
memset(scsi_disk[c], 0, sizeof(scsi_disk_t));
}
/* SCSI disk, attach to the SCSI bus. */
sd = &scsi_devices[hdd[c].scsi_id];
sd->p = scsi_disk[c];
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->type = SCSI_FIXED_DISK;
scsi_disk[c]->id = c;
scsi_disk[c]->drv = &hdd[c];
scsi_disk_mode_sense_load(scsi_disk[c]);
scsi_disk_log("SCSI disk %i attached to SCSI ID %i\n", c, hdd[c].scsi_id);
}
}
}

View File

@@ -6,7 +6,7 @@
*
* Emulation of SCSI fixed and removable disks.
*
* Version: @(#)scsi_disk.h 1.0.5 2018/06/02
* Version: @(#)scsi_disk.h 1.0.6 2018/10/10
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2017,2018 Miran Grca.
@@ -18,43 +18,33 @@ typedef struct {
hard_disk_t *drv;
/* Stuff for SCSI hard disks. */
uint8_t status, phase,
error, id,
uint8_t *temp_buffer,
pad[16], /* This is atapi_cdb in ATAPI-supporting devices,
and pad in SCSI-only devices. */
current_cdb[16],
sense[256];
uint16_t request_length;
uint8_t status, phase,
error, id,
pad0, pad1,
pad2, pad3;
int requested_blocks, block_total,
packet_status, callback,
block_descriptor_len,
total_length, do_page_save;
uint16_t request_length, pad4;
int requested_blocks, packet_status,
total_length, do_page_save,
unit_attention;
uint32_t sector_pos, sector_len,
packet_len;
packet_len, pos;
uint64_t current_page_code;
uint8_t *temp_buffer;
int64_t callback;
} scsi_disk_t;
extern scsi_disk_t *scsi_disk[HDD_NUM];
extern uint8_t scsi_disks[16];
extern void scsi_loadhd(int scsi_id, int id);
extern void scsi_disk_global_init(void);
extern void scsi_disk_hard_reset(void);
extern void scsi_disk_close(void);
extern int scsi_disk_read_capacity(scsi_disk_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len);
extern int scsi_disk_err_stat_to_scsi(scsi_disk_t *dev);
extern int scsi_disk_phase_to_scsi(scsi_disk_t *dev);
extern int find_hdd_for_scsi_id(uint8_t scsi_id);
extern void build_scsi_disk_map(void);
extern void scsi_disk_reset(scsi_disk_t *dev);
extern void scsi_disk_request_sense_for_scsi(scsi_disk_t *dev, uint8_t *buffer, uint8_t alloc_length);
extern void scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb);
extern void scsi_disk_callback(scsi_disk_t *dev);

View File

@@ -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.20 2018/10/08
* Version: @(#)scsi_ncr5380.c 1.0.22 2018/10/09
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* TheCollector1995, <mariogplayer@gmail.com>
@@ -280,19 +280,19 @@ ncr_wait_process(ncr5380_t *ncr_dev)
if (ncr->wait_data) {
ncr->wait_data--;
if (!ncr->wait_data) {
dev = &SCSIDevices[ncr->target_id];
dev = &scsi_devices[ncr->target_id];
SET_BUS_STATE(ncr, ncr->new_phase);
if (ncr->new_phase == SCSI_PHASE_DATA_IN) {
ncr_log("Data In bus phase\n");
ncr->tx_data = dev->CmdBuffer[ncr->data_pos++];
ncr->tx_data = dev->cmd_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) {
ncr_log("Status bus phase\n");
ncr->cur_bus |= BUS_REQ;
ncr->state = STATE_STATUS;
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(dev->Status) | BUS_DBP;
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(dev->status) | BUS_DBP;
} else if (ncr->new_phase == SCSI_PHASE_MESSAGE_IN) {
ncr_log("Message In bus phase\n");
ncr->state = STATE_MESSAGEIN;
@@ -799,7 +799,7 @@ scsiat_out(uint16_t port, uint8_t val, void *priv)
{
ncr5380_t *ncr_dev = (ncr5380_t *)priv;
ncr_t *ncr = &ncr_dev->ncr;
scsi_device_t *dev = &SCSIDevices[ncr->target_id];
scsi_device_t *dev = &scsi_devices[ncr->target_id];
ncr_log("SCSI AT write=0x%03x, val=%02x\n", port, val);
switch (port & 0x0f) {
@@ -852,7 +852,7 @@ scsiat_out(uint16_t port, uint8_t val, void *priv)
if (ncr->unk_08 & 0x01)
{
ncr_dev->block_count_loaded = 1;
ncr_dev->block_count = dev->BufferLength / 128;
ncr_dev->block_count = dev->buffer_length / 128;
}
break;
@@ -875,8 +875,8 @@ ncr_callback(void *priv)
{
ncr5380_t *ncr_dev = (ncr5380_t *)priv;
ncr_t *ncr = &ncr_dev->ncr;
scsi_device_t *dev = &SCSIDevices[ncr->target_id];
int c = 0;
scsi_device_t *dev = &scsi_devices[ncr->target_id];
int req_len, c = 0;
int64_t p;
uint8_t temp, data;
@@ -887,7 +887,7 @@ ncr_callback(void *priv)
if (((ncr->state == STATE_DATAIN) || (ncr->state == STATE_DATAOUT)) && (ncr->dma_mode != DMA_IDLE))
ncr_dev->timer_period = (int64_t) ncr_dev->period;
else
ncr_dev->timer_period += 10LL * TIMER_USEC;
ncr_dev->timer_period += 40LL * TIMER_USEC;
if (ncr->dma_mode == DMA_IDLE) {
ncr->bus_host = get_bus_host(ncr);
@@ -909,7 +909,7 @@ ncr_callback(void *priv)
ncr_log("Select - target ID = %i\n", ncr->target_id);
/*Once the device has been found and selected, mark it as busy*/
if ((ncr->target_id != -1) && scsi_device_present(ncr->target_id)) {
if ((ncr->target_id != -1) && scsi_device_present(&scsi_devices[ncr->target_id])) {
ncr->cur_bus |= BUS_BSY;
ncr_log("Device found at ID %i\n", ncr->target_id);
ncr_log("Current Bus BSY=%02x\n", ncr->cur_bus);
@@ -943,35 +943,36 @@ ncr_callback(void *priv)
/*Reset data position to default*/
ncr->data_pos = 0;
dev = &SCSIDevices[ncr->target_id];
dev = &scsi_devices[ncr->target_id];
ncr_log("SCSI Command 0x%02X for ID %d, status code=%02x\n", ncr->command[0], ncr->target_id, dev->Status);
ncr_log("SCSI Command 0x%02X for ID %d, status code=%02x\n", ncr->command[0], ncr->target_id, dev->status);
dev->BufferLength = -1;
dev->buffer_length = -1;
/*Now, execute the given SCSI command*/
scsi_device_command_phase0(ncr->target_id, ncr->command);
scsi_device_command_phase0(dev, ncr->command);
ncr_log("SCSI ID %i: Command %02X: Buffer Length %i, SCSI Phase %02X\n", ncr->target_id, ncr->command[0], dev->BufferLength, dev->Phase);
ncr_log("SCSI ID %i: Command %02X: Buffer Length %i, SCSI Phase %02X\n", ncr->target_id, ncr->command[0], dev->buffer_length, dev->phase);
if (dev->Status != SCSI_STATUS_OK) {
if (dev->status != SCSI_STATUS_OK) {
ncr->new_phase = SCSI_PHASE_STATUS;
ncr->wait_data = 4;
return;
}
/*If the SCSI phase is Data In or Data Out, allocate the SCSI buffer based on the transfer length of the command*/
if (dev->BufferLength && (dev->Phase == SCSI_PHASE_DATA_IN || dev->Phase == SCSI_PHASE_DATA_OUT)) {
dev->CmdBuffer = (uint8_t *) malloc(dev->BufferLength);
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(ncr->target_id);
p = scsi_device_get_callback(dev);
req_len = MIN(64, dev->buffer_length);
if (p <= 0LL)
ncr_dev->period = 0.2 * ((double) TIMER_USEC) * ((double) MIN(64, dev->BufferLength));
ncr_dev->period = 0.2 * ((double) TIMER_USEC) * ((double) req_len);
else
ncr_dev->period = (p / ((double) dev->BufferLength)) * ((double) MIN(64, dev->BufferLength));
ncr_dev->period = (p / ((double) dev->buffer_length)) * ((double) req_len);
}
if (dev->Phase == SCSI_PHASE_DATA_OUT) {
if (dev->phase == SCSI_PHASE_DATA_OUT) {
/* Write direction commands have delayed execution - only execute them after the bus has gotten all the data from the host. */
ncr_log("Next state is data out\n");
ncr->new_phase = SCSI_PHASE_DATA_OUT;
@@ -979,23 +980,23 @@ ncr_callback(void *priv)
ncr->clear_req = 4;
} else {
/* Other command - execute immediately. */
ncr->new_phase = dev->Phase;
ncr->new_phase = dev->phase;
if (ncr->new_phase == SCSI_PHASE_DATA_IN)
scsi_device_command_phase1(ncr->target_id);
scsi_device_command_phase1(dev);
ncr->wait_data = 4;
}
}
}
} else if (ncr->state == STATE_DATAIN) {
dev = &SCSIDevices[ncr->target_id];
dev = &scsi_devices[ncr->target_id];
ncr_log("Data In ACK=%02x\n", ncr->bus_host & BUS_ACK);
if (ncr->bus_host & BUS_ACK) {
if (ncr->data_pos >= dev->BufferLength) {
if (dev->CmdBuffer != NULL) {
free(dev->CmdBuffer);
dev->CmdBuffer = NULL;
if (ncr->data_pos >= dev->buffer_length) {
if (dev->cmd_buffer != NULL) {
free(dev->cmd_buffer);
dev->cmd_buffer = NULL;
}
ncr->cur_bus &= ~BUS_REQ;
@@ -1003,7 +1004,7 @@ ncr_callback(void *priv)
ncr->wait_data = 4;
ncr->wait_complete = 8;
} else {
ncr->tx_data = dev->CmdBuffer[ncr->data_pos++];
ncr->tx_data = dev->cmd_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;
@@ -1011,18 +1012,18 @@ ncr_callback(void *priv)
}
}
} else if (ncr->state == STATE_DATAOUT) {
dev = &SCSIDevices[ncr->target_id];
dev = &scsi_devices[ncr->target_id];
ncr_log("Data Out ACK=%02x\n", ncr->bus_host & BUS_ACK);
if (ncr->bus_host & BUS_ACK) {
dev->CmdBuffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host);
dev->cmd_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host);
if (ncr->data_pos >= dev->BufferLength) {
scsi_device_command_phase1(ncr->target_id);
if (ncr->data_pos >= dev->buffer_length) {
scsi_device_command_phase1(dev);
if (dev->CmdBuffer != NULL) {
free(dev->CmdBuffer);
dev->CmdBuffer = NULL;
if (dev->cmd_buffer != NULL) {
free(dev->cmd_buffer);
dev->cmd_buffer = NULL;
}
ncr->cur_bus &= ~BUS_REQ;
@@ -1073,10 +1074,10 @@ ncr_callback(void *priv)
temp = BUS_GETDATA(ncr->bus_host);
ncr->bus_host = get_bus_host(ncr);
if (ncr->data_pos >= dev->BufferLength) {
if (dev->CmdBuffer != NULL) {
free(dev->CmdBuffer);
dev->CmdBuffer = NULL;
if (ncr->data_pos >= dev->buffer_length) {
if (dev->cmd_buffer != NULL) {
free(dev->cmd_buffer);
dev->cmd_buffer = NULL;
}
ncr->cur_bus &= ~BUS_REQ;
@@ -1084,7 +1085,7 @@ ncr_callback(void *priv)
ncr->wait_data = 4;
ncr->wait_complete = 8;
} else {
ncr->tx_data = dev->CmdBuffer[ncr->data_pos++];
ncr->tx_data = dev->cmd_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;
@@ -1139,14 +1140,14 @@ ncr_callback(void *priv)
ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK;
ncr->bus_host |= BUS_SETDATA(data);
dev->CmdBuffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host);
dev->cmd_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host);
if (ncr->data_pos >= dev->BufferLength) {
scsi_device_command_phase1(ncr->target_id);
if (ncr->data_pos >= dev->buffer_length) {
scsi_device_command_phase1(dev);
if (dev->CmdBuffer != NULL) {
free(dev->CmdBuffer);
dev->CmdBuffer = NULL;
if (dev->cmd_buffer != NULL) {
free(dev->cmd_buffer);
dev->cmd_buffer = NULL;
}
ncr->cur_bus &= ~BUS_REQ;
@@ -1196,10 +1197,10 @@ ncr_callback(void *priv)
temp = BUS_GETDATA(ncr->bus_host);
ncr->bus_host = get_bus_host(ncr);
if (ncr->data_pos >= dev->BufferLength) {
if (dev->CmdBuffer != NULL) {
free(dev->CmdBuffer);
dev->CmdBuffer = NULL;
if (ncr->data_pos >= dev->buffer_length) {
if (dev->cmd_buffer != NULL) {
free(dev->cmd_buffer);
dev->cmd_buffer = NULL;
}
ncr->cur_bus &= ~BUS_REQ;
@@ -1207,7 +1208,7 @@ ncr_callback(void *priv)
ncr->wait_data = 4;
ncr->wait_complete = 8;
} else {
ncr->tx_data = dev->CmdBuffer[ncr->data_pos++];
ncr->tx_data = dev->cmd_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;
@@ -1248,14 +1249,14 @@ ncr_callback(void *priv)
ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK;
ncr->bus_host |= BUS_SETDATA(data);
dev->CmdBuffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host);
dev->cmd_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host);
if (ncr->data_pos >= dev->BufferLength) {
scsi_device_command_phase1(ncr->target_id);
if (ncr->data_pos >= dev->buffer_length) {
scsi_device_command_phase1(dev);
if (dev->CmdBuffer != NULL) {
free(dev->CmdBuffer);
dev->CmdBuffer = NULL;
if (dev->cmd_buffer != NULL) {
free(dev->cmd_buffer);
dev->cmd_buffer = NULL;
}
ncr->cur_bus &= ~BUS_REQ;

View File

@@ -10,7 +10,7 @@
* NCR and later Symbios and LSI. This controller was designed
* for the PCI bus.
*
* Version: @(#)scsi_ncr53c810.c 1.0.14 2018/05/28
* Version: @(#)scsi_ncr53c810.c 1.0.15 2018/10/09
*
* Authors: Paul Brook (QEMU)
* Artyom Tarasenko (QEMU)
@@ -391,8 +391,10 @@ ncr53c810_soft_reset(ncr53c810_t *dev)
dev->gpreg0 = 0;
dev->sstop = 1;
for (i = 0; i < 16; i++)
scsi_device_reset(i);
/* This is *NOT* a wide SCSI controller, so do not touch
SCSI devices with ID's >= 8. */
for (i = 0; i < 8; i++)
scsi_device_reset(&scsi_devices[i]);
}
@@ -595,11 +597,9 @@ ncr53c810_do_dma(ncr53c810_t *dev, int out, uint8_t id)
uint32_t addr, tdbc;
int count;
scsi_device_t *sd;
scsi_device_t *sd = &scsi_devices[id];
sd = &SCSIDevices[id];
if ((!scsi_device_present(id))) {
if ((!scsi_device_present(sd))) {
ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Device not present when attempting to do DMA\n", id, dev->current_lun, dev->last_command);
return;
}
@@ -610,7 +610,7 @@ ncr53c810_do_dma(ncr53c810_t *dev, int out, uint8_t id)
return;
}
/* Make sure count is never bigger than BufferLength. */
/* Make sure count is never bigger than buffer_length. */
count = tdbc = dev->dbc;
if (count > dev->temp_buf_len)
count = dev->temp_buf_len;
@@ -622,13 +622,13 @@ ncr53c810_do_dma(ncr53c810_t *dev, int out, uint8_t id)
dev->dbc -= count;
if (out)
ncr53c810_read(dev, addr, sd->CmdBuffer+dev->buffer_pos, count);
ncr53c810_read(dev, addr, sd->cmd_buffer + dev->buffer_pos, count);
else {
if (!dev->buffer_pos) {
ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DI\n", id, dev->current_lun, dev->last_command);
scsi_device_command_phase1(dev->current->tag);
scsi_device_command_phase1(&scsi_devices[dev->current->tag]);
}
ncr53c810_write(dev, addr, sd->CmdBuffer+dev->buffer_pos, count);
ncr53c810_write(dev, addr, sd->cmd_buffer + dev->buffer_pos, count);
}
dev->temp_buf_len -= count;
@@ -637,13 +637,13 @@ ncr53c810_do_dma(ncr53c810_t *dev, int out, uint8_t id)
if (dev->temp_buf_len <= 0) {
if (out) {
ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DO\n", id, dev->current_lun, dev->last_command);
scsi_device_command_phase1(id);
scsi_device_command_phase1(&scsi_devices[id]);
}
if (sd->CmdBuffer != NULL) {
free(sd->CmdBuffer);
sd->CmdBuffer = NULL;
if (sd->cmd_buffer != NULL) {
free(sd->cmd_buffer);
sd->cmd_buffer = NULL;
}
ncr53c810_command_complete(dev, sd->Status);
ncr53c810_command_complete(dev, sd->status);
} else {
ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Resume SCRIPTS\n", id, dev->current_lun, dev->last_command);
dev->sstop = 0;
@@ -683,8 +683,8 @@ ncr53c810_do_command(ncr53c810_t *dev, uint8_t id)
dev->sfbr = buf[0];
dev->command_complete = 0;
sd = &SCSIDevices[id];
if (!scsi_device_present(id)) {
sd = &scsi_devices[id];
if (!scsi_device_present(sd)) {
ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Bad Selection\n", id, dev->current_lun, buf[0]);
ncr53c810_bad_selection(dev, id);
return 0;
@@ -693,46 +693,46 @@ ncr53c810_do_command(ncr53c810_t *dev, uint8_t id)
dev->current = (ncr53c810_request*)malloc(sizeof(ncr53c810_request));
dev->current->tag = id;
sd->BufferLength = -1;
sd->buffer_length = -1;
ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DBC=%i\n", id, dev->current_lun, buf[0], dev->dbc);
dev->last_command = buf[0];
scsi_device_command_phase0(dev->current->tag, buf);
scsi_device_command_phase0(&scsi_devices[dev->current->tag], buf);
dev->hba_private = (void *)dev->current;
dev->waiting = 0;
dev->buffer_pos = 0;
dev->temp_buf_len = sd->BufferLength;
dev->temp_buf_len = sd->buffer_length;
if (sd->BufferLength > 0) {
sd->CmdBuffer = (uint8_t *)malloc(sd->BufferLength);
dev->current->dma_len = sd->BufferLength;
if (sd->buffer_length > 0) {
sd->cmd_buffer = (uint8_t *)malloc(sd->buffer_length);
dev->current->dma_len = sd->buffer_length;
}
if ((sd->Phase == SCSI_PHASE_DATA_IN) && (sd->BufferLength > 0)) {
if ((sd->phase == SCSI_PHASE_DATA_IN) && (sd->buffer_length > 0)) {
ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DI\n", id, dev->current_lun, buf[0]);
ncr53c810_set_phase(dev, PHASE_DI);
p = scsi_device_get_callback(dev->current->tag);
p = scsi_device_get_callback(&scsi_devices[dev->current->tag]);
if (p <= 0LL) {
period = ((double) sd->BufferLength) * 0.1 * ((double) TIMER_USEC); /* Fast SCSI: 10000000 bytes per second */
period = ((double) sd->buffer_length) * 0.1 * ((double) TIMER_USEC); /* Fast SCSI: 10000000 bytes per second */
dev->timer_period += (int64_t) period;
} else
dev->timer_period += p;
return 1;
} else if ((sd->Phase == SCSI_PHASE_DATA_OUT) && (sd->BufferLength > 0)) {
} else if ((sd->phase == SCSI_PHASE_DATA_OUT) && (sd->buffer_length > 0)) {
ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DO\n", id, buf[0]);
ncr53c810_set_phase(dev, PHASE_DO);
p = scsi_device_get_callback(dev->current->tag);
p = scsi_device_get_callback(&scsi_devices[dev->current->tag]);
if (p <= 0LL) {
period = ((double) sd->BufferLength) * 0.1 * ((double) TIMER_USEC); /* Fast SCSI: 10000000 bytes per second */
period = ((double) sd->buffer_length) * 0.1 * ((double) TIMER_USEC); /* Fast SCSI: 10000000 bytes per second */
dev->timer_period += (int64_t) period;
} else
dev->timer_period += p;
return 1;
} else {
ncr53c810_command_complete(dev, sd->Status);
ncr53c810_command_complete(dev, sd->status);
return 0;
}
}
@@ -832,7 +832,7 @@ ncr53c810_do_msgout(ncr53c810_t *dev, uint8_t id)
uint32_t current_tag;
scsi_device_t *sd;
sd = &SCSIDevices[id];
sd = &scsi_devices[id];
current_tag = id;
@@ -884,9 +884,9 @@ ncr53c810_do_msgout(ncr53c810_t *dev, uint8_t id)
case 0x0d:
/* The ABORT TAG message clears the current I/O process only. */
ncr53c810_log("MSG: ABORT TAG tag=0x%x\n", current_tag);
if (sd->CmdBuffer) {
free(sd->CmdBuffer);
sd->CmdBuffer = NULL;
if (sd->cmd_buffer) {
free(sd->cmd_buffer);
sd->cmd_buffer = NULL;
}
ncr53c810_disconnect(dev);
break;
@@ -907,9 +907,9 @@ ncr53c810_do_msgout(ncr53c810_t *dev, uint8_t id)
ncr53c810_log("MSG: BUS DEVICE RESET tag=0x%x\n", current_tag);
/* clear the current I/O process */
if (sd->CmdBuffer) {
free(sd->CmdBuffer);
sd->CmdBuffer = NULL;
if (sd->cmd_buffer) {
free(sd->cmd_buffer);
sd->cmd_buffer = NULL;
}
ncr53c810_disconnect(dev);
break;
@@ -1078,7 +1078,7 @@ again:
}
dev->sstat0 |= NCR_SSTAT0_WOA;
dev->scntl1 &= ~NCR_SCNTL1_IARB;
if (!scsi_device_present(id)) {
if (!scsi_device_present(&scsi_devices[id])) {
ncr53c810_bad_selection(dev, id);
break;
}

View File

@@ -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.22 2018/10/02
* Version: @(#)scsi_x54x.c 1.0.23 2018/10/09
*
* Authors: TheCollector1995, <mariogplayer@gmail.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -155,9 +155,8 @@ clear_irq(x54x_t *dev)
static void
target_check(uint8_t id)
{
if (! scsi_device_valid(id)) {
if (! scsi_device_valid(&scsi_devices[id]))
fatal("BIOS INT13 device on ID %02i has disappeared\n", id);
}
}
@@ -237,9 +236,10 @@ x54x_bios_command_08(uint8_t id, uint8_t *buffer)
uint8_t rcbuf[8] = { 0,0,0,0,0,0,0,0 };
uint32_t len = 0;
int i, ret, sc;
scsi_device_t *sd = &scsi_devices[id];
ret = scsi_device_read_capacity(id, cdb, rcbuf, &len);
sc = completion_code(scsi_device_sense(id));
ret = scsi_device_read_capacity(sd, cdb, rcbuf, &len);
sc = completion_code(scsi_device_sense(sd));
if (ret == 0) return(sc);
memset(buffer, 0x00, 6);
@@ -261,15 +261,16 @@ x54x_bios_command_15(uint8_t id, uint8_t *buffer)
uint8_t rcbuf[8] = { 0,0,0,0,0,0,0,0 };
uint32_t len = 0;
int i, ret, sc;
scsi_device_t *sd = &scsi_devices[id];
ret = scsi_device_read_capacity(id, cdb, rcbuf, &len);
sc = completion_code(scsi_device_sense(id));
ret = scsi_device_read_capacity(sd, cdb, rcbuf, &len);
sc = completion_code(scsi_device_sense(sd));
memset(buffer, 0x00, 6);
for (i=0; i<4; i++)
buffer[i] = (ret == 0) ? 0 : rcbuf[i];
scsi_device_type_data(id, &(buffer[4]), &(buffer[5]));
scsi_device_type_data(sd, &(buffer[4]), &(buffer[5]));
x54x_log("BIOS Command 0x15: %02X %02X %02X %02X %02X %02X\n",
buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]);
@@ -308,15 +309,15 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
}
/* Get pointer to selected device. */
dev = &SCSIDevices[cmd->id];
dev->BufferLength = 0;
dev = &scsi_devices[cmd->id];
dev->buffer_length = 0;
if (! scsi_device_present(cmd->id)) {
if (! scsi_device_present(dev)) {
x54x_log("BIOS Target ID %i has no device attached\n", cmd->id);
return(0x80);
}
if ((dev->LunType == SCSI_CDROM) && !x54x->cdrom_boot) {
if ((dev->type == SCSI_REMOVABLE_CDROM) && !x54x->cdrom_boot) {
x54x_log("BIOS Target ID %i is CD-ROM on unsupported BIOS\n", cmd->id);
return(0x80);
}
@@ -326,9 +327,9 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
x54x_log("BIOS Data Buffer write: length %d, pointer 0x%04X\n",
sector_len, dma_address);
if (dev->CmdBuffer != NULL) {
free(dev->CmdBuffer);
dev->CmdBuffer = NULL;
if (dev->cmd_buffer != NULL) {
free(dev->cmd_buffer);
dev->cmd_buffer = NULL;
}
switch(cmd->command) {
@@ -343,20 +344,20 @@ 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->BufferLength = 14;
dev->CmdBuffer = (uint8_t *)malloc(14);
memset(dev->CmdBuffer, 0x00, 14);
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);
DMAPageWrite(dma_address,
scsi_device_sense(cmd->id), 14);
scsi_device_sense(dev), 14);
}
if (dev->CmdBuffer != NULL) {
free(dev->CmdBuffer);
dev->CmdBuffer = NULL;
if (dev->cmd_buffer != NULL) {
free(dev->cmd_buffer);
dev->cmd_buffer = NULL;
}
return(0);
@@ -364,7 +365,7 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
case 0x02: /* Read Desired Sectors to Memory */
target_check(cmd->id);
dev->BufferLength = -1;
dev->buffer_length = -1;
cdb[0] = GPCMD_READ_10;
cdb[1] = (cmd->lun & 7) << 5;
@@ -378,33 +379,33 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
x54x_log("BIOS CMD(READ, %08lx, %d)\n", lba, cmd->secount);
#endif
scsi_device_command_phase0(cmd->id, cdb);
scsi_device_command_phase0(dev, cdb);
if (dev->Phase == SCSI_PHASE_STATUS)
if (dev->phase == SCSI_PHASE_STATUS)
goto skip_read_phase1;
dev->CmdBuffer = (uint8_t *)malloc(dev->BufferLength);
dev->cmd_buffer = (uint8_t *)malloc(dev->buffer_length);
scsi_device_command_phase1(cmd->id);
scsi_device_command_phase1(dev);
if (sector_len > 0) {
x54x_log("BIOS DMA: Reading %i bytes at %08X\n",
dev->BufferLength, dma_address);
dev->buffer_length, dma_address);
DMAPageWrite(dma_address,
dev->CmdBuffer, dev->BufferLength);
dev->cmd_buffer, dev->buffer_length);
}
skip_read_phase1:
if (dev->CmdBuffer != NULL) {
free(dev->CmdBuffer);
dev->CmdBuffer = NULL;
if (dev->cmd_buffer != NULL) {
free(dev->cmd_buffer);
dev->cmd_buffer = NULL;
}
return(completion_code(scsi_device_sense(cmd->id)));
return(completion_code(scsi_device_sense(dev)));
case 0x03: /* Write Desired Sectors from Memory */
target_check(cmd->id);
dev->BufferLength = -1;
dev->buffer_length = -1;
cdb[0] = GPCMD_WRITE_10;
cdb[1] = (cmd->lun & 7) << 5;
@@ -418,29 +419,29 @@ skip_read_phase1:
x54x_log("BIOS CMD(WRITE, %08lx, %d)\n", lba, cmd->secount);
#endif
scsi_device_command_phase0(cmd->id, cdb);
scsi_device_command_phase0(dev, cdb);
if (dev->Phase == SCSI_PHASE_STATUS)
if (dev->phase == SCSI_PHASE_STATUS)
goto skip_write_phase1;
dev->CmdBuffer = (uint8_t *)malloc(dev->BufferLength);
dev->cmd_buffer = (uint8_t *)malloc(dev->buffer_length);
if (sector_len > 0) {
x54x_log("BIOS DMA: Reading %i bytes at %08X\n",
dev->BufferLength, dma_address);
dev->buffer_length, dma_address);
DMAPageRead(dma_address,
dev->CmdBuffer, dev->BufferLength);
dev->cmd_buffer, dev->buffer_length);
}
scsi_device_command_phase1(cmd->id);
scsi_device_command_phase1(dev);
skip_write_phase1:
if (dev->CmdBuffer != NULL) {
free(dev->CmdBuffer);
dev->CmdBuffer = NULL;
if (dev->cmd_buffer != NULL) {
free(dev->cmd_buffer);
dev->cmd_buffer = NULL;
}
return(completion_code(scsi_device_sense(cmd->id)));
return(completion_code(scsi_device_sense(dev)));
case 0x04: /* Verify Desired Sectors */
target_check(cmd->id);
@@ -454,9 +455,9 @@ skip_write_phase1:
cdb[7] = 0;
cdb[8] = sector_len;
scsi_device_command_phase0(cmd->id, cdb);
scsi_device_command_phase0(dev, cdb);
return(completion_code(scsi_device_sense(cmd->id)));
return(completion_code(scsi_device_sense(dev)));
case 0x05: /* Format Track, invalid since SCSI has no tracks */
//FIXME: add a longer delay here --FvK
@@ -472,26 +473,26 @@ skip_write_phase1:
cdb[0] = GPCMD_FORMAT_UNIT;
cdb[1] = (cmd->lun & 7) << 5;
scsi_device_command_phase0(cmd->id, cdb);
scsi_device_command_phase0(dev, cdb);
return(completion_code(scsi_device_sense(cmd->id)));
return(completion_code(scsi_device_sense(dev)));
case 0x08: /* Read Drive Parameters */
target_check(cmd->id);
dev->BufferLength = 6;
dev->CmdBuffer = (uint8_t *)malloc(dev->BufferLength);
memset(dev->CmdBuffer, 0x00, dev->BufferLength);
dev->buffer_length = 6;
dev->cmd_buffer = (uint8_t *)malloc(dev->buffer_length);
memset(dev->cmd_buffer, 0x00, dev->buffer_length);
ret = x54x_bios_command_08(cmd->id, dev->CmdBuffer);
ret = x54x_bios_command_08(cmd->id, dev->cmd_buffer);
x54x_log("BIOS DMA: Reading 6 bytes at %08X\n", dma_address);
DMAPageWrite(dma_address,
dev->CmdBuffer, 4 /* dev->BufferLength */);
dev->cmd_buffer, 4 /* dev->buffer_length */);
if (dev->CmdBuffer != NULL) {
free(dev->CmdBuffer);
dev->CmdBuffer = NULL;
if (dev->cmd_buffer != NULL) {
free(dev->cmd_buffer);
dev->cmd_buffer = NULL;
}
return(ret);
@@ -510,9 +511,9 @@ skip_write_phase1:
cdb[4] = (lba >> 8) & 0xff;
cdb[5] = lba & 0xff;
scsi_device_command_phase0(cmd->id, cdb);
scsi_device_command_phase0(dev, cdb);
return((dev->Status == SCSI_STATUS_OK) ? 1 : 0);
return((dev->status == SCSI_STATUS_OK) ? 1 : 0);
case 0x0d: /* Alternate Disk Reset, in practice it's a nop */
//FIXME: add a longer delay here --FvK
@@ -524,9 +525,9 @@ skip_write_phase1:
cdb[0] = GPCMD_TEST_UNIT_READY;
cdb[1] = (cmd->lun & 7) << 5;
scsi_device_command_phase0(cmd->id, cdb);
scsi_device_command_phase0(dev, cdb);
return(completion_code(scsi_device_sense(cmd->id)));
return(completion_code(scsi_device_sense(dev)));
case 0x11: /* Recalibrate */
target_check(cmd->id);
@@ -534,9 +535,9 @@ skip_write_phase1:
cdb[0] = GPCMD_REZERO_UNIT;
cdb[1] = (cmd->lun & 7) << 5;
scsi_device_command_phase0(cmd->id, cdb);
scsi_device_command_phase0(dev, cdb);
return(completion_code(scsi_device_sense(cmd->id)));
return(completion_code(scsi_device_sense(dev)));
case 0x14: /* Controller Diagnostic */
//FIXME: add a longer delay here --FvK
@@ -545,19 +546,19 @@ skip_write_phase1:
case 0x15: /* Read DASD Type */
target_check(cmd->id);
dev->BufferLength = 6;
dev->CmdBuffer = (uint8_t *)malloc(dev->BufferLength);
memset(dev->CmdBuffer, 0x00, dev->BufferLength);
dev->buffer_length = 6;
dev->cmd_buffer = (uint8_t *)malloc(dev->buffer_length);
memset(dev->cmd_buffer, 0x00, dev->buffer_length);
ret = x54x_bios_command_15(cmd->id, dev->CmdBuffer);
ret = x54x_bios_command_15(cmd->id, dev->cmd_buffer);
x54x_log("BIOS DMA: Reading 6 bytes at %08X\n", dma_address);
DMAPageWrite(dma_address,
dev->CmdBuffer, 4 /* dev->BufferLength */);
dev->cmd_buffer, 4 /* dev->buffer_length */);
if (dev->CmdBuffer != NULL) {
free(dev->CmdBuffer);
dev->CmdBuffer = NULL;
if (dev->cmd_buffer != NULL) {
free(dev->cmd_buffer);
dev->cmd_buffer = NULL;
}
return(ret);
@@ -761,7 +762,7 @@ x54x_set_residue(Req_t *req, int32_t TransferLength)
{
uint32_t Residue = 0;
addr24 Residue24;
int32_t BufLen = SCSIDevices[req->TargetID].BufferLength;
int32_t BufLen = scsi_devices[req->TargetID].buffer_length;
if ((req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) ||
(req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) {
@@ -792,7 +793,7 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir)
uint32_t DataPointer, DataLength;
uint32_t SGEntryLength = (Is24bit ? sizeof(SGE) : sizeof(SGE32));
uint32_t Address, i;
int32_t BufLen = SCSIDevices[req->TargetID].BufferLength;
int32_t BufLen = scsi_devices[req->TargetID].buffer_length;
uint8_t read_from_host = (dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) || (req->CmdBlock.common.ControlByte == 0x00)));
uint8_t write_to_host = (!dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) || (req->CmdBlock.common.ControlByte == 0x00)));
int sg_pos = 0;
@@ -824,11 +825,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, &(SCSIDevices[req->TargetID].CmdBuffer[sg_pos]), DataToTransfer);
DMAPageRead(Address, &(scsi_devices[req->TargetID].cmd_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, &(SCSIDevices[req->TargetID].CmdBuffer[sg_pos]), DataToTransfer);
DMAPageWrite(Address, &(scsi_devices[req->TargetID].cmd_buffer[sg_pos]), DataToTransfer);
}
else
x54x_log("No action on S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address);
@@ -848,9 +849,9 @@ 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, SCSIDevices[req->TargetID].CmdBuffer, MIN(BufLen, (int) DataLength));
DMAPageRead(Address, scsi_devices[req->TargetID].cmd_buffer, MIN(BufLen, (int) DataLength));
else if (write_to_host)
DMAPageWrite(Address, SCSIDevices[req->TargetID].CmdBuffer, MIN(BufLen, (int) DataLength));
DMAPageWrite(Address, scsi_devices[req->TargetID].cmd_buffer, MIN(BufLen, (int) DataLength));
}
}
}
@@ -860,23 +861,23 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir)
void
x54x_buf_alloc(uint8_t id, int length)
{
if (SCSIDevices[id].CmdBuffer != NULL) {
free(SCSIDevices[id].CmdBuffer);
SCSIDevices[id].CmdBuffer = NULL;
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);
SCSIDevices[id].CmdBuffer = (uint8_t *) malloc(length);
memset(SCSIDevices[id].CmdBuffer, 0, 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 (SCSIDevices[id].CmdBuffer != NULL) {
free(SCSIDevices[id].CmdBuffer);
SCSIDevices[id].CmdBuffer = NULL;
if (scsi_devices[id].cmd_buffer != NULL) {
free(scsi_devices[id].cmd_buffer);
scsi_devices[id].cmd_buffer = NULL;
}
}
@@ -920,7 +921,7 @@ SenseBufferFree(Req_t *req, int Copy)
uint8_t temp_sense[256];
if (SenseLength && Copy) {
scsi_device_request_sense(req->TargetID, temp_sense, SenseLength);
scsi_device_request_sense(&scsi_devices[req->TargetID], temp_sense, SenseLength);
/*
* The sense address, in 32-bit mode, is located in the
@@ -945,24 +946,22 @@ static void
x54x_scsi_cmd(x54x_t *dev)
{
Req_t *req = &dev->Req;
uint8_t id, lun;
uint8_t id, lun, phase, bit24 = !!req->Is24bit;
uint8_t temp_cdb[12];
uint32_t i;
int target_cdb_len = 12;
int target_data_len;
uint8_t bit24 = !!req->Is24bit;
uint32_t i, SenseBufferAddress;
int target_data_len, target_cdb_len = 12;
int32_t *BufLen;
uint8_t phase;
uint32_t SenseBufferAddress;
int64_t p;
scsi_device_t *sd;
id = req->TargetID;
sd = &scsi_devices[id];
lun = req->LUN;
target_cdb_len = 12;
target_data_len = x54x_get_length(req, bit24);
if (!scsi_device_valid(id))
if (!scsi_device_valid(sd))
fatal("SCSI target on %02i has disappeared\n", id);
x54x_log("target_data_len = %i\n", target_data_len);
@@ -985,14 +984,14 @@ x54x_scsi_cmd(x54x_t *dev)
dev->Residue = 0;
BufLen = scsi_device_get_buf_len(id);
BufLen = scsi_device_get_buf_len(sd);
*BufLen = target_data_len;
x54x_log("Command buffer: %08X\n", SCSIDevices[id].CmdBuffer);
x54x_log("Command buffer: %08X\n", scsi_devices[id].cmd_buffer);
scsi_device_command_phase0(id, temp_cdb);
scsi_device_command_phase0(sd, temp_cdb);
phase = SCSIDevices[id].Phase;
phase = sd->phase;
x54x_log("Control byte: %02X\n", (req->CmdBlock.common.ControlByte == 0x03));
@@ -1001,14 +1000,14 @@ x54x_scsi_cmd(x54x_t *dev)
/* 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(id);
if ((SCSIDevices[id].Status != SCSI_STATUS_OK) && (*BufLen > 0)) {
scsi_device_command_phase1(sd);
if ((sd->status != SCSI_STATUS_OK) && (*BufLen > 0)) {
SenseBufferAddress = SenseBufferPointer(req);
DMAPageWrite(SenseBufferAddress, SCSIDevices[id].CmdBuffer, *BufLen);
DMAPageWrite(SenseBufferAddress, scsi_devices[id].cmd_buffer, *BufLen);
x54x_add_to_period(*BufLen);
}
} else {
p = scsi_device_get_callback(id);
p = scsi_device_get_callback(sd);
if (p <= 0LL)
x54x_add_to_period(*BufLen);
else
@@ -1016,14 +1015,14 @@ x54x_scsi_cmd(x54x_t *dev)
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);
scsi_device_command_phase1(id);
scsi_device_command_phase1(sd);
if (phase == SCSI_PHASE_DATA_IN)
x54x_buf_dma_transfer(req, bit24, target_data_len, 0);
SenseBufferFree(req, (SCSIDevices[id].Status != SCSI_STATUS_OK));
SenseBufferFree(req, (sd->status != SCSI_STATUS_OK));
}
} else
SenseBufferFree(req, (SCSIDevices[id].Status != SCSI_STATUS_OK));
SenseBufferFree(req, (sd->status != SCSI_STATUS_OK));
x54x_set_residue(req, target_data_len);
@@ -1031,15 +1030,15 @@ x54x_scsi_cmd(x54x_t *dev)
x54x_log("Request complete\n");
if (SCSIDevices[id].Status == SCSI_STATUS_OK) {
if (sd->status == SCSI_STATUS_OK) {
x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock,
CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS);
} else if (SCSIDevices[id].Status == SCSI_STATUS_CHECK_CONDITION) {
} else if (sd->status == SCSI_STATUS_CHECK_CONDITION) {
x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock,
CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR);
}
x54x_log("SCSIDevices[%02i].Status = %02X\n", id, SCSIDevices[id].Status);
x54x_log("scsi_devices[%02i].Status = %02X\n", id, sd->status);
}
@@ -1058,6 +1057,7 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32)
{
Req_t *req = &dev->Req;
uint8_t id, lun;
scsi_device_t *sd;
/* Fetch data from the Command Control Block. */
DMAPageRead(CCBPointer, (uint8_t *)&req->CmdBlock, sizeof(CCB32));
@@ -1069,6 +1069,7 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32)
req->LUN = dev->Mbx24bit ? req->CmdBlock.old.Lun : req->CmdBlock.new.Lun;
id = req->TargetID;
sd = &scsi_devices[id];
lun = req->LUN;
if ((id > dev->max_id) || (lun > 7)) {
x54x_log("SCSI Target ID %i or LUN %i is not valid\n",id,lun);
@@ -1081,10 +1082,10 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32)
x54x_log("Scanning SCSI Target ID %i\n", id);
SCSIDevices[id].Status = SCSI_STATUS_OK;
sd->status = SCSI_STATUS_OK;
/* If there is no device at ID:0, timeout the selection - the LUN is then checked later. */
if (! scsi_device_present(id)) {
if (! scsi_device_present(sd)) {
x54x_log("SCSI Target ID %i and LUN %i have no device attached\n",id,lun);
x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock,
CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR);
@@ -1106,7 +1107,7 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32)
}
if (req->CmdBlock.common.Opcode == 0x81) {
x54x_log("Bus reset opcode\n");
scsi_device_reset(id);
scsi_device_reset(sd);
x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock,
CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS);
x54x_log("%s: Callback: Send incoming mailbox\n", dev->name);
@@ -1443,7 +1444,7 @@ x54x_reset(x54x_t *dev)
/* Reset all devices on controller reset. */
for (i = 0; i < 16; i++)
scsi_device_reset(i);
scsi_device_reset(&scsi_devices[i]);
if (dev->ven_reset)
dev->ven_reset(dev);
@@ -1500,7 +1501,7 @@ x54x_out(uint16_t port, uint8_t val, void *priv)
if (val & CTRL_SCRST) {
/* Reset all devices on SCSI bus reset. */
for (i = 0; i < 16; i++)
scsi_device_reset(i);
scsi_device_reset(&scsi_devices[i]);
}
if (val & CTRL_IRST) {
@@ -1677,7 +1678,7 @@ x54x_out(uint16_t port, uint8_t val, void *priv)
if (i == host_id) continue;
/* TODO: Query device for LUN's. */
if (scsi_device_present(i))
if (scsi_device_present(&scsi_devices[i]))
dev->DataBuf[i] |= 1;
}
dev->DataReplyLeft = i;
@@ -1685,9 +1686,9 @@ x54x_out(uint16_t port, uint8_t val, void *priv)
case CMD_RETCONF: /* return Configuration */
if (dev->ven_get_dma)
dev->DataBuf[0] = (1<<dev->ven_get_dma(dev));
dev->DataBuf[0] = (1 << dev->ven_get_dma(dev));
else
dev->DataBuf[0] = (1<<dev->DmaChannel);
dev->DataBuf[0] = (1 << dev->DmaChannel);
if (dev->ven_get_irq)
irq = dev->ven_get_irq(dev);

View File

@@ -8,7 +8,7 @@
*
* MIDI device core module.
*
* Version: @(#)midi.c 1.0.0 2018/09/06
* Version: @(#)midi.c 1.0.1 2018/10/10
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -179,6 +179,11 @@ midi_init(midi_device_t* device)
void
midi_close(void)
{
if (midi && midi->m_device) {
free(midi->m_device);
midi->m_device = NULL;
}
if (midi) {
free(midi);
midi = NULL;

View File

@@ -61,7 +61,6 @@ static int (*f_fluid_synth_sysex)(void *synth, const char *data, int len, char
static int (*f_fluid_synth_pitch_bend)(void *synth, int chan, int val);
static int (*f_fluid_synth_program_change)(void *synth, int chan, int program);
static int (*f_fluid_synth_sfload)(void *synth, const char *filename, int reset_presets);
static int (*f_fluid_synth_sfunload)(void *synth, unsigned int id, int reset_presets);
static int (*f_fluid_synth_set_interp_method)(void *synth, int chan, int interp_method);
static void (*f_fluid_synth_set_reverb)(void *synth, double roomsize, double damping, double width, double level);
static void (*f_fluid_synth_set_reverb_on)(void *synth, int on);
@@ -84,7 +83,6 @@ static dllimp_t fluidsynth_imports[] = {
{ "fluid_synth_pitch_bend", &f_fluid_synth_pitch_bend },
{ "fluid_synth_program_change", &f_fluid_synth_program_change },
{ "fluid_synth_sfload", &f_fluid_synth_sfload },
{ "fluid_synth_sfunload", &f_fluid_synth_sfunload },
{ "fluid_synth_set_interp_method", &f_fluid_synth_set_interp_method },
{ "fluid_synth_set_reverb", &f_fluid_synth_set_reverb },
{ "fluid_synth_set_reverb_on", &f_fluid_synth_set_reverb_on },
@@ -104,13 +102,14 @@ typedef struct fluidsynth
int samplerate;
int sound_font;
thread_t* thread_h;
event_t* event;
thread_t *thread_h;
event_t *event, *start_event;
int buf_size;
float* buffer;
int16_t* buffer_int16;
int midi_pos;
int on;
} fluidsynth_t;
fluidsynth_t fsdev;
@@ -136,9 +135,14 @@ static void fluidsynth_thread(void *param)
fluidsynth_t* data = (fluidsynth_t*)param;
int buf_pos = 0;
int buf_size = data->buf_size / BUFFER_SEGMENTS;
while (1)
thread_set_event(data->start_event);
while (data->on)
{
thread_wait_event(data->event, -1);
thread_reset_event(data->event);
if (sound_is_float)
{
float *buf = (float*)((uint8_t*)data->buffer + buf_pos);
@@ -237,6 +241,8 @@ void fluidsynth_sysex(uint8_t* data, unsigned int len)
void* fluidsynth_init(const device_t *info)
{
fluidsynth_t* data = &fsdev;
midi_device_t* dev;
memset(data, 0, sizeof(fluidsynth_t));
/* Try loading the DLL. */
@@ -324,12 +330,10 @@ void* fluidsynth_init(const device_t *info)
data->buffer = NULL;
data->buffer_int16 = malloc(data->buf_size);
}
data->event = thread_create_event();
data->thread_h = thread_create(fluidsynth_thread, data);
al_set_midi(data->samplerate, data->buf_size);
midi_device_t* dev = malloc(sizeof(midi_device_t));
dev = malloc(sizeof(midi_device_t));
memset(dev, 0, sizeof(midi_device_t));
dev->play_msg = fluidsynth_msg;
@@ -338,6 +342,16 @@ void* fluidsynth_init(const device_t *info)
midi_init(dev);
data->on = 1;
data->start_event = thread_create_event();
data->event = thread_create_event();
data->thread_h = thread_create(fluidsynth_thread, data);
thread_wait_event(data->start_event, -1);
thread_reset_event(data->start_event);
return dev;
}
@@ -347,10 +361,9 @@ void fluidsynth_close(void* p)
fluidsynth_t* data = &fsdev;
if (data->sound_font != -1) {
f_fluid_synth_sfunload(data->synth, data->sound_font, 1);
data->sound_font = -1;
}
data->on = 0;
thread_set_event(data->event);
thread_wait(data->thread_h, -1);
if (data->synth) {
f_delete_fluid_synth(data->synth);
@@ -362,8 +375,6 @@ void fluidsynth_close(void* p)
data->settings = NULL;
}
midi_close();
if (data->buffer)
{
free(data->buffer);

View File

@@ -83,6 +83,8 @@ int cm32l_available()
static thread_t *thread_h = NULL;
static event_t *event = NULL;
static event_t *start_event = NULL;
static int mt32_on = 0;
#define RENDER_RATE 100
#define BUFFER_SEGMENTS 10
@@ -119,13 +121,19 @@ static void mt32_thread(void *param)
{
int buf_pos = 0;
int bsize = buf_size / BUFFER_SEGMENTS;
while (1)
float *buf;
int16_t *buf16;
thread_set_event(start_event);
while (mt32_on)
{
thread_wait_event(event, -1);
thread_reset_event(event);
if (sound_is_float)
{
float *buf = (float *) ((uint8_t*)buffer + buf_pos);
buf = (float *) ((uint8_t*)buffer + buf_pos);
memset(buf, 0, bsize);
mt32_stream(buf, bsize / (2 * sizeof(float)));
buf_pos += bsize;
@@ -138,9 +146,9 @@ static void mt32_thread(void *param)
}
else
{
int16_t *buf = (int16_t *) ((uint8_t*)buffer_int16 + buf_pos);
memset(buf, 0, bsize);
mt32_stream_int16(buf, bsize / (2 * sizeof(int16_t)));
buf16 = (int16_t *) ((uint8_t*)buffer_int16 + buf_pos);
memset(buf16, 0, bsize);
mt32_stream_int16(buf16, bsize / (2 * sizeof(int16_t)));
buf_pos += bsize;
if (buf_pos >= buf_size)
{
@@ -164,9 +172,12 @@ void mt32_sysex(uint8_t* data, unsigned int len)
void* mt32emu_init(wchar_t *control_rom, wchar_t *pcm_rom)
{
midi_device_t* dev;
wchar_t s[512];
char fn[512];
context = mt32emu_create_context(handler, NULL);
if (!rom_getfile(control_rom, s, 512)) return 0;
wcstombs(fn, s, (wcslen(s) << 1) + 2);
if (!mt32_check("mt32emu_add_rom_file", mt32emu_add_rom_file(context, fn), MT32EMU_RC_ADDED_CONTROL_ROM)) return 0;
@@ -176,8 +187,6 @@ void* mt32emu_init(wchar_t *control_rom, wchar_t *pcm_rom)
if (!mt32_check("mt32emu_open_synth", mt32emu_open_synth(context), MT32EMU_RC_OK)) return 0;
event = thread_create_event();
thread_h = thread_create(mt32_thread, 0);
samplerate = mt32emu_get_actual_stereo_output_samplerate(context);
/* buf_size = samplerate/RENDER_RATE*2; */
if (sound_is_float)
@@ -201,7 +210,7 @@ void* mt32emu_init(wchar_t *control_rom, wchar_t *pcm_rom)
al_set_midi(samplerate, buf_size);
midi_device_t* dev = malloc(sizeof(midi_device_t));
dev = malloc(sizeof(midi_device_t));
memset(dev, 0, sizeof(midi_device_t));
dev->play_msg = mt32_msg;
@@ -210,6 +219,16 @@ void* mt32emu_init(wchar_t *control_rom, wchar_t *pcm_rom)
midi_init(dev);
mt32_on = 1;
start_event = thread_create_event();
event = thread_create_event();
thread_h = thread_create(mt32_thread, 0);
thread_wait_event(start_event, -1);
thread_reset_event(start_event);
return dev;
}
@@ -227,15 +246,15 @@ void mt32_close(void* p)
{
if (!p) return;
if (thread_h)
thread_kill(thread_h);
if (event)
thread_destroy_event(event);
mt32_on = 0;
thread_set_event(event);
thread_wait(thread_h, -1);
event = NULL;
start_event = NULL;
thread_h = NULL;
if (context)
{
if (context) {
mt32emu_close_synth(context);
mt32emu_free_context(context);
}
@@ -248,10 +267,6 @@ void mt32_close(void* p)
if (buffer_int16)
free(buffer_int16);
buffer_int16 = NULL;
midi_close();
free((midi_device_t*)p);
}
static const device_config_t mt32_config[] =

View File

@@ -8,7 +8,7 @@
*
* Sound emulation core.
*
* Version: @(#)sound.c 1.0.20 2018/10/02
* Version: @(#)sound.c 1.0.21 2018/10/09
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -26,7 +26,6 @@
#include "../86box.h"
#include "../device.h"
#include "../timer.h"
#include "../scsi/scsi_device.h"
#include "../cdrom/cdrom.h"
#include "../plat.h"
#include "sound.h"
@@ -188,68 +187,69 @@ void sound_set_cd_volume(unsigned int vol_l, unsigned int vol_r)
static void sound_cd_thread(void *param)
{
int i = 0;
int c, has_audio, d, r, i = 0;
int32_t audio_vol_l, audio_vol_r;
int channel_select[2];
float cd_buffer_temp[2] = {0.0, 0.0};
float cd_buffer_temp2[2] = {0.0, 0.0};
int32_t cd_buffer_temp4[2] = {0, 0};
int c, has_audio;
int d, r;
thread_set_event(sound_cd_start_event);
while (cdaudioon)
{
while (cdaudioon) {
thread_wait_event(sound_cd_event, -1);
thread_reset_event(sound_cd_event);
if (!soundon || !cdaudioon)
return;
for (c = 0; c < CD_BUFLEN*2; c += 2)
{
if (sound_is_float)
{
for (c = 0; c < CD_BUFLEN*2; c += 2) {
if (sound_is_float) {
cd_out_buffer[c] = 0.0;
cd_out_buffer[c+1] = 0.0;
}
else
{
} else {
cd_out_buffer_int16[c] = 0;
cd_out_buffer_int16[c+1] = 0;
}
}
for (i = 0; i < CDROM_NUM; i++)
{
for (i = 0; i < CDROM_NUM; i++) {
has_audio = 0;
if ((cdrom_drives[i].bus_type == CDROM_BUS_DISABLED) || !cdrom[i] || !cdrom[i]->handler)
if ((cdrom_drives[i].bus_type == CDROM_BUS_DISABLED) || !cdrom_drives[i].handler)
continue;
if (cdrom[i]->handler->audio_callback)
if (cdrom_drives[i].handler->audio_callback)
{
r = cdrom[i]->handler->audio_callback(i, cd_buffer[i], CD_BUFLEN*2);
r = cdrom_drives[i].handler->audio_callback(i, cd_buffer[i], CD_BUFLEN*2);
has_audio = (cdrom_drives[i].bus_type && cdrom_drives[i].sound_on/* && r*/);
} else
continue;
if (soundon && has_audio)
{
int32_t audio_vol_l = cdrom_mode_sense_get_volume(cdrom[i], 0);
int32_t audio_vol_r = cdrom_mode_sense_get_volume(cdrom[i], 1);
int channel_select[2];
channel_select[0] = cdrom_mode_sense_get_channel(cdrom[i], 0);
channel_select[1] = cdrom_mode_sense_get_channel(cdrom[i], 1);
if (soundon && has_audio) {
if (cdrom_drives[i].get_volume) {
audio_vol_l = cdrom_drives[i].get_volume(cdrom_drives[i].p, 0);
audio_vol_r = cdrom_drives[i].get_volume(cdrom_drives[i].p, 1);
} else {
audio_vol_l = 255;
audio_vol_r = 255;
}
if (!r)
{
for (c = 0; c < CD_BUFLEN*2; c += 2)
{
if (sound_is_float)
{
if (cdrom_drives[i].get_channel) {
channel_select[0] = cdrom_drives[i].get_channel(cdrom_drives[i].p, 0);
channel_select[1] = cdrom_drives[i].get_channel(cdrom_drives[i].p, 1);
} else {
channel_select[0] = 1;
channel_select[1] = 2;
}
if (!r) {
for (c = 0; c < CD_BUFLEN*2; c += 2) {
if (sound_is_float) {
cd_out_buffer[c] += 0.0;
cd_out_buffer[c+1] += 0.0;
}
else
{
} else {
cd_out_buffer_int16[c] += 0;
cd_out_buffer_int16[c+1] += 0;
}
@@ -257,8 +257,7 @@ static void sound_cd_thread(void *param)
continue;
}
for (c = 0; c < CD_BUFLEN*2; c += 2)
{
for (c = 0; c < CD_BUFLEN*2; c += 2) {
/* First, transfer the CD audio data to the temporary buffer. */
cd_buffer_temp[0] = (float) cd_buffer[i][c];
cd_buffer_temp[1] = (float) cd_buffer[i][c+1];
@@ -271,25 +270,17 @@ static void sound_cd_thread(void *param)
/*Apply ATAPI channel select*/
cd_buffer_temp2[0] = cd_buffer_temp2[1] = 0.0;
if (channel_select[0] & 1)
{
cd_buffer_temp2[0] += cd_buffer_temp[0];
}
if (channel_select[0] & 2)
{
cd_buffer_temp2[1] += cd_buffer_temp[0];
}
if (channel_select[1] & 1)
{
cd_buffer_temp2[0] += cd_buffer_temp[1];
}
if (channel_select[1] & 2)
{
cd_buffer_temp2[1] += cd_buffer_temp[1];
}
if (sound_process_handlers_num)
{
if (channel_select[0] & 1)
cd_buffer_temp2[0] += cd_buffer_temp[0];
if (channel_select[0] & 2)
cd_buffer_temp2[1] += cd_buffer_temp[0];
if (channel_select[1] & 1)
cd_buffer_temp2[0] += cd_buffer_temp[1];
if (channel_select[1] & 2)
cd_buffer_temp2[1] += cd_buffer_temp[1];
if (sound_process_handlers_num) {
cd_buffer_temp4[0] = (int32_t) cd_buffer_temp2[0];
cd_buffer_temp4[1] = (int32_t) cd_buffer_temp2[1];
@@ -298,9 +289,7 @@ static void sound_cd_thread(void *param)
cd_buffer_temp2[0] = (float) cd_buffer_temp4[0];
cd_buffer_temp2[1] = (float) cd_buffer_temp4[1];
}
else
{
} else {
/*Apply sound card CD volume*/
cd_buffer_temp2[0] *= (float) cd_vol_l;
cd_buffer_temp2[0] /= 65535.0;
@@ -309,13 +298,10 @@ static void sound_cd_thread(void *param)
cd_buffer_temp2[1] /= 65535.0;
}
if (sound_is_float)
{
if (sound_is_float) {
cd_out_buffer[c] += (cd_buffer_temp2[0] / 32768.0);
cd_out_buffer[c+1] += (cd_buffer_temp2[1] / 32768.0);
}
else
{
} else {
if (cd_buffer_temp2[0] > 32767)
cd_buffer_temp2[0] = 32767;
if (cd_buffer_temp2[0] < -32768)
@@ -331,6 +317,7 @@ static void sound_cd_thread(void *param)
}
}
}
if (sound_is_float)
givealbuffer_cd(cd_out_buffer);
else
@@ -540,21 +527,15 @@ void sound_cd_thread_reset(void)
int i = 0;
int available_cdrom_drives = 0;
for (i = 0; i < CDROM_NUM; i++)
{
if (cdrom[i] && cdrom[i]->handler && cdrom[i]->handler->audio_stop)
{
cdrom[i]->handler->audio_stop(i);
}
for (i = 0; i < CDROM_NUM; i++) {
if (cdrom_drives[i].handler && cdrom_drives[i].handler->audio_stop)
cdrom_drives[i].handler->audio_stop(i);
if ((cdrom_drives[i].bus_type != CDROM_BUS_DISABLED) && cdrom[i])
{
if (cdrom_drives[i].bus_type != CDROM_BUS_DISABLED)
available_cdrom_drives++;
}
}
if (available_cdrom_drives && !cd_thread_enable)
{
if (available_cdrom_drives && !cd_thread_enable) {
cdaudioon = 1;
sound_cd_start_event = thread_create_event();
@@ -564,9 +545,7 @@ void sound_cd_thread_reset(void)
thread_wait_event(sound_cd_start_event, -1);
thread_reset_event(sound_cd_start_event);
}
else if (!available_cdrom_drives && cd_thread_enable)
{
} else if (!available_cdrom_drives && cd_thread_enable) {
sound_cd_thread_end();
}

View File

@@ -477,7 +477,7 @@ USBOBJ := usb.o
endif
SCSIOBJ := scsi.o scsi_device.o \
scsi_disk.o \
scsi_cdrom.o scsi_disk.o \
scsi_x54x.o \
scsi_aha154x.o scsi_buslogic.o \
scsi_ncr5380.o scsi_ncr53c810.o

View File

@@ -8,7 +8,7 @@
*
* Platform support defintions for Win32.
*
* Version: @(#)win.h 1.0.19 2018/07/19
* Version: @(#)win.h 1.0.20 2018/10/10
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -50,6 +50,8 @@
#define WM_SHOWSETTINGS 0x8889
#define WM_PAUSE 0x8890
#define WM_SENDHWND 0x8891
#define WM_HARDRESET 0x8892
#define WM_SHUTDOWN 0x8893
#ifdef USE_VNC
#define RENDERERS_NUM 5

View File

@@ -8,7 +8,7 @@
*
* Handle the platform-side of CDROM drives.
*
* Version: @(#)win_cdrom.c 1.0.9 2018/10/02
* Version: @(#)win_cdrom.c 1.0.10 2018/10/09
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -43,32 +43,35 @@
void
cdrom_eject(uint8_t id)
{
if (cdrom_drives[id].host_drive == 0) {
cdrom_drive_t *drv = &cdrom_drives[id];
cdrom_image_t *img = &cdrom_image[id];
if (drv->host_drive == 0) {
/* Switch from empty to empty. Do nothing. */
return;
}
if (cdrom_image[id].prev_image_path) {
free(cdrom_image[id].prev_image_path);
cdrom_image[id].prev_image_path = NULL;
if (img->prev_image_path) {
free(img->prev_image_path);
img->prev_image_path = NULL;
}
if (cdrom_drives[id].host_drive == 200) {
cdrom_image[id].prev_image_path = (wchar_t *) malloc(1024);
wcscpy(cdrom_image[id].prev_image_path, cdrom_image[id].image_path);
if (drv->host_drive == 200) {
img->prev_image_path = (wchar_t *) malloc(1024);
wcscpy(img->prev_image_path, img->image_path);
}
cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive;
cdrom[id]->handler->exit(id);
drv->prev_host_drive = drv->host_drive;
drv->handler->exit(id);
cdrom_close_handler(id);
memset(cdrom_image[id].image_path, 0, 2048);
memset(img->image_path, 0, 2048);
cdrom_null_open(id);
if (cdrom_drives[id].bus_type) {
if (drv->insert) {
/* Signal disc change to the emulated machine. */
cdrom_insert(cdrom[id]);
drv->insert(drv->p);
}
ui_sb_check_menu_item(SB_CDROM|id, IDM_CDROM_IMAGE | id, MF_UNCHECKED);
cdrom_drives[id].host_drive=0;
drv->host_drive=0;
ui_sb_check_menu_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, MF_CHECKED);
ui_sb_update_icon_state(SB_CDROM|id, 1);
ui_sb_enable_menu_item(SB_CDROM|id, IDM_CDROM_RELOAD | id, MF_BYCOMMAND | MF_ENABLED);
@@ -81,31 +84,34 @@ cdrom_eject(uint8_t id)
void
cdrom_reload(uint8_t id)
{
if ((cdrom_drives[id].host_drive == cdrom_drives[id].prev_host_drive) || (cdrom_drives[id].prev_host_drive == 0) || (cdrom_drives[id].host_drive != 0)) {
cdrom_drive_t *drv = &cdrom_drives[id];
cdrom_image_t *img = &cdrom_image[id];
if ((drv->host_drive == drv->prev_host_drive) || !drv->prev_host_drive || drv->host_drive) {
/* Switch from empty to empty. Do nothing. */
return;
}
cdrom_close_handler(id);
memset(cdrom_image[id].image_path, 0, 2048);
memset(img->image_path, 0, 2048);
if (cdrom_drives[id].prev_host_drive == 200) {
wcscpy(cdrom_image[id].image_path, cdrom_image[id].prev_image_path);
free(cdrom_image[id].prev_image_path);
cdrom_image[id].prev_image_path = NULL;
image_open(id, cdrom_image[id].image_path);
if (cdrom_drives[id].bus_type) {
if (drv->prev_host_drive == 200) {
wcscpy(img->image_path, img->prev_image_path);
free(img->prev_image_path);
img->prev_image_path = NULL;
image_open(id, img->image_path);
if (drv->insert) {
/* Signal disc change to the emulated machine. */
cdrom_insert(cdrom[id]);
drv->insert(drv->p);
}
if (wcslen(cdrom_image[id].image_path) == 0) {
if (wcslen(img->image_path) == 0) {
ui_sb_check_menu_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, MF_CHECKED);
cdrom_drives[id].host_drive = 0;
drv->host_drive = 0;
ui_sb_check_menu_item(SB_CDROM|id, IDM_CDROM_IMAGE | id, MF_UNCHECKED);
ui_sb_update_icon_state(SB_CDROM|id, 1);
} else {
ui_sb_check_menu_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, MF_UNCHECKED);
cdrom_drives[id].host_drive = 200;
drv->host_drive = 200;
ui_sb_check_menu_item(SB_CDROM|id, IDM_CDROM_IMAGE | id, MF_CHECKED);
ui_sb_update_icon_state(SB_CDROM|id, 0);
}

View File

@@ -20,6 +20,7 @@
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "../86box.h"
#include "../device.h"
#include "../video/video.h"

View File

@@ -11,7 +11,7 @@
* NOTES: This code should be re-merged into a single init() with a
* 'fullscreen' argument, indicating FS mode is requested.
*
* Version: @(#)win_ddraw.cpp 1.0.10 2018/07/17
* Version: @(#)win_ddraw.cpp 1.0.11 2018/10/10
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -178,7 +178,8 @@ SavePNG(wchar_t *szFilename, HBITMAP hBitmap)
bmpInfo.bmiHeader.biSizeImage =
bmpInfo.bmiHeader.biWidth*abs(bmpInfo.bmiHeader.biHeight)*(bmpInfo.bmiHeader.biBitCount+7)/8;
if ((pBuf = malloc(bmpInfo.bmiHeader.biSizeImage)) == NULL) {
pBuf = malloc(bmpInfo.bmiHeader.biSizeImage);
if (pBuf == NULL) {
ddraw_log("[SavePNG] Unable to Allocate Bitmap Memory");
fclose(fp);
return;
@@ -187,7 +188,8 @@ SavePNG(wchar_t *szFilename, HBITMAP hBitmap)
if (ys2 <= 250) {
bmpInfo.bmiHeader.biSizeImage <<= 1;
if ((pBuf2 = malloc(bmpInfo.bmiHeader.biSizeImage)) == NULL) {
pBuf2 = malloc(bmpInfo.bmiHeader.biSizeImage);
if (pBuf2 == NULL) {
ddraw_log("[SavePNG] Unable to Allocate Secondary Bitmap Memory");
free(pBuf);
fclose(fp);
@@ -207,7 +209,8 @@ SavePNG(wchar_t *szFilename, HBITMAP hBitmap)
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
if ((b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * bmpInfo.bmiHeader.biHeight)) == NULL) {
b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * bmpInfo.bmiHeader.biHeight);
if (b_rgb == NULL) {
ddraw_log("[SavePNG] Unable to Allocate RGB Bitmap Memory");
free(pBuf2);
free(pBuf);
@@ -215,8 +218,9 @@ SavePNG(wchar_t *szFilename, HBITMAP hBitmap)
return;
}
for (i = 0; i < bmpInfo.bmiHeader.biHeight; i++)
for (i = 0; i < bmpInfo.bmiHeader.biHeight; i++) {
b_rgb[i] = (png_byte *) malloc(png_get_rowbytes(png_ptr, info_ptr));
}
if (pBuf2) {
DoubleLines((uint8_t *) pBuf2, (uint8_t *) pBuf);

View File

@@ -8,7 +8,7 @@
*
* Windows device configuration dialog implementation.
*
* Version: @(#)win_devconf.c 1.0.18 2018/04/01
* Version: @(#)win_devconf.c 1.0.19 2018/10/10
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -18,6 +18,7 @@
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
@@ -459,10 +460,13 @@ deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
uint8_t deviceconfig_open(HWND hwnd, const device_t *device)
{
const device_config_t *config = device->config;
uint16_t *data_block = malloc(16384);
uint16_t *data_block;
uint16_t *data;
DLGTEMPLATE *dlg = (DLGTEMPLATE *)data_block;
DLGTEMPLATE *dlg;
DLGITEMTEMPLATE *item;
data_block = malloc(16384);
dlg = (DLGTEMPLATE *)data_block;
int y = 10;
int id = IDC_CONFIG_BASE;

View File

@@ -12,7 +12,7 @@
* we will not use that, but, instead, use a new window which
* coverrs the entire desktop.
*
* Version: @(#)win_sdl.c 1.0.0 2018/05/26
* Version: @(#)win_sdl.c 1.0.1 2018/10/10
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Michael Drüing, <michael@drueing.de>
@@ -551,7 +551,8 @@ sdl_take_screenshot(const wchar_t *fn)
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
if ((rgba = (unsigned char *)malloc(width * height * 4)) == NULL) {
rgba = (unsigned char *) malloc(width * height * 4);
if (rgba == NULL) {
sdl_log("[sdl_take_screenshot] Unable to Allocate RGBA Bitmap Memory");
fclose(fp);
return;
@@ -564,7 +565,8 @@ sdl_take_screenshot(const wchar_t *fn)
return;
}
if ((b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * height)) == NULL) {
b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * height);
if (b_rgb == NULL) {
sdl_log("[sdl_take_screenshot] Unable to Allocate RGB Bitmap Memory");
free(rgba);
fclose(fp);

View File

@@ -8,7 +8,7 @@
*
* Implement the application's Status Bar.
*
* Version: @(#)win_stbar.c 1.0.19 2018/10/02
* Version: @(#)win_stbar.c 1.0.20 2018/10/09
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -286,7 +286,7 @@ StatusBarCreateCdromTip(int part)
free(sbTips[part]);
sbTips[part] = NULL;
}
sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 2);
sbTips[part] = (WCHAR *)malloc((wcslen(tempTip) << 1) + 4);
wcscpy(sbTips[part], tempTip);
}
@@ -882,12 +882,13 @@ StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
if (!cdrom_image[id].prev_image_path)
cdrom_image[id].prev_image_path = (wchar_t *) malloc(1024);
wcscpy(cdrom_image[id].prev_image_path, cdrom_image[id].image_path);
cdrom[id]->handler->exit(id);
cdrom_drives[id].handler->exit(id);
cdrom_close_handler(id);
memset(cdrom_image[id].image_path, 0, 2048);
image_open(id, temp_path);
/* Signal media change to the emulated machine. */
cdrom_insert(cdrom[id]);
if (cdrom_drives[id].insert)
cdrom_drives[id].insert(cdrom_drives[id].p);
CheckMenuItem(sb_menu_handles[part], IDM_CDROM_EMPTY | id, MF_UNCHECKED);
cdrom_drives[id].host_drive = (wcslen(cdrom_image[id].image_path) == 0) ? 0 : 200;
if (cdrom_drives[id].host_drive == 200) {

View File

@@ -8,7 +8,7 @@
*
* user Interface module for WinAPI on Windows.
*
* Version: @(#)win_ui.c 1.0.31 2018/10/07
* Version: @(#)win_ui.c 1.0.32 2018/10/10
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -644,6 +644,14 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
CheckMenuItem(menuMain, IDM_ACTION_PAUSE, dopause ? MF_CHECKED : MF_UNCHECKED);
break;
case WM_HARDRESET:
pc_reset(1);
break;
case WM_SHUTDOWN:
PostQuitMessage(0);
break;
case WM_SYSCOMMAND:
/*
* Disable ALT key *ALWAYS*,