File:  [UNIX Amiga Emulator] / uae / hardfile.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:38:16 2018 UTC (8 years, 3 months ago) by root
Branches: MAIN, BSchmidt
CVS tags: uae060, HEAD
uae-0.6.0

 /*
  * UAE - The Un*x Amiga Emulator
  *
  * AutoConfig devices
  *
  * (c) 1995 Bernd Schmidt
  */

#include "sysconfig.h"
#include "sysdeps.h"

#include "config.h"
#include "options.h"
#include "events.h"
#include "memory.h"
#include "custom.h"
#include "newcpu.h"
#include "disk.h"
#include "xwin.h"
#include "autoconf.h"
#include "hardfile.h"

static int opencount = 0;
static int uaedevfd;
static int numtracks = 512;

static ULONG dosname, uaedevname;

static ULONG hardfile_init(void)
{
    ULONG tmp1, tmp2, tmp3,configdev;
    int have36 = 1;
    ULONG retval = regs.d[0];

    if (!automount_uaedev)
	return retval;

    regs.d[0] = 88; regs.d[1] = 1; /* MEMF_PUBLIC */
    tmp1 = CallLib (regs.a[6], -198); /* AllocMem() */
    if (tmp1 == 0) {
	fprintf(stderr, "Not enough memory for uae.device!\n");
	return 0;
    }
    /* Open expansion.lib */
    regs.d[0] = 36; /* Let's try this... */
    regs.a[1] = explibname;
    regs.a[4] = CallLib (regs.a[6], -552); /* OpenLibrary() */
    if (regs.a[4])
	have36 = 1;
    else {
	regs.d[0] = 0;
	regs.a[1] = explibname;
	regs.a[4] = CallLib (regs.a[6], -552); /* OpenLibrary() */
    }
    put_long (tmp1, dosname);
    put_long (tmp1+4, uaedevname);
    put_long (tmp1+8, 0); /* Unit no. */
    put_long (tmp1+12, 0); /* Device flags */
    put_long (tmp1+16, 16); /* Env. size */
    put_long (tmp1+20, 128); /* 512 bytes/block */
    put_long (tmp1+24, 0); /* unused */
    put_long (tmp1+28, 1); /* heads */
    put_long (tmp1+32, 1); /* unused */
    put_long (tmp1+36, 32); /* secs per track */
    put_long (tmp1+40, 1); /* reserved blocks */
    put_long (tmp1+44, 0); /* unused */
    put_long (tmp1+48, 0); /* interleave */
    put_long (tmp1+52, 0); /* lowCyl */
#ifndef __DOS__
    put_long (tmp1+56, 511); /* upperCyl */
#else
    put_long (tmp1+56, numtracks-1); /* upperCyl */
#endif
    put_long (tmp1+60, 0); /* Number of buffers */
    put_long (tmp1+64, 0); /* Buffer mem type */
    put_long (tmp1+68, 0x7FFFFFFF); /* largest transfer */
    put_long (tmp1+72, ~1); /* addMask (?) */
    put_long (tmp1+76, (ULONG)-1); /* bootPri */
    if (have36)
	put_long (tmp1+80, 0x444f5301); /* DOS\1 */
    else
	put_long (tmp1+80, 0x444f5300); /* DOS\0 */


    put_long (tmp1+84, 0); /* pad */
    regs.a[0] = tmp1;
    tmp2 = CallLib (regs.a[4], -144); /* MakeDosNode() */

    configdev = CallLib(regs.a[4], -48); /* AllocConfigDev() */

    /* hier init der Configdev */

    regs.a[0] = tmp2;
    regs.d[0] = (ULONG)-1;
    regs.a[1] = configdev;
    regs.d[1] = 0;
#if 0
    CallLib (regs.a[4], -150); /* AddDosNode() */
#endif


#if 1
#if 1
    if (have36)
	CallLib (regs.a[4], /*-150*/ -36); /* AddDosNode() */
    else {
#endif
        /* We could also try to call AddBootNode() here - but we don't have
	 * a ConfigDev. */
	regs.d[0] = 20;
	regs.d[1] = 0;
	tmp3 = CallLib (regs.a[6], -198);
	if (tmp3 == 0) {
	    fprintf(stderr, "Not enough memory for uae.device bootnode!\n");
	    return 0;
	}
	put_word (tmp3 + 14, 0);
	put_long (tmp3 + 16, tmp2);
	put_word (tmp3 + 8, 0x1005);
	put_long (tmp3 + 10, 0);
	put_long (tmp3 + 0, 0);
	put_long (tmp3 + 4, 0);
	regs.a[0] = regs.a[4] + 74; /* MountList */
	regs.a[1] = tmp3;
	CallLib (regs.a[6], -270); /* Enqueue() */
#if 1
    }
#endif
#endif

    regs.a[1] = tmp1;
    regs.d[0] = 88;
    CallLib (regs.a[6], -210); /* FreeMem() */

    regs.a[1] = regs.a[4];
    CallLib (regs.a[6], -414); /* CloseLibrary() */

    return retval;
}

static ULONG hardfile_open(void)
{
    CPTR tmp1 = regs.a[1]; /* IOReq */

    /* Check unit number */
    if (regs.d[0] == 0) {
	opencount++;
	put_word (regs.a[6]+32, get_word (regs.a[6]+32) + 1);
	put_long (tmp1+24, 0); /* io_Unit */
	put_byte (tmp1+31, 0); /* io_Error */
	put_byte (tmp1+8, 7); /* ln_type = NT_REPLYMSG */
	return 0;
    }

    put_long (tmp1+20, (ULONG)-1);
    put_byte (tmp1+31, (UBYTE)-1);
    return (ULONG)-1;
}

static ULONG hardfile_close(void)
{
    opencount--;
    put_word (regs.a[6]+32, get_word (regs.a[6]+32) - 1);

    return regs.d[0];
}

static ULONG hardfile_expunge(void)
{
    return 0; /* Simply ignore this one... */
}

static ULONG hardfile_beginio(void)
{
    ULONG tmp1, tmp2, dataptr, offset;
    ULONG retval = regs.d[0];

    tmp1 = regs.a[1];
    put_byte (tmp1+8, 5); /* set ln_type to NT_MESSAGE */
    put_byte (tmp1+31, 0); /* no error yet */
    tmp2 = get_word (tmp1+28); /* io_Command */
    switch (tmp2) {
     case 2: /* Read */
	dataptr = get_long (tmp1 + 40);
	if (dataptr & 1)
	    goto bad_command;
	offset = get_long (tmp1 + 44);
	if (offset & 511)
	    goto bad_command;
	tmp2 = get_long (tmp1 + 36); /* io_Length */
	if (tmp2 & 511)
	    goto bad_command;
	if (tmp2 + offset > (ULONG)numtracks * 32 * 512)
	    goto bad_command;

	put_long (tmp1 + 32, tmp2); /* set io_Actual */
	lseek (uaedevfd, offset, SEEK_SET);
	while (tmp2) {
	    int i;
	    char buffer[512];
	    read (uaedevfd, buffer, 512);
	    for (i = 0; i < 512; i++, dataptr++)
		put_byte(dataptr, buffer[i]);
	    tmp2 -= 512;
	}
	break;

     case 3: /* Write */
     case 11: /* Format */
	dataptr = get_long (tmp1 + 40);
	if (dataptr & 1)
	    goto bad_command;
	offset = get_long (tmp1 + 44);
	if (offset & 511)
	    goto bad_command;
	tmp2 = get_long (tmp1 + 36); /* io_Length */
	if (tmp2 & 511)
	    goto bad_command;
	if (tmp2 + offset > (ULONG)numtracks * 32 * 512)
	    goto bad_command;

	put_long (tmp1 + 32, tmp2); /* set io_Actual */
	lseek (uaedevfd, offset, SEEK_SET);
	while (tmp2) {
	    char buffer[512];
	    int i;
	    for (i=0; i < 512; i++, dataptr++)
		buffer[i] = get_byte(dataptr);
	    write (uaedevfd, buffer, 512);
	    tmp2 -= 512;
	}
	break;

	bad_command:
	break;

     case 18: /* GetDriveType */
	put_long (tmp1 + 32, 1); /* not exactly a 3.5" drive, but... */
	break;

     case 19: /* GetNumTracks */
	put_long (tmp1 + 32, numtracks);
	break;

	/* Some commands that just do nothing and return zero */
     case 4: /* Update */
     case 5: /* Clear */
     case 9: /* Motor */
     case 10: /* Seek */
     case 12: /* Remove */
     case 13: /* ChangeNum */
     case 14: /* ChangeStatus */
     case 15: /* ProtStatus */
     case 20: /* AddChangeInt */
     case 21: /* RemChangeInt */
	put_long (tmp1+32, 0); /* io_Actual */
	retval = 0;
	break;

     default:
	/* Command not understood. */
	put_byte (tmp1+31, (UBYTE)-3); /* io_Error */
	retval = 0;
	break;
    }
    if ((get_byte (tmp1+30) & 1) == 0) {
	/* Not IOF_QUICK -- need to ReplyMsg */
	regs.a[1] = tmp1;
	CallLib (get_long(4), -378);
    }
    return retval;
}

static ULONG hardfile_abortio(void)
{
    return (ULONG)-3;
}

void hardfile_install(void)
{
    ULONG devid, functable, datatable, inittable, begin, end;
    ULONG initroutine, openfunc, closefunc, expungefunc;
    ULONG nullfunc, beginiofunc, abortiofunc;

    uaedevfd = open ("hardfile", O_RDWR | O_BINARY);

    if (uaedevfd < 0)
	return;

#ifdef __DOS__
    numtracks = filelength(uaedevfd) / 16384;
#endif

    uaedevname = ds("uae.device");
    devid = ds("uae 0.4"); /* ID */
    dosname = ds("UAEHF"); /* This is the DOS name */

    begin = here();
    dw(0x4AFC); /* RTC_MATCHWORD */
    dl(begin); /* our start address */
    dl(0); /* Continue scan here */
    dw(0x8101); /* RTF_AUTOINIT|RTF_COLDSTART; Version 1 */
    dw(0x0305); /* NT_DEVICE; pri 5 */
    dl(uaedevname); /* name */
    dl(devid); /* ID */
    dl(here() + 4); /* Init area: directly after this */
    /* Init area starts here */
    dw(0x0000); /* Not really sure what to put here */
    dw(0x0100);
    inittable = here();
    dl(0); dl(0); dl(0); /* skip 3 longs */

    /* InitRoutine */
    initroutine = here();
    calltrap(deftrap(hardfile_init)); dw(RTS);

    /* Open */
    openfunc = here();
    calltrap(deftrap(hardfile_open)); dw(RTS);

    /* Close */
    closefunc = here();
    calltrap(deftrap(hardfile_close)); dw(RTS);

    /* Expunge */
    expungefunc = here();
    calltrap(deftrap(hardfile_expunge)); dw(RTS);

    /* Null */
    nullfunc = here();
    dw(0x7000); /* return 0; */
    dw(RTS);

    /* BeginIO */
    beginiofunc = here();
    calltrap(deftrap(hardfile_beginio)); dw(RTS);

    /* AbortIO */
    abortiofunc = here();
    calltrap(deftrap(hardfile_abortio)); dw(RTS);

    /* FuncTable */
    functable = here();
    dl(openfunc); /* Open */
    dl(closefunc); /* Close */
    dl(expungefunc); /* Expunge */
    dl(nullfunc); /* Null */
    dl(beginiofunc); /* BeginIO */
    dl(abortiofunc); /* AbortIO */
    dl(0xFFFFFFFF); /* 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(uaedevname);
    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);
    dw(0x0016); /* LIB_REVISION */
    dw(0x0000);
    dw(0xC000);
    dw(0x0018); /* LIB_IDSTRING */
    dl(devid);
    dw(0x0000); /* end of table */

    end = here();

    org(inittable);
    dl(functable);
    dl(datatable);
    dl(initroutine);

    org(begin + 6);
    dl(end);

    org(end);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.