uae-wii/src/scsiemul.c
2009-05-05 15:36:48 +00:00

951 lines
23 KiB
C

/*
* 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 "uae.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 "sleep.h"
#define CDDEV_COMMANDS
#define UAEDEV_SCSI "uaescsi.device"
#define UAEDEV_SCSI_ID 1
#define UAEDEV_DISK "uaedisk.device"
#define UAEDEV_DISK_ID 2
#define MAX_ASYNC_REQUESTS 20
#define MAX_OPEN_DEVICES 20
#define CMD_INVALID 0
#define CMD_RESET 1
#define CMD_READ 2
#define CMD_WRITE 3
#define CMD_UPDATE 4
#define CMD_CLEAR 5
#define CMD_STOP 6
#define CMD_START 7
#define CMD_FLUSH 8
#define CMD_MOTOR 9
#define CMD_SEEK 10
#define CMD_FORMAT 11
#define CMD_REMOVE 12
#define CMD_CHANGENUM 13
#define CMD_CHANGESTATE 14
#define CMD_PROTSTATUS 15
#define CMD_GETDRIVETYPE 18
#define CMD_GETNUMTRACKS 19
#define CMD_ADDCHANGEINT 20
#define CMD_REMCHANGEINT 21
#define CMD_GETGEOMETRY 22
#define CD_INFO 32
#define CD_CONFIG 33
#define CD_TOCMSF 34
#define CD_TOCLSN 35
#define CD_READXL 36
#define CD_PLAYTRACK 37
#define CD_PLAYMSF 38
#define CD_PLAYLSN 39
#define CD_PAUSE 40
#define CD_SEARCH 41
#define CD_QCODEMSF 42
#define CD_QCODELSN 43
#define CD_ATTENUATE 44
#define CD_ADDFRAMEINT 45
#define CD_REMFRAMEINT 46
#define ASYNC_REQUEST_NONE 0
#define ASYNC_REQUEST_TEMP 1
#define ASYNC_REQUEST_CHANGEINT 10
#define ASYNC_REQUEST_FRAMEINT 11
#define ASYNC_REQUEST_PLAY 12
#define ASYNC_REQUEST_READXL 13
#define ASYNC_REQUEST_FRAMECALL 14
struct devstruct {
int unitnum, aunit;
int opencnt;
int changenum;
int allow_scsi;
int allow_ioctl;
int drivetype;
int iscd;
volatile uaecptr d_request[MAX_ASYNC_REQUESTS];
volatile int d_request_type[MAX_ASYNC_REQUESTS];
volatile uae_u32 d_request_data[MAX_ASYNC_REQUESTS];
struct device_info di;
smp_comm_pipe requests;
uae_thread_id tid;
int thread_running;
uae_sem_t sync_sem;
};
struct priv_devstruct {
int inuse;
int unit;
int mode;
int scsi;
int ioctl;
int noscsi;
int type;
int flags; /* OpenDevice() */
};
static struct devstruct devst[MAX_TOTAL_DEVICES];
static struct priv_devstruct pdevst[MAX_OPEN_DEVICES];
static uae_sem_t change_sem;
static struct device_info *devinfo (int mode, int unitnum, struct device_info *di)
{
return sys_command_info (mode, unitnum, di);
}
static void io_log (const char *msg, uaecptr request)
{
if (log_scsi)
write_log ("%s: %08X %d %08.8X %d %d io_actual=%d io_error=%d\n",
msg, request,get_word(request + 28),get_long(request + 40),get_long(request + 36),get_long(request + 44),
get_long (request + 32), get_byte (request + 31));
}
STATIC_INLINE void memcpyha (uae_u32 dst, const uae_u8 *src, int size)
{
while (size--)
put_byte (dst++, *src++);
}
STATIC_INLINE struct devstruct *getdevstruct (int unit)
{
int i;
for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
if (unit >= 0 && devst[i].aunit == unit) return &devst[i];
}
return 0;
}
static struct priv_devstruct *getpdevstruct (uaecptr request)
{
int i = get_long (request + 24);
if (i < 0 || i >= MAX_OPEN_DEVICES || pdevst[i].inuse == 0) {
write_log ("uaescsi.device: corrupt iorequest %08.8X %d\n", request, i);
return 0;
}
return &pdevst[i];
}
static const char *getdevname (int type)
{
switch (type) {
case UAEDEV_SCSI_ID:
return UAEDEV_SCSI;
case UAEDEV_DISK_ID:
return UAEDEV_DISK;
default:
abort ();
}
}
static void *dev_thread (void *devs);
static int start_thread (struct devstruct *dev)
{
if (dev->thread_running)
return 1;
init_comm_pipe (&dev->requests, 100, 1);
uae_sem_init (&dev->sync_sem, 0, 0);
uae_start_thread (dev_thread, dev, &dev->tid);
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) {
if (pdev->scsi)
sys_command_close (DF_SCSI, dev->unitnum);
if (pdev->ioctl)
sys_command_close (DF_IOCTL, dev->unitnum);
pdev->inuse = 0;
write_comm_pipe_u32 (&dev->requests, 0, 1);
}
}
static uae_u32 REGPARAM2 dev_close_2 (TrapContext *context)
{
uae_u32 request = m68k_areg (&context->regs, 1);
struct priv_devstruct *pdev = getpdevstruct (request);
struct devstruct *dev;
if (!pdev)
return 0;
dev = getdevstruct (pdev->unit);
if (log_scsi)
write_log ("%s:%d close, req=%08.8X\n", getdevname (pdev->type), pdev->unit, request);
if (!dev)
return 0;
dev_close_3 (dev, pdev);
put_long (request + 24, 0);
put_word (m68k_areg (&context->regs, 6) + 32, get_word (m68k_areg (&context->regs, 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 (uaecptr ioreq, int error)
{
put_long (ioreq + 20, -1);
put_byte (ioreq + 31, error);
return (uae_u32)-1;
}
static uae_u32 REGPARAM2 dev_open_2 (TrapContext *context, int type)
{
uaecptr ioreq = m68k_areg (&context->regs, 1);
uae_u32 unit = m68k_dreg (&context->regs, 0);
uae_u32 flags = m68k_dreg (&context->regs, 1);
struct devstruct *dev = getdevstruct (unit);
struct priv_devstruct *pdev = 0;
int i;
if (log_scsi)
write_log ("opening %s:%d ioreq=%08.8X\n", getdevname (type), unit, ioreq);
if (!dev)
return openfail (ioreq, 32); /* badunitnum */
if (!dev->opencnt) {
for (i = 0; i < MAX_OPEN_DEVICES; i++) {
pdev = &pdevst[i];
if (pdev->inuse == 0) break;
}
if (type == UAEDEV_SCSI_ID && sys_command_open (DF_SCSI, dev->unitnum)) {
pdev->scsi = 1;
pdev->mode = DF_SCSI;
}
if (type == UAEDEV_DISK_ID && sys_command_open (DF_IOCTL, dev->unitnum)) {
pdev->ioctl = 1;
pdev->mode = DF_IOCTL;
}
if (!pdev->scsi && !pdev->ioctl)
return openfail (ioreq, -1);
pdev->type = type;
pdev->unit = unit;
pdev->flags = flags;
pdev->inuse = 1;
put_long (ioreq + 24, pdev - pdevst);
start_thread (dev);
} else {
for (i = 0; i < MAX_OPEN_DEVICES; i++) {
pdev = &pdevst[i];
if (pdev->inuse && pdev->unit == (int)unit) break;
}
if (i == MAX_OPEN_DEVICES)
return openfail (ioreq, -1);
put_long (ioreq + 24, pdev - pdevst);
}
dev->opencnt++;
put_word (m68k_areg (&context->regs, 6) + 32, get_word (m68k_areg (&context->regs, 6) + 32) + 1);
put_byte (ioreq + 31, 0);
put_byte (ioreq + 8, 7);
return 0;
}
static uae_u32 REGPARAM2 dev_open (TrapContext *context)
{
return dev_open_2 (context, UAEDEV_SCSI_ID);
}
static uae_u32 REGPARAM2 diskdev_open (TrapContext *context)
{
return dev_open_2 (context, UAEDEV_DISK_ID);
}
static uae_u32 REGPARAM2 dev_expunge (TrapContext *context)
{
return 0;
}
static uae_u32 REGPARAM2 diskdev_expunge (TrapContext *context)
{
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;
}
void scsi_do_disk_change (int device_id, int insert)
{
int i, j;
uae_sem_wait (&change_sem);
for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
if (devst[i].di.id == device_id) {
devst[i].changenum++;
j = 0;
while (j < MAX_ASYNC_REQUESTS) {
if (devst[i].d_request_type[j] == ASYNC_REQUEST_CHANGEINT) {
uae_Cause (devst[i].d_request_data[j]);
}
j++;
}
}
}
uae_sem_post (&change_sem);
}
static int add_async_request (struct devstruct *dev, uaecptr request, int type, uae_u32 data)
{
int i;
if (log_scsi)
write_log ("async request %p (%d) added\n", request, type);
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[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 ("async request %p 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;
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 */
uae_msleep (10);
i = 0;
continue;
}
i++;
}
i = release_async_request (dev, request);
if (i >= 0 && log_scsi)
write_log ("asyncronous request=%08.8X aborted, error=%d\n", request, errcode);
}
static int command_read (int mode, struct devstruct *dev, uaecptr data, int offset, int length, uae_u32 *io_actual)
{
const uae_u8 *temp;
int len, sector;
int startoffset = offset % dev->di.bytespersector;
offset -= startoffset;
sector = offset / dev->di.bytespersector;
*io_actual = 0;
while (length > 0) {
temp = sys_command_read (mode, dev->unitnum, sector);
if (!temp) return 20;
if (startoffset > 0) {
len = dev->di.bytespersector - startoffset;
if (len > length) len = length;
memcpyha (data, temp + startoffset, len);
length -= len;
data += len;
startoffset = 0;
*io_actual += len;
} else if (length >= dev->di.bytespersector) {
len = dev->di.bytespersector;
memcpyha (data, temp, len);
length -= len;
data += len;
*io_actual += len;
} else {
memcpyha (data, temp, length);
*io_actual += length;
length = 0;
}
sector++;
}
return 0;
}
static int dev_do_io (struct devstruct *dev, uaecptr request)
{
uae_u32 command;
uae_u32 io_data = get_long (request + 40); // 0x28
uae_u32 io_length = get_long (request + 36); // 0x24
uae_u32 io_actual = get_long (request + 32); // 0x20
uae_u32 io_offset = get_long (request + 44); // 0x2c
uae_u32 io_error = 0;
int async = 0;
struct device_info di;
struct priv_devstruct *pdev = getpdevstruct (request);
if (!pdev)
return 0;
command = get_word (request+28);
switch (command)
{
case CMD_READ:
io_error = command_read (pdev->mode, dev, io_data, io_offset, io_length, &io_actual);
break;
case CMD_WRITE:
case CMD_FORMAT:
io_error = 28; /* writeprotect */
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 = 0;
break;
case CMD_CHANGENUM:
io_actual = dev->changenum;
break;
case CMD_CHANGESTATE:
io_actual = devinfo(pdev->mode, dev->unitnum, &di)->media_inserted ? 0 : 1;
break;
case CMD_PROTSTATUS:
io_actual = devinfo(pdev->mode, dev->unitnum, &di)->write_protected ? -1 : 0;
break;
case CMD_GETDRIVETYPE:
io_actual = dev->drivetype;
break;
case CMD_GETNUMTRACKS:
io_actual = dev->di.cylinders;
break;
case CMD_ADDCHANGEINT:
io_error = add_async_request (dev, request, ASYNC_REQUEST_CHANGEINT, io_data);
if (!io_error)
async = 1;
break;
case CMD_REMCHANGEINT:
release_async_request (dev, request);
break;
case 28: /* HD_SCSICMD */
if (dev->allow_scsi && pdev->scsi) {
uae_u32 sdd = get_long (request + 40);
io_error = sys_command_scsi_direct (dev->unitnum, sdd);
if (log_scsi)
write_log ("scsidev: did io: sdd %p request %p error %d\n", sdd, request, get_byte (request + 31));
}
break;
default:
io_error = -3;
break;
}
put_long (request + 32, io_actual);
put_byte (request + 31, io_error);
io_log ("dev_io",request);
return async;
}
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:
case CMD_GETNUMTRACKS:
return 1;
}
return 0;
}
static int dev_canquick (struct devstruct *dev, uaecptr request)
{
uae_u32 command = get_word (request + 28);
return dev_can_quick (command);
}
static uae_u32 REGPARAM2 dev_beginio (TrapContext *context)
{
uae_u32 request = m68k_areg (&context->regs, 1);
uae_u8 flags = get_byte (request + 30);
int command = get_word (request + 28);
struct priv_devstruct *pdev = getpdevstruct (request);
struct devstruct *dev = getdevstruct (pdev->unit);
put_byte (request+8, NT_MESSAGE);
if (!dev || !pdev) {
put_byte (request + 31, 32);
return get_byte (request + 31);
}
put_byte (request+31, 0);
if ((flags & 1) && dev_canquick (dev, request)) {
if (dev_do_io (dev, request))
write_log ("device %s command %d bug with IO_QUICK\n", getdevname (pdev->type), command);
return get_byte (request + 31);
} else {
add_async_request (dev, request, ASYNC_REQUEST_TEMP, 0);
put_byte (request+30, get_byte (request + 30) & ~1);
write_comm_pipe_u32 (&dev->requests, request, 1);
return 0;
}
}
static void *dev_thread (void *devs)
{
struct devstruct *dev = devs;
uae_set_thread_priority (2);
dev->thread_running = 1;
sys_command_open_thread (DF_SCSI, dev->unitnum);
sys_command_open_thread (DF_IOCTL, dev->unitnum);
uae_sem_post (&dev->sync_sem);
for (;;) {
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);
break;
} else if (dev_do_io (dev, request) == 0) {
put_byte (request + 30, get_byte (request + 30) & ~1);
release_async_request (dev, request);
uae_ReplyMsg (request);
} else {
if (log_scsi)
write_log ("async request %08.8X\n", request);
}
uae_sem_post (&change_sem);
}
sys_command_close_thread (DF_SCSI, dev->unitnum);
sys_command_close_thread (DF_IOCTL, dev->unitnum);
return 0;
}
static uae_u32 REGPARAM2 dev_init_2 (TrapContext *context, int type)
{
uae_u32 base = m68k_dreg (&context->regs,0);
if (log_scsi)
write_log ("%s init\n", getdevname (type));
return base;
}
static uae_u32 REGPARAM2 dev_init (TrapContext *context)
{
return dev_init_2 (context, UAEDEV_SCSI_ID);
}
static uae_u32 REGPARAM2 diskdev_init (TrapContext *context)
{
return dev_init_2 (context, UAEDEV_DISK_ID);
}
static uae_u32 REGPARAM2 dev_abortio (TrapContext *context)
{
uae_u32 request = m68k_areg (&context->regs, 1);
struct priv_devstruct *pdev = getpdevstruct (request);
struct devstruct *dev;
if (!pdev) {
put_byte (request + 31, 32);
return get_byte (request + 31);
}
dev = getdevstruct (pdev->unit);
if (!dev) {
put_byte (request + 31, 32);
return get_byte (request + 31);
}
put_byte (request + 31, -2);
if (log_scsi)
write_log ("abortio %s unit=%d, request=%08.8X\n", getdevname (pdev->type), pdev->unit, request);
abort_async (dev, request, -2, 0);
return 0;
}
#define BTL2UNIT(bus, target, lun) (2 * (bus) + (target) / 8) * 100 + (lun) * 10 + (target % 8)
/*
* Shut down SCSI layer
*/
static void dev_exit (void)
{
int i, j;
struct devstruct *dev;
for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
dev = &devst[i];
if (dev->opencnt > 0) {
/* Abort any outstanding requests */
for (j = 0; j < MAX_ASYNC_REQUESTS; j++) {
uaecptr request;
if ((request = dev->d_request[i]))
abort_async (dev, request, 0, 0);
}
/* Kill dev thread and wait for it to die */
write_comm_pipe_u32 (&dev->requests, 0, 1);
uae_sem_wait (&dev->sync_sem);
/* Close device */
dev->opencnt = 0;
sys_command_close (DF_SCSI, dev->unitnum);
sys_command_close (DF_IOCTL, dev->unitnum);
}
memset (dev, 0, sizeof (struct devstruct));
dev->unitnum = dev->aunit = -1;
}
}
static void dev_reset (void)
{
int i, j;
struct devstruct *dev;
struct device_info *discsi, discsi2;
int unitnum = 0;
device_func_init (DEVICE_TYPE_SCSI);
dev_exit();
for (i = 0; i < MAX_OPEN_DEVICES; i++)
memset (&pdevst[i], 0, sizeof (struct priv_devstruct));
i = j = 0;
while (i < MAX_TOTAL_DEVICES) {
dev = &devst[i];
discsi = 0;
if (sys_command_open (DF_SCSI, j)) {
discsi = sys_command_info (DF_SCSI, j, &discsi2);
sys_command_close (DF_SCSI, j);
}
if (discsi) {
dev->unitnum = j;
dev->allow_scsi = 1;
dev->drivetype = discsi->type;
memcpy (&dev->di, discsi, sizeof (struct device_info));
if (discsi->type == INQ_ROMD)
dev->iscd = 1;
}
i++;
j++;
}
unitnum = 0;
for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
dev = &devst[i];
if (dev->unitnum >= 0 && dev->iscd) {
dev->aunit = unitnum;
unitnum++;
}
}
if (unitnum == 0)
unitnum = 1;
for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
dev = &devst[i];
if (dev->unitnum >= 0) {
if (!dev->iscd) {
dev->aunit = unitnum;
unitnum++;
}
write_log ("%s = %s:%d\n", dev->di.label, UAEDEV_SCSI, dev->aunit);
}
}
}
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 (uaecptr resaddr)
{
/* Build a struct Resident. This will set up and initialize
* the cd.device */
if (log_scsi)
write_log ("diskdev_startup(0x%x)\n", resaddr);
put_word(resaddr + 0x0, 0x4AFC);
put_long(resaddr + 0x2, resaddr);
put_long(resaddr + 0x6, resaddr + 0x1A); /* Continue scan here */
put_word(resaddr + 0xA, 0x8101); /* RTF_AUTOINIT|RTF_COLDSTART; Version 1 */
put_word(resaddr + 0xC, 0x0305); /* NT_DEVICE; pri 05 */
put_long(resaddr + 0xE, ROM_diskdev_resname);
put_long(resaddr + 0x12, ROM_diskdev_resid);
put_long(resaddr + 0x16, ROM_diskdev_init);
resaddr += 0x1A;
return resaddr;
}
uaecptr scsidev_startup (uaecptr resaddr)
{
if (!currprefs.scsi)
return resaddr;
if (log_scsi)
write_log ("scsidev_startup(0x%x)\n", resaddr);
/* Build a struct Resident. This will set up and initialize
* the uaescsi.device */
put_word(resaddr + 0x0, 0x4AFC);
put_long(resaddr + 0x2, resaddr);
put_long(resaddr + 0x6, resaddr + 0x1A); /* Continue scan here */
put_word(resaddr + 0xA, 0x8101); /* RTF_AUTOINIT|RTF_COLDSTART; Version 1 */
put_word(resaddr + 0xC, 0x0305); /* NT_DEVICE; pri 05 */
put_long(resaddr + 0xE, ROM_scsidev_resname);
put_long(resaddr + 0x12, ROM_scsidev_resid);
put_long(resaddr + 0x16, ROM_scsidev_init); /* calls scsidev_init */
resaddr += 0x1A;
return resaddr;
return diskdev_startup (resaddr);
}
static void diskdev_install (void)
{
uae_u32 functable, datatable;
uae_u32 initcode, openfunc, closefunc, expungefunc;
uae_u32 beginiofunc, abortiofunc;
if (!currprefs.scsi)
return;
if (log_scsi)
write_log ("diskdev_install(): 0x%x\n", here ());
ROM_diskdev_resname = ds (UAEDEV_DISK);
ROM_diskdev_resid = ds ("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)
return;
if (log_scsi)
write_log ("scsidev_install(): 0x%x\n", here ());
ROM_scsidev_resname = ds (UAEDEV_SCSI);
ROM_scsidev_resid = ds ("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); /* end of table already ??? */
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);
diskdev_install ();
}
void scsidev_start_threads (void)
{
if (!currprefs.scsi) /* quite useless.. */
return;
if (log_scsi)
write_log ("scsidev_start_threads()\n");
uae_sem_init (&change_sem, 0, 1);
}
void scsidev_exit (void)
{
if (!currprefs.scsi)
return;
dev_exit ();
}
void scsidev_reset (void)
{
if (!currprefs.scsi)
return;
dev_reset ();
}