1
0
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:
Jim 2007-06-08 00:00:00 -04:00
parent 55ea18c85e
commit 31f4e2e22e
5 changed files with 248 additions and 357 deletions

View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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);
}

8
os.h
View File

@ -1,8 +0,0 @@
/* os.h, Jim Wilcoxson, April 15, 2005
Include file for Primos Operating System data structures.
*/
static struct {
int ttydev;
} os;