diff --git a/em.c b/em.c index c0fd476..94637c5 100644 --- a/em.c +++ b/em.c @@ -311,6 +311,7 @@ int domemdump; /* --memdump arg */ int boot; /* true if reading a boot record */ int pmap32bits; /* true if 32-bit page maps */ int csoffset; /* concealed stack segment offset */ +int tport; /* --port option (incoming terminals) */ /* load map related data, specified with --map */ @@ -907,7 +908,8 @@ void fault(unsigned short fvec, unsigned short fcode, ea_t faddr) { fatal(char *msg) { - printf("Fatal error: instruction #%d at %o/%o %s: %o %o keys=%o, modals=%o\n", instcount, prevpc >> 16, prevpc & 0xFFFF, searchloadmap(prevpc,' '), get16(prevpc), get16(prevpc+1), crs[KEYS], crs[MODALS]); + + printf("Fatal error: instruction #%d at %o/%o %s: %o %o\nowner=%o %s, keys=%o, modals=%o\n", instcount, prevpc >> 16, prevpc & 0xFFFF, searchloadmap(prevpc,' '), get16(prevpc), get16(prevpc+1), crs[OWNERL], searchloadmap(*(unsigned int *)(crs+OWNER),' '), crs[KEYS], crs[MODALS]); if (msg) printf("%s\n", msg); /* should do a register dump, RL dump, PCB dump, etc. here... */ @@ -924,15 +926,27 @@ long devpoll[64] = {0}; #include "emdev.h" -void (*devmap[64])(short, short, short) = { - 0,0,0,0,devasr,0,0,0, - 0,0,0,devmt,devmt,0,0,0, - devcp,0,0,0,0,0,devdisk,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0}; +#if 0 +int (*devmap[64])(short, short, short) = { + /* '0x */ 0,0,0,0,devasr,0,0,0, + /* '1x */ devnone,devnone,0,devmt,devmt,devamlc, devamlc, devamlc, + /* '2x */ devcp,0,devdisk,devdisk,devdisk,devdisk,devdisk,devdisk, + /* '3x */ 0,0,devamlc,0,0,devamlc,devnone,devnone, + /* '4x */ 0,0,0,0,0,0,0,0, + /* '5x */ devnone,devnone,devamlc,devamlc,devamlc,0,devnone,0, + /* '6x */ 0,0,0,0,0,0,0,0, + /* '7x */ 0,0,0,0,0,devnone,devnone,0}; +#else +int (*devmap[64])(short, short, short) = { + /* '0x */ 0,0,0,0,devasr,0,0,0, + /* '1x */ devnone,devnone,0,devmt,devmt,devnone, devnone, devnone, + /* '2x */ devcp,0,devdisk,devdisk,devdisk,devdisk,devdisk,devdisk, + /* '3x */ 0,0,devnone,0,0,devnone,devnone,devnone, + /* '4x */ 0,0,0,0,0,0,0,0, + /* '5x */ devnone,devnone,devnone,devnone,devamlc,0,devnone,0, + /* '6x */ 0,0,0,0,0,0,0,0, + /* '7x */ 0,0,0,0,0,devnone,devnone,0}; +#endif /* read a short (16-bit) integer in big-endian from stdin */ @@ -2549,6 +2563,59 @@ stc(n) { } +/* queue instructions where physical queues may be involved */ + +int rtq(ea_t qcbea, unsigned short *qent, ea_t rp) { + + unsigned int qtop, qbot, qtemp; + unsigned short qseg, qmask; + ea_t qentea; + + qtop = get16r(qcbea, rp); + qbot = get16r(qcbea+1, rp); + + if (qtop == qbot) + return 0; /* queue is empty */ + qseg = get16r(qcbea+2, rp); + qmask = get16r(qcbea+3, rp); + qentea = MAKEVA(qseg & 0xfff, qtop); + if (qseg & 0x8000) /* virtual queue */ + *qent = get16r(qentea, rp); + else { + RESTRICTR(rp); + *qent = mem[qentea]; + } + qtop = (qtop & ~qmask) | ((qtop+1) & qmask); + put16r(qtop & 0xFFFF, qcbea, rp); + return 1; +} + + +int abq(ea_t qcbea, unsigned short qent, ea_t rp) { + + unsigned int qtop, qbot, qtemp; + unsigned short qseg, qmask; + ea_t qentea; + + qtop = get16r(qcbea, rp); + qbot = get16r(qcbea+1, rp); + qseg = get16r(qcbea+2, rp); + qmask = get16r(qcbea+3, rp); + qtemp = (qbot & ~qmask) | ((qbot+1) & qmask); + if (qtemp == qtop) /* queue full */ + return 0; + qentea = MAKEVA(qseg & 0xfff,qbot); + if (qseg & 0x8000) /* virtual queue */ + put16r(crs[A], qentea, rp); + else { + RESTRICTR(rp); + mem[qentea] = qent; + } + put16r(qtemp, qcbea+1, rp); + return 1; +} + + main (int argc, char **argv) { short tempa,tempa1,tempa2; @@ -2621,6 +2688,7 @@ main (int argc, char **argv) { boot = 0; pmap32bits = 0; csoffset = 0; + tport = 0; /* check args */ @@ -2646,6 +2714,12 @@ main (int argc, char **argv) { cpuid = templ; } else fprintf(stderr,"--cpuid needs an argument\n"); + } else if (strcmp(argv[i],"--port") == 0) { + if (i+1 < argc && argv[i+1][0] != '-') { + sscanf(argv[i+1],"%d", &templ); + tport = templ; + } else + fprintf(stderr,"--cpuid needs an argument\n"); } else if (strcmp(argv[i],"--trace") == 0) while (i+1 < argc && argv[i+1][0] != '-') { if (strcmp(argv[i+1],"ear") == 0) @@ -2689,6 +2763,8 @@ main (int argc, char **argv) { pmap32bits = (cpuid == 15 || cpuid == 18 || cpuid == 19 || cpuid == 24 || cpuid >= 26); if ((26 <= cpuid && cpuid <= 29) || cpuid >= 35) csoffset = 1; + if (tport == 0) + tport = 8000; fprintf(stderr,"Sense switches set to %o\n", sswitch); @@ -2696,7 +2772,11 @@ main (int argc, char **argv) { for (i=0; i<64; i++) if (devmap[i]) - devmap[i](-1, 0, i); + if (devmap[i](-1, 0, i)) { /* if initialization fails, */ + devmap[i] = devnone; /* remove device */ + printf("emulator: device '%o removed\n", i); + } + os_init(); @@ -2764,23 +2844,23 @@ main (int argc, char **argv) { traceflags = ~TB_MAP; #endif -#if 1 +#if 0 if (traceflags != 0) savetraceflags = traceflags; #endif -#if 0 +#if 1 if (traceflags != 0) savetraceflags = traceflags; - if (crs[OWNERL] == 0100100 && savetraceflags) + if (crs[OWNERL] == 0100200 && savetraceflags) traceflags = savetraceflags; else traceflags = 0; #endif #if 0 - /* NOTE: this tends to hang if the location being monitored isn't - wired */ + /* NOTE: this tends to cause a page fault loop if the location + being monitored isn't wired */ if (trapaddr != 0 && (crs[OWNERL] & 0100000) && (crs[MODALS] & 010)) { traceflags = -1; @@ -2800,6 +2880,10 @@ main (int argc, char **argv) { if (devpoll[i] && (--devpoll[i] == 0)) { if (!devmap[i]) fatal("devpoll set but devmap is null"); +#if 0 + if (i == 054) + traceflags = savetraceflags; +#endif devmap[i](4, 0, i); } @@ -2915,12 +2999,10 @@ main (int argc, char **argv) { xec: /* NOTE: don't trace JMP * instructions (used to test PX) */ - if (inst != 03777 && savetraceflags) - traceflags = savetraceflags; - else + if (inst == 03777) traceflags = 0; - if (T_FLOW) fprintf(stderr,"\n #%u [%s %o] IT=%d SB: %o/%o LB: %o/%o %s XB: %o/%o\n%o/%o: %o A='%o/%:0d B='%o/%d X=%o/%d Y=%o/%d C=%d L=%d LT=%d EQ=%d K=%o M=%o\n", instcount, searchloadmap(*(unsigned int *)(crs+OWNER),'x'), crs[OWNERL], *(short *)(crs+TIMER), crs[SBH], crs[SBL], crs[LBH], crs[LBL], searchloadmap(*(unsigned int *)(crs+LBH),'l'), crs[XBH], crs[XBL], RPH, RPL-1, inst, crs[A], *(short *)(crs+A), crs[B], *(short *)(crs+B), crs[X], *(short *)(crs+X), crs[Y], *(short *)(crs+Y), (crs[KEYS]&0100000) != 0, (crs[KEYS]&020000) != 0, (crs[KEYS]&0200) != 0, (crs[KEYS]&0100) != 0, crs[KEYS], crs[MODALS]); + if (T_FLOW) fprintf(stderr,"\n #%u [%s %o] IT=%d SB: %o/%o LB: %o/%o %s XB: %o/%o\n%o/%o: %o A='%o/%:0d B='%o/%d L='%o/%d E='%o/%d X=%o/%d Y=%o/%d C=%d L=%d LT=%d EQ=%d K=%o M=%o\n", instcount, searchloadmap(*(unsigned int *)(crs+OWNER),'x'), crs[OWNERL], *(short *)(crs+TIMER), crs[SBH], crs[SBL], crs[LBH], crs[LBL], searchloadmap(*(unsigned int *)(crs+LBH),'l'), crs[XBH], crs[XBL], RPH, RPL-1, inst, crs[A], *(short *)(crs+A), crs[B], *(short *)(crs+B), *(unsigned int *)(crs+L), *(int *)(crs+L), *(unsigned int *)(crs+E), *(int *)(crs+E), crs[X], *(short *)(crs+X), crs[Y], *(short *)(crs+Y), (crs[KEYS]&0100000) != 0, (crs[KEYS]&020000) != 0, (crs[KEYS]&0200) != 0, (crs[KEYS]&0100) != 0, crs[KEYS], crs[MODALS]); /* begin instruction decode: generic? */ @@ -3539,11 +3621,14 @@ stfa: case 001702: if (T_FLOW) fprintf(stderr," 1702?\n", inst); - printf(" 1702? at #%d, OWNERL=%o, RP=%o/%o\n", instcount, crs[OWNERL], RPH, RPL); +#if 1 + fatal("Primos software assertion failure"); +#else RESTRICT(); //fault(UIIFAULT, RPL, RP); traceflags = ~TB_MAP; dispatcher(); +#endif continue; case 000601: @@ -4651,24 +4736,21 @@ lcgt: *(int *)(crs+E) = templ; continue; - /* queue instructions */ + /* queue instructions + + NOTE: ABQ is typically used in software to add an item to a + hardware (physical) queue and RTQ is used by DMQ hardware + to fetch items from the queue. */ case 0141714: if (T_FLOW) fprintf(stderr," RTQ\n"); ea = apea(NULL); - qtop = get16(ea); - qbot = get16(ea+1); - if (qtop == qbot) { + if (rtq(ea,&utempa,RP)) { + crs[A] = utempa; + crs[KEYS] &= ~0100; + } else { crs[A] = 0; crs[KEYS] |= 0100; - } else { - qseg = get16(ea+2) & 0x7FFF; - qmask = get16(ea+3); - qea = MAKEVA(qseg,qtop); - crs[A] = get16(qea); - qtop = (qtop & ~qmask) | ((qtop+1) & qmask); - put16(qtop, ea); - crs[KEYS] &= ~0100; } continue; @@ -4694,19 +4776,10 @@ lcgt: case 0141716: if (T_FLOW) fprintf(stderr," ABQ\n"); ea = apea(NULL); - qtop = get16(ea); - qbot = get16(ea+1); - qseg = get16(ea+2) & 0x7FFF; - qmask = get16(ea+3); - qtemp = (qbot & ~qmask) | ((qbot+1) & qmask); - if (qtemp == qtop) { /* queue full */ - crs[KEYS] |= 0100; - } else { - qea = MAKEVA(qseg,qbot); - put16(crs[A],qea); - put16(qtemp, ea+1); + if (abq(ea, crs[A], RP)) crs[KEYS] &= ~0100; - } + else + crs[KEYS] |= 0100; continue; case 0141717: @@ -6627,8 +6700,11 @@ pio(unsigned int inst) { if (devmap[device]) devmap[device](class, func, device); else { - fprintf(stderr,"pio: no handler for device '%o\n", device); - return; +#if 1 + printf("pio: no handler, class=%d, func='%o, device='%o, A='%o\n", class, func, device, crs[A]); fatal(NULL); +#else + fprintf(stderr, "pio: no handler, class=%d, func='%o, device='%o, A='%o\n", class, func, device, crs[A]); +#endif } } diff --git a/emdev.h b/emdev.h index 94cc8fd..b4c2caa 100644 --- a/emdev.h +++ b/emdev.h @@ -8,29 +8,37 @@ INA/OTA instructions skip if they succeed (data was read/written) Device numbers: + '00 = polling (?) '01 = paper tape reader '02 = paper tape punch - '03 = 1st MPC (line printer/card reader/card punch) + '03 = #1 MPC/URC (line printer/card reader/card punch) '04 = SOC board (system console/user terminal) - '05 = 2nd MPC (line printer/card reader/card punch) + '05 = #2 MPC/URC (line printer/card reader/card punch) '06 = card punch? (RTOS User Guide, A-1) / IPC (Engr Handbook p.101) - '07 = PNC - '12 = diskette - '13 = 2nd magtape controller - '14 = 1st magtape controller + '06 = Interproc. Channel (IPC) (R20 Hacker's Guide) + '07 = #1 PNC + '10 = ICS2 #1 or ICS1 + '11 = ICS2 #2 or ICS1 + '12 = floppy disk/diskette + '13 = #2 magtape controller + '14 = #1 magtape controller + '15 = #5 AMLC or ICS1 + '16 = #6 AMLC or ICS1 + '17 = #7 AMLC or ICS1 '20 = control panel / real-time clock - '21 = 1st 4002 disk controller - '22 = disk - '23 = disk - '24 = disk - '25 = disk + '21 = 1st 4002 (Option B') disk controller + '22 = disk #3 + '23 = disk #4 + '24 = disk (was Writable Control Store) + '25 = disk (was 4000 disk controller) '26 = 1st disk controller '27 = 2nd disk controller '30-32 = BPIOC #1-3 (RTOS User Guide, A-1) - '33 = 1st Versatec (verdim) - '34 = 2nd Versatec - '35 = 4th AMLC - '36-37 = ELFBUS #1 & 2 + '32 = AMLC #8 or ICS1 + '33 = #1 Versatec (verdim) + '34 = #2 Versatec + '35 = #4 AMLC or ICS1 + '36-37 = ELFBUS #1 & 2 (ICS1 #1, ICS1 #2) '40 = A/D converter type 6000 '41 = digital input type 6020 '42 = digital input #2 @@ -38,26 +46,34 @@ '44 = digital output #2 '45 = disk (was D/A converter type 6060 (analog output) - obsolete) '46 = disk - '50 = 1st HSSMLC (cs/slcdim.pma) - '51 = 2nd HSSMLC - '52 = 3rd AMLC - '53 = 2nd AMLC - '54 = 1st AMLC + '47 = #2 PNC + '50 = #1 HSSMLC (cs/slcdim.pma) + '51 = #2 HSSMLC + '52 = #3 AMLC or ICS1 + '53 = #2 AMLC + '54 = #1 AMLC '55 = MACI autocall unit - '56 = old SMLC (RTOS User Guide, A-1) - '60-67 = reserved for user devices + '56 = old SMLC (RTOS User Guide, A-1 & Hacker's Guide) + '60-67 = reserved for user devices (GPIB) '70-'73 = Megatek graphics terminals - Devices emulated by Primos in ks/ptrap.ftn: - '04 = console, '01 = paper tape reader, '02 = paper tape punch, - '20 = control panel + Devices emulated by Primos in ks/ptrap.ftn for I/O instructions in Ring 3: + '01 = paper tape reader + '02 = paper tape punch + '04 = console + '20 = control panel lights & sense switches */ +#include #include #include #include #include #include +#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 */ @@ -81,15 +97,18 @@ -/* this is a template for device handlers */ +/* this is a template for new device handlers */ -void devnull (short class, short func, short device) { +int devnew (short class, short func, short device) { switch (class) { + case -1: + return 0; + case 0: if (T_INST) fprintf(stderr," OCP '%02o%02o\n", func, device); - if (func == 0) { + if (func == 99) { ; } else { printf("Unimplemented OCP device '%02o function '%02o\n", device, func); @@ -99,7 +118,7 @@ void devnull (short class, short func, short device) { case 1: if (T_INST) fprintf(stderr," SKS '%02o%02o\n", func, device); - if (func == 0) + if (func == 99) IOSKIP; /* assume it's always ready */ else { printf("Unimplemented SKS device '%02o function '%02o\n", device, func); @@ -109,7 +128,7 @@ void devnull (short class, short func, short device) { case 2: if (T_INST) fprintf(stderr," INA '%02o%02o\n", func, device); - if (func == 0) { + if (func == 99) { ; } else { printf("Unimplemented INA device '%02o function '%02o\n", device, func); @@ -119,10 +138,10 @@ void devnull (short class, short func, short device) { case 3: if (T_INST) fprintf(stderr," OTA '%02o%02o\n", func, device); - if (func == 0 | func == 1) { - IOSKIP; /* OTA '0004 always works on Unix */ + if (func == 99) { + IOSKIP; } else { - printf("Unimplemented OTA device '%02o function '%02o\n", device, func); + printf("Unimplemented OTA device '%02o function '%02o, A='%o\n", device, func, crs[A]); fatal(NULL); } break; @@ -130,6 +149,38 @@ void devnull (short class, short func, short device) { } +/* this is a template for null (not present) devices */ + +int devnone (short class, short func, short device) { + + switch (class) { + + case -1: + return 0; + + case 0: + if (T_INST) fprintf(stderr," OCP '%02o%02o\n", func, device); + fprintf(stderr, " unimplemented device '%o\n", device); + break; + + case 1: + if (T_INST) fprintf(stderr," SKS '%02o%02o\n", func, device); + fprintf(stderr, " unimplemented device '%o\n", device); + break; + + case 2: + if (T_INST) fprintf(stderr," INA '%02o%02o\n", func, device); + fprintf(stderr, " unimplemented device '%o\n", device); + break; + + case 3: + if (T_INST) fprintf(stderr," OTA '%02o%02o\n", func, device); + fprintf(stderr, " unimplemented device '%o\n", device); + break; + } +} + + /* Device '4: system console NOTES: @@ -193,7 +244,7 @@ void devnull (short class, short func, short device) { */ -void devasr (short class, short func, short device) { +int devasr (short class, short func, short device) { static int ttydev; static int ttyflags; @@ -211,6 +262,7 @@ void devasr (short class, short func, short device) { switch (class) { case -1: + setsid(); ttydev = open("/dev/tty", O_RDWR, 0); if (ttydev < 0) { perror(" error opening /dev/tty"); @@ -233,7 +285,7 @@ void devasr (short class, short func, short device) { perror(" unable to set tty attributes"); fatal(NULL); } - break; + return 0; case 0: if (T_INST) fprintf(stderr," OCP '%02o%02o\n", func, device); @@ -390,7 +442,7 @@ readasr: /* NOTE: 9950 does this in rev 20, others don't */ IOSKIP; } else { - printf("Unimplemented OTA '04 function '%02o\n", func); + printf("Unimplemented OTA device '%02o function '%02o, A='%o\n", device, func, crs[A]); fatal(NULL); } break; @@ -413,10 +465,13 @@ readasr: /* Device '14 - magtape controller #1 */ -void devmt (short class, short func, short device) { +int devmt (short class, short func, short device) { switch (class) { + case -1: + return 0; + case 0: if (T_INST) fprintf(stderr," OCP '%02o%02o\n", func, device); break; @@ -479,29 +534,51 @@ void devmt (short class, short func, short device) { IMPORTANT NOTE: this device ('20) never skips! */ -void devcp (short class, short func, short device) { +int devcp (short class, short func, short device) { static short enabled = 0; static unsigned short clkvec; static short clkpic; + int datnow, i; + time_t unixtime; + ea_t datnowea; + struct tm *tms; + #define SETCLKPOLL devpoll[device] = instpermsec*(-clkpic*3.2)/1000; switch (class) { + case -1: + return 0; + case 0: if (T_INST) fprintf(stderr," OCP '%02o%02o\n", func, device); - printf("OCP '%02o%02o\n", func, device); - if (func == 0 || func == 015) { - fprintf(stderr,"Clock process initialized!\n"); + if (func == 01) { /* ack PIC interrupt */ + ; + + } else if (func == 015) { /* set interrupt mask */ + fprintf(stderr,"Clock interrupt enabled!\n"); /* this enables tracing when the clock process initializes */ //traceflags = ~TB_MAP; enabled = 1; -#if 0 +#if 1 SETCLKPOLL; #else devpoll[device] = 600000; #endif + datnowea = 0; + for (i=0; itm_year<<25 | (tms->tm_mon+1)<<21 | tms->tm_mday<<16 | ((tms->tm_hour*3600 + tms->tm_min*60 + tms->tm_sec)/4); + put32(datnow, datnowea); + } + } else if (func == 016 || func == 017) { enabled = 0; devpoll[device] = 0; @@ -521,7 +598,7 @@ void devcp (short class, short func, short device) { case 2: if (T_INST) fprintf(stderr," INA '%02o%02o\n", func, device); if (func == 011) { /* input ID */ - crs[A] != 0120; /* this is the SOC board */ + crs[A] = 0120; /* this is the SOC board */ } else if (func == 016) { crs[A] = sswitch; } else if (func == 017) { /* read switches in momentary down position */ @@ -537,15 +614,15 @@ void devcp (short class, short func, short device) { if (func == 02) { /* set PIC interval */ clkpic = *(short *)(crs+A); SETCLKPOLL; - printf("Clock PIC interval set to %d\n", clkpic); + //printf("Clock PIC interval set to %d\n", clkpic); } else if (func == 07) { - printf("Clock control register set to '%o\n", crs[A]); + //printf("Clock control register set to '%o\n", crs[A]); } else if (func == 013) { clkvec = crs[A]; - printf("Clock interrupt vector address = '%o\n", clkvec); + //printf("Clock interrupt vector address = '%o\n", clkvec); } else if (func == 017) { /* write lights */ } else { - printf("Unimplemented OTA device '%02o function '%02o\n", device, func); + printf("Unimplemented OTA device '%02o function '%02o, A='%o\n", device, func, crs[A]); fatal(NULL); } break; @@ -594,12 +671,14 @@ void devcp (short class, short func, short device) { */ -void devdisk (short class, short func, short device) { +int devdisk (short class, short func, short device) { #define S_HALT 0 #define S_RUN 1 #define S_INT 2 +#define MAXDRIVES 8 + #if 0 #define CID4005 0100 #else @@ -620,7 +699,7 @@ void devdisk (short class, short func, short device) { unsigned short spt; /* sectors per track */ int devfd; /* Unix device file descriptor */ int readnum; /* increments on each read */ - } unit[4]; + } unit[MAXDRIVES]; } dc[64]; short i,u; @@ -638,6 +717,7 @@ void devdisk (short class, short func, short device) { unsigned int utempl; char ordertext[8]; int theads, spt, phyra; + int nb; /* number of bytes returned from read/write */ char devfile[8]; char rtfile[16]; /* read trace file name */ int rtnw; /* total number of words read (all channels) */ @@ -649,7 +729,7 @@ void devdisk (short class, short func, short device) { dc[i].state = S_HALT; dc[i].status = 0100000; dc[i].usel = -1; - for (u=0; u<4; u++) { + for (u=0; u> 12; + //printf("OTA '01%02o: AMLC line %d config = %x\n", device, lx, crs[A]); + /* if DTR drops on a connected line, disconnect */ + if (!(crs[A] & 0x400) && (dc[device].dss & bitmask16[lx+1])) { + /* see similar code below */ + write(dc[device].sockfd[lx], "\r\nDisconnecting on logout\r\n", 27); + close(dc[device].sockfd[lx]); + dc[device].dss &= ~bitmask16[lx+1]; + printf("Closing AMLC line %d on device '%o\n", lx, device); + } + IOSKIP; + + } else if (func == 02) { /* set line control */ + //printf("OTA '02%02o: AMLC line control = %x\n", device, crs[A]); + lx = (crs[A]>>12); + if (crs[A] & 040) /* character time interrupt enable/disable */ + dc[device].ctinterrupt |= bitmask16[lx+1]; + else + dc[device].ctinterrupt &= ~bitmask16[lx+1]; + if (crs[A] & 010) /* transmit enable/disable */ + dc[device].xmitenabled |= bitmask16[lx+1]; + else + dc[device].xmitenabled &= ~bitmask16[lx+1]; + if (crs[A] & 01) /* receive enable/disable */ + dc[device].recvenabled |= bitmask16[lx+1]; + else + dc[device].recvenabled &= ~bitmask16[lx+1]; + if ((dc[device].ctinterrupt || dc[device].xmitenabled || dc[device].recvenabled) && devpoll[device] == 0) + devpoll[device] = AMLCPOLL*instpermsec; /* setup another poll */ + IOSKIP; + + } else if (func == 014) { /* set DMA/C channel (for input) */ + dc[device].dmcchan = crs[A] & 0x7ff; + //printf("OTA '14%02o: AMLC chan = %o\n", device, dc[device].dmcchan); + if (!(crs[A] & 0x800)) + fatal("Can't run AMLC in DMA mode!"); + IOSKIP; + + } else if (func == 015) { /* set DMT/DMQ base address (for output) */ + dc[device].baseaddr = crs[A]; + IOSKIP; + + } else if (func == 016) { /* set interrupt vector */ + dc[device].intvector = crs[A]; + IOSKIP; + + } else if (func == 017) { /* set programmable clock constant */ + IOSKIP; + + } else { + printf("Unimplemented OTA device '%02o function '%02o, A='%o\n", device, func, crs[A]); + fatal(NULL); + } + break; + + case 4: + //printf("poll device '%o, cti=%x, xmit=%x, recv=%x, dss=%x\n", device, dc[device].ctinterrupt, dc[device].xmitenabled, dc[device].recvenabled, dc[device].dss); + + /* check for new connections */ + +conloop: + + while ((fd = accept(tsfd, (struct sockaddr *)&addr, &addrlen)) == -1 && errno == EINTR) + ; + if (fd == -1) { + if (errno != EWOULDBLOCK) { + perror("accept error for AMLC"); + fatal("accept error for AMLC"); + } + } else { + if (fd >= MAXFD) + fatal("New connection fd is too big"); + newdevice = 0; + for (i=0; !newdevice && i 0) { + for (i=0; i dmcbufendea) { /* end of range has occurred */ + dc[device].bufnum = 1-dc[device].bufnum; + dc[device].eor = 1; + } + } + } + } + if (intvec == -1 && dc[device].intenable && (dc[device].ctinterrupt || dc[device].eor)) { + intvec = dc[device].intvector; + dc[device].interrupting = 1; + } + + if ((dc[device].ctinterrupt || dc[device].xmitenabled || dc[device].recvenabled) && devpoll[device] == 0) + devpoll[device] = AMLCPOLL*instpermsec; /* setup another poll */ + break; + } +}