mirror of
https://github.com/aap/pdp6.git
synced 2026-01-11 23:53:31 +00:00
added network memory; some work on cmdline interface
This commit is contained in:
parent
67fa30288e
commit
28cc63f3ba
@ -71,5 +71,5 @@ The TTY is connected to UART over GPIO pins 4 (RX) and 5 (TX)
|
||||
|
||||
- repeat and maint. switches
|
||||
- test thoroughly!
|
||||
- devices
|
||||
- devices (test UT, implement 340)
|
||||
- timing
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
sysgen.rim: sysgen.rel sysgen.lst
|
||||
ld6 -o sysgen.rim sysgen.rel
|
||||
|
||||
test.rim: main.rel tty.rel pt.rel dt.rel
|
||||
ld6 -o test.rim main.rel tty.rel pt.rel dt.rel
|
||||
|
||||
|
||||
@ -50,16 +50,74 @@ PDP-10 RIM10 LOADER:
|
||||
|
||||
|
||||
MAC DECtape RIM loader:
|
||||
000000 JFCL
|
||||
000001 MOVSI (JFCL)
|
||||
000002 CONO 635550
|
||||
000003 CONO PI,11577
|
||||
000004 CONO UTC,223110
|
||||
000005 CONO DC,4010
|
||||
000006 CONSO DC,1000
|
||||
000007 JRST 6
|
||||
000010 DATAI DC,13
|
||||
000011 AOJGE 13,6
|
||||
000012 TRNE 13,-1
|
||||
000013 .
|
||||
000014 JRST 6
|
||||
00 255000 000000 JFCL / no-op, what for?
|
||||
01 205000 255000 MOVSI (JFCL) / restore JFCL in 0
|
||||
02 700200 635550 CONO 635550 / reset APR
|
||||
03 700600 011577 CONO PI,11577 / reset PI
|
||||
04 721200 223110 CONO UTC,223110 / read all forward
|
||||
05 720200 004010 CONO DC,4010 / read
|
||||
06 720340 001000 LUP%: CONSO DC,1000 / wait for word
|
||||
07 254000 000006 JRST .-1
|
||||
10 720040 000013 DATAI DC,A% / read word
|
||||
11 345540 000006 AOJGE A%,LUP% / try next word if >= -1
|
||||
12 602540 777777 TRNE A%,-1 / execute if RH!=0 (was -1)
|
||||
13 000000 000013 A%: .
|
||||
14 254000 000006 JRST LUP%
|
||||
15
|
||||
16
|
||||
17
|
||||
11: like AOBJP without incrementing left half
|
||||
12: execute only if right half != 0
|
||||
|
||||
0 DATAI PTR,1
|
||||
1 .
|
||||
2 JRST 0
|
||||
|
||||
Written by RIM loader loader (part of MACDMP)
|
||||
2 JRST 0
|
||||
10 CONO 1000 / turn clock flag off
|
||||
11 JFCL X
|
||||
12 JFCL X
|
||||
13 JFCL X
|
||||
14 JFCL X
|
||||
15 CONSZ 1000 / skip if clock flag off
|
||||
16 JRST 10 / clock on, so still on repeat
|
||||
17 SKIPA X / clock off, we're at full speed
|
||||
|
||||
20 CONO PTR,60
|
||||
21 CONSO PTR,10
|
||||
22 JRST 21
|
||||
23 DATAI PTR,26
|
||||
24 CONSO PTR,10
|
||||
25 JRST 24
|
||||
26 XCT 26
|
||||
27 JRST 21
|
||||
|
||||
37 37176
|
||||
|
||||
|
||||
PDP6 SBLK loader:
|
||||
1 MOVE 1,15
|
||||
2 JSP 17,30 / wait for ready
|
||||
3 DATAI PTR,16 / get block header
|
||||
4 MOVE 15,16 / save for checksum
|
||||
5 JUMPG 16,16 / execute if not negative
|
||||
6 JSP 17,30 / read block word
|
||||
7 DATAI PTR,(16)
|
||||
10 ROT 15,1
|
||||
11 ADD 15,(16)
|
||||
12 AOBJN 16,6
|
||||
13 MOVEI 17,33
|
||||
14 JRST 30
|
||||
15 CONO PTR,60 / replaced by current checksum
|
||||
16 / input word: header/aobjn pointer/checksum
|
||||
17 / return address
|
||||
|
||||
30 CONSO PTR,10 / wait for word
|
||||
31 JRST 30
|
||||
32 JRST (17)
|
||||
|
||||
33 DATAI PTR,16 / get checksum word
|
||||
34 CAMN 15,16
|
||||
35 JRST 2 / go to next block if checksum ok
|
||||
36 JRST 4,1
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
SRC=main.c cmd.c apr.c mem.c tty.c pt.c dc.c dt.c ../tools/pdp6common.c
|
||||
SRC=main.c util.c cmd.c apr.c mem.c tty.c pt.c dc.c dt.c netmem.c ../tools/pdp6common.c
|
||||
H=pdp6.h ../tools/pdp6common.h
|
||||
# clang
|
||||
#CFLAGS= -Wno-shift-op-parentheses -Wno-logical-op-parentheses \
|
||||
|
||||
34
emu/apr.c
34
emu/apr.c
@ -68,6 +68,38 @@ nextpulse(Apr *apr, Pulse *p)
|
||||
apr->nlist[apr->nnextpulses++] = p;
|
||||
}
|
||||
|
||||
// TODO This is WIP
|
||||
|
||||
#define EXDEPREGS \
|
||||
X(ir)\
|
||||
X(mi)\
|
||||
X(data)\
|
||||
X(pc)\
|
||||
X(ma)\
|
||||
X(mas)\
|
||||
X(mb)\
|
||||
X(ar)\
|
||||
X(mq)
|
||||
|
||||
static word
|
||||
ex_apr(Device *dev, const char *reg)
|
||||
{
|
||||
Apr *apr = (Apr*)dev;
|
||||
#define X(name) if(strcmp(#name, reg) == 0) return apr->name;
|
||||
EXDEPREGS
|
||||
#undef X
|
||||
return ~0;
|
||||
}
|
||||
static int
|
||||
dep_apr(Device *dev, const char *reg, word data)
|
||||
{
|
||||
Apr *apr = (Apr*)dev;
|
||||
#define X(name) if(strcmp(#name, reg) == 0) { apr->name = data; return 0; }
|
||||
EXDEPREGS
|
||||
#undef X
|
||||
return 1;
|
||||
}
|
||||
|
||||
Device*
|
||||
makeapr(int argc, char *argv[])
|
||||
{
|
||||
@ -81,6 +113,8 @@ makeapr(int argc, char *argv[])
|
||||
apr->dev.name = "";
|
||||
apr->dev.attach = nil;
|
||||
apr->dev.ioconnect = nil;
|
||||
apr->dev.examine = ex_apr;
|
||||
apr->dev.deposit = dep_apr;
|
||||
apr->dev.next = nil;
|
||||
|
||||
apr->iobus.dev[CPA] = (Busdev){ apr, wake_cpa, 0 };
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#define USED(x) ((void)x)
|
||||
#define SET(x) ((x)=0)
|
||||
|
||||
#define ARGBEGIN for((argv0||(argv0=*argv)),argv++,argc--;\
|
||||
#define ARGBEGIN for((void)(argv0||(argv0=*argv)),argv++,argc--;\
|
||||
argv[0] && argv[0][0]=='-' && argv[0][1];\
|
||||
argc--, argv++) {\
|
||||
char *_args, *_argt;\
|
||||
|
||||
122
emu/cmd.c
122
emu/cmd.c
@ -213,6 +213,7 @@ DevDef definitions[] = {
|
||||
{ DC_IDENT, makedc },
|
||||
{ DT_IDENT, makedt },
|
||||
{ DX_IDENT, makedx },
|
||||
{ NETMEM_IDENT, makenetmem },
|
||||
{ nil, nil }
|
||||
};
|
||||
|
||||
@ -408,6 +409,79 @@ c_dep(int argc, char *argv[])
|
||||
dep(start, fastmem, w);
|
||||
}
|
||||
|
||||
/* parse "devname.reg".
|
||||
* look up "devname" and return it.
|
||||
* also remove "devname." from original string.
|
||||
* if "devname." is missing, return last device.
|
||||
* return apr if anything goes wrong */
|
||||
Device*
|
||||
getexdepdev(char *dev)
|
||||
{
|
||||
static Device *exdepdev;
|
||||
char *s;
|
||||
Device *d;
|
||||
|
||||
s = strchr(dev, '.');
|
||||
if(s == nil){
|
||||
if(exdepdev == nil)
|
||||
exdepdev = &apr->dev;
|
||||
return exdepdev;
|
||||
}
|
||||
*s++ = '\0';
|
||||
d = getdevice(dev);
|
||||
exdepdev = d ? d : &apr->dev;
|
||||
while(*dev++ = *s++);
|
||||
return exdepdev;
|
||||
}
|
||||
|
||||
static void
|
||||
c_xex(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
Device *dev;
|
||||
word w;
|
||||
for(i = 1; i < argc; i++){
|
||||
dev = getexdepdev(argv[i]);
|
||||
if(dev->examine){
|
||||
strtolower(argv[i]);
|
||||
w = dev->examine(dev, argv[i]);
|
||||
if(w == ~0)
|
||||
printf("can't examine %s\n", argv[i]);
|
||||
else
|
||||
printf("%012lo\n", w);
|
||||
}else
|
||||
printf("no examine on %s\n", dev->type);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
c_xdep(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
Device *dev;
|
||||
word w;
|
||||
|
||||
if(argc < 3)
|
||||
return;
|
||||
|
||||
w = parsen(&argv[argc-1]);
|
||||
if(w == ~0)
|
||||
return;
|
||||
|
||||
for(i = 1; i < argc-1; i++){
|
||||
dev = getexdepdev(argv[i]);
|
||||
if(dev->deposit){
|
||||
strtolower(argv[i]);
|
||||
if(dev->deposit(dev, argv[i], w))
|
||||
printf("can't deposit %s\n", argv[i]);
|
||||
}else
|
||||
printf("no deposit on %s\n", dev->type);
|
||||
}
|
||||
|
||||
void updatepanel(Apr *apr);
|
||||
updatepanel(apr);
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
FmtUnk, FmtSav
|
||||
@ -475,23 +549,51 @@ c_quit(int argc, char *argv[])
|
||||
quit(0);
|
||||
}
|
||||
|
||||
static void c_help(int argc, char *argv[]);
|
||||
|
||||
struct {
|
||||
char *cmd;
|
||||
void (*f)(int, char **);
|
||||
char *desc;
|
||||
} cmdtab[] = {
|
||||
{ "mkdev", c_mkdev },
|
||||
{ "attach", c_attach },
|
||||
{ "ioconnect", c_ioconnect },
|
||||
{ "memconnect", c_memconnect },
|
||||
{ "devconnect", c_devconnect },
|
||||
{ "examine", c_ex },
|
||||
{ "deposit", c_dep },
|
||||
{ "load", c_load },
|
||||
{ "show", c_show },
|
||||
{ "quit", c_quit },
|
||||
{ "mkdev", c_mkdev,
|
||||
"make a device: mkdev name type [args]" },
|
||||
{ "attach", c_attach,
|
||||
"attach a file to a devie: attach name filename" },
|
||||
{ "connectio", c_ioconnect,
|
||||
"connect device to IO bus: connectio devname procname" },
|
||||
{ "connectmem", c_memconnect,
|
||||
"connect memory to mem bus: connectmem memname memport procname address/16k" },
|
||||
{ "connectdev", c_devconnect,
|
||||
"connect devices: connectdev dev1name dev2name [args]" },
|
||||
{ "examine", c_ex,
|
||||
"examine memory: examine [-sm] memrange" },
|
||||
{ "deposit", c_dep,
|
||||
"deposit memory: deposit [-s] memrange word" },
|
||||
{ "xexamine", c_xex,
|
||||
"examine device" },
|
||||
{ "xdeposit", c_xdep,
|
||||
"deposit device" },
|
||||
{ "load", c_load,
|
||||
"load file into memory: load [-s] filename" },
|
||||
{ "show", c_show,
|
||||
"show configuration" },
|
||||
{ "quit", c_quit,
|
||||
"quit emulator" },
|
||||
{ "help", c_help,
|
||||
"print help" },
|
||||
{ "", nil}
|
||||
};
|
||||
|
||||
static void
|
||||
c_help(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; cmdtab[i].cmd[0]; i++)
|
||||
printf(" %s:\t%s\n", cmdtab[i].cmd, cmdtab[i].desc);
|
||||
}
|
||||
|
||||
void
|
||||
commandline(char *line)
|
||||
{
|
||||
|
||||
10
emu/cmds.txt
10
emu/cmds.txt
@ -2,17 +2,21 @@ mkdev name type
|
||||
creates a device and gives it a name
|
||||
attach name path
|
||||
attaches a file to a device
|
||||
ioconnect name busdevname
|
||||
connectio name busdevname
|
||||
connects a device to the IO bus of a processor
|
||||
memconnect name procnum busdevname addr
|
||||
connectmem name procnum busdevname addr
|
||||
connects a memory module to the memory bus of a processor
|
||||
connectdev dev1name dev2name [args]
|
||||
connects two devices in the appropriate way if possible
|
||||
examine [-sm] address(range)
|
||||
examines memory (s: shadow mode, m: mnemonic)
|
||||
deposit [-sm] address(range) word
|
||||
deposits word into memory (s: shadow mode, m: mnemonic)
|
||||
load filename
|
||||
load [-s] filename
|
||||
loads file into memory (see source for which format)
|
||||
show
|
||||
shows device configuration
|
||||
help
|
||||
print help
|
||||
quit
|
||||
take a guess
|
||||
|
||||
32
emu/init.ini
32
emu/init.ini
@ -11,21 +11,25 @@ mkdev cmem0 cmem161C mem_0
|
||||
mkdev cmem1 cmem161C mem_1
|
||||
mkdev cmem2 cmem161C mem_2
|
||||
mkdev cmem3 cmem161C mem_3
|
||||
#mkdev netmem netmem its.pdp10.se 10006
|
||||
|
||||
devconnect dc dt0
|
||||
devconnect dt0 dx0 8
|
||||
ioconnect tty apr
|
||||
ioconnect ptr apr
|
||||
ioconnect ptp apr
|
||||
ioconnect dc apr
|
||||
ioconnect dt0 apr
|
||||
memconnect fmem 0 apr -1
|
||||
memconnect cmem0 0 apr 0
|
||||
memconnect cmem1 0 apr 1
|
||||
memconnect cmem2 0 apr 2
|
||||
memconnect cmem3 0 apr 3
|
||||
connectdev dc dt0
|
||||
connectdev dt0 dx0 8
|
||||
connectio tty apr
|
||||
connectio ptr apr
|
||||
connectio ptp apr
|
||||
connectio dc apr
|
||||
connectio dt0 apr
|
||||
connectmem fmem 0 apr -1
|
||||
connectmem cmem0 0 apr 0
|
||||
connectmem cmem1 0 apr 1
|
||||
connectmem cmem2 0 apr 2
|
||||
connectmem cmem3 0 apr 3
|
||||
|
||||
attach tty /tmp/6tty
|
||||
attach ptr ../code/test.rim
|
||||
#attach ptr ../code/test.rim
|
||||
attach ptr ../code/sysgen.rim
|
||||
#attach ptr ../lars_sysgen/sysgen.pt
|
||||
attach ptp ../code/ptp.out
|
||||
attach dx0 ../test/out.dt6
|
||||
#attach dx0 ../test/out.dt6
|
||||
attach dx0 ../test/test.dt6
|
||||
|
||||
81
emu/main.c
81
emu/main.c
@ -80,20 +80,6 @@ getms(void)
|
||||
return SDL_GetTicks();
|
||||
}
|
||||
|
||||
int
|
||||
hasinput(int fd)
|
||||
{
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
return select(fd+1, &fds, NULL, NULL, &timeout) > 0;
|
||||
}
|
||||
|
||||
|
||||
SDL_Surface*
|
||||
mustloadimg(const char *path)
|
||||
{
|
||||
@ -143,7 +129,7 @@ Element *extra_l;
|
||||
#include "elements.inc"
|
||||
|
||||
void
|
||||
setlights(word w, Element *l, int n)
|
||||
setelements(word w, Element *l, int n)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < n; i++)
|
||||
@ -151,7 +137,7 @@ setlights(word w, Element *l, int n)
|
||||
}
|
||||
|
||||
word
|
||||
getswitches(Element *sw, int n)
|
||||
getelements(Element *sw, int n)
|
||||
{
|
||||
word w;
|
||||
int i;
|
||||
@ -163,6 +149,20 @@ getswitches(Element *sw, int n)
|
||||
|
||||
#define KEYPULSE(k) (apr->k && !oldapr.k)
|
||||
|
||||
/* Set panel from internal APR state */
|
||||
void
|
||||
updatepanel(Apr *apr)
|
||||
{
|
||||
setelements(apr->data, data_sw, 36);
|
||||
setelements(apr->mas, ma_sw, 18);
|
||||
|
||||
extra_sw[0].state = apr->sw_rim_maint;
|
||||
extra_sw[1].state = apr->sw_rpt_bypass;
|
||||
extra_sw[2].state = apr->sw_art3_maint;
|
||||
extra_sw[3].state = apr->sw_sct_maint;
|
||||
extra_sw[4].state = apr->sw_spltcyc_override;
|
||||
}
|
||||
|
||||
void
|
||||
updateapr(Apr *apr, Ptr *ptr)
|
||||
{
|
||||
@ -171,13 +171,13 @@ updateapr(Apr *apr, Ptr *ptr)
|
||||
if(apr == nil)
|
||||
return;
|
||||
oldapr = *apr;
|
||||
setlights(apr->ir, ir_l, 18);
|
||||
setlights(apr->mi, mi_l, 36);
|
||||
setlights(apr->pc, pc_l, 18);
|
||||
setlights(apr->ma, ma_l, 18);
|
||||
setlights(apr->pih, pih_l, 7);
|
||||
setlights(apr->pir, pir_l, 7);
|
||||
setlights(apr->pio, pio_l, 7);
|
||||
setelements(apr->ir, ir_l, 18);
|
||||
setelements(apr->mi, mi_l, 36);
|
||||
setelements(apr->pc, pc_l, 18);
|
||||
setelements(apr->ma, ma_l, 18);
|
||||
setelements(apr->pih, pih_l, 7);
|
||||
setelements(apr->pir, pir_l, 7);
|
||||
setelements(apr->pio, pio_l, 7);
|
||||
misc_l[0].state = apr->pi_active;
|
||||
misc_l[1].state = apr->mc_stop;
|
||||
misc_l[2].state = apr->run;
|
||||
@ -185,8 +185,8 @@ updateapr(Apr *apr, Ptr *ptr)
|
||||
misc_l[4].state = apr->sw_addr_stop = misc_sw[1].state;
|
||||
misc_l[5].state = apr->sw_power = misc_sw[2].state;
|
||||
misc_l[6].state = apr->sw_mem_disable = misc_sw[3].state;
|
||||
apr->data = getswitches(data_sw, 36);
|
||||
apr->mas = getswitches(ma_sw, 18);
|
||||
apr->data = getelements(data_sw, 36);
|
||||
apr->mas = getelements(ma_sw, 18);
|
||||
|
||||
apr->sw_rim_maint = extra_sw[0].state;
|
||||
if(apr->sw_rim_maint)
|
||||
@ -229,9 +229,9 @@ updateapr(Apr *apr, Ptr *ptr)
|
||||
}
|
||||
}
|
||||
|
||||
setlights(apr->mb, mb_l, 36);
|
||||
setlights(apr->ar, ar_l, 36);
|
||||
setlights(apr->mq, mq_l, 36);
|
||||
setelements(apr->mb, mb_l, 36);
|
||||
setelements(apr->ar, ar_l, 36);
|
||||
setelements(apr->mq, mq_l, 36);
|
||||
|
||||
ff_l[0].state = apr->key_ex_st;
|
||||
ff_l[1].state = apr->key_ex_sync;
|
||||
@ -314,9 +314,9 @@ updateapr(Apr *apr, Ptr *ptr)
|
||||
ff_l[70].state = apr->uuo_f1;
|
||||
ff_l[71].state = apr->cpa_pdl_ov;
|
||||
|
||||
setlights(apr->fe, &ff_l[72], 8);
|
||||
setelements(apr->fe, &ff_l[72], 8);
|
||||
|
||||
setlights(apr->sc, &ff_l[80], 8);
|
||||
setelements(apr->sc, &ff_l[80], 8);
|
||||
|
||||
ff_l[88].state = !apr->ex_user;
|
||||
ff_l[89].state = apr->cpa_illeg_op;
|
||||
@ -345,10 +345,10 @@ updateapr(Apr *apr, Ptr *ptr)
|
||||
ff_l[110].state = !!(apr->cpa_pia&2);
|
||||
ff_l[111].state = !!(apr->cpa_pia&1);
|
||||
|
||||
setlights(apr->pr, pr_l, 8);
|
||||
setlights(apr->rlr, rlr_l, 8);
|
||||
setlights(apr->rla, rla_l, 8);
|
||||
setlights(apr->iobus.c12, iobus_l, 36);
|
||||
setelements(apr->pr, pr_l, 8);
|
||||
setelements(apr->rlr, rlr_l, 8);
|
||||
setelements(apr->rla, rla_l, 8);
|
||||
setelements(apr->iobus.c12, iobus_l, 36);
|
||||
}
|
||||
|
||||
void
|
||||
@ -359,8 +359,8 @@ updatetty(Tty *tty)
|
||||
tty_l[1].state = tty->tti_flag;
|
||||
tty_l[2].state = tty->tto_busy;
|
||||
tty_l[3].state = tty->tto_flag;
|
||||
setlights(tty->pia, &tty_l[4], 3);
|
||||
setlights(tty->tti, ttibuf_l, 8);
|
||||
setelements(tty->pia, &tty_l[4], 3);
|
||||
setelements(tty->tti, ttibuf_l, 8);
|
||||
}
|
||||
}
|
||||
|
||||
@ -371,16 +371,16 @@ updatept(Ptp *ptp, Ptr *ptr)
|
||||
ptp_l[0].state = ptp->b;
|
||||
ptp_l[1].state = ptp->busy;
|
||||
ptp_l[2].state = ptp->flag;
|
||||
setlights(ptp->pia, &ptp_l[3], 3);
|
||||
setlights(ptp->ptp, ptpbuf_l, 8);
|
||||
setelements(ptp->pia, &ptp_l[3], 3);
|
||||
setelements(ptp->ptp, ptpbuf_l, 8);
|
||||
}
|
||||
|
||||
if(ptr){
|
||||
ptr_l[0].state = ptr->b;
|
||||
ptr_l[1].state = ptr->busy;
|
||||
ptr_l[2].state = ptr->flag;
|
||||
setlights(ptr->pia, &ptr_l[3], 3);
|
||||
setlights(ptr->ptr, ptrbuf_l, 36);
|
||||
setelements(ptr->pia, &ptr_l[3], 3);
|
||||
setelements(ptr->ptr, ptrbuf_l, 36);
|
||||
|
||||
extra_l[0].state = ptr->motor_on;
|
||||
}
|
||||
@ -649,7 +649,6 @@ main(int argc, char *argv[])
|
||||
Ptr *ptr;
|
||||
Ptp *ptp;
|
||||
Tty *tty;
|
||||
Mem *mem;
|
||||
|
||||
outfile = "/dev/null";
|
||||
ARGBEGIN{
|
||||
|
||||
@ -101,6 +101,7 @@ wakecore(Mem *mem, Membus *bus)
|
||||
/* read and send read restart */
|
||||
if(core->cma_rd_rq){
|
||||
core->cmb |= core->core[core->cma];
|
||||
core->core[core->cma] = 0;
|
||||
bus->c34 |= core->cmb & FW;
|
||||
bus->c12 |= MEMBUS_MAI_RD_RS;
|
||||
//trace(" sending RD RS\n");
|
||||
|
||||
125
emu/netmem.c
Normal file
125
emu/netmem.c
Normal file
@ -0,0 +1,125 @@
|
||||
#include "pdp6.h"
|
||||
#include <unistd.h>
|
||||
|
||||
char *netmem_ident = NETMEM_IDENT;
|
||||
|
||||
enum
|
||||
{
|
||||
WRRQ = 1,
|
||||
RDRQ = 2,
|
||||
ACK = 3,
|
||||
ERR = 4,
|
||||
};
|
||||
|
||||
static void
|
||||
netmemcycle(void *dev)
|
||||
{
|
||||
Netmem *nm;
|
||||
nm = (Netmem*)dev;
|
||||
u8 buf[9], len;
|
||||
word a, d, *p;
|
||||
|
||||
if(nm->fd < 0)
|
||||
return;
|
||||
|
||||
if(!hasinput(nm->fd))
|
||||
return;
|
||||
|
||||
if(readn(nm->fd, &len, 1)){
|
||||
fprintf(stderr, "netmem fd closed\n");
|
||||
nm->fd = -1;
|
||||
return;
|
||||
}
|
||||
if(len > 9){
|
||||
fprintf(stderr, "netmem botch, closing\n");
|
||||
close(nm->fd);
|
||||
nm->fd = -1;
|
||||
}
|
||||
memset(buf, 0, sizeof(buf));
|
||||
readn(nm->fd, buf, len);
|
||||
|
||||
a = buf[1] | buf[2]<<8 | buf[3]<<16;
|
||||
d = buf[4] | buf[5]<<8 | buf[6]<<16 |
|
||||
(word)buf[7]<<24 | (word)buf[8]<<32;
|
||||
a &= 0777777;
|
||||
d &= 0777777777777;
|
||||
|
||||
switch(buf[0]){
|
||||
case WRRQ:
|
||||
p = getmemref(&nm->apr->membus, a, 0);
|
||||
if(p == nil) goto err;
|
||||
*p = d;
|
||||
printf("write %06lo %012lo\n", a, d);
|
||||
buf[0] = 1;
|
||||
buf[1] = ACK;
|
||||
writen(nm->fd, buf, buf[0]+1);
|
||||
break;
|
||||
case RDRQ:
|
||||
p = getmemref(&nm->apr->membus, a, 0);
|
||||
if(p == nil) goto err;
|
||||
d = *p;
|
||||
printf("read %06lo %012lo\n", a, d);
|
||||
buf[0] = 6;
|
||||
buf[1] = ACK;
|
||||
buf[2] = d;
|
||||
buf[3] = d>>8;
|
||||
buf[4] = d>>16;
|
||||
buf[5] = d>>24;
|
||||
buf[6] = d>>32;
|
||||
writen(nm->fd, buf, buf[0]+1);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown netmem message %d\n", buf[0]);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
err:
|
||||
printf("error address %06lo\n", a);
|
||||
buf[0] = 1;
|
||||
buf[1] = ERR;
|
||||
writen(nm->fd, buf, buf[0]+1);
|
||||
}
|
||||
|
||||
Device*
|
||||
makenetmem(int argc, char *argv[])
|
||||
{
|
||||
const char *host;
|
||||
int port;
|
||||
Netmem *nm;
|
||||
Device *apr;
|
||||
Thread th;
|
||||
|
||||
nm = malloc(sizeof(Netmem));
|
||||
memset(nm, 0, sizeof(Netmem));
|
||||
nm->dev.type = netmem_ident;
|
||||
nm->dev.name = "";
|
||||
nm->dev.attach = nil;
|
||||
nm->dev.ioconnect = nil;
|
||||
nm->dev.next = nil;
|
||||
|
||||
// TODO: don't hardcode;
|
||||
apr = getdevice("apr");
|
||||
assert(apr);
|
||||
assert(apr->type == apr_ident);
|
||||
nm->apr = (Apr*)apr;
|
||||
|
||||
if(argc > 0)
|
||||
host = argv[0];
|
||||
else
|
||||
host = "localhost";
|
||||
if(argc > 1)
|
||||
port = atoi(argv[1]);
|
||||
else
|
||||
port = 10006;
|
||||
|
||||
printf("connecting to %s %d\n", host, port);
|
||||
|
||||
nm->fd = dial(host, port);
|
||||
if(nm->fd < 0)
|
||||
printf("couldn't connect\n");
|
||||
|
||||
th = (Thread){ nil, netmemcycle, nm, 50, 0 };
|
||||
addthread(th);
|
||||
|
||||
return &nm->dev;
|
||||
}
|
||||
20
emu/pdp6.h
20
emu/pdp6.h
@ -25,7 +25,12 @@ void trace(char *fmt, ...);
|
||||
void debug(char *fmt, ...);
|
||||
void err(char *fmt, ...);
|
||||
u32 getms(void);
|
||||
|
||||
void strtolower(char *s);
|
||||
int hasinput(int fd);
|
||||
int writen(int fd, void *data, int n);
|
||||
int readn(int fd, void *data, int n);
|
||||
int dial(const char *host, int port);
|
||||
|
||||
void quit(int code);
|
||||
void cli(FILE *f);
|
||||
@ -100,6 +105,8 @@ struct Device
|
||||
void (*attach)(Device *dev, const char *path);
|
||||
/* connect device to iobus */
|
||||
void (*ioconnect)(Device *dev, IOBus *bus);
|
||||
word (*examine)(Device *dev, const char *reg);
|
||||
int (*deposit)(Device *dev, const char *reg, word data);
|
||||
};
|
||||
|
||||
extern Device *devlist;
|
||||
@ -588,3 +595,16 @@ void dtconn(Dc136 *dc, Dt551 *dt);
|
||||
void dtcono(Dt551 *dt, word iob);
|
||||
void dtcycle(Dt551 *dt);
|
||||
*/
|
||||
|
||||
|
||||
typedef struct Netmem Netmem;
|
||||
struct Netmem
|
||||
{
|
||||
Device dev;
|
||||
int fd;
|
||||
// tmp?
|
||||
Apr *apr;
|
||||
};
|
||||
#define NETMEM_IDENT "netmem"
|
||||
extern char *netmem_ident;
|
||||
Device *makenetmem(int argc, char *argv[]);
|
||||
|
||||
87
emu/util.c
Normal file
87
emu/util.c
Normal file
@ -0,0 +1,87 @@
|
||||
#include "pdp6.h"
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
|
||||
void
|
||||
strtolower(char *s)
|
||||
{
|
||||
for(; *s != '\0'; s++)
|
||||
*s = tolower(*s);
|
||||
}
|
||||
|
||||
int
|
||||
hasinput(int fd)
|
||||
{
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
return select(fd+1, &fds, NULL, NULL, &timeout) > 0;
|
||||
}
|
||||
|
||||
int
|
||||
writen(int fd, void *data, int n)
|
||||
{
|
||||
int m;
|
||||
|
||||
while(n > 0){
|
||||
m = write(fd, data, n);
|
||||
if(m == -1)
|
||||
return -1;
|
||||
data += m;
|
||||
n -= m;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
readn(int fd, void *data, int n)
|
||||
{
|
||||
int m;
|
||||
|
||||
while(n > 0){
|
||||
m = read(fd, data, n);
|
||||
if(m == -1)
|
||||
return -1;
|
||||
data += m;
|
||||
n -= m;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dial(const char *host, int port)
|
||||
{
|
||||
char portstr[32];
|
||||
int sockfd;
|
||||
struct addrinfo *result, *rp, hints;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
snprintf(portstr, 32, "%d", port);
|
||||
if(getaddrinfo(host, portstr, &hints, &result)){
|
||||
perror("error: getaddrinfo");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(rp = result; rp; rp = rp->ai_next){
|
||||
sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
||||
if(sockfd < 0)
|
||||
continue;
|
||||
if(connect(sockfd, rp->ai_addr, rp->ai_addrlen) >= 0)
|
||||
goto win;
|
||||
close(sockfd);
|
||||
}
|
||||
freeaddrinfo(result);
|
||||
perror("error");
|
||||
return -1;
|
||||
|
||||
win:
|
||||
freeaddrinfo(result);
|
||||
return sockfd;
|
||||
}
|
||||
@ -68,6 +68,7 @@ readwrite(int ttyin, int ttyout, int ptyin, int ptyout)
|
||||
if(n = read(ptyin, &c, 1), n <= 0)
|
||||
return;
|
||||
else{
|
||||
//if(c == '\a') c = '.';
|
||||
write(ttyout, &c, 1);
|
||||
SLEEP;
|
||||
}
|
||||
|
||||
@ -3062,6 +3062,7 @@ module apr(
|
||||
// requests coming from the bus
|
||||
wire [1:7] iob_pi_req = iobus_pi_req | cpa_req;
|
||||
|
||||
// TODO: this can be simpler, same as in KA10 code
|
||||
assign pi_ok[1] = pi_active;
|
||||
genvar i;
|
||||
generate
|
||||
@ -3178,6 +3179,7 @@ module apr(
|
||||
cpa_pc_chg_enable & ar_pc_chg_flag |
|
||||
cpa_arov_enable & ar_ov_flag;
|
||||
wire [1:7] cpa_req;
|
||||
// TODO: improve this
|
||||
genvar j;
|
||||
generate
|
||||
for(j = 1; j <= 7; j = j + 1) begin: cpa_req_gen
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user