/scsiemul.cpp
C++ | 1625 lines | 1470 code | 120 blank | 35 comment | 347 complexity | 814b764e3000cc38760bde0ff0177f4a MD5 | raw file
- /*
- * UAE - The Un*x Amiga Emulator
- *
- * scsi.device emulation
- *
- * Copyright 1995 Bernd Schmidt
- * Copyright 1999 Patrick Ohly
- * Copyright 2001 Brian King
- * Copyright 2002 Toni Wilen
- *
- */
- #include "sysconfig.h"
- #include "sysdeps.h"
- #include "threaddep/thread.h"
- #include "options.h"
- #include "memory.h"
- #include "custom.h"
- #include "events.h"
- #include "newcpu.h"
- #include "autoconf.h"
- #include "traps.h"
- #include "execlib.h"
- #include "native2amiga.h"
- #include "blkdev.h"
- #include "scsidev.h"
- #include "uae.h"
- #include "execio.h"
- #include "savestate.h"
- #define CDDEV_COMMANDS
- #define UAEDEV_SCSI _T("uaescsi.device")
- #define UAEDEV_SCSI_ID 1
- #define UAEDEV_DISK _T("uaedisk.device")
- #define UAEDEV_DISK_ID 2
- #define MAX_ASYNC_REQUESTS 20
- #define MAX_OPEN_DEVICES 20
- #define ASYNC_REQUEST_NONE 0
- #define ASYNC_REQUEST_TEMP 1
- #define ASYNC_REQUEST_CHANGEINT 10
- #define ASYNC_REQUEST_FRAMEINT 11
- struct devstruct {
- int unitnum, aunit;
- int opencnt;
- int changenum;
- int drivetype;
- int iscd;
- volatile uaecptr d_request[MAX_ASYNC_REQUESTS];
- volatile uae_u8 *d_request_iobuf[MAX_ASYNC_REQUESTS];
- volatile int d_request_type[MAX_ASYNC_REQUESTS];
- volatile uae_u32 d_request_data[MAX_ASYNC_REQUESTS];
- struct device_info di;
- uaecptr changeint;
- int changeint_mediastate;
- int configblocksize;
- int volumelevel;
- int fadeframes;
- int fadetarget;
- int fadecounter;
- smp_comm_pipe requests;
- int thread_running;
- uae_sem_t sync_sem;
- TCHAR *tape_directory;
- bool readonly;
- };
- struct priv_devstruct {
- int inuse;
- int unit;
- int mode;
- int type;
- int flags; /* OpenDevice() */
- };
- static struct devstruct devst[MAX_TOTAL_SCSI_DEVICES];
- static struct priv_devstruct pdevst[MAX_OPEN_DEVICES];
- static uae_u32 nscmd_cmd;
- static uae_sem_t change_sem;
- static struct device_info *devinfo (struct devstruct *devst, struct device_info *di)
- {
- struct device_info *dio = sys_command_info (devst->unitnum, di, 0);
- if (dio) {
- if (!devst->configblocksize)
- devst->configblocksize = dio->bytespersector;
- }
- return di;
- }
- static void io_log(const TCHAR *msg, uae_u8 *iobuf, uaecptr request)
- {
- if (log_scsi)
- write_log (_T("%s: %08X %d %08X %d %d io_actual=%d io_error=%d\n"),
- msg, request, get_word_host(iobuf + 28), get_long_host(iobuf + 40),
- get_long_host(iobuf + 36), get_long_host(iobuf + 44),
- get_long_host(iobuf + 32), get_byte_host(iobuf + 31));
- }
- static struct devstruct *getdevstruct (int unit)
- {
- int i;
- for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
- if (unit >= 0 && devst[i].aunit == unit)
- return &devst[i];
- }
- return 0;
- }
- static struct priv_devstruct *getpdevstruct(TrapContext *ctx, uaecptr request)
- {
- int i = trap_get_long(ctx, request + 24);
- if (i < 0 || i >= MAX_OPEN_DEVICES || pdevst[i].inuse == 0) {
- write_log (_T("uaescsi.device: corrupt iorequest %08X %d\n"), request, i);
- return 0;
- }
- return &pdevst[i];
- }
- static const TCHAR *getdevname (int type)
- {
- switch (type) {
- case UAEDEV_SCSI_ID:
- return UAEDEV_SCSI;
- case UAEDEV_DISK_ID:
- return UAEDEV_DISK;
- default:
- return _T("NULL");
- }
- }
- static void dev_thread(void *devs);
- static int start_thread(struct devstruct *dev)
- {
- if (dev->thread_running)
- return 1;
- init_comm_pipe (&dev->requests, 300, 3);
- uae_sem_init (&dev->sync_sem, 0, 0);
- uae_start_thread (_T("uaescsi"), dev_thread, dev, NULL);
- uae_sem_wait (&dev->sync_sem);
- return dev->thread_running;
- }
- static void dev_close_3(struct devstruct *dev, struct priv_devstruct *pdev)
- {
- if (!dev->opencnt) return;
- dev->opencnt--;
- if (!dev->opencnt) {
- sys_command_close (dev->unitnum);
- pdev->inuse = 0;
- write_comm_pipe_pvoid(&dev->requests, NULL, 0);
- write_comm_pipe_pvoid(&dev->requests, NULL, 0);
- write_comm_pipe_u32(&dev->requests, 0, 1);
- }
- }
- static uae_u32 REGPARAM2 dev_close_2(TrapContext *ctx)
- {
- uae_u32 request = trap_get_areg(ctx, 1);
- struct priv_devstruct *pdev = getpdevstruct(ctx, request);
- struct devstruct *dev;
- if (!pdev)
- return 0;
- dev = getdevstruct(pdev->unit);
- if (log_scsi)
- write_log (_T("%s:%d close, req=%08X\n"), getdevname (pdev->type), pdev->unit, request);
- if (!dev)
- return 0;
- dev_close_3 (dev, pdev);
- trap_put_long(ctx, request + 24, 0);
- trap_put_word(ctx, trap_get_areg(ctx, 6) + 32, trap_get_word(ctx, trap_get_areg(ctx, 6) + 32) - 1);
- return 0;
- }
- static uae_u32 REGPARAM2 dev_close(TrapContext *context)
- {
- return dev_close_2(context);
- }
- static uae_u32 REGPARAM2 diskdev_close(TrapContext *context)
- {
- return dev_close_2(context);
- }
- static int openfail(TrapContext *ctx, uaecptr ioreq, int error)
- {
- trap_put_long(ctx, ioreq + 20, -1);
- trap_put_byte(ctx, ioreq + 31, error);
- return (uae_u32)-1;
- }
- static uae_u32 REGPARAM2 dev_open_2(TrapContext *ctx, int type)
- {
- uaecptr ioreq = trap_get_areg(ctx, 1);
- uae_u32 unit = trap_get_dreg(ctx, 0);
- uae_u32 flags = trap_get_dreg(ctx, 1);
- struct devstruct *dev = getdevstruct(unit);
- struct priv_devstruct *pdev = 0;
- int i, v;
- if (log_scsi)
- write_log (_T("opening %s:%d ioreq=%08X\n"), getdevname (type), unit, ioreq);
- uae_u16 len = trap_get_word(ctx, ioreq + 0x12);
- if (len < IOSTDREQ_SIZE && len > 0)
- return openfail(ctx, ioreq, IOERR_BADLENGTH);
- if (!dev)
- return openfail(ctx, ioreq, 32); /* badunitnum */
- if (!dev->opencnt) {
- for (i = 0; i < MAX_OPEN_DEVICES; i++) {
- pdev = &pdevst[i];
- if (pdev->inuse == 0)
- break;
- }
- if (dev->drivetype == INQ_SEQD) {
- v = sys_command_open_tape(dev->unitnum, dev->tape_directory, dev->readonly);
- } else {
- v = sys_command_open(dev->unitnum);
- }
- if (!v)
- return openfail(ctx, ioreq, IOERR_OPENFAIL);
- pdev->type = type;
- pdev->unit = unit;
- pdev->flags = flags;
- pdev->inuse = 1;
- trap_put_long(ctx, ioreq + 24, pdev - pdevst);
- start_thread (dev);
- } else {
- for (i = 0; i < MAX_OPEN_DEVICES; i++) {
- pdev = &pdevst[i];
- if (pdev->inuse && pdev->unit == unit) break;
- }
- if (i == MAX_OPEN_DEVICES)
- return openfail(ctx, ioreq, IOERR_OPENFAIL);
- trap_put_long(ctx, ioreq + 24, pdev - pdevst);
- }
- dev->opencnt++;
- trap_put_word(ctx, trap_get_areg(ctx, 6) + 32, trap_get_word(ctx, trap_get_areg(ctx, 6) + 32) + 1);
- trap_put_byte(ctx, ioreq + 31, 0);
- trap_put_byte(ctx, ioreq + 8, 7);
- return 0;
- }
- static uae_u32 REGPARAM2 dev_open(TrapContext *ctx)
- {
- return dev_open_2(ctx, UAEDEV_SCSI_ID);
- }
- static uae_u32 REGPARAM2 diskdev_open (TrapContext *ctx)
- {
- return dev_open_2(ctx, UAEDEV_DISK_ID);
- }
- static uae_u32 REGPARAM2 dev_expunge(TrapContext *ctx)
- {
- return 0;
- }
- static uae_u32 REGPARAM2 diskdev_expunge(TrapContext *ctx)
- {
- return 0;
- }
- static int is_async_request(struct devstruct *dev, uaecptr request)
- {
- int i = 0;
- while (i < MAX_ASYNC_REQUESTS) {
- if (dev->d_request[i] == request)
- return 1;
- i++;
- }
- return 0;
- }
- #if 0
- static int scsiemul_switchscsi (const TCHAR *name)
- {
- struct devstruct *dev = NULL;
- struct device_info *discsi, discsi2;
- int i, opened[MAX_TOTAL_SCSI_DEVICES];
- bool wasopen = false;
- for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++)
- opened[i] = sys_command_isopen (i);
- dev = &devst[0];
- if (dev->opencnt)
- wasopen = true;
- sys_command_close (dev->unitnum);
- dev = NULL;
- if (device_func_init (DEVICE_TYPE_ANY)) {
- if (devst[0].di.media_inserted < 0)
- devst[0].di.media_inserted = 0;
- i = 0;
- while (i < MAX_TOTAL_SCSI_DEVICES && dev == NULL) {
- discsi = 0;
- if (sys_command_open ( i)) {
- discsi = sys_command_info (i, &discsi2, 0);
- if (discsi && discsi->type == INQ_ROMD) {
- if (!_tcsicmp (currprefs.cdimagefile[0], discsi->label)) {
- dev = &devst[0];
- dev->unitnum = i;
- dev->drivetype = discsi->type;
- memcpy (&dev->di, discsi, sizeof (struct device_info));
- dev->iscd = 1;
- write_log (_T("%s mounted as uaescsi.device:0\n"), discsi->label);
- if (dev->di.media_inserted) {
- dev->di.media_inserted = 0;
- scsi_do_disk_change (dev->di.id, 1, NULL);
- }
- }
- }
- if (opened[i] == 0 && !wasopen)
- sys_command_close ( i);
- }
- i++;
- }
- if (dev)
- return dev->unitnum;
- }
- return -1;
- }
- #endif
- // pollmode is 1 if no change interrupts found -> increase time of media change
- int scsi_do_disk_change(int unitnum, int insert, int *pollmode)
- {
- int i, j, ret;
- ret = -1;
- if (!change_sem)
- return ret;
- uae_sem_wait (&change_sem);
- for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
- struct devstruct *dev = &devst[i];
- if (dev->di.unitnum == unitnum + 1) {
- ret = i;
- if ((dev->changeint_mediastate > 0 && insert == 0) || (dev->changeint_mediastate <= 0 && insert)) {
- dev->changeint_mediastate = insert;
- if (pollmode)
- *pollmode = 1;
- if (dev->aunit >= 0) {
- struct priv_devstruct *pdev = &pdevst[dev->aunit];
- devinfo (dev, &dev->di);
- }
- dev->changenum++;
- j = 0;
- while (j < MAX_ASYNC_REQUESTS) {
- if (dev->d_request_type[j] == ASYNC_REQUEST_CHANGEINT) {
- uae_Cause (dev->d_request_data[j]);
- if (pollmode)
- *pollmode = 0;
- }
- j++;
- }
- if (dev->changeint) {
- uae_Cause (dev->changeint);
- if (pollmode)
- *pollmode = 0;
- }
- }
- }
- }
- uae_sem_post (&change_sem);
- return ret;
- }
- static int add_async_request(struct devstruct *dev, uae_u8 *iobuf, uaecptr request, int type, uae_u32 data)
- {
- int i;
- if (log_scsi)
- write_log (_T("async request %08x (%d) %p added\n"), request, type, iobuf);
- i = 0;
- while (i < MAX_ASYNC_REQUESTS) {
- if (dev->d_request[i] == request) {
- dev->d_request_type[i] = type;
- dev->d_request_data[i] = data;
- return 0;
- }
- i++;
- }
- i = 0;
- while (i < MAX_ASYNC_REQUESTS) {
- if (dev->d_request[i] == 0) {
- dev->d_request_iobuf[i] = iobuf;
- dev->d_request[i] = request;
- dev->d_request_type[i] = type;
- dev->d_request_data[i] = data;
- return 0;
- }
- i++;
- }
- return -1;
- }
- static int release_async_request(struct devstruct *dev, uaecptr request)
- {
- int i = 0;
- if (log_scsi)
- write_log (_T("async request %08x removed\n"), request);
- while (i < MAX_ASYNC_REQUESTS) {
- if (dev->d_request[i] == request) {
- int type = dev->d_request_type[i];
- dev->d_request[i] = 0;
- xfree((uae_u8*)dev->d_request_iobuf[i]);
- dev->d_request_iobuf[i] = 0;
- dev->d_request_data[i] = 0;
- dev->d_request_type[i] = 0;
- return type;
- }
- i++;
- }
- return -1;
- }
- static void abort_async(struct devstruct *dev, uaecptr request, int errcode, int type)
- {
- int i;
- i = 0;
- while (i < MAX_ASYNC_REQUESTS) {
- if (dev->d_request[i] == request && dev->d_request_type[i] == ASYNC_REQUEST_TEMP) {
- /* ASYNC_REQUEST_TEMP = request is processing */
- sleep_millis (10);
- i = 0;
- continue;
- }
- i++;
- }
- i = release_async_request (dev, request);
- if (i >= 0 && log_scsi)
- write_log (_T("asyncronous request=%08X aborted, error=%d\n"), request, errcode);
- }
- static int command_read(TrapContext *ctx, struct devstruct *dev, uaecptr data, uae_u64 offset, uae_u32 length, uae_u32 *io_actual)
- {
- int blocksize = dev->di.bytespersector;
- length /= blocksize;
- offset /= blocksize;
- while (length > 0) {
- uae_u8 buffer[4096];
- if (!sys_command_read (dev->unitnum, buffer, offset, 1))
- return 20;
- trap_memcpyha_safe(ctx, data, buffer, blocksize);
- data += blocksize;
- offset++;
- length--;
- }
- return 0;
- }
- static int command_write(TrapContext *ctx, struct devstruct *dev, uaecptr data, uae_u64 offset, uae_u32 length, uae_u32 *io_actual)
- {
- uae_u32 blocksize = dev->di.bytespersector;
- length /= blocksize;
- offset /= blocksize;
- while (length > 0) {
- uae_u8 buffer[4096];
- int err;
- trap_memcpyah_safe(ctx, buffer, data, blocksize);
- err = sys_command_write (dev->unitnum, buffer, offset, 1);
- if (!err)
- return 20;
- if (err < 0)
- return 28; // write protected
- data += blocksize;
- offset++;
- length--;
- }
- return 0;
- }
- static int command_cd_read(TrapContext *ctx, struct devstruct *dev, uaecptr data, uae_u64 offset, uae_u32 length, uae_u32 *io_actual)
- {
- uae_u32 len, sector, startoffset;
- int blocksize;
- blocksize = dev->configblocksize;
- *io_actual = 0;
- startoffset = offset % blocksize;
- offset -= startoffset;
- sector = offset / blocksize;
- while (length > 0) {
- uae_u8 temp[4096];
- if (blocksize != 2048) {
- if (!sys_command_cd_rawread (dev->unitnum, temp, sector, 1, blocksize))
- return 20;
- } else {
- if (!sys_command_cd_read (dev->unitnum, temp, sector, 1))
- return 20;
- }
- if (startoffset > 0) {
- len = blocksize - startoffset;
- if (len > length)
- len = length;
- trap_memcpyha_safe(ctx, data, temp + startoffset, len);
- length -= len;
- data += len;
- startoffset = 0;
- *io_actual += len;
- } else if (length >= blocksize) {
- len = blocksize;
- trap_memcpyha_safe(ctx, data, temp, len);
- length -= len;
- data += len;
- *io_actual += len;
- } else {
- trap_memcpyha_safe(ctx, data, temp, length);
- *io_actual += length;
- length = 0;
- }
- sector++;
- }
- return 0;
- }
- static int dev_do_io_other(TrapContext *ctx, struct devstruct *dev, uae_u8 *iobuf, uaecptr request)
- {
- uae_u32 command;
- uae_u32 io_data = get_long_host(iobuf + 40); // 0x28
- uae_u32 io_length = get_long_host(iobuf + 36); // 0x24
- uae_u32 io_actual = get_long_host(iobuf + 32); // 0x20
- uae_u32 io_offset = get_long_host(iobuf + 44); // 0x2c
- uae_u32 io_error = 0;
- struct priv_devstruct *pdev = getpdevstruct(ctx, request);
- if (!pdev)
- return 0;
- command = get_word_host(iobuf + 28);
- if (log_scsi)
- write_log (_T("SCSI OTHER %d: DATA=%08X LEN=%08X OFFSET=%08X ACTUAL=%08X\n"),
- command, io_data, io_length, io_offset, io_actual);
- switch (command)
- {
- case CMD_UPDATE:
- case CMD_CLEAR:
- case CMD_FLUSH:
- case CMD_MOTOR:
- case CMD_SEEK:
- io_actual = 0;
- break;
- case CMD_GETDRIVETYPE:
- io_actual = dev->drivetype;
- break;
- case HD_SCSICMD:
- {
- uae_u32 sdd = get_long_host(iobuf + 40);
- io_error = sys_command_scsi_direct(ctx, dev->unitnum, dev->drivetype, sdd);
- if (log_scsi)
- write_log (_T("scsidev other: did io: sdd %08x request %08x error %d\n"), sdd, request, get_byte (request + 31));
- }
- break;
- default:
- io_error = IOERR_NOCMD;
- break;
- }
- put_long_host(iobuf + 32, io_actual);
- put_byte_host(iobuf + 31, io_error);
- io_log (_T("dev_io_other"), iobuf, request);
- return 0;
- }
- static int dev_do_io_tape (TrapContext *ctx, struct devstruct *dev, uae_u8 *iobuf, uaecptr request)
- {
- uae_u32 command;
- uae_u32 io_data = get_long_host(iobuf + 40); // 0x28
- uae_u32 io_length = get_long_host(iobuf + 36); // 0x24
- uae_u32 io_actual = get_long_host(iobuf + 32); // 0x20
- uae_u32 io_offset = get_long_host(iobuf + 44); // 0x2c
- uae_u32 io_error = 0;
- struct priv_devstruct *pdev = getpdevstruct(ctx, request);
- if (!pdev)
- return 0;
- command = get_word_host(iobuf + 28);
- if (log_scsi)
- write_log (_T("TAPE %d: DATA=%08X LEN=%08X OFFSET=%08X ACTUAL=%08X\n"),
- command, io_data, io_length, io_offset, io_actual);
- switch (command)
- {
- case CMD_UPDATE:
- case CMD_CLEAR:
- case CMD_FLUSH:
- case CMD_MOTOR:
- case CMD_SEEK:
- io_actual = 0;
- break;
- case CMD_GETDRIVETYPE:
- io_actual = dev->drivetype;
- break;
- case HD_SCSICMD:
- {
- uae_u32 sdd = get_long_host(iobuf + 40);
- io_error = sys_command_scsi_direct(ctx, dev->unitnum, INQ_SEQD, sdd);
- if (log_scsi)
- write_log (_T("scsidev tape: did io: sdd %08x request %08x error %d\n"), sdd, request, get_byte (request + 31));
- }
- break;
- default:
- io_error = IOERR_NOCMD;
- break;
- }
- put_long_host(iobuf + 32, io_actual);
- put_byte_host(iobuf + 31, io_error);
- io_log (_T("dev_io_tape"), iobuf, request);
- return 0;
- }
- static int dev_do_io_cd (TrapContext *ctx, struct devstruct *dev, uae_u8 *iobuf, uaecptr request)
- {
- uae_u32 command;
- uae_u32 io_data = get_long_host(iobuf + 40); // 0x28
- uae_u32 io_length = get_long_host(iobuf + 36); // 0x24
- uae_u32 io_actual = get_long_host(iobuf + 32); // 0x20
- uae_u32 io_offset = get_long_host(iobuf + 44); // 0x2c
- uae_u32 io_error = 0;
- uae_u64 io_offset64;
- int async = 0;
- int bmask = dev->di.bytespersector - 1;
- struct priv_devstruct *pdev = getpdevstruct(ctx, request);
- if (!pdev)
- return 0;
- command = get_word_host(iobuf + 28);
- if (log_scsi)
- write_log (_T("CD %d: DATA=%08X LEN=%08X OFFSET=%08X ACTUAL=%08X\n"),
- command, io_data, io_length, io_offset, io_actual);
- switch (command)
- {
- case CMD_READ:
- if (dev->di.media_inserted <= 0)
- goto no_media;
- if (dev->drivetype == INQ_ROMD) {
- io_error = command_cd_read(ctx, dev, io_data, io_offset, io_length, &io_actual);
- } else {
- if ((io_offset & bmask) || bmask == 0 || io_data == 0)
- goto bad_command;
- if ((io_length & bmask) || io_length == 0)
- goto bad_len;
- io_error = command_read(ctx, dev, io_data, io_offset, io_length, &io_actual);
- }
- break;
- case TD_READ64:
- case NSCMD_TD_READ64:
- if (dev->di.media_inserted <= 0)
- goto no_media;
- io_offset64 = get_long_host(iobuf + 44) | ((uae_u64)get_long_host(iobuf + 32) << 32);
- if ((io_offset64 & bmask) || bmask == 0 || io_data == 0)
- goto bad_command;
- if ((io_length & bmask) || io_length == 0)
- goto bad_len;
- if (dev->drivetype == INQ_ROMD)
- io_error = command_cd_read(ctx, dev, io_data, io_offset64, io_length, &io_actual);
- else
- io_error = command_read(ctx, dev, io_data, io_offset64, io_length, &io_actual);
- break;
- case CMD_WRITE:
- if (dev->di.media_inserted <= 0)
- goto no_media;
- if (dev->di.write_protected || dev->drivetype == INQ_ROMD) {
- io_error = 28; /* writeprotect */
- } else if ((io_offset & bmask) || bmask == 0 || io_data == 0) {
- goto bad_command;
- } else if ((io_length & bmask) || io_length == 0) {
- goto bad_len;
- } else {
- io_error = command_write(ctx, dev, io_data, io_offset, io_length, &io_actual);
- }
- break;
- case TD_WRITE64:
- case NSCMD_TD_WRITE64:
- if (dev->di.media_inserted <= 0)
- goto no_media;
- io_offset64 = get_long_host(iobuf + 44) | ((uae_u64)get_long_host(iobuf + 32) << 32);
- if (dev->di.write_protected || dev->drivetype == INQ_ROMD) {
- io_error = 28; /* writeprotect */
- } else if ((io_offset64 & bmask) || bmask == 0 || io_data == 0) {
- goto bad_command;
- } else if ((io_length & bmask) || io_length == 0) {
- goto bad_len;
- } else {
- io_error = command_write(ctx, dev, io_data, io_offset64, io_length, &io_actual);
- }
- break;
- case CMD_FORMAT:
- if (dev->di.media_inserted <= 0)
- goto no_media;
- if (dev->di.write_protected || dev->drivetype == INQ_ROMD) {
- io_error = 28; /* writeprotect */
- } else if ((io_offset & bmask) || bmask == 0 || io_data == 0) {
- goto bad_command;
- } else if ((io_length & bmask) || io_length == 0) {
- goto bad_len;
- } else {
- io_error = command_write(ctx, dev, io_data, io_offset, io_length, &io_actual);
- }
- break;
- case TD_FORMAT64:
- case NSCMD_TD_FORMAT64:
- if (dev->di.media_inserted <= 0)
- goto no_media;
- io_offset64 = get_long_host(iobuf + 44) | ((uae_u64)get_long_host(iobuf + 32) << 32);
- if (dev->di.write_protected || dev->drivetype == INQ_ROMD) {
- io_error = 28; /* writeprotect */
- } else if ((io_offset64 & bmask) || bmask == 0 || io_data == 0) {
- goto bad_command;
- } else if ((io_length & bmask) || io_length == 0) {
- goto bad_len;
- } else {
- io_error = command_write(ctx, dev, io_data, io_offset64, io_length, &io_actual);
- }
- break;
- case CMD_UPDATE:
- case CMD_CLEAR:
- case CMD_FLUSH:
- case CMD_MOTOR:
- case CMD_SEEK:
- io_actual = 0;
- break;
- case CMD_REMOVE:
- io_actual = dev->changeint;
- dev->changeint = io_data;
- dev->changeint_mediastate = dev->di.media_inserted;
- break;
- case CMD_CHANGENUM:
- io_actual = dev->changenum;
- break;
- case CMD_CHANGESTATE:
- if (dev->di.media_inserted >= 0) {
- io_actual = devinfo (dev, &dev->di)->media_inserted > 0 ? 0 : 1;
- } else {
- io_actual = 1;
- }
- break;
- case CMD_PROTSTATUS:
- io_actual = devinfo (dev, &dev->di)->write_protected ? -1 : 0;
- break;
- case CMD_GETDRIVETYPE:
- io_actual = dev->drivetype;
- break;
- case CMD_GETNUMTRACKS:
- if (dev->di.media_inserted <= 0)
- goto no_media;
- io_actual = dev->di.cylinders;
- break;
- case CMD_GETGEOMETRY:
- {
- struct device_info *di;
- uae_u8 geom[30];
- di = devinfo (dev, &dev->di);
- if (di->media_inserted <= 0)
- goto no_media;
- put_long_host(geom + 0, di->bytespersector);
- put_long_host(geom + 4, di->sectorspertrack * di->trackspercylinder * di->cylinders);
- put_long_host(geom + 8, di->cylinders);
- put_long_host(geom + 12, di->sectorspertrack * di->trackspercylinder);
- put_long_host(geom + 16, di->trackspercylinder);
- put_long_host(geom + 20, di->sectorspertrack);
- put_long_host(geom + 24, 0); /* bufmemtype */
- put_byte_host(geom + 28, di->type);
- put_byte_host(geom + 29, di->removable ? 1 : 0); /* flags */
- trap_put_bytes(ctx, geom, io_data, sizeof geom);
- io_actual = 30;
- }
- break;
- case CMD_ADDCHANGEINT:
- dev->changeint_mediastate = dev->di.media_inserted;
- io_error = add_async_request (dev, iobuf, request, ASYNC_REQUEST_CHANGEINT, io_data);
- if (!io_error)
- async = 1;
- break;
- case CMD_REMCHANGEINT:
- release_async_request (dev, request);
- break;
- case CD_TOCLSN:
- case CD_TOCMSF:
- {
- int msf = command == CD_TOCMSF;
- struct cd_toc_head toc;
- if (sys_command_cd_toc (dev->di.unitnum, &toc)) {
- if (io_offset == 0 && io_length > 0) {
- int pos = toc.lastaddress;
- trap_put_byte(ctx, io_data, toc.first_track);
- trap_put_byte(ctx, io_data + 1, toc.last_track);
- if (msf)
- pos = lsn2msf (pos);
- trap_put_long(ctx, io_data + 2, pos);
- io_offset++;
- io_length--;
- io_data += 6;
- io_actual++;
- }
- for (int i = toc.first_track_offset; i < toc.last_track_offset && io_length > 0; i++) {
- if (io_offset == toc.toc[i].point) {
- int pos = toc.toc[i].paddress;
- trap_put_byte(ctx, io_data, (toc.toc[i].control << 4) | toc.toc[i].adr);
- trap_put_byte(ctx, io_data + 1, toc.toc[i].point);
- if (msf)
- pos = lsn2msf (pos);
- trap_put_long(ctx, io_data + 2, pos);
- io_offset++;
- io_length--;
- io_data += 6;
- io_actual++;
- }
- }
- } else {
- io_error = IOERR_NotSpecified;
- }
- }
- break;
- case CD_ADDFRAMEINT:
- io_error = add_async_request (dev, iobuf, request, ASYNC_REQUEST_FRAMEINT, io_data);
- if (!io_error)
- async = 1;
- break;
- case CD_REMFRAMEINT:
- release_async_request (dev, request);
- break;
- case CD_ATTENUATE:
- {
- if (io_offset != -1) {
- dev->fadeframes = io_length & 0x7fff;
- dev->fadetarget = io_offset & 0x7fff;
- }
- io_actual = dev->volumelevel;
- }
- break;
- case CD_INFO:
- {
- uae_u16 status = 0;
- struct cd_toc_head toc;
- uae_u8 cdinfo[34] = { 0 };
- uae_u8 subq[SUBQ_SIZE] = { 0 };
- sys_command_cd_qcode (dev->di.unitnum, subq, -1, false);
- status |= 1 << 0; // door closed
- if (dev->di.media_inserted) {
- status |= 1 << 1;
- status |= 1 << 2; // motor on
- if (sys_command_cd_toc (dev->di.unitnum, &toc)) {
- status |= 1 << 3; // toc
- if (subq[1] == AUDIO_STATUS_IN_PROGRESS || subq[1] == AUDIO_STATUS_PAUSED)
- status |= 1 << 5; // audio play
- if (subq[1] == AUDIO_STATUS_PAUSED)
- status |= 1 << 6; // paused
- if (isdatatrack (&toc, 0))
- status |= 1 << 4; // data track
- }
- }
- put_word_host(cdinfo + 0, 75); // PlaySpeed
- put_word_host(cdinfo + 2, 1200); // ReadSpeed (randomly chose 16x)
- put_word_host(cdinfo + 4, 1200); // ReadXLSpeed
- put_word_host(cdinfo + 6, dev->configblocksize); // SectorSize
- put_word_host(cdinfo + 8, -1); // XLECC
- put_word_host(cdinfo + 10, 0); // EjectReset
- put_word_host(cdinfo + 12, 0); // Reserved * 4
- put_word_host(cdinfo + 14, 0);
- put_word_host(cdinfo + 16, 0);
- put_word_host(cdinfo + 18, 0);
- put_word_host(cdinfo + 20, 1200); // MaxSpeed
- put_word_host(cdinfo + 22, 0xffff); // AudioPrecision (volume)
- put_word_host(cdinfo + 24, status); // Status
- put_word_host(cdinfo + 26, 0); // Reserved2 * 4
- put_word_host(cdinfo + 28, 0);
- put_word_host(cdinfo + 30, 0);
- put_word_host(cdinfo + 32, 0);
- io_actual = 34;
- trap_put_bytes(ctx, cdinfo, io_data, io_actual);
- }
- break;
- case CD_CONFIG:
- {
- while (trap_get_long(ctx, io_data) != TAG_DONE) {
- uae_u32 tag = trap_get_long(ctx, io_data);
- uae_u32 data = trap_get_long(ctx, io_data + 4);
- if (tag == 4) {
- // TAGCD_SECTORSIZE
- if (data == 2048 || data == 2336 || data == 2352)
- dev->configblocksize = data;
- else
- io_error = IOERR_BADADDRESS;
- }
- io_data += 8;
- }
- break;
- }
- case CD_PAUSE:
- {
- int old = sys_command_cd_pause (dev->di.unitnum, io_length);
- if (old >= 0)
- io_actual = old;
- else
- io_error = IOERR_BADADDRESS;
- break;
- }
- case CD_PLAYLSN:
- {
- int start = io_offset;
- int end = io_length + start;
- if (!sys_command_cd_play (dev->di.unitnum, start, end, 0))
- io_error = IOERR_BADADDRESS;
- }
- break;
- case CD_PLAYMSF:
- {
- int start = msf2lsn (io_offset);
- int end = msf2lsn (io_length) + start;
- if (!sys_command_cd_play (dev->di.unitnum, start, end, 0))
- io_error = IOERR_BADADDRESS;
- }
- break;
- case CD_PLAYTRACK:
- {
- struct cd_toc_head toc;
- int ok = 0;
- if (sys_command_cd_toc (dev->di.unitnum, &toc)) {
- for (int i = toc.first_track_offset; i < toc.last_track_offset; i++) {
- if (i == io_offset && i + io_length <= toc.last_track_offset) {
- ok = sys_command_cd_play (dev->di.unitnum, toc.toc[i].address, toc.toc[i + io_length].address, 0);
- break;
- }
- }
- }
- if (!ok)
- io_error = IOERR_BADADDRESS;
- }
- break;
- case CD_QCODEMSF:
- case CD_QCODELSN:
- {
- uae_u8 subq[SUBQ_SIZE];
- if (sys_command_cd_qcode (dev->di.unitnum, subq, -1, false)) {
- if (subq[1] == AUDIO_STATUS_IN_PROGRESS || subq[1] == AUDIO_STATUS_PAUSED) {
- uae_u8 subqdata[12];
- put_byte_host(subqdata + 0, subq[4 + 0]);
- put_byte_host(subqdata + 1, frombcd (subq[4 + 1]));
- put_byte_host(subqdata + 2, frombcd (subq[4 + 2]));
- put_byte_host(subqdata + 3, subq[4 + 6]);
- int trackpos = fromlongbcd (subq + 4 + 3);
- int diskpos = fromlongbcd (subq + 4 + 7);
- if (command == CD_QCODELSN) {
- trackpos = msf2lsn (trackpos);
- diskpos = msf2lsn (diskpos);
- }
- put_long_host(subqdata + 4, trackpos);
- put_long_host(subqdata + 8, diskpos);
- io_actual = 12;
- trap_put_bytes(ctx, subqdata, io_data, io_actual);
- } else {
- io_error = IOERR_InvalidState;
- }
- } else {
- io_error = IOERR_BADADDRESS;
- }
- }
- break;
- case HD_SCSICMD:
- {
- uae_u32 sdd = get_long_host(iobuf + 40);
- io_error = sys_command_scsi_direct(ctx, dev->unitnum, INQ_ROMD, sdd);
- io_actual = 0;
- if (log_scsi)
- write_log (_T("scsidev cd: did io: sdd %08x request %08x error %d\n"), sdd, request, io_error);
- }
- break;
- case NSCMD_DEVICEQUERY:
- trap_put_long(ctx, io_data + 0, 0);
- trap_put_long(ctx, io_data + 4, 16); /* size */
- trap_put_word(ctx, io_data + 8, NSDEVTYPE_TRACKDISK);
- trap_put_word(ctx, io_data + 10, 0);
- trap_put_long(ctx, io_data + 12, nscmd_cmd);
- io_actual = 16;
- break;
- default:
- io_error = IOERR_NOCMD;
- break;
- bad_len:
- io_error = IOERR_BADLENGTH;
- break;
- bad_command:
- io_error = IOERR_BADADDRESS;
- break;
- no_media:
- io_error = TDERR_DiskChanged;
- break;
- }
- put_long_host(iobuf + 32, io_actual);
- put_byte_host(iobuf + 31, io_error);
- io_log (_T("dev_io_cd"), iobuf, request);
- return async;
- }
- static int dev_do_io(TrapContext *ctx, struct devstruct *dev, uae_u8 *iobuf, uaecptr request)
- {
- if (dev->drivetype == INQ_SEQD) {
- return dev_do_io_tape(ctx, dev, iobuf, request);
- } else if (dev->drivetype == INQ_ROMD) {
- return dev_do_io_cd(ctx, dev, iobuf, request);
- } else {
- return dev_do_io_other(ctx, dev, iobuf, request);
- }
- }
- static int dev_can_quick(uae_u32 command)
- {
- switch (command)
- {
- case CMD_RESET:
- case CMD_STOP:
- case CMD_START:
- case CMD_CHANGESTATE:
- case CMD_PROTSTATUS:
- case CMD_GETDRIVETYPE:
- return 1;
- case CMD_GETNUMTRACKS:
- case CMD_ADDCHANGEINT:
- case CMD_REMCHANGEINT:
- case CD_ADDFRAMEINT:
- case CD_REMFRAMEINT:
- return -1;
- }
- return 0;
- }
- static int dev_canquick(struct devstruct *dev, uae_u8 *iobuf, uaecptr request)
- {
- uae_u32 command = get_word_host(iobuf + 28);
- return dev_can_quick (command);
- }
- static uae_u32 REGPARAM2 dev_beginio(TrapContext *ctx)
- {
- uae_u32 request = trap_get_areg(ctx, 1);
- uae_u8 *iobuf = xmalloc(uae_u8, 48);
- trap_get_bytes(ctx, iobuf, request, 48);
- uae_u8 flags = get_byte_host(iobuf + 30);
- int command = get_word_host(iobuf + 28);
- struct priv_devstruct *pdev = getpdevstruct(ctx, request);
- struct devstruct *dev;
- int canquick;
- put_byte_host(iobuf + 8, NT_MESSAGE);
- if (!pdev) {
- uae_u8 err = 32;
- put_byte_host(iobuf + 31, err);
- trap_put_bytes(ctx, iobuf + 8, request + 8, 48 - 8);
- xfree(iobuf);
- return err;
- }
- dev = getdevstruct (pdev->unit);
- if (!dev) {
- uae_u8 err = 32;
- put_byte_host(iobuf + 31, err);
- trap_put_bytes(ctx, iobuf + 8, request + 8, 48 - 8);
- xfree(iobuf);
- return err;
- }
- put_byte_host(iobuf + 31, 0);
- canquick = dev_canquick (dev, iobuf, request);
- if (((flags & 1) && canquick) || (canquick < 0)) {
- bool async = dev_do_io(ctx, dev, iobuf, request) != 0;
- uae_u8 v = get_byte_host(iobuf + 31);
- trap_put_bytes(ctx, iobuf + 8, request + 8, 48 - 8);
- if (!async)
- xfree(iobuf);
- if (!(flags & 1) && !async)
- uae_ReplyMsg (request);
- return v;
- } else {
- add_async_request (dev, iobuf, request, ASYNC_REQUEST_TEMP, 0);
- put_byte_host(iobuf + 30, get_byte_host(iobuf + 30) & ~1);
- trap_put_bytes(ctx, iobuf + 8, request + 8, 48 - 8);
- trap_set_background(ctx);
- write_comm_pipe_pvoid(&dev->requests, ctx, 0);
- write_comm_pipe_pvoid(&dev->requests, iobuf, 0);
- write_comm_pipe_u32(&dev->requests, request, 1);
- return 0;
- }
- }
- static void dev_thread (void *devs)
- {
- struct devstruct *dev = (struct devstruct*)devs;
- uae_set_thread_priority (NULL, 1);
- dev->thread_running = 1;
- uae_sem_post (&dev->sync_sem);
- for (;;) {
- TrapContext *ctx = (TrapContext*)read_comm_pipe_pvoid_blocking(&dev->requests);
- uae_u8 *iobuf = (uae_u8*)read_comm_pipe_pvoid_blocking(&dev->requests);
- uaecptr request = (uaecptr)read_comm_pipe_u32_blocking (&dev->requests);
- uae_sem_wait (&change_sem);
- if (!request) {
- dev->thread_running = 0;
- uae_sem_post (&dev->sync_sem);
- uae_sem_post (&change_sem);
- return;
- } else if (dev_do_io(ctx, dev, iobuf, request) == 0) {
- put_byte_host(iobuf + 30, get_byte_host(iobuf + 30) & ~1);
- trap_put_bytes(ctx, iobuf + 8, request + 8, 48 - 8);
- release_async_request (dev, request);
- uae_ReplyMsg (request);
- } else {
- if (log_scsi)
- write_log (_T("%s:%d async request %08X\n"), getdevname(0), dev->unitnum, request);
- trap_put_bytes(ctx, iobuf + 8, request + 8, 48 - 8);
- }
- trap_background_set_complete(ctx);
- uae_sem_post (&change_sem);
- }
- }
- static uae_u32 REGPARAM2 dev_init_2(TrapContext *ctx, int type)
- {
- uae_u32 base = trap_get_dreg(ctx, 0);
- if (log_scsi)
- write_log (_T("%s init\n"), getdevname (type));
- return base;
- }
- static uae_u32 REGPARAM2 dev_init(TrapContext *ctx)
- {
- return dev_init_2(ctx, UAEDEV_SCSI_ID);
- }
- static uae_u32 REGPARAM2 diskdev_init(TrapContext *ctx)
- {
- return dev_init_2(ctx, UAEDEV_DISK_ID);
- }
- static uae_u32 REGPARAM2 dev_abortio (TrapContext *ctx)
- {
- uae_u32 request = trap_get_areg(ctx, 1);
- struct priv_devstruct *pdev = getpdevstruct(ctx, request);
- struct devstruct *dev;
- if (!pdev) {
- uae_u8 err = 32;
- trap_put_byte(ctx, request + 31, err);
- return err;
- }
- dev = getdevstruct (pdev->unit);
- if (!dev) {
- uae_u8 err = 32;
- trap_put_byte(ctx, request + 31, err);
- return err;
- }
- trap_put_byte(ctx, request + 31, IOERR_ABORTED);
- if (log_scsi)
- write_log (_T("abortio %s unit=%d, request=%08X\n"), getdevname (pdev->type), pdev->unit, request);
- abort_async(dev, request, IOERR_ABORTED, 0);
- return 0;
- }
- #define BTL2UNIT(bus, target, lun) (2 * (bus) + (target) / 8) * 100 + (lun) * 10 + (target % 8)
- uae_u32 scsi_get_cd_drive_mask (void)
- {
- uae_u32 mask = 0;
- for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
- struct devstruct *dev = &devst[i];
- if (dev->iscd)
- mask |= 1 << i;
- }
- return mask;
- }
- uae_u32 scsi_get_cd_drive_media_mask (void)
- {
- uae_u32 mask = 0;
- for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
- struct devstruct *dev = &devst[i];
- if (dev->iscd && dev->changeint_mediastate)
- mask |= 1 << i;
- }
- return mask;
- }
- int scsi_add_tape (struct uaedev_config_info *uci)
- {
- for (int i = 4; i < MAX_TOTAL_SCSI_DEVICES; i++) {
- struct devstruct *dev = &devst[i];
- if (dev->unitnum >= 0 || dev->drivetype > 0)
- continue;
- if (sys_command_open_tape (i, uci->rootdir, uci->readonly)) {
- dev->drivetype = INQ_SEQD;
- dev->aunit = i;
- dev->unitnum = i;
- dev->tape_directory = my_strdup (uci->rootdir);
- write_log (_T("%s:%d = '%s''\n"), UAEDEV_SCSI, dev->aunit, uci->rootdir);
- return i;
- }
- }
- return -1;
- }
- static void dev_reset (void)
- {
- int i, j;
- struct devstruct *dev;
- int unitnum = 0;
- for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
- dev = &devst[i];
- if (dev->opencnt > 0) {
- for (j = 0; j < MAX_ASYNC_REQUESTS; j++) {
- uaecptr request;
- if ((request = dev->d_request[i]))
- abort_async (dev, request, 0, 0);
- }
- dev->opencnt = 1;
- if (dev->unitnum >= 0)
- sys_command_close (dev->unitnum);
- }
- memset (dev, 0, sizeof (struct devstruct));
- xfree (dev->tape_directory);
- dev->unitnum = dev->aunit = -1;
- }
- for (i = 0; i < MAX_OPEN_DEVICES; i++)
- memset (&pdevst[i], 0, sizeof (struct priv_devstruct));
- device_func_init (0);
- i = 0;
- while (i < MAX_TOTAL_SCSI_DEVICES) {
- dev = &devst[i];
- struct device_info *discsi, discsi2;
- if (sys_command_open (i)) {
- discsi = sys_command_info (i, &discsi2, 0);
- if (discsi) {
- dev->unitnum = i;
- dev->drivetype = discsi->type;
- memcpy (&dev->di, discsi, sizeof (struct device_info));
- dev->changeint_mediastate = discsi->media_inserted;
- dev->configblocksize = discsi->bytespersector;
- if (discsi->type == INQ_ROMD)
- dev->iscd = 1;
- } else {
- sys_command_close (i);
- }
- }
- i++;
- }
- unitnum = 0;
- for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
- dev = &devst[i];
- if (dev->unitnum >= 0)
- sys_command_close (dev->unitnum);
- if (dev->unitnum >= 0 && dev->iscd) {
- dev->aunit = unitnum;
- dev->volumelevel = 0x7fff;
- unitnum++;
- }
- }
- if (unitnum == 0)
- unitnum = 1;
- for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
- dev = &devst[i];
- if (dev->unitnum >= 0) {
- if (!dev->iscd) {
- dev->aunit = unitnum;
- unitnum++;
- }
- write_log (_T("%s:%d = %s:'%s',%d\n"), UAEDEV_SCSI, dev->aunit, dev->di.backend, dev->di.label, dev->di.type);
- }
- dev->di.label[0] = 0;
- }
- }
- static uaecptr ROM_scsidev_resname = 0,
- ROM_scsidev_resid = 0,
- ROM_scsidev_init = 0;
- static uaecptr ROM_diskdev_resname = 0,
- ROM_diskdev_resid = 0,
- ROM_diskdev_init = 0;
- static uaecptr diskdev_startup (TrapContext *ctx, uaecptr resaddr)
- {
- /* Build a struct Resident. This will set up and initialize
- * the cd.device */
- if (log_scsi)
- write_log (_T("diskdev_startup(0x%x)\n"), resaddr);
- trap_put_word(ctx, resaddr + 0x0, 0x4AFC);
- trap_put_long(ctx, resaddr + 0x2, resaddr);
- trap_put_long(ctx, resaddr + 0x6, resaddr + 0x1A); /* Continue scan here */
- trap_put_word(ctx, resaddr + 0xA, 0x8101); /* RTF_AUTOINIT|RTF_COLDSTART; Version 1 */
- trap_put_word(ctx, resaddr + 0xC, 0x0305); /* NT_DEVICE; pri 05 */
- trap_put_long(ctx, resaddr + 0xE, ROM_diskdev_resname);
- trap_put_long(ctx, resaddr + 0x12, ROM_diskdev_resid);
- trap_put_long(ctx, resaddr + 0x16, ROM_diskdev_init);
- resaddr += 0x1A;
- return resaddr;
- }
- uaecptr scsidev_startup(TrapContext *ctx, uaecptr resaddr)
- {
- if (currprefs.scsi != 1)
- return resaddr;
- if (log_scsi)
- write_log (_T("scsidev_startup(0x%x)\n"), resaddr);
- /* Build a struct Resident. This will set up and initialize
- * the uaescsi.device */
- trap_put_word(ctx, resaddr + 0x0, 0x4AFC);
- trap_put_long(ctx, resaddr + 0x2, resaddr);
- trap_put_long(ctx, resaddr + 0x6, resaddr + 0x1A); /* Continue scan here */
- trap_put_word(ctx, resaddr + 0xA, 0x8101); /* RTF_AUTOINIT|RTF_COLDSTART; Version 1 */
- trap_put_word(ctx, resaddr + 0xC, 0x0305); /* NT_DEVICE; pri 05 */
- trap_put_long(ctx, resaddr + 0xE, ROM_scsidev_resname);
- trap_put_long(ctx, resaddr + 0x12, ROM_scsidev_resid);
- trap_put_long(ctx, resaddr + 0x16, ROM_scsidev_init); /* calls scsidev_init */
- resaddr += 0x1A;
- return resaddr;
- //return diskdev_startup(ctx, resaddr);
- }
- static void diskdev_install (void)
- {
- uae_u32 functable, datatable;
- uae_u32 initcode, openfunc, closefunc, expungefunc;
- uae_u32 beginiofunc, abortiofunc;
- if (currprefs.scsi != 1)
- return;
- if (log_scsi)
- write_log (_T("diskdev_install(): 0x%x\n"), here ());
- ROM_diskdev_resname = ds (UAEDEV_DISK);
- ROM_diskdev_resid = ds (_T("UAE disk.device 0.1"));
- /* initcode */
- initcode = here ();
- calltrap (deftrap (diskdev_init)); dw (RTS);
- /* Open */
- openfunc = here ();
- calltrap (deftrap (diskdev_open)); dw (RTS);
- /* Close */
- closefunc = here ();
- calltrap (deftrap (diskdev_close)); dw (RTS);
- /* Expunge */
- expungefunc = here ();
- calltrap (deftrap (diskdev_expunge)); dw (RTS);
- /* BeginIO */
- beginiofunc = here ();
- calltrap (deftrap (dev_beginio));
- dw (RTS);
- /* AbortIO */
- abortiofunc = here ();
- calltrap (deftrap (dev_abortio)); dw (RTS);
- /* FuncTable */
- functable = here ();
- dl (openfunc); /* Open */
- dl (closefunc); /* Close */
- dl (expungefunc); /* Expunge */
- dl (EXPANSION_nullfunc); /* Null */
- dl (beginiofunc); /* BeginIO */
- dl (abortiofunc); /* AbortIO */
- dl (0xFFFFFFFFul); /* end of table */
- /* DataTable */
- datatable = here ();
- dw (0xE000); /* INITBYTE */
- dw (0x0008); /* LN_TYPE */
- dw (0x0300); /* NT_DEVICE */
- dw (0xC000); /* INITLONG */
- dw (0x000A); /* LN_NAME */
- dl (ROM_diskdev_resname);
- dw (0xE000); /* INITBYTE */
- dw (0x000E); /* LIB_FLAGS */
- dw (0x0600); /* LIBF_SUMUSED | LIBF_CHANGED */
- dw (0xD000); /* INITWORD */
- dw (0x0014); /* LIB_VERSION */
- dw (0x0004); /* 0.4 */
- dw (0xD000); /* INITWORD */
- dw (0x0016); /* LIB_REVISION */
- dw (0x0000); /* end of table already ??? */
- dw (0xC000); /* INITLONG */
- dw (0x0018); /* LIB_IDSTRING */
- dl (ROM_diskdev_resid);
- dw (0x0000); /* end of table */
- ROM_diskdev_init = here ();
- dl (0x00000100); /* size of device base */
- dl (functable);
- dl (datatable);
- dl (initcode);
- }
- void scsidev_install (void)
- {
- uae_u32 functable, datatable;
- uae_u32 initcode, openfunc, closefunc, expungefunc;
- uae_u32 beginiofunc, abortiofunc;
- if (currprefs.scsi != 1)
- return;
- if (log_scsi)
- write_log (_T("scsidev_install(): 0x%x\n"), here ());
- ROM_scsidev_resname = ds (UAEDEV_SCSI);
- ROM_scsidev_resid = ds (_T("UAE scsi.device 0.2"));
- /* initcode */
- initcode = here ();
- calltrap (deftrap (dev_init)); dw (RTS);
- /* Open */
- openfunc = here ();
- calltrap (deftrap (dev_open)); dw (RTS);
- /* Close */
- closefunc = here ();
- calltrap (deftrap (dev_close)); dw (RTS);
- /* Expunge */
- expungefunc = here ();
- calltrap (deftrap (dev_expunge)); dw (RTS);
- /* BeginIO */
- beginiofunc = here ();
- calltrap (deftrap (dev_beginio));
- dw (RTS);
- /* AbortIO */
- abortiofunc = here ();
- calltrap (deftrap (dev_abortio)); dw (RTS);
- /* FuncTable */
- functable = here ();
- dl (openfunc); /* Open */
- dl (closefunc); /* Close */
- dl (expungefunc); /* Expunge */
- dl (EXPANSION_nullfunc); /* Null */
- dl (beginiofunc); /* BeginIO */
- dl (abortiofunc); /* AbortIO */
- dl (0xFFFFFFFFul); /* end of table */
- /* DataTable */
- datatable = here ();
- dw (0xE000); /* INITBYTE */
- dw (0x0008); /* LN_TYPE */
- dw (0x0300); /* NT_DEVICE */
- dw (0xC000); /* INITLONG */
- dw (0x000A); /* LN_NAME */
- dl (ROM_scsidev_resname);
- dw (0xE000); /* INITBYTE */
- dw (0x000E); /* LIB_FLAGS */
- dw (0x0600); /* LIBF_SUMUSED | LIBF_CHANGED */
- dw (0xD000); /* INITWORD */
- dw (0x0014); /* LIB_VERSION */
- dw (0x0004); /* 0.4 */
- dw (0xD000); /* INITWORD */
- dw (0x0016); /* LIB_REVISION */
- dw (0x0000);
- dw (0xC000); /* INITLONG */
- dw (0x0018); /* LIB_IDSTRING */
- dl (ROM_scsidev_resid);
- dw (0x0000); /* end of table */
- ROM_scsidev_init = here ();
- dl (0x00000100); /* size of device base */
- dl (functable);
- dl (datatable);
- dl (initcode);
- nscmd_cmd = here ();
- dw (NSCMD_DEVICEQUERY);
- dw (CMD_RESET);
- dw (CMD_READ);
- dw (CMD_WRITE);
- dw (CMD_UPDATE);
- dw (CMD_CLEAR);
- dw (CMD_START);
- dw (CMD_STOP);
- dw (CMD_FLUSH);
- dw (CMD_MOTOR);
- dw (CMD_SEEK);
- dw (CMD_FORMAT);
- dw (CMD_REMOVE);
- dw (CMD_CHANGENUM);
- dw (CMD_CHANGESTATE);
- dw (CMD_PROTSTATUS);
- dw (CMD_GETDRIVETYPE);
- dw (CMD_GETGEOMETRY);
- dw (CMD_ADDCHANGEINT);
- dw (CMD_REMCHANGEINT);
- dw (HD_SCSICMD);
- dw (NSCMD_TD_READ64);
- dw (NSCMD_TD_WRITE64);
- dw (NSCMD_TD_SEEK64);
- dw (NSCMD_TD_FORMAT64);
- dw (0);
- diskdev_install ();
- }
- void scsidev_start_threads (void)
- {
- if (currprefs.scsi != 1) /* quite useless.. */
- return;
- if (log_scsi)
- write_log (_T("scsidev_start_threads()\n"));
- uae_sem_init (&change_sem, 0, 1);
- }
- void scsidev_reset (void)
- {
- if (currprefs.scsi != 1)
- return;
- dev_reset ();
- }
- uae_u8 *save_scsidev (int num, int *len, uae_u8 *dstptr)
- {
- uae_u8 *dstbak, *dst;
- struct priv_devstruct *pdev;
- struct devstruct *dev;
- pdev = &pdevst[num];
- if (!pdev->inuse)
- return NULL;
- if (dstptr)
- dstbak = dst = dstptr;
- else
- dstbak = dst = xmalloc (uae_u8, 1000);
- save_u32 (num);
- save_u32 (0);
- save_u32 (pdev->unit);
- save_u32 (pdev->type);
- save_u32 (pdev->mode);
- save_u32 (pdev->flags);
- dev = getdevstruct (pdev->unit);
- if (dev) {
- save_u32 (0);
- save_u32 (dev->aunit);
- save_u32 (dev->opencnt);
- save_u32 (dev->changenum);
- save_u32 (dev->changeint);
- save_u32 (dev->changeint_mediastate);
- save_u32 (dev->configblocksize);
- save_u32 (dev->fadecounter);
- save_u32 (dev->fadeframes);
- save_u32 (dev->fadetarget);
- for (int i = 0; i < MAX_ASYNC_REQUESTS; i++) {
- if (dev->d_request[i]) {
- save_u32 (dev->d_request[i]);
- save_u32 (dev->d_request_type[i]);
- save_u32 (dev->d_request_data[i]);
- }
- }
- save_u32 (0xffffffff);
- } else {
- save_u32 (0xffffffff);
- }
- *len = dst - dstbak;
- return dstbak;
- }
- uae_u8 *restore_scsidev (uae_u8 *src)
- {
- struct priv_devstruct *pdev;
- struct devstruct *dev;
- int i;
- int num = restore_u32 ();
- if (num == 0)
- dev_reset ();
- pdev = &pdevst[num];
- restore_u32 ();
- restore_u32 ();
- pdev->type = restore_u32 ();
- pdev->mode = restore_u32 ();
- pdev->flags = restore_u32 ();
- if (restore_u32 () != 0xffffffff) {
- dev = getdevstruct (pdev->unit);
- if (dev) {
- dev->aunit = restore_u32 ();
- dev->opencnt = restore_u32 ();
- dev->changenum = restore_u32 ();
- dev->changeint = restore_u32 ();
- dev->changeint_mediastate = restore_u32 ();
- dev->configblocksize = restore_u32 ();
- dev->fadecounter = restore_u32 ();
- dev->fadeframes = restore_u32 ();
- dev->fadetarget = restore_u32 ();
- i = 0;
- for (;;) {
- uae_u32 v = restore_u32 ();
- if (v == 0xffffffff)
- break;
- dev->d_request[i] = v;
- dev->d_request_type[i] = restore_u32 ();
- dev->d_request_data[i] = restore_u32 ();
- }
- }
- }
- return src;
- }