From 31f4e2e22e98326109bcc2abe7d3046f32657c54 Mon Sep 17 00:00:00 2001 From: Jim Date: Fri, 8 Jun 2007 00:00:00 -0400 Subject: [PATCH] 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 --- ea32i.h | 4 -- em.c | 204 +++++++++++++++++++++++++------------------------------- emdev.h | 197 +++++++++++++++++++++++++++++++++++++++++++----------- os.c | 192 ---------------------------------------------------- os.h | 8 --- 5 files changed, 248 insertions(+), 357 deletions(-) delete mode 100644 os.c delete mode 100644 os.h diff --git a/ea32i.h b/ea32i.h index 148824c..9975534 100644 --- a/ea32i.h +++ b/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 } diff --git a/em.c b/em.c index 62d0ab3..ffe3cae 100644 --- a/em.c +++ b/em.c @@ -95,6 +95,7 @@ OK: #include #include #include +#include /* 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 */ diff --git a/emdev.h b/emdev.h index 5bb518f..8e1e648 100644 --- a/emdev.h +++ b/emdev.h @@ -77,6 +77,7 @@ #include #include #include +#include /* 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> 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; diff --git a/os.c b/os.c deleted file mode 100644 index 3d3ff9a..0000000 --- a/os.c +++ /dev/null @@ -1,192 +0,0 @@ -/* os.c, Jim Wilcoxson, 4/15/2005 - Emulations of Primos Operating System routines for Unix. -*/ - -#include -#include -#include -#include -#include -#include -#include - -#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); -} diff --git a/os.h b/os.h deleted file mode 100644 index c6ff5fa..0000000 --- a/os.h +++ /dev/null @@ -1,8 +0,0 @@ -/* os.h, Jim Wilcoxson, April 15, 2005 - Include file for Primos Operating System data structures. -*/ - -static struct { - int ttydev; -} os; -