Permalink
Browse files

first cut of ported code

  • Loading branch information...
0 parents commit 586aedca5fdbe3f207392c5a3d7e50ee5cd5ae9c @stevejwriter stevejwriter committed Jul 10, 2009
Showing with 45,516 additions and 0 deletions.
  1. +113 −0 Makefile
  2. +238 −0 README
  3. BIN cadr_1.bin
  4. BIN cadr_2.bin
  5. BIN cadr_3.bin
  6. BIN cadr_4.bin
  7. BIN cadr_5.bin
  8. BIN cadr_6.bin
  9. +19 −0 cadrmem.c
  10. +806 −0 chaos.c
  11. +12 −0 chaos.h
  12. +51 −0 config.c
  13. +10 −0 config.h
  14. +724 −0 decode.c
  15. +735 −0 disk.c
  16. +848 −0 diskmaker.c
  17. +469 −0 diskmaker_old.c
  18. +158 −0 div.c
  19. +38 −0 endian.h
  20. +4,724 −0 fadd.txt
  21. +549 −0 iob.c
  22. +622 −0 kbd_new.c
  23. +334 −0 kbd_old.c
  24. +46 −0 keyboard.cfg
  25. +341 −0 keyboard.h
  26. +831 −0 lmfs.c
  27. +661 −0 lod.c
  28. +124 −0 logo.h
  29. +507 −0 macro.c
  30. +268 −0 main.c
  31. +312 −0 poo.html
  32. +559 −0 prom.dis.txt
  33. +754 −0 promh.9
  34. +34 −0 promh.sym.9
  35. +241 −0 readmcr.c
  36. +374 −0 sdl.c
  37. +274 −0 syms.c
  38. +27 −0 template.disk1
  39. +20 −0 template.disk2
  40. +8 −0 template.disk3
  41. +26 −0 template.disk4
  42. +26 −0 template.disk5
  43. +20,265 −0 ucadr.lisp.841
  44. BIN ucadr.mcr.841
  45. BIN ucadr.mcr.896
  46. BIN ucadr.mcr.979
  47. +2,508 −0 ucadr.sym.841
  48. +2,638 −0 ucadr.sym.979
  49. +3,065 −0 ucode.c
  50. +77 −0 ucode.h
  51. +23 −0 usim.h
  52. +2 −0 win32/.svn/README.txt
  53. +5 −0 win32/.svn/dir-wcprops
  54. 0 win32/.svn/empty-file
  55. +36 −0 win32/.svn/entries
  56. +1 −0 win32/.svn/format
  57. +226 −0 win32/.svn/text-base/getopt.c.svn-base
  58. +24 −0 win32/.svn/text-base/getopt.h.svn-base
  59. +61 −0 win32/.svn/text-base/win32.c.svn-base
  60. +5 −0 win32/.svn/wcprops/getopt.c.svn-work
  61. +5 −0 win32/.svn/wcprops/getopt.h.svn-work
  62. +5 −0 win32/.svn/wcprops/win32.c.svn-work
  63. +226 −0 win32/getopt.c
  64. +24 −0 win32/getopt.h
  65. +61 −0 win32/win32.c
  66. +376 −0 x11.c
113 Makefile
@@ -0,0 +1,113 @@
+#
+# usim CADR simulator
+# $Id: Makefile 77 2006-07-18 18:13:25Z brad $
+#
+
+#---------- figure out what we are runnign on ---------
+
+OS_NAME = $(shell uname)
+MACH_NAME = $(shell uname -m)
+
+ifeq ($(OS_NAME), Darwin)
+OS = OSX
+endif
+
+ifeq ($(OS_NAME), Linux)
+OS = LINUX
+endif
+
+#--------- options ---------
+
+DISPLAY = SDL
+#DISPLAY = X11
+
+#KEYBOARD = OLD
+KEYBOARD = NEW
+
+#----------- code ------------
+
+USIM_SRC = main.c decode.c ucode.c disk.c iob.c chaos.c syms.c config.c
+USIM_HDR = ucode.h config.h
+
+ifeq ($(DISPLAY), SDL)
+DISPLAY_SRC = sdl.c
+USIM_LIBS = -L/opt/local/lib -lSDL -lpthread
+DEFINES = -DDISPLAY_SDL
+endif
+
+ifeq ($(DISPLAY), X11)
+DISPLAY_SRC = x11.c
+USIM_LIBS = -L/usr/X11R6/lib -lX11
+DEFINES = -DDISPLAY_X11
+endif
+
+ifeq ($(KEYBOARD), OLD)
+KEYBOARD_SRC = kbd_old.c
+endif
+
+ifeq ($(KEYBOARD), NEW)
+KEYBOARD_SRC = kbd_new.c
+endif
+
+# Mac OSX
+ifeq ($(OS), OSX)
+LFLAGS = -framework Cocoa
+USIM_LIBS = -L/opt/local/lib -lSDLmain -lSDL -lpthread -lobjc
+CFLAGS = -O $(DEFINES)
+# good for G5
+#CFLAGS = -fast $(DEFINES)
+endif
+
+ifeq ($(DISPLAY), X11)
+LFLAGS =
+USIM_LIBS = -L/usr/X11R6/lib -lX11
+endif
+
+# Linux
+ifeq ($(OS), LINUX)
+#CFLAGS = -g
+#CFLAGS = -O -pg -g -fprofile-arcs
+#CFLAGS= -O3 -march=pentium3 -mfpmath=sse -mmmx -msse $(DEFINES) -Walle
+#CFLAGS = -O3 -fomit-frame-pointer -mcpu=i686 -g $(DEFINES)
+#CFLAGS= -O3 -mfpmath=sse -mmmx -msse $(DEFINES) -Walle
+CFLAGS = -O3 -mfpmath=sse -mmmx -msse $(DEFINES) -Walle $(M32) -g
+LFLAGS = $(M32) -L/usr/lib
+endif
+
+# override above if 64 bit
+ifeq ($(MACH_NAME), x86_64)
+M32 = -m32
+USIM_LIBS = /usr/lib/libSDL-1.2.so.0.7.0 -lpthread
+endif
+
+#DEFINES=-DLASHUP
+
+USIM_OBJ = $(USIM_SRC:.c=.o) $(DISPLAY_SRC:.c=.o) $(KEYBOARD_SRC:.c=.o)
+
+SRC = $(USIM_SRC) $(DISPLAY_SRC) $(KEYBOARD_SRC)
+
+all: usim readmcr diskmaker lod lmfs
+
+usim: $(USIM_OBJ)
+ $(CC) -o usim $(LFLAGS) $(USIM_OBJ) $(USIM_LIBS)
+
+run:
+ ./usim >xx
+
+readmcr: readmcr.c
+ $(CC) $(CFLAGS) -o $@ $<
+
+diskmaker: diskmaker.c
+ $(CC) $(CFLAGS) -o $@ $<
+
+lmfs: lmfs.c
+ $(CC) $(CFLAGS) -o $@ $<
+
+lod: lod.c macro.c
+ $(CC) $(CFLAGS) -o $@ $<
+
+clean:
+ rm -f *.o usim lod readmcr diskmaker lmfs xx
+ rm -f *~
+
+
238 README
@@ -0,0 +1,238 @@
+CADR simulator
+08/07/06
+Brad Parker
+brad@heeltoe.com
+
+What is this?
+-------------
+
+This is a program designed to emulate the MIT CADR microprocessor
+hardware. A CADR is a second generation MIT lisp machine. A good
+description can be found in "A.I. Memo 528" from the MIT AI Labs
+entitled, "CADR".
+
+The CADR was a 32 bit microcoded microprocessor designed to run the
+lisp language.
+
+This program interprets the microcode found in the machine starting
+with the "prom" microcode which runs when the machine is first powered
+on. The prom microcode loads additional microcode from the simulated
+disk and then boots the load band.
+
+There is sufficient hardware support for the disk and network to
+provide a reasonaly functional lisp machine experience.
+
+Quickstart
+----------
+
+Grab the pre-made disk image with a warm start file (disk-with-state.tgz) and
+run as "./usim -w". Enter the data and time and press "F1" and "F7" to
+clean up the display. You're up!
+
+If you want to use the network download and run chaosd. Read the
+"README" in the disks subdirectory on the http server.
+
+Recent Changes
+--------------
+
+v0.9 - minor speedups.
+ Mac OSX (little endian) fixes.
+ Warm start support (usim.state)
+ Mouse/microcode synchronization (thanks to Devon for the idea)
+
+v0.8 - speedups and bug fixes; chaosd/FILE server supports rebuilding
+ sources from server. can now resize screen.
+
+v0.7 - added raw X11 support. Bjorn's new keyboard configuration code.
+ diskmaker now takes a template file and will show info on existing
+ disk images.
+
+v0.6 - better network support
+
+
+Building
+--------
+
+Unix, Linus, OS X:
+
+There are three defines at the top of the Makefile you should check.
+They are OS, DISPLAY and KEYBOARD. OS should be set automagically.
+
+The X11 display works but the keyboard mapping is not correct yet. Both
+the OLD and NEW keyboard code works, I would recomment using NEW.
+
+Once the Makefile is changed just type "make".
+
+Win32:
+
+I used a VC 6.0 project to make under win32.
+
+
+Making a disk
+-------------
+
+I would recommend using the distributed disk.img unless you understand
+the structure of a CADR disk. The program "diskmaker" will interpret
+a disk image partition table and make a new disk using a template file.
+
+The distributed disk was made using "template.disk1". The template file
+basically feeds all the parameters to diskmaker to build a valid disk
+image an populate it with microcode and a load band.
+
+
+Running
+-------
+
+Everything basically works. The simulator will boot a load band and talk
+on the (simulated) network.
+
+The emulation is reasonably complete (modulo bugs). It gets through the
+prom code, loads the microcode band, copies the band to swap and
+executes the load band cleanly. The system boots and runs.
+
+The code was originally written to run on x86 linux using SDL and X
+Windows. It's since been ported to run on OS X and Win32, both with
+SDL libraries. A native X11 interface has also been added. It should
+compile and run on X86 linux, Win32 and and OS X.
+
+The console display is drawn into an X window (using SDL) which tracks
+the mouse and keyboard. The simplest way to run it is
+
+ ./usim
+
+You can turn off the mouse synchronization with the "-m" option.
+
+If you want to see a trace of macrocode function names try:
+
+ ./usim -n -Tl >output
+
+If you want to see a voluminous trace of every microcode instruction
+try:
+
+ ./usim -n -t >output
+
+You can make a warm start state file with
+
+ ./usim -S
+
+Run the emulator, enter the date and time. The ^C twice. The memory state
+will be saved in "usim.state". You can then warm start to come up
+quickly
+
+ ./usim -w
+
+Note that the warm start state file is intimately connected to the
+disk image. If the two are mismatched bad things will happen. The two
+files should be portable across X86, Win32 and Macintosh.
+
+The disk emulation reads from a 'disk image' file which is constructed
+with 'diskmaker'. The disk image looks like a Trident T-300 disk
+to the microcode, complete with a parition table.
+
+The display board and iob are emulated. An X window displays in
+monochrome at 768x1024. The mouse and keyboard are tracked. The
+keyboard is "mapped" to the old Knight keyboard or new style depending
+on compilation options.
+
+The internal microsecond clock and the 60hz tv interrupt currently try
+and use wall clock time for a more realistic simulation.
+
+There is also emulation of the chaosnet board. Packets are sent via a
+unix socket to a "chaosd" daemon which distributes them to various
+client programs (see the chaos directory).
+
+There are some hacks for noticing unibus access but no xbus/unibus
+mapping support. The two machine lash-up/debug interface is not (yet)
+supported. I want to add this, however.
+
+There's still a long delay when booting the distributed world. The
+system is available right away, however, try "F2-p". If you are
+impatient try the warm start state file, but be sure to use it with
+it's matching disk.img.
+
+
+What needs to be done?
+----------------------
+
+- cleanup mouse emulation
+- speed up the network emulation
+- speed up the microcode simulation
+
+The keyboard mapping has been cleaned up by Bjorn Victor (thanks!). The
+latest (v0.7+) code uses the "keyboard.cfg" file to map the PC keyboard
+onto the lispm keyboard.
+
+Some default keys:
+
+f1 terminal
+f2 system
+f3 network
+f4 abort
+f5 clear_input
+esc Alt Mode
+f1 Terminal
+f2 System
+f3 Network
+f4 Abort
+f5 Clear Input
+f6 Help
+f7 Page
+f8
+f9
+f10
+f11
+f12
+pgup Break
+pgdn {appears to crash usim}
+home Call
+end End
+backspace rubout
+backspace Rub Out
+
+Terminal-M Toggle **MORE** processing.
+Terminal-0-M Disable **MORE** processing.
+
+ http://world.std.com/~jdostale/kbd/Knight1.jpeg
+ http://world.std.com/~jdostale/kbd/SpaceCadet1.jpeg
+ http://world.std.com/~jdostale/kbd/SpaceCadet2.jpeg
+
+The mouse emulation works but doesn't track exactly.
+
+What programs are here?
+-----------------------
+
+usim - the CADR emulator
+diskmaker - program to make CADR disk images from .mcr files and
+ .lod files
+lod - utiltity to pick apart load bands and show their insides
+lmfs - raw hack to read files from LMFS paritition
+
+Standing on the Shoulders of Giants
+-----------------------------------
+
+I would like to thanks the following people for helping me on this, er,
+project:
+
+Tom Knight
+Howard Shrobe
+Richard Greenblatt
+Danial Weinreb
+Al Kossow
+George Carrette
+Steve Krueger
+Alastair Bridgewater
+John Wroclawski
+Bjorn Victor
+Devon Sean McCullough
+
+Without their support or encouragement I would probably not have done
+this. Certainly if Al had not sent me the prom images I would never
+have started. And without Dan's box-of-tapes I could never have
+succeeded. RG offered some good explainations when I was confused.
+TK and Howie were extremely supportive at the just right moment (and
+answered a lot of email). George offered many good suggestions and
+answered lots of questions. Steve helped me locate missing pages from
+"memo 528". Alastair did some amazing work on several explorer
+emulators. Bjorn has used the code, offered many suggestions, fixes
+and improvements. And John's office is where I first saw a 3600
+console and said, "what's that?".
BIN cadr_1.bin
Binary file not shown.
BIN cadr_2.bin
Binary file not shown.
BIN cadr_3.bin
Binary file not shown.
BIN cadr_4.bin
Binary file not shown.
BIN cadr_5.bin
Binary file not shown.
BIN cadr_6.bin
Binary file not shown.
19 cadrmem.c
@@ -0,0 +1,19 @@
+main()
+{
+ int xbusl, xbush, unibusl, unibush, xbusiol, xbusioh;
+
+ printf("CADR memory map:\n");
+ xbusl = 0;
+ xbush = 016777777;
+ unibusl = 017400000;
+ unibush = 017777777;
+ xbusiol = 017000000;
+ xbusioh = 017377777;
+ printf("22-bit %011o\n", (1 << 22)-1);
+ printf("xbus memory %011o-%011o, pn %05o-%05o\n",
+ xbusl, xbush, xbusl >> 8, xbush>> 8);
+ printf("xbus io %011o-%011o, pn %05o-%05o\n",
+ xbusiol, xbusioh, xbusiol >> 8, xbusioh >> 8);
+ printf("unibus io %011o-%011o, pn %05o-%05o\n",
+ unibusl, unibush, unibusl >> 8, unibush >> 8);
+}
806 chaos.c
@@ -0,0 +1,806 @@
+/*
+ * chaosnet adapter emulation
+ * $Id: chaos.c 83 2006-08-07 16:08:20Z brad $
+ */
+
+/* TODO:
+ - desynchronize network process from CPU
+ */
+
+#include "usim.h"
+
+ /* until I split out the unix socket code */
+#if defined(LINUX) || defined(OSX)
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <sys/poll.h>
+#include <sys/uio.h>
+
+#include "ucode.h"
+#include "endian.h"
+
+#ifndef CHAOS_MY_ADDRESS
+# define CHAOS_MY_ADDRESS 0401
+#endif
+
+#ifndef CHAOS_DEBUG
+# define CHAOS_DEBUG 0
+#endif
+
+#define CHAOS_DEBUG_PKT 0
+//#define CHAOS_TOSS_IF_RXBUFF_FULL
+
+#define CHAOS_BUF_SIZE_BYTES 4096
+
+int chaos_csr;
+int chaos_addr = CHAOS_MY_ADDRESS;
+int chaos_bit_count;
+int chaos_lost_count = 0;
+unsigned short chaos_xmit_buffer[CHAOS_BUF_SIZE_BYTES/2];
+int chaos_xmit_buffer_size;
+int chaos_xmit_buffer_ptr;
+
+unsigned short chaos_rcv_buffer[CHAOS_BUF_SIZE_BYTES/2];
+unsigned short chaos_rcv_buffer_toss[CHAOS_BUF_SIZE_BYTES/2];
+int chaos_rcv_buffer_ptr;
+int chaos_rcv_buffer_size;
+int chaos_rcv_buffer_empty;
+
+int chaos_fd;
+int chaos_need_reconnect;
+static int reconnect_delay;
+static int reconnect_time;
+void chaos_force_reconect(void);
+int chaos_send_to_chaosd(char *buffer, int size);
+int chaos_reconnect(void);
+
+
+extern void assert_unibus_interrupt(int v);
+
+
+/*
+chaos csr
+ TIMER-INTERRUPT-ENABLE 1<<0
+ LOOP-BACK 1<<1
+ RECEIVE-ALL 1<<2
+ RECEIVER-CLEAR 1<<3
+ RECEIVE-ENABLE 1<<4
+ TRANSMIT-ENABLE 1<<5
+ INTERRUPT-ENABLES 3<<4
+ TRANSMIT-ABORT 1<<6
+ TRANSMIT-DONE 1<<7
+ TRANSMITTER-CLEAR 1<<8
+ LOST-COUNT 017<<9
+ RESET 1<<13
+ CRC-ERROR 1<<14
+ RECEIVE-DONE 1<<15
+
+;;; Offsets of other registers from CSR
+;;; These are in words, not bytes
+
+ MY-NUMBER-OFFSET 1
+ WRITE-BUFFER-OFFSET 1
+ READ-BUFFER-OFFSET 2
+ BIT-COUNT-OFFSET 3
+ START-TRANSMIT-OFFSET 5
+*/
+#define CHAOS_CSR_TIMER_INTERRUPT_ENABLE (1<<0)
+#define CHAOS_CSR_LOOP_BACK (1<<1)
+#define CHAOS_CSR_RECEIVE_ALL (1<<2)
+#define CHAOS_CSR_RECEIVER_CLEAR (1<<3)
+#define CHAOS_CSR_RECEIVE_ENABLE (1<<4)
+#define CHAOS_CSR_TRANSMIT_ENABLE (1<<5)
+#define CHAOS_CSR_INTERRUPT_ENABLES (3<<4)
+#define CHAOS_CSR_TRANSMIT_ABORT (1<<6)
+#define CHAOS_CSR_TRANSMIT_DONE (1<<7)
+#define CHAOS_CSR_TRANSMITTER_CLEAR (1<<8)
+#define CHAOS_CSR_LOST_COUNT (017<<9)
+#define CHAOS_CSR_RESET (1<<13)
+#define CHAOS_CSR_CRC_ERROR (1<<14)
+#define CHAOS_CSR_RECEIVE_DONE (1<<15)
+
+static unsigned int
+ch_checksum(const unsigned char *addr, int count)
+{
+ /*
+ * RFC1071
+ * Compute Internet Checksum for "count" bytes
+ * beginning at location "addr".
+ */
+ register long sum = 0;
+
+ while( count > 1 ) {
+ /* This is the inner loop */
+ sum += *(addr)<<8 | *(addr+1);
+ addr += 2;
+ count -= 2;
+ }
+
+ /* Add left-over byte, if any */
+ if( count > 0 )
+ sum += * (unsigned char *) addr;
+
+ /* Fold 32-bit sum to 16 bits */
+ while (sum>>16)
+ sum = (sum & 0xffff) + (sum >> 16);
+
+ return (~sum) & 0xffff;
+}
+
+void
+chaos_rx_pkt(void)
+{
+ chaos_rcv_buffer_ptr = 0;
+ chaos_bit_count = (chaos_rcv_buffer_size * 2 * 8) - 1;
+ if (chaos_rcv_buffer_size > 0) {
+#if CHAOS_DEBUG
+ printf("chaos: set RDN, generate interrupt\n");
+#endif
+ chaos_csr |= CHAOS_CSR_RECEIVE_DONE;
+ if (chaos_csr & CHAOS_CSR_RECEIVE_ENABLE)
+ assert_unibus_interrupt(0404);
+ }
+}
+
+void
+char_xmit_done_intr(void)
+{
+ chaos_csr |= CHAOS_CSR_TRANSMIT_DONE;
+ if (chaos_csr & CHAOS_CSR_TRANSMIT_ENABLE)
+ assert_unibus_interrupt(0400);
+}
+
+void
+chaos_xmit_pkt(void)
+{
+#if CHAOS_DEBUG_PKT
+ int i, n;
+#endif
+
+#if CHAOS_DEBUG
+ printf("chaos_xmit_pkt() %d bytes, data len %d\n",
+ chaos_xmit_buffer_ptr * 2,
+ (chaos_xmit_buffer_ptr > 0 ? chaos_xmit_buffer[1]&0x3f : -1));
+#endif
+
+#if CHAOS_DEBUG_PKT
+ n = 0;
+ for (i = 0; i < chaos_xmit_buffer_ptr; i++) {
+ printf("%02x %02x ",
+ chaos_xmit_buffer[i] & 0xff,
+ (chaos_xmit_buffer[i] >> 8) & 0xff);
+ n += 2;
+ if (n > 16) {
+ n = 0;
+ printf("\n");
+ }
+ }
+ if (n)
+ printf("\n");
+#endif
+
+ chaos_xmit_buffer_size = chaos_xmit_buffer_ptr;
+
+ /* Dest is already in the buffer */
+// chaos_xmit_buffer[chaos_xmit_buffer_size++] = 0;/* dest */
+
+ chaos_xmit_buffer[chaos_xmit_buffer_size++] = /* source */
+ chaos_addr;
+
+ chaos_xmit_buffer[chaos_xmit_buffer_size] = /* checksum */
+ ch_checksum((u_char *)chaos_xmit_buffer,
+ chaos_xmit_buffer_size*2);
+ chaos_xmit_buffer_size++;
+
+ chaos_send_to_chaosd((char *)chaos_xmit_buffer,
+ chaos_xmit_buffer_size*2);
+
+ chaos_xmit_buffer_ptr = 0;
+ char_xmit_done_intr();
+
+#if 0
+ /* set back to ourselves - only for testing */
+ chaos_rcv_buffer_size = chaos_xmit_buffer_size + 2;
+ memcpy(chaos_rcv_buffer, chaos_xmit_buffer, chaos_xmit_buffer_size*2);
+
+ chaos_rcv_buffer[chaos_xmit_buffer_size+0] = 0; /* source */
+ chaos_rcv_buffer[chaos_xmit_buffer_size+1] = 0; /* checksum */
+
+ chaos_rx_pkt();
+#endif
+}
+
+int
+chaos_get_bit_count(void)
+{
+ if (chaos_rcv_buffer_size > 0)
+ return chaos_bit_count;
+ else
+ return 07777;
+}
+
+int
+chaos_get_rcv_buffer(void)
+{
+ int v = 0;
+ if (chaos_rcv_buffer_ptr < chaos_rcv_buffer_size) {
+ v = chaos_rcv_buffer[chaos_rcv_buffer_ptr++];
+
+ if (chaos_rcv_buffer_ptr == chaos_rcv_buffer_size)
+ chaos_rcv_buffer_empty = 1;
+
+ } else {
+ /* read last word, clear receive done */
+ chaos_csr &= ~CHAOS_CSR_RECEIVE_DONE;
+ chaos_rcv_buffer_size = 0;
+ }
+ return v;
+}
+
+void
+chaos_put_xmit_buffer(int v)
+{
+ if (chaos_xmit_buffer_ptr < sizeof(chaos_xmit_buffer)/2)
+ chaos_xmit_buffer[chaos_xmit_buffer_ptr++] = v;
+ chaos_csr &= ~CHAOS_CSR_TRANSMIT_DONE;
+}
+
+int
+chaos_get_csr(void)
+{
+ {
+ static int old_chaos_csr = 0;
+ if (chaos_csr != old_chaos_csr) {
+ old_chaos_csr = chaos_csr;
+#if CHAOS_DEBUG
+ printf("unibus: chaos read csr %o\n",
+ chaos_csr);
+#endif
+ }
+ }
+
+ return chaos_csr | ((chaos_lost_count << 9) & 017);
+}
+
+int
+chaos_get_addr(void)
+{
+ return chaos_addr;
+}
+
+void
+print_csr_bits(int csr)
+{
+ if (csr & CHAOS_CSR_LOOP_BACK)
+ printf(" LUP");
+ if (csr & CHAOS_CSR_RECEIVE_ALL)
+ printf(" SPY");
+ if (csr & CHAOS_CSR_RECEIVER_CLEAR)
+ printf(" RCL");
+ if (csr & CHAOS_CSR_RECEIVE_ENABLE)
+ printf(" REN");
+ if (csr & CHAOS_CSR_TRANSMIT_ENABLE)
+ printf(" TEN");
+ if (csr & CHAOS_CSR_TRANSMIT_ABORT)
+ printf(" TAB");
+ if (csr & CHAOS_CSR_TRANSMIT_DONE)
+ printf(" TDN");
+ if (csr & CHAOS_CSR_TRANSMITTER_CLEAR)
+ printf(" TCL");
+ if (csr & CHAOS_CSR_RESET)
+ printf(" RST");
+ if (csr & CHAOS_CSR_RECEIVE_DONE)
+ printf(" RDN");
+ if (csr & CHAOS_CSR_CRC_ERROR)
+ printf(" ERR");
+ if (csr & CHAOS_CSR_LOST_COUNT)
+ printf(" Lost %d.",(csr & CHAOS_CSR_LOST_COUNT)>>9);
+
+ csr &= ~(CHAOS_CSR_LOST_COUNT|CHAOS_CSR_RESET|
+ CHAOS_CSR_TRANSMITTER_CLEAR|CHAOS_CSR_TRANSMIT_ABORT|
+ CHAOS_CSR_RECEIVE_DONE|CHAOS_CSR_RECEIVE_ENABLE|
+ CHAOS_CSR_TRANSMIT_DONE|CHAOS_CSR_TRANSMIT_ENABLE|
+ CHAOS_CSR_CRC_ERROR|CHAOS_CSR_LOOP_BACK|
+ CHAOS_CSR_RECEIVE_ALL|CHAOS_CSR_RECEIVER_CLEAR);
+
+ if (csr)
+ printf(" unk bits 0%o",csr);
+}
+
+int
+chaos_set_csr(int v)
+{
+ int mask;
+
+ v &= 0xffff;
+
+ /* Writing these don't stick */
+ mask = CHAOS_CSR_TRANSMIT_DONE |
+ CHAOS_CSR_LOST_COUNT |
+ CHAOS_CSR_CRC_ERROR |
+ CHAOS_CSR_RECEIVE_DONE |
+ CHAOS_CSR_RECEIVER_CLEAR;
+
+#if CHAOS_DEBUG
+ printf("chaos: set csr bits 0%o (",v);
+ print_csr_bits(v);
+ printf ("), old 0%o ", chaos_csr);
+#endif
+
+ chaos_csr = (chaos_csr & mask) | (v & ~mask);
+
+ if (chaos_csr & CHAOS_CSR_RESET) {
+#if CHAOS_DEBUG
+ printf("reset ");
+#endif
+ chaos_rcv_buffer_size = 0;
+ chaos_xmit_buffer_ptr = 0;
+ chaos_lost_count = 0;
+ chaos_bit_count = 0;
+ chaos_rcv_buffer_ptr = 0;
+ chaos_csr &= ~(CHAOS_CSR_RESET | CHAOS_CSR_RECEIVE_DONE);
+ chaos_csr |= CHAOS_CSR_TRANSMIT_DONE;
+
+ reconnect_delay = 200; /* Do it right away */
+ chaos_force_reconect();
+ }
+
+ if (v & CHAOS_CSR_RECEIVER_CLEAR) {
+ chaos_csr &= ~CHAOS_CSR_RECEIVE_DONE;
+ chaos_lost_count = 0;
+ chaos_bit_count = 0;
+ chaos_rcv_buffer_ptr = 0;
+ chaos_rcv_buffer_size = 0;
+ }
+
+ if (v & (CHAOS_CSR_TRANSMITTER_CLEAR | CHAOS_CSR_TRANSMIT_DONE)) {
+ chaos_csr &= ~CHAOS_CSR_TRANSMIT_ABORT;
+ chaos_csr |= CHAOS_CSR_TRANSMIT_DONE;
+ chaos_xmit_buffer_ptr = 0;
+ }
+
+ if (chaos_csr & CHAOS_CSR_RECEIVE_ENABLE) {
+#if CHAOS_DEBUG
+ printf("rx-enable ");
+#endif
+ if (chaos_rcv_buffer_empty) {
+ chaos_rcv_buffer_ptr = 0;
+ chaos_rcv_buffer_size = 0;
+#if 0
+ chaos_poll();
+#endif
+ }
+
+ /* if buffer is full, generate status & interrupt again */
+ if (chaos_rcv_buffer_size > 0)
+ chaos_rx_pkt();
+ }
+
+ if (chaos_csr & CHAOS_CSR_TRANSMIT_ENABLE) {
+#if CHAOS_DEBUG
+ printf("tx-enable ");
+#endif
+ chaos_csr |= CHAOS_CSR_TRANSMIT_DONE;
+#if 0
+ char_xmit_done_intr();
+ } else {
+ chaos_csr &= ~CHAOS_CSR_TRANSMIT_DONE;
+#endif
+ }
+
+#if CHAOS_DEBUG
+ printf(" New csr 0%o", chaos_csr);
+ print_csr_bits(chaos_csr);
+ printf("\n");
+#endif
+ return 0;
+}
+
+#define UNIX_SOCKET_PATH "/var/tmp/"
+#define UNIX_SOCKET_CLIENT_NAME "chaosd_"
+#define UNIX_SOCKET_SERVER_NAME "chaosd_server"
+#define UNIX_SOCKET_PERM S_IRWXU
+
+static struct sockaddr_un unix_addr;
+
+void
+chaos_force_reconect(void)
+{
+#if CHAOS_DEBUG || 1
+ printf("chaos: forcing reconnect to chaosd\n");
+#endif
+ close(chaos_fd);
+ chaos_fd = 0;
+ chaos_need_reconnect = 1;
+}
+
+int
+chaos_poll(void)
+{
+ int ret;
+ struct pollfd pfd[1];
+ int nfds, timeout;
+
+ if (chaos_need_reconnect) {
+ chaos_reconnect();
+ }
+
+ if (chaos_fd == 0) {
+ return 0;
+ }
+
+ timeout = 0;
+ nfds = 1;
+ pfd[0].fd = chaos_fd;
+ pfd[0].events = POLLIN;
+ pfd[0].revents = 0;
+
+ ret = poll(pfd, nfds, timeout);
+ if (ret < 0) {
+#if CHAOS_DEBUG
+ printf("chaos: Polling, nothing there (RDN=%o)\n",
+ chaos_csr & CHAOS_CSR_RECEIVE_DONE);
+#endif
+ chaos_need_reconnect = 1;
+ return -1;
+ }
+
+ if (ret > 0) {
+ u_char lenbytes[4];
+ int len;
+
+ /* is rx buffer full? */
+ if (!chaos_rcv_buffer_empty &&
+ (chaos_csr & CHAOS_CSR_RECEIVE_DONE))
+ {
+#ifndef CHAOS_TOSS_IF_RXBUFF_FULL
+ printf("chaos: polling, but unread data exists\n");
+ return 0;
+#else
+ /*
+ * Toss packets arriving when buffer is already in use
+ * they will be resent
+ */
+#if CHAOS_DEBUG
+ printf("chaos: polling, unread data, drop "
+ "(RDN=%o, lost %d)\n",
+ chaos_csr & CHAOS_CSR_RECEIVE_DONE,
+ chaos_lost_count);
+#endif
+ chaos_lost_count++;
+ read(chaos_fd, lenbytes, 4);
+ len = (lenbytes[0] << 8) | lenbytes[1];
+#if CHAOS_DEBUG
+ printf("chaos: tossing packet of %d bytes\n", len);
+#endif
+ if (len > sizeof(chaos_rcv_buffer_toss)) {
+ printf("chaos packet won't fit");
+ chaos_force_reconect();
+ return -1;
+ }
+
+ /* toss it */
+ read(chaos_fd, (char *)chaos_rcv_buffer_toss, len);
+ return -1;
+#endif
+ }
+
+ /* read header from chaosd */
+ ret = read(chaos_fd, lenbytes, 4);
+ if (ret <= 0) {
+ perror("chaos: header read error");
+ chaos_force_reconect();
+ return -1;
+ }
+
+ len = (lenbytes[0] << 8) | lenbytes[1];
+
+ if (len > sizeof(chaos_rcv_buffer)) {
+ printf("chaos: packet too big: "
+ "pkt size %d, buffer size %d\n",
+ len, sizeof(chaos_rcv_buffer));
+
+ /* When we get out of synch break socket conn */
+ chaos_force_reconect();
+ return -1;
+ }
+
+ ret = read(chaos_fd, (char *)chaos_rcv_buffer, len);
+ if (ret < 0) {
+ perror("chaos: read");
+ chaos_force_reconect();
+ return -1;
+ }
+
+#if CHAOS_DEBUG
+ printf("chaos: polling; got chaosd packet %d\n", ret);
+#endif
+
+ if (ret > 0) {
+ int dest_addr;
+
+ chaos_rcv_buffer_size = (ret+1)/2;
+ chaos_rcv_buffer_empty = 0;
+
+#if __BIG_ENDIAN__
+ /* flip shorts to host order */
+ int w;
+ for (w = 0; w < chaos_rcv_buffer_size; w++) {
+ chaos_rcv_buffer[w] = SWAP_SHORT(chaos_rcv_buffer[w]);
+ }
+#endif
+
+ dest_addr = chaos_rcv_buffer[chaos_rcv_buffer_size-3];
+
+#if CHAOS_DEBUG
+ printf("chaos rx: to %o, my %o\n", dest_addr, chaos_addr);
+#endif
+
+#if CHAOS_DEBUG_PKT
+ {
+ int i, c = 0, o = 0;
+ unsigned char cc, cb[9];
+ cb[8] = 0;
+ for (i = 0; i < ret; i++) {
+ if (c == 8) { printf("%s\n", cb); c = 0; }
+ if (c++ == 0) printf("%04d ", o);
+ cc = ((unsigned char *)chaos_rcv_buffer)[i];
+ printf("%02x ", cc);
+ cb[c-1] = (cc >= ' ' && cc <= '~') ?
+ cc : '.';
+ if (i == ret-1 && c > 0) {
+ for (; c < 8; c++) {
+ printf("xx "); cb[c]=' ';
+ }
+ printf("%s\n", cb);
+ break;
+ }
+ }
+ }
+#endif
+
+ /* if not to us, ignore */
+ if (dest_addr != chaos_addr) {
+ chaos_rcv_buffer_size = 0;
+ chaos_rcv_buffer_empty = 1;
+ return 0;
+ }
+
+ chaos_rx_pkt();
+ }
+ }
+
+ return 0;
+}
+
+int
+chaos_send_to_chaosd(char *buffer, int size)
+{
+ int ret, wcount, dest_addr;
+
+ /* local loopback */
+ if (chaos_csr & CHAOS_CSR_LOOP_BACK) {
+
+ printf("chaos: loopback %d bytes\n", size);
+ memcpy(chaos_rcv_buffer, buffer, size);
+
+ chaos_rcv_buffer_size = (size+1)/2;
+ chaos_rcv_buffer_empty = 0;
+
+ chaos_rx_pkt();
+
+ return 0;
+ }
+
+ wcount = (size+1)/2;
+ dest_addr = ((u_short *)buffer)[wcount-3];
+
+ //printf("chaos_send_to_chaosd() dest_addr %o\n", dest_addr);
+
+#if __BIG_ENDIAN__
+ /* flip host order to network order */
+ int w;
+ for (w = 0; w < wcount; w++) {
+ u_short *ps = &((u_short *)buffer)[w];
+ *ps = SWAP_SHORT(*ps);
+ }
+#endif
+
+#if CHAOS_DEBUG
+ printf("chaos tx: dest_addr = %o, chaos_addr=%o, size %d, wcount %d\n",
+ dest_addr, chaos_addr, size, wcount);
+#endif
+
+ /* recieve packets address to ourselves */
+ if (dest_addr == chaos_addr) {
+ memcpy(chaos_rcv_buffer, buffer, size);
+
+ chaos_rcv_buffer_size = (size+1)/2;
+ chaos_rcv_buffer_empty = 0;
+
+ chaos_rx_pkt();
+ }
+
+ /* chaosd server */
+ if (chaos_fd) {
+ struct iovec iov[2];
+ unsigned char lenbytes[4];
+
+ lenbytes[0] = size >> 8;
+ lenbytes[1] = size;
+ lenbytes[2] = 1;
+ lenbytes[3] = 0;
+
+ iov[0].iov_base = lenbytes;
+ iov[0].iov_len = 4;
+
+ iov[1].iov_base = buffer;
+ iov[1].iov_len = size;
+
+ ret = writev(chaos_fd, iov, 2);
+ if (ret < 0) {
+ perror("chaos write");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+/*
+ * connect to server using specificed socket type
+ */
+static int
+chaos_connect_to_server(void)
+{
+ int len;
+
+ if (0) printf("connect_to_server()\n");
+
+ if ((chaos_fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
+ perror("socket(AF_UNIX)");
+ chaos_fd = 0;
+ return -1;
+ }
+
+ memset(&unix_addr, 0, sizeof(unix_addr));
+
+ sprintf(unix_addr.sun_path, "%s%s%05u",
+ UNIX_SOCKET_PATH, UNIX_SOCKET_CLIENT_NAME, getpid());
+
+ unix_addr.sun_family = AF_UNIX;
+ len = SUN_LEN(&unix_addr);
+
+ unlink(unix_addr.sun_path);
+
+ if ((bind(chaos_fd, (struct sockaddr *)&unix_addr, len) < 0)) {
+ perror("bind(AF_UNIX)");
+ return -1;
+ }
+
+ if (chmod(unix_addr.sun_path, UNIX_SOCKET_PERM) < 0) {
+ perror("chmod(AF_UNIX)");
+ return -1;
+ }
+
+ memset(&unix_addr, 0, sizeof(unix_addr));
+ sprintf(unix_addr.sun_path, "%s%s",
+ UNIX_SOCKET_PATH, UNIX_SOCKET_SERVER_NAME);
+ unix_addr.sun_family = AF_UNIX;
+ len = SUN_LEN(&unix_addr);
+
+ if (connect(chaos_fd, (struct sockaddr *)&unix_addr, len) < 0) {
+ printf("chaos: no chaosd server\n");
+ return -1;
+ }
+
+ if (0) printf("chaos_fd %d\n", chaos_fd);
+
+ return 0;
+}
+
+int
+chaos_init(void)
+{
+ if (chaos_connect_to_server()) {
+ close(chaos_fd);
+ chaos_fd = 0;
+ return -1;
+ }
+
+ chaos_rcv_buffer_empty = 1;
+
+ return 0;
+}
+
+int
+chaos_reconnect(void)
+{
+ /* */
+ if (++reconnect_delay < 200) {
+ return 0;
+ }
+ reconnect_delay = 0;
+
+ /* try every 5 seconds */
+ if (reconnect_time &&
+ time(NULL) < (reconnect_time + 5))
+ {
+ return 0;
+ }
+ reconnect_time = time(NULL);
+
+# if CHAOS_DEBUG || 1
+ printf("chaos: reconnecting to chaosd\n");
+#endif
+ if (chaos_init() == 0) {
+ printf("chaos: reconnected\n");
+ chaos_need_reconnect = 0;
+ reconnect_delay = 0;
+ }
+
+ return 0;
+}
+
+#endif /* linux || osx */
+
+/* these are stubs; eventually I'll fix the code work with win32 sockets */
+#ifdef WIN32
+int
+chaos_init(void)
+{
+ return 0;
+}
+
+void
+chaos_xmit_pkt(void)
+{
+}
+
+int
+chaos_get_bit_count(void)
+{
+ return 0;
+}
+
+int
+chaos_get_rcv_buffer(void)
+{
+ return 0;
+}
+
+int
+chaos_get_csr(void)
+{
+ return 0;
+}
+
+int
+chaos_put_xmit_buffer(int v)
+{
+ return 0;
+}
+
+int
+chaos_get_addr(void)
+{
+ return 0;
+}
+
+int
+chaos_set_csr(int v)
+{
+ return 0;
+}
+#endif
12 chaos.h
@@ -0,0 +1,12 @@
+/*
+ * chaos.h
+ */
+
+int chaos_get_csr(void);
+int chaos_get_addr(void);
+int chaos_get_rcv_buffer(void);
+int chaos_get_bit_count(void);
+
+int chaos_set_csr(int v);
+int chaos_put_xmit_buffer(int v);
+
51 config.c
@@ -0,0 +1,51 @@
+/*
+ * config.c
+ * $Id: config.c 61 2006-04-01 01:25:14Z brad $
+ */
+
+#include "usim.h"
+
+#include <string.h>
+
+#include "config.h"
+
+static char *mcrsym_filename;
+static char *disk_filename;
+
+const char *
+config_get_promsym_filename(void)
+{
+ return "promh.sym.9";
+}
+
+const char *
+config_get_mcrsym_filename(void)
+{
+ if (mcrsym_filename)
+ return mcrsym_filename;
+
+ return "ucadr.sym.841";
+}
+
+void
+config_set_mcrsym_filename(const char *fn)
+{
+ mcrsym_filename = strdup(fn);
+}
+
+
+const char *
+config_get_disk_filename(void)
+{
+ if (disk_filename)
+ return disk_filename;
+
+ return "disk.img";
+}
+
+void
+config_set_disk_filename(const char *filename)
+{
+ disk_filename = strdup(filename);
+}
+
10 config.h
@@ -0,0 +1,10 @@
+/*
+ * config.h
+ * $Id: config.h 61 2006-04-01 01:25:14Z brad $
+ */
+
+const char *config_get_promsym_filename(void);
+const char *config_get_mcrsym_filename(void);
+void config_set_mcrsym_filename(const char *filename);
+const char *config_get_disk_filename(void);
+void config_set_disk_filename(const char *filename);
724 decode.c
@@ -0,0 +1,724 @@
+/*
+ * decode.c
+ *
+ * disassemble CADR microcode
+ * or at least, try to :-)
+ *
+ * $Id: decode.c 61 2006-04-01 01:25:14Z brad $
+ */
+
+#include "usim.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/types.h>
+
+#if defined(LINUX) || defined(OSX)
+#include <unistd.h>
+#endif
+
+#include "ucode.h"
+
+u_char prom[6][512];
+ucw_t prom_ucode[512];
+
+int
+read_prom_files(void)
+{
+ int fd, i, ret;
+
+ for (i = 0; i < 6; i++) {
+ char name[256];
+
+ sprintf(name, "cadr_%1d.bin", i+1);
+
+ if (alt_prom_flag) {
+ sprintf(name, "../prom/alt_cadr_%1d.bin", i+1);
+ }
+
+ printf("%s\n", name);
+ fd = open(name, O_RDONLY | O_BINARY);
+ if (fd < 0) {
+ perror(name);
+ exit(1);
+ }
+
+ ret = read(fd, prom[i], 512);
+ close(fd);
+
+ if (ret != 512) {
+ fprintf(stderr, "read_prom_files: short read\n");
+ exit(1);
+ }
+ }
+
+ for (i = 0; i < 512; i++) {
+ prom_ucode[511-i] =
+ ((uint64)prom[0][i] << (8*5)) |
+ ((uint64)prom[1][i] << (8*4)) |
+ ((uint64)prom[2][i] << (8*3)) |
+ ((uint64)prom[3][i] << (8*2)) |
+ ((uint64)prom[4][i] << (8*1)) |
+ ((uint64)prom[5][i] << (8*0));
+ }
+
+ return 0;
+}
+
+int
+show_prom(void)
+{
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ printf("%03o %016Lo", i, prom_ucode[i]);
+ printf(" %02x %02x %02x %02x %02x %02x",
+ prom[0][i],
+ prom[1][i],
+ prom[2][i],
+ prom[3][i],
+ prom[4][i],
+ prom[5][i]);
+ printf("\n");
+ }
+
+ for (i = 0100; i < 0110; i++) {
+ printf("%03o %016Lo", i, prom_ucode[i]);
+ printf(" %02x %02x %02x %02x %02x %02x",
+ prom[0][i],
+ prom[1][i],
+ prom[2][i],
+ prom[3][i],
+ prom[4][i],
+ prom[5][i]);
+ printf("\n");
+ }
+
+ printf("----\n");
+ return 0;
+}
+
+#define l48(n) ((uint64)(n))
+#define mask(v, n) (l48(v) << (n))
+#define bit(n) (l48(1) << (n))
+
+char *alu_bool_op[] = {
+ "SETZ",
+ "AND",
+ "ANDCA",
+ "SETM",
+ "ANDCM",
+ "SETA",
+ "XOR",
+ "IOR",
+ "ANDCB",
+ "EQV",
+ "SETCA",
+ "ORCA",
+ "SETCM",
+ "ORCM",
+ "ORCB",
+ "SETO"
+};
+
+char *alu_arith_op[] = {
+ "-1",
+ "(M&A)-1",
+ "(M&~A)-1",
+ "M-1",
+ "M|~A",
+ "(M|~A)+(M&A)",
+ "M-A-1 [M-A-1]",
+ "(M|~A)+M",
+ "M|A",
+ "M+A [ADD]",
+ "(M|A)+(M&~A)",
+ "(M|A)+M",
+ "M",
+ "M+(M&A)",
+ "M+(M|~A)",
+ "M+M"
+};
+
+void
+disassemble_m_src(ucw_t u, int m_src)
+{
+ if (m_src & 040) {
+ switch (m_src & 037) {
+ case 0:
+ printf("dispatch-constant "); break;
+ case 1:
+ printf("SPC-ptr, spc-data ");
+ break;
+ case 2:
+ printf("PDL-ptr %o ", (int)u & 01777);
+ break;
+ case 3:
+ printf("PDL-index %o ", (int)u & 01777);
+ break;
+ case 5:
+ printf("PDL-buffer ");
+ break;
+ case 6:
+ printf("OPC register %o ",
+ (int)u & 017777);
+ break;
+ case 7:
+ printf("Q ");
+ break;
+ case 010:
+ printf("VMA ");
+ break;
+ case 011:
+ printf("MAP[MD] ");
+ break;
+ case 012:
+ printf("MD ");
+ break;
+ case 013:
+ printf("LC ");
+ break;
+ case 014:
+ printf("SPC pointer and data, pop ");
+ break;
+ case 024:
+ printf("PDL[Pointer], pop ");
+ break;
+ case 025:
+ printf("PDL[Pointer] ");
+ break;
+ }
+ } else {
+ printf("m[%o] ", m_src);
+ }
+}
+
+void
+disassemble_dest(int dest)
+{
+ if (dest & 04000) {
+ printf("->a_mem[%o] ", dest & 01777);
+ } else {
+ switch (dest >> 5) {
+ case 0: printf("-><none>"); break;
+ case 1: printf("->LC "); break;
+ case 2: printf("->IC "); break;
+ case 010: printf("->PDL[ptr] "); break;
+ case 011: printf("->PDL[ptr],push "); break;
+ case 012: printf("->PDL[index] "); break;
+ case 013: printf("->PDL index "); break;
+ case 014: printf("->PDL ptr "); break;
+
+ case 015: printf("->SPC data,push "); break;
+
+ case 016: printf("->OA-reg-lo "); break;
+ case 017: printf("->OA-reg-hi "); break;
+
+ case 020: printf("->VMA "); break;
+ case 021: printf("->VMA,start-read "); break;
+ case 022: printf("->VMA,start-write "); break;
+ case 023: printf("->VMA,write-map "); break;
+
+ case 030: printf("->MD "); break;
+ case 031: printf("->MD,start-read "); break;
+ case 032: printf("->MD,start-write "); break;
+ case 033: printf("->MD,write-map "); break;
+ }
+
+ printf(",m[%o] ", dest & 037);
+ }
+}
+
+void
+disassemble_ucode_loc(int loc, ucw_t u)
+{
+ int a_src, m_src, new_pc, dest, alu_op;
+ int r_bit, p_bit, n_bit, ir8, ir7;
+ int widthm1, pos;
+ int mr_sr_bits;
+ int jump_op;
+
+ int disp_cont, disp_addr;
+ int map, len, rot;
+ int out_bus;
+
+ if ((u >> 42) & 1)
+ printf("popj; ");
+
+ switch ((u >> 43) & 03) {
+ case 0: /* alu */
+ printf("(alu) ");
+
+ if ((u & NOP_MASK) == 0) {
+ printf("no-op");
+ goto done;
+ }
+
+ a_src = (u >> 32) & 01777;
+ m_src = (u >> 26) & 077;
+ dest = (u >> 14) & 07777;
+ out_bus = (u >> 12) & 3;
+ ir8 = (u >> 8) & 1;
+ ir7 = (u >> 7) & 1;
+
+ alu_op = (u >> 3) & 017;
+ if (ir8 == 0) {
+ if (ir7 == 0) {
+ printf("%s ", alu_bool_op[alu_op]);
+ } else {
+ printf("%s ", alu_arith_op[alu_op]);
+ }
+ } else {
+ switch (alu_op) {
+ case 0: printf("mult-step "); break;
+ case 1: printf("div-step "); break;
+ case 5: printf("rem-corr "); break;
+ case 011: printf("init-div-step "); break;
+ }
+ }
+
+ printf("a=%o m=%o ", a_src, m_src);
+ disassemble_m_src(u, m_src);
+
+ if ((u >> 2) & 1)
+ printf("C=1 ");
+ else
+ printf("C=0 ");
+
+ switch (out_bus) {
+ case 1: printf("alu-> "); break;
+ case 2: printf("alu>>+s "); break;
+ case 3: printf("alu<<+q31 "); break;
+ }
+
+ switch (u & 3) {
+ case 1: printf("<<Q "); break;
+ case 2: printf(">>Q "); break;
+ case 3: printf("Q-R "); break;
+ }
+
+ disassemble_dest(dest);
+ break;
+ case 1: /* jump */
+ printf("(jump) ");
+
+ a_src = (u >> 32) & 01777;
+ m_src = (u >> 26) & 077;
+ new_pc = (u >> 12) & 037777;
+
+ jump_op = (u >> 14) & 3;
+
+ printf("a=%o m=", a_src);
+ disassemble_m_src(u, m_src);
+
+ r_bit = (u >> 9) & 1;
+ p_bit = (u >> 8) & 1;
+ n_bit = (u >> 7) & 1;
+
+ printf("pc %o, %s%s",
+ new_pc,
+ r_bit ? "R " : "",
+ p_bit ? "P " : "");
+
+ if (n_bit)
+ /* INHIBIT-XCT-NEXT */
+ printf("!next ");
+ if (u & (1<<6))
+ /* INVERT-JUMP-SENSE */
+ printf("!jump ");
+
+ if (u & (1<<5)) {
+ switch (u & 017) {
+ case 0:
+ case 1: printf("M-src < A-src "); break;
+ case 2: printf("M-src <= A-src "); break;
+ case 3: printf("M-src = A-src "); break;
+ case 4: printf("pf "); break;
+ case 5: printf("pf/int "); break;
+ case 6: printf("pf/int/seq "); break;
+ case 7:
+ printf("jump-always "); break;
+ }
+ } else {
+ printf("m-rot<< %o", (int)u & 037);
+ }
+
+/*
+ switch (jump_op) {
+ case 0: printf("jump-xct-next "); break;
+ case 1: printf("jump "); break;
+ case 2: printf("call-xct-next "); break;
+ case 3: printf("call "); break;
+ }
+*/
+ break;
+ case 2: /* dispatch */
+ printf("(dispatch) ");
+
+ disp_cont = (u >> 32) & 01777;
+ m_src = (u >> 26) & 077;
+
+ if ((u >> 25) & 1) printf("!N+1 ");
+ if ((u >> 24) & 1) printf("ISH ");
+ disp_addr = (u >> 12) & 03777;
+ map = (u >> 8) & 3;
+ len = (u >> 5) & 07;
+ rot = u & 037;
+
+ printf("m=%o ", m_src);
+ disassemble_m_src(u, m_src);
+
+ printf("disp-const %o, disp-addr %o, map %o, len %o, rot %o ",
+ disp_cont, disp_addr, map, len, rot);
+ break;
+ case 3: /* byte */
+ printf("(byte) ");
+
+ a_src = (u >> 32) & 01777;
+ m_src = (u >> 26) & 077;
+ dest = (u >> 14) & 07777;
+ mr_sr_bits = (u >> 12) & 3;
+
+ widthm1 = (u >> 5) & 037;
+ pos = u & 037;
+
+ printf("a=%o m=", a_src);
+ disassemble_m_src(u, m_src);
+
+ switch (mr_sr_bits) {
+ case 0:
+ break;
+ case 1: /* ldb */
+ printf("ldb pos=%o, width=%o ",
+ pos, widthm1+1);
+ break;
+ case 2:
+ printf("sel dep (a<-m&mask) pos=%o, width=%o ",
+ pos, widthm1+1);
+ break;
+ case 3: /* dpb */
+ printf("dpb pos=%o, width=%o ",
+ pos, widthm1+1);
+ break;
+ }
+
+ disassemble_dest(dest);
+ break;
+ }
+
+ done:
+ printf("\n");
+}
+
+void
+disassemble_prom(void)
+{
+ int i, start, finish;
+
+#if 0
+ start = 0100;
+ finish = 0110;
+#else
+ start = 0;
+ finish = 512;
+#endif
+
+ for (i = start; i < finish; i++) {
+
+ ucw_t u = prom_ucode[i];
+
+ printf("%03o %016Lo ", i, prom_ucode[i]);
+
+ disassemble_ucode_loc(i, u);
+ }
+}
+
+/* ----------------------------------------------------------------- */
+
+/* see diskmaker.c */
+//static int partoff = 046324;
+//static int partoff = 0114124;
+static int partoff;
+static int bnum = -1;
+static unsigned int buf[256];
+
+extern int disk_fd;
+
+static unsigned long
+str4(char *s)
+{
+ return (s[3]<<24) | (s[2]<<16) | (s[1]<<8) | s[0];
+}
+
+
+static int
+find_disk_partition_table(int fd)
+{
+ int ret;
+ int p, count, nw, i;
+ off_t offset;
+
+ printf("looking for partition\n");
+
+ offset = 0;
+ ret = lseek(fd, offset, SEEK_SET);
+ if (ret != offset) {
+ return -1;
+ }
+
+ ret = read(fd, buf, 256*4);
+ if (ret != 256*4) {
+ return -1;
+ }
+
+ /* this is so much prettier in lisp... */
+ p = 0200;
+ count = buf[p++];
+ nw = buf[p++];
+ if (0) printf("count %d, nw %d\n", count, nw);
+
+ for (i = 0; i < count; i++) {
+ if (0) printf("%d %08x %08x\n", i, buf[p], (int)str4("LOD1"));
+ if (buf[p] == str4("LOD1")) {
+ partoff = buf[p+1];
+ if (0) printf("found lod1 %o\n", partoff);
+ break;
+ }
+ p += nw;
+ }
+
+ bnum = -1;
+ return 0;
+}
+
+
+static unsigned int
+read_virt(int fd, int addr, unsigned int *pv)
+{
+ int b;
+ off_t offset, ret;
+
+ addr &= 077777777;
+
+ b = addr / 256;
+
+ offset = (b + partoff) * (256*4);
+
+ if (b != bnum) {
+ bnum = b;
+
+ if (0) printf("block %d(10)\n", b);
+
+ ret = lseek(fd, offset, SEEK_SET);
+ if (ret != offset) {
+ perror("seek");
+ return -1;
+ }
+
+ ret = read(fd, buf, 256*4);
+ if (ret != 256*4) {
+ return -1;
+ }
+ }
+
+ *pv = buf[ addr % 256 ];
+ return 0;
+}
+
+static char *
+read_string(unsigned int loc)
+{
+ unsigned int v;
+ int t, i, j;
+ static char s[256];
+
+ if (read_virt(disk_fd, loc, &v) == 0) {
+
+ if (0) printf("%o len %o\n", loc, v);
+
+ t = v & 0xff;
+ j = 0;
+ for (i = 0; i < t; i += 4) {
+ unsigned int l;
+
+ l = loc+1+(i/4);
+ if (read_virt(disk_fd, l, &v))
+ return "<read-failed>";
+
+ if (0) printf("%o %o %08x\n", l, v, v);
+
+ s[j++] = v >> 0;
+ s[j++] = v >> 8;
+ s[j++] = v >> 16;
+ s[j++] = v >> 24;
+ }
+
+ s[t] = 0;
+ return s;
+ }
+
+ return (char *)0;
+}
+
+static char *
+show_string(unsigned int loc)
+{
+ char *s;
+
+ s = read_string(loc);
+ printf(" '%s' ", s);
+ return s;
+}
+
+/*
+ * a complete hack; given a pc, find the function header and print
+ * the function name. helpful for debugging.
+ */
+char *
+find_function_name(int the_lc)
+{
+ int i, tag = 0;
+ unsigned int loc = the_lc >> 2;
+ unsigned int v;
+
+ if (0) printf("find %o\n", loc);
+
+ if (partoff == 0) {
+ find_disk_partition_table(disk_fd);
+ }
+
+ /* search backward to find the function header */
+ for (i = 0; i < 512; i++) {
+
+ if (read_virt(disk_fd, loc, &v))
+ break;
+
+ tag = (v >> 24) & 077;
+ if (tag == 7) break;
+ loc--;
+ }
+
+ if (0) printf("%o found header, back %d\n", loc, i);
+
+ if (tag == 7) {
+ /* find function symbol ptr */
+ if (read_virt(disk_fd, loc+2, &v) == 0) {
+
+ if (0) printf("%o ptr %o\n", loc, v);
+
+ loc = v;
+ tag = (v >> 24) & 077;
+
+ if (read_virt(disk_fd, loc, &v))
+ return "<read-failed>";
+
+ /* hack - it's a list */
+ if (tag == 016) {
+ if (read_virt(disk_fd, v, &v))
+ return "<read-failed>";
+ }
+
+ return read_string(v);
+ }
+ }
+
+ return "<no-function>";
+}
+
+void
+show_list(unsigned int lp)
+{
+ unsigned int loc, l1, v;
+ int i;
+
+ loc = 031602653046;
+ loc = 001614546634;
+ loc = 030301442405;
+ read_virt(disk_fd, loc, &v);
+// printf("%011o %011o\n", loc, v);
+// loc = v;
+
+ for (i = 0; i < 10; i++) {
+ int tag, cdr, addr;
+
+ read_virt(disk_fd, loc, &v);
+
+ tag = (v >> 24) & 077;
+ cdr = (v >> 30) & 3;
+ addr = v & 0x00ffffff;
+
+ printf(" %011o %011o %03o %1o\n", loc, v, tag, cdr);
+
+ if (cdr == 2)
+ i = 100;
+
+ if (addr != 0)
+ switch (tag) {
+ case 003:
+ l1 = v;
+ read_virt(disk_fd, l1, &v);
+ tag = (v >> 24) & 077;
+ cdr = (v >> 30) & 3;
+ printf(" %011o %011o %03o %1o\n", l1, v, tag, cdr);
+
+ l1 = v;
+ read_virt(disk_fd, l1, &v);
+ tag = (v >> 24) & 077;
+ cdr = (v >> 30) & 3;
+ printf(" %011o %011o %03o %1o\n", l1, v, tag, cdr);
+
+ show_string(l1);
+ printf("\n");
+ break;
+ case 004:
+ l1 = v;
+ read_virt(disk_fd, l1, &v);
+ tag = (v >> 24) & 077;
+ cdr = (v >> 30) & 3;
+ printf(" %011o %011o %03o %1o\n", l1, v, tag, cdr);
+
+ show_string(l1);
+ printf("\n");
+ break;
+
+ case 016:
+// loc = v;
+ break;
+ case 021:
+ l1 = v;
+ read_virt(disk_fd, l1, &v);
+ tag = (v >> 24) & 077;
+ cdr = (v >> 30) & 3;
+ printf(" %011o %011o %03o %1o\n", l1, v, tag, cdr);
+
+ show_string(l1);
+ printf("\n");
+#if 0
+ l1 = v;
+ read_virt(disk_fd, l1, &v);
+ tag = (v >> 24) & 077;
+ cdr = (v >> 30) & 3;
+ printf(" %011o %011o %03o %1o\n", l1, v, tag, cdr);
+
+ l1++;
+ read_virt(disk_fd, l1, &v);
+ tag = (v >> 24) & 077;
+ cdr = (v >> 30) & 3;
+ printf(" %011o %011o %03o %1o\n", l1, v, tag, cdr);
+
+ l1++;
+ read_virt(disk_fd, l1, &v);
+ tag = (v >> 24) & 077;
+ cdr = (v >> 30) & 3;
+ printf(" %011o %011o %03o %1o\n", l1, v, tag, cdr);
+#endif
+ break;
+ default:
+// i = 100;
+ break;
+ }
+
+ loc++;
+ }
+}
735 disk.c
@@ -0,0 +1,735 @@
+/*
+ * disk.c
+ *
+ * simple CADR disk emulation
+ * attempts to emulate the disk controller on a CADR
+ *
+ * $Id: disk.c 84 2006-08-07 16:21:32Z brad $
+ */
+
+#include "usim.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+
+#if defined(LINUX) || defined(OSX)
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include "ucode.h"
+#include "config.h"
+#include "endian.h"
+
+extern void deassert_xbus_interrupt(void);
+extern void assert_xbus_interrupt(void);
+
+#define DELAY_DISK_INTERRUPT
+#define ALLOW_DISK_WRITE
+
+
+/*
+ Note: original CADR disk controller wrote LS bit first, LS byte first.
+
+ disk controller registers:
+ 0 read status
+ 1 read ma
+ 2 read da
+ 3 read ecc
+ 4 load cmd
+ 5 load clp (command list pointer)
+ 6 load da (disk address)
+ 7 start
+
+ Commands (cmd reg)
+ 00 read
+ 10 read compare
+ 11 write
+ 02 read all
+ 13 write all
+ 04 seek
+ 05 at ease
+ 1005 recalibreate
+ 405 fault clear
+ 06 offset clear
+ 16 stop,reset
+
+ Command bits
+ 0
+ 1 cmd
+ 2
+ 3 cmd to memory
+ 4 servo offset plus
+ 5 servo offset
+ 6 data strobe early
+ 7 data strobe late
+ 8 fault clear
+ 9 recalibrate
+ 10 attn intr enb
+ 11 done intr enb
+
+ Status bits (status reg)
+ 0 active-
+ 1 any attention
+ 2 sel unit attention
+ 3 intr
+ 4 multiple select
+ 5 no select
+ 6 sel unit fault
+ 7 sel unit read only
+ 8 on cyl sync-
+ 9 sel unit on line-
+ 10 sel unit seek error
+ 11 timeout error
+ 12 start block error
+ 13 stopped by error
+ 14 overrun
+ 15 ecc.soft
+
+ 16 ecc.hard
+ 17 header ecc err
+ 18 header compare err
+ 19 mem parity err
+ 20 nmx error
+ 21 ccw cyc
+ 22 read comp diff
+ 23 internal parity err
+
+ 24-31 block.ctr
+
+ Disk address (da reg)
+ 31 n/c
+ 30 unit2
+ 29 unit1
+ 28 unit0
+
+ 27 cyl11
+ ...
+ 16 cyl0
+
+ 15 head7
+ ...
+ 8 head0
+
+ 7 block7
+ ...
+ 0 block0
+
+ ---
+
+ CLP (command list pointer) points to list of CCW's
+ Each CCW is phy address to write block
+
+ clp register (22 bits)
+ [21:16][15:0]
+ fixed counts up
+
+ clp address is used to read in new ccw
+ ccw's are read (up to 65535)
+
+ ccw is used to produce dma address
+ dma address comes from ccw + 8 bit counter
+
+ ccw
+ [21:1][1]
+ physr |
+ addr 0 = last ccw, 1 = more ccw's
+
+ ccw counter
+ [21:8][7:0]
+
+ ---
+
+ read ma register
+ t0 t1 CLP
+ [23][22][21:0]
+ | |
+ | type 1 (show how controller is strapped; i.e. what type of
+ type 0 disk drive)
+
+ (trident is type 0)
+
+
+*/
+
+int disk_fd;
+
+int disk_status = 1;
+int disk_cmd;
+int disk_clp;
+int disk_ma;
+int disk_ecc;
+int disk_da;
+
+int disk_byteswap;
+
+void
+disk_set_byteswap(int on)
+{
+ disk_byteswap = on;
+}
+
+int
+disk_get_status(void)
+{
+ return disk_status;
+}
+
+void
+disk_set_da(int v)
+{
+ disk_da = v;
+}
+
+void
+disk_set_clp(int v)
+{
+ disk_clp = v;
+}
+
+void
+disk_set_cmd(int v)
+{
+ disk_cmd = v;
+
+ if ((disk_cmd & 06000) == 0)
+ deassert_xbus_interrupt();
+}
+
+int cyls, heads, blocks_per_track;
+int cur_unit, cur_cyl, cur_head, cur_block;
+
+void
+_swaplongbytes(unsigned int *buf, int word_count)
+{
+ /* buf contains bytes from the file. Words in that file were written
+ * as little endian. The macintosh will interpret the word values
+ * as big-endian, however. This routine will swap bytes around so
+ * that the DISK_word values in the array will match what would
+ * have been read on a little-endian machine
+ */
+ int i;
+
+ for (i = 0; i < word_count; i++) {
+ buf[i] = SWAP_LONG(buf[i]);
+ }
+}
+
+/*
+ * Disk Structure
+ *
+ * Each disk block contains one Lisp machine page worth of data,
+ * i.e. 256. words or 1024. bytes.
+ */
+
+int
+_disk_read(int block_no, unsigned int *buffer)
+{
+ off_t offset, ret;
+ int size;
+
+ offset = block_no * (256*4);
+
+ tracedio("disk: file image block %d(10), offset %ld(10)\n",
+ block_no, (long)offset);
+
+ ret = lseek(disk_fd, offset, SEEK_SET);
+ if (ret != offset) {
+ printf("disk: image file seek error\n");
+ perror("lseek");
+ return -1;
+ }
+
+ size = 256*4;
+
+ ret = read(disk_fd, buffer, size);
+ if (ret != size) {
+ printf("disk read error; ret %d, offset %lu, size %d\n",
+ (int)ret, (long)offset, size);
+ perror("read");
+
+ memset((char *)buffer, 0, size);
+ return -1;
+ }
+
+ /* byte order fixups? */
+ if (disk_byteswap) {
+ _swaplongbytes((unsigned int *)buffer, 256);
+ }
+
+ return 0;
+}
+
+int
+_disk_write(int block_no, unsigned int *buffer)
+{
+ off_t offset, ret;
+ int size;
+
+ offset = block_no * (256*4);
+
+ tracedio("disk: file image block %d, offset %ld\n",
+ block_no, (long)offset);
+
+ ret = lseek(disk_fd, offset, SEEK_SET);
+ if (ret != offset) {
+ printf("disk: image file seek error\n");
+ perror("lseek");
+ return -1;
+ }
+
+ size = 256*4;
+
+ /* byte order fixups? */
+ if (disk_byteswap) {
+ _swaplongbytes((unsigned int *)buffer, 256);
+ }
+
+ ret = write(disk_fd, buffer, size);
+ if (ret != size) {
+ printf("disk write error; ret %d, offset %lu, size %d\n",
+ (int)ret, (long)offset, size);
+ perror("write");
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+disk_read_block(unsigned int vma, int unit, int cyl, int head, int block)
+{
+ int block_no, i;
+ unsigned int buffer[256];
+
+ block_no =
+ (cyl * blocks_per_track * heads) +
+ (head * blocks_per_track) + block;
+
+ if (disk_fd) {
+ _disk_read(block_no, buffer);
+#if 0
+ if (block_no == 10312)
+ for (i = 0; i < 32; i++) {
+ tracedio("read; vma %011o <- %011o\n",
+ vma + i, buffer[i]);
+ }
+#endif
+ for (i = 0; i < 256; i++) {
+ write_phy_mem(vma + i, buffer[i]);
+ }
+ return 0;
+ }
+
+#define LABEL_LABL 011420440514ULL
+#define LABEL_BLANK 020020020020ULL
+
+ /* hack to fake a disk label when no image is present */
+ if (unit == 0 && cyl == 0 && head == 0 && block == 0) {
+ write_phy_mem(vma + 0, LABEL_LABL); /* label LABL */
+ write_phy_mem(vma + 1, 000000000001); /* version = 1 */
+ write_phy_mem(vma + 2, 000000001000); /* # cyls */
+ write_phy_mem(vma + 3, 000000000004); /* # heads */
+ write_phy_mem(vma + 4, 000000000100); /* # blocks */
+ write_phy_mem(vma + 5, 000000000400); /* heads*blocks */
+ write_phy_mem(vma + 6, 000000001234); /* name of micr part */
+ write_phy_mem(vma + 0200, 1); /* # of partitions */
+ write_phy_mem(vma + 0201, 1); /* words / partition */
+
+ write_phy_mem(vma + 0202, 01234); /* start of partition info */
+ write_phy_mem(vma + 0203, 01000); /* micr address */
+ write_phy_mem(vma + 0204, 010); /* # blocks */
+ /* pack text label - offset 020, 32 bytes */
+ return 0;
+ }
+
+ return -1;
+}
+
+int
+disk_write_block(unsigned int vma, int unit, int cyl, int head, int block)
+{
+ int block_no, i;
+ unsigned int buffer[256];
+
+ block_no =
+ (cyl * blocks_per_track * heads) +
+ (head * blocks_per_track) + block;
+
+ if (disk_fd) {
+ for (i = 0; i < 256; i++) {
+ read_phy_mem(vma + i, &buffer[i]);
+ }
+#if 0
+ if (block_no == 1812)
+ for (i = 0; i < 32; i++) {
+ tracedio("write; vma %011o <- %011o\n",
+ vma + i, buffer[i]);
+ }
+#endif
+ _disk_write(block_no, buffer);
+ return 0;
+ }
+
+ return 0;
+}
+
+void
+disk_throw_interrupt(void)
+{
+ tracedio("disk: throw interrupt\n");
+ disk_status |= 1<<3;
+ assert_xbus_interrupt();
+}
+
+#ifdef DELAY_DISK_INTERRUPT
+static int disk_interrupt_delay;
+
+void
+disk_future_interrupt()
+{
+ disk_interrupt_delay = 100;
+disk_interrupt_delay = 2500;
+}
+
+void
+disk_poll()
+{
+ if (disk_interrupt_delay) {
+ if (--disk_interrupt_delay == 0) {
+ disk_throw_interrupt();
+ }
+ }
+}
+#else
+void disk_poll() {}
+#endif
+
+void
+disk_show_cur_addr(void)
+{
+ tracedio("disk: unit %d, CHB %o/%o/%o\n",
+ cur_unit, cur_cyl, cur_head, cur_block);
+}
+
+void
+disk_decode_addr(void)
+{
+ cur_unit = (disk_da >> 28) & 07;
+ cur_cyl = (disk_da >> 16) & 07777;
+ cur_head = (disk_da >> 8) & 0377;
+ cur_block = disk_da & 0377;
+}
+
+void
+disk_undecode_addr(void)
+{
+ disk_da =
+ ((cur_unit & 07) << 28) |
+ ((cur_cyl & 07777) << 16) |
+ ((cur_head & 0377) << 8) |
+ ((cur_block & 0377));
+}
+
+void
+disk_incr_block(void)
+{
+ cur_block++;
+ if (cur_block >= blocks_per_track) {
+ cur_block = 0;
+ cur_head++;
+ if (cur_head >= heads) {
+ cur_head = 0;
+ cur_cyl++;
+ }
+ }
+}
+
+void
+disk_start_read(void)
+{
+ unsigned int ccw;
+ unsigned int vma;
+ int i;
+
+ disk_decode_addr();
+
+ /* process ccw's */
+ for (i = 0; i < 65535; i++) {
+ int f;
+
+ f = read_phy_mem(disk_clp, &ccw);
+ if (f) {
+ printf("disk: mem[clp=%o] yielded fault (no page)\n",
+ disk_clp);
+
+ /* huh. what to do now? */
+ return;
+ }
+
+ tracedio("disk: mem[clp=%o] -> ccw %08o\n", disk_clp, ccw);
+
+ vma = ccw & ~0377;
+ disk_ma = vma;
+
+ disk_show_cur_addr();
+
+ disk_read_block(vma, cur_unit, cur_cyl, cur_head, cur_block);
+
+ if ((ccw & 1) == 0) {
+ tracedio("disk: last ccw\n");
+ break;
+ }