mirror of
https://github.com/prirun/p50em.git
synced 2026-01-21 01:48:11 +00:00
Removed os.[ch], ignore SIGPIPE, disk model support, 8 drives/controller
added CLEARCL macro to clean up code ignore SIGPIPE so broken socket doesn't kill emulator
This commit is contained in:
parent
55ea18c85e
commit
31f4e2e22e
4
ea32i.h
4
ea32i.h
@ -2,7 +2,6 @@
|
||||
|
||||
inline ea_t ea32i (ea_t earp, unsigned short inst, unsigned long *immu32, unsigned long long *immu64) {
|
||||
|
||||
#ifdef OSX
|
||||
int tm, sr, br, ring;
|
||||
unsigned short d;
|
||||
int temp32;
|
||||
@ -113,7 +112,4 @@ inline ea_t ea32i (ea_t earp, unsigned short inst, unsigned long *immu32, unsign
|
||||
fatal("ea32i: tm out of range!");
|
||||
}
|
||||
fatal("ea32i: main switch fall through");
|
||||
#else
|
||||
fatal("ea32i: not implemented");
|
||||
#endif
|
||||
}
|
||||
|
||||
204
em.c
204
em.c
@ -95,6 +95,7 @@ OK:
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
|
||||
/* In SR modes, Prime CPU registers are mapped to memory locations
|
||||
0-'37, but only 0-7 are user accessible. In the post-P300
|
||||
@ -149,11 +150,9 @@ typedef unsigned int pa_t; /* physical address */
|
||||
else if (*(int *)(crs+FLTH) == 0) \
|
||||
crs[KEYS] |= 0100;
|
||||
|
||||
/* this is probably incorrect - needs to test 16 more bits for denormal
|
||||
doubles.
|
||||
NOTE: actually, this behavior is correct: Prime only tested 32 bits
|
||||
of the fraction, even for double precision. It expected DP floats
|
||||
to be normalized, or mostly normalized. */
|
||||
/* NOTE: Prime only tested 32 bits of the fraction, even for double
|
||||
precision. It expected DP floats to be normalized, or mostly
|
||||
normalized. */
|
||||
|
||||
#define SETCC_D SETCC_F
|
||||
|
||||
@ -177,6 +176,7 @@ typedef unsigned int pa_t; /* physical address */
|
||||
if ((onoff)) crs[KEYS] |= 0120000
|
||||
|
||||
#define SETCL crs[KEYS] |= 0120000
|
||||
#define CLEARCL crs[KEYS] &= ~0120000
|
||||
|
||||
#define SETL(onoff) \
|
||||
if ((onoff)) crs[KEYS] |= 020000; \
|
||||
@ -197,6 +197,8 @@ typedef unsigned int pa_t; /* physical address */
|
||||
#define BLS if (crs[KEYS] & 020000) RPL = iget16(RP); else RPL++
|
||||
#define BXNE if (crs[X] != 0) RPL = iget16(RP); else RPL++
|
||||
#define BYNE if (crs[Y] != 0) RPL = iget16(RP); else RPL++
|
||||
#define BHNE(r) if (crs[(r)*2] != 0) RPL = iget16(RP); else RPL++;
|
||||
#define BRNE(r) if (crsl[(r)] != 0) RPL = iget16(RP); else RPL++;
|
||||
|
||||
/* expressions for logicize instructions */
|
||||
|
||||
@ -357,11 +359,15 @@ unsigned int instpermsec = 2000; /* initial assumption for inst/msec */
|
||||
jmp_buf jmpbuf; /* for longjumps to the fetch loop */
|
||||
|
||||
/* The standard Prime physical memory limit on early machines is 8MB.
|
||||
Later machines have higher memory capacities, up to 512M, using
|
||||
Later machines have higher memory capacities, up to 1024MB, using
|
||||
32-bit page tables.
|
||||
NOTE: rev 20 is limited to 32MB on all machines. */
|
||||
|
||||
#define MEMSIZE 16*1024*1024 /* 32 MB */
|
||||
NOTE:
|
||||
- rev 20 is limited to a max of 32MB
|
||||
- rev 23.4 is limited to a max of 128MB
|
||||
*/
|
||||
|
||||
#define MEMSIZE 256*1024*1024 /* 128 MB */
|
||||
unsigned short mem[MEMSIZE]; /* system's physical memory */
|
||||
|
||||
#define MAKEVA(seg,word) ((((int)(seg))<<16) | (word))
|
||||
@ -1686,7 +1692,11 @@ ea_t stex(unsigned int extsize) {
|
||||
}
|
||||
|
||||
/* for PRTN, load values into temps first so that if any faults occur,
|
||||
PRTN can be restarted */
|
||||
PRTN can be restarted
|
||||
|
||||
XXX: the order of this look wrong - stack free pointer shouldn't
|
||||
be updated if a fault occurs fetching base registers
|
||||
*/
|
||||
|
||||
void prtn() {
|
||||
unsigned short stackrootseg;
|
||||
@ -3034,7 +3044,7 @@ arfa(int n, int val) {
|
||||
|
||||
unsigned int lrs(unsigned int val, short scount) {
|
||||
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
if (scount <= 32) {
|
||||
EXPCL(val & bitmask32[33-scount]);
|
||||
return (*(int *)&val) >> scount;
|
||||
@ -3048,7 +3058,7 @@ unsigned int lrs(unsigned int val, short scount) {
|
||||
unsigned int lls(unsigned int val, short scount) {
|
||||
int templ;
|
||||
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
if (scount < 32) {
|
||||
templ = 0x80000000;
|
||||
templ = templ >> scount; /* create mask */
|
||||
@ -3064,7 +3074,7 @@ unsigned int lls(unsigned int val, short scount) {
|
||||
|
||||
unsigned int lll(unsigned int val, short scount) {
|
||||
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
if (scount <= 32) {
|
||||
EXPCL(val & bitmask32[scount]);
|
||||
return val << scount;
|
||||
@ -3074,7 +3084,7 @@ unsigned int lll(unsigned int val, short scount) {
|
||||
|
||||
unsigned int lrl(unsigned int val, short scount) {
|
||||
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
if (scount <= 32) {
|
||||
EXPCL(val & bitmask32[33-scount]);
|
||||
return val >> scount;
|
||||
@ -3086,7 +3096,7 @@ unsigned int lrl(unsigned int val, short scount) {
|
||||
|
||||
unsigned short arl (unsigned short val, short scount) {
|
||||
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
if (scount <= 16) {
|
||||
EXPCL(val & bitmask16[17-scount]);
|
||||
return val >> scount;
|
||||
@ -3097,7 +3107,7 @@ unsigned short arl (unsigned short val, short scount) {
|
||||
|
||||
unsigned short all (unsigned short val, short scount) {
|
||||
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
if (scount <= 16) {
|
||||
EXPCL(val & bitmask16[scount]);
|
||||
return val << scount;
|
||||
@ -3110,7 +3120,7 @@ unsigned short als (unsigned short val, short scount) {
|
||||
|
||||
short tempa;
|
||||
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
if (scount <= 15) {
|
||||
tempa = 0100000;
|
||||
tempa = tempa >> scount; /* create mask */
|
||||
@ -3126,7 +3136,7 @@ unsigned short als (unsigned short val, short scount) {
|
||||
|
||||
unsigned short ars (unsigned short val, short scount) {
|
||||
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
if (scount <= 16) {
|
||||
EXPCL(val & bitmask16[17-scount]);
|
||||
return (*(short *)&val) >> scount;
|
||||
@ -3141,7 +3151,7 @@ unsigned short ars (unsigned short val, short scount) {
|
||||
|
||||
unsigned int lrr(unsigned int val, short scount) {
|
||||
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
if (scount > 32)
|
||||
scount = scount - 32;
|
||||
EXPCL(val & bitmask32[33-scount]);
|
||||
@ -3150,7 +3160,7 @@ unsigned int lrr(unsigned int val, short scount) {
|
||||
|
||||
unsigned int llr(unsigned int val, short scount) {
|
||||
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
if (scount > 32)
|
||||
scount = scount - 32;
|
||||
EXPCL(val & bitmask32[scount]);
|
||||
@ -3161,7 +3171,7 @@ unsigned int llr(unsigned int val, short scount) {
|
||||
|
||||
unsigned int alr(unsigned short val, short scount) {
|
||||
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
scount = ((scount-1)%16)+1; /* make scount 1-16 */
|
||||
EXPCL(val & bitmask16[scount]);
|
||||
return (val << scount) | (val >> (16-scount));
|
||||
@ -3169,7 +3179,7 @@ unsigned int alr(unsigned short val, short scount) {
|
||||
|
||||
unsigned int arr(unsigned short val, short scount) {
|
||||
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
scount = ((scount-1)%16)+1; /* make scount 1-16 */
|
||||
EXPCL(val & bitmask16[17-scount]);
|
||||
return (val >> scount) | (val << (16-scount));
|
||||
@ -3327,7 +3337,7 @@ tch (unsigned short *un) {
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTE: ea is only used to set faddr should an arithmentic exception occur */
|
||||
/* NOTE: ea is only used to set faddr should an arithmetic exception occur */
|
||||
|
||||
int add32(unsigned int *a1, unsigned int a2, unsigned int a3, ea_t ea) {
|
||||
|
||||
@ -3432,7 +3442,7 @@ star(unsigned int val32, ea_t ea) {
|
||||
if (ea & 040000) { /* absolute RF addressing */
|
||||
RESTRICT();
|
||||
if ((ea & 0777) > 0477) {
|
||||
printf("em: STLR ea '%o is out of range; check -cpuid\n", ea);
|
||||
printf("em: STLR ea '%o is out of range; this -cpuid may not be supported by this version of software\n", ea);
|
||||
fatal(NULL);
|
||||
}
|
||||
regs.u32[ea & 0777] = val32;
|
||||
@ -3450,7 +3460,7 @@ main (int argc, char **argv) {
|
||||
|
||||
int boot; /* true if reading a boot record */
|
||||
char *bootarg; /* argument to -boot, if any */
|
||||
char bootfile[8]; /* boot file to load (optional) */
|
||||
char bootfile[16]; /* boot file to load (optional) */
|
||||
int bootfd=-1; /* initial boot file fd */
|
||||
int bootctrl, bootunit; /* boot device controller and unit */
|
||||
int bootskip=0; /* skip this many bytes on boot dev */
|
||||
@ -3543,11 +3553,7 @@ main (int argc, char **argv) {
|
||||
stlb[i].valid = 0;
|
||||
for (i=0; i < IOTLBENTS; i++)
|
||||
iotlb[i].valid = 0;
|
||||
#if 0
|
||||
bzero(mem, sizeof(mem));
|
||||
#else
|
||||
bzero(mem, 64*1024*2); /* zero first 64K words */
|
||||
#endif
|
||||
|
||||
verbose = 0;
|
||||
domemdump = 0;
|
||||
@ -3701,6 +3707,11 @@ main (int argc, char **argv) {
|
||||
if ((26 <= cpuid && cpuid <= 29) || cpuid >= 35)
|
||||
csoffset = 1;
|
||||
|
||||
/* the emulator has occasionally exited to command level; try
|
||||
ignoring SIGPIPE to see if that is the problem */
|
||||
|
||||
signal (SIGPIPE, SIG_IGN);
|
||||
|
||||
/* initialize all devices */
|
||||
|
||||
for (i=0; i<64; i++)
|
||||
@ -3710,8 +3721,6 @@ main (int argc, char **argv) {
|
||||
}
|
||||
|
||||
|
||||
os_init();
|
||||
|
||||
/* if a filename follows -boot, load and execute this R-mode runfile
|
||||
image. For example, -boot *DOS64 would load *DOS64 from the Unix
|
||||
file system and begin executing Primos II.
|
||||
@ -3750,6 +3759,8 @@ main (int argc, char **argv) {
|
||||
rvec[1] = rvec[0]+1040-1; /* read 1 disk block */
|
||||
/* setup DMA register '20 (address only) for the next boot record */
|
||||
regs.sym.regdmx[041] = 03000;
|
||||
if (globdisk(bootfile, sizeof(bootfile), bootctrl, bootunit) != 0)
|
||||
fatal("Can't find disk boot device file");
|
||||
|
||||
} else if ((sswitch & 0x7) == 5) { /* tape boot */
|
||||
bootctrl = 014;
|
||||
@ -3758,6 +3769,7 @@ main (int argc, char **argv) {
|
||||
bootskip = 4; /* to skip .TAP header */
|
||||
/* setup DMA register '20 (address only) for the next boot record */
|
||||
regs.sym.regdmx[041] = 0200+2355;;
|
||||
snprintf(bootfile, sizeof(bootfile), "dev%ou%d", bootctrl, bootunit);
|
||||
|
||||
} else {
|
||||
printf("\
|
||||
@ -3785,7 +3797,6 @@ For disk boots, the last 3 digits can be:\n\
|
||||
exit(1);
|
||||
}
|
||||
|
||||
snprintf(bootfile, sizeof(bootfile), "dev%ou%d", bootctrl, bootunit);
|
||||
TRACEA("Boot file is %s\n", bootfile);
|
||||
if ((bootfd=open(bootfile, O_RDONLY)) == -1) {
|
||||
perror("Error opening boot device file");
|
||||
@ -4251,7 +4262,7 @@ stfa:
|
||||
continue;
|
||||
|
||||
case 000001:
|
||||
TRACE(T_FLOW, " NOP\n");
|
||||
TRACE(T_FLOW, " NOP 1\n");
|
||||
continue;
|
||||
|
||||
case 000715:
|
||||
@ -5929,7 +5940,7 @@ a1a:
|
||||
if (crs[KEYS] & 010000) { /* V/I mode */
|
||||
crsl[GR2] = lrs(crsl[GR2], scount);
|
||||
} else {
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
utempa = crs[B] & 0x8000; /* save B bit 1 */
|
||||
if (scount <= 31) {
|
||||
templ = (crs[A]<<16) | ((crs[B] & 0x7FFF)<<1);
|
||||
@ -5983,7 +5994,7 @@ a1a:
|
||||
if (crs[KEYS] & 010000) /* V/I mode */
|
||||
crsl[GR2] = lls(crsl[GR2], scount);
|
||||
else {
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
utempa = crs[B] & 0x8000; /* save B bit 1 */
|
||||
if (scount < 31) {
|
||||
utempl = (crs[A]<<16) | ((crs[B] & 0x7FFF)<<1);
|
||||
@ -6002,7 +6013,7 @@ a1a:
|
||||
*(unsigned int *)(crs+A) = utempa;
|
||||
}
|
||||
}
|
||||
if (crs[KEYS] & 0100000)
|
||||
if ((crs[KEYS] & 0100400) == 0100400)
|
||||
mathexception('i', FC_INT_OFLOW, 0);
|
||||
break;
|
||||
|
||||
@ -6019,7 +6030,7 @@ a1a:
|
||||
case 01500: /* ALS */
|
||||
TRACE(T_FLOW, " ALS %d\n", scount);
|
||||
crs[A] = als(crs[A], scount);
|
||||
if (crs[KEYS] & 0100000)
|
||||
if ((crs[KEYS] & 0100400) == 0100400)
|
||||
mathexception('i', FC_INT_OFLOW, 0);
|
||||
break;
|
||||
|
||||
@ -6041,7 +6052,7 @@ badshift:
|
||||
TRACE(T_INST, " skip group\n");
|
||||
|
||||
if (inst == 0101000) {
|
||||
TRACE(T_FLOW, " NOP\n");
|
||||
TRACE(T_FLOW, " NOP-SKP\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -6195,9 +6206,6 @@ keys = 14200, modals=100177
|
||||
}
|
||||
|
||||
if ((crs[KEYS] & 0016000) != 0010000) goto nonimode;
|
||||
#ifndef OSX
|
||||
fault(ILLINSTFAULT, RPL, RP);
|
||||
#endif
|
||||
|
||||
/* branch and register generic instructions don't have ea, so they
|
||||
are tested outside the main switch, before an ea is computed */
|
||||
@ -6319,109 +6327,73 @@ keys = 14200, modals=100177
|
||||
case 0130:
|
||||
TRACE(T_FLOW, " BRI1\n");
|
||||
crsl[dr]++;
|
||||
if (crsl[dr] != 0)
|
||||
RPL = iget16(RP);
|
||||
else
|
||||
RPL++;
|
||||
BRNE(dr);
|
||||
break;
|
||||
|
||||
case 0131:
|
||||
TRACE(T_FLOW, " BRI2\n");
|
||||
crsl[dr] += 2;
|
||||
if (crsl[dr] != 0)
|
||||
RPL = iget16(RP);
|
||||
else
|
||||
RPL++;
|
||||
BRNE(dr);
|
||||
break;
|
||||
|
||||
case 0132:
|
||||
TRACE(T_FLOW, " BRI4\n");
|
||||
crsl[dr] += 4;
|
||||
if (crsl[dr] != 0)
|
||||
RPL = iget16(RP);
|
||||
else
|
||||
RPL++;
|
||||
BRNE(dr);
|
||||
break;
|
||||
|
||||
case 0134:
|
||||
TRACE(T_FLOW, " BRD1\n");
|
||||
crsl[dr]--;
|
||||
if (crsl[dr] != 0)
|
||||
RPL = iget16(RP);
|
||||
else
|
||||
RPL++;
|
||||
BRNE(dr);
|
||||
break;
|
||||
|
||||
case 0135:
|
||||
TRACE(T_FLOW, " BRD2\n");
|
||||
crsl[dr] -= 2;
|
||||
if (crsl[dr] != 0)
|
||||
RPL = iget16(RP);
|
||||
else
|
||||
RPL++;
|
||||
BRNE(dr);
|
||||
break;
|
||||
|
||||
case 0136:
|
||||
TRACE(T_FLOW, " BRD4\n");
|
||||
crsl[dr] -= 4;
|
||||
if (crsl[dr] != 0)
|
||||
RPL = iget16(RP);
|
||||
else
|
||||
RPL++;
|
||||
BRNE(dr);
|
||||
break;
|
||||
|
||||
case 0140:
|
||||
TRACE(T_FLOW, " BHI1\n");
|
||||
crs[dr*2]++;
|
||||
if (crs[dr*2] != 0)
|
||||
RPL = iget16(RP);
|
||||
else
|
||||
RPL++;
|
||||
BHNE(dr);
|
||||
break;
|
||||
|
||||
case 0141:
|
||||
TRACE(T_FLOW, " BHI2\n");
|
||||
crs[dr*2] += 2;
|
||||
if (crs[dr*2] != 0)
|
||||
RPL = iget16(RP);
|
||||
else
|
||||
RPL++;
|
||||
BHNE(dr);
|
||||
break;
|
||||
|
||||
case 0142:
|
||||
TRACE(T_FLOW, " BHI4\n");
|
||||
crs[dr*2] += 4;
|
||||
if (crs[dr*2] != 0)
|
||||
RPL = iget16(RP);
|
||||
else
|
||||
RPL++;
|
||||
BHNE(dr);
|
||||
break;
|
||||
|
||||
case 0144:
|
||||
TRACE(T_FLOW, " BHD1\n");
|
||||
crs[dr*2]--;
|
||||
if (crs[dr*2] != 0)
|
||||
RPL = iget16(RP);
|
||||
else
|
||||
RPL++;
|
||||
BHNE(dr);
|
||||
break;
|
||||
|
||||
case 0145:
|
||||
TRACE(T_FLOW, " BHD2\n");
|
||||
crs[dr*2] -= 2;
|
||||
if (crs[dr*2] != 0)
|
||||
RPL = iget16(RP);
|
||||
else
|
||||
RPL++;
|
||||
BHNE(dr);
|
||||
break;
|
||||
|
||||
case 0146:
|
||||
TRACE(T_FLOW, " BHD4\n");
|
||||
crs[dr*2] -= 4;
|
||||
if (crs[dr*2] != 0)
|
||||
RPL = iget16(RP);
|
||||
else
|
||||
RPL++;
|
||||
BHNE(dr);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -6955,7 +6927,7 @@ keys = 14200, modals=100177
|
||||
if (crs[dr*2] & 0x8000)
|
||||
SETCL;
|
||||
else
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
crs[dr*2] = crs[dr*2] << 1;
|
||||
break;
|
||||
|
||||
@ -6964,7 +6936,7 @@ keys = 14200, modals=100177
|
||||
if (crs[dr*2] & 0x4000)
|
||||
SETCL;
|
||||
else
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
crs[dr*2] = crs[dr*2] << 2;
|
||||
break;
|
||||
|
||||
@ -6973,7 +6945,7 @@ keys = 14200, modals=100177
|
||||
if (crs[dr*2] & 0x0001)
|
||||
SETCL;
|
||||
else
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
crs[dr*2] = crs[dr*2] >> 1;
|
||||
break;
|
||||
|
||||
@ -6982,7 +6954,7 @@ keys = 14200, modals=100177
|
||||
if (crs[dr*2] & 0x0002)
|
||||
SETCL;
|
||||
else
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
crs[dr*2] = crs[dr*2] >> 2;
|
||||
break;
|
||||
|
||||
@ -6991,7 +6963,7 @@ keys = 14200, modals=100177
|
||||
if (crsl[dr] & 0x80000000)
|
||||
SETCL;
|
||||
else
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
crsl[dr] = crsl[dr] << 1;
|
||||
break;
|
||||
|
||||
@ -7000,7 +6972,7 @@ keys = 14200, modals=100177
|
||||
if (crsl[dr] & 0x40000000)
|
||||
SETCL;
|
||||
else
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
crsl[dr] = crsl[dr] << 2;
|
||||
break;
|
||||
|
||||
@ -7009,7 +6981,7 @@ keys = 14200, modals=100177
|
||||
if (crsl[dr] & 0x00000001)
|
||||
SETCL;
|
||||
else
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
crsl[dr] = crsl[dr] >> 1;
|
||||
break;
|
||||
|
||||
@ -7018,7 +6990,7 @@ keys = 14200, modals=100177
|
||||
if (crsl[dr] & 0x00000002)
|
||||
SETCL;
|
||||
else
|
||||
crs[KEYS] &= ~0120000; /* clear C,L */
|
||||
CLEARCL;
|
||||
crsl[dr] = crsl[dr] >> 2;
|
||||
break;
|
||||
|
||||
@ -7125,8 +7097,8 @@ keys = 14200, modals=100177
|
||||
switch (opcode) {
|
||||
|
||||
case 000:
|
||||
warn("I-mode generic class 0?");
|
||||
fault(ILLINSTFAULT, RPL, RP);
|
||||
/* this should have been handled already! */
|
||||
fatal("I-mode generic class 0?");
|
||||
|
||||
case 001:
|
||||
TRACE(T_FLOW, " L\n");
|
||||
@ -7180,7 +7152,7 @@ keys = 14200, modals=100177
|
||||
crs[dr*2] = arl(crs[dr*2], scount);
|
||||
break;
|
||||
default:
|
||||
fatal("SHL?");
|
||||
fatal("I-mode SHL switch?");
|
||||
}
|
||||
continue;
|
||||
|
||||
@ -7228,6 +7200,7 @@ keys = 14200, modals=100177
|
||||
fault(ILLINSTFAULT, RPL, RP);
|
||||
|
||||
case 010: /* register generic branch */
|
||||
/* this should have been handled already! */
|
||||
fatal("I-mode RGBR?");
|
||||
|
||||
case 011:
|
||||
@ -7272,12 +7245,12 @@ keys = 14200, modals=100177
|
||||
switch ((ea >> 14) & 3) {
|
||||
case 0:
|
||||
crsl[dr] = lls(crsl[dr], scount);
|
||||
if (crs[KEYS] & 0100400)
|
||||
if ((crs[KEYS] & 0100400) == 0100400)
|
||||
mathexception('i', FC_INT_OFLOW, 0);
|
||||
break;
|
||||
case 1:
|
||||
crs[dr*2] = als(crs[dr*2], scount);
|
||||
if (crs[KEYS] & 0100400)
|
||||
if ((crs[KEYS] & 0100400) == 0100400)
|
||||
mathexception('i', FC_INT_OFLOW, 0);
|
||||
break;
|
||||
case 2:
|
||||
@ -7337,8 +7310,8 @@ keys = 14200, modals=100177
|
||||
fault(ILLINSTFAULT, RPL, RP);
|
||||
|
||||
case 020:
|
||||
warn("I-mode generic class 1?");
|
||||
fault(ILLINSTFAULT, RPL, RP);
|
||||
/* this should have been handled already! */
|
||||
fatal("I-mode generic class 1?");
|
||||
|
||||
case 021:
|
||||
TRACE(T_FLOW, " ST\n");
|
||||
@ -7384,7 +7357,7 @@ keys = 14200, modals=100177
|
||||
crs[dr*2] = arr(crs[dr*2], scount);
|
||||
break;
|
||||
default:
|
||||
fatal("ROT?");
|
||||
fatal("I-mode ROT switch?");
|
||||
}
|
||||
continue;
|
||||
|
||||
@ -7402,6 +7375,7 @@ keys = 14200, modals=100177
|
||||
fault(ILLINSTFAULT, RPL, RP);
|
||||
|
||||
case 030: /* register generic */
|
||||
/* this should have been handled already! */
|
||||
fatal("I-mode RGEN?");
|
||||
|
||||
case 031:
|
||||
@ -7452,8 +7426,8 @@ keys = 14200, modals=100177
|
||||
fault(ILLINSTFAULT, RPL, RP);
|
||||
|
||||
case 040: /* generic class 2, overlays skip group */
|
||||
warn("I-mode generic class 2?");
|
||||
fault(ILLINSTFAULT, RPL, RP);
|
||||
/* this should have been handled already! */
|
||||
fatal("I-mode generic class 2?");
|
||||
|
||||
case 041:
|
||||
TRACE(T_FLOW, " I\n");
|
||||
@ -7693,8 +7667,8 @@ imodepcl:
|
||||
fault(ILLINSTFAULT, RPL, RP);
|
||||
|
||||
case 060:
|
||||
warn("I-mode generic class 3?");
|
||||
fault(ILLINSTFAULT, RPL, RP);
|
||||
/* this should have been handled already! */
|
||||
fatal("I-mode generic class 3?");
|
||||
|
||||
case 061:
|
||||
TRACE(T_FLOW, " C\n");
|
||||
@ -7835,11 +7809,11 @@ imodepcl:
|
||||
|
||||
case 075:
|
||||
TRACE(T_FLOW, " AIP\n");
|
||||
if (*(int *)&ea > 0) {
|
||||
warn("Immediate mode AIP?");
|
||||
fault(ILLINSTFAULT, RPL, RP);
|
||||
}
|
||||
utempl = crsl[dr] + get32(ea);
|
||||
if (*(int *)&ea < 0)
|
||||
utempl = immu32;
|
||||
else
|
||||
utempl = get32(ea);
|
||||
utempl += crsl[dr];
|
||||
if (utempl & 0x80000000)
|
||||
fault(POINTERFAULT, utempl>>16, ea);
|
||||
/* IXX: ISG says C & L are set, ring needs to be weakened */
|
||||
@ -8658,6 +8632,10 @@ nonimode:
|
||||
*(int *)(crs+L) = ldar(ea);
|
||||
continue;
|
||||
|
||||
case 0502:
|
||||
TRACE(T_FLOW, " QFxx '%06o\n", ea & 0xFFFF);
|
||||
fault(UIIFAULT, RPL, RP);
|
||||
|
||||
case 01401:
|
||||
TRACE(T_FLOW, " EIO\n");
|
||||
crs[KEYS] &= ~0100; /* reset EQ */
|
||||
|
||||
197
emdev.h
197
emdev.h
@ -77,6 +77,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <time.h>
|
||||
#include <sys/file.h>
|
||||
#include <glob.h>
|
||||
|
||||
/* this macro is used when I/O is successful. In VI modes, it sets
|
||||
the EQ condition code bit. In SR modes, it does a skip */
|
||||
@ -493,10 +494,18 @@ readasr:
|
||||
devpoll[device] = instpermsec*100;
|
||||
IOSKIP;
|
||||
} else if (func == 1) { /* write control word */
|
||||
TRACEA("OTA 4, func %d, A='%o/%d\n", func, crs[A], *(short *)(crs+A));
|
||||
IOSKIP;
|
||||
} else if (04 <= func && func <= 07) { /* write control register 1/2 */
|
||||
TRACEA("OTA 4, func %d, A='%o/%d\n", func, crs[A], *(short *)(crs+A));
|
||||
IOSKIP;
|
||||
} else if (func == 012) {
|
||||
TRACEA("OTA 4, func %d, A='%o/%d\n", func, crs[A], *(short *)(crs+A));
|
||||
/* NOTE: does this in rev 23 when system is shutdown with '4110 in A */
|
||||
IOSKIP;
|
||||
|
||||
} else if (func == 013) {
|
||||
TRACEA("OTA 4, func %d, A='%o/%d\n", func, crs[A], *(short *)(crs+A));
|
||||
/* NOTE: does this in rev 20 on settime command (set clock on VCP?) */
|
||||
IOSKIP;
|
||||
|
||||
@ -519,6 +528,8 @@ readasr:
|
||||
vcptime[6] = BCD2(tms->tm_sec);
|
||||
vcptime[7] = 0;
|
||||
vcptimeix = 0;
|
||||
} else {
|
||||
TRACEA("OTA 4, func '%o, A='%o/%d\n", func, crs[A], *(short *)(crs+A));
|
||||
}
|
||||
IOSKIP;
|
||||
} else {
|
||||
@ -1436,6 +1447,28 @@ int devcp (int class, int func, int device) {
|
||||
}
|
||||
|
||||
|
||||
/* helper function to return a disk's file name given a controller and unit */
|
||||
|
||||
int globdisk (char *devfile, int size, int device, int unit) {
|
||||
glob_t g;
|
||||
int globerr;
|
||||
|
||||
snprintf(devfile, size, "dev%ou%d.*", device, unit);
|
||||
if ((globerr=glob(devfile, GLOB_ERR|GLOB_NOSORT, NULL, &g)) != 0) {
|
||||
fprintf(stderr,"globdisk: glob returned %d opening %s\n", globerr, devfile);
|
||||
return -1;
|
||||
}
|
||||
if (g.gl_pathc != 1) {
|
||||
fprintf(stderr,"globdisk: %d matches for %s\n", g.gl_pathc, devfile);
|
||||
return -1;
|
||||
}
|
||||
strncpy(devfile, g.gl_pathv[0], size);
|
||||
devfile[size-1] = 0;
|
||||
TRACE(T_INST|T_DIO, " filename for dev '%o unit %d is %s\n", device, unit, devfile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* disk controller at '26 and '27
|
||||
|
||||
NOTES:
|
||||
@ -1469,13 +1502,48 @@ int devcp (int class, int func, int device) {
|
||||
|
||||
int devdisk (int class, int func, int device) {
|
||||
|
||||
/* static structure for disk file suffixes and config data */
|
||||
|
||||
#define NUMGEOM 24
|
||||
|
||||
static struct {
|
||||
short model;
|
||||
char suffix[5];
|
||||
short heads;
|
||||
short spt;
|
||||
short maxtrack;
|
||||
} geom[NUMGEOM] = {
|
||||
1, "80M", 5, 9, 823,
|
||||
1, "300M", 19, 9, 823,
|
||||
0, "CMD", 20, 9, 823,
|
||||
4, "68M", 3, 9, 1119,
|
||||
5, "158M", 7, 9, 1119,
|
||||
6, "160M", 10, 9, 821,
|
||||
7, "675M", 40, 9, 841,
|
||||
7, "600M", 40, 9, 841,
|
||||
9, "315M", 19, 9, 823, /* MODEL_4475 */
|
||||
10, "84M", 5, 8, 1015, /* MODEL_4714 */
|
||||
11, "60M", 4, 7, 1020, /* MODEL_4711 */
|
||||
12, "120M", 8, 7, 1020, /* MODEL_4715 */
|
||||
13, "496M", 24, 14, 711, /* MODEL_4735 */
|
||||
14, "258M", 17, 6, 1220, /* MODEL_4719 */
|
||||
15, "770M", 23, 19, 848, /* MODEL_4845 */
|
||||
17, "328A", 12, 8, 1641, /* MODEL_4721 */
|
||||
17, "328B", 31, 254, 20, /* MODEL_4721 (7210 SCSI controller) */
|
||||
18, "817M", 15, 19, 1379, /* MODEL_4860 */
|
||||
19, "673M", 31, 254, 42, /* MODEL_4729 */
|
||||
20, "213M", 31, 254, 14, /* MODEL_4730 */
|
||||
22, "421M", 31, 254, 26, /* MODEL_4731 */
|
||||
23, "1.3G", 31, 254, 82, /* MODEL_4732 */
|
||||
24, "1G", 31, 254, 65, /* MODEL_4734 */
|
||||
25, "2G", 31, 254, 122, /* MODEL_4736 */
|
||||
};
|
||||
|
||||
#define S_HALT 0
|
||||
#define S_RUN 1
|
||||
#define S_INT 2
|
||||
|
||||
/* this should be 8, but not sure how it is supported on controllers */
|
||||
|
||||
#define MAXDRIVES 4
|
||||
#define MAXDRIVES 8
|
||||
#define HASHMAX 4451
|
||||
|
||||
#if 0
|
||||
@ -1494,9 +1562,11 @@ int devdisk (int class, int func, int device) {
|
||||
short dmanch; /* number of dma channels-1 */
|
||||
struct {
|
||||
int rtfd; /* read trace file descriptor */
|
||||
unsigned short theads; /* total heads (cfg file) */
|
||||
unsigned short spt; /* sectors per track */
|
||||
unsigned short curtrack; /* current head position */
|
||||
short heads; /* total heads */
|
||||
short spt; /* sectors per track */
|
||||
short maxtrack; /* cylinder limit */
|
||||
short curtrack; /* current head position */
|
||||
short wp; /* true if write protected */
|
||||
int devfd; /* Unix device file descriptor */
|
||||
int readnum; /* increments on each read */
|
||||
unsigned char** modrecs; /* hash table of modified records */
|
||||
@ -1513,23 +1583,23 @@ int devdisk (int class, int func, int device) {
|
||||
unsigned short dmareg;
|
||||
unsigned int dmaaddr;
|
||||
unsigned char *hashp;
|
||||
int lockkey;
|
||||
|
||||
|
||||
/* NOTE: this iobuf size looks suspicious; probably should be 2080 bytes,
|
||||
/* NOTE: this iobuf size looks suspicious; probably should be 1040 words,
|
||||
the largest disk record size, and there probably should be some checks
|
||||
that no individual DMA exceeds this size, that no individual disk
|
||||
read or write exceeds 1040 words. Maybe it's 4096 bytes because this
|
||||
is the largest DMA transfer request size... */
|
||||
|
||||
unsigned short iobuf[4096]; /* local I/O buf (for mapped I/O) */
|
||||
unsigned short iobuf[1040]; /* local I/O buf (for mapped I/O) */
|
||||
unsigned short *iobufp;
|
||||
unsigned short access;
|
||||
short dmanw, dmanw1, dmanw2;
|
||||
unsigned int utempl;
|
||||
char ordertext[8];
|
||||
int theads, spt, phyra, phyra2;
|
||||
int phyra;
|
||||
int nb; /* number of bytes returned from read/write */
|
||||
char devfile[8];
|
||||
char devfile[16];
|
||||
char rtfile[16]; /* read trace file name */
|
||||
int rtnw; /* total number of words read (all channels) */
|
||||
|
||||
@ -1547,9 +1617,11 @@ int devdisk (int class, int func, int device) {
|
||||
dc[i].usel = -1;
|
||||
for (u=0; u<MAXDRIVES; u++) {
|
||||
dc[i].unit[u].rtfd = -1;
|
||||
dc[i].unit[u].theads = 40;
|
||||
dc[i].unit[u].spt = 9;
|
||||
dc[i].unit[u].curtrack = 0;
|
||||
dc[i].unit[u].heads = -1;
|
||||
dc[i].unit[u].spt = -1;
|
||||
dc[i].unit[u].maxtrack = -1;
|
||||
dc[i].unit[u].curtrack = -1;
|
||||
dc[i].unit[u].wp = -1;
|
||||
dc[i].unit[u].devfd = -1;
|
||||
dc[i].unit[u].readnum = -1;
|
||||
dc[i].unit[u].modrecs = NULL;
|
||||
@ -1653,7 +1725,7 @@ int devdisk (int class, int func, int device) {
|
||||
dc[device].status &= ~076000; /* clear bits 2-6 */
|
||||
m2 = get16io(dc[device].oar++);
|
||||
recsize = m & 017;
|
||||
track = m1 & 01777;
|
||||
track = m1 & 03777;
|
||||
rec = m2 >> 8; /* # records for format, rec # for R/W */
|
||||
head = m2 & 077;
|
||||
u = dc[device].usel;
|
||||
@ -1679,6 +1751,7 @@ int devdisk (int class, int func, int device) {
|
||||
dc[device].status |= 4; /* illegal seek */
|
||||
break;
|
||||
}
|
||||
/* XXX: could check for head > max head on drive here... */
|
||||
if (dc[device].unit[u].devfd == -1) {
|
||||
TRACE(T_INST|T_DIO, " Device '%o unit %d not ready\n", device, u);
|
||||
dc[device].status = 0100001;
|
||||
@ -1689,8 +1762,9 @@ int devdisk (int class, int func, int device) {
|
||||
|
||||
/* translate head/track/sector to drive record address */
|
||||
|
||||
phyra = (track*dc[device].unit[u].theads*dc[device].unit[u].spt) + head*9 + rec;
|
||||
phyra = (track*dc[device].unit[u].heads*dc[device].unit[u].spt) + head*dc[device].unit[u].spt + rec;
|
||||
TRACE(T_INST|T_DIO, " Unix ra=%d, byte offset=%d\n", phyra, phyra*2080);
|
||||
/* XXX: check for phyra > 1032444, which is > 2GB max file size */
|
||||
|
||||
/* does this record exist in the disk unit hash table? If it does,
|
||||
we'll do I/O to the hash entry. If it doesn't, then for read,
|
||||
@ -1711,6 +1785,7 @@ int devdisk (int class, int func, int device) {
|
||||
if (order == 5) { /* read */
|
||||
#endif
|
||||
if (lseek(dc[device].unit[u].devfd, phyra*2080, SEEK_SET) == -1) {
|
||||
fprintf(stderr,"devdisk: seek error, phyra=%d\n", phyra);
|
||||
perror("Unable to seek drive file");
|
||||
fatal(NULL);
|
||||
}
|
||||
@ -1732,6 +1807,14 @@ int devdisk (int class, int func, int device) {
|
||||
dmareg = dc[device].dmachan << 1;
|
||||
dmanw = regs.sym.regdmx[dmareg];
|
||||
dmanw = -(dmanw>>4);
|
||||
if (dmanw > 1040) {
|
||||
warn("disk I/O limited to 1040 words");
|
||||
dmanw = 1040;
|
||||
}
|
||||
if (dmanw < 0) {
|
||||
warn("disk I/O size < 0; set to 0");
|
||||
dmanw = 0;
|
||||
}
|
||||
dmaaddr = ((regs.sym.regdmx[dmareg] & 3)<<16) | regs.sym.regdmx[dmareg+1];
|
||||
TRACE(T_INST|T_DIO, " DMA channels: nch-1=%d, ['%o]='%o, ['%o]='%o, nwords=%d\n", dc[device].dmanch, dc[device].dmachan, regs.sym.regdmx[dmareg], dc[device].dmachan+1, dmaaddr, dmanw);
|
||||
|
||||
@ -1788,48 +1871,82 @@ int devdisk (int class, int func, int device) {
|
||||
track = 0;
|
||||
dc[device].status &= ~4; /* clear bit 14: seek error */
|
||||
} else {
|
||||
track = m1 & 01777;
|
||||
track = m1 & 03777;
|
||||
}
|
||||
TRACE(T_INST|T_DIO, " seek track %d, restore=%d, clear=%d\n", track, (m1 & 0100000) != 0, (m1 & 040000) != 0);
|
||||
if (track > dc[device].unit[u].maxtrack) {
|
||||
fprintf(stderr," Device '%o, seek to track %d > cylinder limit of %d\n", device, track, dc[device].unit[u].maxtrack);
|
||||
dc[device].status |= 4; /* set bit 14: seek error */
|
||||
track = -1;
|
||||
}
|
||||
dc[device].unit[u].curtrack = track;
|
||||
break;
|
||||
|
||||
case 4: /* DSEL = Select unit */
|
||||
u = (m1 & 017); /* get unit bits */
|
||||
u = (m1 & 0377); /* get unit bits */
|
||||
dc[device].usel = -1; /* de-select */
|
||||
if (u == 0) {
|
||||
dc[device].usel = -1; /* de-select */
|
||||
TRACE(T_INST|T_DIO, " de-select\n");
|
||||
break;
|
||||
}
|
||||
dc[device].status &= ~3; /* clear 15-16: select err + unavailable */
|
||||
if (u != 1 && u != 2 && u != 4 && u != 8) {
|
||||
if (u == 1) u = 0;
|
||||
else if (u == 2) u = 1;
|
||||
else if (u == 4) u = 2;
|
||||
else if (u == 8) u = 3;
|
||||
else if (u == 16) u = 4;
|
||||
else if (u == 32) u = 5;
|
||||
else if (u == 64) u = 6;
|
||||
else if (u == 128) u = 7;
|
||||
else {
|
||||
fprintf(stderr," Device '%o, bad select '%o\n", device, u);
|
||||
dc[device].usel = -1; /* de-select */
|
||||
dc[device].status != 2; /* set bit 15: select error */
|
||||
dc[device].status |= 0100002; /* set bit 15: select error */
|
||||
break;
|
||||
}
|
||||
u = u >> 1; /* unit => 0/1/2/4 */
|
||||
if (u == 4) u = 3; /* unit => 0/1/2/3 */
|
||||
TRACE(T_INST|T_DIO, " select unit %d\n", u);
|
||||
dc[device].usel = u;
|
||||
if (dc[device].unit[u].devfd == -1) {
|
||||
snprintf(devfile,sizeof(devfile),"dev%ou%d", device, u);
|
||||
TRACE(T_INST|T_DIO, " filename for dev '%o unit %d is %s\n", device, u, devfile);
|
||||
/* NOTE: add O_CREAT to allow creating new drives on the fly */
|
||||
if ((dc[device].unit[u].devfd = open(devfile, O_RDWR, 0770)) == -1) {
|
||||
fprintf(stderr,"em: unable to open disk device file %s for device '%o unit %d; flagging \n", devfile, device, u);
|
||||
dc[device].status = 0100001; /* not ready */
|
||||
} else {
|
||||
#ifdef DISKSAFE
|
||||
if (flock(dc[device].unit[u].devfd, LOCK_SH+LOCK_NB) == -1)
|
||||
fatal("Disk drive file is in use");
|
||||
dc[device].unit[u].modrecs = calloc(HASHMAX, sizeof(void *));
|
||||
//fprintf(stderr," Device '%o, unit %d, modrecs=%p\n", device, u, dc[device].unit[u].modrecs);
|
||||
#else
|
||||
if (flock(dc[device].unit[u].devfd, LOCK_EX+LOCK_NB) == -1)
|
||||
fatal("Disk drive file is in use");
|
||||
#endif
|
||||
if (globdisk(devfile, sizeof(devfile), device, u) != 0) {
|
||||
dc[device].status |= 0100001; /* set bit 16: not ready */
|
||||
break;
|
||||
}
|
||||
if ((dc[device].unit[u].devfd = open(devfile, O_RDWR)) == -1) {
|
||||
if ((dc[device].unit[u].devfd = open(devfile, O_RDONLY)) == -1) {
|
||||
fprintf(stderr, "em: unable to open disk device file %s for device '%o unit %d; flagging \n", devfile, device, u);
|
||||
dc[device].status = 0100001; /* not ready */
|
||||
break;
|
||||
} else {
|
||||
lockkey = LOCK_SH;
|
||||
dc[device].unit[u].wp = 1;
|
||||
}
|
||||
} else {
|
||||
lockkey = LOCK_EX;
|
||||
dc[device].unit[u].wp = 0;
|
||||
}
|
||||
/* determine geometry from disk file suffix */
|
||||
for (i=0; i < NUMGEOM; i++)
|
||||
if (strcasestr(devfile, geom[i].suffix)) {
|
||||
dc[device].unit[u].heads = geom[i].heads;
|
||||
dc[device].unit[u].spt = geom[i].spt;
|
||||
dc[device].unit[u].maxtrack = geom[i].maxtrack;
|
||||
break;
|
||||
}
|
||||
if (i == NUMGEOM) {
|
||||
fprintf(stderr, "em: unknown geometry for %s\n", devfile);
|
||||
close(dc[device].unit[u].devfd);
|
||||
dc[device].unit[u].devfd = -1;
|
||||
dc[device].status = 0100001; /* not ready */
|
||||
break;
|
||||
}
|
||||
#ifdef DISKSAFE
|
||||
if (flock(dc[device].unit[u].devfd, LOCK_SH+LOCK_NB) == -1)
|
||||
fatal("Disk drive file is in use");
|
||||
dc[device].unit[u].modrecs = calloc(HASHMAX, sizeof(void *));
|
||||
//fprintf(stderr," Device '%o, unit %d, modrecs=%p\n", device, u, dc[device].unit[u].modrecs);
|
||||
#else
|
||||
if (flock(dc[device].unit[u].devfd, lockkey+LOCK_NB) == -1)
|
||||
fatal("Disk drive file is in use");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
192
os.c
192
os.c
@ -1,192 +0,0 @@
|
||||
/* os.c, Jim Wilcoxson, 4/15/2005
|
||||
Emulations of Primos Operating System routines for Unix.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <sys/times.h>
|
||||
|
||||
#include "os.h"
|
||||
|
||||
|
||||
os_init() {
|
||||
|
||||
os.ttydev = open("/dev/tty", O_RDWR, 0);
|
||||
if (os.ttydev < 0) {
|
||||
perror(" error opening /dev/tty");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
os_break$(short *onoff) {
|
||||
}
|
||||
|
||||
os_c1in(short *charg) {
|
||||
unsigned char ch;
|
||||
int n;
|
||||
|
||||
fprintf(stderr," c1in waiting for data\n");
|
||||
do {
|
||||
n = read(os.ttydev, &ch, 1);
|
||||
if (n == 0)
|
||||
sleep(1);
|
||||
} while (n == 0);
|
||||
if (n < 0) {
|
||||
perror(" error reading from tty");
|
||||
exit(1);
|
||||
}
|
||||
if (n != 1) {
|
||||
fprintf(stderr," unexpected error reading from tty, n=%d", n);
|
||||
exit(1);
|
||||
}
|
||||
if (ch == 015)
|
||||
ch = 012;
|
||||
*charg = ch | 0x80;
|
||||
}
|
||||
|
||||
|
||||
os_comanl() {
|
||||
}
|
||||
|
||||
|
||||
os_cnin$(unsigned char *buf, short *maxchars, short *n) {
|
||||
short ch;
|
||||
|
||||
*n = 0;
|
||||
while (*n < *maxchars) {
|
||||
os_c1in(&ch);
|
||||
buf[*n] = ch;
|
||||
(*n)++;
|
||||
if (ch == 0212) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
os_exit() {
|
||||
fprintf(stderr,"\nProgram called EXIT\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
os_erkl$$(short *key, short *erasech, short *killch, short *code) {
|
||||
if (*key == 1) { /* k$read */
|
||||
*erasech = 0210;
|
||||
*killch = 0377;
|
||||
*code = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
os_errpr$ (short *key, short *code, char *msg, short *msglen, char *prog, short *proglen) {
|
||||
if (*code == 0) return;
|
||||
fprintf (stderr, " key=%d, code=%d, msglen=%d, proglen=%d\n", *key, *code, *msglen, *proglen);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
os_ginfo (short *buf, short *bufsiz) {
|
||||
int i;
|
||||
|
||||
fprintf(stderr," ginfo bufsiz=%d\n", *bufsiz);
|
||||
if (*bufsiz <= 0) return;
|
||||
buf[0] = 0;
|
||||
if (*bufsiz > 1) buf[1] = 0;
|
||||
if (*bufsiz > 2) buf[2] = 61; /* max device # */
|
||||
for (i=0; i < *bufsiz-3; i++)
|
||||
buf[i+3] = 440; /* disk record size */
|
||||
}
|
||||
|
||||
/* RDTK$$
|
||||
|
||||
key - 1=read UC, 2=read, 3=reset, 4=rest, 5=init
|
||||
info - output array
|
||||
[0] = type - 1=normal, 2=regular, 5=null, 6=eol
|
||||
info[1] = length
|
||||
info[2] = flags
|
||||
:100000=decimal, :40000=octal, :20000=dash, :10000=info[3] < 8
|
||||
info[3] = positional token's position 0-9 (1/44, 4/20, etc)
|
||||
info[4] = positional token's value
|
||||
buf - output token buffer
|
||||
buflen - size in words of buf (in)
|
||||
code - return code
|
||||
|
||||
*/
|
||||
|
||||
os_rdtk$$(short *key, short *info, char *buf, short *buflen, short *code) {
|
||||
fprintf(stderr," key=%d\n", *key);
|
||||
*code = 0;
|
||||
if (*key = 1) {
|
||||
info[0] = 6;
|
||||
info[1] = 0;
|
||||
info[2] = 0;
|
||||
info[3] = 0;
|
||||
info[4] = 0;
|
||||
} else {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
os_t1ou(short *charg) {
|
||||
fprintf(stderr," Character is '%o/%d, Prime is '%o/%d, (%c)\n", *charg, *charg, *charg & 0x7f, *charg & 0x7f, *charg & 0x7f);
|
||||
putchar(*charg & 0x7f);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
||||
os_timdat(short *userbuf, short *n) {
|
||||
time_t tod;
|
||||
struct tm tms;
|
||||
struct {
|
||||
char mmddyy[6];
|
||||
short timemins; /* minutes since midnight */
|
||||
short timesecs; /* plus seconds (0-50) */
|
||||
short timeticks; /* plus ticks (0-329 330ths of a second) */
|
||||
short cpusecs;
|
||||
short cputicks;
|
||||
short iosecs;
|
||||
short ioticks;
|
||||
short tickspersec;
|
||||
short userno;
|
||||
char username[32];
|
||||
} timbuf;
|
||||
|
||||
if (sizeof(timbuf) != sizeof(short)*28) {
|
||||
fprintf(stderr," sizeof(timebuf)=%d, size of 28-word array=%d\n",
|
||||
sizeof(timbuf), sizeof(short)*28);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
tod = time(NULL);
|
||||
localtime_r(&tod, &tms);
|
||||
strncpy(timbuf.mmddyy,"042105",6);
|
||||
#if 0
|
||||
timbuf.timemins = tms.tm_hour*60 + tms.tm_min;
|
||||
timbuf.timesecs = tms.tm_sec;
|
||||
#else
|
||||
timbuf.timemins = 0;
|
||||
timbuf.timesecs = 0;
|
||||
#endif
|
||||
timbuf.timeticks = 0;
|
||||
timbuf.cpusecs = timbuf.cputicks = timbuf.iosecs = timbuf.ioticks = 0;
|
||||
timbuf.tickspersec = 330;
|
||||
timbuf.userno = 1;
|
||||
strncpy(timbuf.username,"SYSTEM ",32);
|
||||
memcpy(userbuf, &timbuf, *n*2);
|
||||
}
|
||||
|
||||
|
||||
os_tnoua(unsigned char *s, short *len) {
|
||||
int i;
|
||||
fprintf(stderr," writing %d char string \"", *len);
|
||||
for (i=0; i < *len; i++)
|
||||
fputc(s[i] & 0x7f,stderr);
|
||||
fprintf(stderr,"\"\n");
|
||||
|
||||
for (i=0; i < *len; i++)
|
||||
putchar(s[i] & 0x7f);
|
||||
fflush(stdout);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user