diff --git a/.gitignore b/.gitignore index b25c15b8..db0f4ea5 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *~ +out diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..2611e428 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "itstar"] + path = tools/itstar + url = https://github.com/PDP-10/itstar +[submodule "tapeutils"] + path = tools/tapeutils + url = https://github.com/brouhaha/tapeutils diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..9fcbe668 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +language: c +sudo: required +install: + - sudo apt-get update -myq + - sudo apt-get install -my simh expect +script: make +notifications: + email: lars@nocrew.org diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..af4233b7 --- /dev/null +++ b/Makefile @@ -0,0 +1,29 @@ +ITSTAR=${PWD}/tools/itstar/itstar +WRITETAPE=${PWD}/tools/tapeutils/tapewrite + +all: out/rp0.dsk + +out/rp0.dsk: build/simh/init out/minsys.tape out/salv.tape out/dskdmp.tape build/build.tcl + expect -f build/build.tcl + +out/minsys.tape: $(ITSTAR) + mkdir -p out + cd bin; $(ITSTAR) -cf ../$@ _ sys sys3 sysbin + cd src; $(ITSTAR) -rf ../$@ system + +out/salv.tape: $(WRITETAPE) bin/boot/ram.262 bin/boot/salv.rp06 + mkdir -p out + $(WRITETAPE) -n 2560 $@ bin/boot/ram.262 bin/boot/salv.rp06 + +out/dskdmp.tape: $(WRITETAPE) bin/boot/ram.262 bin/boot/dskdmp.rp06 + mkdir -p out + $(WRITETAPE) -n 2560 $@ bin/boot/ram.262 bin/boot/dskdmp.rp06 + +$(ITSTAR): + cd tools/itstar; make + +$(WRITETAPE): + cd tools/tapeutils; make + +clean: + rm -rf out diff --git a/README.md b/README.md index ee700d96..7b4997f0 100644 --- a/README.md +++ b/README.md @@ -12,5 +12,12 @@ to operate ITS systems to this day. This repository contains source code, tools, and scripts to build ITS from scratch. -...or at least, that's the plan. There will be some initial -experimentation in the [`test` branch](http://github.com/PDP-10/its/tree/test). +1. First, magnetic tape images are created from files in `src` and + `bin`. There are two bootable tapes, and one tape with files in + DSKDMP backup format. + +2. Then the tapes are used to create a file system on an RP06 disk and + populate it with a minimal system, and also source code. + +3. Finally, the system is booted from the disk, and MIDAS is invoked + to assemble ITS from source code. diff --git a/bin/_/@.ddt b/bin/_/@.ddt new file mode 100644 index 00000000..7a1c2f73 Binary files /dev/null and b/bin/_/@.ddt differ diff --git a/bin/_/bt.rm03 b/bin/_/bt.rm03 new file mode 100644 index 00000000..4eb685eb Binary files /dev/null and b/bin/_/bt.rm03 differ diff --git a/bin/_/bt.rm80 b/bin/_/bt.rm80 new file mode 100644 index 00000000..084455b9 Binary files /dev/null and b/bin/_/bt.rm80 differ diff --git a/bin/_/bt.rp06 b/bin/_/bt.rp06 new file mode 100644 index 00000000..cd17b267 Binary files /dev/null and b/bin/_/bt.rp06 differ diff --git a/bin/_/bt.rp07 b/bin/_/bt.rp07 new file mode 100644 index 00000000..3a92eb0d Binary files /dev/null and b/bin/_/bt.rp07 differ diff --git a/bin/_/dskdmp.rm03 b/bin/_/dskdmp.rm03 new file mode 100644 index 00000000..c47c9ebb Binary files /dev/null and b/bin/_/dskdmp.rm03 differ diff --git a/bin/_/dskdmp.rm80 b/bin/_/dskdmp.rm80 new file mode 100644 index 00000000..3b37ed13 Binary files /dev/null and b/bin/_/dskdmp.rm80 differ diff --git a/bin/_/dskdmp.rp06 b/bin/_/dskdmp.rp06 new file mode 100644 index 00000000..4633cc19 Binary files /dev/null and b/bin/_/dskdmp.rp06 differ diff --git a/bin/_/dskdmp.rp07 b/bin/_/dskdmp.rp07 new file mode 100644 index 00000000..df1f6eae Binary files /dev/null and b/bin/_/dskdmp.rp07 differ diff --git a/bin/_/its.rm03 b/bin/_/its.rm03 new file mode 100644 index 00000000..0192dc57 Binary files /dev/null and b/bin/_/its.rm03 differ diff --git a/bin/_/its.rm80 b/bin/_/its.rm80 new file mode 100644 index 00000000..59727844 Binary files /dev/null and b/bin/_/its.rm80 differ diff --git a/bin/_/its.rp06 b/bin/_/its.rp06 new file mode 100644 index 00000000..bc9f40a3 Binary files /dev/null and b/bin/_/its.rp06 differ diff --git a/bin/_/its.rp07 b/bin/_/its.rp07 new file mode 100644 index 00000000..2ea1fefd Binary files /dev/null and b/bin/_/its.rp07 differ diff --git a/bin/_/ram.ram b/bin/_/ram.ram new file mode 100644 index 00000000..462530fd Binary files /dev/null and b/bin/_/ram.ram differ diff --git a/bin/_/salv.rm03 b/bin/_/salv.rm03 new file mode 100644 index 00000000..297cc733 Binary files /dev/null and b/bin/_/salv.rm03 differ diff --git a/bin/_/salv.rm80 b/bin/_/salv.rm80 new file mode 100644 index 00000000..0d82ad8b Binary files /dev/null and b/bin/_/salv.rm80 differ diff --git a/bin/_/salv.rp06 b/bin/_/salv.rp06 new file mode 100644 index 00000000..b8c0ecfb Binary files /dev/null and b/bin/_/salv.rp06 differ diff --git a/bin/_/salv.rp07 b/bin/_/salv.rp07 new file mode 100644 index 00000000..d2170179 Binary files /dev/null and b/bin/_/salv.rp07 differ diff --git a/bin/boot/dskdmp.rp06 b/bin/boot/dskdmp.rp06 new file mode 100644 index 00000000..e3fda3b6 Binary files /dev/null and b/bin/boot/dskdmp.rp06 differ diff --git a/bin/boot/ram.262 b/bin/boot/ram.262 new file mode 100644 index 00000000..2a696718 Binary files /dev/null and b/bin/boot/ram.262 differ diff --git a/bin/boot/salv.rp06 b/bin/boot/salv.rp06 new file mode 100644 index 00000000..57790686 Binary files /dev/null and b/bin/boot/salv.rp06 differ diff --git a/bin/sys/atsign.ddt b/bin/sys/atsign.ddt new file mode 100644 index 00000000..6364095e Binary files /dev/null and b/bin/sys/atsign.ddt differ diff --git a/bin/sys/atsign.device b/bin/sys/atsign.device new file mode 100644 index 00000000..0548c9ef Binary files /dev/null and b/bin/sys/atsign.device differ diff --git a/bin/sys/atsign.hactrn b/bin/sys/atsign.hactrn new file mode 120000 index 00000000..65d411c7 --- /dev/null +++ b/bin/sys/atsign.hactrn @@ -0,0 +1 @@ +sys/atsign.ddt \ No newline at end of file diff --git a/bin/sys/ts.dump b/bin/sys/ts.dump new file mode 120000 index 00000000..857faedd --- /dev/null +++ b/bin/sys/ts.dump @@ -0,0 +1 @@ +sysbin/dump.bin \ No newline at end of file diff --git a/bin/sys/ts.ksfedr b/bin/sys/ts.ksfedr new file mode 100644 index 00000000..324b7be4 Binary files /dev/null and b/bin/sys/ts.ksfedr differ diff --git a/bin/sys/ts.lock b/bin/sys/ts.lock new file mode 100644 index 00000000..664f0e98 Binary files /dev/null and b/bin/sys/ts.lock differ diff --git a/bin/sys/ts.pdset b/bin/sys/ts.pdset new file mode 100644 index 00000000..b127ef67 Binary files /dev/null and b/bin/sys/ts.pdset differ diff --git a/bin/sys3/ts.midas b/bin/sys3/ts.midas new file mode 100755 index 00000000..04d662b8 Binary files /dev/null and b/bin/sys3/ts.midas differ diff --git a/bin/sysbin/dump.bin b/bin/sysbin/dump.bin new file mode 100644 index 00000000..2ba32ab3 Binary files /dev/null and b/bin/sysbin/dump.bin differ diff --git a/build/build.tcl b/build/build.tcl new file mode 100644 index 00000000..60003643 --- /dev/null +++ b/build/build.tcl @@ -0,0 +1,93 @@ +proc type s { + sleep .2 + foreach c [split $s ""] { + send $c + expect -re . + } +} + +proc respond { w r } { + expect $w + type $r +} + +proc pdset {} { + respond "YOU MAY HAVE TO :PDSET" "\032" + respond "Fair" ":pdset\r" + set t [timestamp] + respond "PDSET" [expr [timestamp -seconds $t -format "%Y"] / 100]C + type [timestamp -seconds $t -format "%y%m%dD"] + type [timestamp -seconds $t -format "%H%M%ST"] + type "!." + expect "DAYLIGHT SAVINGS" { + type "N" + respond "IT IS NOW" "Q" + } "IT IS NOW" { + type "Q" + } + expect ":KILL" +} + +proc shutdown {} { + respond "*" ":lock\r" + expect "_" + send "5kill" + respond "GO DOWN?\r\n" "y" + respond "BRIEF MESSAGE" "\003" + respond "NOW IN DDT" "\005" +} + +spawn pdp10 build/simh/init + +respond "sim>" "b tu1\r" +respond "MTBOOT" "mark\033g" +respond "Format pack on unit #" "0" +respond "Are you sure you want to format pack on drive" "y" +respond "Pack no?" "0\r" +respond "Verify pack?" "n" +respond "Alloc?" "3000\r" +respond "ID?" "foobar\r" +respond "DDT" "tran\033g" +respond "onto unit" "0" +respond "OK" "y" +expect "EOT" +respond "DDT" "\005" + +respond "sim>" "b tu2\r" +respond "MTBOOT" "\033g" +respond "DSKDMP" "l\033ddt\r" +expect "\n"; type "t\033its rp06\r" +expect "\n"; type "\033u" +respond "DSKDMP" "m\033salv rp06\r" +expect "\n"; type "d\033its\r" +expect "\n"; type "its\r" +expect "\n"; type "\033g" +pdset +respond "*" ":ksfedr\r" +respond "File not found" "create\r" +expect -re {Directory address: ([0-7]*)\r\n} +set dir $expect_out(1,string) +type "write\r" +respond "Are you sure" "yes\r" +respond "Which file" "bt\r" +respond "Input from" ".;bt rp06\r" +respond "!" "quit\r" +expect ":KILL" +shutdown + +respond "sim>" "b tu1\r" +respond "MTBOOT" "feset\033g" +respond "on unit #" "0" +respond "address: " "$dir\r" +respond "DDT" \005 +respond "sim>" "quit" + +spawn pdp10 build/simh/boot +respond "DSKDMP" "its\r" +type "\033g" +pdset +respond "*" ":midas system;_its\r" +respond "MACHINE NAME =" "AI\r" +expect ":KILL" +shutdown +respond "sim>" "quit" diff --git a/build/simh/boot b/build/simh/boot new file mode 100644 index 00000000..3f003819 --- /dev/null +++ b/build/simh/boot @@ -0,0 +1,5 @@ +set cpu its +set tim y2k +set rp0 rp06 +at rp0 out/rp0.dsk +b rp0 diff --git a/build/simh/init b/build/simh/init new file mode 100644 index 00000000..1a852a0a --- /dev/null +++ b/build/simh/init @@ -0,0 +1,7 @@ +set cpu its +set tim y2k +at tu0 out/minsys.tape +at tu1 out/salv.tape +at tu2 out/dskdmp.tape +set rp0 rp06 +at rp0 out/rp0.dsk diff --git a/doc/build.doc b/doc/build.doc new file mode 100644 index 00000000..6b19dd7d --- /dev/null +++ b/doc/build.doc @@ -0,0 +1,1068 @@ +-*- Text -*- This is the file AI:KSHACK;BUILD DOC + + + + Building a new KS10 ITS from scratch + + + +1. Inventory + +Your KS10 ITS distribution kit includes: + + 1. A KS10 boot tape containing the Salvager (labeled "Salvager"). + + 2. A KS10 boot tape containing DSKDMP (labeled "DSKDMP"). + + 3. A DUMP tape containing the minimal files needed to bring ITS up for + the first time (labeled "MINSYS"). + + 4. Four DUMP tapes containing sources and binaries for ITS itself, and + various programs including EMACS and MacLisp (Labeled "Distribution + tape #..."). + + 5. Hardcopy of the files: + KSHACK;BUILD DOC + KSHACK;CONSOL > + KSHACK;DSKDMP ORDER + KSHACK;AINOTE > + KSHACK;KSDEFS > + SYSDOC;DUMP FORMAT + .INFO.;DUMP INFO + + + +2. General explanations + +This document contains step-by-step instructions for building a new ITS +system for a KS10. This section introduces the major players. The +following sections describe the steps in detail. + +We use "$" to indicate the altmode/escape character (ascii code 33 octal). +Control characters are indicated by a proceeding "^", so "^Z" indicates the +character Control-Z (ascii code 32 octal). "" is used to indicate the +carriage return character (ascii code 15 octal). + +In this document we use a trailing "." to indicate a decimal number. All +other numbers are in octal. (Thus "105" and "69." both denote the same +number.) However, when these instructions tell you to "type a decimal +number" it only means that the sequence of digits you type will be +interpreted as a decimal number. It does not mean that you need to employ +any special notation to indicate the radix (such as a trailing decimal +point), in fact, you must not. + + +2.1. The 8080 front end + +The 8080 front end processor serves as a front console for the KS10. It +can be used to start and stop the machine, examine and deposit memory, load +and debug both machine language and microcode, as well as boot the KS10 +from tape and disk. The 8080 also controls the system console. + +Under normal operations the 8080 simply passes characters between the +processor and the system console, however typing ^\ causes the 8080 to +enter command mode. When the machine is initially powered on, the 8080 is +already in command mode. Command mode is indicated by the prompt: + + KS10> + +The 8080 will leave command mode if you type ^Z. Relevant commands are: + +MT Loads the machine from a KS10 boot tape. (Boot tapes are explained + below.) + +BT Loads the machine from the front end filesystem on the disk. (Part + of the process described in this document is how one installs a + front end filesystem.) + +ST nn Starts the machine at address nn. + +HA Halts the machine. + +A wallchart of the most useful 8080 front end commands can be found in the +file KSHACK;CONSOL >, there are many many more documented in the DEC +manuals. + + +2.2. Tape formats + +There are two different tape formats used on the tapes in your distribution +kit. + +A "KS10 boot tape" is used to load a standalone program into the KS10 +directly from tape. The MT command to the 8080 front end causes it to +load a KS10 boot tape. Such a tape starts with several records of +microcode that the 8080 loads into the KS10 micromachine. This is followed +by a bootstrap program, called "MTBOOT", that the 8080 loads into main +memory and starts. MTBOOT reads an Exec DDT and some other program into +memory from the rest of the tape and starts DDT. + +[Footnote: We do not use the DEC standard microcode. The most important +differences are that the ITS microcode supports ITS-style paging and has a +different set of I/O instructions. The file KSHACK;KSDEFS > documents the +ITS microcode.] + +A "DUMP tape" contains files (and links) in the format produced by the ITS +DUMP program. It can be used to load files into the filesystem either +using the TRAN routine in the standalone Salvager or using the DUMP program +running under timesharing. The file SYSDOC;DUMP FORMAT describes the +format of DUMP tapes. + +The two kinds of tape are not in the slightest way compatible with +each other. + + +2.3. Exec DDT + +There are perhaps more versions of DDT in the world than there are species +of insect. The standalone DDT used by ITS (sometimes called "Exec DDT") is +incompatible with every other DDT, including the DDT used on ITS under +timesharing. It's not documented anywhere, but the usual commands ($G, /, +return, etc.) work in the usual ways. + +Exec DDT has very primitive rubout processing. Typing a rubout/delete will +cause it to completely abort all unprocessed characters. + +When Exec DDT is loaded its start address is 774000. Even under +timesharing, Exec DDT is always kept at that location. Thus you can +usually get to DDT by starting the KS10 at that address (using the ST +command to the 8080 front end). + + +2.4. The Salvager + +The Salvager is a program that runs standalone and performs various +filesystem maintenance operations. It knows how to format disk packs and +how to copy them, how to build filesystems, how to detect damage in a +filesystem, and it contains tools that enable a hacker to repair a damaged +filesystem. Documentation for the Salvager can be found in its source. +The Salvager used on the KS10 is a rewrite of the older salvager still used +for the KA10 and the KL10, its source can be found in the file +KSHACK;NSALV >. + +Routines in the Salvager are run by simply using DDT to start them. Thus +to run the Salvager routine "CHKR", one types (to Exec DDT): + + CHKR$G + +Relevant routines in the Salvager are: + +MARK Formats a disk pack. + +TRAN Reads files from a DUMP tape and writes them into the filesystem. + +CHKR Checks the filesystem for problems. + +FESET Sets the pointer on disk used by the 8080 front end to boot the + machine. + +Examples of using all of these routines appear in the following sections. + +Salvager routines prompt for and process input in a variety of +idiosyncratic and inconsistent ways. Sometimes numbers are read in +decimal, sometimes they are read in octal. Sometimes (for example when +asking for the number of a disk drive) only a single digit is read, and any +additional input you accidentally type, such as a carriage return, will be +taken as a response to the following command. In the instructions that +follow, I have tried to carefully specify exactly what you must type, and +how it will be interpreted. You should be equally careful about following +these instructions. + +When a Salvager routine is finished it will generally type: + + DDT + +and return you to Exec DDT. Serious errors will also cause Salvager +routines to print an error message and return to DDT. + +Whenever the Salvager is waiting for input, typing ^Z will abort and return +immediately to DDT. Remember this. It will come in useful the first time +you make a error while typing to a Salvager routine. (The Salvager's +rubout processing is generally pretty poor.) + +A copy of the Salvager is also merged in with a dumped out ITS. This is so +that before ITS starts running it can call the Salvager to check out the +filesystem (performing the same checks as CHKR). + + +2.5. DSKDMP + +DSKDMP is a sort of miniature disk operating system. It is used to load +programs from the ITS filesystem into memory and start them, and to dump +memory into the filesystem. The DSKDMP program itself is kept on disk in +the extra cylinders that are beyond those used by the filesystem. DSKDMP +also uses this area of the disk for swapping space. + +A short DSKDMP bootstrap program is always kept in the last 64. words of +memory, from 777700 through 777777, even when timesharing is running. This +bootstrap knows how to find DSKDMP on disk and swap it in, swapping out +whatever is currently in main memory. Thus once DSKDMP is installed you +can usually (unless something trashes those 64. words) start it up by +starting the KS10 at address 777700 (using the ST command to the 8080 +front end). + +The $U command in Exec DDT will check to see if the DSKDMP bootstrap is +present, and will jump to it if it is. This is the most common way of +starting DSKDMP. + +When the 8080 front end filesystem has been built as described below, the +BT command to the 8080 (or pressing the BOOT switch) will load the DSKDMP +bootstrap into memory and start it. This makes it possible to get a DSKDMP +no matter what main memory contains (for example, after powering on the +machine). + +DSKDMP commands are either simply the name of a file to load and start, or +a single letter followed by an altmode. Many single letter commands are +then followed by a filename argument. Relevant DSKDMP commands are: + +F$ Lists the current directory. + +L$file Loads the file into memory without starting it. + +T$file Loads the file into memory assuming Exec DDT is already loaded. + Gives the file's symbols to DDT and starts DDT. + +M$file Merges the file into memory. + Does not load symbols or start anything. + +D$file Dumps memory into the named file. + +Examples of using all of these commands appear in the following sections. + +DSKDMP has an unusual convention for reading filenames: if only a single +name is given, then that is taken to be the second name of the file, and +the first name is defaulted to "@". Thus when giving DSKDMP a filename +".;ITS" refers to the file .;@ ITS. + +DSKDMP commands that read and write files sometimes take a few seconds to +run. So that you will know when DSKDMP is done executing a command, DSKDMP +will not type a linefeed until after the command is finished. + +DSKDMP has very primitive rubout processing. Typing a rubout/delete will +simply cause it to start over and prompt for a new command. + +DSKDMP error messages are somewhat terse. A wallchart of DSKDMP commands +and error messages can be found in the file KSHACK;DSKDMP ORDER. + + + +3. Formatting the disk + +Mount the Salvager boot tape and give the MT command to the 8080. (Type ^\ +to get the 8080 into command mode if necessary.) This will load the +Salvager and Exec DDT into the KS10 and start DDT. MTBOOT announces +itself: + + ITS MTBOOT.176 + +If something goes wrong while reading the tape, MTBOOT will try and tell +you about it, otherwise when the tape stops spinning, MTBOOT is finished +and has started Exec DDT. (A common error here is to forget to put the +tape drive on line.) + +Mount a disk pack on a drive. Understand that you are about to lose any +information you had on that pack. Check that the drive is not write +protected. Just to be safe, you should probably write protect any other +drives you happen to have. + +Run the MARK routine the in Salvager: + + MARK$G + +The Salvager will begin by asking you: + + Format pack on unit # + +You should respond by typing the number of the drive in question. Do not +type a carriage return after typing the number, the Salvager is only waiting +for you to type a single digit. + +The Salvager now asks: + + Are you sure you want to format the pack on drive # 0 (Y or N) + +You should respond by typing "y" if this really is what you want to do. Do +not type a carriage return, the Salvager is only waiting for you to type a +single character. It will then ask you: + + Pack no ? + +The disk packs in an ITS filesystem are numbered. Pack numbers can be +anywhere from 0 to 31., and are customarily written in decimal. With this +question the Salvager is asking you what number you want this pack to be. +Your Salvager has been assembled to believe that pack number 0 is your +primary disk pack (you may have other secondary packs someday). Since this +is in fact your primary pack you are trying to build, answer by typing "0" +followed by a carriage return. The Salvager will type something like: + + Pack 0., Drive #0 is serial #2184. + Begin formatting 815. cylinders.... + +and will start formatting the pack. This will take several minutes (about +10. for an RP06), go make yourself a cup of tea while you wait. When the +formatting is finished the Salvager will type: + + Hardware formatting complete. + Verify pack? (Y or N) + +The Salvager is offering to check that the pack is OK by reading back +everything it has just written. Unless you like to live very dangerously, +you should answer "y". Do not type a carriage return, the Salvager is only +waiting for you to type a single character. + +There are likely to be ECC correctable errors detected during this +verification phase. For each such error the Salvager will tell you where +the error occurred by typing something like: + + Disk transfer error on unit 0. + ECC Corrected error: Unit #0 Cylinder 1264 Head 12 Sector 20 + +After verification is finished (it takes just as long as the writing +phase), the Salvager will count the number of ECC correctable errors that +occurred: + + 7 ECC-corrected errors during verification. + +An absurdly large number of ECC errors, or some other error occurring during +verification should make you start over with a better disk pack. + +The Salvager now asks you for the amount of swap space you want to allocate +on this pack for ITS to use: + + Swapping Alloc? + +This number (given in octal), is the number of blocks that ITS should avoid +using for file storage at the front of the pack. This assures that there +will always be some empty space on the disk for swapping. Since ITS will +use any free block on the disk for swapping, not just those in the swapping +area, this is really only the minimum amount of swapping space. However, +since the first 500. blocks of the disk are already committed for storing +directories and the "HOM blocks" (part of the front end filesystem), you +will actually get 500. blocks less guaranteed swapping space than the +number you type here. If you find this all confusing, just type +"3000". This gives you a minimum of 1036. blocks of swapping space. + +Now the Salvager asks: + + Pack #0. ID? + +The Salvager wants you to tell it the name of the physical disk pack. This +is whatever is actually written on the pack's physical label (probably a +little piece of paper glued to the cover). (This "pack ID" is different +from the pack number, because in the future you might copy the contents of +this pack to a fresh disk pack. That new pack would still be pack #0 in +the filesystem, but would have something different written on its label. +The pack number is the name of the information written on the pack, and the +pack ID as the name of the physical pack itself.) You should type a string +of up to six characters followed by a carriage return. + +The MARK routine is now finished formatting the pack, and it returns you to +DDT after typing: + + DDT + + + +4. Loading the minimal files + +The filesystem you just built is completely empty, so the next step is to +load a minimal set of files into the filesystem so that you can bring ITS +up for the first time. + +Mount the minimal filesystem tape (the one marked "MINSYS") on the tape +drive, and run the TRAN routine in the Salvager: + + TRAN$G + +The Salvager asks: + + onto unit # + +You should respond by typing the number of the drive where your ITS pack is +mounted. As before, you should not type a carriage return after the unit +number, since the salvager is only waiting for you to type a single digit. + +As usual, the Salvager wants to make sure you know what you are doing, so +it asks: + + Copy from unit #5 onto unit #0, OK (Y or N) + +By "unit #5" it means "the tape drive". This does not mean that it is +going to address the tape drive as drive number 5. The Salvager always +uses tape drive number 0. The digit "5" has absolutely no significance, +"unit #5" is just the Salvager's name for the tape drive. You should +respond by typing a "y" if the target unit number is correct. + +The Salvager now types: + + Tape #1 + .;@ DDT + +This means that header on the tape you have mounted identifies this tape as +being tape #1, and that the first file on the tape is the file .;@ DDT, +which the Salvager is now loading. When the file has been loaded, the +Salvager types "OK" and proceeds to the next file: + + .;@ DDT OK + + .;ITS BIN + +This process should continue for about 60. files until the end of the tape, +at which point the Salvager types: + + EOT + + DDT + +and returns you to DDT. + + + +5. Checking your new filesystem + +At this point you might want to satisfy yourself that there really is a +good filesystem out there. The CHKR routine in the Salvager is the +principal means for checking the consistency of the filesystem. To run it +type: + + CHKR$G + +Since this routine is the Salvager's most common function, the Salvager +starts by announcing itself: + + Salvager 215 + +before asking you: + + Active unit numbers? + +To answer this question the Salvager wants you to type a sequence of +digits, each representing the number of an active disk drive in your +filesystem. Since at this point you only have a single drive, you should +just type its number, followed by a carriage return. The Salvager will now +inform you about which packs are mounted on the drives you have specified: + + Unit #0. ID is DX001, Pack #0 + +The unit number, pack ID, and pack number should all look familiar to you. +Now the Salvager asks: + + Use MFD from unit: + +The ITS filesystem keeps duplicate copies of all directories on all packs +for safety. Here the Salvager is asking you which copy of the Master File +Directory (the catalog of all the user directories) you regard as +authoritative. If you were recovering from some accident to a multi-pack +filesystem, this would be a useful question. Since you only have a single +drive, just type the drive number again (and don't type a carriage return). +Now the Salvager asks: + + Read all blocks of all files? (Y or N) + +The Salvager is offering to test the readability of every file in your +filesystem. When you have more files in the filesystem, this will be quite +a slow operation, but at this point it won't delay things too much, so you +might as well type "y". + + Get user dirs from unit: + +Now the Salvager wonders which drive has the pack you regard as +authoritative for the user directories. Again, since you only have a +single pack, you can only answer by typing the number of its drive (and no +carriage return). + +Now the Salvager starts working. It is highly unlikely that there will be +any problem detected. There is a possibility of some ECC correctable +errors during this process, but these aren't fatal. If all is well the +Salvager simply returns you to DDT after typing (as usual): + + DDT + + + +6. Installing DSKDMP + +Now that you have a filesystem you need to install DSKDMP on your pack. +Start by mounting the DSKDMP boot tape and giving the MT command to the +8080. (Type ^\ to get the 8080 into command mode if necessary.) This will +load an Exec DDT and a program for installing DSKDMP into the machine. As +usual MTBOOT types: + + ITS MTBOOT.176 + +when it starts running, and leaves you in DDT after it has read the tape. +To go ahead and install a DSKDMP on disk, you have to actually run the +program that was just loaded, so type: + + $G + +This writes a copy of DSKDMP on your disk, installs the DSKDMP bootstrap in +memory, and starts DSKDMP running. DSKDMP announces itself: + + DSKDMP + +To check that all is well, you can start by listing the directory named "." +where non-timesharing binary programs, like ITS itself, are generally +stored. To do this, use the F$ command to DSKDMP: + + F$ + +DSKDMP should show you a listing like this: + + #00 RAM RAM + #00 BT BIN + #00 DSKDMP BIN + #00 SALV BIN + #00 ITS BIN + #00 @ DDT + +where "#00" is the pack number of your single pack. We will see what each +of these files is for in the following sections. + + + +7. Dumping an ITS + +Now it is time to dump out an executable binary for ITS. Start by using +the L$ command to DSKDMP to load (but not start) a copy of Exec DDT by +typing: + + L$DDT + +This loads the file .;@ DDT into your machine. Now use the T$ command to +load .;ITS BIN into memory, give its symbols to Exec DDT, and start DDT, by +typing: + + T$ITS BIN + +Since DSKDMP has started DDT running, you can take this opportunity to use +DDT to patch ITS in any way that might be appropriate. It's is unlikely +that you know of any such patches under the circumstances, so use the $U +command to DDT to return to DSKDMP by typing: + + $U + +which should cause DSKDMP to return and announce itself: + + DSKDMP + +Now use the M$ command to DSKDMP to merge the file .;SALV BIN into the +programs already in memory by typing: + + M$SALV BIN + +Finally, dump the whole mess out by typing: + + D$ITS + +which will dump memory into the file .;@ ITS. If you give the F$ command +now by typing: + + F$ + +DSKDMP should show you a directory like this: + + #00 @ ITS + #00 RAM RAM + #00 BT BIN + #00 DSKDMP BIN + #00 SALV BIN + #00 ITS BIN + #00 @ DDT + + + +8. Bringing up ITS for the first time + +Now you are ready to run timesharing for the first time. The installation +procedure is not yet finished, because you have not yet built a front end +filesystem. However the program for manipulating the front end filesystem +only runs under timesharing. + +You should still be talking to DSKDMP after having dumped out an executable +ITS binary. To load that binary, and start it in Exec DDT, you need only +type the name of the file to DSKDMP: + + ITS + +After DSKDMP is finished (indicated by typing a linefeed), tell DDT to +start ITS by typing: + + $G + +ITS starts by calling the Salvager, which starts by announcing itself: + + Salvager 215 + +The Salvager will not ask you any questions this time. It will make some +reasonable assumptions about what you want done, and will return to ITS +after it is finished. (It exits to DDT if there are problems with the +filesystem. "GO$G" will start ITS without running the Salvager, should you +be in foolish desperation.) ITS now initializes itself. ITS will discover +that it does not know the time, so it will complain: + + THE KS-10 CLOCK HAS BEEN RESET, IF THE TIME CANNOT + BE DETERMINED FROM THE NETWORK, YOU MAY HAVE TO :PDSET + YEAR, PDTIME OFFSET, NOT ON DISK. + PLEASE SETLOC APPROPRIATELY. + +One of the things you will do when timesharing starts is learn how to set +the time. + +When ITS finally starts running the system console will type: + + DX ITS 1631 SYSTEM JOB USING THIS CONSOLE. + LOGIN TARAKA 0 + TARAKA DMPCPY . _DMPCP OUTPUT WRITE + TARAKA DMPCPY . @ ITS DELRNM + +The first line tells you what version of ITS is running, what machine (DX) +it was assembled for, and that this terminal is currently functioning as +the system console. The second line tells you that someone with user name +"TARAKA" has logged in. TARAKA is the system demon charged with starting +all other system demons. One of the demons TARAKA will start is named +DMPCPY. The next two lines show the job named "TARAKA DMPCPY" copying the +file .;@ ITS. (ITS logs all file operations in system directories on the +system console.) It is beyond the scope of this document to explain why +DMPCPY is copying this file. + +Now you are ready to log in. Type ^Z. After a moment ITS should respond: + + DX ITS.1631. DDT.1513. + TTY 0 + You're all alone, Fair share = 75% + + (ITS does not know the date, so messages cannot be reviewed right now.) + + +8.1. Setting the time using PDSET + +You are now talking to timesharing DDT, a program you will get to know much +better as you learn more about using ITS as a user. At this point all you +need to know is that you run a program by typing a ":", the name of the +program, and then a carriage return. You want to begin by telling the +system what the time is. So run the PDSET program by typing: + + :PDSET + +You will then see: + + (Please Log In) + ___002 PDSET IOTLSR + + PDSET.113 + Please don't use this program unless you know how. + You are certain to break something if you happen to hit the wrong key. + Type Control-Z to exit, or ? for a reminder of the commands. + +The reminder to log in (first line) was typed by timesharing DDT, which +wants to discourage you from running programs before you tell the system +who you are. For the moment you can ignore it since your machine doesn't +have a reasonable database of user names yet anyway. + +The second line was typed by ITS on the system console to advertise the +fact that the job named "___002 PDSET" is going into User I/O mode (see the +processor manual if you don't know what that is). This message isn't +actually part of your output at all, its only because you have chosen to +log in from the system console that causes you to see this message. +"___002 PDSET" is the name of the job that timesharing DDT has created for +you to run the PDSET program in. + +The rest of this output is coming from the PDSET program itself. It tries +to scare you away from using it because normally you don't want people +randomly playing with the system's clock. At this point you can type "?" +to see a list of the available commands if you like. All you need to type +is: + + yymmddD + +where the current year is 19yy, and this is the dd'th day of the mm'th +month. Then type: + + hhmmssT + +where the current time is hh:mm:ss in 24-hour time. And then type: + + !. + +(That's right, an exclamation point followed by a period.) The instant +you type the "." will be taken to be the time you have specified with the D +and T commands. At this point the system will type on the system console +something like: + + 114562/ 0 773322,,1757 ___002 + + 114561/ 0 3702 ___002 + IT IS NOW 9:05:06 PM EDT, TUESDAY, APR 29,1986 + +These messages indicate that PDSET has persuaded ITS about the current date +and time. To exit PDSET type: + + Q + +and you will be back at timesharing DDT. + + +8.2. Building a front end filesystem using KSFEDR + +Now run the KSFEDR program to build the front end filesystem. To DDT type: + + :KSFEDR + +DDT will remind you: + + (Please Log In) + +and then run KSFEDR, which will start by looking for the front end +filesystem. It won't find one, of course, so it will say: + + ERROR: File not found: PK0000: .; .FEFS. PK0000 + ! + +You should cause KSFEDR to create a fresh front end filesystem by typing: + + create + +ITS will now type on the system console something like: + + ___002 KSFEDR . .FEFS. PK0000 WRITE 21:06:01 + +which indicates that the job ___002 KSFEDR has written a file named +.;.FEFS. PK0000, at the indicated time. (All messages on the system +console include the time of day once the system knows what that is.) +KSFEDR now informs you of what it has done: + + FE filesystem DSK: .; .FEFS. PK0000 on pack #0. + Directory address: 6000000004 + ! + +Remember that directory address! You will need to remember that number +later so that you can give it to the FESET routine in the Salvager and +complete the process of installing the front end filesystem. Make sure you +get it right, it tends to have a lot of zeros in the middle which makes it +hard to remember. + +Now you need to put two files in the front end filesystem. Tell KSFEDR +that you want to write a file by typing: + + write + +It responds: + + Are you sure you want to scribble in the FE filesystem? + +You type: + + yes + +It asks: + + Which file? + +You say: + + ram + +because you want to write the microcode file. It says: + + Input from (Default DSK: USERS3; RAM RAM): + +which is almost right, you actually want the file DSK: .; RAM RAM, so you +type + + .; + +and the microcode is written. Next you want to write the DSKDMP bootstrap, +so again you say: + + write + +It responds: + + Are you sure you want to scribble in the FE filesystem? + +Again you type: + + yes + +When it asks: + + Which file? + +This time you say: + + bt + +And it offers + + Input from (Default DSK: USERS3; BT BIN): + +which is almost right, you actually want DSK: .; BT BIN, so you type + + .; + +and the bootstrap is in place. Get out of KSFEDR and back to timesharing +DDT by typing + + quit + + +8.3. Bringing ITS down using LOCK + +Now you are done using timesharing, so it is time to take ITS down again. +Run the LOCK program by typing: + + :LOCK + +LOCK responds (after DDT asks you to log in again): + + LOCK.154 + _ + +Say you want the system to go down in 5 minutes (you can't ask for it to +happen faster) by typing: + + 5kill + +LOCK asks: + + DO YOU REALLY WANT THE SYSTEM TO GO DOWN? + +since you do, you type "y". ITS now types on the system console: + + ___002 LOCK SYS DOWN MAIL WRITE 21:07:36 + +because your LOCK job is writing the file SYS;DOWN MAIL to contain an +explanation of why the system is going down. LOCK will then demand: + + PLEASE ENTER A BRIEF MESSAGE TO USERS, ENDED BY ^C + +Since you are the only user, you hardly need to be considerate, so you +might as well immediately type a ^C. All kinds of things now start +happening: + +Timesharing DDT types on your terminal: + + DX ITS going down in 4:59 + +because it thinks you might want to know about this. ITS types on the +system console: + + CULPRIT = ___002 LOCK 21:07:40 + +to tattle about who took the system down. Then, because nobody is logged +in, ITS decides it is OK to go down immediately. (DDT kept telling you to +log in, but you wouldn't listen!) It types: + + DX ITS 1631 NOT IN OPERATION 21:07:41 + +Then, the system demon named "PFTHMG DRAGON", who performs various +accounting functions and therefore has special dispensation to run after +the system is officially down, finishes up: + + PFTHMG DRAGON CHANNA _DRGN_ TIMES WRITE 21:07:42 + PFTHMG DRAGON CHANNA LOGOUT TIMES DELRNM 21:07:42 + +And finally ITS types: + + SHUTDOWN COMPLETE + PI LEVEL 7 BUG + YOU ARE NOW IN DDT. + BUGPC/ CAIA COFFI4+1 $Q-2/ JRST COFFI7 + +and returns you to Exec DDT. Don't worry about the use of the word "BUG" in +this message, there is no problem. + + + +9. Installing the front end filesystem + +Now you want to run the FESET routine in the salvager. You could use the +Salvager boot tape to get back to the salvager, but now that you have +DSKDMP in place it is more convenient to use it to create an executable +Salvager. (The Salvager merged in with the ITS binary currently in memory +doesn't have any of its symbols loaded into DDT, so it's kind of +inconvenient to use.) Start by returning to DSKDMP by typing: + + $U + +DSKDMP announces itself: + + DSKDMP + +Tell it: + + L$DDT + +to get a fresh copy of Exec DDT, then + + T$SALV BIN + +to load the file .;SALV BIN, give its symbols to DDT and start DDT. Now +you can run the FESET routine by typing: + + FESET$G + +The Salvager will ask you: + + Set FE filesystem directory pointer on the pack on unit # + +to which you should respond by typing the number of the drive on which your +ITS pack is mounted. Remember not to type a carriage return, as the +Salvager is only waiting for a single digit. The Salvager now asks: + + Directory address: + +You should now type the directory address that KSFEDR told you about above. +The FESET routine now returns to DDT. + +Now return to DSKDMP by typing: + + $U + +Since the Salvager currently in memory is a useful tool to have around, you +might as well save it as .;@ SALV. Type: + + D$SALV + + + +10. Bringing up ITS as usual + +Now you should have a bootable ITS disk pack. To test that it really +works, you can try booting it from scratch. First type ^\ to get the 8080 +into command mode. Then tell it to boot from the front end filesystem on +disk by giving the BT command: + + BT + +After a few moments DSKDMP should come up and announce itself in the usual +way. Tell DSKDMP to load the file .;@ ITS, and start it in Exec DDT by +simply typing that file's name: + + ITS + +When DSKDMP indicates it is finished by typing a linefeed, tell DDT to +start ITS running by typing: + + $G + +And ITS should come up. (You will need to run PDSET again, because the BT +command halted the machine.) The file KSHACK;AINOTE > is the notice we +keep posted on the front of AI to explain to users about crash dump +procedures, etc., you might want to go and read it next. + + + +11. Loading the rest of the filesystem using DUMP + +Now that ITS is running, you will want to load in system sources and +binaries from your distribution tapes. Type ^Z to get a timesharing DDT, +and run PDSET to set the time as you did before. Mount the first tape, and +start up the DUMP program by typing (to timesharing DDT): + + :DUMP + +DUMP will announce itself: + + DUMP .399 + + _ + +The file .INFO.;DUMP INFO documents the commands accepted by the dump +program. To load all the files (and links) from a distribution tape into +your filesystem tell DUMP: + + LOAD MERGE NOASK CRDIR + +("MERGE" tells DUMP that it should be careful about writing over any file +that already exists in your filesystem. "NOASK" tells DUMP that when faced +with such a situation, it should always leave the existing file alone. +"CRDIR" tells DUMP to create any directories that are needed.) DUMP will +want to know which files you want to load from the tape, so it will prompt +you: + + FILE= + +You respond by typing: + + *;* * + +Which means "all the files". Now DUMP will go ahead and start loading. It +will type something like: + + TAPE NO 50 CREATION DATE 860601 + +After DUMP has read the entire tape, it will prompt you again with: + + _ + +Then you can use the command: + + UNLOAD + +to rewind and unload the tape. Then mount the next tape and start over +with the LOAD command again. + +Note that the entire set of sources and binarys will probably not fit on a +single RM02 or RM03 disk pack. If you have an RM02 or RM03 system, you +will have to be more selective about what you load. + +If you don't want ITS to type out a line on the system console every time +DUMP loads a file into a system directory, patch the system as follows: + + MNGDIR/ JRST POPJ1 + +12. Getting started using ITS + +Congratulations! Now you should have a functional ITS. + +A good way to get started is to run the INFO program (":INFO" to +timesharing DDT). It is pretty much self documenting. Type "H" the first +time you run it for a tutorial on its commands. After you understand how +to use it, visit the nodes names "INTRO" and "DDT". Then you are on your +own. + +Since we haven't distributed many ITS, I don't know what problems you will +run into. Just off the top of my head, here are a few problems that you +will probably notice: + +ITS itself, and all programs that run under ITS assume the machine is +located in the time zone for the east coast of the United States. + +Many programs have the string "MIT" built in to them. + +A few programs have little tables of the names of other known ITS machines +built into them. One of the worst offenders here is the database that +finds the name of a users home directory given his user name (binary in +INQUIR;DIRS BIN, source in INQUIR;DMUNCH >). Another example is +SYS;ATSIGN DEVICE whose source is in SYSENG;@DEV >. + +MacLisp will not work because it won't recognize the name of your machine. +Programs that are built on top of MacLisp won't work either. An +adventurous hacker can probably find the place in the MacLisp sources to +fix this problem, and assemble a new version. If I ever get around to +fixing MacLisp to handle this problem gracefully, I'll certainly send you +the fix. + +I have no idea what you might have to do to get the ITS mail demon (COMSAT) +to run and deliver local mail. It may not work to build a COMSAT for a +machine with no network interfaces. I haven't been able to get a COMSAT +maintainer to sit down and think about the problem of distributing COMSATs +to far-away places. Send mail to Bug-COMSAT at AI if you want to complain +about this. + +The INQUIR system, which is a database of all the users who use ITS +machines, needs COMSAT to run in order to process changes. Until somebody +figures out how to get you a working COMSAT, you are stuck with the +database that came on your tape. This database contains all of us here at +MIT, but you won't have any way to add yourselves. There are other changes +you have to make to get INQUIR run on your machine as well, for example, +one part of the INQUIR system is a MacLisp program. + +I haven't told you anything about how to expand your filesystem to multiple +disk packs, or what to do if something seriously bad happens to your +filesystem, or what procedures are reasonable for backing up your +filesystem on tape. + +Have fun. diff --git a/doc/build.info b/doc/build.info new file mode 100644 index 00000000..8c1aa675 --- /dev/null +++ b/doc/build.info @@ -0,0 +1,84 @@ +How to build a bootable NSALV tape for ITS on a KS10 with one RM80: + +Write the following to a tape using dd and mt or whatever. All files have +2560-byte records (in TM03 format, the KS will see them as 512 words). +Rumors of PDP-10s using all 9 tracks as data tracks are utterly false, that +would be stupid. You can write the tapes on any machine that can write +unlabeled 1600bpi tapes with 8-bit data. I used an IBM ES/9000 running MTS, +about as far from the 10 as you can get! + +ram.262 (ITS microcode) + +mtboot.bin (boot block) +@.ddt (standalone DDT) +salv.rm80 (NSALV built for RM80) +<2 tape marks> cosmetic, not used but this way the tape is easily copied + using any machine you have handy since 2 tape marks + traditionally mean "end of tape" + +Building the DSKDMP tape is the same but substitute dskdmp.rm80 for salv.rm80. + +This directory also contains the other versions of DSKDMP and [N]SALV from +the MINSYS; directory, converted to TM03 magtape format, but since all I +have that works is an RM80 I haven't tested the others so I don't know for +sure that the files aren't mangled and I don't know whether the patch given +below is required for those versions of MARK to work. If you know, tell me! + +DSKDMP and NSALV tapes will help you build a blank disk but you'll still need +to make DUMP tapes of the MINSYS files if you want to load ITS, and you'll +need a lot more files to run and/or rebuild a real system. Writing DUMP tapes +from a non-ITS machine isn't too difficult, send me email and I'll give you +my code. + +*** NOTE *** + +As distributed there is a bug in the salvager, which needs to be patched before +you run MARK. Here's what to do (user input shown in lower case): + +KS10>mt +KS10>USR MOD +ITS MTBOOT.176 +qcnvt/' MOVSI B,-1 +QCNVT+1/ CAMN A,QTRAN(B) came a,qtran(b) +markg +Format pack on unit # + +... and so on, from here on out it's just like what BUILD DOC says. + +Note that the distributed ITS 1644 binaries are built with the tape RH11 at a +non-standard address, and the system will crash if you try to run DUMP w/o +either moving the RH11 or reassembling a new system with the addr fixed. +So either edit SYSTEM; TM03S DEFS4 to change %TMBAS back to 772440 (instead +of 772400), or just delete the file since SYSTEM; TM03S DEFS3 has it right, and +reassemble the system. + +IMPORTANT STUFF THAT APPARENTLY NOT EVERYONE KNOWS: + +Before you go borrowing peripherals off of a VAX or PDP-11, you need to make +sure that your tape drive has the "universal data formatter" board (also known +as the "universal bit fiddler"), since otherwise it won't support 36-bit words +(packed into 5 tape frames each with 4 wasted bits) and you will lose. In +the TM03 formatter this board is M8915-YA, and it's quite rare since VAXen +don't need it. + +You *can* use VAX Massbus disks with the KS since they all support 18-bit mode +and MARK handles the reformatting (rumors of needing an HDA swap are greatly +exaggerated), but with RM drives (including the RM80) you need to add a jumper +or else 18-bit operation will not work correctly. This jumper must connect +pins E06E1 and E06C2 on the RM Adapter backplane, which is the card cage that +goes under the drive in an RM02/03/80 or next to the drive in an RM05. +THIS IS NOT OPTIONAL! + +The RH11s used in the KS10 are not quite vanilla either (naturally), the M7294 +board used in the RH11-AB (used in some PDP-11s and VAXen) is replaced by an +M7294-YA in the RH11C (used in the KS). I'm fairly sure that all the other +parts interchange though so feel free to gut your VAX for spares. + +DRIVES OTHER THAN THE RM80: +RM80s are all I have that works, so I have no way to test the other versions +of the "dskdmp.*" and "salv.*" files in this directory, so I don't know if +the bug in "MARK" is fixed in them. Give it a try... Anyway otherwise the +instructions for making the tapes are the same as for the RM80 versions, as +far as I know RP06 drives need no jumper changes but the RM drives do. + +John Wilson 31-Jan-1995 diff --git a/src/system/bits.117 b/src/system/bits.117 new file mode 100755 index 00000000..fa77889e --- /dev/null +++ b/src/system/bits.117 @@ -0,0 +1,1111 @@ +; -*-MIDAS-*- + +;;; ITS BITS THAT ARE OFTEN NEEDED + +.AUXIL + +;;; CATALOGUE OF RESERVED BIT NAME AND CONSTANT PREFIXES IN ITS + +.SEE %CA ;BITS IN CLRAC FOR CORE LINK DEVICE +.SEE %CB ;BITS FOR CORBLK SYMBOLIC SYSTEM CALL +.SEE %CL ;.CALL ARGUMENT TYPES. +.SEE %CLS ;BITS IN LH OF CLSTB ENTRY +.SEE %DC ;DTE20 IOELEVEN COMMANDS +.SEE %DF ;T-300 FAULT (DSCFLT) +.SEE %DM ;T-300 COMMAND (DSCCMD) +.SEE %DO ;DSK OPEN MODE BITS +.SEE %DP ;DATAPOINT CURSOR CONTROL CONSTANTS +.SEE %DS ;T-300 STATUS (DSCSTS) +.SEE %DT ;DTE20 COMMANDS BITS AND CONSTANTS +.SEE %DV ;BITS IN DEVTAB +.SEE %E ;.CALL AND OPEN ERROR CODES +.SEE %GO ;SUPDUP GRAPHICS PROTOCOL COMMANDS +.SEE %H1 ;RP04 (RH10/RH11) ERROR REGISTER 1 +.SEE %H3 ;RP04 (RH10/RH11) ERROR REGISTER 3 +.SEE %HA ;RP04 (RH10/RH11) ADDRESS REGISTER +.SEE %HC ;RP04 (RH10) CONTROL REGISTER +.SEE %HD ;RH10 ERROR BITS IN DRIVE REGISTERS +.SEE %HI ;RH10 CONI BITS +.SEE %HM ;RP04 (RH10/RH11) COMMAND CONSTANTS +.SEE %HO ;RH10 CONO BITS +.SEE %HR ;RH10 CONTROLLER AND RP04 DRIVE REGISTER NUMBERS + ; OR RH11 UNIBUS REGISTER ADDRESSES +.SEE %HS ;RP04 (RH10/RH11) STATUS REGISTER BITS +.SEE %HW ;FOR KL AND KS, BITS IN RH OF RESULT OF APRID +.SEE %HX ;RH11 BITS IN %HRCS1 +.SEE %HY ;RH11 BITS IN %HRCS2 +.SEE %IL ;Interlan NI1010 bits and constants +.SEE %IOT ;BITS IN IOTTB +.SEE %IR ;BITS IN IP ROUTE ENTRY FLAGS +.SEE %JB ;BITS IN JBWST VARIABLE +.SEE %JG ;BITS IN JOBGET FIRST VALUE +.SEE %JO ;OPCODES IN JOBGET FIRST VALUE +.SEE %JS ;SPECIAL VALUES FOR SPECS +.SEE %KE ;BITS IN KS10 MEMORY STATUS REGISTER (KSECCS) +.SEE %LH ;BITS AND CONSTANTS FOR ACC LH/DH IMP INTERFACE (KS10) +.SEE %MA ;BITS IN MSRAC (MAGTAPE STATUS TABLE) +.SEE %NC ;NETWORK SOCKET CLOSE REASONS +.SEE %NE ;ETHERNET - constants and bits (%EN taken..) +.SEE %NO ;INTERNET - bits for TCPOPN system call +.SEE %NS ;NETWORK SOCKET STATES +.SEE %NT ;INTERNET - TCP channel states (almost = to %NS. See also %NX) +.SEE %NX ;INTERNET - TCP connection close reasons (almost = to %NC) +.SEE %OP ;BITS IN LH OF .OPTION USER VARIABLE +.SEE %PC ;KA10 PC FLAGS +.SEE %PF ;KL10 AND KS10 PAGE FAIL WORD BITS (DEFINITIONS DIFFER + ; BETWEEN MACHINES) +.SEE %PI ;BITS IN PIRQC USER VARIABLE +.SEE %PJ ;BITS IN LH OF PIRQC USER VARIABLE +.SEE %PS ;KL10 AND KS10 PC FLAGS +.SEE %QA ;BITS IN QSRAC (DISK STATUS TABLE) +.SEE %QM ;DISK ACTION MODES IN RH OF QSRAC +.SEE %RL ;BITS FOR COMMANDS TO .REALT UUO +.SEE %SCV ;BITS IN SYSCVL TO CONTROL SYMBOLIC SYSTEM CALLS +.SEE %SS ;STY STATUS BITS IN STYSTS +.SEE %SW ;LH(USWST) BITS +.SEE %SY ;NAMES FOR SQUOZE FLAGS IN SYMBOL TABLES (NOT DEFINED IN ITS) +.SEE %TA ;BITS IN TTYSTA +.SEE %TB ;BITS IN TTYTBL USER VARIABLE +.SEE %TC ;BITS IN TTYCOM +.SEE %TD ;SOFTWARE TTY CURSOR CONTROL CODE CONSTANTS +.SEE %TF ;BITS IN TPFLAG +.SEE %TG ;BITS IN TTYST1 AND TTYST2 +.SEE %TI ;BITS IN LEFT HALF OF TTY INPUT IOCHNM WORD +.SEE %TJ ;BITS IN LH OF TTY OPTPUT IOCHNM +.SEE %TM ;BITS AND CONSTANTS FOR TM03/RH11 TAPE CONTROLLER (KS10) +.SEE %TN ;CONSTANTS FOR TCTYP +.SEE %TO ;BITS IN LEFT HALF OF TTYOPT +.SEE %TP ;BITS IN RIGHT HALF OF TTYOPT +.SEE %TQ ;BITS IN LEFT HALF OF TTYSMT +.SEE %TR ;BITS IN RIGHT HALF OF TTYSMT +.SEE %TS ;BITS IN TTYSTS +.SEE %TT ;BITS IN LEFT HALF OF TTYTYP +.SEE %TX ;ASCII CHARACTER BITS (META, TOP, CONTROL, ETC.) +.SEE %TY ;BITS IN RIGHT HALF OF TTYTYP +.SEE %UB ;BITS IS KS10 UNIBUS STATUS REGISTER (UBASTA) +.SEE %UC ;FOR KL AND KS, BITS IN LH OF RESULT OF APRID +.SEE %UM ;BITS IN UMAPS VARIABLE, AND ARGS TO PGLD, MPLD1, PLD1. +.SEE %UP ;BITS IN KS10 UNIBUS PAGE MAP (WHEN MAP IS READ) (UBAPAG) +.SEE %UQ ;BITS IN KS10 UNIBUS PAGE MAP (WHEN MAP IS WRITTEN) (UBAPAG) +.SEE %UST ;BITS IN USTP VARIABLE. +.SEE %WY ;WHYINT CODES +.SEE $11 ;BYTE POINTERS TO PDP11 FIELDS IN PDP-10 WORDS, ON AI-KA + ;10-11 INTERFACE. +.SEE ..R ;ARGUMENT CODES FOR .BREAK 12, READING. +.SEE ..S ;ARGUMENT CODES FOR .BREAK 12, WRITING. +.SEE .XC ;INTERNET - TCP connection close reasons (almost = to %NC) + ; (Old names. Use %NX instead.) + +.SEE MMP ;BITS IN MMP ENTRY 1ST WORD L.H. +.SEE OPTTRP ;BITS IN LH OF .OPTION VARIABLE + ; (Old names. Use %OP instead) +.SEE SCL ;BITS IN LH OF SUPCOR +.SEE SCR ;BITS IN RH OF SUPCOR + +IFNDEF DEFSYM,[ ;ALLOW USER TO USE SYMBOLS IN OTHER WAYS IF HE WISHES. + ;BUT NORMALLY, DEFSYM FOO==BAR DOES FOO==BAR WITH ERROR CHECK. +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,.QUOTE/.QUOTE/X +.ELSE [ + $$TEM1==Z + .QUOTE/.QUOTE/X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` +] +.ISTOP +TERMIN TERMIN + +IFLE .MLLIT,.ERR .MLLIT MUST BE 1; SETTING IT TO 1. +.MLLIT==1 +$$TEMP==1 +] +.ELSE $$TEMP==0 + +;OPEN-FAILURE CODE NAMES. +;3RD AND 4TH LETTER: "TM" = "TOO MANY", "BD" = "BAD OR ILLEGAL", +; "TF" = "TOO FEW", "RO" = "READ-ONLY", "NA" = "NOT AVAILABLE", +; "NS" = "NO SUCH", "EX" = "ALREADY EXISTS", "FL" = "FULL", +; "NR" = "NOT READY". +;5TH AND 6TH LETTER: "JB" = "JOB", "RG" = "ARG", "DV" = "DEVICE", +; "DR" = "DIRECTORY", "IO" = "DIRECTION", "FL" = "FILE", +; "FN" = "FILE NAME" +DEFSYM %E==:-100 ;BIT TYPEOUT MASK +DEFSYM %ENSDV==:1 ;NO SUCH DEVICE +DEFSYM %ENSIO==:2 ;WRONG DIRECTION +DEFSYM %ETMTR==:3 ;TOO MANY TRANSLATIONS +DEFSYM %ENSFL==:4 ;FILE NOT FOUND +DEFSYM %EFLDR==:5 ;DIRECTORY FULL +DEFSYM %EFLDV==:6 ;DEVICE FULL +DEFSYM %ENRDV==:7 ;DEVICE NOT READY +DEFSYM %ENADV==:10 ;DEVICE NOT AVAILABLE +DEFSYM %EBDFN==:11 ;ILLEGAL FILE NAME +DEFSYM %ENSMD==:12 ;MODE NOT AVAILABLE +DEFSYM %EEXFL==:13 ;FILE ALREADY EXISTS +DEFSYM %EBDCH==:14 ;BAD CHANNEL NUMBER +DEFSYM %ETMRG==:15 ;TOO MANY ARGUMENTS (CALL) +DEFSYM %ENAPK==:16 ;PACK NOT MOUNTED + ;17 FORMERLY DIRECTORY NOT AVAIL +DEFSYM %ENSDR==:20 ;NON-EXISTENT DIRECTORY +DEFSYM %ELCDV==:21 ;LOCAL DEVICE ONLY +DEFSYM %ESCO==: 22 ;SELF-CONTRADICTORY OPEN +DEFSYM %ENAFL==:23 ;FILE LOCKED +DEFSYM %ETMDR==:24 ;M.F.D. FULL +DEFSYM %EMCHN==:25 ;DEVICE NOT ASSIGNABLE TO THIS PROCESSOR +DEFSYM %ERODV==:26 ;DEVICE WRITE-LOCKED +DEFSYM %ETMLK==:27 ;LINK DEPTH EXCEEDED +DEFSYM %ETFRG==:30 ;TOO FEW ARGUMENTS (CALL) +DEFSYM %EROJB==:31 ;CAN'T MODIFY JOB +DEFSYM %EROPG==:32 ;CAN'T GET THAT ACCESS TO PAGE +DEFSYM %EBDRG==:33 ;MEANINGLESS ARGS +DEFSYM %EBDDV==:34 ;WRONG TYPE DEVICE +DEFSYM %ENSJB==:35 ;NO SUCH JOB +DEFSYM %EBOJ==: 36 ;VALID CLEAR OR STORED SET +DEFSYM %ENACR==:37 ;NO CORE AVAILABLE +DEFSYM %ETOP==: 40 ;NOT TOP LEVEL +DEFSYM %ENAPP==:41 ;OTHER END OF PIPELINE GONE OR NOT OPEN +DEFSYM %ENAJB==:42 ;JOB GONE OR GOING AWAY +DEFSYM %ENSCL==:43 ;ILLEGAL SYSTEM CALL NAME +DEFSYM %ENSCH==:44 ;CHANNEL NOT OPEN +DEFSYM %ENRBF==:45 ;INPUT BUFFER EMPTY OR OUTPUT BUFFER FULL +DEFSYM %EBDFL==:46 ;UNRECOGNIZABLE FILE (LOAD) +DEFSYM %EBDLK==:47 ;LINK TO NON-EXISTENT FILE + +NOPNLS==:47 ;NO DEFSYM BECAUSE THIS SYMBOL IS NOT TO BE PREDEFINED TO USERS + +; BITS IN .PIRQC USER VARIABLE - FIRST-WORD INTERRUPTS +; CLASSES ARE: +; [1] STOPS JOB AND INTERRUPTS SUPERIOR (FATAL INTR) +; [2] STOPS JOB AND INTERRUPTS SUPERIOR UNLESS ENABLED +; [3] DOES NOTHING UNLESS ENABLED +; BITS IN THE LH HAVE TWO NAMES: %PI... AS A BIT IN THE WORD, +; AND %PJ... SHIFTED DOWN BY 18. BITS. + +.SEE PIRQC + +DEFSYM %PI==:525252,,525252 ;FOR BIT-TYPEOUT MODE +DEFSYM %PIRLT==:200000,, ;REAL-TIME TIMER WENT OFF [3] +DEFSYM %PIRUN==:100000,, ;RUN-TIME TIMER WENT OFF [3] +DEFSYM %PINXI==:40000,, ;NON-EX IO REG (KS10 UNIBUS) [2] +DEFSYM %PIJST==:20000,, ;JOB STATUS DISPLAY REQUEST [3] +DEFSYM %PIDCL==:10000,, ;DEFERRED CALL [1] +DEFSYM %PIATY==:4000,, ;WAS JUST GIVEN THE TTY [3] +DEFSYM %PITTY==:2000,, ;DON'T HAVE TTY (SEE %TBINT) [2] +DEFSYM %PIPAR==:1000,, ;MEMORY PARITY ERROR [2] +DEFSYM %PIFOV==:400,, ;FLOATING OVERFLOW [3] +DEFSYM %PIWRO==:200,, ;WRITE IN READ-ONLY PAGE [2] +DEFSYM %PIFET==:100,, ;FETCHED INSN FROM IMPURE PAGE [2] +DEFSYM %PITRP==:40,, ;SYSTEM UUO IN TRAP MODE [1] +DEFSYM %PIDBG==:2,, ;SYSTEM BEING DEBUGGED STATE CHG[3] +DEFSYM %PILOS==:1,, ;.LOSE INSTRUCTION EXECUTED [2] +DEFSYM %PICLI==:400000 ;CLI DEVICE OPENED TO THIS JOB [3] +DEFSYM %PIPDL==:200000 ;PUSHDOWN LIST OVERFLOW [3] +DEFSYM %PILTP==:100000 ;LIGHT PEN [3] +DEFSYM %PIMAR==:40000 ;MAR ADDRESS TRAP [2] +DEFSYM %PIMPV==:20000 ;MEMORY PROTECTION VIOLATION [2] +DEFSYM %PICLK==:10000 ;SLOW (1/2 SEC) CLOCK [3] +DEFSYM %PI1PR==:4000 ;SINGLE-INSTRUCTION PROCEED [1] +DEFSYM %PIBRK==:2000 ;.BREAK INSTRUCTION EXECUTED [1] +DEFSYM %PIOOB==:1000 ;ADDRESS OUT OF BOUNDS [2] +DEFSYM %PIIOC==:400 ;I/O CHANNEL ERROR [2] +DEFSYM %PIVAL==:200 ;.VALUE INSTRUCTION EXECUTED [1] +DEFSYM %PIDWN==:100 ;SYSTEM GOING DOWN STATUS CHANGE[3] +DEFSYM %PIILO==:40 ;ILLEGAL OPERATION (E.G. UUO) [2] +DEFSYM %PIDIS==:20 ;DISPLAY MEMORY PROTECT [2] +DEFSYM %PIARO==:10 ;ARITHMETIC OVERFLOW [3] +DEFSYM %PIB42==:4 ;BAD LOCATION 42 [1] +DEFSYM %PIC.Z==:2 ;^Z OR CALL TYPED [1] +DEFSYM %PITYI==:1 ;TTY INPUT (OBSOLETE) [3] + +DEFSYM %PJ==:1,,525252 ;BIT TYPEOUT MASK +DEFSYM %PJRLT==:200000 ;REAL-TIME TIMER WENT OFF [3] +DEFSYM %PJRUN==:100000 ;RUN-TIME TIMER WENT OFF [3] +DEFSYM %PJNXI==:40000 ;NON-EX IO REG (KS10 UNIBUS) [2] +DEFSYM %PJJST==:20000 ;JOB STATUS DISPLAY REQUEST [3] +DEFSYM %PJDCL==:10000 ;DEFERRED CALL [1] +DEFSYM %PJATY==:4000 ;WAS JUST GIVEN THE TTY [3] +DEFSYM %PJTTY==:2000 ;DON'T HAVE TTY (SEE %TBINT) [2] +DEFSYM %PJPAR==:1000 ;MEMORY PARITY ERROR [2] +DEFSYM %PJFOV==:400 ;FLOATING OVERFLOW [3] +DEFSYM %PJWRO==:200 ;WRITE IN READ-ONLY PAGE [2] +DEFSYM %PJFET==:100 ;FETCHED INSN FROM IMPURE PAGE [2] +DEFSYM %PJTRP==:40 ;SYSTEM UUO IN TRAP MODE [1] +DEFSYM %PJDBG==:2 ;SYSTEM BEING DEBUGGED STATE CHG[3] +DEFSYM %PJLOS==:1 ;.LOSE INSTRUCTION EXECUTED [2] + +;;; PC FLAGS (LEFT HALF) + +DEFSYM %PC==:1,,525240 ;FOR BIT-TYPEOUT MODE +DEFSYM %PCARO==:400000 ;ARITHMETIC OVERFLOW +DEFSYM %PCCR0==:200000 ;CARRY OUT OF BIT 0 +DEFSYM %PCCR1==:100000 ;CARRY OUT OF BIT 1 +DEFSYM %PCFOV==:040000 ;FLOATING OVERFLOW +DEFSYM %PCFPD==:020000 ;FIRST PART DONE + ; (E.G. ILDB PTR INCREMENTED, BYTE NOT FETCHED) +DEFSYM %PCUSR==:010000 ;USER MODE +DEFSYM %PCUIO==:004000 ;USER I/O +DEFSYM %PCPUR==:002000 ;GIVE %PIFET IF FETCH INSTR FROM WRITABLE + ; PAGE (KA-10 ONLY) +DEFSYM %PCSPC==:001000 ;"SPECIAL" - OBSOLETE +DEFSYM %PC1PR==:000400 ;1 PROCEED - GIVE %PI1PR AFTER ONE INSTRUCTION +DEFSYM %PCX17==:000200 ;XR 17 = PC (AI-KA ONLY) +DEFSYM %PCFXU==:000100 ;FLOATING EXPONENT UNDERFLOW +DEFSYM %PCDIV==:000040 ;DIVIDE ERROR + +;;; PC FLAGS FOR KL-10 AND KS-10 + +DEFSYM %PS==:1,,525240 ;FOR BIT-TYPEOUT MODE +DEFSYM %PSARO==:400000 ;ARITHMETIC OVERFLOW +DEFSYM %PSPCP==:400000 ;PREVIOUS CONTEXT PUBLIC - PXCT CAN'T + ;REFERENCE CONCEALED PAGE THIS APPLIES ONLY + ;IN EXEC MODE. IN USER MODE AND ON KS IS + ;STILL %PSARO. +DEFSYM %PSCR0==:200000 ;CARRY OUT OF BIT 0 +DEFSYM %PSCR1==:100000 ;CARRY OUT OF BIT 1 +DEFSYM %PSFOV==:040000 ;FLOATING OVERFLOW +DEFSYM %PSFPD==:020000 ;FIRST PART DONE (E.G. ILDB PTR + ;INCREMENTED, BYTE NOT FETCHED) +DEFSYM %PSUSR==:010000 ;USER MODE ; 0 0 1 1 +DEFSYM %PSUIO==:004000 ;USER I/O ;; KERNEL SUPERV CONCEAL PUBLIC +DEFSYM %PSPUB==:002000 ;PUBLIC MODE ; 0 1 0 1 + ;%PSPUB ALWAYS 0 ON KS. +DEFSYM %PSPCU==:004000 ;IN EXEC MODE %PSUIO MEANS PREVIOUS CONTEXT + ;USER. +DEFSYM %PSINH==:001000 ;INHIBIT ADDRESS BREAK & TRAP 3 (TURNS OFF + ;AFTER 1 INST) %PSINH ALWAYS 0 ON KS. +DEFSYM %PSTR2==:000400 ;TRAP 2 (PDL OVERFLOW) ;TRAP 1 PLUS TRAP 2 +DEFSYM %PSTR1==:000200 ;TRAP 1 (ARITH OVERFLOW) ; MAKES TRAP 3 + ; (ONE PROCEED + ; ON KL) +DEFSYM %PSFXU==:000100 ;FLOATING EXPONENT UNDERFLOW +DEFSYM %PSDIV==:000040 ;DIVIDE ERROR + +DEFSYM %PS1PR==:001600 ;BITS TO SET TO CAUSE A 1-PROCEED ON KL. + +; INTERNET and ARPANET + +.SEE NETRFC +DEFSYM %NQ==:1,,525252 ; Control bits for NETRFC system call +DEFSYM %NQREF==:1 ; Refuse this connection request. Arg 2 must be a + ; previously returned RFC identifier. + +.SEE TCPOPN +DEFSYM %NO==:1,,525252 ; Control bits for TCPOPN system call +DEFSYM %NOLSN==:100 ; Listen mode - wait for SYN (request for conn) + +DEFSYM %NS==:,-1 ; NCP (old ARPANET) SOCKET STATES +DEFSYM %NSCLS==:0 ;CLS RECEIVED. CONNECTION CLOSED (IMSCLS GIVES REASON) +DEFSYM %NSLSN==:1 ;LISTENING FOR RFC +DEFSYM %NSRFC==:2 ;RFC RECEIVED WHILE IN LISTENING STATE +DEFSYM %NSRCL==:3 ;CLS RECEIVED WHILE IN RFC RECEIVED STATE +DEFSYM %NSRFS==:4 ;RFC SENT +DEFSYM %NSOPN==:5 ;CONNECTION OPEN +DEFSYM %NSRFN==:6 ;RFNM WAIT ON WRITE LINK +DEFSYM %NSCLW==:7 ;CLS SENT. WAITING FOR MATCHING CLS +DEFSYM %NSCLI==:10 ;CLS RECEIVED BUT INPUT STILL AVAILABLE +DEFSYM %NSINP==:11 ;INPUT AVAILABLE + +DEFSYM %NT==:,,-1 ; TCP port states as seen by user + ; Legend: - Pre-Open, * Open, + Post-open, ? impossible. + ; I = can read, O = can write. + ; Note that the input and output channels for a TCP connection + ; will usually have different states. Also, note that + ; for all practical purposes, %NT and %NS symbols with the same + ; value have the same meaning. SYN = Request for connection. + ; In Out +DEFSYM %NTCLS==:0 ; - - Closed (reason available from WHYINT) +DEFSYM %NTLSN==:1 ; - - Listening for a SYN +DEFSYM %NTSYR==:2 ; - - SYN received +DEFSYM %NTCLU==:3 ; + ? Being closed by fgn host +DEFSYM %NTSYN==:4 ; - - SYN sent, waiting for response +DEFSYM %NTOPN==:5 ; *I *O Open +DEFSYM %NTWRT==:6 ; ? *O Output buffer full +DEFSYM %NTCLX==:7 ; ? + Being closed by user +DEFSYM %NTCLI==:10 ; +I ? Closing/closed, input still available +DEFSYM %NTINP==:11 ; *I ? Open, input available + + +DEFSYM %NC==:,-1 ; NCP (old ARPANET) CLOSE REASONS (IN IMSCLS) +DEFSYM %NCNTO==:0 ;NEVER OPENED +DEFSYM %NCUSR==:1 ;CLSED BY USER +DEFSYM %NCFRN==:2 ;CLSED BY FOREIGN HOST +DEFSYM %NCRST==:3 ;RST +DEFSYM %NCDED==:4 ;HOST DEAD +DEFSYM %NCINC==:5 ;INCOMPLETE TRANSMISSION +DEFSYM %NCBYT==:6 ;BYTE SIZE MISMATCH. +DEFSYM %NCNCP==:7 ;OUR NCP WENT DOWN. +DEFSYM %NCRFS==:10 ;REQUEST FOR CONNECTION REFUSED + +;;; .XC is being phased out for the name %NX instead. +;;; The .XC symbols will be flushed "soon". + +DEFSYM .XC==,,-1 ; TCP port cls reasons (valid for ALL post-open states) + ; Note .XC and %NC symbols with the same value + ; have pretty much the same meanings. +DEFSYM .XCNTO==:0 ; Never opened +DEFSYM .XCUSR==:1 ; Closed by user +DEFSYM .XCFRN==:2 ; Closed by foreign host +DEFSYM .XCRST==:3 ; Fgn host refused or aborted connection. +DEFSYM .XCDED==:4 ; Fgn host dead (not used yet) +DEFSYM .XCINC==:5 ; Incomplete transmission (retransmission timeout) + ; This is the usual indication when a foreign host + ; or the intervening network crashes. + ; ==:6 ; Byte size mismatch - can't happen +DEFSYM .XCNCP==:7 ; Local TCP went down (not used yet) +DEFSYM .XCRFS==:10 ; RST received while in SYN-SENT state. + ; (foreign host refused connection) + +DEFSYM %NX==,,-1 ; TCP port cls reasons (valid for ALL post-open states) + ; Note %NX and %NC symbols with the same value + ; have pretty much the same meanings. +DEFSYM %NXNTO==:0 ; Never opened +DEFSYM %NXUSR==:1 ; Closed by user +DEFSYM %NXFRN==:2 ; Closed by foreign host +DEFSYM %NXRST==:3 ; Fgn host refused or aborted connection. +DEFSYM %NXDED==:4 ; Fgn host dead (not used yet) +DEFSYM %NXINC==:5 ; Incomplete transmission (retransmission timeout) + ; This is the usual indication when a foreign host + ; or the intervening network crashes. + ; ==:6 ; Byte size mismatch - can't happen +DEFSYM %NXNCP==:7 ; Local TCP went down (not used yet) +DEFSYM %NXRFS==:10 ; RST received while in SYN-SENT state. + ; (foreign host refused connection) + + + +;;; BITS IN RESULT OF APRID (BLKI APR,) ON KL-10 AND KS-10 +DEFSYM %UC==:1,,525000 ;FOR BIT-TYPEOUT MODE +DEFSYM $UCOPT==:331100 ;MICROCODE OPTIONS: +DEFSYM %UCKLP==:400000 ; KL-10-STYLE PAGING +DEFSYM %UCITS==:20000 ; ITS-STYLE PAGING +DEFSYM %UCTRK==:1000 ; TRACKS FEATURE +DEFSYM $UCVRS==:221100 ;MICROCODE VERSION NUMBER +DEFSYM %UCVRS==:1 +DEFSYM %HW==:0,,527777 ;FOR BIT-TYPEOUT MODE +DEFSYM $HWOPT==:140600 ;HARDWARE OPTIONS +DEFSYM $HWSER==:001400 ;PROCESSOR SERIAL NUMBER + + +;;; .CALL ARGUMENT TYPES +DEFSYM %CL==:1,,400777 +DEFSYM %CLIN==:0 ;INPUT ARGUMENT +DEFSYM %CLIMM==:1000 ;IMMEDIATE ARGUMENT +DEFSYM %CLOUT==:2000 ;OUTPUT ARGUMENT +DEFSYM %CLERR==:3000 ;ERROR CODE OUTPUT ARGUMENT +DEFSYM %CLBTW==:4000 ;DIRECT CONTROL BITS +DEFSYM %CLBIT==:5000 ;IMMEDIATE CONTROL BITS + + +;;; CONTROL BITS FOR CORBLK SYSTEM CALL + +.SEE NCORBLK +DEFSYM %CB==:0,,525252 ;FOR BIT-TYPEOUT MODE +DEFSYM %CBWRT==:400000 ;TRY FOR WRITE ACCESS, OK IF CAN'T GET IT +DEFSYM %CBRED==:200000 ;TRY FOR READ ACCESS, OK IF CAN'T GET IT +DEFSYM %CBNDW==:100000 ;NEED WRITE ACCESS, FAIL IF CAN'T GET IT +DEFSYM %CBPUB==:040000 ;MAKE PAGE PUBLIC, REQUIRES WRITE ACCESS +DEFSYM %CBPRV==:020000 ;MAKE PAGE PRIVATE, REQUIRES WRITE ACCESS +DEFSYM %CBNDR==:010000 ;NEED READ ACCESS, FAIL IF CAN'T GET IT +DEFSYM %CBCPY==:004000 ;MAKE A COPY (DISK FILES ONLY) +DEFSYM %CBLOK==:002000 ;LOCK PAGE IN CORE. +DEFSYM %CBULK==:001000 ;UNLOCK PAGE (ALLOW SWAP-OUT) +DEFSYM %CBSLO==:000400 ;MAY ONLY RESIDE IN SLOWEST MEMORY +DEFSYM %CBUSL==:000200 ;ALLOWS USE OF ANY MEMORY. + ;ABOVE BITS ALL ZERO MEANS DELETE PAGE FROM MAP + +;;; SPECIAL VALUES FOR SPECS + +DEFSYM %JS==:,,-1 +DEFSYM %JSELF==:,,-1 ;SELF (ALL SPECS) +DEFSYM %JSTVB==:,,-2 ;11TV BUFFER (CORBLK) +DEFSYM %JSNUL==:,,-3 ;NULL JOB (KLPERF) +DEFSYM %JSALL==:,,-4 ;ALL JOBS (KLPERF) +DEFSYM %JSNEW==:,,-5 ;FRESH PAGE (CORBLK) +DEFSYM %JSABS==:,,-6 ;ABSOLUTE CORE (CORBLK) +DEFSYM %JSNUM==:400000 ;THIS + JOB # => THAT JOB (ALL SPECS) +DEFSYM %JSSIX==:400376 ;PDP6 IS USER NUMBER 376 +DEFSYM %JSSUP==:400377 ;SUPERIOR (ALL SPECS) +;A SPEC MAY ALSO BE THE NUMBER OF A CHANNEL OPEN ON USR:, BOJ:, OR STY: + +;;; CONTROL BITS FOR ".REALT AC," UUO. +;;; FLAG BITS ARE IN LH(AC). + +.SEE AREALT +DEFSYM %RL==:1,,525252 ;FOR BIT-TYPEOUT MODE +DEFSYM %RLFLS==:400000 ;FLUSH OLD TIMER +DEFSYM %RLSET==:200000 ;SET NEW CLOCK RATE +DEFSYM %RLUSR==:100000 ;TRY TO SEIZE REAL TIME USER FACILITY +DEFSYM %RLPSD==:020000 ;ONLY WANT PSEUDO REAL TIME +DEFSYM %RLNPS==:040000 ;CANNOT ACCEPT PSEUDO REAL TIME +DEFSYM %RLBLK==:010000 ;PROGRAM TO BE BLOCKED EXCEPT FOR HIGH PRIORITY + ; PHASE OR INTERRUPT LEVEL +DEFSYM %RLGET==:004000 ;GET PREVIOUS STATUS IN WORDS 3+4 + ;REMAINING BITS MUST BE ZERO + +;;; BITS OF .OPTION USER VARIABLE. + +.SEE OPTION +DEFSYM OPTTRP==:400000 ;ALL SYSTEM UUOS TRAP TO SUPERIOR (%PITRP) +DEFSYM OPTDEC==:100000 ;UUOS 40,41 AND 47 ARE USER UUOS + ;THE FOLLOWING 3 BITS ARE NOT USED BY SYSTEM. + ;THEY ARE FOR COMMUNICATION FROM SUPERIOR. +DEFSYM OPTCMD==:040000 ;SUPERIOR SAYS IT HAS CMD STRING - DO + ; .BREAK 12,. +DEFSYM OPTBRK==:020000 ;SUPERIOR SAYS IT HANDLES ALL .BREAK'S. +DEFSYM OPTDDT==:010000 ;SUPERIOR SAYS HE'S DDT. (CLEARED WHEN DDT + ; DISOWNS) +DEFSYM OPTINT==:004000 ;NEW STYLE VECTORING INTS. +DEFSYM OPTOJB==:002000 ;ALLOW OTHER JOBS TO OPEN ME ON THE OJB + ; DEVICE. OPENING ME ON OJB DEVICE TURNS + ; ME INTO A JOB DEVICE. +DEFSYM OPTLOK==:001000 ;ENABLE SWITCH-UNLOCKING FEATURE + .SEE IODCSW ; SEE COMMENT THERE FOR DESCRIPTION. +DEFSYM OPTLIV==:000400 ;DON'T KILL THIS TOP LEVEL JOB WHEN SYS + ; GOES DOWN. +DEFSYM OPTOPC==:000200 ;INTERRUPTS THAT ABORT AN INSTRUCTION + ; SHOULD LEAVE THE PC POINTING TO THAT + ; INSTRUCTION (OTHERWISE IT GETS AOS'ED) +DEFSYM OPTLSP==:000100 ;SUPERIOR SAYS HE'S LISP +DEFSYM OPTLKF==:000040 ;UNLOCK LOCKS ON FATAL INTERRUPT IN + .SEE SYSDT ; TOP-LEVEL NON-DISOWNED JOB. + +;;; NEW NAMES FOR BITS IN LH(.OPTION) + +DEFSYM %OP==:525252(1) ;FOR BIT-TYPEOUT MODE +DEFSYM %OPTRP==:400000 ;ALL SYSTEM UUOS TRAP TO SUPERIOR (%PITRP) +DEFSYM %OPDEC==:100000 ;UUOS 40,41 AND 47 ARE USER UUOS + ;THE FOLLOWING 3 BITS ARE NOT USED BY SYSTEM. + ;THEY ARE FOR COMMUNICATION FROM SUPERIOR. +DEFSYM %OPCMD==:040000 ;SUPERIOR SAYS IT HAS CMD STRING - DO + ; .BREAK 12,. +DEFSYM %OPBRK==:020000 ;SUPERIOR SAYS IT HANDLES ALL .BREAK'S. +DEFSYM %OPDDT==:010000 ;SUPERIOR SAYS HE'S DDT. (CLEARED WHEN DDT + ; DISOWNS) +DEFSYM %OPINT==:004000 ;NEW STYLE VECTORING INTS. +DEFSYM %OPOJB==:002000 ;ALLOW OTHER JOBS TO OPEN ME ON THE OJB + ; DEVICE. OPENING ME ON OJB DEVICE TURNS + ; ME INTO A JOB DEVICE. +DEFSYM %OPLOK==:001000 ;ENABLE SWITCH-UNLOCKING FEATURE + .SEE IODCSW ; SEE COMMENT THERE FOR DESCRIPTION. +DEFSYM %OPLIV==:000400 ;DON'T KILL THIS TOP LEVEL JOB WHEN SYS + ; GOES DOWN. +DEFSYM %OPOPC==:000200 ;INTERRUPTS THAT ABORT AN INSTRUCTION + ; SHOULD LEAVE THE PC POINTING TO THAT + ; INSTRUCTION (OTHERWISE IT GETS AOS'ED) +DEFSYM %OPLSP==:000100 ;SUPERIOR SAYS HE'S LISP +DEFSYM %OPLKF==:000040 ;UNLOCK LOCKS ON FATAL INTERRUPT IN + .SEE SYSDT ; TOP-LEVEL NON-DISOWNED JOB. + +;;; LOSING ERROR CODES + +DEFSYM %LS==:777400 ;RH OF .LOSE INSTRUCTION +DEFSYM %LSINT==:1 +DEFSYM %LSSYS==:1000 ;INTERPRET LAST OPEN LOSS CODE, USING .BCHN +DEFSYM %LSFIL==:1400 ; DO THAT AND PRINT FILE NAMES FROM CALL'S CHNL + +;;; FIRST RESULT OF .CALL WHYINT + +DEFSYM %WY==:,-1 +DEFSYM %WYTYI==:1 ;TTY INPUT +DEFSYM %WYTYO==:2 ;TTY OUTPUT +DEFSYM %WYSTI==:3 ;STY INPUT +DEFSYM %WYSTO==:4 ;STY OUTPUT +DEFSYM %WYNET==:5 ;ARPANET (NCP) +DEFSYM %WYCHA==:6 ;CHAOS NET +DEFSYM %WYTCP==:7 ;INTERNET (TCP) +DEFSYM %WYUBI==:10 ;UNIBUS INTERRUPT + +;I/O MODES FOR OPENS. + +DEFSYM .UAI==0 ;UNIT ASCII INPUT. +DEFSYM .UAO==1 ;UNIT ASCII OUTPUT. +DEFSYM .BAI==2 ;BLOCK ASCII INPUT. +DEFSYM .BAO==3 ;BLOCK ASCII OUTPUT. +DEFSYM .UII==4 ;UNIT IMAGE INPUT. +DEFSYM .UIO==5 ;UNIT IMAGE OUTPUT. +DEFSYM .BII==6 ;BLOCK IMAGE INPUT. +DEFSYM .BIO==7 ;BLOCK IMAGE OUTPUT. + +;OPEN BITS FOR DEVICE DSK: + +DEFSYM %DO==1,,525252 ;BIT TYPEOUT MASK +DEFSYM %DOOUT==1 +DEFSYM %DOBLK==2 +DEFSYM %DOIMG==4 +DEFSYM %DONRF==10 ;DON'T SET REFERENCE DATE. +DEFSYM %DONLK==20 ;DON'T CHASE LINKS. +DEFSYM %DORWT==40 ;ON OUTPUT OPEN, MAKES WOULD-BE READERS + ;WAIT TILL WE CLOSE. +DEFSYM %DOWOV==100000 ;WRITE OVER (USE WITH %DOOUT, TO OVERWRITE + ;EXISTING FILE). + +;ARGUMENT CODES FOR .BREAK 12,'S. +;..R AND ..S ARE BIT TYPEOUT MASKS, NOT MADE PREDEFINED TO MIDAS +;SINCE THEY ARE USEFUL ONLY IN DDT, WHICH DEFINES THEM ITSELF. + +..R==0 ;(FOR .SEE) +DEFSYM ..RSTART==1 ;READ STARTING ADDRESS +DEFSYM ..RLFILE==2 ;READ LOADED FILE'S NAMES +DEFSYM ..RSTP==3 ;READ SYMBOL TABLE POINTER +DEFSYM ..RSYM==4 ;READ VALUE OF SYMBOL. +DEFSYM ..RJCL==5 ;READ JOB COMMAND LINE. +DEFSYM ..RPFILE==6 ;READ :PRINT FILENAME DEFAULTS. +DEFSYM ..RSTB==7 ;READ WHOLE SYMBOL TABLE. +DEFSYM ..RCONV==10 ;READ NAME OF SYMBOL CLOSEST IN VALUE TO + ; ARGUMENT. +DEFSYM ..RLJB==13 ;READ IDX OF PREVIOUSLY CURRENT JOB. +DEFSYM ..RRND==14 ;READ RANDOM JOB-SPECIFIC BITS. +DEFSYM ..RPUR==15 ;UNPURIFY PAGE +DEFSYM ..RHSNAME==16 ;ASK SUPERIOR TO LOOKUP AN HSNAME FROM XUNAME +DEFSYM ..RMAIL==17 ;ASK A SUPERIOR TO LOOKUP USER'S MAIL FILE NAME + +..S==0 ;(FOR .SEE) +DEFSYM ..SSTART==400001 ;SET STARTING ADDRESS +DEFSYM ..SLFILE==400002 ;SET LOADED FILE'S NAMES +DEFSYM ..SSYM==400004 ;SET VALUE OF SYMBOL. +DEFSYM ..SJCL==400005 ;CLEAR JOB COMMAND LINE. +DEFSYM ..SPFILE==400006 ;SET :PRINT FILENAME DEFAULTS. +DEFSYM ..SSTB==400007 ;PASS WHOLE SYMBOL TABLE TO SUPERIOR. +DEFSYM ..SRND==400014 ;SET RANDOM JOB-SPECIFIC BITS. +DEFSYM ..SPUR==400015 ;SAME AS ..RPUR + +;.CALL JOBGET +;ARG 1 - BOJ CHNL +;UP TO SIX WDS RETURNED +;WD1 BITS: +DEFSYM %JG==:1,,525252 + ;4.9-4.7 => IMAGE/ASCII, BLOCK/UNIT, OUTPUT/INPUT + ; 4.9-4.7 SHOULDN'T BE USED, SINCE THE FULL MODE IS IN + ; WD7 ON AN OPEN +DEFSYM %JGCLS==:40000 ;4.6 => CLOSE (NOTE 4.5 USED TO BE A CLS BIT ALSO) +DEFSYM %JGSIO==:1000 ;4.1 => SIOT (ONLY IF OPCODE = 1) +DEFSYM %JGFPD==:200 ;3.8 => THIS CALL WAS PCLSRED AND IS RESTARTING +;1.4-1.1 => TYPE OF OPERATION +DEFSYM %JO==:,,-1 +DEFSYM %JOOPN==:0 ;OPEN +DEFSYM %JOIOT==:1 ;IOT/SIOT +DEFSYM %JOLNK==:2 ;MLINK +DEFSYM %JORST==:3 ;RESET +DEFSYM %JORCH==:4 ;RCHST +DEFSYM %JOACC==:5 ;ACCESS +DEFSYM %JORNM==:6 ;FDELE (DELETE OR RENAME) +DEFSYM %JORWO==:7 ;FDELE (RENAME WHILE OPEN) +DEFSYM %JOCAL==:10 ;SYMBOLIC .CALL + +;MODE BITS FOR TTY OPENS: +;3.1 0 -> IN 1 -> OUT +;3.2 0 -> UNIT 1 -> BLOCK + +;OUTPUT +;3.3 => IMAGE MODE (SET ALL %TGIMG BITS IN TTYST1 AND TTYST2) +;3.4 0 -> NORMAL 1 -> ECHO MODE OUTPUT (SET %TJECH, %TJPP2, %TJMOR). +;3.5 0 -> NORMAL 1 -> DISPLAYMODE, LOOK FOR ^P (SET %TJDIS). +;3.6 0 -> NORMAL 1 -> SUPER-IMAGE OUTPUT (SET %TJSIO). +;OUTPUT IOCHNM BITS MAY ALSO BE SPECIFIED, EXCEPT FOR +;%TJCNS, %TJCP1, AND %TJCP2 + +;INPUT +;3.3 => IMAGE MODE (CLEAR ALL ECHO BITS IN TTYST1, TTYST2). +;3.4 => "DDT" (DON'T ECHO CR, LF, TAB) +;3.6 => WANT 3 LINES IN ECHO AREA. +;INPUT IOCHNM BITS MAY ALSO BE SPECIFIED, EXCEPT FOR %TICNS. + +;BITS 3.4 AND 3.6 ON INPUT, AND BIT 3.3, HAVE EFFECT +;ONLY ON THE FIRST OPEN IN EITHER DIRECTION. +;(THEY ARE OBSOLETED BY THE TTYSET SYSTEM CALL) + +;BITS IN LH OF A TTY CHANNEL IOCHNM WORD +;THESE BITS MAY BE TEMPORARILY COMPLEMENTED BY SPECIFYING +;THEM IN THE CONTROL-BIT ARGUMENT TO A SYMBOLIC IOT +;(EXCEPT FOR %TICNS AND $TIIDX). +DEFSYM %TI==:1,,525277 ;BIT TYPEOUT MASK +DEFSYM %TJ==:1,,525277 ;BIT TYPEOUT MASK + +DEFSYM %TICNS==:400000 ;4.9 1-> CONSOLE 0 -> DEVICE +DEFSYM %TJCNS==:400000 ;4.9 1-> CONSOLE 0 -> DEVICE + +;THE FOLLOWING INTERPRETATIONS OF BITS ARE FOR OUTPUT ONLY. +DEFSYM %TJCP1==:200000 ;^P-CODE ANTICIPATION STATE. +DEFSYM %TJCP2==:100000 ; ". 0=>NORMAL, 1=> CHAR AFTER ^P, 2=> ^PH, 3=>^PV. +DEFSYM %TJECH==:40000 ;SET => ECHO MODE OUTPUT.-MODE OUTPUT (ALL CHARS + ; OUTPUT THE WAY THEY WOULD BE ECHOED) +DEFSYM %TJCTN==:20000 ;SET => DON'T DO LINE-CONTINUATION. +DEFSYM %TJSTP==:10000 ;SET => THIS CHANNEL IS HUNG IN **MORE**. +DEFSYM %TJDIS==:4000 ;SET => LOOK FOR ^P CODES. +DEFSYM %TJSIO==:2000 ;SET => SUPERIMAGE OUTPUT, NO PADDING OR CURSOR CTL. +DEFSYM %TJMOR==:1000 ;SET => DON'T DO **MORE** PROCESSING. +DEFSYM %TJPP2==:400 ;SET => USE ALTERNATE PC PPR (THE ECHO AREA) +DEFSYM %TJINK==:200 ;SET => NEXT CHAR OUT TAKEN AS PRINTING + ; REGARDLESS (^PI) +DEFSYM %TJHDE==:100 ;SET => ACCOUTING FOR CURSOR MOTION DUE TO + ;CHAR ECHOED ON A HALF-DUPLEX TTY. + +;INPUT +DEFSYM %TIECH==:40000 ;CAN READ EVEN IF CHAR NEEDS PI ECHOING. +DEFSYM %TIPEK==:20000 ;DON'T REMOVE CHAR FROM BUFFER. +DEFSYM %TIACT==:4000 ;SET => DON'T WAIT FOR ACTIVATION CHARACTER. +DEFSYM %TIINT==:2000 ;SET => CAN READ A CHAR EVEN IF IT IS SUPPOSED TO + ; INTERRUPT & HASN'T YET. +DEFSYM %TINWT==:1000 ;SET => IF NO INPUT AVAILABLE, DON'T WAIT, JUST + ; RETURN -1. +DEFSYM %TIFUL==:400 ;SET => GIVE FULL CHARACTER (SIGNIFICANT ON IMLAX, TVS) + +DEFSYM $TIIDX==:220600 ;3.6-3.1 CONSOLE #, OR 77 FOR A "DISOWNED" CONSOLE + ; TTY CHNL, IE, ONE THAT CORRESPONDS TO NO REAL TTY. + ; THEY EXIST ONLY IN TREES WITH NO TTY, IN JOBS + ; THAT CAME FROM TREES WITH TTYS. +DEFSYM %TIIDX==:1 ;FOR BIT TYPEOUT MODE +DEFSYM %TJIDX==:1 ;FOR BIT TYPEOUT MODE +DEFSYM %TINON==:77 ;"TTY #" FOR A CHANNEL WITH NO REAL TTY. + +;EACH CHARACTER IN THE INPUT BUFFER OCCUPIES 18 BITS +;THE UPPER BITS ARE AS FOLLOWS (NOTE THAT AN IOTTED +;CHARACTER MAY ACTUALLY CONTAIN %TXPIE, %TXMPE, %TXECI, OR %TXINT) +DEFSYM %TX==:525200 ;BIT TYPEOUT MASK +DEFSYM %TXMPE==:400000 ;MAIN PROGRAM ECHO CHARACTER +DEFSYM %TXPIE==:200000 ;PI ECHO CHARACTER +; DEFSYM %TXCOM==:100000 ;COM MODE ECHO CHAR; DO PI ECHO EVEN IF HDX +; ; TTY. +; DEFSYM %TXIGN==:40000 ;IGNORE THIS CHAR AT .IOT TIME. +; DEFSYM %TXACT==:20000 ;THIS IS AN ACTIVATION CHAR. +; THESE CAN'T BE NEEDED EXCEPT INSIDE THE SYSTEM. +DEFSYM %TXINT==:10000 ;THIS CHAR SHOULD INTERRUPT THE USER. +;GAP +DEFSYM %TXECI==:2000 ;THIS CHAR WAS ECHOED BY AN ECHOIN SYSTEM CALL. + +;NOW COME THE BITS OF THE CHARACTER ITSELF: +DEFSYM %TXTOP==:4000 ;The "TOP" key. +;GAP +DEFSYM %TXSFT==:1000 ;What used to be the "SHIFT" key is now the +DEFSYM %TXSUP==:1000 ;"SUPER" key. (def'ed in this order for DDT) +DEFSYM %TXMTA==:400 ;"META" key. +DEFSYM %TXCTL==:200 ;"CONTROL" key. +DEFSYM %TXASC==:177 ;The ASCII part of the character. + +;DISPLAY COMMANDS (WHICH LIVE IN THE OUTPUT BUFFER). +;NOTE THAT ALL OF THEM HAVE 200-BIT SET. +DEFSYM %TD==:777400 +DEFSYM %TDMOV==:200 ;MOVE CURSOR +DEFSYM %TDMV1==:201 ;DUMMY COMMAND CREATED BY TYMOV. + ;MAKES IT POSSIBLE FOR TYMOV TO STOP WHEN BUFFER FULL + ;AND BE REENTERED NEXT INTERRUPT. +DEFSYM %TDEOF==:202 ;CLEAR REST OF PAGE +DEFSYM %TDEOL==:203 ;CLEAR REST OF LINE +DEFSYM %TDDLF==:204 ;DELETE FORWARD (FOR IMLACS AND TVS) +DEFSYM %TDMTF==:205 ;MOTOR OFF (FOR TERMINETS) +DEFSYM %TDMTN==:206 ;MOTOR ON (FOR TERMINETS) +DEFSYM %TDCRL==:207 ;CRLF ON DATAPOINTS, IMLACS. +DEFSYM %TDNOP==:210 ;NO-OP FOR SUPERDUPERIMAGE MODE. +DEFSYM %TDBS==:211 ;BACKSPACE (FOR TTY'S WITH %TORAW SET). +DEFSYM %TDLF==:212 ;LINEFEED ("). +DEFSYM %TDRCR==:213 ;CARRET ("). +DEFSYM %TDORS==:214 ;"OUTPUT RESET" FOR SAKE OF SOFTWARE TTYS +DEFSYM %TDQOT==:215 ;MYSTERY COMMAND -- SEND IN A JINGLE IN 25 WORDS OR + ; LESS AND WIN +DEFSYM %TDFS==:216 ;CURSOR FORWARD ONE COLUMN +DEFSYM %TDMV0==:217 ;MOVE CURSOR, FOLLOWED BY NEW VERT POS, NEW HOR POS +DEFSYM %TDCLR==:220 ;CLEAR THE SCREEN +DEFSYM %TDBEL==:221 ;DING THE BELL +DEFSYM %TDINI==:222 ;SYSTEM JUST CAME UP, RE-INITIALIZE INTELLIGENT + ; TERMINAL +DEFSYM %TDILP==:223 ;INSERT LINE-POSITION, FOLLOW BY COUNT +DEFSYM %TDDLP==:224 ;DELETE LINE-POSITION, FOLLOW BY COUNT +DEFSYM %TDICP==:225 ;INSERT CHARACTER-POSITION, FOLLOW BY COUNT +DEFSYM %TDDCP==:226 ;DELETE CHARACTER-POSITION, FOLLOW BY COUNT +DEFSYM %TDBOW==:227 ;ENTER BLACK ON WHITE MODE +DEFSYM %TDRST==:230 ;DESELECT ALL SPECIAL MODES (SUCH AS BLACK-ON-WHITE). +DEFSYM %TDGRF==:231 ;ENTER GRAPHICS MODE +DEFSYM %TDRSU==:232 ;REGION SCROLL UP +DEFSYM %TDRSD==:233 ;REGION SCROLL DOWN + +; Apparently codes 234 - 237 are used for an undocumented kludge for +; sending ARDS graphics protocol. See SYSENG;IMPRIN (the source of +; :ARDPRN). + +;%TDSYN THROUGH %TDMLT ARE USED ONLY ON TERMINALS WHICH HAVE %TRLED SET IN +; TTYSMT. +DEFSYM %TDSYN==:240 ;RESYNCH REPLY TO LOCAL EDITING TERMINAL +DEFSYM %TDECO==:241 ;ASK TERMINAL TO TRY LOCAL EDITING BY SENDING A + ; RESYNCH. +DEFSYM %TDEDF==:242 ;SET LOCAL EDITING TERMINAL COMMAND DEFINITION. + ; FOLLOWED BY TWO BYTES, DECODED AS DESCRIBED IN + ; LOCAL EDITING PROTOCOL. +DEFSYM %TDNLE==:243 ;STOP DOING LOCAL EDITING. +DEFSYM %TDTSP==:244 ;DISPLAYS LIKE SPACE, BUT IS PART OF A TAB. USED + ; ONLY FOR LOCAL EDITING TERMINALS, TO ENABLE THEM + ; DISTINGUISH SPACES FROM TABS. +DEFSYM %TDCTB==:245 ;THIS LINE IS CONTINUED AT THE BEGINNING. +DEFSYM %TDCTE==:246 ;THIS LINE IS CONTINUED AT THE END. +DEFSYM %TDMLT==:247 ;%TDMLT => NEXT COLS ARE DISPLAY REP FOR + ; ONE CHAR OF TEXT. +;%TDSVL THROUGH %TDSLL ARE USED ON TERMINALS WHICH HAVE NONZERO %TRLSV. +DEFSYM %TDSVL==:250 ; => SAVE LINES' CONTENTS UNDER + ; LABELS STARTING WITH *200+. +DEFSYM %TDRSL==:251 ;SAME THREE ARGS. RESTORE LABELED CONTENTS ONTO + ; LINES. +DEFSYM %TDSSR==:252 ; SET RANGE OF COLUMNS TO COPY IN + ; %TDSVL, %TDRSL. +DEFSYM %TDSLL==:253 ; SET LABEL FOR NEXT LINE PUSHED OFF + ; SCREEN LOCALLY. +DEFSYM %TDMAX==:254 ;1 + LARGEST DISPLAY CODE. + +;THE TCTYP WORD FOR A TTY CONTAINS A NUMBER WHICH SAYS HOW TO +;PERFORM CURSOR-CONTROL FUNCTIONS ON THE TTY. THE POSSIBILITIES ARE: +DEFSYM %TN==:777777 +DEFSYM %TNPRT==:0 ;PRINTING TTY. +DEFSYM %TNDP==:1 ;TTY USES DATAPOINT CURSOR CTL CODES. +DEFSYM %TNODP==:2 ;TTY IS A LOSING DATAPOINT. +DEFSYM %TNIML==:3 ;TTY USES IMLAC CURSOR CODES. +DEFSYM %TNTEK==:4 ;TEKTRONIX 4000 SERIES +DEFSYM %TNTV==:5 ;TTY IS A KNIGHT TV DISPLAY. +DEFSYM %TNMEM==:6 ;TTY IS A MEMOWRECK. +DEFSYM %TNSFW==:7 ;"SOFTWARE" TTY THAT WANTS I.T.S. CURSOR-MOTION CODES. +DEFSYM %TNTRM==:10 ;TTY IS A TERMINET. +DEFSYM %TNESC==:11 ;TTY WANTS ASCII STANDARD ESCAPE SEQUENCES. (E.G. VT52) +DEFSYM %TNDTM==:12 ;DATAMEDIA +DEFSYM %TNRAY==:13 ;TELERAY 1061 +DEFSYM %TNHDS==:14 ;HDS CONCEPT-100 +DEFSYM %TNH19==:15 ;H19 +DEFSYM %TNAAA==:16 ;Ann Arbor Ambassador +DEFSYM %TNMAX==:17 + + +;TTYOPT WORD DESCRIBES CHARACTERISTICS OF THE PARTICULAR +;TERMINAL ATTACHED TO EACH LINE. + +;LEFT HALF BITS ARE: +DEFSYM %TO==:1,,525252 ;BIT TYPEOUT MASK +DEFSYM %TOALT==:200000 ;4.8 => STANDARDIZE ALTMODES. +DEFSYM %TOCLC==:100000 ;4.7 => CONVERT LOWER CASE TO UPPER. +DEFSYM %TOERS==:40000 ;4.6 => THIS TTY CAN SELECTIVELY ERASE. +DEFSYM %TOHDX==:20000 ;4.5 => THIS TTY IS HALF-DUPLEX. +DEFSYM $TOHDX==:370100 +DEFSYM %TOMVB==:10000 ;4.4 => THIS TTY CAN BACKSPACE. +DEFSYM %TOSAI==:4000 ;4.3 => THIS TTY HAS SAIL CHAR SET ON OUTPUT. +DEFSYM %TOSA1==:2000 ;4.2 INIT %TSSAI OF NEW JOBS. +DEFSYM %TOOVR==:1000 ;4.1 => THIS TTY CAN OVERPRINT SUCCESSFULLY. +DEFSYM %TOMVU==:400 ;3.9 => THIS TTY CAN MOVE CURSOR UP (I.E. IT'S A + ; DISPLAY). +DEFSYM %TOMOR==:200 ;3.8 => DO **MORE** PROCESSING ON THIS TTY + ; (ACTUALLY JUST USED TO INIT %TSMOR FOR NEW JOBS). +DEFSYM %TOROL==:100 ;3.7 SIMILARLY, INIT %TSROL FOR NEW JOBS. +DEFSYM %TORAW==:40 ;3.6 => SUPPRESS CURSOR MOTION OPTIMIZATION. +DEFSYM %TOLWR==:20 ;3.5 => THIS TTY HAS LOWER CASE KEYBOARD. +DEFSYM %TOFCI==:10 ;3.4 => KEYBOARD CAN GENERATE FULL 12-BIT CHARACTER SET +DEFSYM %TOIML==:4 ;3.3 => SPACE, BS DON'T EQUAL ^PF, ^PB; ALSO ^PC + ; SENDS ^L. +DEFSYM %TOLID==:2 ;3.2 => %TDILP, %TDDLP WORK (INSERT AND DELETE LINES) +DEFSYM %TOCID==:1 ;3.1 => %TDICP, %TDDCP WORK + ; (INSERT AND DELETE CHARACTERS) + +;RIGHT HALF: +DEFSYM %TP==:707252 ;BIT TYPEOUT MASK +DEFSYM %TPPLF==:100000 +DEFSYM $TPPLF==:170300 ;3-BIT FIELD SAYING HOW TO PAD LF. + ; 0 - DON'T. 1 - MEMOWRECK, 2741. 2 - TERMINET. +DEFSYM %TPPCR==:10000 +DEFSYM $TPPCR==:140300 ;3-BIT FIELD SAYING HOW TO PAD CR. + ; 7 - UNUSED. 6 - MEMOWRECK. 5 - 2741. 4 - EXECUPORT. + ; 0 - DON'T. 1 - NORMAL. 2 - DOUBLE. + ; ON DATAPOINTS, = # CHARS PADDING NEEDED FOR ALL + ; CURSOR MOTION. + ; 4 IS RIGHT FOR 2400 BAUD; 3, FOR 1200. + ; ON TERMINETS, 0 => NO PADDING, ELSE 1,2,3,4,5 + ; ARE PADDING FOR SPEEDS 10,15,30,60,120 CPS. +DEFSYM %TPPCW==:6 ;FOR MEMO WRECK. +DEFSYM %TPPTB==:1000 +DEFSYM $TPPTB==:110300 ;3 BIT FIELD SAYING HOW MUCH PADDING NEEDED AFTER + ; TAB. 0 => TABS NOT ALLOWED; ELSE 1 +<# PADDING + ; CHARS NEEDED> BUT ON A DISPLAY, TABS ARE NEVER + ; PADDED AND THIS FIELD IS 1 TO USE TABS, 2 TO USE + ; ABSOLUTE CURSOR POSITIONING, 3 TO USE BOTH, 0 TO + ; USE NEITHER. +DEFSYM %TPMTA==:400 ;1.9 => HARDWARE META KEY SETS 8TH BIT +DEFSYM %TPPRN==:200 ;1.8 => INTERCHANGE () WITH [] ON INPUT +DEFSYM %TPTEL==:100 ;1.7 => HANDLE CR-LF ON INPUT AS CR, FOR TELNET + ; PROTOCOL +DEFSYM %TPCBS==:40 ;1.6 => ENABLE SPECIAL HANDLING OF CONTROL BACK + ; SLASH ON INPUT (THE "INTELLIGENT TERMINAL + ; PROTOCOL"). +DEFSYM %TP11T==:20 ;1.5 => PDP-11 TV TTY. REFLECTS %TY11T. NOT + ; SETTABLE BY USER. +DEFSYM %TPORS==:10 ;1.4 => OUTPUT RESET ON THIS TTY SHOULD REALLY DO + ; SOMETHING. +DEFSYM %TPRSC==:4 ;1.3 => THIS TTY SUPPORTS %TDRSU, %TDRSD + +;DEFINE BITS WHICH ARE USER-OPTIONS +DEFSYM %TOUSR==:%TOCLC+%TOSA1+%TOMOR+%TOROL +DEFSYM %TPUSR==:%TPPRN+1 ;THE 1 IS TO AVOID INTEFERING WITH BIT-TYPE-OUT + +DEFSYM %TQ==1,,701725 ;TTY "SMARTS" BITS IN LH(TTYSMT) +DEFSYM %TQIM1==300000 ;TTY IS A PDS1 +DEFSYM %TQIM4==200000 ;TTY IS A PDS4 +DEFSYM %TQP11==100000 ;TTY IS A PDP11 +DEFSYM %TQMCH==700000 ;4.7-4.9 MACHINE TYPE, 0 => NOTHING SPECIAL +DEFSYM %TQGRF==1 ;3.1 UNDERSTANDS GRAPHICS PROTOCOL +DEFSYM %TQGPH==1 ;3.1 UNDERSTANDS GRAPHICS PROTOCOL (OBSOLETE NAME) +DEFSYM %TQSET==2 ;3.2 HAS MULTIPLE OBJECT SETS +DEFSYM %TQREC==4 ;3.3 HAS RECTANGLE COMMANDS +DEFSYM %TQXOR==10 ;3.4 HAS XOR MODE +DEFSYM %TQBNK==20 ;3.5 HAS BLINKING +DEFSYM %TQVIR==40 ;3.6 VIRTUAL COORDINATES +DEFSYM %TQHGT==76000 ;4.2-4.6 CHARACTER HEIGHT IN DOTS +DEFSYM %TQWID==1700 ;3.7-4.1 CHARACTER WIDTH IN DOTS + +DEFSYM %TR==534052 ;RH(TTYSMT) +DEFSYM %TRGIN==400000 ;2.9 HAS GRAPHIC INPUT +DEFSYM %TRGHC==200000 ;2.8 HAS GRAPHIC HARDCOPY +DEFSYM %TRLED==100000 ;2.7 HAS LOCAL EDITING PROTOCOL. +DEFSYM %TRSCN==040000 ;2.6 HAS RASTER COMMANDS +DEFSYM %TRLSV==034000 ;2.3-2.5 NONZERO MEANS TERMINAL SUPPORTS 4**N SAVED + ; LINES. +DEFSYM %TRTIM==003700 +DEFSYM $TRTIM==060500 ;5 BIT FIELD WHICH IS THE SIGNED OFFSET FROM GMT + ; MINUS #o20; A VALUE OF ZERO MEANS DON'T KNOW, + ; DON'T CARE, OR USER PROGRAM HASN'T IMPLEMENTED IT + ; YET + +;GROUP NUMBER CHARACTERS +;[ 0 ^A-^F ^K-^L ^N-^R ^T-^Z ^] ^^ ^_ ^@ ^\ +; 1 A-Z LOWER CASE A-Z +; 2 0-9 +; 3 !"#$(DOLLAR)%&',.:;?@\ (ACCENT GRAVE) +; (VERTICAL BAR) (TILDE) +; 4 *+-/=^_ +; 5 <>[]() (LEFT BRACE) (RIGHT BRACE) +; 6 ^G ^S +; 7 LF ^I(TAB) +; 10 (ALTMODE) +; 11 CR +; 12 RUBOUT +; 13 SPACE ^H(BACKSPACE) + +;TTYST1 HAS GROUPS 0 THROUGH 5 FROM LEFT TO RIGHT +;TTYST2 HAS 6 THROUGH 13 +;EACH GROUP HAS SIX BITS AS FOLLOWS: +DEFSYM %TG==:777725 ;BIT TYPEOUT MASK +DEFSYM %TGINT==:1 ;N.1 => INTERRUPT ON THIS GROUP +DEFSYM %TGACT==:2 ;N.2 => ACTIVATE ON THIS GROUP (FOR SWAPPING) +DEFSYM %TGSPC==:4 ;N.3 => SPECIAL HACKS. + ; (THIS SET ON GROUP 1 => CONVERT LOWER CASE) +DEFSYM %TGIMG==:10 ;N.4 => IMAGE MODE OUTPUT (N.4=0 => ASCII MODE) + ;N.6-N.5 => ECHO MODE + ; 00 => NO ECHO +DEFSYM %TGPIE==:20 ; 01 => PI ECHO (ECHO CHARACTER WHEN TYPED) +DEFSYM %TGMPE==:40 ; 10 => MAIN PROGRAM ECHO (ECHO WHEN MAIN + ; PROGRAM RECEIVES CHARACTER) + +;TTYSTS HAS RANDOM BITS ASSOCIATED WITH THE TELETYPE +DEFSYM %TS==:1,,525252 ;BIT TYPEOUT MASK +DEFSYM %TSFRE==:400000 ;4.9 => TTY FREE +DEFSYM %TSCLE==:200000 ;4.8 => ECHO ^L AS UPARROW-L EVEN ON DISPLAYS + ;(OTHERWISE WOULD ECHO AS CLEAR SCREEN) +DEFSYM %TSHDX==:100000 ;4.7 REFLECTS %TOHDX BIT. +DEFSYM %TSFCO==:040000 ;4.6 => HANDLE 9-BIT CHARS ON OUTPUT, USING ALPHA, + ; BETA, EPSILON. +DEFSYM %TSALT==:020000 ;4.5 => DON'T STANDARDIZE ALTMODE. +DEFSYM %TSROL==:010000 ;4.4 => SCROLL MODE. +DEFSYM %TSSAI==:004000 ;4.3 => ECHO AND ASCII MODE SHOULD USE SAIL CHAR SET. +DEFSYM %TSACT==:002000 ;4.2 => GOBBLE NEXT CHAR REGARDLESS OF ACTIVATION + ; STATUS +DEFSYM %TSNEA==:001000 ;4.1 => DON'T ECHO IN ECHO AREA; ECHO IN M.P. AREA +DEFSYM %TSINT==:000400 ;3.9 => INT ON NEXT CHAR REGARDLESS +DEFSYM %TSMOR==:000200 ;3.8 => INHIBIT **MORE**. +DEFSYM %TSATY==:000100 ;3.7 SET BY .ATTY, SAYS TTY WAS TAKEN AWAY & RETURNED. + ;3.6-3.5 UNUSED. +DEFSYM %TSNOE==:000010 ;3.4 => DEFER ECHOING, AND MAKE INPUT IOT'S ACT AS + ; IF %TIECH=1. +DEFSYM %TSLCZ==:000004 ;3.3 => LAST CHARACTER TYPED WAS ^Z + ; (NOT PRECEEDED BY ^_) +DEFSYM %TSSII==:000002 ;3.2 => SUPER IMAGE INPUT MODE. ^Z AND ^_ INHIBITED. +DEFSYM %TSCNS==:000001 ;3.1 => TTY IN USE AS CONSOLE CONTROLLING A TREE. +DEFSYM $TSCNS==:220100 + ;RH => USER INDEX + ; -1 => NO USER + +;TTYCOM VARIABLE. +;4.9 => TTY IN COMMUNICATE MODE +DEFSYM %TC==:1,,525252 ;BIT TYPEOUT MASK +DEFSYM %TCLFT==:200000 ;4.8 => LOCAL FEED THROUGH (SET IF MY PRGM + ; RECEIVING HIS CHRS) +DEFSYM %TCRFT==:100000 ;4.7 => REMOTE FEED THROUGH (SET IF HIS PRGM + ; RECEIVING MY CHRS) +DEFSYM %TCICO==:40000 ;4.6 => INPUT COMMUNICATE OVERRIDE (SET IF MY + ; CONSOLE FEEDING MY PRGM EVEN THO IN COMM MODE). + ; ALSO IMPLIES OUTPUT OVER-RIDE +DEFSYM %TCOCO==:20000 ;4.5 => OUTPUT COMMUNICATE OVERRIDE (SET IF MY + ; PRGM'S OUTPUT TO APPEAR ON MY CONSOLE ONLY EVEN + ; THO IN COM MODE) + ;4.4-4.3 => MESSAGE RECEIPT SWITCH + ; 00 => ACCEPT +DEFSYM %TCRFS==:10000 ; 10 => REFUSE +DEFSYM %TCQRY==:4000 ; 01 => INTERROGATE +DEFSYM %TCMTR==:2000 ;4.2 SET FOR TTY WHOSE MOTOR IS OFF & MUST BE + ; TURNED ON BEFORE ANY OTHER OUTPUT IS DONE. (ONLY + ; TERMINETS HAVE THEIR MOTORS SHUT OFF BY ITS). +DEFSYM %TCECH==:1000 ;4.1 THE OUTPUT BUFFER CONTAINS ECHOING OUTPUT. + ; THIS MAKES OUTPUT RESET DO NOTHING. THE BUFFER + ; MUST NOT CONTAIN ECHO OUTPUT AND NORMAL OUTPUT AT + ; ONE TIME. +DEFSYM %TCLED==:400 ;3.9 JOB WHICH OWNS TTY WANTS LOCAL EDITING IN + ; TERMINAL. SET BY CTL BIT 1.1 IN SCPOS; CLEARED + ; BY SWITCHING JOBS. +DEFSYM %TCDET==:200 ;3.8 CONSOLE'S TREE DETACHED BY TOP LEVEL + ; INTERRUPT. SET BY NDETAC AS SIGNAL TO SYSCFM + ; (CNSL-FREE-MSG TYPER) +DEFSYM %TCDNG==:100 ;3.7 => TYPE BELL ON TTY (BECAUSE INPUT BFR FULL). +DEFSYM %TCCBK==:40 ;3.6 => READING UNAME OR TTY # AFTER ^_K. +DEFSYM %TCCBS==:20 ;3.5 => READING UNAME OR TTY # AFTER ^_S. +DEFSYM %TCFPD==:10 ;3.4 => FIRST PART OF MULTI-CHAR OUTPUT SEQUENCE DONE. +DEFSYM %TCTPN==:4 ;3.3 TYPE ^_N ON LEAVING COM MODE (UNLESS USER + ; EXPLICITLY TYPES ^_N) +DEFSYM %TCPAD==:2 ;3.2 0 => PADDING NECESSARY ON DATAPOINT. +DEFSYM %TCHNG==:1 ;3.1 TTY'S DONE FLAG APPEARS TO BE FRIED, TIME OUT + ; QUICKLY +;RH => USER INDEX COMMUNICATING WITH (-1 NONE) + +;TTYTYP TABLE +;THIS TABLE HOLDS BITS THAT DESCRIBE THE LINE +;AND ITS CONTROLLER, RATHER THAN THE TTY ATTACHED TO THE LINE. +DEFSYM %TT==:1,,525360 ;BIT TYPEOUT MASK +DEFSYM %TTLCL==:400000 ;BIT 4.9 ONE => LOCAL TTY +DEFSYM %TT340==:200000 ;BIT 4.8 ONE => CONSOLE NEXT TO 340 OR A 340 SLAVE +DEFSYM %TT3HP==:100000 ;BIT 4.7 HIGH PRIORITY ON 340 +DEFSYM %TTPAR==:004000 ;BIT 4.3 +DEFSYM %TTDDI==:002000 ;BIT 4.2 DONT DING ON EXCESS INPUT +DEFSYM $TTISP==:260400 ;3.8-3.5 INPUT SPEED CODE +DEFSYM %TTISP==:20 +DEFSYM $TTOSP==:220400 ;3.4-3.1 OUTPUT SPEED CODE +DEFSYM %TTOSP==:1 +;RIGHT HALF BITS +DEFSYM %TY==:525252 ;BIT TYPEOUT MASK +DEFSYM %TYDPK==:400000 ;BIT 2.9 (DATAPOINT KLUDGE TTY LINE) +DEFSYM %TYSTY==:200000 ;BIT 2.8 PSEUDO TTY +DEFSYM %TYNVA==:100000 ;BIT 2.7 NOVA TTY +DEFSYM %TYMTY==:040000 ;BIT 2.6 MORTON BOX +DEFSYM %TYDIL==:020000 ;BIT 2.5 DIAL UP +DEFSYM %TY11T==:010000 ;BIT 2.4 PDP-11 TV TTY. +DEFSYM %TYDL==:004000 ;BIT 2.3 DL-11 TTY +DEFSYM %TYOTY==:002000 ;BIT 2.2 KA-10 CONSOLE TTY +DEFSYM %TYETY==:001000 ;BIT 2.1 DTE20 TTY +DEFSYM %TYNTY==:000400 ;BIT 1.9 TK-10 TTY +DEFSYM %TYMDM==:000200 ;BIT 1.8 LINE DETECTS DIALINS AND HANGUPS +DEFSYM %TYKST==:000100 ;BIT 1.7 KS-10 CONSOLE TTY +DEFSYM %TYDZT==:000040 ;BIT 1.6 DZ-11 TTY ON KS-10 +DEFSYM %TYRLM==:000020 ;BIT 1.5 ROLM DATA SWITCH + +;SPEED CODES ARE DOCUMENTED ON PAGE 3 OF ITS (DEFINE SPEED1) + +;SUPDUP GRAPHICS PROTOCOL COMMANDS: + +DEFSYM %GO==:,,-1 + +DEFSYM %GODLR==:101 ;

Draw line relative, from the cursor to

. +DEFSYM %GODPR==:102 ;

Draw point relative, at

. +DEFSYM %GODRR==:103 ;

Draw rectangle relative, corners at

and + ; at the current cursor position. +DEFSYM %GODCH==:104 ; <0> + ;Display the chars of starting at the current + ;graphics cursor position. +DEFSYM %GODSC==:105 ; Draws scan bits starting at + ;the current gaphics cursor position. come + ;in bits of 6-6-4. has 100 bit (character + ;gobbled) or 200 bit (interpreted as %TD code) set. +DEFSYM %GODRN==:106 ; <0> Draw run length encoded raster line + ;starting at current graphic cursor. Low six bits are + ;count. 100 bit determines point type (on/off). + +DEFSYM %GODLA==:121 ;

Draw line absolute, from the cursor to

. + ; The same effect as %GODLR, but the arg absolute. +DEFSYM %GODPA==:122 ;

Draw point absolute, at

. +DEFSYM %GODRA==:123 ;

Draw rectangle absolute, corners at

and + ; at the current cursor position. + +DEFSYM %GOELR==:141 ;

Erase line relative, from the cursor to

. +DEFSYM %GOEPR==:142 ;

Erase point relative, at

. +DEFSYM %GOERR==:143 ;

Erase rectangle relative, corners at

and + ; at the current cursor position. +DEFSYM %GOECH==:144 ; <0> + ;Erase the chars of starting at the current + ;graphics cursor position. +DEFSYM %GOESC==:145 ; . Erase scan bits starting at + ;the current graphics cursor position. +DEFSYM %GOERN==:146 ; <0> Erase run-length encoded rasters + ;starting at current grphaics cursor position. + +DEFSYM %GOELA==:161 ;

Erase line absolute, from the cursor to

. +DEFSYM %GOEPA==:162 ;

Erase point absolute, at

. +DEFSYM %GOERA==:163 ;

Erase rectangle absolute, corners at

and + ; at the current cursor position. + +DEFSYM %GOMVR==:001 ;

Move cursor to point

+DEFSYM %GOMVA==:021 ;

Move cursor to point

, absolute address. +DEFSYM %GOXOR==:002 ; Turn on XOR mode. Bit matrix terminals only. +DEFSYM %GOIOR==:022 ; Turn off XOR mode. +DEFSYM %GOSET==:003 ; Select set. is a 1-character set number, + ; 0 - 177. +DEFSYM %GOMSR==:004 ;

Move set origin to

. Display list + ; terminals only. +DEFSYM %GOMSA==:024 ;

Move set origin to

, absolute address. +DEFSYM %GOINV==:006 ; Make current set invisible. +DEFSYM %GOVIS==:026 ; Make current set visible. +DEFSYM %GOBNK==:007 ; Make current set blink. Canceled by %GOINV + ; or %GOVIS. +DEFSYM %GOCLR==:010 ; Erase whole screen. +DEFSYM %GOCLS==:030 ; Erase entire current set (display list + ; terminals). +DEFSYM %GOPSH==:011 ; Push all input-stream status information, to be + ; restored when graphics mode is exited. +DEFSYM %GOVIR==:012 ; Start using virtual co-ordinates +DEFSYM %GOPHY==:032 ; Resume giving co-ordinates in units of dots. +DEFSYM %GOHRD==:013 ; Divert output to output subdevice . + ; =0 reselects the main display screen. +DEFSYM %GOGIN==:014 ; Request graphics input (mouse, tablet, etc). + ; is the reply code to include in the answer. +DEFSYM %GOLMT==:015 ; + ;Limits graphics to a subrectangle of the + ;screen. %GOCLR will clear only that area. + ;This is for those who would use the rest for text. + +;THE TTYTBL VARIABLE EXISTS FOR EACH JOB. +;IT DESCRIBES THE ATTY-DTTY STATE OF THE JOB +;AND OTHER THINGS THAT HAVE TO DO WITH THE TREE'S +;CONTROLLING TTY ONLY. +DEFSYM %TB==:1,,525277 ;BIT TYPEOUT MASK +DEFSYM %TBNOT==:400000 ;4.9 THIS JOB DOES NOT HAVE THE TTY NOW. +DEFSYM %TBNVR==:200000 ;4.8 IF JOB DOESN'T HAVE TTY, OPENS SHOULD FAIL. +DEFSYM %TBINT==:100000 ;4.7 IF JOB DOESN'T HAVE TTY, ATTEMPT TO USE TTY + ; SHOULD INTERRUPT. +DEFSYM %TBWAT==:040000 ;4.6 IF SET, OVERRIDES %TBINT AND %TBNVR, AND + ; FORCES TTY USAGE ATTEMPTS TO HANG. MAY BE ALTERED + ; ONLY BY SUPERIOR. +DEFSYM %TBDTY==:010000 ;4.4 THE JOB DOESN'T HAVE THE TTY, BUT IT IS IN A + ; DTTY'ING STATE. IN OTHER WORDS, THIS JOB DOESN'T + ; WANT TO GIVE THE TTY TO ONE OF ITS INFERIORS. +DEFSYM %TBOUT==:004000 ;4.3 ALLOW TYPEOUT EVEN IF DON'T HAVE TTY (SETTABLE + ; BY SUPERIOR) +DEFSYM %TBINF==:002000 ;4.2 ALLOW INFERIORS TO TAKE ADVANTAGE OF THEIR + ; %TBOUTS. +DEFSYM %TBOIG==:001000 ;4.1 IGNORE OUTPUT (NORMALLY SET BY SUPERIOR). + ; OVERRIDES %TBWAT, %TBINT. +DEFSYM %TBIIN==:000400 ;3.9 INTERRUPT ON ATTEMPT TO DO INPUT. OVERRIDES + ; %TBWAT. NORMALLY SET BY SUPERIOR. +DEFSYM $TBECL==:220600 ;3-6-3.1 # ECHO LINES IF I DONT HAVE DISPLAY +DEFSYM %TBECL==:77 + +;RH - IF %TBNOT IS 0, THE RH HAS THE TTY NUMBER. +;OTHERWISE, IF %TBDTY IS 0, THE RH HAS THE USR INDEX OF +;THE INFERIOR THAT THIS JOB GAVE OR WOULD LIKE TO GIVE +;THE TTY TO. OTHERWISE, THE RH IS 0. + +;BITS IN THE PER-STY VARIABLE STYSTS, RETURNED BY STYGET SYSTEM CALL. +DEFSYM %SS==:1,,525252 ;BIT TYPEOUT MASK +DEFSYM %SSHNG==:400000 ;4.9 = 1 => DON'T HANG ON INPUT IOTS +DEFSYM %SSUSE==:200000 ;4.8 = 1 => IN USE +DEFSYM %SSINT==:100000 ;4.7 = 1 => HAVE GIVEN INT ON STY OUTPUT + ; CHNS ALREADY +DEFSYM %SSONT==:040000 ;4.6 = 1 => DITTO FOR STY INPUT (TTY OUTPUT) +DEFSYM %SSOHG==:20000 ;4.5 = 1 => DON'T HANG ON OUTPUT IOT + ;RH = USER INDEX THAT HAS IT OPEN + + +IFN $$TEMP, EXPUNGE DEFSYM diff --git a/src/system/ch10.defs1 b/src/system/ch10.defs1 new file mode 100755 index 00000000..8c325e39 --- /dev/null +++ b/src/system/ch10.defs1 @@ -0,0 +1,26 @@ +;Hardware definitions for CH10 PDP-10 CHAOSNET interface + +CHX==470 ;I/O Device number + +;CONI/CONO BITS + ;1.1-1.3 PIA +CHXTEN==10 ;1.4 Transmit interrupt enable +CHXREN==20 ;1.5 Receive interrupt enable +CHXSPY==40 ;1.6 Match any destination (on receive) +CHXLUP==100 ;1.7 Loop back +CHXSWB==200 ;1.8 Swap bytes +CHXHLF==400 ;1.9 Halfword DATAO +CHXXMT==1000 ;2.1 Transmit done (CONI) + ; Transmit or retransmit packet (CONO) +CHXRCV==2000 ;2.2 Receive done (CONI) + ; Enable to receive next packet (CONO) +CHXABT==4000 ;2.3 Transmit aborted (CONI) + ; Reset transmitter (CONO) +$CHXLC==140400 ;2.4-2.7 Lost count (CONI) +CHXRST==10000 ;2.4 Reset (CONO) +CHXCRC==200000 ;2.8 CRC error (CONI) +CHXWLE==400000 ;2.9 Word length error (CONI) +CHXPLE==1,, ;3.1 Packet length error (CONI) +CHXOVR==2,, ;3.2 Overrun (CONI) +$CHXAD==242000 ;3.3-4.9 Chaosnet address (CONI) + diff --git a/src/system/ch11.defs1 b/src/system/ch11.defs1 new file mode 100755 index 00000000..31e60f26 --- /dev/null +++ b/src/system/ch11.defs1 @@ -0,0 +1,58 @@ +;; CH11 Unibus Chaosnet Interface definitions + +CAICSR=3,,764140 ;COMMAND STATUS REG +CH%CSR==0 + %CABSY==1 ;0 XMT BUSY (RO) + %CALUP==2 ;1 LOOP BACK (R/W) + %CASPY==4 ;2 RECIEVE MSGS FOR ANY DESTINATION (R/W) + %CARCL==10 ;3 CLEAR THE RECEIVER, IT CAN NOW GOBBLE ANOTHER MSG (WO) + %CAREN==20 ;4 RCV INT ENB (R/W) + %CATEN==40 ;5 XMT INT ENB (R/W) + %CATAB==100 ;6 TRANSMIT ABORTED BY ETHER CONFLICT (RO) + %CATDN==200 ;7 TRANSMIT DONE. SET WHEN TRANSMITTER IS DONE + %CATCL==400 ;8 CLEAR THE TRANSMITTER, MAKING IT READY (WO) + $CALOS==110400 ;9-12 LOST COUNT (RO) [# MSGS RCVED WITH RCV BFR FULL] + ; WHEN MSG IS WAITING IN BUFFER, THIS COUNTS + ; THE MESSAGES THAT MATCHED OUR DESTINATION OR + ; WERE BROADCAST, BUT COULDN'T BE RECIEVED. + ; WHEN RECEIVER IS RE-ENABLED (WRITE 1 INTO %CARDN) + ; THE COUNT IS THEN CLEARED. + ; WHEN A MESSAGE IS LOST, RECEIVER ZAPS ETHER + ; SO TRANSMITTER WILL ABORT (IF MESSAGE WAS DESTINED + ; TO US.) + %CARST==20000 ;13 I/O RESET (WO) + %CAERR==40000 ;14 CRC ERROR (RO) + %CARDN==100000 ;15 RCV DONE. + +CAIMYN==3,,764142 ;MY # (READ ONLY) +CH%MYN==2 ;RETURNS THE [SOURCE] HOST# OF THIS INTERFACE. + +CAIWBF=3,,764142 ;WRITE BUFFER (WRITE ONLY) +CH%WBF==2 ;FIRST WAIT FOR TDONE. (OR SET IT VIA CSR) + ;FIRST WORD IN RESETS TRANSMITTER AND CLEARS TDONE. + ;STORE INTO THIS REGISTER TO WRITE WORDS OF MESSAGE, + ;LAST WORD IN IS DESTINATION ADDRESS, THEN READ CAIXMT. + ;SOURCE ADDRESS AND CHECK WORD PUT IN BY HARDWARE. + +CAIRBF=3,,764144 ;READ BUFFER (READ ONLY) +CH%RBF==4 ;THE FIRST WORD READ WILL BE FILLED TO THE LEFT + ;TO MAKE THE MESSAGE RECIEVED A MULTIPLE OF 16 BITS. + ;IF THE NUMBER OF DATA BITS IN THE MESSAGE WAS A + ;MULTIPLE OF 16, THIS WORD WILL BE THE FIRST WORD PUT + ;INTO THE BUFFER BY THE TRANSMITTING HOST. + ;THE LAST 3 WORDS READ ARE DESTINATION, SOURCE, CHECK. + +CAIRBC=3,,764146 ;RECEIVE BIT COUNTER (READ ONLY) +CH%RBC==6 ;WHEN A MESSAGE HAS BEEN RECEIVED THIS IS ONE LESS THAN + ;THE NUMBER OF BITS IN THE MESSAGE (16 X THE + ;NUMBER OF WORDS INCLUDING THE THREE OVERHEAD WORDS.) + ;AFTER THE LAST WORD (THE CRC WORD) HAS BEEN READ, IT IS 7777 + ;BITS 10 AND 11 ARE THE HIGH ORDER BITS, AND IF THEY ARE ONE, + ;THEN THERE WAS A BUFFER OVERFLOW + +CAIXMT=3,,764152 ;READING THIS INITIATES TRANSMISSION (!!) +CH%XMT==12 ;THE VALUE READ IS ONE'S OWN HOST#. + +;REFERENCING ADDRESSES IN THE GROUP OF 8 WORDS NOT LISTED HERE, OR +;USING COMBINATIONS OF READ/WRITE NOT LISTED HERE, WILL TYPICALLY CAUSE +;STRANGE AND BIZARRE EFFECTS. diff --git a/src/system/chaos.288 b/src/system/chaos.288 new file mode 100755 index 00000000..e29d65b5 --- /dev/null +++ b/src/system/chaos.288 @@ -0,0 +1,2782 @@ +IFE IMPP, IFE CH11P, .ERR NOT EVERYTHING IN CHAOS WILL WORK WITHOUT IMP +IFNDEF FTRCHK, FTRCHK==0 ;PROBABLY FOUND ALL THE BUGS THIS WAS GOOD FOR + ; LONG AGO +IFN FTRCHK, .ERR REDUNDANT CHECKING ENABLED IN CHAOS ROUTINES + +;NOTES: +; WINDOW SIZE ADJUSTMENT STUFF +; ROUND TRIP TIME MEASUREMENT & OTHER METERING +; BETTER METERING, SOME METERS ARE CURRENTLY MISSING + +SUBTTL CH-10 HARDWARE DEFINITIONS + +IFN CH10P,[ +CHX==470 ;I/O DEVICE NUMBER + +;CONI/CONO BITS + ;1.1-1.3 PIA +CHXTEN==10 ;1.4 TRANSMIT INTERRUPT ENABLE +CHXREN==20 ;1.5 RECEIVE INTERRUPT ENABLE +CHXSPY==40 ;1.6 MATCH ANY DESTINATION +CHXLUP==100 ;1.7 LOOP BACK +CHXSWB==200 ;1.8 SWAP BYTES +CHXHLF==400 ;1.9 HALFWORD DATAO +CHXXMT==1000 ;2.1 TRANSMIT DONE (CONI) + ; TRANSMIT OR RETRANSMIT PACKET (CONO) +CHXRCV==2000 ;2.2 RECEIVE DONE (CONI) + ; ENABLE TO RECEIVE NEXT PACKET (CONO) +CHXABT==4000 ;2.3 TRANSMIT ABORTED (CONI) + ; RESET TRANSMITTER (CONO) +$CHXLC==140400 ;2.4-2.7 LOST COUNT (CONI) +CHXRST==10000 ;2.4 RESET (CONO) +CHXCRC==200000 ;2.8 CRC ERROR (CONI) +CHXWLE==400000 ;2.9 WORD LENGTH ERROR (CONI) +CHXPLE==1,, ;3.1 PACKET LENGTH ERROR (CONI) +CHXOVR==2,, ;3.2 OVERRUN (CONI) +$CHXAD==242000 ;3.3-4.9 CHAOSNET ADDRESS (CONI) +];CH10P + +IFN CH11P,[ +$INSRT KSNET +];CH11P + +SUBTTL CHAOS NET VARIABLES + +EBLK + +$CHXRI==001200 ;REAL INDEX PART (LOW TEN BITS) - IS IN LH(IOCHNM) +$CHXUN==120600 ;UNIQUIZATION PART (TOP SIX BITS) +CHXMUN==1_6-1 ;MAXIMUM VALUE OF UNIQUIZER +MXWIND==100 ;MAXIMUM WINDOW SIZE (8K WORDS) +.SEE MYCHAD ;SUBNET AND HOST OF MYSELF +.SEE DLCP ;1 MEANS USE DL10 TO GET TO CHAOS NET +.SEE T11CHP ;1 MEANS USE TEN-11 INTERFACE TO GET TO CHAOS NET +.SEE CH10P ;1 MEANS USE CH10 HARDWARE TO GET TO CHAOS NET +.SEE CH11P ;1 MEANS USE UNIBUS CHAOSNET HARDWARE ON KS10 + +;Internet address of my Chaosnet Interface +IMPUS4==<.BYTE 4 ? 0 ? .BYTE 8 ? 128. ? 31. ? .BYTE 16. ? MYCHAD> + +;PER-INDEX VARIABLES + +CHSUSR: REPEAT NINDX,-1 ;-1 INDEX NOT IN USE + ;OTHERWISE RH USER + $CHSUO==220600 ;3.1-3.6 OUTPUT CHANNEL NUMBER (77=IOPUSHED) + $CHSUI==300600 ;3.7-4.3 INPUT CHANNEL NUMBER (77=IOPUSHED) + ;4.9 ZERO IF IN USE + +CHSSTA: REPEAT NINDX,-1 ;RH STATE, LH FLAGS + %CF==525252(1) + %CFOFF==400000 ;SIGN BIT MEANS TURNED OFF AT PI LEVEL, NO TALKING TO NETWORK + %CFSTS==200000 ;SEND STS PACKET AS SOON AS POSSIBLE (1/2 SECOND CLOCK) + %CFCLS==100000 ;HALF-CLOSED FLAG + %CFSTY==040000 ;DIRECT-CONNECTED TO STTY FLAG + $CFTTN==220600 ;TTY NUMBER OF STTY CONNECTED TO + + %CS==,,-1 + .SEE %CSCLS ;FOR SYMBOLS FOR STATES + +CHSNBF: BLOCK NINDX ;LH LENGTH(CHSPBF), RH LENGTH(CHSIBF) +CHSNOS: BLOCK NINDX ;NUMBER OF FREE OUTPUT SLOTS IN THE WINDOW +CHSIBF: BLOCK NINDX ;RECEIVE BUFFER POINTERS FIRST,,LAST +CHSPBF: BLOCK NINDX ;OUT OF ORDER RECEIVE BUFFER POINTERS FIRST,,LAST +CHSOBF: BLOCK NINDX ;TRANSMIT BUFFER POINTERS FIRST,,LAST +CHSITM: BLOCK NINDX ;TIME OF LAST INPUT FROM NET +CHSWIN: BLOCK NINDX ;WINDOW SIZE RECEIVE,,TRANSMIT +CHSPKN: BLOCK NINDX ;LAST PACKET# GIVEN TO USER,,LAST PACKET# SENT BY USER +CHSACK: BLOCK NINDX ;LAST PACKET# ACKNOWLEDGED RECEIVE,,TRANSMIT (START OF WINDOW) +CHSLCL: REPEAT NINDX,<.BYTE 16. ? MYCHAD ? 100000+.RPCNT> + ;BYTE (16) LOCAL HOST, LOCAL INDEX (4) 0 + ;NOTE THIS SAVES THE UNIQUIZER BITS FOR THIS INDEX +CHSFRN: BLOCK NINDX ;BYTE (16) FOREIGN HOST, FOREIGN INDEX (4) 0 +;THESE FOUR ARE FOR BYTE-STREAM I/O +CHSOBP: BLOCK NINDX ;BYTE PNTR TO OUTPUT BUFFER, 0 IF NONE +CHSOBC: BLOCK NINDX ;BYTE COUNT, NUMBER OF BYTE SPACES LEFT IN OUTPUT BUFFER +CHSIBP: BLOCK NINDX ;BYTE PNTR TO INPUT BUFFER, 0 IF NONE +CHSIBC: BLOCK NINDX ;BYTE COUNT, NUMBER OF VALID BYTES REMAINING IN INPUT BUFFER + +CHAOSW: -1 ? 0 ;SWITCH FOR ALLOCATING INDICES +CHALCP: 0 ;LAST INDEX ALLOCATED, USED TO CIRCULARIZE ALLOCATION + +CHIRFJ: SIXBIT/CHAOS/ ? 0 ;AGENT OF CHAOS +.SEE NETUSW ;NON-ZERO ENABLES RFC'S FROM HOSTS OTHER THAN SELF. + +;METERS + +CHNPI: 0 ;NUMBER OF PACKETS INPUT (REALLY TO 10) +CHNPO: 0 ;NUMBER OF PACKETS OUTPUT (ALL CAUSES) +CHNPF: 0 ;NUMBER OF PACKETS FORWARDED +CHNSTS: 0 ;NUMBER OF STS PACKETS OUTPUT +CHNSNS: 0 ;NUMBER OF SNS PACKETS OUTPUT +CHNRTR: 0 ;NUMBER OF RETRANSMITTED PACKETS OUTPUT +CHNPFL: 0 ;NUMBER OF PACKETS DISCARDED (FORWARDING LOOP) +CHNPD: 0 ;NUMBER OF PACKETS DISCARDED (DUPLICATES) +CHNIPI: 0 ;NUMBER OF INTERNET PACKETS IN FROM CHAOSNET +CHNIPO: 0 ;NUMBER OF INTERNET FRAGMENTS OUT TO CHAOSNET + +;BUFFER QUEUES. EACH HAS A ONE-WORD HEADER, WHICH IS ZERO +;IF IT IS EMPTY, OR CONTAINS FIRST,,LAST BUFFER ADDRESS. + +CHQFRE: 0 ;FREE LIST +CHQRFC: 0 ;PENDING RFCS +CHQLSN: 0 ;PENDING LISTENS +CHCLNQ: 0 .SEE CHCLN + +CHFRBF: 0 ;NUMBER OF FREE BUFFERS +CHTTBF: 0 ;TOTAL NUMBER OF BUFFERS +IF2 CHMXBF==50.*<1024./<%CPMXW+2>> ;MAX CORE FOR CHAOS NET 50K +CHMXTM: 0 ;TIME OF LAST COMPLAINT ABOUT USING TOO MUCH CORE + +IFN T11CHP,[ +;VARIABLES FOR TEN-11 INTERFACE CONNECTING TO CHAOS NET + +.SEE T11CHS ;EXEC ADDRESS OF PDP11 COMMUNICATION AREA +T11VER=T11CHS ;VERSION NUMBER +T11I10=T11CHS+1 ;INIT 10 +T11I11=T11CHS+2 ;INIT 11 +T11PRM=T11CHS+3 ;.WORD BUFFER SIZE, # BUFFERS + ;THEN 4 SPARE DOUBLEWORDS +T11IBB: T11CHS+8 ;BEGINNING OF INPUT BUFFERS +T11IBE: 0 ;END OF INPUT BUFFERS +T11IBP: 0 ;POINTER TO NEXT INPUT BUFFER +T11OBB: 0 ;BEGINNING OF OUTPUT BUFFERS +T11OBE: 0 ;END OF OUTPUT BUFFERS +T11OBP: 0 ;POINTER TO NEXT OUTPUT BUFFER +T11BSZ: 0 ;BUFFER SIZE IN PDP10 WORDS +T11WIN: 0 ;1 WINNING, -1 HAVE TOLD 11 TO INIT, 0 NOT WINNING +T11XMQ: 0 ;QUEUED TRANSMISSION QUEUE +T11CKE: 0 ;COUNT OF CHECKSUM ERRORS +;THE FIRST 32-BIT WORD OF A BUFFER IS 0 IF IDLE, OR +;NON-ZERO IF BUFFER IS TO BE SENT TO OTHER MACHINE. +;THE SECOND 32-BIT WORD IS THE CHECKSUM, WHICH IS +;COMPUTED BY ADDING ALL THE 32-BIT WORDS, IGNORING OVERFLOW, +; AND LOGICALLY SHIFTING RIGHT ONE BIT AFTER EACH ADD; BITS SHIFTED +; OUT ON THE RIGHT ARE BROUGHT BACK IN ON THE LEFT. +;IF THE NUMBER OF 16-BIT WORDS IS ODD, THE LEFT-OVER ONE BETTER BE 0. +];T11CHP + +IFN DLCP,[ +;VARIABLES FOR INTERFACE TO CHAOS NET ON PDP11 ON DL10 +;.SEE INDICATES A VARIABLE SHARED BETWEEN 10 AND 11 +;NOTE THAT THE DL10 HARDWARE LIMITS PACKET LENGTH TO 256 WORDS (1K BYTES) + +.SEE DLCINI ;WHEN THE 11 SEES THIS NON-ZERO, IT KNOWS ITS HAS + ; BEEN RELOADED AND RESETS ITS PACKET POINTER TO 0 + ; AND CLEARS DLCINI. +DLCSBF: 0 ;CURRENT BUFFER, 10 SEND SIDE (1 OR 0) + +DLCSA1: 0 ;ADDRESS OF PACKET BEING SENT +DLCSA2: 0 ;DITTO, SECOND BUFFER +.SEE DLCSP1 ;POINTER USED BY PDP11 TO COPY PACKET (16-BIT BYTES) +.SEE DLCSP2 ;DITTO, SECOND BUFFER +.SEE DLCSS1 ;STATE FOR BUFFER 1, 0 IDLE, 1 SENT TO 11, 2 11 DONE +.SEE DLCSS2 ;STATE FOR BUFFER 2 + +DLCRA1: 0 ;ADDRESS OF PACKET BUFFER RECEIVING A PACKET +DLCRA2: 0 ;DITTO, SECOND BUFFER +.SEE DLCRP1 ;POINTER USED BY PDP11 TO COPY PACKET (16-BIT BYTES) +.SEE DLCRP2 ;DITTO, SECOND BUFFER +.SEE DLCRS1 ;STATE FOR BUFFER 1, 0 IDLE, 1 AWAITING 11, 2 CONTAINS A PACKET +.SEE DLCRS2 ;STATE FOR BUFFER 2 + +DLCXMQ: 0 ;TRANSMIT BUFFER LIST FOR DL10 + ;NOTE THAT THIS IS NOT A REGULAR BUFFER LIST SINCE + ;IT IS THREADED THROUGH LH INSTEAD OF RH. WE DO MAINTAIN + ;POINTERS TO FIRST,,LAST HOWEVER +];DLCP + +IFN CH10P,[ +;VARIABLES FOR CH10 INTERFACE ONLY + +CHXCNO: CHXREN+CHXTEN+CHXCHN ;CONO BITS CURRENTLY IN EFFECT +];CH10P + +IFN CH11P,[ +;VARIABLES FOR CH11 INTERFACE ONLY + +CHXCSR: %CAREN+%CATEN ;CURRENT BITS WANTED IN CSR +];CH11P + +IFN CH10P+CH11P,[ +;VARIABLES THAT WOULD OTHERWISE BE IN THE FRONT-END + +CHXXMQ: 0 ;HEAD,,TAIL OF TRANSMIT QUEUE +CHOSTA: 0 ;OUTPUT STATUS: 0 IDLE, ELSE NUMBER OF TRANSMISSIONS +NCHRTR==4 ;TRANSMIT UP TO 4 TIMES IN FACE OF COLLISIONS + +;ROUTING STUFF +NSUBNT==122. ;122 is maximum possible +SBNRUT: REPEAT NSUBNT, 1000,,3040 ;COST,,GATEWAY ADDRESS + +;EXTRA METERS +CHNABT: 0 ;NUMBER OF TRANSMIT ABORTS +CHNCRC: 0 ;NUMBER OF CRC ERRORS BEFORE READING PACKET +CHNCR2: 0 ;NUMBER OF CRC ERRORS AFTER READING PACKET +CHNWLE: 0 ;NUMBER OF WORD LENGTH ERRORS (NOT MULTIPLE OF 16 BITS) +CHNPLE: 0 ;NUMBER OF PACKET LENGTH ERRORS (DISAGREES WITH LENGTH IN HEADER) +CHNLOS: 0 ;NUMBER OF PACKETS LOST DUE TO RECEIVER BUSY +];CH10P+CH11P +IFN CH11P,[ +CHNSPZ: 0 ;NUMBER OF TIMERS BIT COUNTER SPAZZED +];CH11P + +BBLK + +;Get definitions of packet format + +IF1,[ +$INSRT CHSDEF + +PKTBSZ==%CPMXW+2 ;PACKET BUFFER IS 2 HEADER WORDS + MAX SIZE PACKET +IFN >-PKTBSZ, .ERR PKTBSZ IS SUPPOSED TO BE A POWER OF 2 + +$CPKSX==$CHXRI+40000,,2 ;REAL PART OF SOURCE INDEX +$CPKDX==$CHXRI+40000,,1 ;REAL PART OF DESTINATION INDEX + +];IF1 + +;;; Debugging Info + +;;; This contains the last N headers received from the network +NRECHD==20 +EBLK +RECHDP: RECHDR ;POINTER TO NEXT +RECHDR: BLOCK NRECHD*%CPKDT +BBLK + +SUBTTL CHAOS NET OPEN (.CALL CHAOSO) + +;.CALL CHAOSO,RCVCHN,XMTCHN, + +CHASO: JRST OPNL12 ; Say "mode not avail" +CHAOSO: HRRZS A + HRRZS B + CAIGE A,20 + CAIL B,20 + JRST OPNL14 ;BAD CHANNEL NUMBER ARGUMENT + CAMN A,B + JRST OPNL33 ;BOTH CHANNELS SAME IS ILLEGAL + PUSH P,A ;SAVE ARGS, CLOSE THE SPECIFIED CHANNELS + PUSH P,B + PUSH P,C + MOVE R,A + ADDI R,IOCHNM(U) + PUSHJ P,CCLOSE + MOVE R,-1(P) ;B + ADDI R,IOCHNM(U) + PUSHJ P,CCLOSE + POP P,C + POP P,B + POP P,A + MOVE U,USER ;TO SAVE ULCERS + HRRZM A,UUAC(U) ;REMEMBER INPUT CHNL # FOR ERRS + PUSHJ P,SWTL ;LOCK CHAOS INDEX ASSIGNMENT SWITCH + CHAOSW + MOVE I,CHALCP ;ALLOCATE AN INDEX + SOJL I,CHASO2 +CHASO1: SKIPL CHSUSR(I) + SOJGE I,CHASO1 + JUMPGE I,CHASO3 +CHASO2: MOVEI I,NINDX ;REACHED BEGINNING, WRAP AROUND TO END + CAMN I,CHALCP + JRST OPNL6 ;ALL INDICES IN USE + MOVEM I,CHALCP + SOJA I,CHASO1 + +CHASO3: MOVEM I,CHALCP ;SAVE SCAN POINTER FOR NEXT TIME + PUSHJ P,CHASO4 ;INIT VARIOUS STUFF + CAILE C,MXWIND ;SET UP WINDOW SIZE + MOVEI C,MXWIND ;DON'T LET USER USE UP TOO MUCH WIRED CORE + HRLZM C,CHSWIN(I) + HRRZM U,CHSUSR(I) ;VARIABLES INITIALIZED, MAKE INDEX IN USE. + DPB A,[$CHSUI,,CHSUSR(I)] + DPB B,[$CHSUO,,CHSUSR(I)] + HRLZ T,I ;SET UP USER'S IOCHNM WORDS + HRRI T,CHAIDN + ADDI A,IOCHNM(U) + MOVEM T,(A) + HRRI T,CHAODN + ADDI B,IOCHNM(U) + MOVEM T,(B) + JRST LSWPJ1 ;SUCCESS RETURN + +;INITIALIZE CONNECTION IN I +CHASO4: SETZM CHSNBF(I) + SETZM CHSNOS(I) + SETZM CHSIBF(I) + SETZM CHSPBF(I) + SETZM CHSOBF(I) + SETZM CHSACK(I) + SETZM CHSPKN(I) ;START PACKET NUMBERING AT ONE + SETZM CHSOBP(I) + SETZM CHSOBC(I) + SETZM CHSIBP(I) + SETZM CHSIBC(I) + MOVSI T,%CFOFF .SEE %CSCLS + MOVEM T,CHSSTA(I) + LDB TT,[$CHXUN+40000,,CHSLCL(I)] + CAIE TT,CHXMUN ;INCREMENT THE UNIQUIZER + AOSA TT + MOVEI TT,1 ;BUT MAKE SURE IT ISN'T ZERO + DPB TT,[$CHXUN+40000,,CHSLCL(I)] + SETZM CHSFRN(I) + POPJ P, + +SUBTTL CHAOS NET CLOSE, FINISH, WHYINT, NETBLK, CHAOSQ + +;CLOSE A CHAOS CHANNEL. +CHACLS: HLRZ I,(R) ;GET VARIABLES INDEX + MOVSI A,%CFCLS + TDNN A,CHSSTA(I) ;ONLY REALLY CLOSE WHEN BOTH CHANNELS CLOSED + JRST CHACS7 + PUSHJ P,CHACS1 ;FLUSH ALL BUFFERS OF THIS CONNECTION + HRRZ T,CHSSTA(I) + CAIN T,%CSOPN + PUSHJ P,CHABGI ;SEND A CLS IF OPEN AND MEM AVAIL + JRST CHACS4 + MOVE T,CHSFRN(I) + MOVEM T,%CPKS(A) + MOVE T,CHSLCL(I) + MOVEM T,%CPKD(A) + MOVEI B,[ASCIZ/Channel closed/] + PUSHJ P,CHIRF2 +CHACS4: CONO PI,NETOFF + SETZM (R) ;CLOSE THIS CHANNEL + SETOM CHSUSR(I) ;RETURN INDEX + MOVE W,CHQLSN ;FLUSH ANY PENDING LSN PACKET + SETZM CHQLSN +CHACS5: MOVEI Q,W ;GET NEXT PACKET OFF OLD LIST + PUSHJ P,CHAQGF + JUMPE A,NETONJ ;EXHAUSTED + LDB B,[$CPKSX(A)] ;GET OWNER + CAME B,I + JRST [ MOVEI Q,CHQLSN ;NOT THIS INDEX, PUT BACK + PUSHJ P,CHAQPL + JRST CHACS5 ] + PUSHJ P,CHABRT ;FREE + JRST CHACS5 + +CHACS7: IORM A,CHSSTA(I) .SEE %CFCLS + HRRZ B,(R) ;GET DIRECTION + CAIN B,CHAIDN ;AS A BYTE POINTER TO CHANNEL NUMBER + SKIPA B,[$CHSUI,,CHSUSR(I)] + MOVE B,[$CHSUO,,CHSUSR(I)] + MOVEI T,77 ;CLOSE THAT CHANNEL + DPB T,B + SETZM (R) + POPJ P, + +;THIS FLUSHES ALL BUFFERS FOR CONNECTION IN I +CHACS1: MOVSI A,%CFOFF ;INHIBIT RETRANSMISSIONS + IORB A,CHSSTA(I) + LDB E,[$CFTTN,,CHSSTA(I)] + EXCH E,I + TLNE A,%CFSTY + PUSHJ P,NSTYN0 ;DISCONNECT FROM STY + JFCL + EXCH E,I +IFN DLCP,[ + MOVEI Q,DLCXMQ ;REMOVE THIS INDEX'S BUFFERS FROM DL10 TRANSMIT LIST + PUSHJ P,CFLXMQ +];DLCP +IFN T11CHP,[ + MOVEI Q,T11XMQ ;REMOVE THIS INDEX'S BUFFERS FROM TEN11 TRANSMIT LIST + PUSHJ P,CFLXMQ +];T11CHP +IFN CH10P+CH11P,[ + MOVEI Q,CHXXMQ ;REMOVE THIS INDEX'S BUFFERS FROM CH10 TRANSMIT LIST + PUSHJ P,CFLXMQ +];CH10P+CH11P + MOVEI Q,CHSIBF(I) ;RETURN RECEIVE BUFFERS + PUSHJ P,CHALFR + MOVEI Q,CHSPBF(I) ;RETURN OUT OF ORDER RECEIVE BUFFERS + PUSHJ P,CHALFR + MOVEI Q,CHSOBF(I) ;RETURN TRANSMIT BUFFERS + PUSHJ P,CHALFR +IFE FTRCHK,[ + SKIPE A,CHSOBP(I) ;RETURN STREAM I/O BUFFERS + PUSHJ P,CHBPFR + SKIPE A,CHSIBP(I) + PUSHJ P,CHBPFR +];FTRCHK +IFN FTRCHK,[ + SKIPN A,CHSOBP(I) + JRST .+3 + SETZM CHSOBP(I) + PUSHJ P,CHBPFR + SKIPN A,CHSIBP(I) + JRST .+3 + SETZM CHSIBP(I) + PUSHJ P,CHBPFR +];FTRCHK + POPJ P, + +;.CALL FORCE ON A CHAOS OUTPUT CHANNEL. +CHAFRC: HLRZ I,(R) + SKIPGE CHSSTA(I) .SEE %CFOFF + JRST OPNL7 ;DEVICE NOT READY + AOS (P) ;WILL TAKE SUCCESS RETURN +CHAFC1: SKIPN A,CHSOBP(I) + POPJ P, ;NO BUFFERED OUTPUT TO BE FORCED + SUBI A,1 ;SIOKT LIKES TO POINT BP AT NEXT BUFFER + ANDI A,-PKTBSZ ;GET PACKET POINTER + ADDI A,2 + MOVSI T,(SETZ) ;DATA OPCODE + MOVEM T,(A) .SEE $CPKOP + MOVEI T,%CPMXC ;SET BYTE COUNT + SUB T,CHSOBC(I) + DPB T,[$CPKNB(A)] + PUSHJ P,[JUMPN T,CHODT1 ;IF THERE IS ANYTHING IN THE BUFFER, TRANSMIT IT + JRST CHABRT ] ;OTHERWISE, JUST THROW IT AWAY + SETZM CHSOBP(I) ;NOW THERE IS NO BUFFER + SETZM CHSOBC(I) + POPJ P, + +;.CALL FINISH ON A CHAOS OUTPUT CHANNEL. WAIT FOR ALL BUFFERS +;ON SEND LIST TO GET SENT AND ACKNOWLEDGED. +;HANGS FOREVER IF SOCKET GETS INTO AN IMPROPER STATE, BUT YOU SHOULD GET AN INTERRUPT +CHAFIN: HLRZ T,(R) + PUSHJ P,[HRRZ A,CHSWIN(T) + CAMG A,CHSNOS(T) + AOS (P) + POPJ P, ] + PUSHJ P,UFLS + JRST POPJ1 + +;.CALL WHYINT ON A CHAOS CHANNEL. +;RESULTS ARE: A/ %WYCHA +; B/ STATE +; C/ LH NUMBER OF INPUT PACKETS AVAILABLE +; RH NUMBER OF OUTPUT SLOTS AVAILABLE +; D/ WINDOW SIZE (RECEIVE,,TRANSMIT) +; E/ INPUT CHNL#,,OUTPUT CHNL# +CHAWHY: HLRZ I,(R) + MOVEI A,%WYCHA + HRRZ B,CHSSTA(I) + HRLZ C,CHSNBF(I) ;NUMBER OF PACKETS AVAILABLE + SKIPE CHSIBP(I) + ADD C,[1,,] ;ADD 1 IF PARTIALLY-READ INPUT BUFFER EXISTS + MOVSI D,%CFSTY + TDNE D,CHSSTA(I) + MOVEI C,0 ;NO INPUT AVAILABLE IF DIRECT-CONNECTED + SKIPLE CHSNOS(I) + HRR C,CHSNOS(I) + MOVE D,CHSWIN(I) + LDB E,[$CHSUO,,CHSUSR(I)] + CAIN E,77 + MOVEI E,-1 + LDB T,[$CHSUI,,CHSUSR(I)] + CAIN T,77 + TLOA E,-1 + HRL E,T + JRST POPJ1 + +;.CALL RFNAME on a CHAOS channel. A contains index. +;Returns results analogous to RFNAME on TCP: and (almost) RFNAME on NET:. +;"FN1" is local index, "FN2" is foreign index, "SNAME" is foreign host +;number in HOSTS3 format. +CHARCH: LDB B,[042000,,CHSLCL(A)] + LDB C,[042000,,CHSFRN(A)] + LDB D,[242000,,CHSFRN(A)] + TLO D,(NW%CHS) + POPJ P, + +;IOPDL ROUTINES. I IS 0 FOR IOPUSH, 1 FOR IOPOP. R POINTS AT IOCHNM WORD. +;C(R) IS SET UP TO THIS DEVICE IN EITHER CASE. +CHAIOP: HRRZ T,R ;DISCOVER CHANNEL NUMBER + SUBI T,IOCHNM(U) + SKIPN I + MOVEI T,77 ;IOPUSH, USE 77 + HLRZ I,(R) ;GET CHAOS INDEX + HRRZ B,(R) ;GET DIRECTION + CAIN B,CHAIDN ;AS A BYTE POINTER TO CHANNEL NUMBER + SKIPA B,[$CHSUI,,CHSUSR(I)] + MOVE B,[$CHSUO,,CHSUSR(I)] + DPB T,B ;ADJUST SAVED CHANNEL NUMBER + POPJ P, + +;.CALL NETBLK ON A CHAOS CHANNEL. +;ARG 1 - CHANNEL (COMES IN IN R) +;ARG 2 - UNDESIRED STATE +;ARG 3 - OPTIONAL TIMEOUT, WRITTEN BACK UNLESS IMMEDIATE +;VAL 1 - NEW STATE +;VAL 2 - TIME LEFT +CHANBK: HRRZ T,(R) + CAIL T,CHAIDN + CAILE T,CHAODN +IFN NCPP, JRST ANETBL ;NOT A CHAOS CHANNEL, TRY ARPANET +IFE NCPP, JRST OPNL34 + HLRZ I,(R) + MOVE T,I ;SAVE INDEX IN T FOR FLSINS + CAIGE W,3 + JRST [ HRLOI D,377777 ;NO TIME GIVEN, USE INFINITY + JRST CHANB4 ] + TLNE C,1000 ;SKIP IF POINTER RATHER THAN IMMEDIATE + JRST [ HRRZ D,C ;GET IMMEDIATE TIME + ADD D,TIME + JRST CHANB4 ] + XCTR XRW,[MOVES D,(C)] ;GET TIME, CHECK WRITEABILITY + JUMPGE D,[ MOVNS D ;RELATIVE TIME, MAKE NEGATIVE ABSOLUTE + SUB D,TIME + JRST .+1 ] + UMOVEM D,(C) ;STORE BACK ABSOLUTE TIME + MOVNS D ;MAKE POSITIVE +CHANB4: MOVEM D,AC0S+D(U) ;SAVE ABSOLUTE TIME TO WAIT UNTIL + MOVEM B,AC0S+B(U) ;SAVE UNDESIRED STATE + PUSHJ P,CHANB2 ;SKIP IF STATE CHANGE OR TIMEOUT + PUSHJ P,UFLS + MOVE B,D + SUB B,TIME ;HOW MUCH USED? + HRRZ A,CHSSTA(I) ;NEW STATE + JRST POPJ1 + +CHANB2: HRRZ A,CHSSTA(T) ;CURRENT STATE + CAME A,AC0S+B(U) ;SKIP IF STILL MATCH + JRST POPJ1 + MOVE A,AC0S+D(U) ;TIMEOUT TIME + CAMG A,TIME + AOS (P) + POPJ P, + +;.CALL CHAOSQ +;ARG 1 - ADDRESS OF A %CPMXW-WORD PACKET BUFFER +;FINDS THE FIRST PACKET ON THE PENDING-RFC QUEUE, COPIES IT +;INTO THE USER'S BUFFER, AND RETURNS IT TO THE QUEUE. +CHAOSQ: MOVE C,A ;SAVE POINTER TO USER'S BUFFER + HRL A,A ;MAKE SURE USER'S BUFFER IS SWAPPED IN + XCTR XBRW,[BLT A,%CPMXW-1(C)] ;AND NO MAR BREAK SET + MOVEI Q,CHQRFC ;GET FIRST PACKET ON RFC QUEUE + PUSHJ P,CHAQGF + JUMPE A,OPNL4 ;QUEUE IS EMPTY + PUSHJ P,CHAQPL ;PUT BACK AT END OF QUEUE + HRL C,A ;COPY PACKET TO USER + MOVE T,C + XCTR XBW,[BLT T,%CPMXW-1(C)] + JRST POPJ1 + +SUBTTL CHAOS NET IOT ROUTINES + +;.CALL PKTIOT. ARG1 CHANNEL, ARG2 ADDRESS OF %CPMXW-WORD BUFFER +PKTIOT: HRRZ A,(R) + CAIN A,CHAODN + JRST CHPKO + CAIE A,CHAIDN + JRST OPNL34 ;WRONG TYPE DEVICE +;CHAOSNET INPUT PKTIOT +;B POINTS TO %CPMXW-WORD PACKET BUFFER +CHPKI: PUSHJ P,CHAIOS ;SET UP I, E + HLRZ A,CHSIBF(I) ;GET FIRST RECEIVE BUFFER + JUMPE A,[PUSHJ P,CHPKI0 ;LIST EMPTY + JRST CHPKI ] + HRL B,A ;COPY TO USER BEFORE REMOVING FROM LISTS + LDB T,[$CPKNB(A)] ;GET SIZE OF PACKET + ADDI T,4*%CPKDT+3 ;HEADER PLUS ROUND-UP TO NEXT WORD BOUNDARY + LSH T,-2 ;CONVERT BYTES TO WORDS + ADDI T,-1(B) ;ADDRESS OF LAST DESTINATION WORD + XCTR XBW,[BLT B,(T)] + LDB TT,[$CPKOP(A)] ;GET OPCODE + CAIGE TT,%CODAT ;ACKNOWLEDGE IF DATA + CAIN TT,%COEOF ;OR EOF MARK + PUSHJ P,CHPKIA + SOS CHSNBF(I) ;NOW REMOVE BUFFER FROM RECEIVE LIST + MOVEI Q,CHSIBF(I) + PUSHJ P,CHAQGF + PUSHJ P,CHABRT ;AND RETURN TO FREE + JRST POPJ1 ;SUCCESS + +;INPUT WITH INPUT BUFFER EMPTY. MUSTN'T BASH B,C,E. +CHPKI0: SKIPGE CHSSTA(I) .SEE %CFOFF + JRST [ HRRZ T,CHSSTA(I) + CAIE T,%CSFRN ;CHAOSNET OR FOREIGN PROTOCOL? + JRST IOCR10 ;IOT WITH CHANNEL IN IMPROPER STATE + JRST .+1 ] ;WAIT BUT DON'T TRY TO TOUCH WINDOW SIZE + ;HERE CONSIDER INCREASING WINDOW SIZE + SKIPN CHSIBF(I) ;AWAIT INPUT + PUSHJ P,UFLS + POPJ P, ;RETRY + +;ACKNOWLEDGE DATA PACKET IN A. ITS OPCODE IN TT. +CHPKIA: LDB T,[$CPKPN(A)] ;GET PACKET # + HRLM T,CHSPKN(I) ;IT NOW NEEDS TO BE ACKNOWLEDGED + CAIN TT,%COEOF ;ALWAYS ACKNOWLEDGE EOF RIGHT AWAY + JRST CHASTO + HLRZ TT,CHSACK(I) ;GET LAST ONE REALLY ACKNOWLEDGED + SUB T,TT ;GET NUMBER OF PACKETS AWAITING ACK + SKIPGE T + ADDI T,200000 + IMULI T,3 ;MORE THAN ONE THIRD THE WINDOW SIZE? +IFN FTRCHK,[ + MOVE TT,-1(A) + CAMN TT,[ASCII/LUNCH/] + BUG PAUSE,[CHAOS BUFFER ADDRESS TRASHED],OCT,A +];FTRCHK + HLRZ TT,CHSWIN(I) + CAML T,TT + PUSHJ P,CHASTO ;YES, SEND ACK (CAN'T PCLSR) + POPJ P, + +;SET UP FOR CHAOS IOT +CHAIOS: HLRZ I,(R) ;GET INDEX + MOVE E,CHSSTA(I) + TLNE E,%CFSTY+%CFCLS + JRST IOCR10 ;CAN'T DO I/O WHILE DIRECT-CONNECTED OR HALF-CLOSED + HRRZS E ;RETURN STATE IN E + POPJ P, + +;UNIT-MODE INPUT. +;1.4 IN CTLBTS IS DON'T-HANG MODE + SKIPA T,[SIOKT] +CHAUI: MOVEI T,CHRKT + PUSHJ P,CHAIOS ;SET UP I, E + MOVE E,[440800,,4] + JSP B,(T) + CHSIBP(I) + CHSIBC(I) + CHAIBG + CHAIBD + 0 + TRNA + +;CHAOS INPUT BUFFER DISCARD +CHAIBD: SKIPN A,CHSIBP(I) + POPJ P, + SETZM CHSIBP(I) + SETZM CHSIBC(I) + JRST CHBPFR + +;CHAOS INPUT BUFFER GET +CHAIBG: HLRZ A,CHSIBF(I) ;GET FIRST RECEIVE BUFFER + JUMPE A,CHAIB2 ;NONE + LDB TT,[$CPKOP(A)] ;IS IT NORMAL DATA? + CAIE TT,%CODAT + JRST CHAIB1 ;NO + PUSHJ P,CHAIB3 ;YES, ACKNOWLEDGE AND REMOVE FROM LIST + LDB J,[$CPKNB(A)] ;SET UP FOR BYTE STREAM INPUT + MOVEI TT,%CPKDT(A) + JRST SIOBG1 + +CHAIB3: PUSH P,B + PUSH P,C + PUSH P,E + PUSHJ P,CHPKIA ;SEND ACKNOWLEDGEMENT + POP P,E + POP P,C + POP P,B + SOS CHSNBF(I) ;REMOVE BUFFER FROM RECEIVE LIST + MOVEI Q,CHSIBF(I) + JRST CHAQGF + +CHAIB1: CAIE TT,%COEOF + JRST CHAIB2 + PUSHJ P,CHAIB3 ;EOF PACKET, ACKNOWLEDGE IT + PUSHJ P,CHABRT ;RETURN IT TO FREE + JRST POPJ2 ;AND SIGNAL EOF + +CHAIB2: MOVE TT,CTLBTS(U) ;CHECK DON'T-HANG MODE + TRNE TT,10 + JRST POPJ2 ;YES, EOF + JUMPN A,IOCR10 ;NO, ABNORMAL PACKET, BARF + PUSHJ P,CHPKI0 ;AWAIT INPUT + JRST CHAIBG ;RETRY + +;UNIT-MODE OUTPUT. +;1.4 IN CTLBTS IS DON'T-HANG MODE + SKIPA T,[SIOKT] +CHAUO: MOVEI T,CHRKT + PUSHJ P,CHAIOS ;SET UP I, E + CAIE E,%CSOPN + JRST IOCR10 ;NOT OPEN, ERROR + MOVE E,[440800,,4] + JSP B,(T) + SETZ CHSOBP(I) + CHSOBC(I) + CHAOBG + CHAOBW + 0 + TRNA + +;GET NEW OUTPUT BUFFER +CHAOBG: SKIPG CHSNOS(I) ;WINDOW FULL + PUSHJ P,[ MOVE TT,CTLBTS(U) + TRNN TT,10 + JRST UFLS + SUB P,[1,,1] + JRST POPJ2 ] ;DON'T HANG MODE, RETURN "EOF" + PUSH P,B + PUSHJ P,CHABGT ;SET UP AN OUTPUT BUFFER + POP P,B + + MOVEI TT,%CPKDT(A) + MOVEI J,%CPMXC + JRST SIOBG1 + +;WRITE OUTPUT BUFFER +CHAOBW: PUSH P,B + PUSH P,C + PUSH P,E + PUSHJ P,CHAFC1 + POP P,E + JRST POPCBJ + +;CHAOSNET OUTPUT PKTIOT. +;B POINTS TO %CPMXW-WORD PACKET BUFFER +CHPKO: PUSHJ P,CHAIOS ;SET UP I, E + UMOVE H,(B) ;GET HEADER WORD OF USER'S PACKET BUFFER + LDB D,[$CPKNB H] ;GET BYTE COUNT + CAIG D,%CPMXC + TLNE H,(.BM $CPKMV) ;WE DON'T SUPPORT MUPPETS ANY MORE + JRST IOCER3 ;BYTE LENGTH OUT OF BOUNDS + ADDI D,4*%CPKDT+3 ;CONVERT BYTES TO WORDS, INCLUDING HEADER WDS + LSH D,-2 + MOVSI J,1(B) ;SAVE ADDRESS+1 OF USER'S PACKET + PUSHJ P,CHABGT ;GET A BUFFER + PUSHJ P,LOSSET ;RETURN IT IF PCLSR + CHPKO2 + MOVEM H,(A) ;STORE PACKET HEADER, NOT STORED WITH BLT + HRRI J,1(A) ; BECAUSE MIGHT HAVE CHANGED AFTER ERROR CHECK + ADDI D,-1(A) + XCTR XBR,[BLT J,(D)] ;COPY USER'S PACKET INTO SYSTEM + AOS (P) ;GOING TO SUCCEED + SKIPGE (A) ;SKIP IF CONTROL PACKET + JRST CHODAT ;DATA + LDB D,[$CPKOP(A)] ;GET OPCODE + CAIGE D,%COMAX ;DISPATCH ON IT + JRST @.+1(D) + OFFSET -. + JRST IOCER3 ;OPCODE OUT OF BOUNDS +%CORFC::JRST CHORFC +%COOPN::JRST CHOOPN +%COCLS::JRST CHOCLS +%COFWD::JRST CHOFWD +%COANS::JRST CHOFWD +%COSNS::JRST IOCER3 +%COSTS::JRST IOCER3 +%CORUT::JRST IOCER3 +%COLOS::JRST IOCER3 +%COLSN::JRST CHOLSN +%COMNT::JRST IOCER3 +%COEOF::JRST CHOEOF +%COUNC::JRST CHOUNC +%COBRD::JRST IOCER9 ;UNTIL I IMPLEMENT IT +%COMAX::OFFSET 0 + +;LOSSET ROUTINE TO RETURN BUFFER A POINTS TO. +CHPKO2: MOVE A,AC0S+A(U) + PUSH P,Q ;MAY CLOBBER ONLY A AND T + PUSHJ P,CHABRT + JRST POPQJ + +;SENDING %COEOF (END-FILE MARK) +CHOEOF: CAIE E,%CSOPN ;CONNECTION MUST BE OPEN + JRST IOCR10 + SKIPG CHSNOS(I) + PUSHJ P,UFLS ;WINDOW FULL, WAIT + JRST CHOOP1 ;SEND RETRANSMITTABLE CONTROL PACKET + +;SENDING REQUEST FOR CONNECTION +CHORFC: PUSHJ P,CHORF1 ;RE-INITIALIZE CONNECTION + MOVSI B,777774 ;SAVE DESTINATION HOST, CLEAR OTHER BITS + ANDB B,%CPKD(A) + MOVEM B,CHSFRN(I) + MOVEI E,%CSRFS ;PUT INTO RFC-SENT STATE + JRST CHOOP1 ;GO SEND + +;RE-INITIALIZE CONNECTION WHEN USER OUTPUTS RFC OR LSN +;FLUSHES ANY OLD PACKET BUFFERS, CHANGES UNIQUIZER IN INDEX# +CHORF1: JUMPN E,IOCR10 .SEE %CSCLS ;CONNECTION MUST BE CLOSED + PUSH P,A + PUSH P,B + PUSHJ P,CHACS1 ;FLUSH BUFFERS FROM CONNECTION + PUSHJ P,CHASO4 ;REINITIALIZE VARIABLES + JRST POPBAJ + +;"SENDING" LISTEN +CHOLSN: PUSHJ P,CHORF1 + PUSHJ P,LSWDEL ;GOING TO USE PACKET + MOVEI E,%CSLSN ;PUT INTO LISTENING STATE + HRRM E,CHSSTA(I) + MOVEI Q,CHQRFC ;NOW SEARCH PENDING-RFC QUEUE + CONO PI,NETOFF + PUSHJ P,CHAQSR + JRST [ CONO PI,NETON ;NO MATCH, PUT ONTO LISTENING QUEUE + MOVEI Q,CHQLSN + MOVE T,CHSLCL(I) + MOVEM T,%CPKS(A) + JRST CHAQPL ] + PUSHJ P,CHIRF0 ;MATCH, JOIN INTERRUPT LEVEL CODE + JRST NETONJ + +;SENDING OPEN +CHOOPN: CAIE E,%CSRFC ;CONNECTION MUST BE RFC-RECEIVED + JRST IOCR10 + MOVEI TT,4 ;SET BYTE COUNT TO 4 + DPB TT,[$CPKNB(A)] + PUSHJ P,DPBRCP ;INCLUDE RECEIPT + HLRZ B,CHSWIN(I) ;INCLUDE WINDOW SIZE + DPB B,[042000,,%CPKDT(A)] + MOVEI E,%CSOPN ;MAKE IT OPEN +;HERE TO SEND A RETRANSMITTABLE CONTROL PACKET (RFC OR OPN), NEW STATE IN E +;THIS PACKET WILL GET TAKEN OFF THE CHSOBF LIST BY RECEIPT IN THE NORMAL WAY +;THIS CODE COPIED FROM CHODAT WITH SOME MODIFICATIONS +CHOOP1: MOVE T,TIME ;UPDATE CHSITM SO WON'T THINK HOST IS DOWN + MOVEM T,CHSITM(I) + MOVEM E,CHSSTA(I) ;AND CLEAR %CFOFF (NO OTHER LH FLAGS CAN BE ON) + PUSHJ P,LSWDEL ;BUFFER WILL BE USED + HRRZ B,CHSPKN(I) ;ASSIGN PACKET NUMBER + CAIL B,177777 + TDZA B,B + ADDI B,1 + HRRM B,CHSPKN(I) + DPB B,[$CPKPN(A)] + HLRZ B,CHSPKN(I) ;GET PACKET NUMBER TO ACKNOWLEDGE + HRLM B,CHSACK(I) ;REMEMBER IT HAS BEEN + DPB B,[$CPKAN(A)] ;PIGGY-BACK THIS ACKNOWLEDGE + MOVE B,[<.BM $CPKOP>+<.BM $CPKNB>] + ANDM B,(A) ;CLEAR FORWARDING COUNT AND UNUSED FIELD + MOVE B,CHSLCL(I) ;SET UP SOURCE + MOVEM B,%CPKS(A) + MOVE D,CHSFRN(I) ;SET UP DESTINATION + MOVEM D,%CPKD(A) + SETOM -2(A) ;NOTE NOT ON TRANSMIT LIST YET + CONI PI,E ;SUPER KLUDGERY REQUIRED HERE! FOREIGN HOST MIGHT RECEIPT + CONO PI,NETOFF ;THIS PACKET JUST AS WE START TO TRANSMIT IT. THIS IS A + ;VIOLATION OF PROTOCOL, BUT SHOULDN'T CRASH I.T.S. BECAUSE THE + ;PACKET ABOUT TO BE GIVEN TO CHAXMT HAS BEEN FREED ALREADY. + MOVEI Q,CHSOBF(I) ;PUT ON END OF SEND LIST + PUSHJ P,CHAQPL + JRST CHAXM0 ;GO TRANSMIT + +;SENDING CLOSE +CHOCLS: CAIE E,%CSOPN ;CONNECTION MUST BE OPEN +;SEND FWD OR ANS +CHOFWD: CAIN E,%CSRFC ; OR RFC-RECEIVED + TLOA E,%CFOFF ;PUT IT INTO THE CLOSED STATE + JRST IOCR10 + HLLZM E,CHSSTA(I) .SEE %CSCLS + PUSHJ P,LSWDEL ;BUFFER WILL BE USED + JRST CHODT2 ;GO TRANSMIT + +;Here for transmitting an UNC packet. It could be part of a connection +;or it could be foreign-protocol mode. In any case transmit it without +;munging the header very much. +CHOUNC: CAIN E,%CSFRN + JRST CHOUN1 ;Okay to transmit UNC now + CAIN E,%CSOPN + JRST CHOUN2 + JUMPN E,IOCR10 .SEE %CSCLS ;Bad state + SKIPE CHSPBF(I) ;I guess out of order packets would + JRST IOCR10 ; cause some confusion in the NCP. + MOVE E,[%CFOFF,,%CSFRN] ;Put into foreign-protocol state + MOVEM E,CHSSTA(I) +CHOUN1: MOVE D,%CPKD(A) ;Save destination + MOVEM D,CHSFRN(I) +CHOUN3: MOVE B,CHSLCL(I) ;Set up source + MOVEM B,%CPKS(A) + PUSHJ P,LSWDEL + SETOM -2(A) + JRST CHAXMT + +CHOUN2: MOVE D,CHSFRN(I) ;Set up destination + MOVEM D,%CPKD(A) + JRST CHOUN3 + +OVHMTR CHX + +;SENDING REGULAR PACKET +CHODAT: CAIE E,%CSOPN ;CONNECTION MUST BE OPEN + JRST IOCR10 + SKIPG CHSNOS(I) + PUSHJ P,UFLS ;WINDOW FULL, WAIT + PUSHJ P,LSWDEL ;BUFFER WILL BE USED +CHODT1: HRRZ B,CHSPKN(I) ;ASSIGN PACKET NUMBER + CAIL B,177777 + TDZA B,B + ADDI B,1 + HRRM B,CHSPKN(I) + DPB B,[$CPKPN(A)] +CHODT2: HLRZ B,CHSPKN(I) ;GET PACKET NUMBER TO ACKNOWLEDGE + HRLM B,CHSACK(I) ;REMEMBER IT HAS BEEN + DPB B,[$CPKAN(A)] ;PIGGY-BACK THIS ACKNOWLEDGE + MOVE B,[<.BM $CPKOP>+<.BM $CPKNB>] + ANDM B,(A) ;CLEAR FORWARDING COUNT AND UNUSED FIELD + MOVE B,CHSLCL(I) ;SET UP SOURCE + MOVEM B,%CPKS(A) + MOVE D,CHSFRN(I) ;SET UP DESTINATION + MOVEM D,%CPKD(A) + SETOM -2(A) ;NOTE NOT ON TRANSMIT LIST YET + SKIPL (A) ;SKIP IF DATA PACKET + JRST CHAXMT + CONI PI,E ;SUPER KLUDGERY REQUIRED HERE! FOREIGN HOST MIGHT RECEIPT + CONO PI,NETOFF ;THIS PACKET JUST AS WE START TO TRANSMIT IT. THIS IS A + ;VIOLATION OF PROTOCOL, BUT SHOULDN'T CRASH I.T.S. BECAUSE THE + ;PACKET ABOUT TO BE GIVEN TO CHAXMT HAS BEEN FREED ALREADY. + MOVEI Q,CHSOBF(I) ;PUT ON END OF SEND LIST + PUSHJ P,CHAQPL + SOSA CHSNOS(I) ;USE UP WINDOW, SKIP +;SKIPS THROUGH INTO CHAXMT + ;SKIPS IN +SUBTTL CHAOS NET PACKET TRANSMIT ROUTINE + +;CALL WITH PACKET IN A, SMASHES B, C, D, E, T, TT, Q, J +;USES E TO SAVE THE PI STATUS, NOTHING BETTER CLOBBER THIS, OR, BOY, WILL IT EVER LOSE! +;YOU BETTER SETOM -2(A) BEFORE CALLING THIS, AND IF YOU'RE +;PUTTING IT ON A SEND LIST, DO THAT FIRST ALSO. +;THIS CODE ASSUMES THERE IS ONLY ONE INTERFACE, AND IT IS ON A +;PDP11 WHICH WILL TAKE CARE OF THE ROUTING. +;;THIS ROUTINE IS SKIPPED INTO FROM THE PREVIOUS PAGE! +CHAXMT: CONI PI,E ;SAVE PI STATUS BEFORE TURNING NETOFF; CALLED FROM MANY LEVELS +CHAXM0: ANDI E,177 + AOS CHNPO + MOVE T,TIME + MOVEM T,-1(A) ;SET TIME OF LAST TRANSMISSION + CONO PI,NETOFF ;ONE PROCESS AT A TIME, TO PROTECT INTERFACE VARIABLES +IFN FTRCHK,[ + HLRZ J,-2(A) ;I TOLD YOU TO SETOM -2(A) + CAIE J,-1 + BUG PAUSE,[CHAOS BUFFER THREAD TRASHED],OCT,A,OCT,-2(A) +];FTRCHK +IFN DLCP,[ +;FOR NOW, JUST ALWAYS SHIP IT OUT THE DL10 +IFN FTRCHK,[ + HLRZ J,DLCXMQ ;MAKE SURE NOT PUTTING ON LIST TWICE + JUMPE J,.+7 + CAMN J,A + BUG PAUSE,[CHAOS BUFFER ALREADY ON DLCXMQ],OCT,A + HLRZ J,-2(J) + CAIN J,-1 + BUG PAUSE,[DLCXMQ THREAD TRASHED] + JUMPN J,.-5 + MOVEI J,1 ;MAKE SURE NOT ACTIVE TO 11 + HRRZ T,DLCSA1(J) + CAMN T,A + BUG PAUSE,[CHAOS BUFFER ALREADY ACTIVE TO 11],OCT,A + SOJGE J,.-3 +];FTRCHK + HRRZS -2(A) ;PUT END-LIST INDICATOR IN LH (FLAGS TRANSMIT ACTIVE) + MOVE J,DLCSBF ;SEE IF SEND BUFFER IS FREE + SKIPE DLCSS1(J) + JRST CHXMD1 + PUSHJ P,DLCXMT ;YES, SEND THE PACKET NOW + JRST CHXMD2 + +CHXMD1: HRRZ B,DLCXMQ ;NO BUFFERS FREE RIGHT NOW, QUEUE + JUMPE B,[ HRLZM A,DLCXMQ ? JRST .+2 ] + HRLM A,-2(B) + HRRM A,DLCXMQ +CHXMD2: CONO PI,PICON(E) ;RESTORE PI + POPJ P, +];DLCP +IFN T11CHP,[ +;FOR NOW, JUST ALWAYS SHIP IT OUT THE TEN11 + PUSHJ P,T11CHK ;SEE IF TEN-11 IS READY + JRST CHXME3 ;NO + SKIPE @T11OBP ;SEE IF HAVE AVAILABLE OUTPUT BUFFER + JRST CHXME1 ;NO + PUSHJ P,T11XMT ;SEND THE PACKET NOW + JRST CHXME2 + +CHXME3: HRROS T,-2(A) ;TEN11 DOWN, DISCARD PACKET + AOJN T,CHXME2 + PUSHJ P,CHABRT + JRST CHXME2 + +CHXME1: HRRZ B,T11XMQ ;NO BUFFERS FREE RIGHT NOW, QUEUE + JUMPE B,[ HRLZM A,T11XMQ ? JRST .+2 ] + HRLM A,-2(B) + HRRM A,T11XMQ + HRRZS -2(A) ;PUT END-LIST INDICATOR IN LH +CHXME2: CONO PI,PICON(E) ;RESTORE PI + POPJ P, +];T11CHP +IFN CH10P,[ +;FOR NOW, JUST ALWAYS SHIP IT OUT THE CH10 + HRRZ B,CHXXMQ ;ADD TO END OF TRANSMIT QUEUE + JUMPE B,[ HRLZM A,CHXXMQ ? JRST .+2 ] + HRLM A,-2(B) + HRRM A,CHXXMQ + HRRZS -2(A) ;PUT END-LIST INDICATOR IN LH + MOVEI B,CHXTEN ;ENABLE TRANSMIT-DONE INTERRUPT + IORM B,CHXCNO + CONO CHX,@CHXCNO + CONO PI,PICON(E) ;RESTORE PI + POPJ P, +];CH10P +IFN CH11P,[ +;FOR NOW, JUST ALWAYS SHIP IT OUT THE CH11 + HRRZ B,CHXXMQ ;ADD TO END OF TRANSMIT QUEUE + JUMPE B,[ HRLZM A,CHXXMQ ? JRST .+2 ] + HRLM A,-2(B) + HRRM A,CHXXMQ + HRRZS -2(A) ;PUT END-LIST INDICATOR IN LH + MOVEI B,%CATEN ;ENABLE TRANSMIT-DONE INTERRUPT + IORB B,CHXCSR + IOWRI B,CAICSR + CONO PI,PICON(E) ;RESTORE PI + POPJ P, +];CH11P + +SUBTTL CHAOS NET DIRECT CONNECT TO STY + +OVHMTR CHS + +;CALLED AT CLOCK LEVEL FROM STYNTC WHEN A CHAOS STY IS ENCOUNTERED +;TTY NUMBER IN I & R +STYCHA: MOVE I,STYNTI-NFSTTY(R) ;GET CHAOS INDEX + MOVE TT,CHSSTA(I) + TLNN TT,%CFSTY + JRST 4,. ;CHAOS CONNECTION CLAIMS NOT BE CONNECTED? + JUMPL TT,STYCH9 .SEE %CFOFF ;OK TO USE? IF NOT, DISCONNECT + SKIPGE TTYOAC(R) ;ANY OUTPUT? + JRST STYCH1 ;NO, CHECK FOR INPUT + SKIPN D,CHSOBP(I) ;IF BUFFER ALLOCATED, USE IT + JRST [ SKIPG CHSNOS(I) ;OTHERWISE ALLOCATE ONE + JRST STYCH1 ;WINDOW FULL, WAIT UNTIL REACTIVATED + PUSHJ P,CHABGI + JRST STYCH3 ;NO CORE, WAIT ONE CLOCK TICK + MOVEI D,%CPKDT(A) + HRLI D,440800 + MOVEM D,CHSOBP(I) + MOVEI E,%CPMXC + MOVEM E,CHSOBC(I) + JRST .+3 ] + SKIPG E,CHSOBC(I) + JRST STYCH4 ;BUFFER FULL, FORCE IT + EXCH R,I ;I GETS TTY, R GETS CHAOS + CONO PI,TTYOFF + MOVEM D,DBBBP ;SET UP BUFFER FOR TTY OUTPUT INTERRUPT LEVEL + MOVEM E,DBBCC + MOVEM E,DBBCC1 + PUSH P,R + SETOM TYPNTF + PUSHJ P,TYP ;GENERATE OUTPUT + SETZM TYPNTF + POP P,R + EXCH R,I ;I GETS CHAOS, R GETS TTY + MOVE D,DBBBP ;ADVANCE POINTERS + MOVEM D,CHSOBP(I) + MOVE E,DBBCC + SUB E,DBBCC1 ;MINUS # CHARS OUTPUT GENERATED + CONO PI,TTYON + ADDM E,CHSOBC(I) +STYCH4: PUSHJ P,CHAFC1 ;FORCE THE BUFFER + JRST STYCHA ;CHECK FOR MORE OUTPUT + +STYCH3: PUSHJ P,CHINTI ;REACTIVATE SO WILL COME BACK ON NEXT CLOCK TICK +STYCH1: SOSGE CHSIBC(I) ;GET INPUT, IF ANY + JRST [ PUSHJ P,CHAIBD ;DISCARD EXHAUSTED INPUT BUFFER, IF ANY + HLRZ A,CHSIBF(I) + JUMPE A,STYNT8 ;NONE, RETURN TO STYNTC + LDB TT,[$CPKOP(A)] + CAIE TT,%CODAT + JRST STYCH9 ;RANDOM PACKET, DISCONNECT + PUSHJ P,CHPKIA ;ACKNOWLEDGE GOBBLING OF THIS PACKET + SOS CHSNBF(I) ;REMOVE BUFFER FROM RECEIVE LIST + MOVEI Q,CHSIBF(I) + PUSHJ P,CHAQGF + LDB E,[$CPKNB(A)] ;SET UP FOR BYTE STREAM INPUT + MOVEM E,CHSIBC(I) + MOVEI D,%CPKDT(A) + HRLI D,440800 + MOVEM D,CHSIBP(I) + JRST STYCH1 ] + ILDB A,CHSIBP(I) ;GET CHARACTER OF INPUT + TRNE A,200 + JRST [ AOS CHSIBC(I) ;WOOPS, SPECIAL CHARACTER, NEEDS USER ATTENTION + MOVSI A,8_14 ;SO PUT IT BACK AND DISCONNECT + ADDM A,CHSIBP(I) + JRST STYCH9 ] + EXCH R,I ;I GETS TTY, R GETS CHAOS + PUSH P,R + PUSH P,I + CONO PI,TTYOFF + PUSHJ P,NTYI5 ;GIVE CHARACTER TO TTY INPUT INTERRUPT LEVEL + CONO PI,TTYON + POP P,R + POP P,I ;I GETS CHAOS, R GETS TTY ((POP IN REVERSE ORDER)) + JRST STYCH1 ;TRY FOR MORE INPUT + +STYCH9: PUSH P,I + MOVE I,R ;I GETS TTY + PUSHJ P,NSTYN0 ;DISCONNECT THE STY + JRST 4,. + POP P,I ;I GETS CHAOS + PUSHJ P,CHINTI ;WAKE UP THE TELNET SERVER + JRST STYNT8 ;GO HANDLE OTHER STYS + +SUBTTL CHAOS NET CLOCK LEVEL STUFF + +OVHMTR CHC + +;HERE FROM 1/2 SECOND CLOCK. DO RETRANSMISSIONS AND DELAYED STS'S +CHACLK: +IFN DLCP,[ + CONO PI,NETOFF + PUSHJ P,DLCIBG ;GET MEMORY FOR INPUT BUFFERS IF NEEDED + CONO PI,NETON +];DLCP + MOVEI I,NINDX-1 ;SCAN ALL INDICES +CHACL0: SKIPL CHSUSR(I) ;SKIP THIS ONE IF NOT IN USE + SKIPGE CHSSTA(I) .SEE %CFOFF ;OR INHIBITED FROM PI LEVEL + SOJGE I,CHACL0 + JUMPL I,CPOPJ ;JUMP IF ALL INDICES DONE + PUSHJ P,CHARTR ;RETRANSMIT IF NEEDED + MOVSI B,%CFSTS + TDNE B,CHSSTA(I) ;SEND STS IF NEEDED + PUSHJ P,CHASTO + SOJGE I,CHACL0 + POPJ P, + +;HERE EVERY 5 SECONDS, TO DO PROBES +CHA5CL: MOVEI I,NINDX-1 ;SCAN ALL INDICES +CHA5C0: SKIPL CHSUSR(I) ;SKIP IF THIS ONE NOT IN USE + SKIPGE CHSSTA(I) .SEE %CFOFF ;OR INHIBITED FROM PI LEVEL +CHA5C1: SOJGE I,CHA5C0 + JUMPL I,CHA5C4 ;JUMP IF ALL INDICES DONE + MOVE T,TIME + SUB T,CHSITM(I) ;TIME SINCE LAST COMMUNICATION FROM OTHER END + CAILE T,90.*30. + JRST [ MOVEI W,%CSINC ;TOO LONG, CONNECTION BROKEN + PUSHJ P,CHINT + JRST CHA5C1 ] + HRRZ B,CHSSTA(I) ;ONLY PROBE IF OPEN (COULD BE RFC-SENT) + CAIE B,%CSOPN + JRST CHA5C1 + HRRZ B,CHSWIN(I) ;SEE IF NO TRANSMIT WINDOW (LOST STS DURING OPEN) + JUMPE B,CHA5C2 + HRRZ B,CHSACK(I) ;SEE IF AWAITING ACK (WINDOW NOT EMPTY) + HRRZ C,CHSPKN(I) + CAMN B,C + CAIL T,60.*30. +CHA5C2: PUSHJ P,CHABGI ;AWAITING ACK OR IDLE FOR 1 MINUTE, PROBE + JRST CHA5C1 ;NO PROBE, OR NO BUFFER AVAILABLE + MOVSI T,(.DPB %COSNS,($CPKOP),0) ;SENSE PACKET, BYTE-COUNT=0 + MOVEM T,(A) + AOS CHNSNS + PUSHJ P,CHODT2 + JRST CHA5C1 + +CHA5C4: MOVEI B,[ASCIZ/Timeout/] + MOVEI Q,CHQRFC ;TIME-OUT FIRST RFC ON LIST + PUSHJ P,CHAQGF + JUMPE A,CHA5C5 + MOVE T,-1(A) + ADDI T,60.*30. ;TIME-OUT IS ONE MINUTE + PUSHJ P,[ CAMG T,TIME + JRST CHIRF2 + JRST CHAQPF ] +CHA5C5: +IFN CH10P,[ + MOVEI T,CHXREN+CHXTEN ;WAKE UP IN CASE OF TIMING ERROR + IORM T,CHXCNO ;IN DEALING WITH CHXCNO + CONO CHX,@CHXCNO + MOVSI T,-NSUBNT ;DECAY ROUTING COSTS + CONO PI,NETOFF ;PREVENT RUT PACKET FROM COMING IN +CHA5C6: HLRZ TT,SBNRUT(T) + ADDI TT,1 + CAIG TT,1000 + HRLM TT,SBNRUT(T) + AOBJN T,CHA5C6 + CONO PI,NETON +];CH10P +IFN CH11P,[ + MOVEI T,%CAREN+%CATEN ;WAKE UP IN CASE OF TIMING ERROR + IORB T,CHXCSR ;IN DEALING WITH CHXCSR + IOWRI T,CAICSR + MOVSI T,-NSUBNT ;DECAY ROUTING COSTS + CONO PI,NETOFF ;PREVENT RUT PACKET FROM COMING IN +CHA5C6: HLRZ TT,SBNRUT(T) + ADDI TT,1 + CAIG TT,1000 + HRLM TT,SBNRUT(T) + AOBJN T,CHA5C6 + CONO PI,NETON +];CH11P + MOVEI T,5*60. + MOVEI C,CHA5CK + JRST CLQREE + +OVHMTR CHR + +;RETRANSMIT FOR INDEX IN I +CHARTR: CONI PI,W ;SAVE PI CHANNELS ACTIVE + ANDI W,177 ;CHAXMT BETTER NOT CLOBBER W! + CONO PI,NETOFF ;PI BETTER BE OFF THROUGHOUT THIS ZONE + ; SO WE DON'T GET INTO CHIACK + HLRZ A,CHSOBF(I) ;SCAN DOWN OUTPUT BUFFER LIST + JUMPE A,CHART2 ;EMPTY +CHART1: MOVE T,-1(A) ;DON'T RETRANSMIT IF DONE TOO RECENTLY + HLRZ TT,-2(A) ;OR IF ALREADY ON ITS WAY OUT (DON'T LINK TWICE ON XMIT LIST) + CAME T,TIME + CAIE TT,-1 + JRST CHART2 ;ANYTHING AFTER THIS IS LIKELY TO LOSE ALSO + AOS CHNRTR + PUSHJ P,CHAXMT ;RETRANSMIT THIS +; HRRZ A,-2(A) ;THREAD TO NEXT +; JUMPN A,CHART1 +CHART2: CONO PI,PICON(W) + POPJ P, + +;THIS ROUTINE SENDS A STS PACKET, OR TRIES TO. FAILURE => SLOW CLOCK WILL TRY AGAIN. +;CANNOT PCLSR NOR WAIT, CALLABLE FROM INTERRUPT LEVEL. +;INDEX IN I, CLOBBERS A,B,C,D,E,T,TT,Q,J +CHASTO: MOVSI D,%CFSTS + IORM D,CHSSTA(I) + PUSHJ P,CHABGI ;GET A BUFFER, WITHOUT WAITING + POPJ P, ;CAN'T GET ONE, WILL RETRY AT CLOCK LEVEL + ANDCAM D,CHSSTA(I) ;OK, A STS WILL BE SENT, CLEAR NEED-STS FLAG + MOVE T,[.DPB %COSTS,($CPKOP),<.DPB 4,($CPKNB),0>] + MOVEM T,(A) ;SEND A STS WITH 4 DATA BYTES + PUSHJ P,DPBRCP ;FIRST PAIR IS RECEIPT + HLRZ B,CHSWIN(I) ;SECOND PAIR IS WINDOW SIZE + DPB B,[042000,,%CPKDT(A)] + AOS CHNSTS + JRST CHODT2 ;FIRE IT OFF + +DPBRCP: HLRZ B,CHSPKN(I) + SKIPE T,CHSIBF(I) + LDB B,[$CPKPN(T)] + DPB B,[242000,,%CPKDT(A)] + POPJ P, + +SUBTTL CHAOS NET INTERRUPT-LEVEL INPUT PROCESSING + +OVHMTR CHI + +;PROCESS A PACKET RECEIVED AT INTERRUPT LEVEL. BY THE TIME WE GET HERE +; A BUFFER HAS BEEN ALLOCATED AND FILLED WITH THE DATA FROM THE DEVICE. +; ITS ADDRESS IS IN A. RETURN VIA POPJ P, WITH ALL REGISTERS CLOBBERED. +CHAPII: MOVE B,RECHDP ;SAVE HEADER FOR DEBUGGING IN RING BUFFER + MOVEI D,%CPKDT(B) + HRL B,A + BLT B,-1(D) + CAIN D,RECHDR+ + MOVEI D,RECHDR + MOVEM D,RECHDP + ;END OF DEBUGGING CODE + LDB D,[$CPKMV(A)] ;MUPPET? + JUMPN D,CHABRT ;FLUSH, NOT SUPPORTED + LDB D,[$CPKOP(A)] ;GET OPCODE + LDB B,[$CPKDA(A)] ;CHECK DESTINATION + CAIE B,MYCHAD ;IF FOR ME, + SKIPN B ;OR FOR ME BY VIRTUE OF BROADCAST + AOSA CHNPI ;ACCEPT IT + JRST CHAPFW ;NOT ME, FORWARD + LDB C,[$CPKNB(A)] ;PASS LENGTH IN C TO OP ROUTINES + MOVEI B,[ASCIZ/Illegal byte count/] + CAILE C,%CPMXC + JRST CHALOS + SKIPGE (A) ;TEST OPCODE + JRST CHIDAT ;DATA PACKET + MOVEI B,[ASCIZ/Illegal opcode/] + CAIGE D,%COMAX + JRST @.+1(D) + OFFSET -. + JRST CHALOS ;ILLEGAL, FLUSH +%CORFC::JRST CHIRFC +%COOPN::JRST CHIOPN +%COCLS::JRST CHICLS +%COFWD::JRST CHIANS +%COANS::JRST CHIANS +%COSNS::JRST CHISNS +%COSTS::JRST CHISTS +%CORUT:: +IFE CH10P+CH11P,JRST CHABRT ;IGNORE +IFN CH10P+CH11P,JRST CHIRUT +%COLOS::JRST CHILOS +%COLSN::JRST CHALOS ;ILLEGAL, FLUSH +%COMNT::JRST CHABRT ;IGNORE +%COEOF::JRST CHIDAT +%COUNC::JRST CHIUNC +%COBRD::JRST CHIBRD +%COMAX::OFFSET 0 + +;FORWARDING +CHAPFW: LDB B,[$CPKDA(A)] ;CHECK DESTINATION HOST + TRNN B,377_8 ;SUBNET 0? + JRST CHABRT ;FLUSH IT, XX-NETWORK-11 IS TRYING TO MAKE US CRASH + LDB B,[$CPKFC(A)] ;INCREMENT FORWARDING COUNT + ADDI B,1 + CAIL B,20 + JRST [ AOS CHNPFL ? JRST CHABRT ] ;LOOP, DISCARD + DPB B,[$CPKFC(A)] + SETOM -2(A) ;NOT ON SEND LIST + AOS CHNPF + JRST CHAXMT + +IFN CH10P+CH11P,[ ;INCOMING ROUTING INFO +CHIRUT: LSH C,-2 ;NUMBER OF SUBNET ENTRIES + JUMPE C,CHABRT ;COULD BE ZERO-LENGTH + MOVEI D,%CPKDT(A) + HRLI D,442000 + LDB E,[$CPKSA(A)] ;SOURCE HOST IS GATEWAY +CHIRU1: ILDB T,D ;SUBNET + ILDB TT,D ;COST + HLRZ B,SBNRUT(T) ;COST OF EXISTING ROUTE + CAIGE T,NSUBNT + CAMLE TT,B + JRST CHIRU2 + HRLM TT,SBNRUT(T) ;THIS IS BEST ROUTE NOW + HRRM E,SBNRUT(T) +CHIRU2: SOJG C,CHIRU1 + JRST CHABRT +];CH10P+CH11P + +;INTERRUPT-LEVEL PROCESSING OF SNS PACKET +;NOTE THAT WE DO NOT BARF AT SNS'S TO EXISTENT NON-OPEN CONNECTIONS. IF IT +;WAS AN RFC-SENT CONNECTION, THIS COULD BREAK IT PREMATURELY IF AN OPN WAS +;LOST AND THEN A SNS WAS NOT. +CHISNS: MOVEI E,%CSOPN + PUSHJ P,CHFNDX + JRST [ CAIE E,%CSOPN + JRST CHABRT ;CONNECTION EXISTS AND IS NOT OPEN, IGNORE PACKET + JRST CHALOS ] ;CONNECTION DOES NOT EXIST, COMPLAIN + PUSHJ P,CHABRT ;CONNECTION DOES EXIST + CAIE E,%CSOPN + POPJ P, ;NOT OPEN, IGNORE + JRST CHASTO ;REPLY WITH STS + +;INTERRUPT LEVEL PROCESSING OF RECEIVED FWD OR ANS +CHIANS: PUSHJ P,CHFNDX ;FIND CONNECTION + JRST CHABRT ;NOBODY AT OTHER END TO RECEIVE A LOS ANYWAY + CAIE E,%CSRFS + JRST CHABRT ;NOT IN RFC-SENT STATE, LOSS +; JRST CHICL1 ;CLOSE THE CONNECTION BUT GIVE TO USER AS INPUT + ;DROPPING THROUGH WILL DO + +;INTERRUPT LEVEL PROCESSING OF RECEIVED CLS PACKET +CHICLS: PUSHJ P,CHFNDX ;FIND CONNECTION BEING CLOSED + JRST CHALOS ;NONE, LOSS +CHICL1: MOVEI W,%CSCLS ;CLOSE THE CONNECTION +CHICL2: PUSHJ P,CHINT ;SET TO STATE IN W, INTERRUPT + PUSH P,A + MOVEI Q,CHSPBF(I) ;DISCARD OUT-OF-ORDER PACKETS + PUSHJ P,CHALFR + HRRZS CHSNBF(I) +CHIC2A: MOVEI Q,CHSOBF(I) ;DISCARD TRANSMIT PACKETS, E.G. RFC WHICH RECEIVED + PUSHJ P,CHAQGF ;AN ANS OR FWD, DON'T WANT TO TRANSMIT AGAIN + JUMPE A,CHIC2B + PUSHJ P,CHABR1 + JRST CHIC2A + +CHIC2B: POP P,A + JRST CHIDT1 ;GIVE PACKET TO USER AS DATA + ;INTERRUPT LEVEL PROCESSING OF RFC PACKET +CHIRFC: MOVE T,%CPKDT(A) ;CHECK FOR STATUS REQUEST + CAMN T,[.BYTE 8 ? "S ? "T ? "A ? "T] + CAIE C,6 + JRST CHIRF7 + MOVS TT,%CPKDT+1(A) + XORI TT,(<.BYTE 8 ? "U ? "S>) + TRNN TT,(<.BYTE 8 ? -1 ? -1>) + JRST CHIRF3 +CHIRF7: MOVEI Q,CHQLSN ;SEARCH LISTENING QUEUE + PUSHJ P,CHAQSR + JRST CHIRF1 ;NOT FOUND, LOAD SERVER + EXCH A,B ;A LSN, B RFC + LDB I,[$CPKSX(A)] ;GET CORRESPONDING INDEX + HRRZ E,CHSSTA(I) + CAIE E,%CSLSN + JRST 4,. +CHIRF0: PUSHJ P,CHABRT ;FOUND, DISCARD LISTEN PACKET + MOVE A,B ;GET OTHER HOST'S RFC + LDB B,[$CPKPN(A)] ;INITIALIZE RECEIVER'S PACKET NUMBER + HRLM B,CHSPKN(I) + MOVE B,%CPKS(A) + MOVEM B,CHSFRN(I) ;HOOK 'EM UP + MOVEI W,%CSRFC ;PUT INTO RFC-RECEIVED STATE + MOVE T,TIME ;AND ENGAGE PI LEVEL + MOVEM T,CHSITM(I) + JRST CHICL2 + +;RFC RECEIVED AND NOT IMMEDIATELY MATCHED TO A LSN. QUEUE AND LOAD SERVER JOB. +;BUT FIRST CHECK WHETHER THIS IS A DUPLICATE WHICH SHOULD BE DISCARDED. +CHIRF1: MOVE C,%CPKS(A) ;SEARCH PENDING RFC QUEUE FOR RFC FROM + HLRZ T,CHQRFC ;THE SAME SOURCE AS THIS. + JUMPE T,CHIRD1 +CHIRD0: CAMN C,%CPKS(T) + JRST CHABRT ;THIS RFC IS A DUPLICATE, IGNORE IT + HRRZ T,-2(T) + JUMPN T,CHIRD0 +CHIRD1: MOVSI T,-NINDX ;SEARCH OPEN AND RFC-RECEIVED CONNECTIONS +CHIRD2: SKIPL CHSUSR(T) ;FOR ONE CONNECTED TO SAME GUY AS SENT RFC + CAME C,CHSFRN(T) + AOBJN T,CHIRD2 + JUMPGE T,CHIRD3 ;NO DUPLICATE OF THIS RFC, QUEUE IT + HRRZ TT,CHSSTA(T) + CAIE TT,%CSOPN + CAIN TT,%CSRFC + JRST CHABRT ;REALLY A DUPLICATE, DISCARD + AOBJN T,CHIRD2 +CHIRD3: MOVEI B,[ASCIZ/System not up/] + SKIPL SYSDBG ;REFUSE INCOMING CONNECTIONS IF LOGINS REFUSED + SKIPE NETUSW ;ALLOWING INCOMING NET CONNECTIONS? + JRST CHIRF2 ;NO, REFUSE (EVEN IF FROM OURSELVES) + HRROI T,CHIRFJ ;LOAD JOB + CONI PI,Q ;MUST TURN UTCOFF TO CALL NUJBST + ANDI Q,177 ;SINCE THIS MAY RUN AT OTHER INT LEVELS + CONO PI,NETOFF + PUSHJ P,NUJBST + JRST [ CONO PI,PICON(Q) + JRST CHABRT ] ;RING BUFFER FULL, IGNORE, RETRY WILL CATCH + CONO PI,PICON(Q) + MOVE T,TIME ;REMEMBER WHEN THIS RFC WAS QUEUED + MOVEM T,-1(A) + MOVEI Q,CHQRFC + JRST CHAQPF ;PUT ON FRONT OF QUEUE + +;COME HERE TO SEND A LOS PACKET IN RESPONSE TO CRUFTY INPUT IN A +;B SHOULD POINT TO AN ASCIZ STRING FOR WHY. +CHALOS: SKIPA T,[%COLOS] +;HERE TO REFUSE AN RFC. TURN IT INTO A CLS AND SEND IT BACK. +;B SHOULD POINT TO AN ASCIZ STRING FOR WHY. +CHIRF2: MOVEI T,%COCLS + HRLI B,440700 ;BP TO MESSAGE + SETZB C,(A) .SEE $CPKFC + DPB T,[$CPKOP(A)] + MOVE T,%CPKS(A) ;EXCHANGE SOURCE AND DESTINATION + EXCH T,%CPKD(A) + MOVEM T,%CPKS(A) + MOVE D,[440800,,%CPKDT(A)] +CHIRF4: ILDB T,B + JUMPE T,CHIRF5 + IDPB T,D + AOJA C,CHIRF4 + +CHIRF5: DPB C,[$CPKNB(A)] + SETOM -2(A) ;NOT ON ANY SEND LIST + JRST CHAXMT ;SEND IT + +;HERE FOR RFC TO "STATUS" +EXPUNGE FOO,BAR +DEFINE FOO NAME +BAR==0 +.BYTE 8 +IRPC CH,,NAME +"CH +BAR==BAR+1 +TERMIN +IFG BAR-4, .ERR NAME MORE THAN 4 CHARACTERS +REPEAT 4-BAR, 0 +.BYTE +TERMIN + +CHIRF3: MOVE B,[MNAME FOO ,,] ;NAME OF MACHINE IN 8-BIT ASCII +EXPUNGE FOO,BAR + MOVEM B,%CPKDT(A) + SETZM %CPKDT+1(A) + MOVSI B,%CPKDT+1(A) + HRRI B,%CPKDT+2(A) + BLT B,%CPKDT+7(A) + MOVE B,[.BYTE 8 ? MYCHAD/400 ? 1 ? 4+IFN CH10P+CH11P,[10.] ? 0 ] + MOVEM B,%CPKDT+10(A) + MOVEI B,%CPKDT+11(A) + HRLI B,441000 + MOVE T,CHNPI + PUSHJ P,CHRF3A + MOVE T,CHNPO + PUSHJ P,CHRF3A +IFN CH10P+CH11P,[ + MOVE T,CHNABT + PUSHJ P,CHRF3A + MOVE T,CHNLOS + PUSHJ P,CHRF3A + MOVE T,CHNCRC + PUSHJ P,CHRF3A + MOVE T,CHNCR2 + PUSHJ P,CHRF3A + MOVE T,CHNPLE + ADD T,CHNWLE + PUSHJ P,CHRF3A +];CH10P+CH11P + MOVEI T,%COANS + SETZM (A) .SEE $CPKFC + DPB T,[$CPKOP(A)] + MOVE T,%CPKS(A) ;EXCHANGE SOURCE AND DESTINATION + EXCH T,%CPKD(A) + MOVEM T,%CPKS(A) + MOVEI C,13*4+IFN CH10P+CH11P,[20.] ;BYTE COUNT + JRST CHIRF5 ;SEND + +CHRF3A: MOVEI TT,4 + IDPB T,B + LSH T,-8 + SOJG TT,.-2 + POPJ P, + +;HERE TO CONVERT A BRD INTO AN RFC + +CHIBRD: LDB T,[$CPKAN(A)] ;NUMBER OF BITMAP BYTES + LDB TT,[$CPKNB(A)] ;NUMBER OF TOTAL DATA BYES (INCLUDES BITMAP) + CAIG T,32. ;ACK NUMBER NO GREATER THAN 32. + TRNE T,3 ; MUST BE MULTIPLE OF 4 + JRST CHABRT ; FREE THE PACKET IF NO GOOD + CAMG TT,T ;MUST BE SOME TEXTUAL RFC DATA AS WELL + JRST CHABRT ; IF NOT, FREE PACKET + MOVE C,TT ;GET NUMBER OF BYTES (CHIRFC WANTS COUNT IN C) + SUB C,T ;WITHOUT BITMAP + DPB C,[$CPKNB(A)] ;NEW BYTE COUNT + LSH T,-2 ;CONVERT BITMAP BYTE COUNT TO WORD COUNT + ADDI TT,3 ;CONVERT BYTE COUNT TO... + LSH TT,-2 ;... WORD COUNT + MOVEI D,%CPKDT(A) ;GET POINTER TO BEGINNING OF DATA + HRL D,D ;IN UPPER AND LOWER HALVES (ALMOST BLT POINTER) + HRLZ T,T ;BITMAP WORD COUNT,,0 + ADD D,T ;RFC-STRING,,DATA-FIELD + ADDI TT,%CPKDT-1(A) ;LAST LOCATION FOR BLT + BLT D,(TT) + SETZI TT, + DPB TT,[$CPKAN(A)] ;ZERO THE ACK FIELD + MOVE TT,MYCHAD + DPB TT,[$CPKDA(A)] ;PRETEND IT WAS FOR ME + JRST CHIRFC ;AND HANDLE IT AS AN RFC + + +;ROUTINE TO FIND INDEX PACKET CORRESPONDS TO, SKIP IF FOUND, INDEX IN I. +;ALSO RETURNS STATE IN E SINCE THAT'S OFTEN HANDY. +;ALSO SETS B FOR CHALOS +CHFNDX: MOVEI B,[ASCIZ/Connection does not exist at this end/] + LDB I,[$CPKDX(A)] ;GET REAL-INDEX PART OF DESTINATION INDEX + CAIGE I,NINDX + SKIPGE CHSUSR(I) + POPJ P, ;NO MATCH + SKIPGE CHSSTA(I) .SEE %CFOFF + POPJ P, ;NOT TALKING TO NETWORK + HRRZ E,CHSSTA(I) + MOVE TT,%CPKD(A) + MOVE T,%CPKS(A) + CAIN E,%CSRFS ;IF IN RFC-SENT STATE, ONLY + AND T,[.BYTE 16. ? -1 ? 0] ;THE SOURCE HOST HAS TO MATCH + CAMN TT,CHSLCL(I) ;COMPARE LOCAL ADDRESS + CAME T,CHSFRN(I) ; AND FOREIGN ADDRESS + POPJ P, ;NO MATCH + MOVE T,TIME + MOVEM T,CHSITM(I) + JRST POPJ1 ;SUCCEED, CALLER CHECKS THE STATE + +;INTERRUPT LEVEL PROCESSING OF RECEIVED OPN PACKET +CHIOPN: PUSHJ P,CHFNDX ;FIND CONNECTION TO BE OPENED + JRST CHALOS + CAIE E,%CSRFS ;NOT IN RFC-SENT STATE, + JRST CHABRT ; MUST BE DUPLICATE, DISCARD. + LDB B,[$CPKPN(A)] ;GET ITS PACKET NUMBER + HRLM B,CHSPKN(I) ;INITIALIZE PACKET NUMBERING OF RECEIVED MESSAGES + MOVE B,%CPKS(A) + MOVEM B,CHSFRN(I) ;HOOK 'EM UP + PUSHJ P,CHIST1 ;PROCESS AS A STS, DISCARD + PUSHJ P,CHASTO ;RESPOND WITH A STS + MOVEI W,%CSOPN + ;DROP INTO CHINT + +;COME HERE WITH INDEX IN I AND NEW STATE IN W, TO CHANGE STATE AND INTERRUPT +CHINT: HRRM W,CHSSTA(I) + MOVE T,TIME + MOVEM T,CHSITM(I) ;IN CASE GOT HERE FROM CHOLSN + MOVSI T,%CFOFF + CAIE W,%CSOPN + IORM T,CHSSTA(I) ;DISENGAGE PI LEVEL + CAIN W,%CSOPN + ANDCAM T,CHSSTA(I) ;NOW OPEN, ENGAGE PI LEVEL +;COME HERE TO INTERRUPT ON THE INPUT CHANNEL. SMASHES T,TT,W +CHINTI: LDB T,[$CHSUI,,CHSUSR(I)] +CHINT2: MOVE TT,CHSSTA(I) ;SIGNAL USER OR STY? + TLNN TT,%CFSTY + JRST CHINT4 ;USER + LDB T,[$CFTTN,,TT] ;STY, GET TTY NUMBER + CONO PI,PIOFF ;PROTECT LIST MODIFICATION + SKIPL STYNTL-NFSTTY(T) ;DON'T PUT ON LIST TWICE + JRST PIONJ + MOVE TT,STYNTA ;ADD TO LIST + MOVEM TT,STYNTL-NFSTTY(T) + MOVEM T,STYNTA + JRST PIONJ + +CHINT4: SKIPGE TT,CHSUSR(I) + JRST 4,. + MOVSI W,(SETZ) ;PCLSR THE JOB SO IT GETS AN IOC ERROR IF NEEDFUL + IORM W,PIRQC(TT) ;EVEN IF NORMAL INTERRUPTS ARE NOT ENABLED + CAIN T,77 + POPJ P, ;IOPUSH'D, NO INTERRUPT + MOVE T,CHNBIT(T) + AND T,MSKST2(TT) + IORM T,IFPIR(TT) + POPJ P, + +OVHMTR CHD + +;INTERRUPT LEVEL PROCESSING OF RECEIVED DATA PACKET +CHIDAT: PUSHJ P,CHFNDX ;FIND ASSOCIATED CONNECTION + JRST CHALOS ;NONE, LOSS + CAIE E,%CSOPN ;STATE MUST BE OPEN + JRST CHALOS ;BAD, LOSS + PUSHJ P,CHIACK ;PROCESS ACKNOWLEDGEMENT FIELD +;NOW DECIDE WHETHER IT GOES ON CHSIBF(I), OR ON CHSPBF(I), OR GETS DISCARDED. + HLRZ B,CHSPKN(I) ;LAST PACKET NUMBER GIVEN TO USER + LDB C,[$CPKPN(A)] ;GET PACKET NUMBER OF THE NEW PACKET + HLRZ T,CHSWIN(I) ;RECEIVE WINDOW SIZE + ADDI T,(B) ;HIGHEST LEGAL PACKET NUMBER + SUB T,C + TRNE T,100000 ;SKIP IF T >= C + JRST CHABRT ;FOO ON YOU, OVER WINDOW SIZE + HRRZ T,CHSIBF(I) ;COMPUTE NEXT IN-ORDER PACKET EXPECTED + JUMPE T,CHIDT6 ;BASED ON LAST IN-ORDER PACKET + LDB TT,[$CPKOP(T)] + CAIE TT,%COUNC + JRST [ LDB B,[$CPKPN(T)] + JRST CHIDT6 ] + HLRZ T,CHSIBF(I) ;IF IT'S AN UNC, HAVE TO GO FIND CORRECT PACKET +CHIDT5: LDB TT,[$CPKOP(T)] + CAIE TT,%COUNC + LDB B,[$CPKPN(T)] + HRRZ T,-2(T) + JUMPN T,CHIDT5 +CHIDT6: ADDI B,1 + ANDI B,177777 ;NEXT IN-ORDER PACKET EXPECTED + CAMN B,C + JRST CHIDT1 ;EQUAL, IT GOES ON THE END OF CHSIBF(I) LIST. + SUB B,C ;NOT EQUAL, COMPARE THEM MODULO 2^16. + TRNN B,100000 + JRST CHIDTD ;B GREATER, THIS IS AN OLD PACKET, DISCARD IT + ;PUT ON CHSPBF(I) IN PROPER ORDER + ;A IS THIS PACKET, C IS HIS NUMBER, B IS PREDECESSOR, D IS NEXT, E IS HIS # + MOVEI B,0 ;SIGNIFY AT FRONT OF LIST + HLRZ D,CHSPBF(I) ;GET FIRST PACKET ON OUT-OF-ORDER LIST + JUMPE D,CHIDT4 ;LIST IS EMPTY +CHIDT3: LDB E,[$CPKPN(D)] + SUB E,C ;COMPARE PACKET NUMBERS + JUMPE E,CHIDTD ;DUPLICATE, DISCARD + TRNE E,100000 + JRST [ MOVE B,D ;E IS LESS, KEEP LOOPING + HRRZ D,-2(B) + JUMPN D,CHIDT3 + JRST .+1 ] ;REACHED END PUT IT HERE + SKIPE B + HRRM A,-2(B) ;THREAD ONTO PREVIOUS PACKET + SKIPN D +CHIDT4: HRRM A,CHSPBF(I) ;THREAD ONTO BACK OF LIST + SKIPN B + HRLM A,CHSPBF(I) ;THREAD ONTO FRONT OF LIST + HRRM D,-2(A) ;THREAD IN BEFORE PACKET IN D + MOVSI B,1 + ADDM B,CHSNBF(I) + POPJ P, + +;HERE IT GOES ON CHSIBF(I). A HAS PACKET, C HAS ITS PACKET NUMBER. +;IF GETTING HERE FROM CHICL1, C HAS GARBAGE BUT IT WILL NEVER BE USED. +CHIDT1: SKIPN CHSIBF(I) + PUSHJ P,CHINTI ;THERE WAS NO INPUT, BUT THERE IS NOW, COME AND GET IT + AOS CHSNBF(I) + MOVEI Q,CHSIBF(I) + PUSHJ P,CHAQPL ;PUT ON END OF RECEIVE LIST + HLRZ A,CHSPBF(I) ;GET FIRST OUT-OF-ORDER PACKET + JUMPE A,CPOPJ ;NONE + LDB B,[$CPKPN(A)] ;SEE IF THIS PACKET IS NOW IN-ORDER + CAIL C,177777 ;BY COMPARING AGAINST C+1 MODULO 2^16. + TDZA C,C + ADDI C,1 + CAME B,C + POPJ P, ;NO + MOVEI Q,CHSPBF(I) + PUSHJ P,CHAQGF ;YES, PULL PACKET OF OUT-OF-ORDER LIST + MOVSI B,-1 + ADDM B,CHSNBF(I) + JRST CHIDT1 ;AND GO PUT ONTO IN-ORDER LIST + +;HERE IF PACKET IS A DUPLICATE AND IS TO BE DISCARDED. MUST SEND +;RECEIPT TO SHUT OFF EXCESS RETRANSMISSION. +CHIDTD: PUSHJ P,CHABRT + AOS CHNPD + JRST CHASTO + +;HERE FOR RECEIVING AN UNC PACKET +CHIUNC: LDB I,[$CPKDI(A)] ;Destination index zero? + JUMPE I,CHIUN2 + LDB I,[$CPKDX(A)] ;GET REAL-INDEX PART OF DESTINATION INDEX + CAIGE I,NINDX + SKIPGE CHSUSR(I) + JRST CHALOS ;NO MATCH + MOVE TT,%CPKD(A) ;DESTINATION ADDRESS MATCHES? + CAME TT,CHSLCL(I) + JRST CHALOS + HRRZ E,CHSSTA(I) ;IN FOREIGN PROTOCOL MODE? + CAIN E,%CSFRN + JRST CHIUN1 + MOVE TT,%CPKS(A) ;NORMAL PROTOCOL, SOURCE ADDRESS MUST MATCH + CAMN TT,CHSFRN(I) + CAIE E,%CSOPN ;AND STATE MUST BE OPEN + JRST CHALOS +CHIUN1: MOVE TT,TIME + MOVEM TT,CHSITM(I) + SKIPE T,CHSIBF(I) ;DISCARD PACKET IF OVER WINDOW SIZE + JRST [ LDB TT,[$CPKOP(T)] ; AND ALREADY HAVE AN UNC + HRRZ T,CHSNBF(I) + HLRZ Q,CHSWIN(I) + CAML T,Q + CAIE TT,%COUNC + JRST .+2 + JRST CHABRT ] + PUSHJ P,CHINTI ;THERE WAS NO INPUT, BUT THERE IS NOW, COME AND GET IT + AOS CHSNBF(I) ;PUT ON END OF RECEIVE LIST. + MOVEI Q,CHSIBF(I) ;PACKET NUMBER IS RANDOM, NOTHING LOOKS AT IT + JRST CHAQPL + +CHIUN2: +IFE INETP,JRST CHALOS ;No comprendo internet +IFN INETP,[ + LDB I,[$CPKAN(A)] ;Protocol number + CAIE I,8_8 ;DOD Internet #x0800 + JRST CHALOS + AOS CHNIPI ;Meter Internet packets in from Chaosnet + MOVE J,A ;Save Chaosnet packet + LDB A,[$CPKNB(A)] ;Compute size of Internet datagram in words + ADDI A,3 + LSH A,-2 + MOVE C,A ;Save word count + CALL IPGIPT ;Get buffer to copy datagram into + JRST CHIUN3 ;No buffers available, discard packet + MOVSI T,%CPKDT(J) ;Make BLT pointer + HRRI T,1(B) + ADDI B,(C) ;Address of last destination word + BLT T,(B) + EXCH A,J ;Free the Chaosnet packet + CALL CHABRT + MOVE A,J ;Datagram structure + MOVE B,C ;Word count + MOVEI C,0 ;Offset to start of IP header + CALRET IPRDGM ;Dispose of datagram + +CHIUN3: MOVE A,J ;Discard Chaosnet packet + CALRET CHABRT +];INETP + +OVHMTR CHJ + +;INTERRUPT LEVEL PROCESSING OF LOS +CHILOS: PUSHJ P,CHFNDX ;FIND CONNECTION TO BE BROKEN + JRST CHABRT ;NONE, IGNORE + MOVEI W,%CSLOS ;PUT INTO LOST STATE + JRST CHICL2 ;GIVE PACKET TO USER AS DATA, DISENGAGE, AND INTERRUPT + +;INTERRUPT LEVEL PROCESSING OF STS +CHISTS: PUSHJ P,CHFNDX + JRST CHALOS + CAIE E,%CSOPN ;CONNECTION MUST BE OPEN + JRST CHALOS +CHIST1: LDB B,[042000,,%CPKDT(A)] ;GET NEW WINDOW SIZE + CAILE B,MXWIND + MOVEI B,MXWIND + HRRM B,CHSWIN(I) + LDB B,[242000,,%CPKDT(A)] ;PROCESS RECEIPT + PUSHJ P,CHIAK0 + PUSHJ P,CHABRT + JRST CHARTR ;RETRANSMIT + +OVHMTR CHA + +;INTERRUPT LEVEL PROCESSING OF RECEIVED ACKNOWLEDGEMENT. +;REMOVE THE ACKNOWLEDGED PACKETS FROM THE INDEX'S SEND LIST AND UPDATE CHSNOS(I). +;NOTE THAT THE LIST IS ASSUMED TO BE SORTED SO WE ONLY +;REMOVE PACKETS FROM THE FRONT. CLOBBERS B,C,D,T,TT,Q. +CHIACK: LDB B,[$CPKAN(A)] ;PACKET NUMBER BEING RECEIPTED +CHIAK0: LDB T,[$CPKAN(A)] ;ENTER HERE FROM CHISTS + HRRZ D,CHSACK(I) ;GET MAX OF THIS ACKNOWLEDGE AND PREVIOUS + SUB D,T + TRNE D,100000 + HRRM T,CHSACK(I) ;ACKNOWLEDGED PACKET NUMBER IS NEW START OF WINDOW + PUSH P,A + HLRZ A,CHSOBF(I) ;MAP DOWN SEND LIST + JUMPE A,CHIAK2 ;LIST EMPTY +CHIAK1: LDB D,[$CPKPN(A)] + SUBM B,D + TRNE D,100000 + JRST CHIAK2 ;RCP# LESS THAN PKT# + HRRZ C,-2(A) ;GET NEXT PACKET + HLLOS D,-2(A) ;MARK NOT ON SEND LIST + AOJE D,CHIAK3 ;AND JUMP IF NOT ON TRANSMIT LIST +IFN DLCP,[ + MOVEI Q,DLCXMQ ;ON TRANSMIT LIST, TRY TO TAKE OFF + PUSHJ P,CHIAKF +];DLCP +IFN T11CHP,[ + MOVEI Q,T11XMQ + PUSHJ P,CHIAKF +];T11CHP +IFN CH10P+CH11P,[ + MOVEI Q,CHXXMQ + PUSHJ P,CHIAKF +];CH10P+CH11P + CAIA ;AND DON'T FREE IT +CHIAK3: PUSHJ P,CHABRT + HRLM C,CHSOBF(I) + SKIPE A,C + JRST CHIAK1 + SETZM CHSOBF(I) ;SEND LIST NOW EMPTY +CHIAK2: MOVE D,CHSNOS(I) ;COMPUTE NEW VALUE OF CHSNOS + HRRZ T,CHSACK(I) ;START OF WINDOW + HRRZ C,CHSPKN(I) ;LAST PACKET SENT + SUB T,C + SKIPLE T + SUBI T,200000 ;T GETS NEGATIVE AMOUNT OF WINDOW OCCUPIED + ADD T,CHSWIN(I) ;RH(T) GETS AVAILABLE PORTION OF WINDOW + HRREM T,CHSNOS(I) ;WHICH IS NUMBER OF OUTPUT SLOTS + JUMPG D,POPAJ ;IF FORMERLY THERE WERE NO OUTPUT SLOTS, + LDB T,[$CHSUO,,CHSUSR(I)] + SKIPLE CHSNOS(I) ;AND NOW THERE ARE, + PUSHJ P,CHINT2 ;INTERRUPT ON THE OUTPUT CHANNEL + JRST POPAJ + +;TRY TO TAKE PACKET IN A OFF OF TRANSMIT LIST IN Q. +;CLOBBER T,Q,D. CALLED WITH INTERRUPTS OFF. +;MAY RETURN WITH A POINTING TO FREE BUT THAT IS OK AT THIS TIME. +CHIKF1: SKIPA D,T +CHIAKF: MOVEI D,2(Q) ;LH[-2(D)] POINTS TO (T) + HLRZ T,-2(D) + JUMPE T,CPOPJ ;NOT FOUND + CAIE T,(A) + JRST CHIKF1 + HLRZ T,-2(A) ;LINK OUT + HRLM T,-2(D) + JUMPN T,CHABRT ;JUMP IF DIDN'T DELETE LAST PACKET IN LIST + HRRM D,(Q) ;NEW LAST PACKET IN LIST + CAIN D,2(Q) + SETZM (Q) ;FOO, TRANSMIT LIST NOW EMPTY + JRST CHABRT + +SUBTTL CHAOS NET DL10 INTERRUPT ROUTINE + +OVHMTR CHH + +IFN DLCP,[ + +;COME HERE FROM EACH DL10 INTERRUPT AT TTY LEVEL. SMASH ALL REGISTERS EXCEPT P AND 0. +DLCWAK: CONI PI,E ;SAVE PI STATUS AND SWITCH TO NETWORK INTERRUPT LEVEL + ANDI E,177 + PUSH P,E + CONO PI,NETOFF +DLCWK1: MOVEI J,1 ;ALWAYS CHECK BOTH BUFFERS SO WE CAN'T GET OUT OF PHASE WITH 11 + MOVEI R,2 ;CHECK FOR INPUT AVAILABLE + CAME R,DLCRS1(J) + SOJGE J,.-1 + JUMPL J,DLCWK2 + MOVE A,DLCRA1(J) ;GOT INPUT, PROCESS IT + SETZM DLCRS1(J) ;BUFFER SLOT NOT OCCUPIED NOW +IFN KS10P, CLRCSH +IFN KL10P, PUSHJ P,DLCSWP ;SWEEP CACHE IN CASE ANYONE HAPPENED TO TOUCH BUFFER + SKIPE A ;THIS CAN HAPPEN IF PDP11 WAS JUST STUFFED + PUSHJ P,CHAPII ;PROCESS THE PACKET + PUSHJ P,DLCIBG ;SUPPLY A NEW INPUT BUFFER TO 11 + JRST DLCWK1 ;TRY FOR MORE INPUT + +DLCWK2: MOVEI J,1 ;SCAN CHANNELS FOR OUTPUT DONE + CAME R,DLCSS1(J) +DLCWK3: SOJGE J,.-1 + JUMPL J,DLCWK4 + MOVE A,DLCSA1(J) ;FOUND AN OUTPUT DONE BUFFER + HRROS B,-2(A) ;MARK IT NOT ON TRANSMIT LIST + AOJN B,.+2 ;AND UNLESS IT IS ON SEND LIST + PUSHJ P,CHABRT ;RETURN IT TO FREE + SETZM DLCSA1(J) ;IDLE THIS BUFFER + SETZM DLCSS1(J) + JRST DLCWK3 + +DLCWK4: MOVE J,DLCSBF ;TRY TO SEND SOME OUTPUT + SKIPE DLCSS1(J) + JRST DLCWK9 ;BUFFER BUSY + HLRZ A,DLCXMQ ;GET ANOTHER OFF TRANSMIT QUEUE + JUMPE A,DLCWK9 ;QUEUE EMPTY + HLRZ T,-2(A) +IFN FTRCHK,[ + CAIN T,-1 + BUG PAUSE,[CHAOS LIST THREAD TRASHED],OCT,A,OCT,-2(A) +];FTRCHK + HRLM T,DLCXMQ +IFN FTRCHK,[ + JUMPN T,.+4 + CAME A,DLCXMQ ;REACHED END OF LIST, END IN RIGHT PLACE? + BUG PAUSE,[DCLXMQ THREAD TRASHED] + SETZM DLCXMQ +];FTRCHK +IFE FTRCHK,[ + SKIPN T + SETZM DLCXMQ +];FTRCHK + PUSHJ P,DLCXMT ;SEND IT ON THIS BUFFER + JRST DLCWK4 ;GO TRY TO SEND ON OTHER BUFFER + +DLCWK9: POP P,E + CONO PI,PICON(E) ;RESTORE PI + POPJ P, + +;THIS ROUTINE SUPPLIES AN INPUT BUFFER TO THE 11 ON ALL BUFFERS THAT NEED IT +;CALL WITH INTERRUPTS OFF OR IN PROGRESS +DLCIBG: MOVEI J,1 + SKIPE DLCRS1(J) +DLCIB1: SOJGE J,.-1 + JUMPL J,CPOPJ + PUSHJ P,CHABGI ;GET A BUFFER + JRST [ SETZM DLCRA1(J) ;NO MEMORY, WILL TRY AGAIN AT CLOCK LEVEL + SETZM DLCRS1(J) + POPJ P, ] + SETZM (A) ;CLEAR THE BUFFER SINCE THE DL10 DOESN'T TOUCH LOW 4 BITS + HRLZ T,A + HRRI T,1(A) + BLT T,%CPMXW-1(A) + MOVEM A,DLCRA1(J) ;MAKE AVAILABLE TO PDP11 + HRLI A,120000 + MOVEM A,DLCRP1(J) + SOS DLCRP1(J) +IFN KS10P, .ERR CLRCSH not needed here? +IFN KL10P, PUSHJ P,DLCSWP ;SWEEP CACHE BEFORE SIGNALLING 11 + MOVEI T,1 + MOVEM T,DLCRS1(J) + CONO DLC,100040+TTYCHN ;INTERRUPT 11 + JRST DLCIB1 ;TRY FOR OTHER BUFFER ALSO + +;THIS ROUTINE SENDS PACKET IN A TO DL10 (CALL WITH NETOFF OR IN PROGRESS) +;SWITCHES BUFFERS, LEAVES NEW ONE IN J +DLCXMT: MOVE J,DLCSBF + MOVEM A,DLCSA1(J) + HRLI A,120000 + MOVEM A,DLCSP1(J) ;GIVE 11 POINTER TO NEW PACKET + SOS DLCSP1(J) +IFN KS10P, .ERR CLRCSH not needed here? +IFN KL10P, PUSHJ P,DLCSWP ;SWEEP CACHE, PUTTING PACKET INTO CORE + MOVEI T,1 + MOVEM T,DLCSS1(J) ;ACTIVATE PDP11 + CONO DLC,100040+TTYCHN + XORI J,1 ;NEXT BUFFER + MOVEM J,DLCSBF + POPJ P, + +IFN KL10P,[ +;THIS ROUTINE SWEEPS PACKET IN A OUT OF THE CACHE, +;CLOBBERING B, C, AND D. +IFG PKTBSZ-1000, .ERR PKTBSZ BIGGER THAN HARDWARE PAGE SIZE, CACHE SWEEP LOSES +DLCSWP: LDB D,[111100,,A] ;SWEEP ONE PAGE OF CACHE + SWPUO (D) ;STORING PACKET INTO CORE + MOVE B,[CONSZ 200000] ;AWAIT COMPLETION IN ACS + MOVE C,[JRST B] ;TO MINIMIZE CACHE INTERFERENCE + MOVSI D,(POPJ P,) + JRST B +];KL10P +];DLCP + +SUBTTL CHAOS NET TEN-11 INTERFACE STUFF + +IFN T11CHP,[ +;THIS ROUTINE CHECKS FOR TEN-11 INITIALIZATION, SKIP-RETURNS IF OK TO USE +;CLOBBERS T,TT +T11CHK: SKIPE TEN11F + JRST T11LUZ ;NOT SUPPOSED TO USE TEN11 + MOVE T,T11VER ;CHECK VERSION TO MAKE SURE RIGHT PROGRAM, ETC. + CAME T,[.BYTE 8 ? "H ? "C ? 0 ? 1] + JRST T11LUZ ;PROBABLY TURNED OFF OR WRONG PROGRAM + SKIPE T11I10 ;SHOULD WE REINIT? + JRST T11CK1 ;YES, GO DO SO + SKIPLE T,T11WIN ;ARE WE WINNING? + JRST POPJ1 ;YES, FINE + JUMPE T,[SETOM T11WIN ;NOW THAT VERSION IS OK, TELL 11 TO INIT + MOVSI T,-1 + MOVEM T,T11I11 + JRST T11CK1 ] ;AND INIT OURSELVES + SKIPE T11I11 ;WAITING FOR 11 TO REINIT? + POPJ P, ;YES, WAIT +;HERE TO REINIT. FIRST, PICK UP PARAMETERS. +T11CK1: LDB TT,[242000,,T11PRM] ;BYTES PER PACKET BUFFER + CAIGE TT,<%CPMXW+1>*4 ;BETTER BE RIGHT SIZE + JRST T11LUZ ;TOO SMALL (ASSUME IF TOO BIG, PACKETS WON'T BE) + LSH TT,-2 + MOVEM TT,T11BSZ ;SAVE BUFFER SIZE IN PDP10 WORDS + LDB T,[042000,,T11PRM] ;NUMBER OF BUFFERS IN EACH DIRECTION + IMULB T,TT ;NUMBER OF PDP10 WORDS IN EACH DIRECTION + ADD TT,T11IBB + MOVEM TT,T11IBE ;INIT POINTERS + MOVEM TT,T11OBB + MOVEM TT,T11OBP + ADD TT,T + MOVEM TT,T11OBE + HRREI T,-T11CHS-2000(TT) + JUMPG T,T11LUZ ;COMMUNICATION AREA LONGER THAN 1K + MOVE T,T11IBB + MOVEM T,T11IBP +T11CK2: SETZM (T) ;CLEAR BUFFER HEADERS + ADD T,T11BSZ + CAMGE T,TT + JRST T11CK2 + MOVEM T,T11WIN ;WE'RE WINNING (MAKE T11WIN POSITIVE NON-ZERO) + SETZM T11I10 ;INIT DONE + JRST POPJ1 + +;HERE IF PDP11 PARAMETERS DON'T MATCH WHAT WE EXPECT +T11LUZ: SETZM T11WIN ;NOT WINNING + POPJ P, + +;HERE FROM CLOCK LEVEL TO CHECK ON TEN-11 CHAOS NET CHANNEL +T11WAK: PUSHJ P,T11CHK ;IS EVERYTHING OK? + POPJ P, ;NO. +T11WK0: MOVE C,T11IBP ;CHECK INPUT + SKIPN (C) + JRST T11WK1 ;NONE AVAILABLE + MOVSI J,2(C) ;POINT TO PACKET + LDB D,[$CPKNB+2(C)] ;GET SIZE OF PACKET + ADDI D,4*%CPKDT+3 ;CONVERT BYTES TO WORDS INCLUDING HEADER + LSH D,-2 + CAILE D,%CPMXW ;DON'T GET FAKED OUT BY CLOBBERED COUNT + MOVEI D,%CPMXW + PUSHJ P,CHABGI ;GET PLACE TO PUT IT + JRST T11WK1 ;NONE AVAILABLE + HRLOI E,-1(D) + EQVI E,(A) ;AOBJN POINTER TO PACKET BUFFER + HRRI J,(A) ;BLT POINTER TO COPY PACKET + ADDI D,-1(A) ;LAST WORD + BLT J,(D) ;COPY PACKET FROM 11 TO 10 + MOVEI H,0 ;COMPUTE CHECKSUM +T11WK4: ADD H,(E) + LSH H,-1 + TRZE H,10 + TLO H,(SETZ) + AOBJN E,T11WK4 + MOVE TT,1(C) ;GET PDP11'S CHECKSUM + SETZM (C) ;GIVE THE 11 BACK THE BUFFER + ADD C,T11BSZ ;ADVANCE THE POINTER + CAML C,T11IBE + MOVE C,T11IBB + MOVEM C,T11IBP + CAME H,TT + JRST [ AOS T11CKE ;COUNT CHECKSUM ERRORS + PUSHJ P,CHABRT ;AND DISCARD PACKET + JRST T11WK0 ] + CONO PI,NETOFF + PUSHJ P,CHAPII ;PROCESS THE INPUT + CONO PI,NETON + JRST T11WK0 + +T11WK1: CONO PI,NETOFF + SKIPE T11XMQ ;ANY OUTPUT? + SKIPE @T11OBP ;AND OUTPUT BUFFER SPACE AVAILABLE? + JRST NETONJ ;NO, RETURN FROM T11WAK + HLRZ A,T11XMQ ;GET PACKET OFF TRANSMIT QUEUE + HLRZ B,-2(A) ;GET NEXT AFTER THAT + HRLM B,T11XMQ ;BECOMES NEW HEAD OF QUEUE + SKIPN B + SETZM T11XMQ + PUSHJ P,T11XMT ;COPY PACKET INTO 11 + CONO PI,NETON + JRST T11WK1 ;LOOK FOR MORE OUTPUT + +;SEND PACKET A-> TO 11. SMASHES B,C,T,TT,Q. CALL WITH NETOFF. +T11XMT: LDB C,[$CPKNB(A)] ;GET BYTE COUNT + MOVE Q,C ;MUST CLEAR UNUSED BYTES AT END OF LAST WORD + ANDI Q,3 ;TO MAKE THE CHECKSUM COME OUT RIGHT + ADDI C,4*%CPKDT+3 + LSH C,-2 ;CONVERT TO WORD COUNT + MOVE Q,(Q)[ -1 ;MASK FOR BYTES TO RETAIN IN LAST WORD + <.BYTE 8 ? -1> + <.BYTE 8 ? -1 ? -1> + <.BYTE 8 ? -1 ? -1 ? -1> ] + MOVEI TT,-1(C) + ADD TT,A + ANDM Q,(TT) ;MASK OFF LAST WORD + HRLOI C,-1(C) + EQVI C,(A) ;AOBJN PTR + MOVEI TT,0 ;COMPUTE XOR CHECKSUM IN TT + SKIPA B,T11OBP ;-> CURRENT OUTPUT BUFFER IN 11 +T11XM1: ADDI B,1 + MOVE T,(C) + TRZ T,17 ;CLEAR BITS 10-11 TREATS SPECIALLY + ADD TT,T ;COMPUTE CHECKSUM + LSH TT,-1 + TRZE TT,10 + TLO TT,(SETZ) + MOVEM T,2(B) + AOBJN C,T11XM1 + MOVE B,T11OBP + MOVEM TT,1(B) ;GIVE CHECKSUM TO 11 + MOVSI TT,-1 + MOVEM TT,0(B) ;GIVE PACKET TO 11 + ADD B,T11BSZ ;ADVANCE BUFFER POINTER + CAML B,T11OBE + MOVE B,T11OBB + MOVEM B,T11OBP + HRROS T,-2(A) ;TAKE PACKET OFF TRANSMIT LIST + AOJN T,.+2 + PUSHJ P,CHABRT ;NOT ON SEND LIST, FREE IT + POPJ P, +];T11CHP + +SUBTTL CH-10 INTERRUPT ROUTINES + +;THE GENERAL IDEA IS THAT WE INTERRUPT ON A LOW-PRIORITY INTERRUPT LEVEL, +;AND DO THE TIME-INTENSIVE PACKET COPYING AT THAT LEVEL. THE GENERAL +;CHAOS ROUTINES ARE THEN CALLED WITH NETOFF. + +IFN CH10P,[ + +EBLK + +CHXACS: BLOCK 20 +CHXPDL: -60,,. + BLOCK 60 + +CHXBRK: 0 +BBLK + MOVEM 17,CHXACS+17 + MOVEI 17,CHXACS + BLT 17,CHXACS+16 + MOVE P,CHXPDL + CONSO CHX,CHXRCV ;PACKET RECEIVED? + JRST CHXBK5 + PUSHJ P,CHABGI ;GET PLACE TO PUT PACKET + JRST [ MOVEI T,CHXREN ;NONE AVAILABLE, DISABLE INTR + ANDCAM T,CHXCNO + CONO CHX,@CHXCNO + JRST CHXBK5 ] + CONSZ CHX,CHXCRC+CHXWLE ;CHECK FOR ERRORS + JRST [ CONSZ CHX,CHXCRC + AOSA CHNCRC + AOS CHNWLE + JRST CHXBK4 ] ;IGNORE PACKET + DATAI CHX,T ;FIRST DATAI YIELDS GARBAGE + MOVEI T,CHXSWB ;DISABLE BYTE SWAPPING + ANDCAM T,CHXCNO + CONO CHX,@CHXCNO + HRLI A,-%CPKDT ;READ HEADER + DATAI CHX,(A) + AOBJN A,.-1 + HRRZI A,-%CPKDT(A) + PUSHJ P,CHSWAB ;ENABLE BYTE SWAPPING IF NEEDED + LDB T,[$CPKNB(A)] ;GET SIZE OF PACKET + CAILE T,%CPMXC ;DON'T RUN OFF END OF BUFFER + JRST CHXBK4 + ADDI T,3 ;ROUND UP TO NEXT WORD BOUNDARY + LSHC T,-2 ;CONVERT BYTES TO WORDS, TT GETS REMAINDER + HRLOI D,-1(T) ;MAKE AOBJN POINTER + EQVI D,%CPKDT(A) + JUMPGE D,.+3 ;EMPTY PACKET BOUNDARY CASE + DATAI CHX,(D) + AOBJN D,.-1 + DATAI CHX,T ;NOW READ AND IGNORE HARDWARE HEADER + TLNE T+1,400000 + DATAI CHX,T ;THIRD HALFWORD + CONI CHX,T ;CHECK FOR ERRORS + TDNE T,[CHXPLE+CHXCRC+CHXOVR] + JRST [ TLNE T,(CHXOVR) + JRST CHXBKZ ;OVERRRUN CAN'T HAPPEN UNLESS HARDWARE BROKEN + TLNE T,(CHXPLE) + AOSA CHNPLE + TRNN T,CHXCRC + JRST CHXBK4 + AOS CHNCR2 + JRST CHXBK4 ] + CONO PI,NETOFF-1 + PUSHJ P,CHAPII ;PROCESS THE INPUT + CONO PI,NETON-1 + CAIA +CHXBK4: PUSHJ P,CHABRT ;DIDN'T USE BUFFER AFTER ALL + CONI CHX,T ;COUNT LOST PACKETS + LDB T,[$CHXLC,,T] + ADDM T,CHNLOS + MOVEI T,CHXREN ;ENABLE RECEIVER FOR NEXT PACKET + IORB T,CHXCNO + CONO CHX,CHXRCV(T) +CHXBK5: CONSO CHX,CHXXMT ;TRANSMIT DONE? + JRST CHXBK9 + SKIPE T,CHOSTA ;TRANSMIT IN PROGRESS? + CONSO CHX,CHXABT ;AND WAS ABORTED? + JRST CHXBK7 ;NO TO EITHER, LOOK FOR MORE WORK + AOS CHNABT ;METER TRANSMIT ABORTS + CAIL T,NCHRTR ;ABORTED TOO MANY TIMES? + JRST CHXBK7 ;DONE WITH PACKET + AOS CHOSTA ;COUNT RETRANSMISSIONS + MOVEI T,CHXTEN + IORB T,CHXCNO + CONO CHX,CHXXMT(T) ;RETRANSMIT PACKET + JRST CHXBK9 + +CHXBK7: SETZM CHOSTA ;TRANSMITTER IDLE, LOOK FOR NEXT PACKET + CONO PI,PIOFF + HLRZ A,CHXXMQ ;ANYTHING QUEUED FOR TRANSMISSION? + JUMPE A,[ MOVEI T,CHXTEN ;DISABLE INTERRUPTS + ANDCAM T,CHXCNO + CONO CHX,@CHXCNO + CONO PI,PION + JRST CHXBK9 ] + HLRZ B,-2(A) ;CDR TRANSMIT QUEUE + HRLM B,CHXXMQ + SKIPN B + SETZM CHXXMQ ;QUEUE EMPTY NOW + CONO PI,PION + AOS CHOSTA ;NOW SEND THIS PACKET + MOVEI T,CHXHLF+CHXSWB ;CLEAR HALFWORD, BYTE-SWAP MODES + ANDCAM T,CHXCNO + CONO CHX,@CHXCNO + HRLI A,-%CPKDT ;TRANSMIT HEADER + DATAO CHX,(A) + AOBJN A,.-1 + HRRZI A,-%CPKDT(A) + PUSHJ P,CHSWAB ;ENABLE BYTE SWAPPING IF NEEDED + LDB T,[$CPKNB(A)] ;GET SIZE OF PACKET + ADDI T,1 ;ROUND UP TO NEXT HALF WORD BOUNDARY + LSHC T,-2 ;CONVERT BYTES TO WORDS, T+1 GETS REMAINDER + HRLOI D,-1(T) ;MAKE AOBJN POINTER + EQVI D,%CPKDT(A) + JUMPGE D,.+3 ;EMPTY PACKET BOUNDARY CASE + DATAO CHX,(D) + AOBJN D,.-1 + MOVEI T,CHXHLF+CHXTEN ;SWITCH TO HALFWORD MODE, ENABLE DONE INTR + IORM T,CHXCNO + CONO CHX,@CHXCNO + TLNE T+1,400000 ;SEND EXTRA HALFWORD IF NEEDED + DATAO CHX,(D) + MOVEI T,CHXSWB ;DISABLE SWAP BYTES MODE + ANDCAM T,CHXCNO + CONO CHX,@CHXCNO + LDB T,[$CPKDN(A)] ;GET DESTINATION SUBNET + HRRZ D,SBNRUT(T) ;GATEWAY TO THAT SUBNET + CAIGE T,NSUBNT + CAIN T,MYCHAD_-8 ;IF ON LOCAL CABLE + LDB D,[$CPKDA(A)] ;GO DIRECT + LSH D,16.+4 + DATAO CHX,D ;STORE HARDWARE DESTINATION ADDRESS + MOVE T,CHXCNO ;TRANSMIT PACKET + CONO CHX,CHXXMT(T) + CONI CHX,T + TLNE T,(CHXOVR) ;CAN'T HAPPEN UNLESS HARDWARE BROKEN +CHXBKZ: BUG HALT,[CHAOS: I/O BUS OVERRUN] + HRROS B,-2(A) ;MARK IT NOT ON TRANSMIT LIST + AOJN B,.+2 ;AND UNLESS IT IS ON SEND LIST + PUSHJ P,CHABRT ;RETURN IT TO FREE +CHXBK9: MOVSI 17,CHXACS ;DISMISS INTERRUPT + BLT 17,17 + JRST 12,@CHXBRK + +CHSWAB: LDB T,[$CPKOP(A)] ;DOES THIS PACKET NEED BYTE SWAPPING? + TRNE T,200 + JRST [ TRNE T,100 + POPJ P, ;BINARY DATA + JRST CHSWB1 ] ;CHARACTER DATA + IDIVI T,40 + MOVE T,CHSWBT(T) + LSH T,(T+1) + JUMPL T,CPOPJ ;BINARY CONTROL PACKET +CHSWB1: MOVEI T,CHXSWB ;CHARACTER, SWAP DEM BYTES + IORM T,CHXCNO + CONO CHX,@CHXCNO + POPJ P, + +CHSWBT: 1_<35.-%COOPN>+1_<35.-%COSTS>+1_<35.-%CORUT> + 0 ? 0 ? 0 +];CH10P + +SUBTTL CH-11 INTERRUPT ROUTINES + +;The Unibus Chaosnet board interrupts on the same level as TTYs, +;and comes to CHXBKH via vectored interrupt. We use a programmed +;interrupt request to drop down to a lower interrupt level for the +;slow packet-copying operation, so as not to interfere with the TTYs, +;then turn NETOFF when we call into the Chaosnet NCP. +;(We actually use NETOFF-1 and NETON-1 so as not to interfere with +;CLKOFF. This assumes that interrupt levels between CLKCHN and +;CHXCHN are never turned off.) + +IFN CH11P,[ + +;;; Macros that will eventually be instructions + +DEFINE PACK16 AC,E ;AC,AC+1 right-aligned and zero-filled + LSH AC,16. + IOR AC,AC+1 + LSH AC,4 + MOVEM AC,E +TERMIN + +DEFINE PACK8 AC,E ;AC: ...B2B1 AC+1: ...B4B3 zero-filled!! + ROTC AC,-8 ;B3...B2 B1...B4 + ROT AC,-16. ;B1,B2,B3 in position, B4 right-aligned + ADDI AC+1,(AC+1) ;Shift RH(AC+1) left 4 bits + ADDI AC+1,(AC+1) + ADDI AC+1,(AC+1) + ADDI AC+1,(AC+1) ;B1,B4 in position in AC+1 + IOR AC,AC+1 + MOVEM AC,E +TERMIN + +DEFINE UNPK16 AC,E ;Doesn't bother masking off garbage bits + MOVE AC,E + MOVE AC+1,AC + ROT AC,16. ;First halfword right-aligned + LSH AC+1,-4 ;Second halfword right-aligned +TERMIN + +DEFINE UNPK8 AC,E + MOVE AC,E ;B1B2B3B4... + ROT AC,8 ;B2B3B4...B1 + MOVE AC+1,AC + AND AC,[377_2,,377] ;...B3...B1 zero-filled + ROT AC+1,16. ;B4...B1B2B3 + AND AC+1,[377_12,,377_8];B4...B2... zero-filled + IORB AC,AC+1 ;B4B3...B2B1 + ROT AC+1,16. ;...B4B3, garbage in high bits +TERMIN + +EBLK + +CHXACS: BLOCK 20 +CHXSVH: 0 +CHXPDL: -60,,. + BLOCK 60 + +CHXBKH: 0 ;Hardware interrupt on TTYCHN comes here +BBLK + CONO PI,CHXRQ ;Redirect to lower interrupt level + MOVEM T,CHXSVH ;Clear hardware interrupt enable + MOVEI T,%CAREN+%CATEN ; so the Chaos board will stop interrupting + ANDCAB T,CHXCSR + IOWRI T,CAICSR + MOVE T,CHXSVH + JRST 12,@CHXBKH +EBLK + +CHXBRK: 0 ;Software interrupt on CHXCHN comes here +BBLK + CONO PI,020000+200_<-CHXCHN> ;BAG-BITING DEC LOSERS + MOVEM 17,CHXACS+17 + MOVEI 17,CHXACS + BLT 17,CHXACS+16 + MOVE P,CHXPDL + IORDI T,CAICSR ;Check for received packet + TRNN T,%CARDN + JRST CHXBK3 ;No incoming packet yet + TRNE T,%CAERR ;Check for error in received packet + JRST [ AOS CHNCRC + JRST CHXBK1 ] ;Ignore packet + IORDI R,CAIRBC ;Number of bits in packet - 1 + SUBI R,31. ;Exclude the three extra hardware words + TRNE R,17 + JRST [ AOS CHNWLE ;Length not a multiple of 16 + JRST CHXBK1 ] + ASH R,-5 ;32-bit word count, rounded up + PUSHJ P,CHABGI ;Get place to put packet + JRST [ AOS CHNLOS ;No buffers, lose this packet + JRST CHXBK1 ] + HRLI A,-%CPKDT ;Copy out the packet header +CHSRC1: IORDI B,CAIRBF + IORDI C,CAIRBF + PACK16 B,(A) + AOBJN A,CHSRC1 + PUSHJ P,CHSHDR ;Decode the header + JRST CHSRC4 ;No byte swapping + JUMPGE D,CHSRC3 +CHSRC2: IORDI B,CAIRBF ;Read out the data, byte-swapped + IORDI C,CAIRBF + PACK8 B,(D) + AOBJN D,CHSRC2 +CHSRC3: JUMPGE H,CHSRC7 ;Jump if even packet length + IORDI B,CAIRBF ;Residual halfword + SETZ C, ;Somebody depends on zero here + PACK8 B,(D) + AOJA D,CHSRC7 + +CHSRC4: JUMPGE D,CHSRC6 +CHSRC5: IORDI B,CAIRBF ;Read out the data, halfwords + IORDI C,CAIRBF + PACK16 B,(D) + AOBJN D,CHSRC5 +CHSRC6: JUMPL H,[ IORDI B,CAIRBF ;Residual halfword + SETZ C, ;Somebody depends on zero here + PACK16 B,(D) + AOJA D,CHSRC7 ] +CHSRC7: SUB D,R ;AOBJN pointer minus number of words in packet + CAIE A,(D) + JRST [ AOS CHNPLE ;Packet length disagrees with hardware length + JRST CHXBK2 ] + IORDI T,CAIRBF ;Read the three hardware header words + IORDI T,CAIRBF + IORDI T,CAIRBF + IORDI T,CAICSR + TRNE T,%CAERR ;Make sure packet came out of RAM okay + JRST [ AOS CHNCR2 ;Garbage, try again + JRST CHXBK2 ] + IORDI T,CAIRBC ;Make sure counter didn't spazz + CAIE T,7777 + JRST [ AOS CHNSPZ + JRST CHXBK2 ] + CONO PI,NETOFF-1 ;Get to network interrupt level + PUSHJ P,CHAPII ;Process the input + CONO PI,NETON-1 +CHXBK1: IORDI T,CAICSR ;Count lost packets + LDB TT,[$CALOS,,T] + ADDM TT,CHNLOS + MOVE TT,CHXCSR + IORI TT,%CARCL ;Enable receiver for next packet + IOWRI TT,CAICSR +CHXBK3: TRNN T,%CATDN ;Transmit done? + JRST CHXBK8 ;No, dismiss + SKIPN TT,CHOSTA ;Transmit in progress? + JRST CHXBK7 ;No, look for something to transmit + TRNN T,%CATAB ;Yes, was it aborted? + JRST CHXBK5 ;No, we're done with that packet + AOS CHNABT ;Meter transmit aborts + CAIGE TT,NCHRTR ;Aborted too many times? + JRST CHXBK7 ;No, retransmit it +CHXBK5: CONO PI,PIOFF ;Lock transmit list + HLRZ A,CHXXMQ ;Get packet probably being transmitted now + JUMPE A,[ CONO PI,PION ;It vanished? + JRST CHXBK6 ] + HLRZ B,-2(A) ;CDR transmit queue + HRLM B,CHXXMQ + SKIPN B + SETZM CHXXMQ ;Queue empty now + CONO PI,PION + HRROS B,-2(A) ;Mark it not on transmit list + AOJN B,CHXBK6 ;And unless it is on send list + PUSHJ P,CHABRT ;Return it to free +CHXBK6: SETZM CHOSTA ;Transmitter idle, look for next packet +CHXBK7: HLRZ A,CHXXMQ ;Anything queued for transmission? + JUMPE A,CHXBK9 ;No, leave interrupts disabled + AOS CHOSTA ;Count retransmissions + MOVE T,CHXCSR ;Reset transmitter + IORI T,%CATDN + IOWRI T,CAICSR + HRLI A,-%CPKDT ;Transmit header +CHXXM1: UNPK16 B,(A) + IOWRI B,CAIWBF + IOWRI C,CAIWBF + AOBJN A,CHXXM1 + PUSHJ P,CHSHDR ;Decode the header + JRST CHXXM4 ;No byte swapping + JUMPGE D,CHXXM3 +CHXXM2: UNPK8 B,(D) ;Transmit data with byte swapping + IOWRI B,CAIWBF + IOWRI C,CAIWBF + AOBJN D,CHXXM2 +CHXXM3: JUMPGE H,CHXXM7 ;Jump if even packet length + UNPK8 B,(D) ;Transmit residual bytes + IOWRI B,CAIWBF + JRST CHXXM7 + +CHXXM4: JUMPGE D,CHXXM6 +CHXXM5: UNPK16 B,(D) ;Transmit data with byte swapping + IOWRI B,CAIWBF + IOWRI C,CAIWBF + AOBJN D,CHXXM5 +CHXXM6: JUMPGE H,CHXXM7 ;Jump if even packet length + UNPK16 B,(D) ;Transmit residual bytes + IOWRI B,CAIWBF +CHXXM7: LDB T,[$CPKDN(A)] ;Get destination subnet + HRRZ D,SBNRUT(T) ;Gateway to that subnet + CAIGE T,NSUBNT + CAIN T,MYCHAD_-8 ;If on local cable, + LDB D,[$CPKDA(A)] ; go direct + IOWRI D,CAIWBF ;Store hardware destination address + IORDI T,CAIXMT ;Transmit packet +CHXBK8: MOVEI A,%CATEN ;Enable transmit-done interrupt if xmitting +CHXBK9: IORI A,%CAREN ;Enable receive-done interrupt always + IORB A,CHXCSR + IOWRI A,CAICSR + MOVSI 17,CHXACS ;Dismiss software interrupt + BLT 17,17 + JRST 12,@CHXBRK + +CHXBK2: PUSHJ P,CHABRT ;Packet no good, discard it + JRST CHXBK1 + +;Examine packet in A, return AOBJN pointer to data in D, +; H is negative if there is an extra halfword after that. +; W gets number of full words of data (same as LH D). +; T,U get clobbered +; Returns: +; +1 16-bit data +; +2 8-bit data +CHSHDR: HRRZI A,-%CPKDT(A) ;Restore packet address + LDB W,[$CPKNB(A)] ;Get size of packet in bytes + CAILE W,%CPMXC + MOVEI W,%CPMXC ;Self-defense + ADDI W,1 ;Round up to next word boundary + LSHC W,-2 ;Convert bytes to words, H gets remainder + HRLOI D,-1(W) ;Make AOBJN pointer + EQVI D,%CPKDT(A) + LDB T,[$CPKOP(A)] ;Does this packet need byte swapping? + TRNE T,200 + JRST [ TRNN T,100 + AOS (P) ;Character data + POPJ P, ] ;Binary data + IDIVI T,40 + MOVE T,CHSWBT(T) + LSH T,(T+1) + JUMPL T,CPOPJ ;Binary control packet + JRST POPJ1 ;Characters + +CHSWBT: 1_<35.-%COOPN>+1_<35.-%COSTS>+1_<35.-%CORUT> + 0 ? 0 ? 0 +];CH11P + +SUBTTL CHAOS NET BUFFER LIST STUFF + +OVHMTR CHL + +;BUFFERS ARE PKTBSZ WORDS LONG; 2 HEADER WORDS AND %CPMXW PACKET WORDS. +;PKTBSZ IS A POWER OF 2 AND LESS THAN 1K (MEMORY PAGE SIZE). +;NOTE THAT A BUFFER ADDRESS POINTS AT THE FIRST PACKET WORD +;AND THE HEADER WORDS ARE AT NEGATIVE ADDRESSES. +;FIRST HEADER WORD: -2(A) +; RH LIST THREAD FOR MOST LISTS, 0=END, -1=NOT ON LIST +; LH LIST THREAD FOR TRANSMIT LIST +;SECOND HEADER WORD: -1(A) +; TIME RECEIVED OR TIME PUT ON TRANSMIT LIST +; OR VALUE OF I FOR A PACKET ON THE LSN QUEUE +; ASCII/LUNCH/ FOR A PACKET ON THE FREE LIST + +;I DO IT THIS WAY (PIOFF) TO AVOID HAVING TO PUSH AND POP PI STATUS, +;CONO PI,NETOFF CAN LOSE AT INTERRUPT LEVEL (MAINLY THE NETON LOSES) + +;THESE ROUTINES TURN OFF INTERRUPTS MOMENTARILY SO THAT +;LISTS MAY BE SAFELY MANIPULATED. + +;Q POINTS TO THE HEADER WORD OF A QUEUE, REMOVE THE FIRST +;THING AND RETURN IN A. (ZERO IF NONE) CLOBBERS T +CHAQGF: CONO PI,PIOFF + HLRZ A,(Q) ;GET FIRST + JUMPE A,PIONJ ;EMPTY + HRRZ T,-2(A) ;GET SECOND + HRLM T,(Q) ;MAKE FIRST +IFN FTRCHK,[ + JUMPN T,PIONJ + HRRZ T,(Q) + CAIE T,(A) + BUG PAUSE,[CHAOS LIST TRASHED],OCT,Q + SETZM (Q) ;IS NOW EMPTY +];FTRCHK +IFE FTRCHK,[ + SKIPN T + SETZM (Q) ;IS NOW EMPTY +];FTRCHK + CONO PI,PION + POPJ P, + +;RETURN BUFFER INTO WHICH THE BYTE POINTER IN A POINTS. CLOBBERS A,T,Q +CHBPFR: SUBI A,1 ;SIOKT LIKES TO MAKE BP POINT AT NEXT BUFFER + ANDI A,-PKTBSZ + ADDI A,2 + JRST CHABRT + +;RETURN BUFFER POINTED TO BY A TO FREE UNLESS ON TRANSMIT LIST. +CHABR1: HLLOS T,-2(A) ;RH GETS -1, NO LONGER ON REGULAR LIST + AOJN T,CPOPJ ;EXIT IF STILL ON TRANSMIT LIST + ;DROPS THROUGH +;RETURN BUFFER POINTED BY A TO FREE STORAGE. CLOBBERS T, Q. +CHABRT: MOVEI Q,CHQFRE +IFN FTRCHK,[ + SKIPN A + BUG PAUSE,[FREEING 0] +];FTRCHK + MOVE T,[ASCII/LUNCH/] ;TANSTAAFL + MOVEM T,-1(A) + SETOM -2(A) ;NOT ON TRANSMIT LIST NOW (THIS IS WHAT INITS + AOS CHFRBF ; LH[-2(A)] WHEN BUFFER FIRST CREATED) + ;JRST CHAQPL ;DROPS THROUGH + +;A POINTS TO A BUFFER, Q TO A QUEUE. PUT IT ON AS THE LAST THING. BASHES T. +CHAQPL: HLLZS -2(A) ;PUT ENDLIST IN RH + CONO PI,PIOFF + HRRZ T,(Q) ;GET LAST + HRRM A,(Q) ;MAKE NEW LAST + JUMPN T,[HRRM A,-2(T) ;MAKE A COME AFTER IT + JRST PIONJ ] + HRLM A,(Q) ;WAS EMPTY, ALSO IS NEW FIRST + CONO PI,PION + POPJ P, + +;A POINTS TO A BUFFER, Q TO A QUEUE. PUT IT ON AS THE FIRST THING. SMASHES T. +CHAQPF: CONO PI,PIOFF + HLRZ T,(Q) ;GET FIRST + HRRM T,-2(A) ;MAKE SECOND + HRLM A,(Q) ;MAKE NEW FIRST + SKIPN T + HRRM A,(Q) ;WAS EMPTY, ALSO MAKE NEW LAST + CONO PI,PION + POPJ P, + +;ALLOCATE A BUFFER AT MAIN PROGRAM LEVEL, TO A, MASHES T, TT, Q, B. +CHABG0: PUSHJ P,UDELAY ;WAIT FOR MEMORY +CHABGT: PUSHJ P,CHABGI + JRST CHABG0 + POPJ P, ;WIN + +;ALLOCATE A BUFFER, RETURN POINTER TO IT IN A, SKIP. BLOWS AWAY T, TT, Q. +;NON-SKIP IF NO BUFFERS AVAILABLE. (DOESN'T MAKE NEW ONES IF FREE LIST EMPTY) +CHABAL: MOVEI Q,CHQFRE + PUSHJ P,CHAQGF + JUMPE A,CPOPJ + SETZM -1(A) ;NO LUNCH + SOS CHFRBF + JRST POPJ1 + +;ALLOCATE A BUFFER TO A, MAKE NEW IF NONE FREE. OBLITERATES T,Q,B. +;NON-SKIP IF CAN'T GET MEMORY. (SUITABLE FOR CALLING FROM INT LEVEL) +CHABGI: PUSHJ P,CHABAL ;TRY TO ALLOCATE A BUFFER FROM FREE LIST + CAIA + JRST POPJ1 ;WON, RETURN + CONI PI,Q ;SAVE PI CHANNELS ON STATUS + ANDI Q,177 + CONO PI,UTCOFF ;MAKE THE WORLD SAFE FOR IOMQ + MOVE B,CHTTBF + CAIL B,CHMXBF ;MAKE SURE NOT TO USE UP ALL CORE + JRST CHABG4 + PUSHJ P,IOMQ ;GET 1K OF MEMORY + JRST CHABG3 ;MEM NOT AVAILABLE, FAIL + CONO PI,PICON(Q) ;WON, RESTORE PI STATUS + MOVEI B,MUCHA + DPB B,[MUR,,MEMBLT(A)] + LSH A,10. ;ADDRESS OF 1K OF ALLOCATED MEMORY + ADD A,[-<2000/PKTBSZ>,,2] ;-BUFFERS PER 1K,,OFFSET TO HEADER +CHABG2: PUSHJ P,CHABRT ;PUT THEM ALL ON FREE LIST + ADDI A,PKTBSZ-1 + AOBJN A,CHABG2 + MOVEI B,<2000/PKTBSZ> ;THIS MANY MORE BUFFERS HAVE BEEN CREATED + ADDM B,CHTTBF + JRST CHABGI ;NOW GO ALLOCATE ONE + +;HERE IF CHAOS NET TRYING TO USE UP TOO MUCH CORE +CHABG4: MOVE B,CHMXTM ;DON'T COMPLAIN TOO OFTEN + ADDI B,60.*30. ;JUST ONCE A MINUTE + CAMLE B,TIME + JRST CHABG3 +IFE CH10P, BUG CHECK,[CHAOS NET ATTEMPTING TO USE TOO MUCH CORE] +IFN CH10P,[ + CONI CHX,B + BUG CHECK,[CHAOS NET ATTEMPTING TO USE TOO MUCH CORE, CONI=],OCT,B,[CONO=],OCT,CHXCNO,[CHOSTA=],OCT,CHOSTA +];CH10P + MOVE B,TIME + MOVEM B,CHMXTM +CHABG3: CONO PI,PICON(Q) ;LOST, RESTORE PI STATUS + POPJ P, ;AND TAKE ERROR RETURN + +;FREE A WHOLE LIST OF BUFFERS, Q-> HEAD. DESTROYS A,T +CHALFR: PUSHJ P,CHAQGF + JUMPE A,CPOPJ + PUSH P,Q + PUSHJ P,CHABR1 ;FREE UNLESS STILL ON TRANSMIT LIST + POP P,Q + JRST CHALFR + +;Q -> A TRANSMIT QUEUE, FLUSH ALL BUFFERS BELONGING TO INDEX I. +;CLOBBERS A,B,C,T +CFLXMQ: PUSH P,Q + CONO PI,NETOFF ;DON'T LET TRANSMIT LIST CHANGE (AT ALL) + HLRZ A,(Q) ;HEAD OF TRANSMIT LIST + JUMPE A,CFLXM3 + MOVEI B,2(Q) ;B PREVIOUS PACKET, A CURRENT, C NEXT +CFLXM1: HLRZ C,-2(A) ;GET THREAD TO NEXT +IFN FTRCHK,[ + CAIN C,-1 + JRST 4,. ;CLAIMS NOT TO BE ON LIST? +];FTRCHK + LDB T,[$CPKSX(A)] ;GET THIS PACKET'S INDEX + CAME T,I + JRST CFLXM2 + HRLM C,-2(B) ;THREAD PREVIOUS TO NEXT + HRROS T,-2(A) ;IF THIS BUFFER IS NOT ALSO ON SEND LIST, + AOJN T,.+2 + PUSHJ P,CHABRT ;RETURN IT + SKIPA Q,(P) +CFLXM2: MOVE B,A + SKIPE A,C + JRST CFLXM1 + HRRM B,(Q) ;LAST PACKET ON LIST MAY HAVE CHANGED + CAIN B,2(Q) + SETZM (Q) ;TRANSMIT QUEUE IS NOW EMPTY +CFLXM3: POP P,Q + JRST NETONJ + +;SEARCH LIST IN Q FOR PACKET WHOSE CONTACT NAME MATCHES THAT +;OF PACKET IN A, RETURN IT IN B, SKIPPING IF WINNING. CLOBBERS T,TT,C,D,E,H,J. +;THE PACKET RETURNED IN B IS DE-LINKED FROM THE SEARCHED QUEUE. +;HAS TO BE CALLED WITH NETOFF OR IN PROGRESS, SO LIST CAN'T GET MUNGED. +;I HOPE IT'S NOT TOO BLETCHEROUSLY SLOW. +CHAQSR: HLRZ B,(Q) ;GET START OF LIST TO SEARCH + JUMPE B,CPOPJ ;EMPTY, LOSE + MOVEI J,0 ;PACKET PREVIOUS TO B +CHAQS1: LDB C,[$CPKNB(A)] ;SET UP STRING COMPARE LOOP + LDB H,[$CPKNB(B)] ;THIS ASSUMES NO ZERO-LENGTH STRINGS + MOVEI D,%CPKDT(A) + HRLI D,440800 + MOVEI E,%CPKDT(B) + HRLI E,440800 +CHAQS2: ILDB T,D + ILDB TT,E ;DON'T IGNORE CASE, THAT WOULD JUST SLOW THIS + CAME T,TT ;BAG-BITER DOWN EVEN MORE. EVERYONE SHOULD + JRST CHAQS4 ;PUT THEIR CONTACT NAMES IN UPPER-CASE. + CAIN T,40 ;TERMINATE ON SPACE + JRST CHAQS5 + SOJLE C,CHAQS3 + SOJG H,CHAQS2 + ILDB T,D + CAIE T,40 + JRST CHAQS4 +CHAQS5: HRRZ C,-2(B) ;WON, DELINK PACKET FROM LIST + JUMPE J,[ HRLM C,(Q) + JUMPN C,POPJ1 + IFN FTRCHK,[ + HRRZ C,(Q) ;CHECK LIST ENDING IN RIGHT PLACE + CAIE C,(B) + JRST 4,. + ];FTRCHK + SETZM (Q) + JRST POPJ1 ] + HRRM C,-2(J) + JUMPN C,POPJ1 + HRRM J,(Q) ;TOOK LAST PACKET, STORE NEW LAST + JRST POPJ1 + +CHAQS3: SOJLE H,CHAQS5 + ILDB TT,E + CAIN TT,40 + JRST CHAQS5 +CHAQS4: MOVE J,B ;THIS ONE DOESN'T MATCH, TRY NEXT + HRRZ B,-2(B) + JUMPN B,CHAQS1 + POPJ P, ;NO MATCHES + +;THIS ROUTINE RUNS IN THE CORE JOB AND CLEANS UP MEMORY USED BY CHAOS BUFFERS +;SMASHES ALL ACS +CHCLN: SKIPE A,CHTTBF ;SEE IF 2/3 OR MORE OF BUFFERS FREE + SKIPN B,CHFRBF + POPJ P, ;NO BUFFERS OR NONE FREE, NOTHING TO DO + SUBM A,B + IDIV A,B ;GET RATIO OF TOTAL TO USED + CAIGE A,3 ;NOTE IF B IS ZERO A IS UNCHANGED + POPJ P, ; AND AT LEAST 32. +IFL TSYSM-256., MOVEI D,TSYSM-1 ;SCAN MEMORY FOR CHAOS BUFFER PAGES +.ELSE MOVEI D,255. +CHCLN0: LDB A,[MUR,,MEMBLT(D)] + CAIE A,MUCHA +CHCLN4: SOJGE D,CHCLN0 + JUMPL D,CPOPJ + MOVE A,D ;QUICKLY DETERMINE IF ANY NON-FREE BUFFERS + LSH A,10. ; ON THIS PAGE + HRLI A,-<2000/PKTBSZ> + MOVE T,[ASCII/LUNCH/] +CHCLN5: CAME T,1(A) + JRST CHCLN4 ;NOT FREE, DON'T BOTHER WITH SLOW STUFF + ADDI A,PKTBSZ-1 + AOBJN A,CHCLN5 + SETZB C,CHCLNQ ;COLLECT ALL FREE BUFFERS THAT ARE ON THIS PAGE + MOVE E,CHFRBF ;LOOP ABOUT AS MANY TIMES AS THERE ARE FREE BUFFERS +CHCLN1: PUSHJ P,CHABAL ;GET NEXT FREE BUFFER + JUMPE A,CHCLN2 + LDB B,[121000,,A] + CAMN B,D + JRST [ MOVEI Q,CHCLNQ ;THIS ONE'S ON THE PAGE, SAVE IT + PUSHJ P,CHAQPL + AOJA C,.+2 ] ;COUNT THEM + PUSHJ P,CHABRT ;NOT ON THE PAGE, PUT BACK + SOJG E,CHCLN1 +CHCLN2: CAIE C,<2000/PKTBSZ> ;DID WE GET THE WHOLE PAGE? + JRST [ MOVEI Q,CHCLNQ ? PUSHJ P,CHALFR ? JRST CHCLN4 ] + MOVNS C ;YES, GET RID OF THESE BUFFERS + ADDM C,CHTTBF + MOVE A,D + PUSHJ P,MEMR + JRST CHCLN + +OVHMTR CHZ diff --git a/src/system/chsdef.15 b/src/system/chsdef.15 new file mode 100755 index 00000000..b53fa8ca --- /dev/null +++ b/src/system/chsdef.15 @@ -0,0 +1,68 @@ +;;; CHAOS NET PACKET DEFINITION + +;NOTE, IF YOU MAKE CHANGES TO OPCODES OR CONNECTION STATE SYMBOLS, +;ALSO CHANGE AI:MAINT;CHS DEFS. +;THIS FILE IS FOR PDP-10'S - CHS DEFS IS FOR PDP-11'S. + + +;PACKET HEADER +;NOTE THESE ARE FULL WORD BYTE POINTERS, INCLUDING A WORD OFFSET + +$CPKOP==341000,,0 ;OPCODE + %CO==,,-1 + %CORFC==1 ;REQUEST FOR CONNECTION + %COOPN==2 ;OPEN + %COCLS==3 ;CLOSE + %COFWD==4 ;FORWARD + %COANS==5 ;ANSWER + %COSNS==6 ;SENSE STATUS + %COSTS==7 ;REPORT STATUS + %CORUT==10 ;ROUTING INFO (NOT YET USED) + %COLOS==11 ;REPORT LOSSAGE + %COLSN==12 ;LISTEN FOR RFC + %COMNT==13 ;MAINTENANCE USE, IGNORED BY NORMAL NCPS + %COEOF==14 ;END OF FILE + %COUNC==15 ;UNCONTROLLED USER PACKET + %COBRD==16 ;Software broadcast packet + %COMAX==17 ;HIGHEST NON-DATA OPCODE +1 + %CODAT==200 ;NORMAL DATA OPCODE (NOTE SIGN BIT OF WORD IS SET) + %CODWD==300 ;16-BIT DATA +$CPKMV==241000,,0 ;"MUPPET" VERSION (MUST BE ZERO, NO MUPPETS EXIST!) +$CPKFC==200400,,0 ;FORWARDING COUNT +$CPKNB==041400,,0 ;NUMBER OF BYTES +$CPKDA==242000,,1 ;DESTINATION ADDRESS + $CPKDN==341000,,1 ;DESTINATION SUBNET + $CPKDH==241000,,1 ;DESTINATION HOST +$CPKDI==042000,,1 ;DESTINATION INDEX + %CPKD==1 ;DESTINATION ADDRESS WORD +$CPKSA==242000,,2 ;SOURCE ADDRESS + $CPKSN==341000,,2 ;SOURCE SUBNET + $CPKSH==241000,,2 ;SOURCE HOST +$CPKSI==042000,,2 ;SOURCE INDEX + %CPKS==2 ;SOURCE ADDRESS WORD +$CPKPN==242000,,3 ;PACKET NUMBER +$CPKAN==042000,,3 ;ACKNOWLEDGE NUMBER + %CPKDT==4 ;FIRST WORD OF DATA + +;PACKET SIZE + +;THESE NUMBERS ARE FOR 1K PACKET BUFFERS +;%CPMXW==30. ;MAXIMUM NUMBER OF PDP10 WORDS IN WHOLE PACKET +;%CPMXC==104. ;MAXIMUM NUMBER OF CHARACTERS OF DATA + +;THESE NUMBERS ARE FOR 4K PACKET BUFFERS +%CPMXW==126. ;MAXIMUM NUMBER OF PDP10 WORDS IN WHOLE PACKET +%CPMXC==488. ;MAXIMUM NUMBER OF CHARACTERS OF DATA + +;CONNECTION STATES + +%CS==,,-1 +%CSCLS==0 ;CLOSED +%CSLSN==1 ;LISTENING +%CSRFC==2 ;RFC RECEIVED +%CSRFS==3 ;RFC SENT +%CSOPN==4 ;OPEN +%CSLOS==5 ;BROKEN BY RECEIPT OF "LOS" +%CSINC==6 ;BROKEN BY INCOMPLETE TRANSMISSION (NO RESPONSE TO SNS) +%CSFRN==7 ;OPEN IN FOREIGN PROTOCOL MODE +%CSBRS==10 ;BRD sent state diff --git a/src/system/config.196 b/src/system/config.196 new file mode 100755 index 00000000..352b6558 --- /dev/null +++ b/src/system/config.196 @@ -0,0 +1,926 @@ +.AUXIL + +;;; "INSTALLATION" RELATED SWITCHES + +IFNDEF DEFSYM,[ ;ALLOW USER TO USE SYMBOLS IN OTHER WAYS IF HE WISHES. + ;BUT NORMALLY, DEFSYM FOO==BAR DOES FOO==BAR WITH ERROR CHECK. +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ + $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` +] +.ISTOP +TERMIN TERMIN + +IFLE .MLLIT,.ERR .MLLIT MUST BE 1; SETTING IT TO 1. +.MLLIT==1 +$$TEMP==1 +] +.ELSE $$TEMP==0 + +IFNDEF DEFOPT,[ ;ALLOW USER TO USE SYMBOLS IN OTHER WAYS IF HE WISHES. + ;BUT NORMALLY, DEFOPT FOO==BAR DOES IT UNLESS FOO ALREADY DEFINED +DEFINE DEFOPT X/ +IRPS Z,,[X] +IFNDEF Z, X +.ISTOP +TERMIN TERMIN + +IFLE .MLLIT,.ERR .MLLIT MUST BE 1; SETTING IT TO 1. +.MLLIT==1 +$$TEM2==1 +] +.ELSE $$TEM2==0 + +IFE MCOND AIKA,[ +DEFOPT KA10P==1 ;AI-KA HAS KA10 PROCESSOR +DEFOPT MAXJ==85. ;MAX NUMBER OF JOBS ALLOWED +DEFOPT SWBLK==1 ;1=> SWAP BLOCKING, 0=> PRIVILEGED USER +DEFOPT SWPWSP==0 ;NO WORKING-SET SWAP SCHEDULER +DEFOPT PAGPRE==1 ;PAGE-IN PREEMPTION +DEFOPT SCHBLN==10. ;NUMBER OF RUNNABLE JOBS TO REMEMBER + +DEFOPT NQS==8. ;# 2314 UNITS +DEFOPT NTUTBL==2 ;TUTS ARE 2 BLOCKS LONG (THIS DEFN BETTER AGREE WITH DC10 DEFS) +DEFSYM NUDSL==440. ;# USER DIRECTORIES ON DISK. NOTE: JUST CHANGING THIS + ; IS NOT SUFFICIENT!! +DEFOPT NQCHN==40. ;NUMBER 2314 CHNLS +DEFOPT DC10P==1 ;HAS SYSTEMS CONCEPTS DISK CONTROL +DEFOPT DMDSK==0 ;DOES NOT USE DM DSK FORMAT (I.E. HAS EXTRA WORDS) +DEFOPT QRSRVP==1 ;HAS RESERVED DISK PACKS (SECONDARY PACK) +DEFOPT QAUTHP==1 ;KEEPS TRACK OF FILE AUTHORS + +DEFOPT C1MXP==1 ;CHNL 1 MPX FEATURE +DEFOPT NMTCS==1 ;NUMBER MAG TAPE UNITS +DEFOPT TM10A==1 ;IO-BUS MAG TAPE +DEFOPT PTRP==1 ;HAS PAPER TAPE +DEFOPT PTPP==0 ; But punch doesn't work! +DEFOPT PDCLKP==1 ;"DeCoriolis" CLOCK +DEFOPT DPKPP==1 ;DATA POINT KLUDGE (TTY mux) + +DEFOPT NETP==1 ; Connected to a network +DEFOPT IMPP==1 ; Has IMP interface +DEFOPT KAIMP==1 +DEFOPT IMPUS==206 ; ARPA net host number +DEFOPT IMPUS3==<1200,,400006> ; Internet host number +DEFOPT NCPP==1 ; Include NCP code +DEFOPT NNETCH==30. ; # NCP network channels +DEFOPT INETP==1 ; Include Internet code +DEFOPT TCPP==1 ; Include TCP code +DEFOPT XBL==20. ; # TCP network channels + +DEFOPT TK10P==1 ;HAS TK10 TTY SCANNER (NO MORE, BUT LEAVE IT SO TTY#S DON'T CHANGE) +DEFOPT NOTYS==1 ;# KA-10 CONSOLE 0 TTYS +DEFOPT NNTYS==16. ;# TTYS ON KNIGHT KLUDGE +DEFOPT NDPTYS==9. ;# TTYS ON DATAPOINT KLUDGE +DEFOPT NSTTYS==16. ;# OF STY'S (PSEUDO-TTY'S) +DEFOPT APL==10 ;AP TTY # (really?) + +DEFOPT CODP==1 ; Has Morse code output device (no antenna though) + +; The following AI-KA stuff is broken since the 10-11 interface doesn't work, +; but is retained in case it gets fixed. +DEFOPT TEN11P==0 ; Rubin 10-11 interface +IFN TEN11P,[ + DEFOPT XGP==1 ; Has XGP + DEFOPT CHAOSP==1 ; Has CHAOS net + DEFOPT MYCHAD==2026 ; CHAOS net address + DEFOPT NINDX==50. ; Number of Chaosnet indices + DEFOPT T11CHP==1 ; CHAOS net goes through TEN-11 interface + DEFOPT CH11NM==7 ; # of 10-11 PDP11 handling CHAOS net. + DEFOPT TT11NM==0 ; # of 10-11 PDP11 that handles TV TTYs. + DEFOPT N11TYS==16. ; # PDP11 TV TTYS + DEFOPT MXVBN==40 ; Max video bfr # for assignment purposes. +] ;TEN11P ; These actually correspond to video switch inputs. + + +; The following stuff used to be on AI-KA and is unlikely to ever +; come back. +;DEFOPT PDP6P==0 ;HAS PDP6 (ALAS, NO MORE) +;DEFOPT 340P==0 ;HAS 340 DISPLAY (ALAS, NO MORE) +;DEFOPT TABP==0 ;DOESN'T HAVE SYLVANIA TABLET ANY MORE +;DEFOPT DSDP==0 ;HAS DESELECTION DEVICE (ALAS, NO MORE) +;DEFOPT NEWDTP==0 ;HAD OLD DECTAPE CONTROLLER +;DEFOPT RBTCP==0 ;ROBOT CONSOLE +;DEFOPT HCLKP==0 ;HOLLOWAY CLOCK (ALAS, NO MORE) +;DEFOPT ARMP==0 ;HAS NO ARM (AMF MOSTLY) (R.I.P.) +;DEFOPT OMXP==0 ;HAS OMX (OUTPUT MULTIPLEXOR) (ALAS, NO MORE) +;DEFOPT IMXP==0 ;HAS IMX (INPUT MULTIPLEXOR) (ALAS, NO MORE) +;DEFOPT VIDP==0 ;HAD VIDI (R.I.P.) +;DEFOPT CCLKP==0 ;NO CHESS TOURN CLOCK STUFF +;DEFOPT NDAP==0 ;NEW D/A CONVERTERS (ALAS, NO MORE) + +; Physical memory variables + +DEFOPT TSYSM==768. ;TOTAL PDP10 1K MEM BLOCKS +DEFOPT ECCMEM==1 ;HAS HIC'S ERROR CORRECTING MEMORY +DEFOPT NMMP==4 ;# EXEC PAGES FOR MMP TABLE (# VIR PGS/512.); + +DEFSYM PMRCM==1777 ;CORE ADR FIELD IN PAGE MAP (AI-KA HAS 10 BITS) +DEFSYM PMAGEM==16000 ;AI-KA HAS ONE LESS AGE BITS +DEFSYM PMCSHM==0 ;NO CACHE BIT +DEFSYM PMUNSD==160000 ;UNUSED BITS + +IFDEF TEN11P,IFN TEN11P,DEFSYM T11CPA==3776000 ;ADRS OF TEN-11 CONTROL PAGE +IFDEF PDP6P,IFN PDP6P,DEFSYM PDP6BM==3000000 ;BASE ADR OF PDP6 MEM AS SEEN FROM 10 +IFDEF PDP6P,IFN PDP6P,DEFSYM LPDP6M==16. ;LENGTH OF PDP6 MEM IN PAGES +] ;AIKA + +IFE MCOND MLKA,[ +DEFOPT KA10P==1 ;ML-KA HAS KA PROCESSOR +DEFOPT MAXJ==60. ;MAX NUMBER OF JOBS ALLOWED +DEFOPT SWBLK==1 ;1 => SWAP BLOCKING, 0 => PRIV USER +DEFOPT SWPWSP==0 ;NO WORKING-SET SWAP SCHEDULER +DEFOPT PAGPRE==1 ; Page-in preemption +DEFOPT SCHBLN==10. ;NUMBER OF RUNNABLE JOBS TO REMEMBER + +DEFOPT NQCHN==30. ;NUMBER 2314 CHNLS +DEFOPT NQS==7 ;# DISK UNITS +DEFOPT NTUTBL==1 ;TUTS ARE ONE BLOCK LONG +DEFSYM NUDSL==250. ;# USER DIRECTORIES ON DISK +DEFOPT RP10P==1 ;HAS DEC RP10 DISK CONTROL (RP02) +DEFOPT QRDCMP==1 ;SOFTWARE READ-COMPARE +DEFOPT DMDSK==1 ;USES DM DISK FORMAT +DEFOPT QRSRVP==1 ;HAS RESERVED DISK PACKS (SECONDARY PACK) +DEFOPT QAUTHP==1 ;KEEPS TRACK OF FILE AUTHORS + +DEFOPT C1MXP==1 ;CHANNEL 1 MPX FEATURE +DEFOPT NEWDTP==1 ;HAS NEW DECTAPE CONTROLLER +;DEFOPT NUNITS==4 ; Number of utape units (R.I.P.) +DEFOPT NMTCS==1 ;NUMBER OF MAG TAPE UNITS +DEFOPT TM10A==1 ;IO-BUS MAG TAPE +DEFOPT NLPTP==1 ;HAS NEW LPT (ODEC) +DEFOPT TPLP==1 ;PSEUDO LPT +DEFOPT PTRP==1 ;HAS PAPER TAPE +DEFOPT PTPP==1 ; And punch works. +DEFOPT MTYP==1 ;HAS MORTON MULTIPLEX BOX +DEFOPT PDCLKP==1 ;"DeCoriolis" CLOCK + +DEFOPT NETP==1 ; Has net connection +DEFOPT IMPP==1 ; Has IMP interface +DEFOPT KAIMP==1 +DEFOPT IMPUS==306 ; ARPA net host number +DEFOPT IMPUS3==<1200,,600006> ; Internet host number +DEFOPT NCPP==0 ; Flush NCP code +DEFOPT NNETCH==20. ; # NCP net channels +DEFOPT INETP==1 ; Include Internet code +DEFOPT TCPP==1 ; Include TCP code +DEFOPT XBL==20. ; # TCP network channels +DEFOPT CHAOSP==1 ;CHAOS NET +DEFOPT MYCHAD==3114 ;CHAOS NET ADDRESS +DEFOPT NINDX==30. ;NUMBER OF INDICES +DEFOPT CH10P==1 ;CHAOS NET VIA PDP-10 I/O BUS, NOT FRONT-END + +DEFOPT NOTYS==1 ;# KA-10 CONSOLE 0 TTYS +;DEFOPT NNVTTS==0 ;# NOVA TTYS (used to have?) +DEFOPT NMTYS==33 ;# TTYS ON MORTON BOX +DEFOPT NSTTYS==8 ;# STY'S (PSEUDO-TTY'S) + +DEFOPT TSYSM==512. ;TOTAL PDP10 1K MEM BLOCKS +DEFOPT NMMP==4 ;# EXEC PAGES FOR MMP TABLE (# VIR PGS/512.) + +DEFSYM PMRCM==777 ;9 BIT REAL CORE ADR +DEFSYM PMAGEM==17000 ;4 BIT AGE +DEFSYM PMCSHM==0 ;NO CACHE BIT +DEFSYM PMUNSD==160000 ;UNUSED BITS +] ;MLKA + +IFE MCOND DM,[ +DEFOPT KA10P==1 ;DM HAS KA10 PROCESSOR +DEFOPT MAXJ==63. ;MAX NUMBER OF JOBS ALLOWED +DEFOPT SWBLK==0 ;1 => SWAP BLOCKING, 0 => PRIVILEGED USER +DEFOPT SWPWSP==0 ;NO WORKING-SET SWAP SCHEDULER +DEFOPT PAGPRE==0 ;NO PAGE-IN PREEMPTION +DEFOPT SCHBLN==10. ;NUMBER OF RUNNABLE JOBS TO REMEMBER + +DEFOPT NQS==6 ;# OF DISK UNITS +DEFOPT NTUTBL==1 ;TUTS ARE ONE BLOCK LONG +DEFSYM NUDSL==200. ;# USER DIRECTORIES ON DISK +DEFOPT NQCHN==30. ;NUMBER 2314 CHNLS +DEFOPT RP10P==1 ;HAS DEC RP10 DISK CONTROL (RP02) +DEFOPT DMDSK==1 ;USES DM DISK FORMAT +DEFOPT QRSRVP==1 ;HAS RESERVED DISK PACKS +DEFOPT QAUTHP==1 ;KEEPS TRACK OF FILE AUTHORS + +DEFOPT C1MXP==1 ;HAS CHANNEL 1 MPX FEATURE +DEFOPT NMTCS==1 ;NUMBER MAG TAPE UNITS +DEFOPT TM10B==1 ;DF10-BASED CONTROLLER +DEFOPT TTLPTP==1 ;LPT IS A TTY (I.E. ON A TTY LINE) VALUE IS LINE #. +DEFOPT PTRP==1 ;HAS PAPER TAPE +DEFOPT PTPP==1 ;PUNCH DOES WORK. +DEFOPT MTYP==1 ;HAS MORTON MULTIPLEX BOX +;DEFOPT CODP==0 ;NO COD DEVICE (used to?) +DEFOPT PDCLKP==1 ;"DeCoriolis" CLOCK + +DEFOPT NETP==1 ; Has net connection +DEFOPT IMPP==1 ; Has IMP interface +DEFOPT DMIMP==1 ; This is a DM IMP interface +DEFOPT IMPUS==106 ; ARPA net host number +DEFOPT IMPUS3==<1200,,200006> ; Internet host number +DEFOPT NCPP==0 ; Flush NCP code +DEFOPT NNETCH==30. ; # NCP network channels +DEFOPT INETP==1 ; Include Internet code +DEFOPT TCPP==1 ; Include TCP code +DEFOPT XBL==20. ; # TCP network channels + +DEFOPT MSPP==1 ;HAS MESSAGE SLURPER +DEFOPT DEMON==1 ;HAS DEMON ROUTINES +DEFOPT NOTYS==1 ;# KA-10 CONSOLE 0 TTYS +DEFOPT NMTYS==12. ;# TTYS ON MORTON BOX +DEFOPT NSTTYS==16. ;# OF STY'S (PSEUDO-TTY'S) + + +DEFOPT TSYSM==512. ;TOTAL PDP10 1K MEM BLOCKS +DEFOPT NMMP==4 ;# EXEC PAGES FOR MMP TABLE (# VIR PGS/512.) + +DEFSYM PMRCM==777 ;9 BIT REAL CORE ADR +DEFSYM PMAGEM==17000 ;4 BIT AGE +DEFSYM PMCSHM==0 ;NO CACHE BIT +DEFSYM PMUNSD==160000 ;UNUSED BITS +] ;DM + +IFE MCOND MX,[ +DEFOPT KL10P==1 ;MX IS WHAT WE CALL THE KL10 NOW +DEFOPT MAXJ==120. ;MAX NUMBER OF JOBS ALLOWED +DEFOPT SWBLK==1 ;1 => SWAP BLOCKING, 0 => PRIVILEGED USER +DEFOPT SWPWSP==0 ;NO WORKING-SET SWAP SCHEDULER +DEFOPT PAGPRE==1 ;PAGE-IN PREEMPTION +DEFOPT SCHBLN==20. ;NUMBER OF RUNNABLE JOBS TO REMEMBER + +DEFOPT NQS==6 ;# OF DISK UNITS (3 RP04'S AND 3 T-300'S) +DEFOPT NTUTBL==2 ;TUTS ARE TWO BLOCKS LONG +DEFSYM NUDSL==500. ;# USER DIRECTORIES ON DISK +DEFOPT NQCHN==50. ;NUMBER 2314 CHNLS +DEFOPT RH10P==1 ;HAS DEC RH10 DISK CONTROL (RP04) +DEFOPT T300P==3 ;TRIDENT T-300S VIA PDP-11 START AT DRIVE 3 +DEFOPT QRDCMP==0 ;SOFTWARE READ-COMPARE, HARDWARE IS PINING FOR THE + ; FJORDS (But this isn't debugged yet.) +DEFOPT DMDSK==1 ;USES DM DISK FORMAT +DEFOPT QRSRVP==1 ;HAS RESERVED DISK PACKS +DEFOPT QAUTHP==1 ;KEEPS TRACK OF FILE AUTHORS + +DEFOPT NMTCS==1 ;NUMBER MAG TAPE UNITS +DEFOPT TM10B==1 ;DF10-BASED TAPE CONTROLLER + +DEFOPT DL10P==1 ;HAS DL10/DC76 TTY CONTROLLER +DEFOPT PDCLKP==1 ;HAS "DeCoriolis" CLOCK + +DEFOPT NETP==1 ; Has net connection +DEFOPT INETP==1 ; Include Internet IP code +DEFOPT TCPP==1 ; Include Internet TCP code +DEFOPT XBL==25. ; # TCP connections +DEFOPT IMPP==1 ; Has IMP interface +DEFOPT KAIMP==1 +DEFOPT IMPUS==106 ; ARPA net host number +DEFOPT IMPUS3==<1200,,200006> ; Internet host number +DEFOPT NCPP==0 ; Flush NCP code +DEFOPT NNETCH==30. ; # NCP network channels +DEFOPT CHAOSP==1 ;HAS CHAOS NET +DEFOPT MYCHAD==1440 ;CHAOS NET ADDRESS +DEFOPT NINDX==50. ;NUMBER OF INDICES +DEFOPT DLCP==1 ;CHAOS NET GOES THROUGH DL10 + +DEFOPT NOTYS==0 ;# KA-10 CONSOLE 0 TTYS +DEFOPT NETYS==33. ;# KL-10 DTE20 TTYS +NEWDTE==1 ;TEMPORARY CONDITIONAL TO ENABLE NEW DTE20 PROTOCOL +DEFOPT NDLTYS==4. ;# TTYS ON DL10/DC76 + ;Note: 3d TTY on DL10 is VT52 by console. +DEFOPT NSTTYS==25. ;# OF STY'S (PSEUDO-TTY'S) + +DEFOPT TSYSM==2048. ;TOTAL PDP10 1K MEM BLOCKS +DEFOPT NMMP==7 ;# EXEC PAGES FOR MMP TABLE (# VIR PGS/512.) + +DEFSYM PMRCM==7777 ;12 BIT REAL CORE ADDR +DEFSYM PMCSHM==10000 ;CACHE ENABLE BIT +DEFSYM PMAGEM==160000 ;3 BIT AGE +DEFSYM PMUNSD==0 ;NO UNUSED BITS + +DEFINE ITSIRP BODY +IRPS ITS,,[MX] +BODY +TERMIN +TERMIN +] ;MX + +IFE MCOND AI,[ +DEFOPT KS10P==1 ;The new AI has a KS10 processor. + +DEFOPT MAXJ==60. ;Max number of jobs allowed +DEFOPT NQCHN==30. ;Max number of user disk channels open in system +DEFOPT SCHBLN==10. ;Number of runnable jobs to remember +DEFOPT SWBLK==1 ;1= 1=> swap blocking, 0=> privileged user +DEFOPT SWPWSP==0 ;1= Use working-set swap scheduler +DEFOPT PAGPRE==1 ;1= Use page-in preemption + +DEFOPT DMDSK==1 ;1= Use DM DSK format +DEFOPT QRSRVP==1 ;1= Has reserved disk packs (Secondary pack) +DEFOPT QAUTHP==1 ;1= Keep track of file authors + +DEFOPT NQS==2 ;# of disk drive units +DEFOPT NTUTBL==4 ;# 1K blocks in a TUT (better agree with RP06 DEFS) +DEFSYM NUDSL==500. ;# directories in file system (better agree with + ; SALV and DSKDMP) +DEFOPT RH11P==1 ; Has RH11 controller +DEFOPT RP06P==1 ; with two RP06s + +DEFOPT NMTCS==1 ;Number of magtape units (so why not NMTUS?) +DEFOPT TM03S==1 ;TM03/RH11 Unibus tape controller + +DEFOPT NETP==1 ;Has one kind of network anyway +;AI's IMP is gone 5/5/89 +;DEFOPT INETP==1 ; Include Internet code +;DEFOPT TCPP==1 ; Include TCP code +;DEFOPT XBL==30. ; # TCP network channels +;DEFOPT IMPP==1 ; Has an IMP interface +;DEFOPT KSIMP==1 ; ACC LH/DH interface on KS unibus +;DEFOPT IMPUS==206 ; ARPA net host number +;DEFOPT IMPUS3==<1200,,400006> ; Internet host number of IMP +;DEFOPT PKTTRC==-1 ;Packet tracing code enabled +DEFOPT CHAOSP==1 ;Has CHAOS net +DEFOPT MYCHAD==3130 ;CHAOS net address +DEFOPT NINDX==50. ;Number of indices +DEFOPT CH11P==1 ;CHAOS net goes through Unibus + +DEFOPT DZ11P==1 ;Has DZ11 TTY controllers + DEFOPT DZ11NB==1 ; 1 of them + DEFSYM DZ0BA=:760010 + +DEFOPT NKSTYS==1 ;# KS-10 8080 console 0 TTYs +DEFOPT NDZTYS==8. ;# DZ-11 TTYs +DEFOPT NSTTYS==12. ;# of STY's (Pseudo-TTY's) + +DEFOPT TSYSM==512. ;Total PDP10 1K memory blocks +DEFOPT NMMP==4 ;# exec pages for MMP table (# vir pgs/512.) + +;;; Next four better agree with SYSTEM;KSDEFS: +DEFSYM PMAGEM==020000 ;2.5 Age bit +DEFSYM PMCSHM==010000 ;2.4 Cache enable bit +DEFSYM PMRCM==001777 ;2.1 - 1.1 Physical page number + ; (The page table supports 20 bit physical + ; addresses.) +DEFSYM PMUNSD==146000 ;Unused bits + +DEFINE ITSIRP BODY +IRPS ITS,,[AI MC] +BODY +TERMIN +TERMIN +] ;AI + +IFE MCOND MC,[ +DEFOPT KS10P==1 ;MC is now a KS10. + +DEFOPT MAXJ==60. ;Max number of jobs allowed +DEFOPT NQCHN==30. ;Max number of user disk channels open in system +DEFOPT SCHBLN==10. ;Number of runnable jobs to remember +DEFOPT SWBLK==1 ;1= 1=> swap blocking, 0=> privileged user +DEFOPT SWPWSP==0 ;1= Use working-set swap scheduler +DEFOPT PAGPRE==1 ;1= Use page-in preemption + +DEFOPT DMDSK==1 ;1= Use DM DSK format +DEFOPT QRSRVP==1 ;1= Has reserved disk packs (Secondary pack) +DEFOPT QAUTHP==1 ;1= Keep track of file authors + +DEFOPT NQS==1 ;# of disk drive units +DEFOPT NTUTBL==4 ;# 1K blocks in a TUT (better agree with RP06 DEFS) +DEFSYM NUDSL==500. ;# directories in file system (better agree with + ; SALV and DSKDMP) +DEFOPT RH11P==1 ; Has RH11 controller +DEFOPT RP06P==1 ; with one RP06 + +DEFOPT NETP==1 ;Has one kind of network anyway +DEFOPT INETP==1 ; Include Internet code +DEFOPT TCPP==1 ; Include TCP code +DEFOPT XBL==30. ; # TCP network channels +;MC's IMP is gone 5/18/89 +;DEFOPT IMPP==1 ; Has an IMP interface +;DEFOPT KSIMP==1 ; ACC LH/DH interface on KS unibus +;DEFOPT IMPUS==354 ; ARPA net host number +;DEFOPT IMPUS3==<1200,,600054> ; Internet host number of IMP +DEFOPT IPUNCP==1 ; IP in Chaos UNC is our only Internet address +DEFOPT PKTTRC==-1 ;Packet tracing code enabled +DEFOPT CHAOSP==1 ;Has CHAOS net +DEFOPT MYCHAD==3131 ;CHAOS net address +DEFOPT NINDX==50. ;Number of indices +DEFOPT CH11P==1 ;CHAOS net goes through Unibus + +DEFOPT DZ11P==1 ;Has DZ11 TTY controllers + DEFOPT DZ11NB==1 ; 1 of them + DEFSYM DZ0BA=:760010 + +DEFOPT NKSTYS==1 ;# KS-10 8080 console 0 TTYs +DEFOPT NDZTYS==6. ;# DZ-11 TTYs +DEFOPT NSTTYS==4. ;# of STY's (Pseudo-TTY's) + +DEFOPT TSYSM==512. ;Total PDP10 1K memory blocks +DEFOPT NMMP==4 ;# exec pages for MMP table (# vir pgs/512.) + +;;; Next four better agree with SYSTEM;KSDEFS: +DEFSYM PMAGEM==020000 ;2.5 Age bit +DEFSYM PMCSHM==010000 ;2.4 Cache enable bit +DEFSYM PMRCM==001777 ;2.1 - 1.1 Physical page number + ; (The page table supports 20 bit physical + ; addresses.) +DEFSYM PMUNSD==146000 ;Unused bits + +DEFINE ITSIRP BODY +IRPS ITS,,[AI MC] +BODY +TERMIN +TERMIN +] ;MC + +IFE MCOND ML,[ +DEFOPT KS10P==1 ;ML is now a KS10. + +DEFOPT MAXJ==60. ;Max number of jobs allowed +DEFOPT NQCHN==30. ;Max number of user disk channels open in system +DEFOPT SCHBLN==10. ;Number of runnable jobs to remember +DEFOPT SWBLK==1 ;1= 1=> swap blocking, 0=> privileged user +DEFOPT SWPWSP==0 ;1= Use working-set swap scheduler +DEFOPT PAGPRE==1 ;1= Use page-in preemption + +DEFOPT DMDSK==1 ;1= Use DM DSK format +DEFOPT QRSRVP==1 ;1= Has reserved disk packs (Secondary pack) +DEFOPT QAUTHP==1 ;1= Keep track of file authors + +DEFOPT NQS==1 ;# of disk drive units +DEFOPT NTUTBL==4 ;# 1K blocks in a TUT (better agree with RP06 DEFS) +DEFSYM NUDSL==500. ;# directories in file system (better agree with + ; SALV and DSKDMP) +DEFOPT RH11P==1 ; Has RH11 controller +DEFOPT RP06P==1 ; with one RP06 + +DEFOPT NETP==1 ;Has one kind of network anyway +DEFOPT CHAOSP==1 ;Has CHAOS net +DEFOPT MYCHAD==3133 ;CHAOS net address +DEFOPT NINDX==50. ;Number of indices +DEFOPT CH11P==1 ;CHAOS net goes through Unibus + +DEFOPT DZ11P==1 ;Has DZ11 TTY controllers + DEFOPT DZ11NB==4 ; 4 of them + DEFSYM DZ0BA=:760010 + DEFSYM DZ1BA=:760020 + DEFSYM DZ2BA=:760030 + DEFSYM DZ3BA=:760040 + +DEFOPT NKSTYS==1 ;# KS-10 8080 console 0 TTYs +DEFOPT NDZTYS==4. ;# DZ-11 TTYs +DEFOPT NSTTYS==4. ;# of STY's (Pseudo-TTY's) + +DEFOPT TSYSM==512. ;Total PDP10 1K memory blocks +DEFOPT NMMP==4 ;# exec pages for MMP table (# vir pgs/512.) + +;;; Next four better agree with SYSTEM;KSDEFS: +DEFSYM PMAGEM==020000 ;2.5 Age bit +DEFSYM PMCSHM==010000 ;2.4 Cache enable bit +DEFSYM PMRCM==001777 ;2.1 - 1.1 Physical page number + ; (The page table supports 20 bit physical + ; addresses.) +DEFSYM PMUNSD==146000 ;Unused bits + +DEFINE ITSIRP BODY +IRPS ITS,,[AI MC ML] +BODY +TERMIN +TERMIN +] ;ML + +IFE MCOND MD,[ + +DEFOPT KS10P==1 ;MD is a KS10. + +DEFOPT MAXJ==60. ;Max number of jobs allowed +DEFOPT NQCHN==30. ;Max number of user disk channels open in system +DEFOPT SCHBLN==10. ;Number of runnable jobs to remember +DEFOPT SWBLK==1 ;1= 1=> swap blocking, 0=> privileged user +DEFOPT SWPWSP==0 ;1= Use working-set swap scheduler +DEFOPT PAGPRE==1 ;1= Use page-in preemption + +DEFOPT DMDSK==1 ;1= Use DM DSK format +DEFOPT QRSRVP==1 ;1= Has reserved disk packs (Secondary pack) +DEFOPT QAUTHP==1 ;1= Keep track of file authors + +DEFOPT NQS==1 ;# of disk drive units +DEFOPT NTUTBL==3 ;# 1K blocks in a TUT (better agree with disk DEFS) +DEFSYM NUDSL==500. ;# directories in file system (better agree with + ; SALV and DSKDMP) +DEFOPT RH11P==1 ; Has RH11 controller +DEFOPT RM80P==1 ; with one RM80 + +DEFOPT NETP==1 ;Has one kind of network anyway +DEFOPT CHAOSP==1 ;Has CHAOS net +DEFOPT MYCHAD==3132 ;CHAOS net address +DEFOPT NINDX==50. ;Number of indices +DEFOPT CH11P==1 ;CHAOS net goes through Unibus + +DEFOPT DZ11P==1 ;Has DZ11 TTY controllers + DEFOPT DZ11NB==4 ; 4 of them + DEFSYM DZ0BA=:760010 + DEFSYM DZ1BA=:760020 + DEFSYM DZ2BA=:760030 + DEFSYM DZ3BA=:760040 + +DEFOPT NKSTYS==1 ;# KS-10 8080 console 0 TTYs +DEFOPT NDZTYS==4. ;# DZ-11 TTYs +DEFOPT NSTTYS==4. ;# of STY's (Pseudo-TTY's) + +DEFOPT TSYSM==512. ;Total PDP10 1K memory blocks +DEFOPT NMMP==4 ;# exec pages for MMP table (# vir pgs/512.) + +;;; Next four better agree with SYSTEM;KSDEFS: +DEFSYM PMAGEM==020000 ;2.5 Age bit +DEFSYM PMCSHM==010000 ;2.4 Cache enable bit +DEFSYM PMRCM==001777 ;2.1 - 1.1 Physical page number + ; (The page table supports 20 bit physical + ; addresses.) +DEFSYM PMUNSD==146000 ;Unused bits + +DEFINE ITSIRP BODY +IRPS ITS,,[AI MC ML MD] +BODY +TERMIN +TERMIN +] ;MD + +IFE MCOND SI,[ ;Stacken ITS +DEFOPT KS10P==1 ;SI is a KS10 + +DEFOPT MAXJ==60. ;Max number of jobs allowed +DEFOPT NQCHN==30. ;Max number of user disk channels open in system +DEFOPT SCHBLN==10. ;Number of runnable jobs to remember +DEFOPT SWBLK==1 ;1= 1=> swap blocking, 0=> privileged user +DEFOPT SWPWSP==0 ;1= Use working-set swap scheduler +DEFOPT PAGPRE==1 ;1= Use page-in preemption + +DEFOPT DMDSK==1 ;1= Use DM DSK format +DEFOPT QRSRVP==1 ;1= Has reserved disk packs (Secondary pack) +DEFOPT QAUTHP==1 ;1= Keep track of file authors + +DEFOPT NQS==1 ;# of disk drive units +DEFOPT NTUTBL==4 ;# 1K blocks in a TUT (better agree with RP06 DEFS) +DEFSYM NUDSL==500. ;# directories in file system (better agree with + ; SALV and DSKDMP) +DEFOPT RH11P==1 ; Has RH11 controller +DEFOPT RP06P==1 ; with one RP06 + +DEFOPT NMTCS==1 ;Number of magtape units (so why not NMTUS?) +DEFOPT TM03S==1 ;TM03/RH11 Unibus tape controller + +DEFOPT DZ11P==1 ;Has DZ11 TTY controllers + DEFOPT DZ11NB==2 ; 2 of them + DEFSYM DZ0BA=:760010 + DEFSYM DZ1BA=:760020 + +DEFOPT NKSTYS==1 ;# KS-10 8080 console 0 TTYs +DEFOPT NDZTYS==16. ;# DZ-11 TTYs +DEFOPT NSTTYS==8. ;# of STY's (Pseudo-TTY's) + +DEFOPT TSYSM==512. ;Total PDP10 1K memory blocks +DEFOPT NMMP==4 ;# exec pages for MMP table (# vir pgs/512.) + +;;; Next four better agree with SYSTEM;KSDEFS: +DEFSYM PMAGEM==020000 ;2.5 Age bit +DEFSYM PMCSHM==010000 ;2.4 Cache enable bit +DEFSYM PMRCM==001777 ;2.1 - 1.1 Physical page number + ; (The page table supports 20 bit physical + ; addresses.) +DEFSYM PMUNSD==146000 ;Unused bits + +DEFINE ITSIRP BODY +IRPS ITS,,[SI] +BODY +TERMIN +TERMIN +] ;SI + +IFE MCOND FU,[ ;Australian KS10 +DEFOPT KS10P==1 ;FU is a KS10 + +DEFOPT MAXJ==60. ;Max number of jobs allowed +DEFOPT NQCHN==30. ;Max number of user disk channels open in system +DEFOPT SCHBLN==10. ;Number of runnable jobs to remember +DEFOPT SWBLK==1 ;1= 1=> swap blocking, 0=> privileged user +DEFOPT SWPWSP==0 ;1= Use working-set swap scheduler +DEFOPT PAGPRE==1 ;1= Use page-in preemption + +DEFOPT DMDSK==1 ;1= Use DM DSK format +DEFOPT QRSRVP==1 ;1= Has reserved disk packs (Secondary pack) +DEFOPT QAUTHP==1 ;1= Keep track of file authors + +DEFOPT NQS==1 ;# of disk drive units +DEFOPT NTUTBL==4 ;# 1K blocks in a TUT (better agree with RP06 DEFS) +DEFSYM NUDSL==500. ;# directories in file system (better agree with + ; SALV and DSKDMP) +DEFOPT RH11P==1 ; Has RH11 controller +DEFOPT RP06P==1 ; with one RP06 + +DEFOPT NMTCS==1 ;Number of magtape units (so why not NMTUS?) +DEFOPT TM03S==1 ;TM03/RH11 Unibus tape controller + +DEFOPT DZ11P==1 ;Has DZ11 TTY controllers + DEFOPT DZ11NB==1 ; 1 of them + DEFSYM DZ0BA=:760010 + +DEFOPT NKSTYS==1 ;# KS-10 8080 console 0 TTYs +DEFOPT NDZTYS==8. ;# DZ-11 TTYs +DEFOPT NSTTYS==4. ;# of STY's (Pseudo-TTY's) + +DEFOPT TSYSM==512. ;Total PDP10 1K memory blocks +DEFOPT NMMP==4 ;# exec pages for MMP table (# vir pgs/512.) + +;;; Next four better agree with SYSTEM;KSDEFS: +DEFSYM PMAGEM==020000 ;2.5 Age bit +DEFSYM PMCSHM==010000 ;2.4 Cache enable bit +DEFSYM PMRCM==001777 ;2.1 - 1.1 Physical page number + ; (The page table supports 20 bit physical + ; addresses.) +DEFSYM PMUNSD==146000 ;Unused bits + +DEFINE ITSIRP BODY +IRPS ITS,,[FU] +BODY +TERMIN +TERMIN +] ;FU + +IFE MCOND PM,[ ;MRC's KS10 (PandaMonium) +DEFOPT KS10P==1 ;PM is a KS10 + +DEFOPT MAXJ==60. ;Max number of jobs allowed +DEFOPT NQCHN==30. ;Max number of user disk channels open in system +DEFOPT SCHBLN==10. ;Number of runnable jobs to remember +DEFOPT SWBLK==1 ;1= 1=> swap blocking, 0=> privileged user +DEFOPT SWPWSP==0 ;1= Use working-set swap scheduler +DEFOPT PAGPRE==1 ;1= Use page-in preemption + +DEFOPT DMDSK==1 ;1= Use DM DSK format +DEFOPT QRSRVP==1 ;1= Has reserved disk packs (Secondary pack) +DEFOPT QAUTHP==1 ;1= Keep track of file authors + +DEFOPT NQS==1 ;# of disk drive units +DEFOPT NTUTBL==2 ;# 1K blocks in a TUT (better agree with RM03 DEFS) +DEFSYM NUDSL==500. ;# directories in file system (better agree with + ; SALV and DSKDMP) +DEFOPT RH11P==1 ; Has RH11 controller +DEFOPT RM03P==1 ; with one RM03 + +DEFOPT NMTCS==1 ;Number of magtape units (so why not NMTUS?) +DEFOPT TM03S==1 ;TM03/RH11 Unibus tape controller + +DEFOPT DZ11P==1 ;Has DZ11 TTY controllers + DEFOPT DZ11NB==1 ; 1 of them + DEFSYM DZ0BA=:760010 + +DEFOPT NKSTYS==1 ;# KS-10 8080 console 0 TTYs +DEFOPT NDZTYS==5. ;# DZ-11 TTYs +DEFOPT NSTTYS==4. ;# of STY's (Pseudo-TTY's) + +DEFOPT TSYSM==512. ;Total PDP10 1K memory blocks +DEFOPT NMMP==4 ;# exec pages for MMP table (# vir pgs/512.) + +;;; Next four better agree with SYSTEM;KSDEFS: +DEFSYM PMAGEM==020000 ;2.5 Age bit +DEFSYM PMCSHM==010000 ;2.4 Cache enable bit +DEFSYM PMRCM==001777 ;2.1 - 1.1 Physical page number + ; (The page table supports 20 bit physical + ; addresses.) +DEFSYM PMUNSD==146000 ;Unused bits + +DEFINE ITSIRP BODY +IRPS ITS,,[PM] +BODY +TERMIN +TERMIN +] ;PM + +IFE MCOND DX,[ ;Digex's KS10 +DEFOPT KS10P==1 ;DX is a KS10 + +DEFOPT MAXJ==60. ;Max number of jobs allowed +DEFOPT NQCHN==30. ;Max number of user disk channels open in system +DEFOPT SCHBLN==10. ;Number of runnable jobs to remember +DEFOPT SWBLK==1 ;1= 1=> swap blocking, 0=> privileged user +DEFOPT SWPWSP==0 ;1= Use working-set swap scheduler +DEFOPT PAGPRE==1 ;1= Use page-in preemption + +DEFOPT DMDSK==1 ;1= Use DM DSK format +DEFOPT QRSRVP==1 ;1= Has reserved disk packs (Secondary pack) +DEFOPT QAUTHP==1 ;1= Keep track of file authors + +DEFOPT NQS==1 ;# of disk drive units +DEFOPT NTUTBL==2 ;# 1K blocks in a TUT (better agree with RM03 DEFS) +DEFSYM NUDSL==500. ;# directories in file system (better agree with + ; SALV and DSKDMP) +DEFOPT RH11P==1 ; Has RH11 controller +DEFOPT RM03P==1 ; with one RM02/3 + +DEFOPT NMTCS==1 ;Number of magtape units (so why not NMTUS?) +DEFOPT TM03S==1 ;TM03/RH11 Unibus tape controller + +DEFOPT DZ11P==1 ;Has DZ11 TTY controllers + DEFOPT DZ11NB==1 ; 1 of them + DEFSYM DZ0BA=:760010 + +DEFOPT NKSTYS==1 ;# KS-10 8080 console 0 TTYs +DEFOPT NDZTYS==8. ;# DZ-11 TTYs +DEFOPT NSTTYS==4. ;# of STY's (Pseudo-TTY's) + +DEFOPT TSYSM==512. ;Total PDP10 1K memory blocks +DEFOPT NMMP==4 ;# exec pages for MMP table (# vir pgs/512.) + +;;; Next four better agree with SYSTEM;KSDEFS: +DEFSYM PMAGEM==020000 ;2.5 Age bit +DEFSYM PMCSHM==010000 ;2.4 Cache enable bit +DEFSYM PMRCM==001777 ;2.1 - 1.1 Physical page number + ; (The page table supports 20 bit physical + ; addresses.) +DEFSYM PMUNSD==146000 ;Unused bits + +DEFINE ITSIRP BODY +IRPS ITS,,[DX] +BODY +TERMIN +TERMIN +] ;DX + +; Default settings for all configuration-dependent assembly parameters. +; If a system definition has already set a value for a parameter, the +; default here will NOT be used. + +DEFOPT KL10P==0 ;1= KL10 processor +DEFOPT KS10P==0 ;1= KS10 processor +DEFOPT KA10P==0 ;1= KA10 processor + +IFE KL10P\KS10P\KA10P, .ERR Processor type required - KL10P, KS10P or KA10P + +IFN KS10P, DEFOPT KSFREQ==4100000./60. ; KS-ticks per PD-tick. + +DEFOPT C1MXP==0 ;1= Has PI channel 1 MPX feature + +DEFOPT MAXJ==63. ; Max number of jobs allowed +DEFOPT NQCHN==30. ; Max number of user disk channels open in system +DEFOPT SCHBLN==10. ; Number of runnable jobs to remember +DEFOPT SWBLK==0 ;1= 1=> swap blocking, 0=> privileged user +DEFOPT SWPWSP==0 ;1= Use working-set swap scheduler +DEFOPT PAGPRE==0 ;1= Use page-in preemption + +; Disk parameters + +IFNDEF NQS, .ERR NQS required - # of disk drive units +IFNDEF NTUTBL,.ERR NTUTBL required - # 1K blocks in a TUT + ; (This defn better agree with DC/RP/RH/T3 defs) +IFNDEF NUDSL, .ERR NUDSL required - # directories in file system + ; Just changing this will not work!! +DEFOPT DC10P==0 ;1= Has Systems Concepts disk control +DEFOPT RP10P==0 ;1= DEC RP10 disk control (RP02) +DEFOPT RH10P==0 ;1= DEC RH10 disk control (RP04) +DEFOPT RH11P==0 ;1= DEC RH11 disk control +DEFOPT RP06P==0 ;1= RH11 with RP06's +DEFOPT RM03P==0 ;1= RH11 with RM03's +DEFOPT RM80P==0 ;1= RH11 with RM80's +DEFOPT T300P==0 ;1= Trident T-300 via PDP-11 +DEFOPT QRDCMP==0 ;1= Software read-compare +DEFOPT DMDSK==0 ;1= Use DM DSK format +DEFOPT QRSRVP==0 ;1= Has reserved disk packs (Secondary pack) +DEFOPT QAUTHP==0 ;1= Keep track of file authors + + +; Magtape parameters +DEFOPT NMTCS==0 ; # Mag tape units +DEFOPT TM10A==0 ;1= IO-bus TM10 Mag tape +DEFOPT TM10B==0 ;1= DF10/TM10 Magtape +DEFOPT TM03S==0 ;1= TM03/RH11 KS Magtape +IFN NMTCS,IFE TM10A\TM10B\TM03S,.ERR No Magtape Controller type specified? + + +; Network parameters +DEFOPT NETP==0 ;1= Connected to some network, include net code. +DEFOPT CHAOSP==0 ;1= Has CHAOS net (Must have some interface def'd) +DEFOPT NCPP==0 ;1= Include NCP code (must have IMPP) +DEFOPT INETP==0 ;1= Include Internet Protocol code +DEFOPT TCPP==0 ;1= Include TCP code (must have INETP) +DEFOPT IPUNCP==0 ;1= IP in Chaos UNC is our only Internet address + +;NCP-specific parameters +DEFOPT NNETCH==30. ; # of NCP network channels system supports + +;IP-specific paramters +IFN INETP,[ +IFE IPUNCP,IFNDEF IMPUS3,.ERR IMPUS3 must be defined as Internet host addr +IFN IPUNCP,IFE CHAOSP,.ERR Chaosnet must exist for IP encapsulation scheme +] + +;Chaos-specific parameters +IFN CHAOSP,IFNDEF MYCHAD, .ERR MYCHAD must be defined as CHAOSnet host addr +DEFOPT NINDX==0 ; Number of indices for CHAOS connections +DEFOPT CH10P==0 ;1= CHAOS net via PDP-10 I/O bus +DEFOPT CH11P==0 ;1= CHAOS net via Unibus Chaos board on KS10 +DEFOPT DLCP==0 ;1= CHAOS net via DL10 +DEFOPT T11CHP==0 ;1= CHAOS net via Rubin 10-11 interface +IFN T11CHP,DEFOPT CH11NM==7 ; CHAOS net is on PDP-11 #7 of 10-11 interface + +;IMP interface specific parameters +DEFOPT IMPP==0 ;1= Has IMP interface to ARPAnet +IFN IMPP,IFNDEF IMPUS, .ERR IMPUS must be defined as ARPAnet host # +DEFOPT DMIMP==0 ;1= Has DM IMP interface +DEFOPT KAIMP==0 ;1= Has AI-KA/ML-KA/MX-KL IMP interface +DEFOPT KSIMP==0 ;1= Has KS10 UNIBUS ACC LH-DH IMP interface +IFN IMPP,IFE DMIMP+KAIMP+KSIMP,.ERR IMPP requires an interface type +IFN IMPP,IFN IPUNCP,.ERR IPUNCP and IMPP are incompatible + +; TTY line parameters +DEFOPT MTYP==0 ;1= Has Morton box multiplexor +DEFOPT DL10P==0 ;1= Has DL10/DC76 TTY controller +DEFOPT TK10P==0 ;1= Has TK10 TTY scanner +DEFOPT DPKPP==0 ;1= Has Datapoint kludge TTY mpxr +DEFOPT DZ11P==0 ;1= Has DZ11 Multiplexors + +IFN DZ11P, IFNDEF DZ11NB, .ERR DZ11P requires a value for DZ11NB +IFE DZ11P, DEFSYM DZ11NB==0 ; # DZ11s + +DEFOPT NOTYS==0 ; # KA-10 console 0 TTYs +DEFOPT NETYS==0 ; # KL-10 DTE20 console 0 TTYs +DEFOPT NKSTYS==0 ; # KS-10 8080 console 0 TTYs +DEFOPT NNVTTS==0 ; # Nova TTYs +DEFOPT NNTYS==0 ; # TTYs on Knight kludge +DEFOPT NDZTYS==0 ; # TTYs on DZ11s +DEFOPT NDPTYS==0 ; # TTYs on Datapoint kludge +DEFOPT NMTYS==0 ; # TTYs on Morton box +DEFOPT NDLTYS==0 ; # TTYs on DL10/DC76 +DEFOPT NSTTYS==0 ; # of STY's (Pseudo-TTY's) +DEFOPT N11TYS==0 ; # PDP11 TV TTYs (formerly 16. of them) +IFN N11TYS,[ + DEFOPT TT11NM==0 ; # of PDP11 that handles TTYs. + DEFOPT MXVBN==40 ; Max video buffer # for assignment purposes. +] ; These actually correspond to video switch inputs. +DEFOPT NF2741==0 ; First 2741 console # +DEFOPT N2741==0 ; # 2741's (formerly 3; flushed 3/21/76) +DEFOPT SYSCON==0 ; TTY # of system job console +DEFOPT APL==0 ; AP TTY # + +; Miscellaneous devices + +DEFOPT TEN11P==0 ;1= Rubin 10-11 interface (late of AI-KA) +DEFOPT XGP==0 ;1= Has XGP +DEFOPT NEWDTP==0 ;1= Has new dectape controller +DEFOPT NUNITS==0 ; # Utape (DECtape) units +DEFOPT OLPTP==0 ;1= Has old LPT (Data Products) +DEFOPT NLPTP==0 ;1= Has new LPT (ODEC) +DEFOPT GLPTP==0 ;1= Has Gould LPT +DEFOPT TTLPTP==0 ;1= LPT is on a TTY line (value = line #) +DEFOPT PTRP==0 ;1= Has paper tape reader/punch +DEFOPT PTPP==0 ;1= Paper tape punch works +DEFOPT PDCLKP==0 ;1= Has "DeCoriolis" clock +DEFOPT HCLKP==0 ;1= Has Holloway clock (device 710, 714) +DEFOPT CCLKP==0 ;1= Hack chess tournament clock stuff (device 374) +DEFOPT 340P==0 ;1= Has 340 display +DEFOPT TABP==0 ;1= Has Sylvania tablet +DEFOPT PLTP==0 ;1= Has Calcomp plotter +DEFOPT DSDP==0 ;1= Has deselection device +DEFOPT ARMP==0 ;1= Has arm (AMF mostly) (R.I.P.) +DEFOPT IMXP==0 ;1= Has IMX (input A/D multiplexor) (alas, no more) +DEFOPT OMXP==0 ;1= Has OMX (output D/A multiplexor) (alas, no more) +DEFOPT VIDP==0 ;1= Has VIDI (R.I.P.) +DEFOPT NTYP==0 ;1= Has DM kludge for talking to 11 +DEFOPT CODP==0 ;1= Has Morse code F1 92Mhz broadcast output device +DEFOPT PDP6P==0 ;1= Has PDP-6 (alas, no more) + ; (turning this on probably won't work) +DEFOPT RBTCP==0 ;1= Has Robot console +DEFOPT NDAP==0 ;1= Has "new" D/A converters (alas, no more) +DEFOPT STKP==0 ;1= Has Stanford keyboard (not any more) +DEFOPT E.SP==0 ;1= Has E&S LDS-1 display + +; Some software options + +DEFOPT MSPP==0 ;1= Want message slurper +DEFOPT DEMON==0 ;1= Want crufty DM demon facility +DEFOPT TPLP==0 ;1= Want pseudo LPT + + +; Physical memory parameters + +DEFOPT ECCMEM==0 ;1= Has HIC's error correcting memory +DEFOPT NMMP==4 ; # exec pages for MMP table (# vir pgs/512.) +IFNDEF TSYSM, .ERR TSYSM required - Total PDP10 1K mem blocks + +IFNDEF PMRCM, .ERR PMRCM required - Mem addr field in page map +IFNDEF PMAGEM,.ERR PMAGEM required - Age bits in page map +IFNDEF PMCSHM,.ERR PMCSHM required - Cache bit +IFNDEF PMUNSD,.ERR PMUNSD required - Unused bits + +IFNDEF ITSIRP,.ERR ITSIRP required - Names of local ITS machines + +; Any parameter conflict checks can be made here. + +IFN DZ11P,[ +IFG NDZTYS-, .ERR More DZ11 TTYs than controllers? +REPEAT DZ11NB,[ +IFNDEF CONC DZ,\.RPCNT,BA, .ERR DZ11 bus address not specified. +] +] +IFN $$TEMP,EXPUNGE DEFSYM +IFN $$TEM2,EXPUNGE DEFOPT diff --git a/src/system/core.82 b/src/system/core.82 new file mode 100755 index 00000000..cd3a18b1 --- /dev/null +++ b/src/system/core.82 @@ -0,0 +1,2989 @@ + +;;; CORE JOB + +SUBTTL CORE ALLOCATOR - USER ROUTINES +; +; USER ROUTINES (TO COMMUNICATE WITH CORE JOB) +; +UACORE: ;U HAS INDEX CORE REQUEST IS FOR +ACORE: CAILE B,400 + POPJ P, + MOVE Q,U ;USER TO MAKE CORE FOR +ACORE1: PUSH P,U + MOVE U,USER + PUSHJ P,ACRF1 + SKIPA + AOS -1(P) + POP P,U + POPJ P, + +;EXCESSIVE CORE REQUEST CHECK +ACRTST: CAILE B,400 + POPJ P, + JRST POPJ1 + ;CORTYP SYSTEM CALL. +;IF 2 ARGS,1ST ARG IS JOB SPEC, LIKE CORBLK'S 2ND AND 4TH ARGS. +;2ND ARG IS PAGE NUMBER IN THAT JOB. +;IF ONLY 1 ARG, IT IS THE PAGE NUMBER IN THE EXECUTING JOB. +;RETURNED VALUES: +;1ST VALUE BITS: +; %CBWRT ;4.9 PAGE IS WRITEABLE +; %CBRED ;4.8 PAGE IS READABLE (EXISTS) +; %CBPUB ;4.6 PAGE IS PUBLIC +; %CBLOK ;4.2 PAGE IS LOCKED IN CORE +; %CBSLO ;3.9 PAGE IS IN SLOW MEMORY +; FOR NON EX PAGE, ALL THE REST ARE 0. +;2ND IS 0 => PAGE IS ABSOLUTE, -1 => UNSHARED, +; ELSE IS JOB NUMBER OF NEXT JOB IN CIRCULAR LIST. +;3RD IF ABSOLUTE PAGE, HAS PAGE NUMBER. +; IF PAGE IS SHARED, HAS PAGE NUMBER IN THE JOB +; WHOSE NUMBER IS THE 2ND VALUE. ELSE, 0. +;4TH BIT 4.9 => PAGE IS IN CORE. +; RH IS NUMBER OF TIMES PAGE IS SHARED +; (WILL BE 0 FOR ABS PAGE OR IF NO PAGE, +; OTHERWISE WILL BE >= 1) + +NCORTY: PUSHJ P,SWTL ;DON'T LET PAGE MAPS CHANGE. + CIRPSW + SOSG W ;IF 1 ARG, USE -1 (SELF) FOR JOB SPEC. + SKIPA B,[-1] + EXCH A,B ;ELSE 1ST ARG IS JOB SPEC. + MOVE J,B + JSP T,NCRUI2 ;DECODE THE JOB SPEC IN J, + JFCL ;RETURNS USR IDX IN J. + TDNE A,[-400] + JRST OPNL33 ;BAD PAGE NUM. + PUSHJ P,NCORT0 ;DO THE ACTUAL WORK. + PUSHJ P,LSWPOP ;UNLOCK CIRPSW, + JRST POPJ1 ;GIVE VALUES TO USER, SKIP. + +;CALL HERE FROM AUSET5 (ALWAYS COMES WITH CIRPSW LOCKED) +NCORT0: PUSH P,U +IFN PDP6P,[ + CAIN J,-1 + JRST [ SETZB B,D ;DON'T CALL UPLC IF PDP6, WOULD CRASH SYSTEM + MOVEI C,PDP6BM_-12(A) + CAIL A,LPDP6M + TDZA A,A + MOVSI A,%CBRED+%CBWRT + JRST POPUJ ] +];PDP6P + MOVEI U,(J) ;UPLC USES USER IN U. + PUSHJ P,UPLC ;NOTE PAGE NUM IS IN A. + LDB J,T ;GET PAGE'S HARDWARE HALFWD, + LDB C,Q ;GET CIRC. LIST POINTER. + JUMPE C,NCORTE ;J IF NO PAGE THERE. + MOVEI A,(J) + TRNE A,600000 ;GET ACCESS INTO A 1.1-1.2 + LDB A,[200200,,A] + CAIN A,2 ;CHANGE READ-WRITE-FIRST TO READ-WRITE. + MOVEI A,3 + ROT A,-2 ;SHIFT INTO 4.8-4.9 + CAIN C,-1 + JRST NCORTA ;J IF ABSOLUTE PAGE(CIRC PTR -1) + PUSHJ P,CHACK ;PG MUST HAVE REAL CIRC LIST, TRACE IT. + EXCH C,D ;D HAD MMP IDX; C HAD IN-CORE,,LIST LENGTH. + ADD C,MMPEAD + SKIPGE C,(C) .SEE MMPPUB + TLO A,%CBPUB + TLNE C,MMPLOK + TLO A,%CBLOK + TLNE C,MMPSLO + TLO A,%CBSLO + SUBI D,1 ;LIST LENGTH COUNTS THE MMP ENTRY, + SKIPGE D + SUBI D,1 ;COUNTS THE MEMBLT ENTRY IF PAGE IN CORE. + TRNN D,-2 ;RH NOW HAS # SHARERS, + JRST NCORTS ;ONLY 1 => PAGE NOT SHARED. + MOVE C,Q + MOVE B,P + PUSHJ P,UCPRL ;>1 SHARER => FIND NEXT SHARER, + 400000,,.+1 + MOVE P,B ;UN-SCREW STACK (UCPRL PUSHJ'D BACK) + LDB B,[101100,,T] + MOVE C,I ;2ND, 3RD VALUES USR NUM & PAGE NUM + JRST POPUJ ;OF THE NEXT SHARER. + +;COME HERE IF NO PAGE WITH THAT PAGE NUM. +NCORTE: SETZB A,B + SETZB C,D ;RETURN ALL ZEROS. + JRST POPUJ + +;COME HERE IF ABS PAGE, ACCESS ALREADY IN A. +NCORTA: SETZB B,D ;JOB # 0 (SYS JOB) FOR ABS PAGE. + LDB C,[PMRCAD,,J] ;GET ABS PAGE NUM FROM HARDWARE HALFWD. + JRST POPUJ + +;COME HERE IF UNSHARED NORMAL PAGE. +;ACCESS ALREADY IN A, 4TH VALUE IN D. +NCORTS: SETO B, ;2ND VALUE -1 FOR UNSHARED. + SETZ C, + JRST POPUJ + +;CORBLK CALL +;1ST ARG FLAG BITS: (RH XOR'D INTO LH BEFORE DECODING) + +%CB==0,,525252 +%CBWRT==400000 ; 4.9 GET WRITE ACCESS IF OK, DON'T FAIL IF NOT. +%CBRED==200000 ; 4.8 GET READ ACCESS +%CBNDW==100000 ; 4.7 GET WRITE ACCESS, FAIL IF CAN'T. +%CBPUB==40000 ; 4.6 MAKE PAGE PUBLIC +%CBPRV==20000 ; 4.5 MAKE IT PRIVATE (BOTH FAIL IF COULDN'T GET WRITE ACCESS) +%CBNDR==10000 ; 4.4 FAIL IF CAN'T GET READ ACCESS.(COPYING NONEXISTANT PAGE) +%CBCPY==4000 ; 4.3 MAKE COPY (CURRENTLY ONLY IMPLEMENTED FOR PAGE OF FILE) +%CBLOK==2000 ; 4.2 LOCK PAGE IN CORE. +%CBULK==1000 ; 4.1 UNLOCK PAGE (ALLOW SWAP-OUT) +%CBSLO==400 ; 3.9 MAY ONLY RESIDE IN SLOWEST MEMORY +%CBUSL==200 ; 3.8 ALLOWS USE OF ANY MEMORY. + ;IF ALL 0, DELETE. + +%CBNWP==563600 ;BITS THAT NEED WRITE-PERMISSION. + +;2ND ARG SPECIFIES JOB TO PUT PAGE IN +; IS EITHER CHNL NUM, -1 FOR SELF, OR 400000+USRNUM +;JOB SPECIFIED MUST BE CURRENT JOB OR INFERIOR. + +;3RD ARG RH. IS PAGE NUM. IN IT. +; LH. IF NEGATIVE, BLOCK MODE, REPEAT THAT MANY TIMES, +; INCREMENTING BOTH PAGE NUMS EACH TIME. +;IN BLOCK MODE, REWRITES 3RD AND 5TH ARGS EACH TIME. + +;4TH ARG IS SOURCE OF PAGE, +; A DISK CHANNEL NUMBER (GET N'TH PAGE IN FILE), OR +; A SPEC: +; A USR, JOB, BOJ, OR STY CHANNEL NUMBER +; OR ONE OF THE FOLLOWING SPECIAL CODES: +%JS==,-1 +%JSNUM==400000 ;400000+JOB NUMBER => THAT JOB +%JSSUP==400377 ;CURRENT JOB'S SUPERIOR +%JSELF==,,-1 ;SELF +%JSTVB==,,-2 ;TV11 VIDEO BUFFER IN FIRST 8 PAGES, 1ST WD OF 9TH PG IS CONSOLE REG +%JSNUL==,,-3 ;NULL JOB (NOT VALID FOR CORBLK) +%JSALL==,,-4 ;ALL JOBS (NOT VALID FOR CORBLK) +%JSNEW==,,-5 ;FRESH PAGE +%JSABS==,,-6 ;ABSOLUTE PAGE (PHYSICAL MEMORY) +; JOB 0 = SYSTEM JOB = EXEC VIRTUAL ADDRESS SPACE +; JOB 1 = CORE JOB = FRESH PAGE (OBSOLESCENT, USE %JSNEW, EVENTUALLY WILL GO AWAY) +;IF NO 4TH ARG, SAME AS 2ND + +;5TH ARG IS PAGE NUM IN SOURCE (IGNORED FOR FRESH PAGE) +;IF NO 5TH ARG, SAME AS 3RD IF 4TH ARG SPECIFIES JOB. + +;IF 4TH ARG SPECS FILE, USE CURRENT ACCESS PNTR +;IF INSERTING DISK PAGES, THE ACCESS PTR WILL BE +;POSITIONED AT THE BEGINNING OF THE PAGE AFTER THE LAST PAGE INSERTED. + +;BITS IN REGS R AND I: +NCOR$P==400000 ;SOURCE USER ISN'T WRITEABLE. PAGES ARE, IFF PUBLIC. +NCOR$Q==200000 ;SOURCE IS A DISK FILE. + +;CORBLK - COMMENTS ON PRECEDING PAGE. +NCORBL: TSC A,CTLBTS(U) + TLC A,(A) ;WIN FOR IMMEDIATE FIRST ARG + HRRZM C,SRN3(U) ;SAVE PTRS TO 3RD, 5TH ARGS IN SRN3, SRN4 RESPECTIVELY + TLNE C,1000 + TLZA C,-1 + UMOVE C,(C) + SKIPGE C ;IF WILL REWRITE,CHECK FOR PURE + XCTR XRW,[MOVES @SRN3(U)] + HRRZM E,SRN4(U) + CAIGE W,5 ;BUT IF NO 5TH ARG, SAY SO & USE 3RD. + JRST NCORB1 ;DEFAULT E TO C,SETOM SRN4 + TLNN E,1000 ;IMMEDIATE 5TH ARG LEGAL + JRST NCORB8 + JUMPGE C,NCORB7 ;ONLY IF WON'T HAVE TO REWRITE IT + JRST OPNL33 + +NCORB1: SETOM SRN4(U) + MOVE E,C + JRST NCORB7 + +NCORB8: UMOVE E,(E) + SKIPGE C + XCTR XRW,[MOVES @SRN4(U)] +NCORB7: ANDI E,-1 + MOVE J,B + JSP T,NCRUI1 ;GET USER INDEX OF TARGET. + JRST NCORB0 ;IF DOESN'T SKIP, CAN CERTAINLY WRITE. + CAIE J,-1 ;CAN'T STICK PAGE IN 6. + JSP T,NCORWR ;ELSE CHECK. + JRST OPNL31 ;CANT WRITE SO CANT STICK PAGE IN +NCORB0: MOVEI TT,(J) ;SAVE DEST. USER IDX. + CAIN TT,(U) ;IF NOT ACTING ON SELF, PCLSR TARGET JOB. + JRST NCORC1 + EXCH A,TT + PUSHJ P,RPCLSR + PUSHJ P,LSWPOP ;SOS DIELOK(A) + MOVEM A,SRN5(U) + MOVSI T,BSSTP ;BUT LEAVE BSSTP SET INSTEAD OF RH + IORM T,USTP(A) + SOS USTP(A) ;BECAUSE CORE JOB WANTS RH TO BE CLEAR + EXCH A,TT + PUSHJ P,LOSSET ;UNDO SETTING OF BSSTP IF WE PCLSR OR FAIL + NCORFS + CAIA +NCORC1: PUSHJ P,LSWPOP ;SOS DIELOK(TT) +;DROPS THROUGH. + +;DROPS THROUGH. ALSO COME HERE FROM ACBLK. +;TARGET DECODED AND STOPPED IF NEC.; USER IDX IN TT. +; NOW DECODE SOURCE IF NEC. +NCORB9: PUSHJ P,SWTL + CIRPSW + TLNE A,%CBNDW ;FORCE WRITE => WRITE. + TLO A,%CBWRT + JUMPE A,NCORD ;0 ACCESS WANTED => DELETE PAGES. + TLO A,%CBRED ;NOT DELETE, WANT AT LEAST READ ACCESS. + CAIGE W,4 ;IF HAD 4TH ARG, DECODE, + JRST NCORC2 ;ELSE USE DECODED 2ND (STILL IN J). + HRRZ J,D + CAIE J,%JSNEW + CAIN J,%JSABS + JRST NCORC2 ;SPECIAL NON-JOB SOURCE, SKIP DECODE +IFN N11TYS,[ + CAIN J,%JSTVB + JRST [ SKIPN TEN11F ;TV11 SOURCE + SKIPL TT11P + JRST OPNL10 ;DEVICE NOT AVAIL + JRST NCORC2] +] + MOVE J,D + JSP T,NCRUI1 ;GET SOURCE USR IDX + JRST NCORB2 + JRST NCORC0 + TLNN H,%CLSQ ;COME HERE IF ARG IS RANDOM IO CHANNEL. + JRST OPNL34 ;NOT DSK => NO GOOD. + MOVE R,J ;2 SKIPS => DISK CHNL; PUT ITS # IN R. + TLO R,NCOR$Q ;INDICATE DISK CHNL + MOVSI T,%QAACC + TDNE T,QSRAC(R) ;INSURE THAT %QAACC WILL BE ON IF OUR + JRST NCORQD + IORM T,QSRAC(R) ;CALL TO QFNTR FINDS EOF. + MOVE T,QFBLNO(R) ;IF %QAACC WAS 0, THEN QRADAD ISN'T SET UP. + MOVEM T,QRADAD(R) +NCORQD: SETOM NCORQC ;1ST TIME THRU NCORL LOOP COMING UP. + CAIGE W,5 + JRST NCORL + MOVE T,E ;DON'T SMASH E, WILL BE WRITTEN BACK TO USER + LSH T,10. ;5TH ARG GIVES PAGE ADDRESS IN FILE FOR DISK CHNL + IMULI T,@QSBYTE(R) + MOVEM T,QRADAD(R) ;SET ACCESS PTR OF DSK CHNL -> SPEC'D PAGE. + JRST NCORL + +NCORC0: TLNN A,%CBNWP ;IF REQUIRE ALTERATION, + JRST NCORB2 + JSP T,NCORW1 ;IF CAN'T WRITE THAT JOB, + HRLI J,NCOR$P ;SET FLAG TO CHECK FOR PUBLIC. +NCORB2: CAIE J,-1 ;IF NOT PDP6, + PUSHJ P,LSWPOP ;SOS DIELOK(J) + CAIN J,LUBLK ;IF SOURCE IS CORE JOB (EVENTUALLY DELETE THESE TWO LINES) + MOVEI J,%JSNEW ; THAT MEANS GET FRESH PAGE +NCORC2: MOVE R,J + CAIN R,%JSNEW ;FRESH PAGE IMPLIES WRITING + TLO A,%CBNDW+%CBWRT + +;DROPS THROUGH + +;DROPS IN + +;NOW HAVE TARGET IDX IN TT, SOURCE IN R (USER INDEX, -1 FOR +; PDP6, %JSTVB, %JSNEW, OR %JSABS). +;TARGET PAGNUM IN C; SOURCE IN E (MAYBE INVALID). +;R 4.9 => WRITE REQUIRES PUBLIC PAGE. +;R 4.8 => R HAS DISK CHNL (AND NCORQC IS -1 THE 1ST TIME AROUND) +;DECIDE WHAT KIND PAGE WANTED AND FIND IT. +;CIRPSW MUST BE ON TOP OF LSWPR. IT WILL BE +;UNLOCKED EVENTUALLY (AND ALSO 1 MORE UNDERNEATH IT +;IF THE TARGET JOB ISN'T US). FAILURE DOES A LSWCLR. +NCORL: MOVEI I,(R) ;I WILL HAVE USR IDX FOR ACTUAL PAGE. + HLRS A ;RH OF A WILL GET ACCESS TO BE GRANTED. + TRNE C,-400 ;CHECK DEST PAGE NUM IN RANGE. + JRST OPNL33 + + PUSH P,U + PUSH P,C + TLNE R,NCOR$Q + JRST NCORQ1 ;DISK FILE +IFN PDP6P,[ + CAIN I,-1 + JRST NCORE4 ;-1 => PDP6 PAGE. +] +IFN N11TYS,[ + CAIN I,%JSTVB + JRST NCORV1 ;TV11 +] + CAIN I,%JSNEW + JRST NCORF0 ;FRESH PAGE. + CAIN I,%JSABS + JRST NCORE1 ;ABSOLUTE PAGE. + CAIL E,400 + JRST NCORE7 ;ELSE SOURCE PAGNUM MUST BE < 400 + MOVEI U,(R) ;SOURCE IS A USER +NCORF2: EXCH E,A ;GET SOURCE PAGNUM IN A + PUSHJ P,UPLC;(A,U) ;FIND THE PAGE WANTED. + EXCH E,A + LDB J,Q ;UPLC RETURNS IN T,Q. + JUMPE J,NCORE6 ;FAIL OR DELETE IF HE HAS NO PAGE THERE. + CAIN J,-1 + JRST NCORE5 ;IF THAT PAGE IS ABS,CHANGE TO ABS REQ. + PUSHJ P,CHACK ;A REAL PAGE, FIND MMP, PREV. PTR. + ADD D,MMPEAD + MOVE B,Q + MOVEI I,(R) ;CHACK CLOBBERS I + TLNN A,%CBNDW+%CBWRT ;IF WANTED ALTERATION, CHECK LEGAL. + JRST NCORB3 + LDB J,T ;1ST OF ALL, SOURCE MUST HAVE WRITE PERM. + TRNN J,600000 + LSH J,20 + TRNN J,400000 + JRST NCORB5 + CAIN R,%JSNEW + JRST NCORF3 +NCORF4: CONO PI,UTCOFF ;DSK XFER COULD COMPLETE, CHANGING INTRANSIT BIT + MOVE J,(D) ; HE HAS WRITE PERM.; GET MMP IN J. + TLNE R,NCOR$P ; CAN'T ALTER IF NEEDED PUBLIC BUT IT ISN'T. + JUMPGE J,[ CONO PI,UTCON .SEE MMPPUB + JRST NCORB5] + TLNE A,%CBPUB ;WE CAN ALTER; CHANGE PUBLIC IF REQ. + TLO J,MMPPUB + TLNE A,%CBPRV + TLZ J,MMPPUB + TLNE A,%CBLOK + TLO J,MMPLOK + TLNE A,%CBULK + TLZ J,MMPLOK + TLNE A,%CBSLO + TLO J,MMPSLO + TLNE A,%CBUSL + TLZ J,MMPSLO + MOVEM J,(D) + CONO PI,UTCON + JRST NCORB3 + +NCORF0: MOVEI U,(TT) ;WHEN CREATING A FRESH PAGE, HAVE TO RE-USE A PREVIOUSLY + MOVEI E,(C) ;EXISTING PAGE IF POSSIBLE, BECAUSE AFTER THE FRESH PAGE + JRST NCORF2 ;IS GIVEN, USER WILL BE PCLSR'ED AND WILL COME IN AGAIN + ;LOOKING FOR A FRESH PAGE. CURRENTLY THIS CAUSES A BUG + ;THAT A "FRESH PAGE" IS NOT ALWAYS ZERO. + +NCORF3: CAIE C,2 ;WANT FRESH PAGE + CAMN C,[SETZ 3] + JRST .+2 + JRST NCORD0 ;SHARED PAGE CAN'T SERVE AS FRESH PAGE + MOVEI I,(TT) + JRST NCORF4 + +;COME HERE IF REQ WRITE ON REAL PAGE BUT CAN'T GRANT. +NCORB5: CAIN R,%JSNEW + JRST NCORD0 ;JUST REPLACE WITH FRESH PAGE + TLNE A,%CBNDW+%CBPUB+%CBPRV+%CBSLO+%CBUSL+%CBLOK+%CBULK ;IF HE INSISTED, FAIL. + JRST NCORE0 + TRZ A,%CBWRT ;ELSE GIVE HIM ONLY READ PERM. +;COME HERE IF PAGE EXISTS TO GIVE ACCESS AS IN A 2.8,2.9 +NCORB3: HRRZ J,(P) + CAIN TT,(I) ;ARE WE REPLACING PAGE BY ITSELF? + CAME E,J + JRST NCORD0 ;NO, DELETE OLD, INSERT NEW. + LDB J,T ;REPLACING PG W/ SELF, SET ACCESS & EXIT. + TRNN J,600000 + JRST NCORI1 + TRNN J,400000 ;CHANGE READ TO RWF + TRC J,600000 + TRNE A,%CBWRT + JRST NCORI2 + MOVSI I,40000 + TROE J,200000 + ANDCAM I,(D) + TRZ J,400000 + JRST NCORI2 + +NCORI1: MOVEI J,1 + TRNE A,%CBWRT + TRO J,2 +NCORI2: DPB J,T + POP P,C + POP P,U + JRST NCORX ;TO END OF LOOP. + +NCORQ1: PUSH P,A + PUSH P,TT + PUSH P,R + MOVEI A,(R) + AOSN NCORQC ;THE 1ST TIME AROUND LOOP? + JRST NCORQ0 ;YES, ACCESS TO 1ST PAGE TO BE INSERTED. + PUSHJ P,QFNTN ;NO, JUST MOVE FORWARD 1 PAGE + JRST NCORE8 ;REACHED EOF, CAN'T INSERT PAGE +NCORQF: POP P,R + POP P,TT + POP P,A + MOVE I,R ;FOUND THE PAGE, GO INSERT IT. + JRST NCORD0 + +NCORQ0: MOVE Q,QRADAD(A) + PUSHJ P,QFNTR + JRST NCORE8 + PUSHJ P,QUDULK ;QFNTR LEAVES IT LOCKED + AOS QSLGL(A) ;DON'T BE FOOLED BY QFNTR'S TRICK + SOS QSBI(A) ;ON THE DISK PI RTNS. + JRST NCORQF + +NCORE8: POP P,R + POP P,TT + POP P,A +NCORE6: CAIN R,%JSNEW ;COPY NONEXISTANT PAGE + JRST NCORD0 ;JUST PUT IN A FRESH PAGE + HRRI A,0 ;CHANGE TO DELETE RQ. + TLNN A,%CBNDR+%CBNDW+%CBPUB+%CBPRV+%CBLOK+%CBULK+%CBSLO+%CBUSL + JRST NCORD0 ;IF INSIST ON ACCESS, FAIL. +NCORE0: PUSHJ P,OPNL32 ;CAN'T GRANT ACCESS OPNL. +POPCUJ: POP P,C ;FAIL OUT OF CALL. + JRST POPUJ + +IFN PDP6P,[ +;REQ FOR PDP6 PAGE. +NCORE4: CAIL E,LPDP6M + JRST NCORE7 ;OUT OF RANGE. + MOVEI B,PDP6BM_<-10.>(E) + JRST NCORE3 ;CONVERT TO ABS REQ, WRITE OK +] + +IFN N11TYS,[ +;REQ FOR TV11 PAGE. +NCORV1: CAIL E,NTVBP + JRST NCORE7 + SKIPL TVCREG(TT) ;IF CONSOLE REGISTER NOT ALREADY SET UP + JRST NCORV2 + MOVE B,TVVBN(TT) ;INITIALIZE IT FROM BLINKER + MOVEM B,TVCREG(TT) + CAMN TT,USER + MOVEM B,400000+TTR10*2000 ;INITIALIZE HARDWARE CONSOLE REGISTER. +NCORV2: LDB B,TTCRT(E) ;GET MAP ENTRY OUT OF EXEUMP + ANDI B,PMRCM ;MASK TO PAGE # + JRST NCORE3 ;CONVERT TO ABS REQ, WRITE OK +] +;REQ FOR ABS PAGE. +NCORE1: MOVEI B,(E) + CAIGE B,TSYSM + JRST NCORE2 ;ACCESS AVAILABLE, READ ONLY + JRST NCORE6 ;CAN'T GET ACCESS TO PAGE. + +NCORE7: PUSHJ P,OPNL33 ;BAD ARG OPNL. + JRST POPCUJ + +;PAGE TO COPY WAS AN ABS PAGE. +NCORE5: CAIN R,%JSNEW + JRST NCORD0 ;SUBSTITUTE A FRESH PAGE + LDB B,T ;GET ABS PAGE NUM. + TRZE B,400000 ;IF HE HASN'T WRITE PERM. + JUMPGE R,NCORE3 ;OR WE CAN'T WRITE IN HIM, +NCORE2: TRZ A,%CBWRT ;CAN'T GET WRITE, + TLNN A,%CBNDW ;FAIL IF INSIST. +NCORE3: TLNE A,%CBPUB+%CBPRV+%CBLOK+%CBULK+%CBSLO+%CBUSL + JRST NCORE0 ;OR IF TRYING TO CHANGE PUBLICNESS. + MOVE D,B ;GET JUST THE PAGE # (NOT THE ACCESS CODE) + ANDI D,PMRCM ;TO INDEX INTO TABLES WITH. +IFN TEN11P,[ + LDB I,[.BP D] ;GET MOBY # + CAIE I,T11CPA_-18. + JRST NCORE9 + MOVE Q,D + SUBI Q,_8 + CAIL Q,256. + JRST 4,. + SKIPN I,T11MP(Q) + JRST 4,. ;SHOULDNT HAVE ABS PNTR TO NOT SET UP PAGE + AOJE I,NCOREA ;CONFLICT PAGE + LDB I,[350500,,T11MP(Q)] + CAIN I,37 + JRST NCOREA ;USAGE COUNT FULL + ADDI I,1 + DPB I,[350500,,T11MP(Q)] + JRST NCOREA +NCORE9:] +IFN PDP6P,[ + CAIL D,PDP6BM_-10. ;IS ABS PAGE # WITHIN RANGE OF PDP6 PAGES? + CAIL D,PDP6BM_-10.+LPDP6M + JRST NCOREB + SKIPL PDP6UP ;IF SO, ALLOW PAGE COPYING, IFF PDP6 IS UP. + JRST NCORE6 + JRST NCOREA + +NCOREB:] + CAIL D,TSYSM + JRST NCORE6 ;DONT ALLOW POINTER TO PAGE ABOVE TOTAL SYSTEM MEMORY + LDB I,[MUR,,MEMBLT(D)] + CAIN I,MUHOLE ;DON'T GIVE ABS PAGE THAT IS NXM. + JRST NCORE6 +NCOREA: MOVEI I,%JSABS ;INDICATE ABS REQ. + JRST NCORD0 + +EBLK +NCORQC: 0 ;COUNTS PASSES THRU NCORL, IF SOURCE IS DISK FILE. + ;FORCES COMPLETE REPOSITIONING IN FILE THE 1ST TIME THRU. +BBLK + +;THIS IS FOR DELETE RQS WHAT NCORL IS FOR INSERTS. +.SEE NCORL ;ABOUT CIRPSW, ACS, ETC. + ;ALSO SEE COMMENTS HALFWAY DOWN THIS PAGE. +NCORD: TRNE C,-400 + JRST OPNL33 ;PAGE NUM. OUT OF RANGE. + PUSH P,U + PUSH P,C +NCORD0: PUSH P,A ;COME IN HERE ON VALID INSERT RQ. +NCORD1: MOVE U,TT + HRRZ A,-1(P) + PUSH P,T + PUSH P,B + PUSHJ P,UPLC ;SAVE TIME BY CHECKING WHETHER PAGE EXISTS. + LDB B,T + SKIPE B + PUSHJ P,PAGERT ;IT EXISTS; DELETE IT. + POP P,B + POP P,T + POP P,A ;FLAG WORD + POP P,C ;TARGET PAGNUM + POP P,U + TRNN A,%CBRED+%CBWRT ;IF NO ACCESS REQ, IS DELETE, THRU. + JRST NCORX +;RH. OF A HAS ACCESS TO GRANT. LH(A) HAS ORIGINAL CONTROL BITS. +;IF I=%JSABS, ABS PAGE, NUM. IN B. +;IF I=%JSNEW, FRESH PAGE. +;IF 4.8 IN I SET, DISK PAGE POINTED TO BY CHNL IN I +;ELSE OLD PAGE, B IS BP -> CIRC LIST, T -> OLD ACCESS. + PUSH P,C ;-3 + PUSH P,E ;-2 + PUSH P,TT ;-1 + PUSH P,A ;0 + TLNE I,NCOR$Q + JRST NCORQ2 ;INSERT PAGE FROM FILE + CAIN I,%JSABS + JRST NCORA ;GO INSERT ABS PAGE + CAIE I,%JSNEW + JRST NCORR ;GO INSERT REAL PAGE. + PUSH P,R + LSH C,9 ;INSERT FRESH PAGE. + MOVEI Q,(TT) ;TARGET JOB + IDIVI TT,LUBLK ;CLOBBERS I. + IORI TT,400000(C) + HRLI TT,204000 + TLNE A,%CBPUB ;MAYBE RQ PUBLIC + TLO TT,1000 + PUSHJ P,NACRFL ;PUT IN CORE RQ (FREES CIRPSW) + JRST NCORF1 + POP P,R + PUSHJ P,SWTL + CIRPSW + HRRZ E,-3(P) ;GET TARGET PAGE NUM + JRST NCORR2 + +NCORF1: SUB P,[5,,5] + JRST OPNL37 ;NO CORE OPNL. + +;COME HERE IF NEED TO WAIT FOR CORE AVAILABLE FOR NEW MMP PAGE. +NCORQW: PUSHJ P,LSWPOP ;UNLOCK TUT. + PUSHJ P,LSWPOP ;AND CIRPSW, SO CORE JOB CAN OPERATE. + MOVEI T,3 ;WAIT TILL MEM HAS BEEN FREED BY CORE JOB. + CAMLE T,LMEMFR + PUSHJ P,UFLS + PUSHJ P,SWTL ;RE-LOCK CIRPSW + CIRPSW + MOVE TT,(P) + JRST NCORQB ;THEN RETRY, RELOCKING TUT. + ;FIND OR CREATE MMP ENTRY FOR BLOCK <- DISK CHNL IN I. +;ACCESS TO GRANT IS IN A. +;RETURNS STUFF IN B,T ACCORDING TO COMMENT +;AFTER NCORD1 (IF NEW MMP, IT POINT TO SELF AND B -> IT) +NCORQ2: PUSH P,R + PUSH P,[NCORR3] ;RETURN TO NCORR3, SKIPPING UNLESS MMP FULL + MOVE TT,A + MOVE A,I +NCORQ7: PUSH P,TT ;ENTRY FROM NLOAD +NCORQB: MOVE I,QDSKN(A) + MOVE W,QSLGL(A) + HRL W,I + PUSHJ P,QTLOCK + TRNE TT,%CBCPY ;SPECIFIED COPY-ON-WRITE? + JRST NCORQ6 ;GET FRESH COPY OF PAGE + MOVE B,W ;ELSE TRY TO SHARE EXISTING COPY OF PAGE + IDIVI B,SHRHSL ;LOOK UP IN SHAREABLE-PAGE HASH TABLE + MOVEI B,SHRHSH-1(C) +NCORQ5: HRRZ B,1(B) ;THREAD TO NEXT MMP ENTRY IN BUCKET + JUMPE B,NCORQ6 ;END OF LIST, DESIRED PAGE NOT FOUND + HLRZ C,1(B) ;GET DISK ADDRESS OF THIS PAGE + LDB R,[$MMPUN,,(B)] + CAIN C,(W) + CAIE R,(I) + JRST NCORQ5 ;NOT THE ONE WE WANT + MOVEI R,(B) ;SET UP MMP IDX IN R + SUB R,MMPEAD ;AS GMMPP RETURNS IT. + PUSHJ P,QTULK ;TUT ALREADY AOS'ED. + MOVSI T,MMPGON + TDNE T,(B) + JRST [ MOVSI T,MMPTMP ;MMP ENTRY GOING AWAY. + TDNE T,(B) ;IF DISK TRANSFER ALSO IN PROGRESS, + JRST NCRMMW ; GO WAIT FOR THINGS TO SETTLE WITH CIRPSW FREE. + PUSH P,A + PUSHJ P,RETMM4 ;CLEAR PENDING FREEAGE + POP P,A + JRST NCORQB ] ;AND TRY AGAIN + MOVEI C,-1 + HRRZ T,(B) ;GET CIRC PNTR OUT OF MMP ENTRY. + CAIL T,600000 ;SKIP IF DOESN'T POINT TO MEMORY + TDNE C,MMSWP-600000(T) ;SKIP IF IT'S A LOOSE PAGE + JRST NCORQ8 + HRRZ C,MEMPNT-600000(T) + CAIE C,400000(R) ;SKIP IF NO USERS IN CIRCULAR LIST + JRST NCORQ8 ;NOT REALLY LOOSE, USERS LINKED BUT NOT CONNECTED + MOVEI C,0 ;REMOVE FROM LOOSE PAGE LIST + MOVE W,FLOOSP +NCORQ3: MOVE TT,C ;TT PREDECESSOR + SKIPN C,W ;W SUCCESSOR + JRST 4,. ;NOT IN LOOSE PAGE LIST? + LDB W,[MLO,,MEMBLT(C)] + CAIE C,-600000(T) + JRST NCORQ3 + SKIPE TT + DPB W,[MLO,,MEMBLT(TT)] + SKIPN TT + MOVEM W,FLOOSP + SKIPN W + MOVEM TT,LLOOSP + SOSL NLOOSP + JRST NCORQ8 + JRST 4,. ;NLOOSP WAS TOO SMALL? + +NCORQ6: SOSGE MMPFR ;NEED TO CREATE NEW MMP ENTRY; COMMIT ONE + JRST [ AOS MMPFR ;MMP FULL + JRST POPTTJ ] ;TAKE ERROR RETURN + PUSHJ P,GMMPP ;GET FREE MMP ENTRY (CAN'T PCLSR AFTER THIS SUCCEEDS) + JRST NCORQW ;WAIT FOR MORE MEM + PUSHJ P,QTAOS1 ;AOS TUT FOR BLOCK (TUT ALREADY LOCKED) + HRLZM W,1(TT) ;STORE DISK ADR + MOVE D,R + IOR D,[MMPOUT+MMPWOD,,400000] ;SWAPPED OUT, MMP POINTING TO SELF + DPB I,[$MMPUN,,D] + MOVE C,(P) ;A + TRNE C,%CBCPY + TLCA D,MMPWOD+MMPISW ;COPYING, SO SET INITIAL-SWAPIN + JRST [ MOVE B,W ;NO COPYING, SO + IDIVI B,SHRHSL ;STICK INTO SHAREABLE-PAGE HASH TABLE + MOVE B,SHRHSH(C) + HRRM B,1(TT) + HRRZM TT,SHRHSH(C) + TLO D,MMPSHR ;FLAG MMP ENTRY AS IN SHRHSH TABLE + JRST .+1 ] + MOVEM D,(TT) + HRRZ B,TT + AOS NPGSWO +NCORQ8: MOVE T,[300,,[3]] + HRLI B,2200 + AOS -1(P) ;SUCCESS RETURN + JRST POPTTJ + +NCORA: MOVEI A,(C) + MOVE U,TT ;INSERT ABS PAGE. + PUSHJ P,UPLC ;FIND TARGET PAGE + IOR B,(P) ;COMBINE ACCESS W/ PAGE NUM. + TRZ B,PMAGEM\PMUNSD\PMCSHM +IFE KA10P,[ + TRNE B,PMRCM ;PAGE 0 NOT CACHED + IORI B,PMCSHM +] + LDB D,T + TRZ D,PMAGEM ;TURN OFF REMNANT AGE BITS + JUMPN D,[JRST 4,.] ;SHOULD HAVE DELETED PAGE ALREADY + DPB B,T + MOVNI B,1 ;CIRC. PTR. IS -1. + DPB B,Q + MOVEI E,(A) + JRST NCORR2 + + ;VIRTUAL PUSHJ AT NCORQ2 +NCORR3: JRST [ SUB P,[5,,5] ;MMP WAS FULL + JRST OPNL37 ] + POP P,R ;COME HERE FOR DSK PG, AFTER FINDING MMP. + MOVE C,QRADAD(A) ;MOVE ACCESS POINTER OF FILE TO + IDIVI C,@QSBYTE(A) ;NEXT PAGE BOUNDARY, BEING CAREFUL + IORI C,1777 ;ABOUT BYTES. + AOS C + IMULI C,@QSBYTE(A) ;NEXT USE OF FILE WILL GET + MOVEM C,QRADAD(A) ;WHAT FOLLOWS PAGES MAPPED. + MOVSI C,%QAACC ;INDICATE ACCESS PTR CHANGED. + IORM C,QSRAC(A) +;COME HERE TO INSERT PG FROM OTHER USER. +NCORR: HRRZ E,-3(P) ;TARGET PAGE # C + HRRZ U,-1(P) ;TARGET JOB TT + HRRZ TT,(P) ;ACCESS (WRITE BIT IN 2.9) + PUSHJ P,NCORR1 ;ACTUALLY MUNG MAP. +NCORR2: PUSHJ P,GHUSRA ;TARGET PAGE NUM MUST BE IN E + POP P,A + POP P,TT +NCORA1: POP P,E + POP P,C +;COME HERE AFTER HANDLING 1 PAGE. +NCORX: MOVE U,USER + CLRPGM (U) + JUMPGE C,NCORX1 ;IF LH POS, DON'T REWRITE. + ADD C,[1,,1] + ADDI E,1 + UMOVEM C,@SRN3(U) + SKIPL SRN4(U) ;REWRITE 5TH ARG ONLY IF WAS GIVEN. + UMOVEM E,@SRN4(U) + JUMPGE C,NCORX1 + TLNN A,%CBRED + JRST NCORD ;LOOP AROUND FOR DELETE RQ + JRST NCORL ;FOR INSERT RQ. + +NCORX1: AOS (P) +NCORX0: PUSHJ P,LSWPOP ;FREE CIRPSW +NCORX2: CAIN TT,(U) ;IF NOT ACTING ON SELF, + POPJ P, + JRST LSWPOP ;CAN'T FALL THRU SINCE MIGHT BE NULSET. + +;THIS IS A LOSSET ROUTINE TO CLEAR THE BSSTP BIT OF THE JOB +;WHOSE INDEX IS IN THE SRN5 OF THE RUNNING JOB. +NCORFS: MOVE A,SRN5(U) + MOVSI T,BSSTP + ANDCAM T,USTP(A) + POPJ P, + ;JSP T,NCORUI WITH JOB-SPEC IN J, RETURNS USER IDX IN J (OR ,,-1 FOR PDP6) + +;JOB SPECS ARE: +; -1 OR ,,-1 FOR SELF. +; (MUST BE USR, STY, JOB OR BOJ DEVICE ELSE OPNL34) +; 400000+ JOB WITH THAT NUMBER (OPNL35 IF NONE) +; ( -1,, ALSO WORKS) +;IF THIS JOB IS CERTAINLY ALLOWED TO MODIFY SPEC'D JOB, DOESN'T SKIP. +;IF SKIPS ONCE, MUST CHECK FARTHER. IN EITHER CASE, DIELOK OF JOB HAS BEEN AOS'D +;AND SOSSET'ED, UNLESS ENTRY POINT WAS NCRUI2, OR JOB IS PDP6. +;2 SKIPS => ARG IS RANDOM I-O CHANNEL; CLSTB ENTRY IN H. +;IN THAT CASE, NO SOSSET WAS DONE. RANDOM CHANNELS ALLOWED ONLY IF ENTRY POINT IS NCRUI1. + +NCRUI2: HRLI T,200000 ;ENTRY TO SUPPRESS AOS'ING OF DIELOK, AND SOSSET'ING. + JRST NCRUI3 + +NCRUI1: TLOA T,400000 ;ENTRY FOR RANDOM CHNLS OK (SKIP TWICE IF SO) +NCORUI: TLZ T,400000 ;RANDOM DEVS NOT OK + TLZ T,200000 +NCRUI3: TRZE J,400000 + HRLI J,-1 + JUMPL J,NCORU1 + CAIL J,NIOCHN ;>0 => CHNL NUM. + JRST OPNL14 + ADDI J,IOCHNM(U) + MOVE H,(J) + HLRZ J,H + SKIPGE H,CLSTB(H) + JRST NCORU4 ;IF INFERIOR, CAN WRITE. + TLNE H,%CLSBJ ;OR IF BOJ DEVICE + JRST [HRRZ J,JBCUI(J) ? JRST NCORU4] + TLNE H,%CLSST ;STY => USE JOB THAT HAS ASSOCIATED TTY. + JRST [ SKIPGE J,TTYSTS(J) + JRST OPNL41 ;NO JOB HAS THAT TTY. + ANDI J,-1 + JRST NCORU4] + TLNE H,%CLSFU ;FOREIGN USR, MUST CHECK. + AOJA T,NCORU4 +IFN PDP6P,[ + TLNN H,%CLS6 + JRST NCORU5 ;RANDOM DEVICE. (MAYBE DISK) +NCRUI6: MOVEI J,-1 ;PDP6, MUST CHECK. + JRST 1(T) +];PDP6P +NCORU5: JUMPL T,2(T) ;RANDOM DEVICE, SKIP TWICE IF THATS OK + JRST OPNL34 + +NCORU1: TRNE J,777400 ;CHECK FOR -1 FOR SELF. + JRST NCORU2 + ANDI J,377 + CAIN J,377 ;CHECK FOR 377 => SUPERIOR. + JRST NCORU3 +IFN PDP6P,[ ;AND FOR 376 => PDP6. + CAIN J,376 + JRST NCRUI6 +] + IMULI J,LUBLK ;ELSE WAS USRNUM, + CAMGE J,USRHI ;CHECK FOR VALID USER + SKIPN UNAME(J) + JRST OPNL35 ;IF NOT, NO SUCH JOB. + AOJA T,NCORU4 + +NCORU2: CAME J,[-1,,377777] + JRST OPNL33 + MOVEI J,(U) +NCORU4: CONO PI,CLKOFF + MOVE H,APRC(J) ;IS THE JOB WE'RE HACKING DIEING? + TLNE H,BULGOS + JRST OPNL42 ;YES, PREVENT TIMING ERRORS. + TLNE T,200000 ;UNLESS ENTRY POINT WAS NCRUI2, + JRST NCORU6 + AOS DIELOK(J) ;PREVENT THE JOB FROM DIEING. + PUSH P,T + PUSHJ P,SOSSET + DIELOK(J) + POP P,T +NCORU6: CONO PI,CLKON + JRST (T) + +NCORU3: SKIPGE J,SUPPRO(U) ;GET SUPERIOR, + JRST OPNL35 + MOVEI J,(J) + AOJA T,NCORU4 + +;SKIP IF ALLOWED WRITE ACCESS TO PAGES FROM SOURCE IN J +;USE IF NCORUI ETC. SKIPS ONCE. CALL BY JSP T,. + +NCORW1: +IFN PDP6P,[ + CAIN J,-1 ;IF IT GETS THIS FAR, USER HAS A PDP6 CHANNEL, + JRST 1(T) ; THEREFORE OBVIOUSLY IS ALLOWED TO WRITE PDP6 MEMORY. +];PDP6P + CAIE J,LUBLK ;CAN GET WRITE ACCESS TO FRESH PAGE, +;SKIP IF ALLOWED TO MODIFY PAGE MAP OF TARGET JOB IN J. +NCORWR: CAIN J,(U) ;CAN DO THAT AND STICK PAGE IN SELF + JRST 1(T) + HRRZ H,SUPPRO(J) + CAIE U,(H) ;AND OUR INFERIORS + CAMN U,SERVER(J) ; and anyone who thinks we are a server + JRST 1(T) + SKIPL H,JBI(U) ;AND OUR BOJ DEVICE. + CAIE J,JBCUI(H) + JRST (T) + JRST 1(T) + +;.CBLK AC, +;(OBSOLESCENT) + ;AC 4.9 MUST BE ZERO + ;4.7 USED INTERNALLY IN CODE (W RQ ON PDP6) + ;4.3-4.1 = 0 GET PAGE FROM SELF + ; = 1 GET ABSOLUTE PAGE + ; = 2 GET PAGE FROM USER OPEN ON CH # 3.1-3.8 + ; = 3 GET PAGE FROM USER NUMBER 3.1-3.8 + ; = 4 GET PAGE + ; = 5 GET PAGE (PUBLIC) + ; = 6 MAKE PAGE PRIVATE + ; = 7 MAKE PAGE PUBLIC + ;3.9=1 REQUEST WRITE PERMISSION (IGNORED ON FRESH PAGE, OTHERWISE VALID ONLY FOR + ; SELF OR DIRECT INFERIOR OPEN ON CH OR PUBLIC PAGE) + ;3.1-3.8 USER NUMBER OR CH # (377 => CREATOR IF JOB DEVICE) + ;2.9=1 INSERT PAGE, 0 DELETE (IGNORES 4.3-4.1 EXCEPT FOR 6 OR 7 WHEN IT IS IGNORED) + ;2.1-2.8 VIRTUAL PAGE TO BE AFFECTED + ;1.1-1.9 BLOCK # IN ABSOLUTE OR OTHER USER (OR SELF IF 4.3-4.1 = 0) + +;TO CALL NCBLK, SET UP Q WITH USER INDEX REQUEST IS FOR AND U WITH +;THE USER INDEX MAKING THE REQUEST + +;NEW .CBLK CODE, PASSES THE BUCK TO CORBLK. +;SAME AS FAR AS CALLER IS CONCERNED. + +ACBLK: MOVE TT,U ;TARGET USR IDX. + UMOVE B,(J) +NCBLK0: MOVEI W,5 ;FAKE 5 ARGS TO NCORBL + LDB C,[111000,,B] ;TARGET PAGNUM. + LDB E,[1100,,B] ;SOURCE PAGNUM. + TRNN B,400000 + JRST NCBLKD ;LIKELY TO BE DELETE RQ. +NCBLK1: MOVSI A,210000 ;NOT DELETE => RQ READ, FAIL IF CAN'T. + LDB D,[221000,,B] ;SOURCE USR IDX OR CHNL NUM. + LDB H,[330300,,B] ;REQUEST TYPE-CODE. + JRST .+1(H) + + JRST NCBLKS ;TYPE 0, SOURCE IS SELF. + JRST NCBLKA ;TYPE 1, GET ABS PAGE. + JRST NCBLKC ;2, USE SPEC'D CHNL NUM. + JRST NCBLKI ;3, USE SPEC'D USR IDX. + JRST NCBLKF ;4, FRESH PAGE. + JRST NCBLKP ;5, FRESH PUBLIC PAGE. + TLOA A,420000 ;6, MAKE PRIVATE, SOURCE=TARGET. + TLO A,440000 ;7, MAKE PUBLIC, " " + MOVE E,C ;SOURCE PAGNUM _ TARGET PAGNUM, +NCBLKS: TROA D,-1 ;GET PAGE FROM SELF. (%JSELF=-1) +NCBLKA: MOVEI D,%JSABS ;GET ABS PAGE +;IF GET-FROM-CHANNEL, THE CHNL NUM IN D IS DESIRED JOB-SPEC. +NCBLKC: TLNE B,400 ;IF WRITE-RQ BIT ON, + TLO A,100000 ;INSIST ON WRITE ACCESS. +NCORBX: CAIE TT,(U) ;IF TARGET .NE. SELF, + PUSHJ P,NULSET ;FAKE OUT THOSE EXPECTING A LOSSET. + JRST NCORB9 + +NCBLKI: IORI D,%JSNUM ;GET FROM USR IDX, MAKE JOB SPEC. + JRST NCBLKC + +NCBLKP: TLO A,40000 ;GET FRESH PUBLIC PAGE. +NCBLKF: MOVEI D,%JSNEW ;GET FRESH PAGE + JRST NCBLKC + +NCBLKD: TLC B,6000 ;COME HERE IF BIT 2.9 IS 0 + TLCN B,6000 + JRST NCBLK1 ;(TYPES 6,7 IGNORE THAT BIT) + SETZB A,B ;OTHERWISE IS DELETE REQUEST. + JRST NCBLKS + +NCBLK: MOVE B,TT + MOVE TT,Q + JRST NCBLK0 + +;ACTUALLY COPY A PAGE FROM ONE MAP TO ANOTHER +;T PNTR TO MAP COPYING FROM +;TT 400000 BIT 1=> WRITE +;E TARGET PAGE # +;U TARGET USER +;B PNTR TO CIRC LIST + +NCORR1: LDB J,T ;ENTRY FROM NCORR + TRNN J,600000 + JRST ACBK3A ;PAGE NON EXISTANT OR SWAPPED OUT + TRNN TT,400000 ;WRITE RQ ? + TRZ J,400000 ;DOESN'T RQ MORE + TRNN J,600000 + TRO J,200000 ;IN CASE OF RWF +ACBK3B: MOVE A,E ;TARGET PAGE # + PUSHJ P,UPLC + LDB C,T ;GET PTW ABOUT TO BE CLOBBERED + TRZ C,PMAGEM ;TURN OFF AGE BITS + JUMPN C,[JRST 4,.] ;SHOULD HAVE DELETED PAGE BY NOW + DPB J,T ;SET UP MAP + TRNN J,600000 + JRST ACBK3C ;JUMP IF PAGE SWAPPED OUT + ANDI J,PMRCM + CAIL J,TSYSM + JRST 4,. +IFE SWPWSP, AOS MMSWP(J) ;AOS NUMBER OF USERS POINTING TO PAGE +IFN SWPWSP,[ + HRRZ TT,MMSWP(J) + AOS MMSWP(J) ;AOS NUMBER OF USERS POINTING TO PAGE + MOVSI C,1 ;ADJUST WORKING SET OF TARGET JOB + IDIV C,TT ;1,,0 IF DIVISION BY ZERO + ADDM C,UWRKST(U) + JUMPE TT,ACBK3D ;JUMP IF NO SHARERS + IMULI TT,1(TT) ;COMPUTE ADJUSTMENT TO ALL WORKING SETS + MOVSI C,-1 ;DUE TO INCREASE IN SHARING + IDIV C,TT + MOVE D,C + PUSH P,U + PUSH P,I + PUSHJ P,UCPRL7 ;CLOBBERS C,H,I,U + 400000,,SWOP6B + POP P,I + POP P,U +];SWPWSP +ACBK3D: LDB J,B ;POINTER TO PREVIOUS IN CHAIN + DPB J,Q ;PATCH + MOVE C,U + IDIVI C,LUBLK + DPB C,[101000,,A] + DPB A,B ;PATCH + AOS NMPGS(U) + AOS SNMPGS ;SYSTEM HAS 1 MORE PAGE + POPJ P, + +ACBK3A: TRNN TT,400000 + TRZ J,2 + TRO J,1 ;IN CASE OF R/W/F + JRST ACBK3B + +ACBK3C: AOS NSWPGS(U) + AOS SNSWPG + JRST ACBK3D + ACRF1: MOVE TT,B + MOVE W,Q ;INDEX OF USER THAT REQUEST IS FOR + IDIVI W,LUBLK ;CLOBBERS H + HRL TT,W + TLNE TT,600000 + JRST 4,. + JRST ACRFL + +NACRFL: PUSHJ P,LSWPOP ;UNLOCK CASW OR CIRPSW +ACRFL: PCLT + SKIPL CORRQ(U) ;CURRENT USER IN U COR RQ FOR USER IN Q + PUSHJ P,UFLS ;WAIT FOR MY CORE RQ TO CORE JOB TO CLEAR + MOVSI J,BUSRCR + MOVE T,J + TDNE T,APRC(Q) + PUSHJ P,UFLS ;SOMEBODY ELSE HAS RQ IN ON THIS JOB WAIT TO CLEAR + PUSHJ P,SWTL + CASW ;GET CORE ASSIGN SW + TDNE J,APRC(Q) + JRST NACRFL ;CHECK FOR TIMING ERROR + TLNN TT,200000 + JRST ACRF6 ;OLD TYPE + MOVNI J,1 ;ADDING ONE BLOCK + MOVEI B,105 ;FAKE OUT CORE TO ZERO CHECK + JRST ACRF8 + +ACRF6: MOVE J,HUSRAD(Q) + LSH J,-10. + CAMN J,B + JRST LSWPJ1 ;SAME AMOUNT AS NOW + MOVE T,APRC(Q) + TLNE T,BULGOS + JUMPN B,LSWPOP ;TRYING TO CORE NON-ZERO A JOB THAT IS DYING? + SUB J,B ;GET AMT OF DECREASE (- => INCREASE) + CAMGE J,[-20.] + JRST ACRF6A ;GET 20 AT A WHACK MAX +ACRF8: MOVN I,J ;I GETS POSITIVE # OF PAGES ADDED + ADD J,MEMFR + SUB J,NCBCOM ;J GETS AMT THAT WILL BE LEFT + CAIGE J,5 + JUMPG I,ACRF7 ;NOT ENUF CORE + MOVEI J,0 ;INDICATE RQ WILL BE COMPLETELY SATISFIED + CAIL I,20. + MOVNI J,1 ;MAKE SURE RQ IS REALLY FILLED +ACRF5: JUMPL I,ACRF2 ;JUMP IF DECREASING CORE + JUMPE Q,ACRF3 ;SYSTEM JOB DOESN'T USE MMP + MOVN T,I + ADDB T,MMPFR ;COMMIT SUFFICIENT NUMBER OF MMP ENTRIES + JUMPGE T,ACRF3 ;JUMP IF THAT MANY ARE AVAILABLE + ADDM I,MMPFR ;MMP FULL, DECOMMIT THE MMP ENTRIES + JRST LSWPOP ;AND TAKE ERROR RETURN + +ACRF2: AOSA NCRQL ;COUNT # REQUESTS FOR LESS +ACRF3: ADDM I,NCBCOM ;IF EXPANDING, COMMIT SUFFICIENT AMOUNT OF PHYSICAL CORE + MOVSI T,BUSRCR + IORM T,APRC(Q) ;CORING USER + MOVEM TT,CORRQ(U) + AOS NCORRQ + PUSHJ P,LSWPOP ;UNLOCK +IFN SCHBLN,[ + CONO PI,CLKOFF ;GET CORE JOB TO RUN RIGHT AWAY + MOVE I,USER ;THEN COME RIGHT BACK TO US (WHAT A CROCK THIS ALL IS) + PUSHJ P,SCHSB + MOVEI I,LUBLK + PUSHJ P,SCHSB + CONO PI,CLKON +];SCHBLN + PCLT + SKIPL CORRQ(U) ;WILL NOT SKIP AT FIRST + PUSHJ P,UFLS + JUMPN J,ACRF1 ;REALLY NEED TO TAKE ANOTHER WACK AT THIS + JRST POPJ1 + +ACRF7: PUSHJ P,LSWPOP + PCLT + MOVE T,I + PUSHJ P,CFHPO3 + PUSHJ P,UFLS + TLNE TT,200000 + JRST ACRFL + JRST ACRF1 + +ACRF6A: ADDI J,20. + ADD TT,J ;GET REDUCED RQ + MOVNI J,20. + JRST ACRF8 + +SUBTTL CORE ALLOCATOR - CORE JOB ROUTINES + +CORJI: MOVE P,USRPDL+L ;SET UP CORE JOB PDL + JRST CORJOB + +CORJ2: AOSN UTBFLF + JRST UTBFF ;FLUSH UTAPE + AOSN UFDFLF + JRST UFDFF ;FLUSH 2314 UFDS + SKIPE MMPFS2 + JRST RETMM2 ;FLUSH PARTIALLY-RETURNED MMP ENTRIES + SKIPE QFBTS + JRST [ PUSHJ P,QDLFBT ;RETURN DISK BLOCKS TO FREE + SOS NCORRQ + JRST CORJOB ] + SKIPE NCRQL + JRST CORJOB ;RQ'S FOR LESS HAVE COME IN. BETTER EXECUTE THEM OR MAY NOT HAVE ENUF CORE + SKIPL CORUPU + JRST CORUP ;FOUND USER IN SEARCH WHO WANTS MORE GIVE IT TO HIM + SKIPL CORSRV + JRST CORJOB + MOVE A,LMEMFR + CAMGE A,MINCOR + PUSHJ P,CFLM1 ;FREE SOME LOW MEMORY BY SHUFFLING + SKIPLE NCORRQ + SOS NCORRQ ;CAN'T FIND ANYTHING TO DO SO DECREMENT COUNT + ;THIS CAN HAPPEN AS A RESULT OF EXCESS ATTEMPTED UTAPE FLUSHAGE + ;OR DUE TO CALLING CFLM1 +CORJOB: PUSHJ P,ACMTC ;XFER ANY "SPECIAL FREE" MEM BLOCKS TO FREE + SKIPN NCORRQ ;ANYONE WANT CORE? + PUSHJ P,[ ;IF NOT, WAIT UNTIL SOMEONE DOES, BUT FIRST + MOVE TT,QMDRO ;SEE IF MFD AND TUTS NEED TO BE READ IN + AOJE TT,IDSK + JRST UFLS ] ;WAIT + SETOM CORSRV ;INITIALIZE NO RQS SERVED THIS PASS + SETOM CORUPU + MOVNI U,LUBLK ;SCAN FOR USER WITH HIGHEST PRIORITY +CORLUP: ADDI U,LUBLK + CAML U,USRHI + JRST CORJ2 ;THRU EXAMINE RESULTS OF SEARCH + SKIPGE B,CORRQ(U) + JRST CORLUP + TLNE B,200000 + JRST CORNEW + LDB Q,[221000,,B] + IMULI Q,LUBLK + MOVE A,HUSRAD(Q) + LSH A,-10. ;COMPUTE # BLKS JOB HAS NOW + CAIN A,(B) + JRST 4,CORL1 ;SAME AS NOW, CHECKED FOR AT ACORE + CAIG A,(B) + JRST CORLUG ;INCREASE + MOVEM U,CORUPU ;DECREASE HAS PRIORITY + HRRZS B + SUB B,A + MOVEM A,CORUPS + MOVEM B,CORUPA ;DIFFERENCE + MOVEM Q,CORUUC + JRST CORUP + +CUSTOP: PUSHJ P,RPCLSR ;STOP USER WHO IS BEING CORED + MOVSI T,BUCSTP ;(THE BUCK STOPS HERE) + IORM T,USTP(A) + PUSHJ P,UPCLSR + MOVEI T,-1 ;GET MASK FOR RH + TDNE T,USTP(A) ;WAIT FOR RANDOM STOPS TO CLEAR + PUSHJ P,UFLS + POPJ P, + +;Core job initializes disks while system job stands around and supervises +;This makes it possible for system job to print any resulting error messages +;Provided no one hits ^Z too soon +IDSK: MOVE I,MDSK + MOVE U,USER + PUSHJ P,QMCH1 + MOVSI I,-NQS + SKIPL QACT(I) + PUSHJ P,QTCH1 + AOBJN I,.-2 + MOVSI TT,SCLIDK ;System is up now + IORM TT,SUPCOR + JRST CORJI + +EBLK + +CORUPU: -1 ;BEST USER SO FAR TO CHANGE CORE + ;IF SETOMED AT CORUPR, REQUEST NOT COMPLETELY FILLED +CORUPA: 0 ;INCREASE AMOUNT(1 FOR .CBLK) +CORUPS: 0 ;CURRENT SIZE +CORUUC: 0 ;USER CORE REQ ACTUALLY FOR +CORSRV: -1 ;0 => RQ SRVED THIS TIME THRU USER VARS +NCRQL: 0 ;# RQS FOR LESS + +BBLK + +CORLUG: HRRZS B ;GUY WANTS MORE GIVE GUY WHO WANTS LEAST PRIORITY + SUB B,A +CORLUH: MOVE A,NMPGS(Q) + SKIPGE CORUPU + JRST CORLG1 ;FIRST + CAMGE B,CORUPA ;IS RQ SMALLER? + JRST CORLG1 +CORLG2: CAME B,CORUPA ;OR IF TIE GIVE IT TO GUY WHO IS SMALLER NOW + JRST CORG1A + CAML A,CORUPS ;IS RQ= & SIZE SMALLER? + JRST CORG1A +CORLG1: MOVEM U,CORUPU ;HIGHEST PRIORITY SO FAR + MOVEM B,CORUPA + MOVEM A,CORUPS + MOVEM Q,CORUUC +CORG1A: JRST CORLUP + +CORNEW: LDB Q,[1100,,B] ;.CBLK TYPE RQ + IMULI Q,LUBLK + MOVEI B,1 + JRST CORLUH + +CORUP: ;EXECUTE REQUEST + MOVE U,CORUUC + MOVEM U,CUSER + SKIPL D,CORUPU + SKIPN UNAME(U) + JRST 4,. + MOVE A,CORUUC + JUMPE A,CORUP8 ;DONT USTOP SYS JOB + PUSHJ P,CUSTOP ;STOP GUY +CORUP8: PUSHJ P,SWTL + CIRPSW + MOVE TT,CORRQ(D) + TLNE TT,200000 + JRST CORUPN ;.CBLK TYPE + MOVE B,CORUPS + MOVE A,B ;A HAS CURRENT SIZE + ADD B,CORUPA ;B HAS NEW SIZE + PUSHJ P,SWTL + MEMFRZ + SKIPL J,CORUPA + JRST CORM1C ;WANTS MORE THAN NOW +CORL2: LDB A,[121100,,HUSRAD(U)] + CAMG A,B + JRST CORUPR + SOS A + PUSH P,B + PUSHJ P,UPGRTN ;RETURN USER PG + POP P,B + JRST CORL2 + +CORUPR: MOVE U,CUSER ;FINISHED FOR NOW ANYWAY REVIVE USER + SKIPN UNAME(U) + JRST 4,. +IFN E.SP,[ + CAMN U,DISUSR + PUSHJ P,E.SLPM ;LOAD PAGE MAP +] +IFN 340P,[ + CAMN U,DISUSR + PUSHJ P,DCRRST ;DIS IS RUNNING BUT UPDATE UPR ETC +] + MOVSI A,BUCSTP + ANDCAM A,USTP(U) ;RESTART USER + PUSHJ P,LSWPOP ;UNLOCK MEMORY + PUSHJ P,LSWPOP + PUSHJ P,ACMTC ;XFER IN PROCESS BLOCKS TO FREE + SKIPGE U,CORUPU + JRST CORJOB ;NOT THRU WITH THIS RQ + MOVE A,CORUUC ;THRU WITH RQ + SETOM CORUPU + SKIPGE CORUPA + SOS NCRQL ;FINISHED A REQUEST FOR LESS, DECREMENT COUNT OF THEM + MOVSI TT,BUSRCR + ANDCAM TT,APRC(A) ;CLEAR RQ PENDING THIS USER FLAG +CORL1: SETOM CORRQ(U) + CLEARM CORSRV + SOSE NCORRQ + JRST CORLUP + JRST CORJOB + +CORUPN: LDB A,[111000,,TT] + PUSHJ P,SWTL + MEMFRZ + PUSH P,A + PUSHJ P,UPGRTN + POP P,E + TLNE TT,4000 + TRNN TT,400000 + JRST 4,. + TLO E,600000+PMCSHM ;ADD FRESH PAGE + PUSH P,TT + PUSHJ P,CORGP + POP P,TT + LDB A,[111000,,TT] + PUSHJ P,UPLC + LDB B,T + TRNN B,400000 + JRST 4,. ;LOSEY + MOVE C,Q + PUSHJ P,UCPRL + 200000,,[ LDB B,[330100,,TT] + DPB B,[430100,,(C)] + POPJ P, ] ;SET TO DESIRED PUBLICNESS + SOS NCBCOM + JRST CORUPR + +CORM1C: MOVEM J,CORCNT +CORM1A: JUMPE U,CORS2 ;SNIFFLE +CORM1B: MOVE U,CORUUC + LDB E,[121100,,HUSRAD(U)] + TLO E,600000+PMCSHM + PUSHJ P,CORGP + SOS NCBCOM + SOSLE CORCNT + JRST CORM1A + JRST CORUPR + + ;INSERT FRESH PAGE INTO USR MEM IN PLACE SPECIFIED BY E PROT BITS IN LH +;MMPFR SHOULD HAVE BEEN SOS'ED ALREADY + +CORGP: JUMPN U,CORGP0 ;JUMP UNLESS GIVING PAGE TO SYS JOB + MOVE A,SJSPG ;GOBBLE PAGE RESERVED + SETZM MEMBLT(A) + CAIL A,SYSB + JRST CORGP1 ;USER VARIABLES, CLEAR IT OUT + JRST CORGP2 ;INITIAL GET OF SYSTEM, DON'T ZERO IT + +CORGP0: PUSHJ P,GMMPP ;RETN MMP PNTR IN R + JRST CORGPZ + PUSHJ P,TCALL + JRST HMEMRQ ;GET MEM, HIGH IF POSSIBLE + JRST 4,. +CORGP1: PUSHJ P,CZRR +CORGP2: AOS NMPGS(U) + AOS SNMPGS ;INCR SYS PAGE COUNT (VIRT) + PUSH P,A ;REAL CORE BLOCK # + HRRZ A,E ;ADDR IN USERS MAP + PUSHJ P,UPLC + POP P,A + LDB B,Q + SETZM MMSWP(A) + JUMPE U,CORGP3 ;IF SYS JOB, DON'T TRY TO SET UP MAP + JUMPN B,[JRST 4,.] ;ALREADY HAS PAGE + AOS MMSWP(A) ;INDICATE THAT ONE USER MAP POINTS AT THIS PAGE + TSO A,E ;SET PROTECTION BITS + DPB A,T ;STORE IN USER'S MAP + MOVE C,R ;MMP IDX + TRO R,400000 ;MAKE USERS CP POINT AT MMP + DPB R,Q +IFN SWPWSP,[ + MOVSI TT,1 ;INCREASE WORKING SET + ADDM TT,UWRKST(U) +];SWPWSP + ANDI A,PMRCM ;TURN ACCESS BITS BACK OFF +CORGP3: CAIL A,TSYSM + JRST 4,. + MOVEI TT,MURUSR + DPB TT,[MUR,,MEMBLT(A)] ;SET USER FIELD IN MEMBLT + MOVE TT,U + IDIVI TT,LUBLK + LSH TT,8 + IOR TT,E ;PG # IN USER'S MAP + SKIPN U + MOVEI TT,600000(A) ;IF SYS JOB, MEM BLOCK POINTS AT SELF + HRRZM TT,MEMPNT(A) ;ELSE MAKE MEM BLOCK POINT AT USERS MAP + JUMPE U,GHUSRA ;IF SYS JOB, NO MMP ENTRY + DPB C,[MMMPX,,MEMBLT(A)];STORE INDEX OF MMP ENTRY IN MEMBLT + TRO A,600000 + HRRM A,MMP(C) ;MAKE MMP POINT AT MEM BLOCK + PUSHJ P,CHACK ;FOR CHECKING ONLY + CAME C,[SETZ 3] ;REAL MEM, 3 ENTRIES (MMP, MEMPNT, USER) + JRST 4,. +GHUSRA: AOS E + LSH E,10. ;COMP NEW HUSRAD AFTER GETTING PAGE + TLZ E,-2 ;FLUSH PROTECT BITS (LEAVE 3.1) + CAMLE E,HUSRAD(U) + MOVEM E,HUSRAD(U) + POPJ P, + +CORGPZ: PUSH P,E ;SAVE REGISTERS + PUSH P,U + PUSHJ P,CFLM2 ;TRY TO FREE UP SOME LOW MEMORY + POP P,U + POP P,E + SKIPE LMEMFR + JRST CORGP ;SHOULD WORK NOW + PUSHJ P,LSWPOP ;MEMFRZ + PUSHJ P,LSWPOP ;CIRPSW + BUG INFO,[NO CORE AVAIL FOR MMP PAGE] + PUSHJ P,UDELAY ;Break possible infinite loop if no user pgs in low mem + SKIPG MEMFR ;WAIT FOR SWAPPER TO MAKE ROOM (PANIC!) + PUSHJ P,UFLS + PUSHJ P,SWTL + CIRPSW + PUSHJ P,SWTL + MEMFRZ + JRST CORGP + +PAGERT: PUSHJ P,SWTL + MEMFRZ + PUSHJ P,UPGRTN + JRST LSWPOP + +UPGRTN: PUSH P,R ;RETURN VIRT PG # IN A USER IN U + PUSH P,I + PUSH P,TT + PUSH P,E +IFN XGP,[ + PUSHJ P,UPLC ;SEE IF PAGE XGP LOCKED + LDB E,T + TRNN E,600000 + JRST UPGRT7 ;SWAPPED OUT, OBVIOUSLY NOT XGP + ANDI E,PMRCM ;E := PHYS PAGE NO + CAIL E,TSYSM + JRST UPGRT7 + IDIVI E,36. + MOVNS TT + PUSH P,T + MOVSI T,400000 + LSH T,(TT) + TDNE T,XGPMTB(E) + PUSHJ P,UFLS ;WAIT FOR XGP TO CLEAR + POP P,T +UPGRT7: ] +.ELSE PUSHJ P,UPLC ;FIND PAGE IF DIDN'T ALREADY + JUMPE U,UPGRT8 ;SYS JOB, NO SWAPPING NOR MMP ENTRY + LDB B,Q + CAIN B,-1 + JRST UPRABS ;ABSOLUTE PAGE + JUMPE B,RHUSRA ;DOESNT REALLY HAVE PG + PUSH P,T + PUSHJ P,CHACK + ADD D,MMPEAD ;D HAS MMP ADDRESS +UPGRTA: MOVSI T,MMPTMP + TDNE T,(D) + JRST UPGRTW ;WAIT FOR PAGE TO TRANSIT BUT UNLOCK SWITCHES + MOVNI I,1 ;ASSUME NO DISK SPACE + HLRZ A,1(D) ;SEE IF DISK SPACE ASSIGNED + JUMPE A,UPGRT5 + LDB I,[$MMPUN,,(D)] + PUSHJ P,QTLOCK ;LOCK APPRO TUT +UPGRT5: POP P,T ;POINTER TO ORIG MAP ENTRY OF USER + MOVE H,(T) ;SAVE MAP WORD FOR DEBUGGING + LDB TT,T ;IF PROT BITS=0 PAGE IS SWAPPED OUT FOR PURPOSES + MOVEI E,0 ;OF USER'S SWAP OUT COUNT, EVEN IF IN CORE + DPB E,T ;CLEAR USER MAP ENTRY + TRCN TT,600000 ;IS USER MAPPED TO PAGE? + JRST UPGRT9 + MOVSI E,MMPWRT ;YES, CHECK IF ACCESS BITS = RW + TRNN TT,600000 + IORM E,(D) ;PAGE WRITTEN BY USER WHO HAS DETACHED IT + ANDI TT,PMRCM ;MASK TO MEM PAGE # + CAIE TT,(J) + JRST 4,. ;PTW POINTED TO WRONG PAGE + MOVSI E,MMPOUT+MMPTMP + TDNE E,(D) + JRST 4,. ;PAGE NOT IN, IN MMP +IFE SWPWSP, SOS MMSWP(J) ;ONE LESS USER POINTING AT PAGE +IFN SWPWSP,[ + HRRZ E,MMSWP(TT) ;DECREASE THIS USER'S WORKING SET + MOVSI T,-1 + IDIVM T,E + ADDM E,UWRKST(U) + SOS MMSWP(TT) + HRRZ E,MMSWP(TT) + JUMPE E,UPGRTB ;JUMP IF NO OTHER SHARERS, FOR SPEED AND NO ZERODIVIDE + PUSH P,C ;ADJUST OTHER SHARER'S WORKING SETS + PUSH P,D + PUSH P,I + PUSH P,U + IMULI E,1(E) + MOVSI D,1 + IDIV D,E + PUSHJ P,UCPRL7 ;CLOBBERS H ALSO C,T,U,I + 400000,,SWOP6F + POP P,U + POP P,I + POP P,D + POP P,C +];SWPWSP + JRST UPGRTB + +;RETURNING A PAGE TO WHICH USER IS NOT CURRENTLY MAPPED (MAY BE IN OR OUT) +UPGRT9: SOS NSWPGS(U) + SOS SNSWPG ;DECR CNT OF SWAPPED OUT FOR SYS + JUMPGE C,UPGRT4 ;NO MEM IN CP S, PAGE REALLY SWAPPED OUT +;RETURNING A PAGE WHICH IS SWAPPED IN +UPGRTB: HLRE E,MMSWP(J) ;GET # EXEC PGS POINTING TO THIS + JUMPL E,[JRST 4,.] ;<0 EXEC PAGES + JUMPE E,UPGRT4 ;NO EXEC PGS POINTING TO THIS + PUSH P,J + MOVE TT,J + MOVSI T,-NEXPGS ;LOOK FOR EXEC PGS SET UP TO PNT + MOVE E,[442200,,EXEUMP] ;TO USER PAGE FLUSHED +UPGRT3: ILDB J,E + TRZN J,600000 + JRST UPGRT2 + ANDI J,PMRCM + CAMN TT,J + JRST UPGRT1 +UPGRT2: AOBJN T,UPGRT3 +IFN E.SP,[ + MOVSI T,-1 + TDNE T,MMSWP(TT) + PUSHJ P,E.SPRT ;SEE IF E&S HAS IT +] +IFN XGP,[ + MOVSI T,-1 + TDNE T,MMSWP(TT) ;FLUSH XGP TIE DOWNS AND RETURN + PUSHJ P,XGPCFL +] + POP P,J +UPGRT4: LDB T,Q ;DELINK CIRC PNTR + DPB T,B + MOVEI T,0 + DPB T,Q ;CLOBBER CIRC P + SOS NMPGS(U) + SOS SNMPGS ;SYSTEM HAS 1 LESS PAGE + CAME C,[SETZ 3] + CAIN C,2 + JRST MMPRTN ;RETURN MMP ENTRY SINCE PAGE NO LONGER IN USE +MMPRT4: MOVE A,J + CAMN C,[SETZ 3] + JRST MMPRT5 ;FLUSH REAL MEM +MMPRT6: SKIPL I + PUSHJ P,QTULK +RHUSRA: POP P,E + POP P,TT + POP P,I + POP P,R +RHUSR1: LDB A,[121100,,HUSRAD(U)] ;COMP HUSRAD AFTER RETURNING PAGE + JUMPE A,CPOPJ + SOS A + PUSHJ P,UPLC + LDB B,Q + JUMPN B,CPOPJ ;FOUND ACTIVE PAGE + MOVNI C,2000 ;KEEP LOOKING + ADDM C,HUSRAD(U) + JRST RHUSR1 + +UPGRT8: SOS NMPGS ;RETURNING PAGE FROM SYS JOB + SOS SNMPGS + DPB A,[121100,,HUSRAD(U)] ;NORMAL METHOD OF COMPUTING HUSRAD WON'T WORK + MOVNI I,1 ;NO DISK SPACE +MMPRT5: SKIPE MMSWP(A) ;MAKE SURE NO ONE (EXEC OR USER) IS POINTING AT PAGE + JRST 4,. + PUSHJ P,CMEMR ;HAS REAL MEM, CIRC LENGTH =3 SO FLUSH MEM + JRST MMPRT6 + +UPRABS: +IFN TEN11P,[ + LDB B,T + LDB E,[.BP B] ;GET MOBY # + CAIE E,T11CPA_-18. + JRST UPRAB1 + ANDI B,377 + PUSHJ P,T11DL ;DELETE PAGE REF TO TEN11 MAP +UPRAB1:] + MOVEI B,0 + DPB B,Q + DPB B,T + JRST RHUSRA + +IFN E.SP,[ +;TT/MMSWP INDEX +E.SPRT: CAME U,DISUSR ;IS HE USING THE DISPLAY? + POPJ P, ;NO, DON'T UNTIE ANYTHING + PUSH P,H + MOVE T,TT ;FOR E.SPCH + PUSHJ P,E.SPCH ;LOOK IN E&S TABLES + SKIPA ;FOUND, INDEX IN H + JRST E.SPR2 ;NOT FOUND, DO NOTHING + MOVSI T,-1 + ADDM T,MMSWP(TT) ;SOS COUNT + SETZM DISSWP(H) ;CLEAR DISPLAY MMSWP TABLE + AOS E.SNUT ;COUNT FOR UNTIES +E.SPR2: POP P,H + POPJ P, +] +UPGRT1: MOVSI J,-1 + XCT EXPFT(T) ;MAYBE XFERR TO ROUTINE TO DO SOMETHING ABOUT THIS + JRST UPGRT6 ;NOT USER CONCERNED ABOUT (THERE HAD BETTER BE ANOTHER) + MOVEI J,0 + DPB J,E ;CLEAR OUT EXEC PAGE ENTRY + MOVE J,USER + CLRPGM (J) +UPGRT6: CONO PI,UTCON + JRST UPGRT2 + +;WAIT FOR PAGE TO TRANSIT, WITH CIRPSW FREE (IN CASE SWAP READ ERROR!) +;COME HERE WITH T/MMPTMP,, D/MMP.ENTRY.ADDR +UPGRTW: MOVE B,D +NCRMMW: MOVE U,USER + PUSHJ P,LSWCLR + PCLT + TDNE T,(B) + PUSHJ P,UFLS ;WAIT FOR ACTIVE PAGE TO SETTLE DOWN + CAIE U,LUBLK ;SKIP IF CORE JOB + JRST UUOTROLL ;AS IF PCLSR'ED OUT OF WAIT FOR PAGE & CAME BACK + SETOM CORUPU ;REQUEST FOR THIS USER NOT SATISFIED + MOVE P,USRPDL+LUBLK ;CLEAN UP AND RE INIT CORE JOB + PUSHJ P,NULSET + PUSHJ P,NULSET + JRST CORUPR + +EXPFT: +IFN 340P, REPEAT 2+N340PB, PUSHJ P,DISACR + REPEAT 2,JFCL ;CORJF, CORJT +IFN VIDP, REPEAT 2,PUSHJ P,SCNACR +IFN TEN11P, JRST 4,. ;TEN-11 CONTROL PAGE + JRST 4,. ;PAREP +IFN ECCMEM, JRST 4,. ;ECCPG +IFN XGP, REPEAT 3,JRST 4,. +IFN N11TYS, REPEAT NTTPG+NTVBP,JRST 4,. +IFN CHAOSP, IFN T11CHP, JRST 4,. + REPEAT NMMP,JRST 4,. ;MMP +IFN .-EXPFT-NEXPGS, .ERR LOSE AT EXPFT + ;CIRCULAR MEM LIST HACKER +;CALL WITH Q CONTAINING BYTE POINTER TO CIRC PNTR IN LIST TO BE HACKED +;THE BYTE POINTER MUST POINT AT A UPGCP ENTRY (RATHER THAN MEMPNT OR MMP) +;OR THIS CODE WILL LOOP FOREVER. +;RETN BYTE PNTR IN B TO GUY WHO PNTS TO THAT PNTR +;COUNT FOR ENTRIES IN C (RH) +; 4.9 C SAYS ACTUAL MEM IN LOOP +;RETN IN D MMP INDEX +;RETURN MEM PAGE IF ANY IN J +;CLOBBERS H,I,W + +CHACK: PUSH P,A + LDB J,Q ;PICK UP STARTING C. P. + SETZM C + MOVNI D,1 + MOVE B,Q +CHACK1: JUMPE B,[JRST 4,.] + AOS C + CAIE J,-1 ;SKIP ON ABS PAGE + TRNE C,776000 + JRST 4,. ;CIRC CHAIN TOO LONG? + TRZE J,400000 + JRST CHACK3 ;MEMPNT OR MMP PNTR + LDB I,[1000,,J] ;PG # + LDB H,[101100,,J] ;USER # + IMULI H,LUBLK + SKIPE UNAME(H) + CAML H,USRHI + JRST 4,. ;POINTER TO NON-EXISTENT USER + MOVEI W,UPGCP(H) + ROT I,-1 + ADDI W,(I) + HRLI W,222200 + SKIPGE I + HRLI W,2200 + CAMN W,Q + JRST CHACK2 ;FOUND ENTRY WHICH PNTS AT ORIGINAL ENTRY + LDB J,W + MOVE B,W + JRST CHACK1 ;KEEP LOOKING + +CHACK2: MOVE J,A + JUMPL D,[JRST 4,.] ;NO MMP ENTRY ? + JRST POPAJ + +CHACK3: TRZE J,200000 + JRST CHACK4 ;ACTUAL CORE + CAML J,MMPMX + JRST 4,. ;GARBAGE POINTER + MOVSI B,2200 ;MMP ENTRY + HRR B,MMPEAD + ADDI B,(J) + JUMPGE D,[JRST 4,.] ;MORE THAN 1 MMP ENTRY + MOVE D,J + LDB J,B + JRST CHACK1 + +CHACK4: TLOE C,400000 + JRST 4,. ;PAGES IS IN TWO PLACES IN CORE + CAIL J,TSYSM + JRST 4,. ;GARBAGE POINTER + MOVE A,J ;SAVE MEMBLT INDEX + MOVSI B,2200 + HRRI B,MEMPNT + ADDI B,(J) + LDB J,B + JRST CHACK1 + +;LOOK UP PAGE IN USER MAP +;USER IN U, VIR PG # IN A +;GET PNTR TO MAP HW IN T, TO CIRC IN Q + +UPLC: SKIPL A + CAIL A,400 + JRST 4,. ;BAD VIRTUAL PAGE NUMBER + PUSH P,A + MOVEI Q,UPGCP(U) + MOVEI T,UPGMP(U) + ROT A,-1 + ADDI T,(A) + HRLI T,222200 + SKIPGE A + HRLI T,2200 + ADDI Q,(A) + HLL Q,T + JRST POPAJ + +;FREE THE MMP ENTRY D POINTS AT, SOSING TUT IF DISK SPACE ASSIGNED. +;I HAS DSK #, C HAS WHAT CHACK RETURNED IN C, A HAS TRACK #. +;TUT MUST BE LOCKED ALREADY. CIRPSW AND MEMFRZ SHOULD BE LOCKED. +;EXIT TO MMPRT4 OR RHUSRA + +MMPRTN: MOVEM C,MMPRTC ;SAVE IN CASE OF BUG HALT LATER + JUMPL I,MMPRT3 ;NO DISK SPACE ASSIGNED + PUSH P,B + LDB B,[$MMPUN,,(D)] + CAME B,I + JRST 4,. ;WRITING WRONG DISK + MOVE H,D ;H SAVES POINTER TO MMP ENTRY + MOVE D,A ;D GETS DISK TRACK NUMBER + PUSHJ P,TUTPNT + CAIGE B,TUTMNY + SOJL B,[JRST 4,.] ;DETECT OVER-SOS + DPB B,D + EXCH D,H ;D GETS MMP PNTR, H GETS TUT BYTE PNTR + JUMPN B,MMPRT2 + MOVE T,QTUTO(I) + CAML A,QSWAPA(T) + AOS QSFT(I) + CAMGE A,QSWAPA(T) + AOS QSFTS(I) +MMPRT2: MOVE T,DCHBT(I) + IORM T,QTUTO(I) + MOVE A,(D) ;ELSE DELETE MMP ENTRY NOW + SKIPGE C + JUMPN B,MMPRT0 ;IF PG IS IN FILE, AND SWAPPED IN, MAYBE WRITE OUT. + TLNN A,MMPSHR + JRST MMPRT8 + HLRZ A,1(D) ;ALSO REMOVE FROM SHAREABLE PAGE TABLE + HRL A,I + IDIVI A,SHRHSL + ADDI B,SHRHSH-1 +MMPRT7: MOVE A,B + HRRZ B,1(B) + JUMPE B,[JRST 4,.] + CAME B,D + JRST MMPRT7 + HRRZ B,1(B) + HRRM B,1(A) +MMPRT8: POP P,B + JUMPL C,MMPRT3 ;WAS MEM IN LOOP SO NOT SWAPPED OUT FOR SYSTEM'S COUNT + SOS NPGSWO ;IT WAS SWAPPED OUT +MMPRT3: PUSHJ P,MMPRT1 + SOS MMPCNT ;1 LESS IN USE + AOS MMPFR ;1 MORE FREE + JRST MMPRT4 + +;FLUSHING AN MMP ENTRY FOR A PAGE SHARED WITH A FILE WHICH IS CURRENTLY IN CORE. +;WE MAY WANT THIS PAGE AGAIN, SO TRY TO KEEP IT AROUND FOR A WHILE. +;BUT IF PAGE HAS BEEN MODIFIED, IMMEDIATELY SWAP IT OUT SO FILE GETS UPDATED. + +MMPRT0: POP P,B + LDB C,H ;UN-SOS THE TUT + CAIGE C,TUTMNY ;DON'T OVER-AOS + AOS C + DPB C,H + PUSHJ P,QTULK + MOVEI C,.BM MLO + ANDCAM C,MEMBLT(J) + SKIPE C,LLOOSP ;ADD TO TAIL OF LOOSE PAGE LIST + DPB J,[MLO,,MEMBLT(C)] + MOVEM J,LLOOSP + SKIPN C + MOVEM J,FLOOSP + AOS NLOOSP + TLNN A,MMPWRT + JRST RHUSRA + PUSH P,U ;PAGE WAS MODIFIED, SWAP IT OUT RIGHT AWAY + CONO PI,CLKOFF ;CALL SWAPPER AT IMITATION CLOCK LEVEL + MOVEM J,SWOBK + MOVEM D,SWOMMP + AOS CIRPSW ;SWOP1A WILL SOS IT BEFORE RETURNING + PUSHJ P,SWOP1A ;WILL RETURN THE MMP ENTRY SINCE NO USERS ARE LINKED TO IT + JRST 4,. ;EXEC PAGES STILL POINT TO PAGE, ALTHOUGH UPGRTN FLUSHED THEM + CONO PI,CLKON + POP P,U + JRST RHUSRA + +;HERE TO RETURN AN MMP ENTRY AND SOS THE TUT, AT P.I. LEVEL +;IF TUT OR CIRPSW IS LOCKED, PUTS ON MMPFS2 AND WAKES UP CORE JOB +;OTHERWISE, CLEARS OUT AND PUTS ON MMPFS +;A -> MMP ENTRY, CLOBBERS B,D,E,I + +RETMMP: PI2SAF + LDB I,[$MMPUN,,(A)] + SKIPGE CIRPSW + SKIPGE QTUTO(I) + JRST RETMM1 ;CAN'T SET LOCKS, LET CORE JOB DO IT +RETMM0: HLRZ D,1(A) + PUSHJ P,TUTPNT ;SOS THE TUT + CAIGE B,TUTMNY + SOJL B,[JRST 4,.] + DPB B,D + JUMPN B,RETMM7 + MOVE E,QTUTO(I) ;RETURNING BLOCK TO FREE, AOS APPROPRIATE FREE COUNT + HLRZ D,1(A) + CAML D,QSWAPA(E) + AOSA QSFT(I) + AOS QSFTS(I) +RETMM7: MOVSI D,MMPSHR + TDNN D,(A) + JRST RETMM6 + HLRZ D,1(A) ;REMOVE FROM SHAREABLE PAGE HASH TABLE + HRL D,I + IDIVI D,SHRHSL + MOVEI D,SHRHSH-1(E) +RETMM5: MOVE E,D + HRRZ D,1(D) + JUMPE D,[JRST 4,.] ;NOT IN TABLE OR MIS-HASHED? + CAME D,A + JRST RETMM5 + HRRZ D,1(D) + HRRM D,1(E) +RETMM6: MOVE D,A + SOS MMPCNT + AOS MMPFR +MMPRT1: EXCH D,MMPFS ;ADD THIS ENTRY ONTO THE FRONT OF + MOVE A,MMPFS ;THE LIST OF AVAILABLE MMP ENTRIES + MOVEM D,(A) ;CLEAR LH OF FIRST WORD OF ENTRY + SETZM 1(A) ;CLEAR SECOND WORD OF ENTRY + POPJ P, + +RETMM1: MOVE D,A ;ADD THIS ENTRY TO LIST OF ONES TO HACK LATER + EXCH D,MMPFS2 + HRRM D,(A) ;ONLY CLOBBER THE CIRC PNTR, WHICH POINTS TO SELF + SKIPN D + AOS NCORRQ ;LIST WAS EMPTY, AWAKEN CORE JOB + POPJ P, + +;CORE JOB COMES HERE WHEN MMPFS2 IS NON-ZERO + +RETMM2: SOS NCORRQ + PUSHJ P,SWTL + CIRPSW + PUSHJ P,RETMM4 + PUSHJ P,LSWPOP + JRST CORJOB + +RETMM4: MOVEI A,0 ;HERE, WITH CIRPSW LOCKED, TO FINISH RETURNING MMP ENTRIES + EXCH A,MMPFS2 +RETMM3: JUMPE A,CPOPJ + LDB I,[$MMPUN,,(A)] + PUSHJ P,QTLOCK + HRRZ H,(A) + PUSHJ P,RETMM0 + PUSHJ P,QTULK + MOVE A,H + JRST RETMM3 + +;GET AN MMP ENTRY, RET. IDX IN R, ADDR IN TT. +;CLEARS BOTH WDS OF MMP ENTRY. CLOBBERS NO ACS. +;SKIPS IF SUCCESSFUL. DOESN'T SKIP IF NO LOW CORE FOR NEW MMP PAGE. +;YOU BETTER ALREADY HAVE COMMITTED THE MMP ENTRY VIA SOSGE MMPFR + +GMMPP: HRRZ TT,MMPFS + JUMPE TT,GMMP1 ;FREE LIST IS EMPTY + CAMGE TT,MMPEAD + JRST 4,. ;IDX GOT ON FREE LIST; SHOULD BE ADDR + MOVE R,TT + SUB R,MMPEAD + CLEARM 1(TT) + HRL TT,(TT) + CLEARM (TT) + HLRZM TT,MMPFS + AOS MMPCNT ;1 MORE MMP ENTRY IN USE. + JRST POPJ1 + +GMMP1: SKIPN MMPFS2 + JRST GMMP4 + PUSH P,A ;PROTECT ACS CLOBBERED BY RETMM4 + PUSH P,B + PUSH P,D + PUSH P,E + PUSH P,H + PUSH P,I + PUSH P,T + PUSHJ P,RETMM4 + POP P,T + POP P,I + POP P,H + POP P,E + POP P,D + POP P,B + POP P,A + JRST GMMPP + +GMMP4: PUSH P,A ;CREATE ANOTHER PAGE-FULL OF MMP ENTRIES + PUSH P,B + PUSH P,D + PUSHJ P,TCALL + ;JRST IOMQ ;ALLOCATE LOW CORE SO GETS DUMPED WITH CRASHES + JRST NMMRQ ;IOMQ LOSES BECAUSE WE GET CALLED WITH MEMFRZ LOCKED + ;NMMRQ ISN'T QUITE RIGHT, BECAUSE OF NCBCOM. FIX LATER. --- + JRST GMMP3 ;NO LOW CORE AVAIL NOW + MOVEI B,MUMMP + DPB B,[MUR,,MEMBLT(A)] + MOVEI B,2000 + ADDM B,MMPMX ;INCREMENT MAX ALLOWABLE ADDR OF MMP + AOS B,MMPNP + CAILE B,NMMP + JRST 4,. ;SOMEONE DIDN'T CHECK MMPFR? + MOVEM A,MMMPG-1(B) + TRO A,600000+PMCSHM + DPB A,MMPPPP-1(B) ;PUT NEW MMP PAGE INTO EXEC MAP + MOVE D,USER + CLRPGM (D) + SOS B + LSH B,10. + HRLI B,-1000 +GMMP2: MOVEI D,MMP(B) ;PUT ALL ENTRIES IN PAGE ON THE FREE LIST + PUSHJ P,MMPRT1 + AOS B + AOBJN B,GMMP2 + POP P,D + POP P,B + POP P,A + JRST GMMPP + +GMMP3: POP P,D + POP P,B + POP P,A + POPJ P, + +;HERE IF TRANSIENT CONDITION PREVENTS GRABBING PAGE RIGHT NOW + +CORS18: MOVE T,LSWPR+LUBLK + CAIE T,MEMFRZ + JRST 4,. + PUSHJ P,LSWPOP ;MEMFRZ + PUSHJ P,UDELAY + PUSHJ P,ACMTC + PUSHJ P,SWTL + MEMFRZ + +;GROW A JOB'S CONTIGUOUS MEMORY. USED ONLY FOR SYSTEM JOB THESE DAYS. + +CORS2: +IFN XGP,[ + SKIPL XGPUSR ;AVOID EXPANDING INTO XGP PAGE. + PUSHJ P,UFLS +] + LDB J,[121100,,HUSRAD(U)] + LDB E,[MUR,,MEMBLT(J)] + CAIN E,MUFR + JRST COSFR ;FREE PAGE, TAKE IT. + CAIE E,MUINP + CAIN E,MUFRT + JRST CORS18 ;WAIT UNTIL IT STABILIZES + CAIN E,MUSWPG + JRST CORS18 ;WAIT UNTIL IT GETS WHERE IT'S GOING + CAIE E,MURUSR ;USER PAGE, SHUFFLE IT AWAY. + JRST 4,. ;SHOULDN'T HAVE TO SHUFFLE SYSTEM PAGES. + +;SHUFFLE A USER PAGE +CORS4: PUSHJ P,TCALL + JRST HMEMRQ ;GET FREE PAGE TO SHUFFLE IT INTO + JRST 4,. ;THERE OUGHT TO BE ONE + PUSHJ P,CORS5 + JRST CBMRT + +;Shuffle user page in J into page in A +;Clobbers C,D,E,H,I,Q,U,T +CORS5: MOVE D,A + SKIPGE E,MMSWP(J) + JRST 4,. ;BLOCK IS ON SWAP OUT LIST (??) + TRNN E,-1 + PUSHJ P,CORS6 ;SHUFFLING A POSSIBLY LOOSE PAGE, FIX POINTERS + SETOM DLSRCH ;CAN'T BE BEING SWAPPED OUT ETC BECAUSE SWAPOUT + PUSHJ P,UCPRL7 ;BLOCKS HAVE MUR=MU23B, AND CIRPSW IS SIEZED + SETZ CORSTU ;STOP DIRECT TO MEM DEVICES AND FIX USER MAPS + TLC C,200 ;CHANGE TO 20 BIT BYTE + DPB D,C ;RELOCATE PTR TO MEMPNT ENTRY + PUSHJ P,CMOVE1 ;MOVE CONTENTS OF BLOCK + MOVSI C,-NEXPGS + MOVE T,[442200,,EXEUMP] + PUSHJ P,CORPS1 ;FIX ANY EXEC PAGE MAP PNTRS TO THIS PAGE + PUSHJ P,UCPRL4 + SETZ DEVSTR ;RESTART DIRECT TO MEM DEVICES + SETZM DLSRCH ;MAPS ARE CONSISTENT AGAIN, LET USERS RUN + POPJ P, + +CORSTU: PUSHJ P,DEVSTP ;STOP DIRECT-TO-MEM DEVICES + MOVE A,I ;COMPUTE USER'S MAP ENTRY LOCN + PUSHJ P,UPLC + LDB C,T + TRNN C,600000 + POPJ P, ;PAGE SWAPPED IN BUT NOT YET LINKED UP + ANDI C,PMRCM + CAIE C,(J) + JRST 4,. + TLC T,2200# ;CHANGE TO ADDRESS REAL CORE ADR FIELD + DPB D,T ;RELOCATE USER'S MAP + POPJ P, + +COSFR: MOVE D,J + PUSHJ P,MEMMF +CBMRT: MOVEM J,SJSPG ;SAVE PAGE # RESERVED + JRST CORM1B + +;CORE SHUFFLER, TO KEEP LOW MEMORY FREE +CFLM1: PUSHJ P,SWTL + CIRPSW + PUSHJ P,SWTL + MEMFRZ + PUSHJ P,CFLM2 + PUSHJ P,LSWPOP ;MEMFRZ + JRST LSWPOP ;CIRPSW + +CFLM2: MOVEI J,LIOBLK ;Scan through "low" memory + SKIPE MEMHPT ;Make sure there is likely to be free high mem + JRST CFLM4 + AOS SWPOPR ;Kick swapper more than kicked already + POPJ P, ;And give up + +CFLM3: CAIN J,128. + MOVEI J,128.+NEXPGS + CAIL J,256. ;Assume USEMDM is always on (safe assumption) + POPJ P, ;All done, couldn't find anything +CFLM4: LDB A,[MUR,,MEMBLT(J)] + CAIE A,MURUSR + AOJA J,CFLM3 + PUSHJ P,TCALL + JRST HMEMRQ ;Get free page to shuffle it into + POPJ P, ;No memory free, give up for now + PUSHJ P,CORS5 ;Shuffle page into new memory + MOVE A,J ;Free old page + PUSHJ P,CMEMR + MOVE A,LMEMFR + CAMGE A,MINCOR + AOJA J,CFLM3 + POPJ P, ;Freed sufficient low pages, stop now + +;STOP DIRECT TO MEM DEVICES + +DEVSTP: +IFN VIDP,[ + CAMN U,SCNUSR ;STOP DIRECT MEM DEVICES + PUSHJ P,SCNSTC ;STOP DIRECT VIDI INPUT +] +IFN 340P\E.SP,[ + CAMN U,DISUSR ;STOP DISPLAY IF THIS GUY HAS IT + PUSHJ P,DCRSTP +] + POPJ P, + +;RESTART DIRECT TO MEM DEVICES + +DEVSTR: CLRPGM +LUBLK ;CLEAR PAGE MAP ASSOC REGS IN HARDWARE +IFN VIDP,[ + CAMN U,SCNUSR ;RESTART DIRECT MEM DEVICES + PUSHJ P,SCNRST ;RESTART DIRECT VIDI INPUT +] +IFN 340P\E.SP,[ + CAMN U,DISUSR + PUSHJ P,DCRRST ;RESTART DISPLAY +] + POPJ P, + +;HERE TO RELOCATE EXEC PAGES WHICH POINT TO PAGE IN J + +CORPS1: MOVEI I,0 +CORPS4: ILDB Q,T + TLC T,2200# ;CHANGE SIZE FIELD TO ADDRESS REAL CORE ADR + ANDI Q,PMRCM + CAME Q,J + JRST CORPS3 + AOS I ;COUNT # OF EXEC PGS POINTING TO THIS ONE + DPB D,T ;RELOCATE EXEC PG PNTR +CORPS3: TLC T,2200# ;CHANGE SIZE BACK TO 22 + AOBJN C,CORPS4 + HLRZ T,MMSWP(D) + CAMN T,I ;CHECK COUNT OF EXEC PAGES + POPJ P, ;COUNTED CORRECTLY, WIN + +IFN E.SP,[ ;SEE IF E&S CAN ACCOUNT FOR SOME PAGES + MOVSI Q,-MXDISP ;SET UP INDEX + CAMN J,DISSWP(Q) ;J/ OLD INDEX, D/ NEW + AOJA I,E.SX2 ;COUNT I IF FOUND, AND RECHECK COUNT + AOBJN Q,.-2 ;ELSE CONTINUE SEARCH + JRST 4,. ;NOT FOUND, BOMB +E.SX2: MOVEM D,DISSWP(Q) ;RELOCATE PAGE + AOS E.SREL ;# PAGES RELOCATED (FOR DEBUGGING) + CAMN T,I ;SKIP IF COUNT IS STILL BAD + POPJ P, ;E&S COUNT WAS CULPRIT -- HAPPY AGAIN +] +IFN XGP,[ + PUSH P,A + PUSH P,B + MOVE B,J + PUSHJ P,XGPBIT + TDNE A,XGPMTB(B) + AOS I + CAMN I,T + JRST POPBAJ +] + JRST 4,. ;EXEC PGS COUNT OFF + +CORS6: MOVE T,FLOOSP ;FIX POINTERS TO LOOSE PAGE BEING SHUFFLED +CORS7: SKIPN C,T + JRST CORS8 + LDB T,[MLO,,MEMBLT(C)] + CAME T,J + JRST CORS7 + DPB D,[MLO,,MEMBLT(C)] +CORS8: CAMN J,FLOOSP + MOVEM D,FLOOSP + CAMN J,LLOOSP + MOVEM D,LLOOSP + POPJ P, + +;RUN AROUND CIRC LIST STRUCTURE +;WORD AFTER CALL IS POINTER TO ROUTINE TO BE CALLED FOR EACH ITEM IN LIST ACCORDING +;TO FLAGS IN LH: 4.9 USER PAGE (U=USER,I=PG#), 4.8 MMP (T=IDX), 4.7 MEMPNT (T=PG#) +;CALLED ROUTINE MUSTN'T CLOBBER C,H; NOR U,I IF A USER PAGE; NOR T IF MEMPNT. +;RETURNS IN C BYTE POINTER TO PLACE THAT POINTS TO +;STARTING BYTE POINTER THAT WAS IN C +;ENTRIES: +; UCPRL - STARTING BYTE POINTER IN C +; UCPRL4 - STARTING CORE PAGE # IN D +; UCPRL7 - STARTING CORE PAGE # IN J +;PDL DEEPENED BY TWO PUSH'S AND TWO PUSHJ'S. +;---WARNING--- : CLOBBERS U ------- ALSO CLOBBERS H,T,I + +UCPRL7: SKIPA C,[2200,,MEMPNT(J)] +UCPRL4: MOVE C,[2200,,MEMPNT(D)] +UCPRL: MOVE H,@(P) + HRRI C,@C + TLZ C,37 + PUSH P,C + PUSH P,C + JRST UCPRL5 + +UCPRL2: CAMN C,-1(P) + JRST UCPRL6 + MOVEM C,(P) +UCPRL5: LDB T,C + JUMPE T,[JRST 4,.] + TRZE T,400000 + JRST UCPRL1 + LDB I,[1000,,T] ;PAGE # + LDB U,[101100,,T] ;USER # + IMULI U,LUBLK + CAML U,USRHI + JRST 4,. + SKIPGE H + PUSHJ P,(H) + MOVEI C,UPGCP(U) + ROT I,-1 + ADDI C,(I) + HRLI C,222200 + SKIPGE I + HRLI C,2200 + JRST UCPRL2 + +UCPRL1: TRZE T,200000 + JRST UCPRL3 + CAML T,MMPMX + JRST 4,. ;MMP ADR OUT OF RANGE + MOVSI C,2200 ;MMP + HRR C,MMPEAD + ADDI C,(T) + TLNE H,200000 + PUSHJ P,(H) + JRST UCPRL2 + +UCPRL3: CAIL T,TSYSM + JRST 4,. ;MEMBLT ADR OUT OF RANGE + TLNE H,100000 ;MEMPNT + PUSHJ P,(H) + MOVE C,[2200,,MEMPNT] + ADDI C,(T) + JRST UCPRL2 + +UCPRL6: MOVE C,(P) + SUB P,[2,,2] + JRST POPJ1 + ;DISCARD IDLE DISK UFD'S. + +UFDFF: PUSHJ P,SWTL + UDRSW + MOVEI C,MEMR + PUSHJ P,QDFLS + JRST UTBFF5 + +;FLUSH "UTAPE" (200-WD) BUFFERS +;TRY TO COMPACTIFY INTO FEWER PAGES BY DELETING PAGES CONTAINING +;ONLY FREE ONES AND BY MOVING NETWORK BUFFERS AROUND. OTHER KINDS +;OF BUFFERS DON'T STAY AROUND VERY LONG AND ARE HARD TO MOVE +;WITHOUT INTRODUCING TIMING/PCLSR'ING BUGS. + +UTBFF: PUSHJ P,SWTL + MEMFRZ + MOVSI J,-TSYSM +UTBFF3: LDB R,[MUR,,MEMBLT(J)] + CAIN R,MUIOB + PUSHJ P,UTBFF2 + AOBJN J,UTBFF3 +UTBFF5: SOS NCORRQ + PUSHJ P,LSWPOP +IFN CHAOSP, PUSHJ P,CHCLN ;ALSO, CLEAN UP CHAOS NET BUFFERS +IFN INETP, PUSHJ P,PKBCLN ; Clean up network packet buffers +;SWAP OUT ALL LOOSE PAGES. THE REASON THIS IS DONE IS THAT IF THE +;SYSTEM LOAD IS LIGHT LOOSE PAGES FOR DELETED INQUIR DATA BASE FILES +;CAN STAY AROUND INDEFINITELY, TYING UP DISK SPACE. +;SWAPPING OUT LOOSE PAGES DOES NOT CAUSE ANY DISK I/O. +;SWPOPG MAY NON-SKIP RETURN IF CIRPSW OR A TUT IS LOCKED, +;IN WHICH CASE WE GIVE UP UNTIL THE NEXT 2-MINUTE CLOCK. +UTBFF6: CONO PI,CLKOFF + SKIPN A,FLOOSP ;GET A LOOSE PAGE + JRST UTBFF7 + MOVNI C,1 + PUSHJ P,SWPOPL ;SWAP OUT EVEN IF LOCKED (SHOULDN'T BE) + JRST UTBFF7 ;COULDN'T SWAP OUT, GIVE UP FOR NOW + CONO PI,CLKON ;ALLOW CHANCE FOR AN INTERRUPT + JRST UTBFF6 + +UTBFF7: CONO PI,CLKON + JRST CORJOB + +;RH(J) HAS PAGE NUMBER OF A BLOCK OF 200-WD BUFFERS +UTBFF2: LDB R,[MNUMB,,MEMBLT(J)] ;GET LIST OF IOBFT ENTRIES IN THIS BLOCK + CLEARB Q,TT +COSIO1: MOVSI E,200000 ;ALLOC INH ALL BUFFERS IN BLOCK + IORM E,IOBFT(R) + LDB E,[IOCH,,IOBFT(R)] + CAIE E,77 + AOS Q ;COUNT NUMBER USED FOR SOMETHING + CAIL E,NFNETC + CAIL E,NFNETC+NNETCH + CAIA + AOS TT ;COUNT NUMBER USED FOR NETWORK + LDB R,[IOLC,,IOBFT(R)] + CAIE R,377 + JRST COSIO1 + JUMPE Q,COSIO3 ;IF ALL BUFFERS FREE, FLUSH THIS PAGE + CAME Q,TT + JRST UTBFF1 ;CONTAINS NON-NET BUFFERS, LEAVE ALONE + MOVEI E,0 + EXCH E,UTTBF + CAIL E,8 ;IF THERE ARE ENOUGH FREE IN OTHER BLOCKS + JRST CISHUF ;THEN GO SHUFFLE THE NET BUFFERS + EXCH E,UTTBF +UTBFF1: LDB R,[MNUMB,,MEMBLT(J)] ;ABANDON IDEA OF FLUSHING THIS BLOCK + MOVSI E,200000 ;UN-INHIBIT THE BUFFERS.. +UTBFF4: ANDCAM E,IOBFT(R) + LDB R,[IOLC,,IOBFT(R)] + CAIE R,377 + JRST UTBFF4 + POPJ P, ;RETURN OUT OF UTBFF2 + ;SHUFFLE BUFFERS +;COME HERE WITH UTTBF SET TO 0 AND OLD VALUE IN E +;LEAVE UTTBF 0 WHILE SHUFFLING SO NO ONE ELSE CAN ALLOCATE + +CISHUF: PUSH P,E + LDB R,[MNUMB,,MEMBLT(J)] +CISHF1: LDB Q,[IOCH,,IOBFT(R)] + CAIN Q,77 + JRST CISHF2 ;FREE, IGNORE + CAIL Q,NFNETC + CAILE Q,NFNETC+NNETCH + JRST 4,. ;SOME RANDOM UNSHUFFABLE BUFFER + PUSHJ P,CINET +CISHF2: LDB R,[IOLC,,IOBFT(R)] + CAIE R,377 + JRST CISHF1 + POP P,UTTBF ;ALLOW ALLOC AGAIN. THIS MEM BLOCK NOW + ;CONTAINS 8 FREE, ALLOC INH BUFFERS. + ;SO FALL INTO COSIO3 TO FLUSH THEM. +;FLUSH ALL 8 BUFFERS. + +COSIO3: LDB R,[MNUMB,,MEMBLT(J)] + MOVEI TT,7 +COSIO4: LDB Q,[IOCH,,IOBFT(R)] + CAIE Q,77 + JRST 4,. ;BUFFER WAS SUPPOSED TO BE FREE?? + MOVEI Q,UTFS-IOBFT ;PNTR TO F.S. LIST + SOS UTTBF ;SOON WILL BE ONE LESS FREE UTAPE BUFFER + CONO PI,UTCOFF +COSIO5: MOVE E,Q ;REMOVE IOBFT ENTRY IN R FROM F.S. LIST + LDB Q,[IOLO,,IOBFT(Q)] + CAIN Q,377 + JRST 4,. ;IT WASN'T IN THE LIST + CAME Q,R + JRST COSIO5 + + LDB Q,[IOLO,,IOBFT(R)] + DPB Q,[IOLO,,IOBFT(E)] + MOVE A,R ;GIVE IOBFT ENTRY BACK TO LIST OF UNUSED IOBFTS + LDB R,[IOLC,,IOBFT(R)] + PUSHJ P,IOBR + CONO PI,UTCON + CAIE R,377 + SOJA TT,COSIO4 + + JUMPN TT,[JRST 4,.] ;BLOCK DIDN'T CONTAIN 8 BUFFERS + MOVNI A,8 + ADDB A,UTTLB + CAMGE A,[-NUTIC-NUTOC] + JRST 4,. + PUSHJ P,FSCMP + HRRZ A,J ;THIS BLOCK OF MEMORY IS FREE NOW + JRST CMEMR ;AND RETURN OUT OF UTBFF2 + +;EXCHANGE BUFFER IN R WITH SOME FREE BUFFER, RETURNED IN A +;CALL WITH UCTOFF, CHANNEL NUMBER IN Q, TURNS UTCON + +COSIMG: MOVEI D,NFNETC(Q) ;CHNL NO TO CONS FOR + AOS UTTBF ;UNRESERVE ONE BUFFER MOMENTARILY + PUSHJ P,IUTCONS + JRST 4,. + CONO PI,UTCON + LDB TT,[IOSA1,,IOBFT(R)] ;TRANSFER BUFFER R TO BUFFER A + LDB T,[IOSA1,,IOBFT(A)] + HRL T,TT + LSH T,7 + HRRZ TT,T + BLT T,177(TT) + EXCH R,A + CONO PI,UTCOFF + PUSHJ P,IBRTN ;RETURN THE OLD BUFFER + SOS UTTBF ;BUT RESERVE IT + EXCH R,A + JRST UTCONJ + +;SHUFFLE OFF A NCP NETWORK BUFFER +;R HAS IOBFT INDEX, Q HAS CHANNEL NUMBER, E MUST BE PRESERVED + +CINET: +IFE NCPP,JRST 4,. +IFN NCPP,[ + SUBI Q,NFNETC ;GET IMSOC INDEX + HRRZ A,IMSOC1(Q) ;USER WHO OWNS THIS BUFFER + MOVSI T,200000 + TDNE T,IMSOC1(Q) ;SKIP OVER USER STOP IF BEING CLOSED + TROA A,-1 ; SINCE USER CAN'T REFERENCE BUFFER ANY MORE + PUSHJ P,RPCLSR ;AND LEAVE A=USER # STOPPED OR 0,,-1 IF NONE + MOVSI T,200000 ;MUSTN'T BE ACTIVE AT PI LEVEL + PUSHJ P,LWAIT + TDNE T,IMSOC6(Q) + SKIPN IMSOC6(Q) ;LWAIT RETURNS WITH NETOFF + JRST CINET2 ;BUFFER HAS BEEN RETURNED + MOVSI T,400000 ;LOCK THE BUFFER SO PI LEVEL WON'T TOUCH + IORM T,IMSOC6(Q) + LDB T,[221000,,IMSOC6(Q)] + CAIE T,(R) + JRST 4,. ;IOBFT ENTRY POINTS TO WRONG CHANNEL + PUSH P,A ;SAVE INDEX OF STOPPED USER + PUSHJ P,COSIMG ;COPY BUFFER + LDB TT,[IOSA,,IOBFT(A)] + LSH TT,6 + MOVE T,TT + HRRZ D,IMSOC6(Q) + SUB T,D ;OFFSET NEW BUFFER MINUS OLD + HRL TT,A + DPB TT,[003200,,IMSOC6(Q)] ;STORE NEW BUFFER ADDR, LEAVE FLAGS ALONE + ADDM T,IMSBFE(Q) ;RELOCATE VARIOUS POINTERS + ADDM T,IMSMPP(Q) + ADDM T,IMSPIP(Q) + MOVE TT,IMSOC2(Q) + TRNN TT,1 + AOSA IMNISH + AOS IMNOSH + CONO PI,NETOFF + MOVE TT,IMSOC6(Q) + TLNN TT,100000 ;SKIP IF INPUT OCCURRED WITH BUFFER LOCKED + JRST CINET1 +IFE DMI,[ + MOVE TT,IMPSVP ;RESTART INPUT + MOVEM TT,IMPPIA + CONO IMP,(TT) +] +IFN DMI,CONO FI,FIIN+NETCHN*11 +CINET1: MOVSI TT,500000 ;UNLOCK THE BUFFER, CLEAR INPUT WITH LOCK FLAG + ANDCAM TT,IMSOC6(Q) + PUSHJ P,IMPIOS ;RESTART OUTPUT + POP P,A ;AND FALL INTO CINET2 TO RESTART USER +CINET2: CONO PI,NETON + JRST NJUPCL ;RESTART USER IF ONE WAS STOPPED +] ;END IFN NCPP + +;FREE BLOCKS THAT BECAME FREE AT INT LEVEL. +ACMTC: SKIPN MEMFP1 ;ANY BLKS BECAME FREE AT INT LVL? + POPJ P, + CONO PI,UTCOFF + SKIPL MEMFRZ ;IF MEMFRZ IS LOCKED, CAN'T DO THIS. JUST + JRST UTCONJ ;HOPE ENOUGH CORE IS FREE. MUST BE BETTER WAY! + MOVE A,MEMFP1 ;GET # OF ONE OF THEM, + LDB B,[MLO,,MEMBLT(A)] ;REMOVE IT FROM LIST OF SUCH BLOCKS + HRRZM B,MEMFP1 + LDB B,[MUR,,MEMBLT(A)] + CAIE B,MUFRT + JRST 4,. + PUSHJ P,MEMR + JRST ACMTC + +;COPY A PHYSICAL PAGE'S DATA FROM PAGE (J) TO PAGE (D) +CMOVE1: MOVE C,MEMBLT(J) + MOVEM C,MEMBLT(D) + CLEARM MEMBLT(J) + MOVE C,MEMPNT(J) + MOVEM C,MEMPNT(D) + CLEARM MEMPNT(J) + MOVE C,MMSWP(J) + MOVEM C,MMSWP(D) + HRRZ A,D + CAIGE A,SYSB + JRST 4,. + TRO D,600000+PMCSHM + TRO J,600000+PMCSHM + DPB D,[.CORJT+EXEUMP] + DPB J,[.CORJF+EXEUMP] + TRZ D,600000+PMCSHM + TRZ J,600000+PMCSHM + CLRPGM +LUBLK + MOVE A,[400000+CORJF*2000,,400000+CORJT*2000] + BLT A,400000+CORJT*2000+1777 + MOVEI A,0 + DPB A,[.CORJT+EXEUMP] + DPB A,[.CORJF+EXEUMP] + POPJ P, + +MEMMF: LDB A,[MUR,,MEMBLT(D)] + CAIE A,MUFR + JRST 4,. + HRRZ A,D + PUSHJ P,TCALL + JRST MPOUT + POPJ P, + +UDELAY: PUSH P,T + MOVE T,TIME + ADDI T,15. ;SLEEP 1/2 SEC. (REALLY SHOULD DO A LOW + CAMLE T,TIME ;PRIORITY UNBLOCK IF SYS LIGHTLY LOADED) +UDELA1: PUSHJ P,UFLS + JRST POPTJ + +CZRR: PUSH P,A + CAIGE A,SYSB ;CORE ZEROER + JRST 4,. + TRO A,600000+PMCSHM + DPB A,[.CORJT+EXEUMP] + CLRPGM +LUBLK + CLEARM 400000+CORJT*2000 + MOVE A,[400000+CORJT*2000,,400000+CORJT*2000+1] + BLT A,400000+CORJT*2000+1777 + MOVEI A,0 + DPB A,[.CORJT+EXEUMP] + JRST POPAJ + +;ROUTINES TO ALLOCATE BLOCKS OF MEMORY +;CALL ONLY AT UTC LEVEL OR WITH UTC OFF + +OVHMTR ALC ;CORE ALLOCATION + +;SEE IF CAN ALLOCATE MEMORY +MQTEST: MOVE A,MEMFR + SUB A,NCBCOM + JUMPLE A,CPOPJ + SKIPLE MEMFR + SKIPL MEMFRZ + POPJ P, + JRST POPJ1 + +;ALLOCATE PREFERRING HIGH MEMORY, FOR RANDOM USER PAGE. SHUFFLEABLE PAGE OK. +HMRQC: PUSHJ P,MQTEST + POPJ P, +HMEMRQ: PUSH P,B + PUSH P,E + HRREI B,MEMHPT-MEMBLT +HMRQ3: LDB A,[MLO,,MEMBLT(B)] + JUMPE A,HMRQ1 ;HIGH HALF FULL TRY LOW + CAIL A,SYSB ;DON'T ALLOCATE PART OF THE SYSTEM + SKIPGE MEMBLT(A) ;DON'T ALLOCATE IF LOCKED + SKIPA B,A ;THIS PAGE NOT AVAIL, TRY NEXT + JRST IMRQ8 ;GOBBLE IT + JRST HMRQ3 + +HMRQ1: POP P,E + POP P,B + JRST NMMRQ ;THAT DIDNT WORK, TRY LOW HALF + +;ALLOCATE A BLOCK OF MEM FOR 200-WORD BUFFERS +UIMRQ: MOVE A,IOBFC + CAIGE A,8 + POPJ P, ;NOT ENOUGH ROOM IM IOBFT + MOVE A,MEMFR + SUB A,NCBCOM + CAIG A,3 + POPJ P, + +;GET A BLOCK THAT WON'T BE SHUFFLED, AND IS DIRECTLY ACCESSIBLE. +IOMQ: PUSHJ P,MQTEST ;GET LOW OR MEDIUM MEMORY FOR I/O + POPJ P, + +;ALLOCATING LOW MEM +NMMRQ: MOVEI A,0 ;MEMFP = MEMBLT+0 +IMRQ7: PI2SAF + PUSH P,B + PUSH P,E +IMRQ2: LDB A,[MLO,,MEMBLT(A)] + JUMPN A,IMRQ3 + PUSH P,C + PUSH P,H + PUSH P,TT + MOVEI C,IMEMR + SKIPGE UDRSW + PUSHJ P,QDFLS ;TRY FLUSHING DISK DIRS + POP P,TT + POP P,H + POP P,C + MOVEI A,0 +IMRQ6: LDB A,[MLO,,MEMBLT(A)] + JUMPE A,IMRQR ;NO MEM AVAIL IN LOW HALF, TAKE NON-SKIP RETURN + SKIPGE MEMBLT(A) + JRST IMRQ6 + JRST IMRQ9 + +MPOUT1: +IMRQR: POP P,E + JRST POPBJ + +IMRQ3: SKIPGE MEMBLT(A) + JRST IMRQ2 ;LOCKED LOOK FOR ANOTHER +IMRQ9: TDZA B,B ;GOBBLE FROM LOW +IMRQ8: MOVNI B,1 ;GOBBLE FROM HIGH + AOS -2(P) ;CAUSE RETURN TO SKIP + LDB E,[MUR,,MEMBLT(A)] + CAIN E,MUFR + JUMPN A,IMRQ4 + JRST 4,. ;BLOCK GOT PUT ON FREE STORAGE LIST WITHOUT USAGE FIELD GETTING "FREE" + ;ROUTINES FOR RETURNING MEMORY +IMEMR: PI2SAF ;HERE OTHERWISE (SEE BELOW) + CAIGE A,TSYSM + CAIGE A,SYSB + JRST 4,. ;DON'T RETURN PART OF SYSTEM + SKIPL MEMFRZ + JRST IMEMR1 +CIMEMR: PUSH P,B ;ENTER HERE IF OK TO HACK WITH MEM FROZEN + LDB B,[MUR,,MEMBLT(A)] ;I E CALLING FROM CORE ALLOCATOR + CAIN B,MUFR + JRST 4,. ;ALREADY FREE, LOSSAGE + SETZM MEMBLT(A) ;INITIALIZE RANDOM FIELDS + CAIGE A,256. ;HIGH MOBY GOES ON HIGH LIST + CAIGE A,LIOBLK ;LOW SHUFFLEABLE GOES ON HIGH LIST + JRST CIMEM1 + CAIGE A,128. ;LOW NON-SHUFFLEABLE GOES ON LOW LIST + JRST CIMEM0 + CAIL A,128.+NEXPGS ;SHADOWS OF EXEC PAGES GO ON HIGH LIST + SKIPN USEMDM ;MEDIUM MEMORY GOES ON LOW OR HIGH DEPENDING ON USEMDM + JRST CIMEM1 +CIMEM0: LDB B,[MLO,,MEMFP] ;PICK UP HEAD OF APPRO FS LIST + DPB B,[MLO,,MEMBLT(A)] ;STORE AS LINK OUT OF CURRENT WD + CAIE B,0 ;SKIP IF NO BLOCK PREVIOUSLY ON LIST + DPB A,[MLU,,MEMBLT(B)] ;MAKE FORMER HEAD'S BACK PNTR POINT TO CURRENT + MOVEI B,0 ;NO BACK PTR, THIS WILL BE FIRST IN LIST + DPB B,[MLU,,MEMBLT(A)] + DPB A,[MLO,,MEMFP] ;STORE THIS AS FREE LIST HEAD + AOS LMEMFR +CIMEM3: MOVEI B,MUFR + DPB B,[MUR,,MEMBLT(A)] ;STORE FREE IN USER + CLEARM MEMPNT(A) + AOS MEMFR + JRST POPBJ + +CIMEM1: LDB B,[MLO,,MEMHPT] ;PICK UP HEAD OF APPRO FS LIST + DPB B,[MLO,,MEMBLT(A)] ;STORE AS LINK OUT OF CURRENT WD + CAIE B,0 ;SKIP IF NO BLOCK PREVIOUSLY ON LIST + DPB A,[MLU,,MEMBLT(B)] ;MAKE FORMER HEAD'S BACK PNTR POINT TO CURRENT + MOVEI B,0 ;NO BACK PTR, THIS WILL BE FIRST IN LIST + DPB B,[MLU,,MEMBLT(A)] + DPB A,[MLO,,MEMHPT] ;STORE THIS AS FREE LIST HEAD + JRST CIMEM3 + +IMEMR1: PUSH P,B ;FREE A PAGE WHEN MEMFRZ LOCKED. + MOVE B,MEMFP1 ;ADD IT TO FRONT OF MEMFP1 LIST + DPB B,[MLO,,MEMBLT(A)] + HRRZM A,MEMFP1 + MOVEI B,MUFRT ;THEN SAY THIS BLK BECAME FREE WITH MEM FROZEN. + DPB B,[MUR,,MEMBLT(A)] + SETZM MEMPNT(A) + JRST POPBJ + +;ROUTINES TO RETURN MEMORY CONTINUED + +MGMEMR: PUSHJ P,TMEMR ;MAG TAPE MEMR + MUMGB + POPJ P, + +TMEMR: PUSH P,B + LDB B,[MUR,,MEMBLT(A)] + CAME B,@-1(P) + JRST 4,. ;RETURNING BLOCK NOT OF TYPE EXPECTED + POP P,B + AOS (P) ;SKIP OVER ARG +MEMR: CONO PI,UTCOFF + PUSHJ P,IMEMR + JRST UTCONJ + +CMEMR: CONO PI,UTCOFF + PUSHJ P,CIMEMR + JRST UTCONJ + +; ROUTINES TO UNTHREAD BLOCKS FROM FREE LISTS + +MPOUT: PI2SAF +MPOUT2: JUMPE A,[JRST 4,.] ;ENTER HERE FROM INITIALIZATION IF HOLE FOUND + PUSH P,B + PUSH P,E + CAIGE A,256. ;HIGH MOBY GOES ON HIGH LIST + CAIGE A,LIOBLK ;LOW NON-SHUFFLEABLE GOES ON HIGH LIST + JRST MPOUT4 + CAIGE A,128. ;LOW SHUFFLEABLE GOES ON LOW LIST + JRST MPOUT3 + CAIL A,128.+NEXPGS ;SHADOWS OF EXEC PAGES GO ON HIGH LIST + SKIPN USEMDM ;MEDIUM MEMORY GOES ON LOW OR HIGH DEPENDING ON USEMDM +MPOUT4: SKIPA B,[-1] ;IT'S HIGH MEM +MPOUT3: MOVEI B,0 ;IT'S LOW MEM + +IMRQ4: PUSH P,B ;0 LOW -1 HIGH + LDB B,[MLU,,MEMBLT(A)] ;LINK UP + LDB E,[MLO,,MEMBLT(A)] ;LINK OUT + JUMPN B,IMRQ5 ;JUMP IF NOT FIRST IN LIST + JUMPE E,IMRQ5 ;JUMP IF LAST BLOCK IN LIST + LDB B,[MUR,,MEMBLT(E)] ;FIRST AND FOLLOWED + CAIE B,MUFR + JRST 4,. ;DOESNT LINK TO A FREE BLOCK + MOVEI B,0 ;PUT BACK 0 +IMRQ5: SKIPE E ;SKIP IF NO BLOCK FOLLOWS + DPB B,[MLU,,MEMBLT(E)] ;STORE LINK UP OF PATCHED OUT BLOCK IN LINK OUT BLOCK + JUMPE B,IMRQ5A + DPB E,[MLO,,MEMBLT(B)] ;STORE LINK OUT OF PATCHED OUT BLOCK IN LINK UP BLOCK + POP P,B ;GET BACK WHICH PART OF MEM IT'S IN + JRST IMRQ5C + +IMRQ5A: POP P,B ;GET BACK WHICH PART OF MEM IT'S IN + DPB E,[MLO,,MEMFP(B)] ;THIS WAS FIRST IN FREE LIST, ADJUST LIST HEADER +IMRQ5C: SKIPL B ;SKIP IF NOT IN LOW HALF + SOS LMEMFR ;ADJUST FREE BLOCKS IN LOWER HALF + SOS MEMFR ;1 LESS FREE BLOCK IN SYSTEM + SETZM MEMBLT(A) ;CLEAN UP MEMBLT ENTRY FOR CALLER'S SAKE + MOVEI B,MUINP ;IN PROCESS + DPB B,[MUR,,MEMBLT(A)] + JRST MPOUT1 + +OVHMTR UUO ;MORE MISC UUOS ETC. + +TCALL: CONO PI,UTCOFF + PUSHJ P,@(P) + SKIPA + AOS (P) + JRST UTCOJ1 + +EBLK + +SUBTTL MEMORY ALLOCATION TABLES + +IOBFTL: MXIOB ;BEG FOR GETSYS (MEMORY) +IOBFT: REPEAT MXIOB-1,176000,,.RPCNT+1 ;MAX DYN ALLOC IO BUFFERS + 176000,,377 ;4.9 FREEZE + ;4.8 ALLOC INHIBIT +IOCH==340600 ;4.7-4.2 SYS CHN NO 77 => FREE +IOLC==241000 ;4.1-3.3 LINK TO NEXT SEQ BUF IN CORE (W/IN 1K BLK) +IOLO==1000 ; LINK TO FOLLOWING BUFFER OR + ;SPECIAL STATES LINK OUT + ;-1 LAST BUFFER CURRENTLY FILLED + ;-2 END OF FILE + ;-3 BUFFER ACTIVE AT MAIN PROG LEVEL + ;-4 BUFFER ACTIVE AT PI LEVEL +;IF CHN IS NUTIC+NUTOC (UTAPE FILE DIR) THEN IOLO IS TAPE NO +;CHNLS NUTIC+NUTOC+1 (NFCLC)=>$Q+NCLCH-1 ARE CORE LINK DEVICE +;CHNLS NFNETC => $Q+NNETCH-1 ARE NET CHNLS +SCNCLO==NUTIC+NUTOC+1 + +IOSA==101400 ; BUFFER SA _-6 +IOSA1==111300 ;ONLY RELEVANT BITS FOR 200 WD BUFFERS + + +IOBFP: 0 ;FREE STG TO IOBFT ENT +IOBFC: MXIOB-8 ;CNT OF AVAIL + ;LEAVE 8 AVAIL SO CORE HACKER CAN NOT RUN OUT + +UTFS: 377 ;FREE STG PNTR TO 200 WD BUFFERS +UTTLB: -NUTIC-NUTOC ;TOTAL BUFFERS ALLOCATED TO UTAPES +UTTBF: 0 ;TOTAL UT BUFFERS FREE + +;EXEC MAPS +IF2,[ +EXEUMP=UPGMP+100 ;EXEC UPPER MAP LIVES IN SYSTEM JOB'S MAP AREA +EXELMP==UPGMP ;KL10 AND KS10 ALSO NEED EXEC LOWER MAP, + EXISTS +];IF2 ;SO USERS CAN COPY PAGES FROM THE SYSTEM JOB + +;TABLE OF BYTE POINTERS THAT POINT TO VIDEO BUFFER AREA OF EXEUMP +IFN N11TYS,[ +TTCRT: REPEAT NTVBP,[ + CONC [.TTR]\.RPCNT,+EXEUMP +] +] + +IFN PDP6P,[ +;DBR FOR REFERENCING PDP6 MEM +PDP6MP: _1,,PDPUMP + +;PAGE MAP FOR REFERENCING PDP6 MEM +PDPUMP: REPEAT LPDP6M/2,600000++2*.RPCNT,,600000++2*.RPCNT+1 +] + +IFN 340P,[ +DDEXCF: BLOCK NEXPGS ;-1 IF EXEC PAGE SET UP FOR 340 +] + +IFN KA10P, EXECMP: 100_1,,EXEUMP ;EXEC DBR + ;MEMORY ORGANIZATION + +;PAGE 0 ALWAYS BELONGS TO THE SYSTEM AND IS NEVER ALLOCATED OR FREED. +; +;N PAGES OF SYSTEM CODE AND VARIABLES ARE ACQUIRED BY THE SYSTEM JOB AT STARTUP. +; +;N PAGES OF USER-VARIABLE BLOCKS BELONG TO THE SYSTEM JOB. THESE ARE +;ALLOCATED AND DEALLOCATED AS REQUIRED. LIOBLK-1 IS THE HIGHEST THIS CAN GO. +;USER PAGES BELOW LIOBLK CAN BE SHUFFLED OUT WHEN THE SYSTEM JOB NEEDS THE CORE. +; +;FROM LIOBLK TO 128K IS THE "LOW HALF." THESE PAGES ARE DIRECTLY ADDRESSABLE +;IN EXEC MODE AND NEVER NEED TO BE SHUFFLED. I/O BUFFERS, DISK DIRECTORIES, +;ETC. ARE ALLOCATED IN THESE PAGES. +; +;128K TO 128K+NEXPGS ARE PAGES WHICH CAN'T BE ADDRESSED DIRECTLY FROM +;EXEC MODE BECAUSE THEIR EXEUMP SLOTS ARE USED BY "EXEC PAGES." +; +;THE REST OF THE LOW MOBY, UP TO FDDTPG, IS DIRECT-MAPPED AND +;USED FOR ADDITIONAL "LOW HALF" PAGES. +; +;FDDTPG TO 256K CONTAINS DDT AND THE SYSTEM SYMBOL TABLE. +; +;PAGES ABOVE 256K ARE IN THE "HIGH MOBY". +; +;PAGES NOT IN THE "LOW HALF" (BELOW LIOBLK, SHADOWED BY EXEC, OR HIGH MOBY) +;ARE CONSIDERED TO BE IN THE "HIGH HALF". USER PAGES PREFER TO GO HERE. +; +;COMPLICATIONS: +; IF USEMDM IS OFF, THE DIRECT MAPPED PAGES IN THE HIGH HALF +; OF THE LOW MOBY ARE CONSIDERED HIGH RATHER THAN LOW. THIS IS USED +; MOSTLY FOR DEBUGGING, TO CATCH REFERENCES TO RANDOM ADDRESSES. +; THERE CAN BE HOLES IN MEMORY (NXM). +; +;THE MEMBLT TABLE HAS ONE WORD FOR EACH 1K BLOCK OF MEMORY. +;IT SAYS WHAT THAT BLOCK IS USED FOR AND CONTAINS LINKS TO OTHER +;BLOCKS AND OTHER TABLES. THE MEMPNT AND MMSWP TABLES ALSO CONTAIN +;ONE WORD PER BLOCK AND CONTAIN ADDITIONAL INFORMATION. + +FDDTPG: 0 ;# OF LOWEST BLOCK USED BY DDT & SYMTAB (SET AT STARTUP) + +MEMFR: 0 ;# OF FREE BLOCKS IN ALL OF MEMORY. + +LMEMFR: 0 ;# OF FREE BLOCKS IN LOW LIST (MEMFP). + +MINCOR: 8 ;TRY TO KEEP THIS MANY PAGES FREE IN LOW MEMORY + ;MUST BE >= 3, SINCE LESSER-PRIORITY CONSUMERS OF + ;MEMORY WAIT IF LMEMFR IS < 3. + +MEMFP1: 0 ;LIST (THREADED THROUGH MLO, TERMINATED BY 0) + ;OF BLKS THAT BECAME FREE WHILE MEMFRZ WAS LOCKED. + +MEMHPT: 0 ;FREE LIST OF HIGH HALF PAGES AND HIGH MOBY PAGES + ;AND SHUFFLEABLE LOW HALF PAGES. MUST BE AT MEMFP-1. +MEMFP:: +MEMBLT: 0 ;FREE LIST POINTER FOR LOW PGS AND ALSO WD FOR BLOCK 0 + BLOCK TSYSM-1 .SEE BEGF0 ;FILLS THIS IN + +;FIELDS IN MEMBLT ENTRY: +;4.9 FREEZE OR ALLOC INHIBIT +;IF 4.9=1, DONT SET UP ANY MORE EXEC PGS POINTING TO THIS ONE +MUR==360500 ;4.4-4.8 USAGE CODE + MURUSR==1 ;USER PAGE, MMMPX=MMP INDEX + MUEX==2 ;EXEC (?) + MUIOB==3 ;200 WD BUFFERS, MNUMB=FIRST IOBFT ENTRY IN BLOCK + MUFR==4 ;FREE + MUINP==5 ;IN PROCESS OF BEING ALLOCATED + MUMGB==6 ;MAG TAPE BUFFER, MNUMB=TAPE NO+EOF BIT, MWC=WORD COUNT + MUMMP==7 ;MMP TABLE + MUDISB==10 ;340 DISPLAY BUFFER + MUFRT==11 ;BLOCK RETURNING TO FREE WHEN MEM LOCKED + MU23B==12 ;DISK BUF, MWC=WORD COUNT, MNUMB=CHANNEL + MU23UD==13 ;DISK USER DIR, MNUMB=QSNUD SLOT + MU23MD==14 ;DISK MASTER DIR + MU23TT==15 ;DISK TUT MNUMB=DISK NO. + MU23LS==16 ;DISK COPY OF USER DIR FOR LISTING + MUHOLE==17 ;"HOLE" IN REAL MEM + MUDDT==20 ;"DDT" PAGE + MUNET==21 ;NETWORK "BIG" BUFFER + MUSWPG==22 ;PAGE IN SWAPPING QUEUE, MMMPX=MMP INDEX + MUCHA==23 ;CHAOS NET BUFFERS + MU23FB==24 .SEE QSFBT ;DISK FREED-BLOCKS TABLES + MUPKT==25 ; Net packet buffers + MUDVB==26 ;Semi-static device IO buffer page +;ADD NEW MUR TYPES HERE ^ +MURMAX==27 ;HIGHEST VALID CODE + 1 + +MWC==221400 ;3.1-4.3 WORD COUNT IN I/O BUFFERS + +MLU==221400 ;3.1-4.3 LINK UP FOR DOUBLY-THREADED FREE LIST + +MNUMB==140600 ;2.4-2.9 MAGIC NUMBER SEE COMMENTS UNDER MUR ABOVE + +MMMPX==142200 ;2.4-4.3 MMP INDEX IN USER PGS + SWAP BUFFERS + +MLO==001400 ;1.1-2.3 LINK TO NEXT PAGE IN A LIST + ;0 = END OF LIST + ;UNLIKE IOLO AND PREVIOUS VERSION OF MLO, THERE ARE NO MAGIC NEGATIVE CODES + ;N.B.: MLO MUST BE AT RIGHT-HAND END OF WORD - CODE DEPENDS + +MEMPNT: BLOCK TSYSM ;RH USED FOR CIRC MEM USE PNTR IF USER MEM + ;LH FOR DISK ADDRESS CAME FROM OR GOING TO + ;MEMPNT HAS BLOCK NUMBER + ;DISK NUMBER COMES FROM CHANNEL LINKED TO + ;CIRCULAR PAGE LINK FORM + ;2.9=0 + ;1.1-1.8 PAGE # + ;2.8-1.9 USER # + ;2.9=1 + ;2.8=0 2.7-1.1 LINK TO MMP TABLE + ;2.8=1 2.7-1.1 LINK TO MEM PNT TABLE + ;EXCEPT 2.9-1.1=777777 => ABSOLUTE PAGE, NOT LINKED + +MMSWP: BLOCK TSYSM ;IF USER MEM, HAS NUMBER OF PAGE TABLE WORDS + ; WHICH POINT AT THIS PAGE. LH IS NUMBER OF EXEC + ; PAGES, RH IS NUMBER OF USER PAGES. NOTE THAT THE + ; NUMBER OF UPGCP ENTRIES COULD BE MORE, FOR VARIOUS + ; REASONS, E.G. CIRPSW LOCKED WHEN PAGE SWAPPED IN, + ; OR A USER WAS SWAPPED OUT. + ;IFN SWPWSP, RH(MMSWP) IS USED AS NUMBER OF SHARERS. + +EMEMTL==.-1 ;END FOR GETSYS (MEMORY) + +MMPRTC: 0 ;C AT MMPRTN, FOR DEBUGGING + +MMPFS: 0 ;FREE-LIST OF MMP ENTRIES. VALUE IS ADDRESS. (FORMERLY WAS IDX). + +MMPFS2: 0 ;LIST OF MMPS THAT NEED TO HAVE TUT SOS'ED BEFORE THEY CAN BE FREED. + ;TUT COULDN'T BE SOS'ED AT P.I. LEVEL BECAUSE IT WAS LOCKED. + ;THESE MMPS MAY ALSO NEED TO BE REMOVED FROM THE SHAREABLE + ;PAGE TABLE, WHICH REQUIRES CIRPSW. + +MMPCNT: 0 ;# OF MMP ENTRIES IN USE. + +MMPFR: NMMP*1000 ;MAX POSSIBLE # MMP ENTRIES, MINUS # IN USE OR COMMITTED. + +;MMP TABLE - TWO WDS PER ENTRY +MMPPUB==400000 ;WD1 4.9 INDICATES A PUBLIC PAGE IF ON (ANYONE CAN ATTACH TO WRITE) +MMPOUT==200000 ;4.8 => PAGE IS SWAPPED OUT OR ON WAY OUT. +MMPTMP==100000 ;4.7 => IN TRANSIT (ON WAY IN OR ON WAY OUT). +MMPWOD==40000 ;4.6 => THIS PAGE HAS BEEN WRITTEN ON DISK AT LEAST ONCE +MMPISW==20000 ;4.5 PAGE ON INITIAL SWAPIN, BEING COPIED SO SWAP OUT TO DIFF PLACE +MMPWRT==10000 ;4.4 HAS BEEN WRITTEN SINCE LAST DISK WRITE BY USER WHO HAS DETACHED THIS PAGE +MMPGON==4000 ;4.3 FILE PAGE BEING WRITTEN OUT AFTER + ;DELETED FROM ALL MAPS (MMP ENTRY WILL SOON GO AWAY.) +MMPBAD==2000 ;4.2 PAGE GOT PAR ERR SINCE LAST TIME SWAPPED OUT OR IN. +MMPLOK==1000 ;4.1 => PAGE MAY NOT BE SWAPPED OUT. +MMPSLO==400 ;3.9 => PAGE SHOULD GO IN SLOW MEMORY. +MMPSHR==200 ;3.8 MMP ENTRY IS IN SHAREABLE PAGE HASH TABLE +MMPPGA==100 ;3.7 BEING SWAPPED IN BY PAGE-AHEAD. DON'T PUT IN USER MAPS; WAIT FOR FAULTS. +MMPPGB==40 ;3.6 BEING SWAPPED OUT BY PAGE-BEHIND. +$MMPUN==220300 ;3.1-3.3 UNIT NUMBER (GOES WITH DISK ADDR IN WD2 LH) + ;WD1 RH CIRC MEM USE PNTR + ;WD2 LH READ DISK ADR OR 0 + ;WD2 RH THREAD FOR SHAREABLE PAGE HASH TABLE + +MMPNP: 0 ;#MMP PGS ACTUALLY IN USE +MMPMX: 0 ;HIGHEST VALID MMP INDEX (MMPNP*2000) + +MMMPG: BLOCK NMMP ;BLOCK NOS OF BLOCKS ACTUALLY USED + +;SHAREABLE PAGE HASH TABLE +;MMP ENTRIES THAT ARE SHARED WITH FILES ARE LISTED HERE TO SAVE TIME AT NCORQ2 +;SIMPLE REMAINDER HASH ON UNIT#,,DISK ADDRESS, +;BUCKETS THREADED THROUGH RH(MMPE+1) + +SHRHSL==31. ;NUMBER OF BUCKETS +SHRHSH: BLOCK SHRHSL + +;"LOOSE" PAGES (NOT USED BY ANY USER, BUT NOT YET SWAPPED OUT.) +;MMP ENTRY GOES AWAY WHEN SWAPPED OUT, OR GETS PUT BACK INTO SERVICE AT NCORQ3. +NLOOSP: 0 ;NUMBER OF LOOSE PAGES +FLOOSP: 0 ;HEAD OF LIST. THREADED THROUGH MLO IN MEMBLT. +LLOOSP: 0 ;TAIL OF LIST. ADD AT TAIL, SWAPPER REMOVES FROM HEAD. + +BBLK +MMPEAD: REPEAT NMMP, CONC MMP,\.RPCNT,*2000+400000 ;EXEC ADR +MMPPPP: REPEAT NMMP, CONC .MMP,\.RPCNT,+EXEUMP ;PNTR TO EXEC PC MP +USEMDM: DIRMAP ;NON-ZERO => USE MEDIUM MEMORY. + ;DON'T CHANGE AFTER SYSTEM STARTUP + +SUBTTL 200-WORD I/O BUFFER ROUTINES + +;SYS CHANNEL ASSIGN +; 77=>FREE +; 0 - NUTIC+NUTOC-1 => UTAPE CHNL +;NUTIC+NUTOC (=NFCLC-1) =>UTAPE FILE DIR +;NFCLS-NFCLC+NCLCH-1 (=NFNETC-1) => CORE LINK +;NFNETC-NNETCH => NETWORK + +IOBCNS: MOVEI A,IOBFP-IOBFT +IOBC1: MOVE E,A + LDB A,[IOLO,,IOBFT(A)] + CAIN A,377 + JRST 4,. ;IOBFT POINTERS FOULED UP + +IOBC2: LDB B,[420200,,IOBFT(A)] + JUMPN B,IOBC1 + LDB B,[IOLO,,IOBFT(A)] + DPB B,[IOLO,,IOBFT(E)] + SOS IOBFC + POPJ P, + + +IOBR: MOVE B,IOBFP ;RETURN IOBFT WORD + CLEARM IOBFT(A) + DPB B,[IOLO,,IOBFT(A)] + MOVEM A,IOBFP + MOVEI B,77 + DPB B,[IOCH,,IOBFT(A)] + AOS IOBFC + POPJ P, + +IUTCONS: ;ALLOCATE 200 WORD BUFFER +IUTCO1: PI2SAF + SKIPG UTTBF ;CLOBBERS A B E TT, RETURNS IOBFT INDEX IN A + JRST IUTC1 ;NO UTAPE BUFFERS FREE + MOVEI E,UTFS-IOBFT + MOVE A,UTFS ;CHNL NO IN D +IUTC3: CAIN A,377 + JRST IUTC1 + LDB B,[420200,,IOBFT(A)] + JUMPN B,IUTC2 + LDB B,[IOCH,,IOBFT(A)] + CAIE B,77 + JRST 4,. ;BUFFER BEING ALLOCATED ISN'T FREE. + LDB B,[IOLO,,IOBFT(A)] + DPB B,[IOLO,,IOBFT(E)] + DPB D,[IOCH,,IOBFT(A)] + SOS UTTBF + JRST POPJ1 + +IUTC2: MOVE E,A + LDB A,[IOLO,,IOBFT(A)] + JRST IUTC3 + +IUTC1: PUSHJ P,UIMRQ + POPJ P, + PUSHJ P,UTMGB + JRST IUTCO1 + +IBRTN: PI2SAF + PUSH P,B ;FREE 200 WORD BUFFER (SEE BRTN) +; LDB B,[IOCH,,IOBFT(A)] +; CAIN B,77 +; JRST 4,. ;RETURNING A BUFFER THAT'S FREE? + MOVE B,UTFS + DPB B,[IOLO,,IOBFT(A)] + MOVEM A,UTFS + MOVEI B,77 + DPB B,[IOCH,,IOBFT(A)] + LDB B,[IOSA,,IOBFT(A)] + SKIPN B + JRST 4,. + AOS UTTBF + JRST POPBJ + +UTMGB: PUSH P,J ;GOBBLE MEM BLK IN A FOR UTAPE BUFFER + PUSH P,R + PUSH P,Q + PUSH P,B + PUSH P,E + MOVEI B,MUIOB + DPB B,[MUR,,MEMBLT(A)] + MOVE J,A + LSH A,10.-6. ;CONV TO BUF SA + MOVE TT,A ;INCR TO NEXT BUF ADR + MOVEI R,8 + ADDM R,UTTLB ;UTTBF AOSED AT IBRTN + MOVNI Q,1 +UTMG1: PUSHJ P,IOBCNS + DPB TT,[IOSA,,IOBFT(A)] + JUMPL Q,UTMG2 + DPB A,[IOLC,,IOBFT(Q)] +UTMG3: MOVE Q,A + PUSHJ P,IBRTN + ADDI TT,2 + SOJG R,UTMG1 + MOVEI TT,377 + DPB TT,[IOLC,,IOBFT(A)] + POP P,E + POP P,B + POP P,Q + POP P,R + POP P,J +FSCMP: ;RECOMPUTE UTAPE BUFFER FAIR SHARE +IFN NUNITS,[ + MOVE A,UTTLB + PUSH P,A+1 + IDIV A,NUTCA + POP P,A+1 + MOVEM A,UPCHFS +] + POPJ P, + +UTMG2: DPB A,[MNUMB,,MEMBLT(J)] + JRST UTMG3 + +BRTN: CONO PI,UTCOFF ;RETURN A 200-WD BUFFER + PUSHJ P,IBRTN + JRST UTCONJ diff --git a/src/system/dc10.defs27 b/src/system/dc10.defs27 new file mode 100755 index 00000000..618dc86c --- /dev/null +++ b/src/system/dc10.defs27 @@ -0,0 +1,270 @@ +.AUXIL + +IFNDEF DEFSYM,[ ;ALLOW USER TO USE SYMBOLS IN OTHER WAYS IF HE WISHES. + ;BUT NORMALLY, DEFSYM FOO==BAR DOES FOO==BAR WITH ERROR CHECK. +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ + $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` +] +.ISTOP +TERMIN TERMIN + +IFLE .MLLIT,.ERR .MLLIT MUST BE 1; SETTING IT TO 1. +.MLLIT==1 +$$TEMP==1 +] +.ELSE $$TEMP==0 + + +;SYSTEMS CONCEPTS DC10 PHYSICAL CHARACTERISTICS + +DEFSYM NCYLS==400. ;# CYLINDERS NORMALLY USED +DEFSYM XCYLS==6 ;# EXTRA CYLINDERS FOR SPARES, HACKS, ETC. +DEFSYM NHEDS==20. ;# TRACKS/CYLINDER +DEFSYM NSECS==2 ;# BLKS/TRK +DEFSYM SECBLK==1 ;# SECTORS/BLOCK +DEFSYM NBLKSC==NHEDS*NSECS ;# BLKS/CYL +DEFSYM NBLKS==NCYLS*NBLKSC ;TOTAL # REG BLKS +DEFSYM XBLKS==XCYLS*NBLKSC ;# XTRA BLKS +DEFSYM TBLKS==NBLKS+XBLKS ;TOTAL BLOCKS + +DEFSYM NTUTBL==2 ;2 BLOCKS PER TUT (DUAL-DENSITY CALCOMPS THESE DAYS) +DEFSYM DECADE==20. ;NUMBER OF BLOCKS TO ALLOCATE AT A TIME + ;QSWAPA AND QLASTB MUST BE MULTIPLES OF THIS + +;EXTRA WORDS IN BLOCK + +DEFSYM XWBWC==0 +DEFSYM XWBLK==1700,, ;BP TO PREV BLK # IN FILE FLD +DEFSYM XWAWC==171200,, ;BP TO ACTIVE WD CNT +DEFSYM XWSYSN==1 +DEFSYM XWFN1==2 +DEFSYM XWFN2==3 +DEFSYM NXWDS==4 ;NUMBER OF EXTRA WORDS + +DEFSYM DC0==610 ;MAIN DEVICE CODE +DEFSYM DC1==614 ;READS ERR STATUS ETC, SETS TIMER DRIVER # ON CONO + +;FIELDS IN HEADER WORD 0 + +DEFSYM DPKID==240700,, ;PACK ID FIELD +DEFSYM DCYL==131100,, ;CYLINDER CHECK FIELD +DEFSYM DSURF==60500,, ;SURFACE CHECK FIELD +DEFSYM DSECT==600,, ;SECTOR FIELD + +;WORD 1 HEADER + +DEFSYM DHIND==1000,, ;4.1 INDIRECT IF 1, CYL, SURF, SECTOR SAME AS ABOVE +DEFSYM DHSPRT==400,, ;BIT 3.9 SOFTWARE PROTECT +DEFSYM DHHPRT==200,, ;3.8 HARDWARE PROTECT +DEFSYM DHNXAD==270200,, ;3.7, 3.6 HOW TO COMPUTE NEXT DISK ADR + ;=00 ADD 1 TO SECTOR + ;01 SET SECTOR TO 0, ADD 1 TO SURF + ;10 SET SECTOR AND SURFACE TO 0, ADD 1 TO CYL + ;11 END OF DISK +DEFSYM DHEPB==10,, ;PARITY BIT FOR EVEN BITS OF 56 BIT HEADER +DEFSYM DHOPB==4,, ;PARITY BIT FOR ODD BITS OF 56 BIT HEADER +DEFSYM DHSLNG==1600,, ;-LENGTH OF SECTOR FIELD + +;DISK ADDRESS DATA COMMANDS (OP CODES) + +DEFSYM DRC==400000,, ;READ COMPARE +DEFSYM DWRITE==440000,, ;WRITE +DEFSYM DREAD==500000,, ;READ +DEFSYM DSEEK==540000,, ;SEEK +DEFSYM DRCC==600000,, ;READ COMPARE CONTINUOUS +DEFSYM DWRITC==640000,, ;WRITE CONTINUOUS +DEFSYM DREADC==700000,, ;READ CONTINUOUS + +DEFSYM DUNENB==20000,, ;ENABLE LOAD UNIT FIELD +DEFSYM DUNFLD==330400,, ;UNIT FIELD +;PKID, CYL, SURF, AND SECTOR SAME AS ABOVE + +;COPY / COMPARE / SKIP COMMAND + +DEFSYM DCOPY==40000,, ;COPY +DEFSYM DCCOMP==100000,, ;COMPARE +DEFSYM DCSKIP==140000,, ;SKIP + +DEFSYM DCWC==241400,, ;-WC FIELD +DEFSYM DCCA==2400,, ;CORE ADDRES +DEFSYM DCBN==121200,, ;BLOCK NUMBER + +;JUMP COMMANDS +DEFSYM DHLT==0 ;0 IN 4.9-4.5 = JUMP AND IN 3.5,3.6 = HALT +DEFSYM DXCT==20,, ;XCT +DEFSYM DJMP==40,, ;JUMP +DEFSYM DJSR==60,, ;JSR + +;"B" COMMAND BITS 3.3, 3.4 +;0 ALWAYS +DEFSYM DAOJNC==4,, ;AOJN THE CONTROL COUNTER +DEFSYM DDOK==10,, ;ON NO DATA ERROR +DEFSYM DSRQF==14,, ;IF SEEK RQ FLAG ON + +;STORE REGISTER COMMAND +DEFSYM DSREG==240400,, ;STORE REG +;USE, UNIT BITS SAME +DEFSYM DSREGS==240300,, ;SOURCE REGISTER SELECT FIELD +DEFSYM DSRDB==0 ;STORE DATA BUFFER +DEFSYM DSRDL==4,, ;STORE DISK LOCATION +DEFSYM DSRCC==10,, ;STORE COMMAND COUNT +DEFSYM DSRPC==24,, ;STORE PC (IN FORM OF JMP INST.) +DEFSYM DSRWC==30,, ;STORE WORD COUNT +DEFSYM DSRCA==34,, ;STORE CORE ADDRESS (TO XFER DATA TO OR FROM) + +;ALU COMMAND +DEFSYM DALU==300000,, ;BASIC ALU OP CODE +DEFSYM DALUX==40000,, ;INDEX BIT (ADD CC TO ADR) +DEFSYM DALUD==40,, ;DIRECT BIT IF 1, REF MEM OT GET B OP + +DEFSYM DASL==4000,, ;SKIP ON <0 +DEFSYM DASE==10000,, ;SKIP ON = 0 +DEFSYM DASLE==14000,, ;SKIP ON < OR = 0 +DEFSYM DASA==20000,, ;ALWAYS SKIP +DEFSYM DASGE==24000,, ;SKIP ON > OR = 0 +DEFSYM DASN==30000,, ;SKIP ON NOT = 0 +DEFSYM DASG==34000,, ;SKIP ON > 0 + +;DESTINATION SUB OP (ALSO SPECIFIES SOURCE A) +DEFSYM DLDB==0 ;OP A FROM DB, STORE IN DB +DEFSYM DLDL==4,, ;OP FROM DL, STORE IN DL +DEFSYM DLCC==10,, ;OP FROM CC, STORE IN CC +DEFSYM DLCA==14,, ;OP A =0, STORE IN CA +DEFSYM DLTDB==20,, ;TEST DB (OP A FROM DB, NO STORE) +DEFSYM DLDBPC==24,, ;OP A FROM DB, STORE IN PC +DEFSYM DLDBWC==30,, ;OP A FROM DB, STORE IN WC +DEFSYM DLDBM==34,, ;OP A FROM DB, STORE IN MEM (DIRECT MUST BE ONE TO REALLY MAKE IT) + +;SOME USEFUL (?) OPS +DEFSYM DLADD==100,, ;A+B +DEFSYM DLSOS==200,, ;B-1 +DEFSYM DLLB==300,, ;B +DEFSYM DLSUB==400,, ;B-A + +DEFSYM DLAND==2300,, ;A&B +DEFSYM DLIOR==2500,, ;A IOR B +DEFSYM DLLA==3100,, ;LOAD A +DEFSYM DLSETO==3200,, ;-1 +DEFSYM DLSETZ==3300,, ;0 + +;OPR COMMAND +DEFSYM DOPR==200000,, ;BASIC OPR +DEFSYM DOHXFR==400,, ;HALT DURING XFER (SO MB WILL BE SAFE) +DEFSYM DOCSRQ==200,, ;CLEAR SEEK RQ +DEFSYM DOSSRQ==100,, ;SET SEEK RQ +DEFSYM DOSCFL==40,, ;SET C FLAG + +;STORE DRIVE STATUS +DEFSYM DSDRST==240000,, ;STORE DRIVE STATUS +;UNIT ENABLE, UNIT FIELD SAME +DEFSYM DSDCNT==240400,, ;COUNT-1 FIELD + +;BITS IN DRIVE STATUS STORED + +DEFSYM DDSWC==40,, ;WRITE CURRENT SENSED +DEFSYM DDSUNS==20,, ;DRIVE UNSAFE +DEFSYM DDSRDO==10,, ;READ ONLY +DEFSYM DDSSIC==4,, ;SEEK INCOMPLETE +DEFSYM DDSRDY==2,, ;DRIVE READY +DEFSYM DDSONL==1,, ;DRIVE ON LINE +DEFSYM DDSSEL==400000 ;DRIVE SELECTED +DEFSYM DDSCYL==101000,, ;PRESENT CYLINDER +DEFSYM DDSLAT==1000,, ;LATENCY TIMER + +;DISK ADR "SPECIAL COMMAND" + +DEFSYM DSPC==740000,, ;BASIC OP CODE +;USE, UNIT FIELDS AS NORMAL + +; E CONDITION (WAIT) +;0 NONE +DEFSYM DSWIDX==20,, ;WAIT UNTIL INDEX PULSE +DEFSYM DSWSEC==40,, ;WAIT UNTIL SECTOR PULSE +DEFSYM DSWINF==60,, ;NEVER (USE WITH G=3 OR 7) + +; F CONDITION (OTHER WAIT) +DEFSYM DSWHDM==0 ;WAIT FOR MATCHING HEADER +DEFSYM DSWAGH==4,, ;ANY GOOD HEADER +DEFSYM DSWAH==10,, ;ANY HEADER +DEFSYM DSWNUL==14,, ;NO WAIT + +;G OPERATION +DEFSYM DSCRDC==0 ;READ DATA THRU DECODERS +DEFSYM DSCRIM==100,, ;READ DATA IMAGE +DEFSYM DSCRHD==200,, ;READ HEADER WORDS +DEFSYM DSRCAL==300,, ;(RECALIBRATE) +DEFSYM DSCWDC==400,, ;WRITE THRU DECODERS +DEFSYM DSCWIM==500,, ;WRITE IMAGE +DEFSYM DSMAIT==700,, ;MAINTENANCE (PUT CYL FIELD ON BUS LINES WITH CONTROL TAG) + +;BITS IN CONI DC0, +DEFSYM DASSGN==400000,, ;ASSIGNED TO PROC (WITH SWITCH) +DEFSYM DPIRQC==400000 ;PI REQ BEING GENERATED +DEFSYM DSSRQ==200000 ;SEEK REQUEST +DEFSYM DSDEEB==10000 ;ENABLE INTERRUPT ON DATA ERROR OR READ/ COMP ERROR +DEFSYM DSSERR==4000 ;ERROR FLAG +DEFSYM DSSAEB==2000 ;ATTENTION ENABLE FLAG +DEFSYM DSSATT==1000 ;ATTENTION FLAG +DEFSYM DSIENB==400 ;IDLE FLAG ENABLE +DEFSYM DSSRUN==200 ;RUN +DEFSYM DSSACT==100 ;ACTIVE +DEFSYM DSSCEB==40 ;CHANNEL ENABLE +DEFSYM DSSCHF==20 ;CHANNEL FLAG +DEFSYM DSSCFL==10 ;CPU FLAG +;PIA 1.3-1.1 + +;DATAO DC0, SENDS COMMAND TO DISK +; (IGNORED IF EXECUTING COMMANDS FROM MEMORY) + +;CONO DC0, +DEFSYM DCSET==400000 ;SET SELECTED +DEFSYM DCCLR==200000 ;CLEAR SELECTED +DEFSYM DCCSET==600000 ;RESET CONTROLLER THEN SET SELECTED +DEFSYM DCDENB==10000 ;DATA ERROR ENABLE +DEFSYM DCERR==4000 ;SET ERROR FLAG OR CLEAR ALL ERRORS +DEFSYM DCATEB==2000 ;ATTENTION ENABLE +DEFSYM DCCATT==1000 ;CLEAR ATTENTION +DEFSYM DCSSRQ==1000 ;SET SEEK REQUEST +DEFSYM DCIENB==400 ;IDLE ENABLE +DEFSYM DCSTAR==200 ;START (SET) +DEFSYM DCSSTP==200 ;STOP (CLEAR) +DEFSYM DCSGL==100 ;DO SINGLE COMMAND +DEFSYM DCCENB==40 ;CHANNEL ENABLE +DEFSYM DCCFLG==20 ;CHANNEL FLAG +DEFSYM DCCPUF==10 ;CPU FLAG +;1.1-1.3 PIA + +;CONO DC1, + +;SET TIMER DRIVE # FROM 1.1-1.3 + +;CONI DC1, +;LH +DEFSYM DSATDN==360400,, ;ATTENTION DRIVE # +DEFSYM DSTMDN==320400,, ;TIMER DRIVE # +DEFSYM DSLAT==221000,, ;LATENCY TIMER FOR DRIVE ABOVE + +;RH (ERROR FLAGS) +DEFSYM DIPE==4000 ;INTERNAL PARITY ERROR +DEFSYM DRLNER==2000 ;RECORD LENGTH +DEFSYM DRCER==1000 ;READ COMPARE ERROR +DEFSYM DOVRRN==400 ;OVERRUN +DEFSYM DCKSER==200 ;CKSUM OR DECODER ERR +DEFSYM DWTHER==100 ;WATCHDOG TIMER +DEFSYM DFUNSF==40 ;FILE UNSAFE, SEEK INCOMPLETE OR END OR DSK +DEFSYM DOFFL==20 ;OFF LINE OR MULT SEL +DEFSYM DPROT==10 ;WRT KEY OR RD ONLY OR PROTECT +DEFSYM DDOBSY==4 ;DATAO WHEN BSY +DEFSYM DNXM==2 ;NON-EX MEM +DEFSYM DCPERR==1 ;CORE PARITY ERR + +DEFSYM LRIBLK==16 ;CONSISTENCY CHECK DSKDMP VS MARK + + +IFN $$TEMP,EXPUNG DEFSYM + \ No newline at end of file diff --git a/src/system/ddt.68 b/src/system/ddt.68 new file mode 100755 index 00000000..fbbfe57b Binary files /dev/null and b/src/system/ddt.68 differ diff --git a/src/system/ddtdsk.31 b/src/system/ddtdsk.31 new file mode 100755 index 00000000..e20ecf60 Binary files /dev/null and b/src/system/ddtdsk.31 differ diff --git a/src/system/disk.1224 b/src/system/disk.1224 new file mode 100755 index 00000000..fc5eedaa --- /dev/null +++ b/src/system/disk.1224 @@ -0,0 +1,6412 @@ +; I T S DISK SERVICE ROUTINES AND FILE SYSTEM -*-MIDAS-*- + +DSKVRS==.IFNM2 +IFN DC10P+RP10P+RH10P+RH11P-1, .ERR WRONG NUMBER OF DISK CONTROLLERS + +;GET DISK PHYSICAL PARAMETERS BY .INSRT'ING APPROPRIATE FILE + +IFN DC10P,[ +$INSRT DC10 +] + +IFN RP10P,[ +$INSRT RP10 +] + +IFN RH10P,[ +$INSRT RH10 +] + +IFN RH11P,[ +$INSRT RH11 +IFE KS10P, .ERR RH11 on something other than a KS10? +IFN RP06P+RP07P+RM03P+RM80P-1, .ERR WRONG NUMBER OF KINDS OF DISK DRIVE +IFN RP06P,[ +$INSRT RP06 +] +IFN RP07P,[ +$INSRT RP07 +] +IFN RM03P,[ +$INSRT RM03 +] +IFN RM80P,[ +$INSRT RM80 +] +] + +;GET FILE SYSTEM DEFINITIONS: +; MFD MASTER FILE DIRECTORY +; TUT TRACK (BLOCK) UTILIZATION TABLE +; UFD USER FILE DIRECTORY + +$INSRT FSDEFS + +IFN T300P,[ +$INSRT T300 +] + +SUBTTL MISC FILE SYSTEM CALLS + +ADMPCH: UMOVE A,(J) ;SET OR READ STATUS OF DUMP BIT OF FILE OPEN ON + ; CHNL IN AC(RH) + MOVEI T,POPJ1 ;MAKE CHNDCD SKIP RETURN IF ALL OK. + PUSHJ P,CHNDCD ;DECODE RH(A) AS CHNL NUM. + JRST ILUUO ;NO SKIP IMPLIES BAD CHNL NUM. + TLNN R,%CLSQ + JRST ILUUO ;NOT DISK CHANNEL. + PUSHJ P,QCHNLT ;DECODE THE CHNL FURTHER. + MOVSI B,400000 + TLNE A,400000 + IORM B,UNRNDM(C) + TLNE A,200000 + ANDCAM B,UNRNDM(C) + MOVE D,QACTB + TLNE A,600000 + IORM D,QSNLCN(H) + LDB A,[430100,,UNRNDM(C)] + PUSHJ P,QUDULK + JRST APTUAJ + +NRFDATE: PUSHJ P,QCHNLT ;READ FILE CREATION DATE WORD + MOVE A,UNDATE(C) +NRDM1: PUSHJ P,QUDULK + JRST POPJ1 ;STORE BACK IN USER MEM + +NSRDATE: PUSHJ P,QCHNLT ; SET REFERENCE DATE + HLRS B + DPB B,[UNREFD+UNREF(C)] + JRST NSDM1 + +NRESRDT: PUSHJ P,QCHNLT ; RESTORE REFERENCE DATE + HLRZ A,OLDRDT(R) ; WHOEVER CHOSE R IN QCHNLC SHOULD BE SHOT + DPB A,[UNREFD+UNREF(C)] + JRST NSDM1 + +NSFDATE: PUSHJ P,QCHNLT ;SET FILE CREATION DATE WORD + MOVEM B,UNDATE(C) +NSDM1: MOVE TT,QACTB + IORM TT,QSNLCN(H) +QUDUL1: AOS (P) + JRST QUDULK + + +NRDMPBT: PUSHJ P,QCHNLT ;READ FILE DUMPED BIT + LDB A,[430100,,UNRNDM(C)] + JRST NRDM1 + +NSDMPBT: PUSHJ P,QCHNLT ;SET FILE DUMPED BIT + DPB B,[430100,,UNRNDM(C)] + JRST NSDM1 + +NLNKEDP: + PUSHJ P,QCHNLT ;RETURN NONZERO IF WE TRACED LINKS TO GET THIS FILE. + MOVE T,QSRAC(R) + LDB A,[.BP (%QALOP),T] + JRST NRDM1 + +NFILBLK:PUSHJ P,QCHNLT ;READ ALL 5 PARAMETERS OF NAME AREA + MOVE A,(C) + MOVE B,1(C) + MOVE D,3(C) + MOVE E,4(C) + MOVE C,2(C) + JRST NRDM1 ; UNLOCK DIR AND STORE ARGUMENTS + +QCHNLT: TLNN R,%CLSQ ;IS CHNL A DISK CHNL? + JRST [SUB P,[1,,1] ? JRST OPNL34] + HLRZ R,H + MOVE H,QUDPR(R) + PUSHJ P,QUDLK + MOVE C,QSNLCN(H) + ADD C,QUDFPR(R) + POPJ P, + +IFN QAUTHP,[ +ASAUTH: PUSHJ P,QCHNLT ;SET AUTHOR OF FILE + PUSH P,C + JUMPE B,ASAUT4 ;SETTING AUTHOR TO 0 + MOVE J,QSNMI(H) + CAMN B,QSNUD(H) + JRST ASAUT1 + MOVE C,B + PUSHJ P,QFL + SKIPA + JRST ASAUT1 + SETZM C + MOVEI J,5 + MOVE TT,[440600,,B] + MOVE I,[440600,,C] + ILDB D,TT + IDPB D,I +ASAUT2: ILDB D,TT + CAIG D,'Z + CAIGE D,'A + JRST ASAUT3 + IDPB D,I + SOJG J,ASAUT2 + JRST ASAUT4 + +ASAUT3: PUSHJ P,QFL +ASAUT4: SETOM J +ASAUT1: POP P,C + DPB J,[UNAUTH+UNREF(C)] + JRST NSDM1 + +ARAUTH: PUSHJ P,QCHNLT ;READ CREATOR OF FILE + LDB B,[UNAUTH+UNREF(C)] + MOVEI A,0 ;RETURN VALUE IS 0 IF UNKNOWN OR ILLEGAL AUTHOR + CAIL B,NUDSL + JRST NRDM1 + LSH B,1 + MOVEI B,2000-(B) + ADD B,QMDRO + MOVE A,(B) + JRST NRDM1 +];QAUTHP + +ASREAP: PUSHJ P,QCHNLT ;SET NO REAP BIT + DPB B,[.BP (UNREAP),UNRNDM(C)] + JRST NSDM1 + +ARQDAT: CONO PI,CLKOFF ;GET DSK TIME AND DATE + SKIPL A,QDATE + HRR A,TIMOFF + MOVE B,QDATEI ;2ND VALUE = DATE & TIME SYS CAME UP, IN DISK FORMAT. + CONO PI,CLKON + JRST POPJ1 + +ADSKUP: PUSHJ P,QCHNLT ;SET CREATION DATE, REF DATE AND CLEAR DUMP BIT + CONO PI,CLKOFF + SKIPL TT,QDATE + HRR TT,TIMOFF + CONO PI,CLKON + MOVEM TT,UNDATE(C) + HLRS TT + DPB TT,[UNREFD+UNREF(C)] + MOVSI TT,UNDUMP + ANDCAM TT,UNRNDM(C) + JRST NSDM1 + +DELEWO: TLNN R,%CLSQ ;DELETE WHILE OPEN + JRST OPNL34 ;WRONG TYPE DEVICE + PUSHJ P,QCHNLT + PUSH P,W + PUSH P,C + MOVEI W,4 + MOVE A,UNFN1(C) ;Get names of file being hacked. + MOVE B,UNFN2(C) + MOVE C,QSNUD(H) + PUSHJ P,MNGDIR ;If this is a sanctified dir + PUSHJ P,SYSDSK ; get SYS job to tattle about it. + POP P,C + POP P,W + MOVSI T,%QADEL ;SET DELETE BIT IN QSK CHNL + IORM T,QSRAC(R) + MOVSI T,UNCDEL ;AND IN FILE + IORM T,UNRNDM(C) + JRST NSDM1 + +;.CALL FILLEN +;RETURNS (1) FILE LENGTH IN BYTES (BYTE SIZE CURRENTLY OPEN IN) +; (2) BITS PER BYTE (BYTE SIZE CURRENTLY OPEN IN) +; (3) FILE LENGTH IN BYTES (BYTE SIZE WRITTEN IN) +; (4) BITS PER BYTE (BYTE SIZE WRITTEN IN) + +NFILLEN:PUSHJ P,QCHNLT + MOVE A,QSRAC(R) + TLNE A,%QALNK + JRST OPNL34 ;NOT A FILE + SKIPGE QSCRW(R) + TLNE A,%QAMWO + JRST NFILL1 ;READ CHANNEL OR WRITE-OVER, GET FILE'S STORED LENGTH. + MOVE A,QFBLNO(R);NORMAL WRITE, GET ACCESS POINTER. + SKIPGE QSMDN(R) + JRST NFILL2 ;NO BUFFER ACTIVE + ADD A,QMPBSZ(R) ;END OF CURRENT BUFFER + SUB A,QSMPRC(R) ;BACK UP TO CURRENT LOC +NFILL2: PUSHJ P,QUDULK + LDB B,[QSBSIZ(R)] ;CURRENT BYTE SIZE + MOVE D,B ;WRITTEN BYTE SIZE SAME AS CURRENT + MOVE C,A ;WRITTEN LENGTH SAME AS CURRENT + JRST POPJ1 + +NFILL1: LDB TT,[UNDSCP+UNRNDM(C)] + IDIVI TT,UFDBPW + HLL TT,QBTBLI(I) ;GET DESCRIPTOR POINTER + LDB E,[UNWRDC+UNRNDM(C)] + SKIPN E + MOVEI E,2000 ;E GETS NUMBER OF WORDS IN LAST BLOCK + LDB D,[UNBYTE+UNREF(C)] ;D GETS BYTE INFO + ANDI C,-2000 ;C GETS BASE ADDR OF DIR + ADDI TT,UDDESC(C) ;TT GETS DESC PNTR + SETOM A ;INITIALIZE NUMBER OF BLOCKS IN FILE + PUSHJ P,NFLLN1 ;A GETS NUMBER OF BLOCKS IN FILE MINUS ONE + PUSHJ P,QUDULK + IMULI A,2000 ;NUMBER OF WORDS IN COMPLETE BLOCKS + ADD A,E ;ADD WORDS IN LAST BLOCK + PUSHJ P,QBDCD ;D GETS BYTE SIZE, E NUMBER OF RESIDUE BYTES + MOVEI Q,36. + IDIV Q,D ;Q GETS BYTES PER WORD + MOVE C,A ;C WRITTEN LENGTH, A CURRENT (B.S. DIFFERENT) + IMUL C,Q ;CONVERT WORD LENGTH TO BYTES + SUB C,E ;C NOW HAS CORRECT WRITTEN LENGTH + IMUL E,D ;E GETS NUMBER OF RESIDUE BITS + LDB B,[QSBSIZ(R)] ;B GETS BYTE SIZE OPENED IN + IMULI A,@QSBYTE(R) ;A GETS LENGTH IN THOSE SIZE BYTES + IDIV E,B ;NUMBER OF RESIDUE BYTES, -ROUNDING DOWN- + SUB A,E ;ADJUST THE LENGTH + JRST POPJ1 ;RETURN VALUES IN A,B,C,D + +NFLLN2: ADD A,B ; NEXT N BLOCKS +NFLLN1: ILDB B,TT ; GET NEXT DESC BYTE + JUMPE B,CPOPJ ; NO MORE + CAIG B,UDTKMX + JRST NFLLN2 ; TAKE-N + CAIGE B,UDWPH + AOJA A,NFLLN1 ; SKIP-N, TAKE-1 + CAIN B,UDWPH + JRST NFLLN1 ; IGNORE WRITE-PLACEHOLDER +REPEAT NXLBYT, IBP TT ; LOAD-ADDRESS, TAKE-1 + AOJA A,NFLLN1 + +;DIRSIZ - READ OR SET DISK QUOTAS, READ # BLOCKS IN ALL FILES IN DIRECTORY. +;1ST VALUE IS GRIM REAP QUOTA,,DIR SIZE +;2ND VALUE IS 0 OR PACK#,,ALLOCATION FOR DIR ALLOCATED TO SPECIFIC PACK +;LH OF 2ND ARG SETS GRIM REAP QUOTA; 3RD ARG SETS PACK#,,ALLOCATION +NDIRSI: MOVE D,C + PUSHJ P,QCHNLT + MOVE C,QSNLCN(H) + MOVE A,UDBLKS(C) + JUMPL B,NDIRS1 + CAIE W,1 + HLLM B,UDBLKS(C) +NDIRS1: MOVE B,UDALLO(C) + CAILE W,2 + MOVEM D,UDALLO(C) +IFN QRSRVP,[ + HLRZS D ;PACK ALLOCATED TO + SETO E, + JUMPE D,NDIRS2 + MOVEI E,NQS-1 ;UPDATE ALLOC DRIVE NUM + CAME D,QPKID(E) + SOJGE E,.-1 +NDIRS2: MOVEM E,QSALLO(H) +];QRSRVP + JRST NSDM1 + +SUBTTL DISK OPEN ROUTINES + +%DO==1,,525252 ;Special mode bits for disk opens. +%DOWOV==100000 ;Write over mode +%DONRF==10 ;Don't set ref-date +%DONLK==20 ;Don't chase links; actually open the link itself. +%DORWT==40 ;Make readers wait (used on opens for write or write-over). + +IFN TPLP+UNSPLP,[ +TPLO: MOVE C,[SIXBIT /.LPTR./] ;PSEUDO LINE PRINTER (DISC) + JUMPGE D,TPLO2 + MOVE B,UNAME(U) + AOS A,TPLFNO ;GENERATE RANDOM FILE NAME + JRST TPLO2 +] + +COMO: SKIPA C,[SIXBIT /COMMON/] ;.OPEN ENTRY FOR "COM" DEVICE +SYSO: MOVSI C,(SIXBIT /SYS/) ; " FOR "SYS" DEVICE +TPLO2: MOVEM C,USYSN1(U) + MOVNI I,1 + JRST QSKO + +QSKPO: MOVSI TT,-NQS ;PACK # OPEN + CAME I,QPKID(TT) + AOBJN TT,.-1 ;I <= PHYSICAL UNIT WITH SPECIFIED PACK + JUMPL TT,QSKPO1 + PUSHJ P,QPKNFP + JRST QSKPO + CAIE W,4 ;IF RENAME/DELETE, OK, DOESN'T TOUCH FILE ANYWAY + JRST OPNL16 ;OTHERWISE COMPLAIN PACK NOT MOUNTED +QSKPO1: HRRZ I,TT +QSKUO: CAIGE I,NQS ;DISK UNIT # OPEN + SKIPE QACT(I) ;I <= UNIT # + JRST OPNL10 ;BAD UNIT # OR NOT ENGAGED +IFE MCOND DM,[ ;; Security check in reserved pack feature only on DM. +IFN QRSRVP,[ + JUMPN W,QSKOB ;WRITE-OVER OR RENAME OK. + JUMPGE D,QSKOB ;READ OK. + SKIPE QRESRV(I) ;WRITE: IS PACK ON THIS DRIVE RESERVED? + JRST OPNL10 ;YES, CAN'T WRITE ON IT. +];QRSRVP +];DM + JRST QSKOB + +;DNRF: DEVICE IS LIKE DSK: BUT DOESN'T SET REFERENCE DATE +DNRFO: TRO D,%DONRF/2 ;SET MODE BIT AND DROP INTO QSKO + +; Regular DSK: device +; +; RH(D) has open mode, rotated 1 bit right. +; W has operation code (0=r/w, 2=link, 4=del/rnm, 1=wov) + +QSKO: MOVNI I,1 ;DSK OPEN, I <= # DETERMINED BY SYS +QSKOB: MOVEM I,EPDL(U) ;SAVE DISK # + MOVE C,USYSN1(U) + CAIN W,4 + JUMPE A,QSKOB2 ;IF RENAME OF OPEN FILE TRAP OUT +QSKOA: MOVE I,MDSK ;IS MFD IN? + PUSHJ P,QMCH1 ;READ IN MFD OF MASTER DISK + CLEARM QLD(U) ;LINK DEPTH +QSKOL: PUSHJ P,MFDCK + JRST SYSDS2 + JUMPN W,OPNL11 + JUMPL D,OPNL11 ;MUST BE NORMAL READ + JRST QMLSTF ;USER WANT TO READ THE MASTER DIRECTORY + +MFDCK: CAMN A,[SIXBIT /M.F.D./] + CAME B,[SIXBIT /(FILE)/] + POPJ P, + JRST POPJ1 + +SYSDS2: PUSHJ P,QFLD ;H <= PTR TO USER DIR TABLE + PUSHJ P,QSKO1 ;LOSER DIR NOT IN CORE + SKIPG QSNNR(H) + BUG + PUSHJ P,QUDLK ;RETURN WITH SOS OF QSNNR ON LSWPR + MOVSI TT,40000 + TDNE TT,QSNLCN(H) + JRST QSKDP1 ;PAW OVER USER DIRECTORY +QSKDP2: PUSHJ P,QUDULK + PUSHJ P,FLDRCK + JRST QSKDP9 ;NOT SPECIAL DIRECTORY FILE + JUMPN W,QPNL11 + JUMPL D,QPNL11 + JRST QLISTF ;USER WANTS TO READ HIS USER DIRECTORY + +QSKDP9: JUMPN W,QSKDPY ;If doing IO? + SKIPL D ; and reading + JRST QSKDPZ ; then don't bother with "security". +QSKDPY: PUSHJ P,MNGDIR ;Else if this is a sanctified dir + PUSHJ P,SYSDSK ; get SYS job to tattle about it. +QSKDPZ: JUMPL D,QWRO ;WRITE + CAIN W,4 + JRST QRNAM ;RENAME/DEL + CAIN W,2 + JRST QALINK ;MAKE LINK + JUMPN W,QPNL22 +QWROR: JUMPE A,QPNL11 ;ALSO ENTER FOR VARIOUS WRITE OVER, COPY OVER MODES + JUMPE B,QPNL11 + PUSHJ P,QCHNF ;GET CHANNEL FOR READ + PUSHJ P,LOSSET + QCHNRT + PUSHJ P,QUDLK ;LOCK USER DIR + PUSHJ P,QLOOK ;LOOK UP FILE + JRST [ PUSHJ P,QROR1C ;Not found => decide whethe error or wait. + POPJ P, ;Error (error code already set up). + PUSHJ P,QUDULK ;If retrying, first unlock directory, + PUSHJ P,LSWPOP ;Return the channel, + PUSHJ P,UDELAY ;Wait a little while, + JRST QWROR] ;Try again. + TRNE D,3 ;SKIP IF UNIT ASCII MODE + JRST QSKO2 + MOVE J,[440700,,5] ;BYTE SIZE IS 7 BITS + MOVEM J,QSBYTE(E) +QSKO2: HLLZ J,QSBYTE(E) ;GET PROPER BYTE POINTER LH + MOVEM J,QSMPRP(E) + TRNN D,%DONRF/2 ;3.4 BIT IN OPEN IMPLIES DONT SET REFERENCE DATE + PUSHJ P,QFREF ;"REFERENCE" FILE + MOVE C,Q + SUB C,QSNLCN(H) + HRRZM C,QUDFPR(E) ;SET UP PTR FROM CHNL TO FILE NAME AREA + LDB TT,[UNDSCP+UNRNDM(Q)] ;FOUND FILE SET UP CHNL + MOVEM TT,QDIRP(E) ;SET UP CHAR PTR TO DESC AREA + MOVE C,UNRNDM(Q) + TLNE C,UNLINK + JRST QLINK ;FILE IS A LINK + MOVSI C,%QALOP + SKIPE QLD(U) ;IF WE TRACED A LINK TO OPEN THE FILE, REMEMBER THAT. + IORM C,QSRAC(E) + MOVSI C,%QARWT + TRNE D,%DORWT/2 + IORM C,QSRAC(E) + LDB J,[UNPKN+UNRNDM(Q)] ;GET PACK NUMBER FILE IS ON + MOVSI I,-NQS + CAME J,QPKID(I) + AOBJN I,.-1 ;TRANSLATE LOGICAL TO PHYSICAL DISK UNIT + JUMPGE I,QPKNF ;PACK NOT ON * + HRRZM I,QDSKN(E) ;SET CHNL DISK NUMBER + JUMPL D,QWROR1 ;REALLY WANT TO WRITE OVER, ETC + MOVEI TT,%QMRD ;PUT CHANNEL IN NORMAL READ MODE + HRRM TT,QSRAC(E) +QOEX1: PUSHJ P,QUDULK ;UNLOCK USER DIR + PUSHJ P,LSWDEL ;QUSR ENTRY + PUSHJ P,LSWDEL ;QSNNR ENTRY + SKIPG QSNNR(H) + BUG + PUSHJ P,QSTRTR + MOVE C,D + ROT C,1 + HRL A,E + JSP Q,OPSLC7 ;SET UP IOCHNM AND DEPART + DQUAI,,DQUAO + DQBI,,DQBO + DQUII,,DQUIO + DQBI,,DQBO + +QWROR1: SOJN W,OPNL12 ;NORMAL WRITE OVER MODE + HRRZS H ;CLEAR GARBAGE IN USER DIR NUM + HRRZS E ;CLEAR GARBAGE IN CHNL NUM + HRRZ J,QUDFPR(E) ;PICK UP LOCN OF FILE WITH U.F.D + MOVSI I,-NQCHN ;MAKE SURE THIS FILE NOT OPEN FOR READING +QROR1A: CAIE E,(I) ;DONT GET FAKED OUT BY OWN CHNL + SKIPGE QUSR(I) + JRST QROR1B + CAMN H,QUDPR(I) + CAME J,QUDFPR(I) + JRST QROR1B + JRST OPNL23 + +QROR1B: AOBJN I,QROR1A + PUSHJ P,QAUTH + MOVSI TT,UNWRIT + IORM TT,UNRNDM(Q) ;SET WRITE BIT + MOVSI TT,UNDUMP + ANDCAM TT,UNRNDM(Q) + PUSH P,D + PUSH P,Q + PUSH P,R + PUSH P,E ;CONVERT FROM ORIGINAL BYTE SIZE TO ONE OPENED IN NOW + LDB D,[UNBYTE+UNREF(Q)] + PUSHJ P,QBDCD ;GET INFO FROM ORIGINAL WRITE OF FILE + MOVEI Q,36. + IDIV Q,D ;BYTES PER WORD + SUB Q,E ;# VALID BYTES + IMUL Q,D ;VALID BITS IN LAST WORD + POP P,E ;RESTORE QSK CHNL # + HRRZ R,QSBYTE(E);BYTES PER WORD IN NEW BYTE SIZE + LDB J,[QSBSIZ(E)] ;BITS PER BYTE IN NEW BYTE SIZE + IDIV Q,J ;NUMBER OF NEW-SIZE BYTES IN LAST WORD + SUB R,Q ;RESIDUE IN NEW-SIZE BYTES + LDB Q,[QSBSIZ(E)] ;NEW BYTE SIZE + PUSHJ P,QBENC ;RH(Q) GETS NEW BYTE INFO + MOVE R,-1(P) + DPB Q,[UNBYTE+UNREF(R)] ;CLOBBER FILE'S BYTE SIZE + POP P,R + POP P,Q + POP P,D + CONO PI,CLKOFF + SKIPL TT,QDATE + HRR TT,TIMOFF + CONO PI,CLKON + MOVEM TT,UNDATE(Q) + HLRS TT + DPB TT,[UNREFD+UNREF(Q)] + HLLM TT,OLDRDT(E) + MOVE TT,QACTB + IORM TT,QSNLCN(H) + MOVSI TT,%QAMWO ;WRITE OVER MODE + IORM TT,QSRAC(E) ;LEAVE %QMIDL UNTIL FIRST .IOT SINCE + JRST QOEX1 ; THE USER WILL PROBABLY DO A .ACCESS + +;Call here if lookup fails on open. +;Either signal some error and return, +;or skip-return if caller should wait and retry the lookup. +;Assumes H has dir slot, Q has address of filename block, +;E has channel number allocated for this open. +;Clobbers C, J. +QROR1C: HRRZ C,QSNLCN(H) + SUBI Q,-LUNBLK(C) + SKIPL Q ;SEE IF STILL POINTED INSIDE DIR + CAILE Q,2000-LUNBLK + JRST QROR1D ;NO - REALLY FNF + ADDI Q,(C) + CAMN A,UNFN1(Q) ;DO NAMES MATCH? + CAME B,UNFN2(Q) + JRST QROR1D ;NO - REALLY FNF + HRRZ J,Q ;Find channel that has this file open. + SUB J,QSNLCN(H) + ANDI J,-1 + HRRZS H ;Clear garbage in user dir num + HRRZS E ;Clear garbage in chnl num + MOVSI I,-NQCHN +QROR1E: CAIE E,(I) ;Dont get faked out by our own chnl. + SKIPGE QUSR(I) + JRST QROR1F + CAMN H,QUDPR(I) + CAME J,QUDFPR(I) + JRST QROR1F +;Found the channel. Does it want us to wait? + MOVE I,QSRAC(I) + TLNN I,%QARWT + JRST OPNL23 ;He didn't say so => get "file locked". + JRST POPJ1 + +QROR1F: AOBJN I,QROR1E + JRST POPJ1 ;Cannot find channel => maybe was closed. Retry. + +QROR1D: SKIPN QLD(U) + JRST OPNL4 ;FILE NOT FOUND + JRST OPNL47 ;LINK WAS FOUND, BUT NOT THE FILE IT POINTED TO + +;COME HERE FOR RENAME-WHILE-OPEN +QSKOB2: HRRZ A,B ;DO RENAME WHILE OPEN HERE TO AVOID + CAIL A,20 ;IN CASE SYS NAME HAS CHANGED + JRST OPNL14 + SKIPE SRN3(U) + SKIPN SRN4(U) + JRST OPNL11 + ADD A,U + HLRZ E,IOCHNM(A) + MOVE H,QUDPR(E) + MOVE A,SRN3(U) + MOVE B,SRN4(U) + PUSHJ P,MFDCK + JRST .+2 + JRST QPNL11 + PUSHJ P,FLDRCK + JRST .+2 + JRST QPNL11 + PUSHJ P,QUDLK + MOVE Q,QUDFPR(E) + ADD Q,QSNLCN(H) + PUSHJ P,QGRLSC ;EITHER NAME > OR FROM POINTER + MOVE I,D ;I => TO POINTER + HRLOI E,377777 ;PREVIOUS FN1 (BIT 4.9 COMPLEMENTED) + MOVE W,E ;FN2 + MOVEI J,0 ;J NEGATIVE => NEED SORT, NON-ZERO => DIR MODIFIED +QSKDP4: SUBI I,LUNBLK +QSKDP5: SUBI D,LUNBLK + CAMLE C,D + JRST QSKDP8 ;THROUGH + SKIPN A,UNFN1(D) + SKIPE UNFN2(D) + JRST QSKDP3 + HLLOS J + JRST QSKDP5 ;NAME BLOCK FREE + +QSKDP3: MOVE Q,UNRNDM(D) + TLNN Q,UNIGFL + JRST QSKDPR ;NOT OPEN FOR WRITE OR BEING DELETED + HLLOS J ;NEED TO WRITE OUT DIR + SKIPN A,UNFN1(D) + MOVSI A,(SETZ) + SKIPN B,UNFN2(D) + MOVSI B,(SETZ) +QSKDP7: PUSHJ P,QGRLSC ;DON'T CREATE ANY FILE WITH NAME OF < OR > + AOJA A,QSKDPA ;CHANGE BOTH JUST TO BE SURE + AOJA A,QSKDPA + MOVE Q,QSNLCN(H) ;SEE IF THAT NAME EXISTS + MOVEI Q,2000-LUNBLK(Q) ;THERE MAY BE DUPLICATE ENTRIES +QSKDPU: CAMN A,UNFN1(Q) ;DURING THIS SEARCH BUT IT DOESN'T + CAME B,UNFN2(Q) ;MATTER + JRST QSKDPT + CAIE Q,(D) ;DON'T CHANGE NAME IF NOT DUPLICATE +QSKDPA: AOJA B,QSKDP7 ;FOUND IT. CHANGE SECOND NAME +QSKDPT: SUBI Q,LUNBLK + CAMG C,Q + JRST QSKDPU + MOVEM A,UNFN1(D) + MOVEM B,UNFN2(D) + MOVSI Q,UNIGFL + ANDCAM Q,UNRNDM(D) +QSKDPR: CAMN D,I + JRST QSKDP6 + HRLZ Q,D ;RELOCATE FILE BLOCK + HRR Q,I + BLT Q,LUNBLK-1(I) +QSKDP6: JUMPL J,QSKDP4 ;ALREADY NEEDS SORT + MOVE B,UNFN2(D) ;MAY NOT HAVE YET IF GOT HERE FASTEST WAY + TLC A,(SETZ) + TLC B,(SETZ) + EXCH A,E + EXCH B,W + CAMLE A,E + JRST QSKDP4 ;ORDER OK + CAMN A,E + CAMGE B,W + MOVNI J,1 ;NEED SORT + JRST QSKDP4 + +QSKDP8: ADDI I,LUNBLK ;I POINTED TO EMPTY SLOT + MOVE D,I + SUBI D,(TT) + EXCH D,UDNAMP(TT) + ADDI D,(TT) + CAML D,I + JRST QSKDPV + SETZM (D) ;CLEAR VACATED AREA + HRLS D + ADDI D,1 + BLT D,-1(I) +QSKDPV: JUMPL J,QSKDPS ;SORT + TRNN J,-1 + JRST QSKDPK +QSKDPX: MOVE I,QACTB + IORM I,QSNLCN(H) +QSKDPK: MOVE W,QSNLCN(H) +IFN QRSRVP,[ + HLRZ A,UDALLO(W) ;IF THIS DIR HAS ALLOCATION + JUMPE A,QSKBK0 + MOVEI B,NQS-1 ;CONVERT PACK # TO DRIVE # + CAME A,QPKID(B) + SOJGE B,.-1 + SKIPGE A,B +QSKBK0: SETO A, ;ALLOCATED PACK NOT MOUNTED, USE ANY + MOVEM A,QSALLO(H) ;SAVE DRIVE # (-1 IF NONE) +];QRSRVP + HLLZS UDBLKS(W) + MOVE A,UDNAMP(W) + ADDI A,(W) +QSKBK1: CAIL A,2000(W) ;COUNT BLOCKS USED + JRST QSKBK2 + MOVE B,UNRNDM(A) + TLNE B,UNLINK + JRST QSKBK3 + LDB B,[UNDSCP+UNRNDM(A)] + IDIVI B,UFDBPW + HLL B,QBTBLI(C) + ADDI B,UDDESC(W) ;B GETS BYTE PNTR TO DESC +QSKBK4: ILDB C,B + JUMPE C,QSKBK3 + CAIN C,UDWPH + JRST QSKBK4 + CAIG C,UDTKMX + JRST [ADDM C,UDBLKS(W) ? JRST QSKBK4] + CAIG C,UDWPH + JRST [AOS UDBLKS(W) ? JRST QSKBK4] + REPEAT NXLBYT, IBP B + AOS UDBLKS(W) + JRST QSKBK4 + +QSKBK3: ADDI A,LUNBLK + JRST QSKBK1 + +QSKBK2: POP P,W + POP P,I + POP P,D + POP P,C + POP P,B + POP P,A + JRST QSKDP2 + +QSKDPS: MOVEI T,LUNBLK + ADD P,[3,,3] +QSKDPB: MOVEI Q,(I) ;BEGINNING OF NAME AREA + SKIPGE T + MOVEI Q,2000-LUNBLK(TT) ;START AT END + MOVEI W,2000(TT) + SKIPGE T + MOVEI W,-LUNBLK(I) + SETZM (P) + TDZA J,J ;0 => SORTED -1 => MAKE ANOTHER PASS +QSKDPE: ADD Q,T + CAIE Q,(W) + JRST QSKDPC + JUMPE J,QSKDPW + MOVNS T + JRST QSKDPB + +QSKDPW: SUB P,[3,,3] + JRST QSKDPX + +QSKDPC: SKIPN A,UNFN1(Q) + SKIPE UNFN2(Q) + JRST QSKDPD + BUG + +QSKDPD: MOVE B,UNFN2(Q) + TLC A,(SETZ) + TLC B,(SETZ) + SKIPE E,(P) ;FIRST ENTRY + JRST QSKDPF +QSKDPG: MOVEM A,-2(P) + MOVEM B,-1(P) +QSKDPI: MOVEM Q,(P) + JRST QSKDPE + +QSKDPF: JUMPL T,QSKDPJ + CAMLE A,-2(P) + JRST QSKDPG + CAME A,-2(P) + JRST QSKDPH + CAML B,-1(P) + JRST QSKDPG +QSKDPH: REPEAT LUNBLK,[ + EXCH A,.RPCNT(E) + EXCH A,.RPCNT(Q) + EXCH A,.RPCNT(E) +] + MOVNI J,1 + JRST QSKDPI + +QSKDPJ: CAMGE A,-2(P) + JRST QSKDPG + CAME A,-2(P) + JRST QSKDPH + CAMG B,-1(P) + JRST QSKDPG + JRST QSKDPH + +SUBTTL OPEN FOR WRITE + +;RETURNS WITH QUSR(E) AND QSNLCN(E) ON LSWPR +QWRO2: JUMPE A,QPNL11 + JUMPE B,QPNL11 + SKIPGE I,EPDL(U) ;PICK UP DESIRED DISK UNIT + JRST QWRO2A ;SYSTEMS CHOICE +QWRO2B: CAIGE I,NQS + SKIPE QACT(I) + BUG ;WE LOST SOMEHOW... + MOVE TT,QTUTO(I) + SKIPL QDPWF(I) ;TUT IN BUT NOT PAWED OVER + TLNE TT,40000 ;TUT NOT IN + PUSHJ P,QTCH1 ;READ IN TUT OF DISK INVOLVED + PUSHJ P,QCHNF ;GET CHANNEL + PUSHJ P,LOSSET + QCHNRT + MOVE TT,[440700,,5] + TRNN D,3 + MOVEM TT,QSBYTE(E) ;UNIT ASCII MODE, BYTE SIZE=7 + PUSHJ P,QUDLK ;LOCK USER DIRECTORY + PUSHJ P,QGRLSC ;CHECK < AND > + JRST QPNLBN ;LOSE + PUSHJ P,QFNG ;REPLACE WITH COMPUTED EFFECTIVE NAME + PUSHJ P,QFREEF ;FIND FREE FILE NAME AREA AND STORE IN QDIRP(E) + JRST QFDF ;FILE DIR FULL + MOVSI TT,UNWRIT ;SET WRITE IN PROGRESS + IORM TT,UNRNDM(Q) + MOVE TT,QPKID(I) + DPB TT,[UNPKN+UNRNDM(Q)] + PUSHJ P,QAUTH ;SET FILE AUTHOR, MAY NOT PCLSR + MOVE TT,QACTB + IORM TT,QSNLCN(H) + SETOM QSCRW(E) ;SET CHNL WRITE SWITCH + POPJ P, + +QWRO2A: +IFN QRSRVP,[ + SKIPL I,QSALLO(H) + JRST QWRO2B ;THIS DIR GOES ON A PARTICULAR UNIT +] + SKIPGE I,QWRU ;GET CURRENT WRITING UNIT + JRST QWRO2E ;NO CURRENT UNIT, GO FIND ONE + MOVE TT,QSFT(I) + CAML TT,QFTTHR + JRST QWRO2B ;ENOUGH ROOM ON PREFERRED UNIT +QWRO2E: SETOB T,I ;NOT MUCH SPACE LEFT TRY OTHER UNITS + MOVSI E,-NQS +QWRO2C: SKIPGE QACT(E) ;SKIP ON UNIT ACTIVE + JRST QWRO2D +IFN QRSRVP,SKIPN QRESRV(E) ;DONT CHOOSE THIS PACK IF RESERVED + CAML T,QSFT(E) ;NOTE QSFT IS -1 IF TUT NEVER BEEN READ IN + JRST QWRO2D ;OTHERWISE CONTAINS VALID BLOCK COUNT + MOVE T,QSFT(E) + HRRZ I,E +QWRO2D: AOBJN E,QWRO2C + SKIPGE I + BUG ;NO ACTIVE UNRESERVED UNITS + CAMN I,QWRU + JRST QWRO2B ;DON'T WRITE MFD IF UNCHANGED + MOVEM I,QWRU + MOVE E,QACTB + IORB E,QMDRO + MOVEM I,MPDWDK(E) + JRST QWRO2B + +QWRO: JUMPN W,QWROR ;REALLY WANT TO MODIFY OR OTHERWISE HACK AN EXISTING FILE + PUSHJ P,QWRO2 ;MAKING NEW FILE, DECIDE WHICH UNIT TO PUT IT ON + SETOM QMFTP(E) ;TRACK TO SCAN IN TUT + SETOM QMTTR(E) + CLEARM QMPTN(E) + CLEARM QMPTC(E) + MOVEI TT,%QMWRT ;ENTER NORMAL WRITE MODE + HRRM TT,QSRAC(E) + MOVSI TT,%QARWT + TRNE D,%DORWT/2 + IORM TT,QSRAC(E) + JRST QOEX1 ;EXIT + + +SUBTTL File hacking tracking + +; MNGDIR checks the file name (sname in C) +; Fails to skip if the file is an important system file. +; Skips if the file is of the everyday sort. + +MNGDIR: HLRZ TT,C +IFN KL10P, CAME C,[SIXBIT /.KLFE./] + CAIN TT,'SYS ;A sys directory? + POPJ P, + CAME C,[SIXBIT /ACOUNT/] + CAMN C,[SIXBIT /./] + POPJ P, + CAME C,[SIXBIT /DEVICE/] + CAMN C,[SIXBIT /CHANNA/] + POPJ P, + AOS (P) ;Not a system directory. skip return. + POPJ P, + +; SYSDSK notifies the SYS job to print a message on the +; console about the file being hacked. +; File names in C;A B, the opcode in W (or zero) specifies the hacking. + +SYSDSK: JUMPE U,CPOPJ ;Avoid deadly embrace! + MOVSI T,SCLWRT ;Writing on SYS directory. + PUSHJ P,CWAIT ;Take turns like nice little lusers. + TDNE T,SUPCOR ;Wait for previous req to finish. + MOVE TT,W ;Check file operation code. + CAILE TT,4 ;If impossible opcode + SETZ TT, ; probably supposed to be R/W. + MOVEM TT,SWMOD ;Store opcode. + MOVE TT,UNAME(U) + MOVEM TT,SWUNAM ;Luser. + MOVE TT,JNAME(U) + MOVEM TT,SWJNAM + MOVEM A,SWFN1 + MOVEM B,SWFN2 + MOVEM C,SWFN3 ;Sname. + IORM T,SUPCOR ;Notify the SYS job. + JRST CLKONJ ;Turn on the clock and return. + + +SUBTTL DIRECTORY ROUTINES + +QFREEF: PUSH P,A ;Q_PTR TO USER DIR FREE FILE QDIRP(E)_PTR TO FREE DESC AREA + PUSH P,B ;GET FREE FILE AREA + PUSH P,I + MOVEI I,0 ;SIGNAL NO GC YET +QFREFA: SETZM QUDFPR(E) ;CLEAR SO WILL NOT POINT TO RANDOMNESS IN CASE OF G C + MOVE TT,QSNLCN(H) + SKIPL Q,UDESCP(TT) + CAIL Q,2000*UFDBPW + BUG ;FREE DESC POINTER OUT OF RANGE + IDIVI Q,UFDBPW + MOVE C,UDNAMP(TT) + CAIL Q,-UDDESC-7-LUNBLK(C) + JRST QAGARB ;NOT ENOUGH ROOM BETWEEN DESC AND NAME AREAS + PUSHJ P,QLGLK ;FIND WHERE FILE OUGHT TO GO + JRST QFREFF ;DIR WAS EMPTY + TRNN J,1777 + JRST QFREFE ;GOES AT END OF DIR +QFREFC: CAMN A,UNFN1(J) + CAME B,UNFN2(J) + JRST QFREFE + MOVE C,UNRNDM(J) + TLNE C,UNIGFL ;* FILES MUST COME AFTER NON * FILES + JRST QFREFE ;OF SAME NAME + ADDI J,LUNBLK + CAIGE J,2000(TT) + JRST QFREFC +QFREFE: CAMN Q,J + JRST QFREFF ;GOES AT BEGINNING + PUSHJ P,QINSRT + JRST QFREFD + +QFREFF: SUBI Q,LUNBLK ;Q -> NAME BLOCK FILE WILL GO IN +QFREFD: MOVNI T,LUNBLK ;ALLOCATE MORE SPACE FOR NAME AREA + ADDM T,UDNAMP(TT) + HRRZ A,UDESCP(TT) ;FIRST FREE DESCRIPTOR LOC + DPB A,[UNDSCP+UNRNDM(Q)];STORE IN FILE AREA + MOVEM A,QDIRP(E) ;STORE IN CHANNEL + MOVEI B,6*UFDBPW+1 ;ENOUGH FOR A LINK WITH EVERY CHAR QUOTED PLUS ONE ZERO + ADDM B,UDESCP(TT) ;ALLOCATE MORE SPACE FOR DESC AREA + MOVE B,Q + SUB B,QSNLCN(H) + HRRZM B,QUDFPR(E) ;ASSOCIATE CHANNEL WITH FILE + CONO PI,CLKOFF + SKIPL B,QDATE ;GET TIME AND DATE + HRR B,TIMOFF + CONO PI,CLKON + MOVEM B,UNDATE(Q) ;SET CREATION DATE + HLLM B,OLDRDT(E) + HLRS B + DPB B,[UNREFD+UNREF(Q)] ;SET REFERENCE DATE + IDIVI A,UFDBPW ;GET WRD AND CHAR ADRS + HLLZ B,QBTBLI(B) + ADDI B,UDDESC(A) + HRRZ A,QSNLCN(H) + ADD B,A + ILDB A,B + SKIPE A + BUG ;DESCRIPTOR AREA ALREADY OCCUPIED + MOVEI A,UDWPH + DPB A,B + ILDB A,B + SKIPE A + BUG ;NOT FOLLOWED BY ZERO + POP P,I + POP P,B + POP P,A + MOVEM A,UNFN1(Q) ;SET FILE NAMES + MOVEM B,UNFN2(Q) + JRST POPJ1 + +QAGARB: JUMPL I,QNOFRE ;IF GC WAS ALREADY TRIED, DON'T TRY IT AGAIN - GIVE UP. + PUSHJ P,QGC ;GC. BTW, IT IS OK TO PCLSR HERE. + JFCL + MOVNI I,1 ;SIGNAL GC HAS BEEN TRIED + JRST QFREFA + +;MAKE ROOM FOR FILE BEFORE J. Q POINTS TO NEW EMPTY FILE SLOT +QINSRT: PUSH P,A + PUSH P,TT + HRRZ TT,QSNLCN(H) + HRRZ A,UDNAMP(TT) + PUSH P,A + ADDI A,(TT) + HRLS A + SUBI A,LUNBLK + BLT A,-LUNBLK-1(J) + SETZM -LUNBLK(J) + HRRZI A,-LUNBLK+1(J) + HRLI A,-LUNBLK(J) + BLT A,-1(J) + SUB J,QSNLCN(H) + MOVSI A,-NQCHN +QINSR1: HRRZ TT,QUDPR(A) + SKIPL QUSR(A) + CAIE TT,(H) + JRST QINSR2 + MOVE TT,QUDFPR(A) + CAMGE TT,(P) + JRST QINSR2 + CAIGE TT,(J) + SUBI TT,LUNBLK + MOVEM TT,QUDFPR(A) +QINSR2: AOBJN A,QINSR1 + ADD J,QSNLCN(H) + HRRZI Q,-LUNBLK(J) + SUB P,[1,,1] + POP P,TT + POP P,A + POPJ P, + +;DIR NOT IN CORE. GET IT FROM DISK, CREATE IT IF DOESN'T ALREADY +; EXIST, OR GIVE NO SUCH DIRECTORY ERROR. +;C HAS SNAME. RETURNS DIRECTORY NUMBER IN H. + +QSKO1: PUSHJ P,SWTL + QSKOSW ;PREVENT TIMING ERROR IF TWO PCS SHOULD + PUSHJ P,QFLD ; ATTEMPT TO BRING IN SAME DIRECTORY + JRST QSKO11 + MOVEI T,2 ;SOMEONE ELSE BROUGHT IT IN, RELEASE QSKOSW + JRST LSWPON ;BUT LEAVE QSNNR(H) LOCKED. + +QSKO11: PUSH P,J + PUSH P,I + PUSHJ P,QFL ;LOOK UP DIR IN MFD, RET TRACK IN J + JRST QSKON ;NON EXISTENT + PUSHJ P,QFLDF ;FIND FREE LOSER DIR SLOT + MOVE I,MDSK + PUSHJ P,QCHNF ;FIND FREE CHNL (TO READ IN DIR) + MOVEM C,QSNUD(H) ;SET USER NAME IN DIR SLOT + MOVEM J,QSLGL(E) ;REQUEST READ IN OF USER DIR FROM TRACK IN J + MOVEI TT,%QMUDR + MOVEM TT,QSRAC(E) +QSKON1: MOVEI T,2 + PUSHJ P,LSWPON ;RELEASE QSKOSW, LEAVE SOSSET OF QSNNR(H) + POP P,I ;GO AWAY WILL HANG UP WAITING IN QUDLK + POP P,J ;DIR IS LOCKED BUT NOT ON LSWPR, PI WILL UNLOCK AFTER READIN + JRST QSTRTR + +QNOFRE: POP P,I ;NO FREE FILES AVAIL + JRST POPBAJ + +QPNL24: PUSHJ P,OPNL24 + JRST URET + +QPNL20: PUSHJ P,OPNL20 + SKIPE QLD(U) + PUSHJ P,OPNL47 ;FOUND LINK, BUT IT POINTS TO NON-EXISTENT DIRECTORY + JRST URET + +AUTOCR: ;AUTOMATICALLY CREATED DIRECTORIES +IFN TPLP+UNSPLP,SIXBIT /.LPTR./ ;FOR TPL SPOOLING + SIXBIT /.MSGS./ ;FOR MESSAGES TO ALL LOSERS + SIXBIT /.MAIL./ ; Programs like to write mail here + SIXBIT /CRASH/ ; Programs like to dump themselves here + SIXBIT /.TEMP./ ; Programs like to write randomness here +NATOCR==.-AUTOCR + +QSKON: JUMPE C,QPNL20 ;DON'T ALLOW ZERO USER NAME + PUSH P,TT + MOVSI TT,-NATOCR +QSKONA: CAMN C,AUTOCR(TT) + JRST QSKONB + AOBJN TT,QSKONA + CAMN A,[SIXBIT /..NEW./] + CAME B,[SIXBIT /(UDIR)/] + JRST [POP P,TT + JRST QPNL20] + BUG INFO,[DSK: DIR ],SIXBIT,C,[CREATED BY ],SIXBIT,UNAME(U),SIXBIT,JNAME(U) +QSKONB: POP P,TT + SKIPG NQFUS + JRST QPNL24 ;NO MFD SLOTS AVAILABLE + PUSH P,A + PUSH P,B + PUSH P,C +QSKONE: PUSHJ P,QFLDF ;FIND FREE DIR SLOT + PUSHJ P,QMLOCK + PUSHJ P,TCALL + JRST IOMQ + JRST [PUSHJ P,LSWPOP ;QMDRO + PUSHJ P,LSWPOP ;QSNNR + PUSHJ P,UDELAY ;HOPEFULLY MEMORY WILL APPEAR SHORTLY + JRST QSKONE] + MOVEM C,QSNUD(H) + SOS NQFUS ;NO TIMING ERR DUE TO QSKOSW + MOVEI J,MU23UD + DPB J,[MUR,,MEMBLT(A)] + DPB H,[MNUMB,,MEMBLT(A)] + LSH A,10. + HRRM A,QSNLCN(H) + SETZM (A) + HRLS A + AOS B,A + BLT A,2000-2(B) + MOVEI A,2000 + MOVEM A,UDNAMP-1(B) + MOVE A,QSNUD(H) + MOVEM A,UDNAME-1(B) + MOVE B,QACTB ;NOW PUT UFD INTO MFD + IORB B,QMDRO + MOVE TT,MDNAMP(B) ;LOOK FOR A FREE SLOT + ADDI TT,(B) +QSKONC: TRNN TT,1777 + JRST QSKOND + SKIPN MNUNAM(TT) + JRST QSKONF + ADDI TT,LMNBLK + JRST QSKONC + +QSKONF: SUBI TT,(B) + JRST QSKONG + +QSKOND: MOVNI TT,LMNBLK ;NO FREE SLOTS, SO EXTEND DOWNWARD + ADDB TT,MDNAMP(B) +QSKONG: ADDI B,(TT) + MOVEM A,MNUNAM(B) + SUBI TT,2000-2*NUDSL ;GET DISK BLOCK NUMBER +IFN KA10P, SKIPGE TT +IFE KA10P, CAIGE TT,2 ; Don't clobber 'HOM' blocks + BUG ;TOO MANY UFDS (NQFUS CHECK DIDN'T WORK) + LSH TT,-1 + MOVEM TT,QSNMI(H) + MOVE TT,QACTB ;UNLOCK UFD AND CAUSE IT TO GET WRITTEN + HLLM TT,QSNLCN(H) + PUSHJ P,QMULK ;UNLOCK MFD + POP P,C + POP P,B + POP P,A + JRST QSKON1 + +SUBTTL MAKE LINK + +QALINK: MOVE I,MDSK ;ENTER WITH QSNNR ON LSWPR + MOVEM I,EPDL(U) + PUSHJ P,QWRO2 ;MAKES NEW FILE WITH MINIMUM OF 37 BYTES OF DESC SPACE + MOVSI A,UNLINK ; AND ADDS QUSR AND QSNLCN ON LSWPR + IORM A,UNRNDM(Q) ;SET LINK BIT + MOVE A,E ;QSK CHANNEL NUMBER + MOVE C,SRN5(U) ;SNAME LINKED TO + PUSHJ P,LDEP + PUSHJ P,QUDS + MOVE C,SRN3(U) ;FN1 LINKED TO + PUSHJ P,LDEP + PUSHJ P,QUDS + MOVE C,SRN4(U) ;FN2 LINKED TO + PUSHJ P,LDEP + JFCL + MOVE E,A ;QSK CHANNEL NUMBER FOR QCHNRT + MOVEI R,EPDL(U) ;DON'T CLOSE A REAL IOCHNM WORD + PUSHJ P,QSOCL4 ;CLOSE CHNL & FILE + PUSHJ P,LSWDEL ;DELETE QUSR, HAS BEEN SETOM'ED + PUSHJ P,LSWDEL ;DELETE QSNRR, HAS BEEN SOS'ED + JRST POPJ1 + +LDEP: MOVEI E,6 ;STORE SIXBIT FROM C INTO LINK DESC +LDEPL: MOVEI B,0 ;GET NEXT CHAR + LSHC B,6 + JUMPE B,LDEPS ;*THIS ALLOWS EMBEDDED BLANKS. + CAIE B,'; + CAIN B,': + JRST LDEPS +LDEPS2: MOVE D,B + PUSHJ P,QUDS + SOS E ;NUMBER OF CHARACTERS LEFT IN WORD + JUMPN C,LDEPL ;JUMP IF ANY MORE NON-BLANK CHARS TO STORE + MOVEI D,'; + JUMPE E,POPJ1 ;JUMP IF STORED 6 CHARACTERS + POPJ P, ;STORED FEWER, NEED TERMINATOR + +LDEPS: MOVEI D,': ;THIS CHAR NEEDS TO BE QUOTED + PUSHJ P,QUDS + JRST LDEPS2 + +;LINK ENCOUNTERED DURING LOOKUP + +QLINK: TRNE D,%DONLK/2 ;CHECK 3.5 BIT IN OPEN MODE + JRST QOLINK ;JUMP IF DON'T CHASE LINKS MODE + AOS A,QLD(U) + CAIL A,100. + JRST OPNL27 ;LINK DEPTH EXCEEDED + PUSH P,E ;SAVE XR NEEDED BY LSWPOP OF QUSR ENTRY + MOVE E,TT + IDIVI E,UFDBPW + ADD E,QSNLCN(H) + ADDI E,UDDESC + MOVE TT,QBTBLI(TT) + HRR TT,E + MOVE I,[440600,,A] + SETZB A,B + SETZ C, +QL1: ILDB J,TT + JUMPE J,QL3 ;END DESC + CAIN J,': + JRST QL4 ;QUOTE NEXT CHAR + CAIN J,'; + TLZA I,770000 ;TERMINATE THIS WORD +QL5: IDPB J,I + JRST QL1 + +QL4: ILDB J,TT ;GET CHAR THAT WAS QUOTED + JRST QL5 + +QL3: EXCH A,C ;END OF DESC REACHED + EXCH A,B ;MAKE A FN1 B FN2 C SNM + SKIPN C + MOVE C,USYSN1(U) + PUSHJ P,QUDULK ;UNLOCK DIR + POP P,E ;RESTORE XR USED BY LSWPOP OF QUSR ENTRY + PUSHJ P,LSWPOP ;QUSR ENTRY + PUSHJ P,LSWPOP ;QSNNR ENTRY + PUSHJ P,OPBRK ;IF TRYING TO BE PCLSRED, SUBMIT + JRST QSKOL + +QOLINK: MOVSI TT,%QALNK ;OPENING UP A LINK + IORM TT,QSRAC(E);DON'T ALLOW FILE-ONLY OPERATIONS SUCH AS IOT + JUMPL D,QWROR1 ;LEAVE RH(QSRAC)=%QMIDL SO PI LEVEL WON'T MESS WITH IT + JRST QOEX1 ;AND FINISH OPENING + +SUBTTL PAW OVER MFD + +QMCH1: CONO PI,UTCOFF + MOVE TT,QMDRO + TLNE TT,40000 + AOJE TT,QMCH2 ;NOT ON WAY IN +QMCH3: CONO PI,UTCON + SKIPGE QMDRO + PUSHJ P,UFLS + MOVSI E,2 + TDNN E,QMDRO + POPJ P, ;PAWED OVER + PUSHJ P,QMLOCK + ANDCAM E,QMDRO + HRRZ E,QMDRO + MOVE TT,MDCHK(E) + CAME TT,[SIXBIT /M.F.D./] + BUG HALT,[MFD CLOBBERED] +QMCH1A: MOVEI E,2000-LMNBLK*NUDSL(E) +IFN KA10P, SETZM NQFUS +IFE KA10P,[ + MOVNI TT,2 ;PROTECT DEC 'HOM' BLOCKS SO KLDCP OR 8080 + MOVEM TT,NQFUS ; CAN FIND ITS CRUFT +] ;IFE KA10P +QMCH1E: LDB TT,[1200,,E] + JUMPE TT,QMULK + SKIPN (E) + AOS NQFUS + ADDI E,LMNBLK + JRST QMCH1E + +QMCH2: SOS QMDRO ;INDICATE ON WAY IN + CONO PI,UTCON + SKIPG QFCHN + BUG ;DON'T WANT TO WAIT FOR CHANNEL? + PUSHJ P,QCHNF + MOVEI TT,MFDBLK ;MFD TRACK + MOVEM TT,QSLGL(E) + MOVEI TT,%QMMDR + MOVEM TT,QSRAC(E) + PUSHJ P,QSTRTR + JRST QMCH3 + +SUBTTL PAW OVER TUT + +QTCH1: CONO PI,UTCOFF + MOVSI TT,200000 + TDNE TT,QTUTO(I) + JRST QTCH2 ;GO READ IT IN + CONO PI,UTCON +QTCH1A: PUSHJ P,QTLOCK ;TO MAKE SURE IT'S IN + AOSE QDPWF(I) + JRST QTULK ;ALREADY PAWED OVER + PUSH P,A + PUSH P,B + MOVE T,QTUTO(I) + MOVE E,QSWAPA(T) + IDIVI E,DECADE + SKIPE TT + ADDI E,1 + IMULI E,DECADE ;ROUND SWAPPING ALLOC TO MULTIPLE OF A DECADE + MOVEM E,QSWAPA(T) + PUSH P,D + PUSH P,E ;FIRST TRACK OF NON-SWAPPING (FILE) AREA + MOVE E,QTUTP(T) ;ROUND TUT POINTER TO MULTIPLE OF A DECADE + ADDI E,DECADE-1 + IDIVI E,DECADE + IMULI E,DECADE + CAMGE E,(P) ;KEEP IT WITHIN THE FILE AREA + MOVE E,(P) + MOVEM E,QTUTP(T) + MOVE E,QPKNUM(T) +IFN DC10P,[ + CAME E,QPKID(I) + BUG HALT,[PACK ID ],OCT,E,[IN TUT FOR UNIT ],DEC,I,[DIFFERS FROM HARDWARE PACK ID],OCT,QPKID(I) +] +IFE DC10P, MOVEM E,QPKID(I) + MOVE E,QPAKID(T) + MOVEM E,QPKNM(I) +IFN QRSRVP,[ + MOVE E,QTRSRV(T) + MOVEM E,QRESRV(I) +] +;DROPS THROUGH + ;DROPS IN + CLEARM QSFTS(I) ;FREE SPACE IN SWAPPING AREA + SETZB D,QSFT(I) + MOVE B,QTUTO(I) + HRLI B,(TUTBP) + ADDI B,LTIBLK +QTCH1D: ILDB A,B + JUMPN A,QTCH1F + CAML D,(P) + AOS QSFT(I) ;BLOCK IN NON-SWAPPING AREA + CAMGE D,(P) + AOS QSFTS(I) ;BLOCK IN SWAPPING AREA +QTCH1F: ADDI D,1 + CAMGE D,QLASTB(T) + JRST QTCH1D + SUB P,[1,,1] + POP P,D + POP P,B + POP P,A + JRST QTULK + +QTCH2: SETOM QDPWF(I) + ANDCAM TT,QTUTO(I) + CONO PI,UTCON + SKIPG QFCHN + BUG ;DON'T WANT TO WAIT FOR CHANNEL? + PUSHJ P,QCHNF + HRRZM I,QDSKN(E) + MOVEI TT,MFDBLK ;TELL PI LEVEL TO READ IT ALL IN + SUB TT,NTBL(I) + MOVEM TT,QSLGL(E) + LDB TT,[121000,,QTUTO(I)] + MOVEM TT,QSCABN(E) + MOVEI TT,%QMTTR + MOVEM TT,QSRAC(E) + PUSHJ P,QSTRTR + JRST QTCH1A + +;ROUTINE TO ACCESS TUT +;CALL WITH DISK UNIT NUMBER IN I, BLOCK NUMBER IN D +;RETURNS IN D AN LDB-STYLE POINTER TO THE TUT AND IN B THE BYTE +;THAT YOU WOULD GET BY LDB'ING THAT POINTER. +;CLOBBERS E +;CALLER MUST LOCK TUT + +TUTPNT: MOVE B,QTUTO(I) + CAML D,QFRSTB(B) + CAML D,QLASTB(B) + BUG ;BLOCK NUMBER NOT IN RANGE COVERED BY TUT + SUB D,QFRSTB(B) + IDIVI D,TUTEPW + ADDI D,LTIBLK(B) + HLL D,TBTBL(E) + LDB B,D + POPJ P, + +QSTRTR: +IFN DC10P,[ +QSTRT1: CONSO DC0,DSKCHN + SETOM QHUNGF ;SOMEONE PUSHED RESET BUTTON, RECOVER AT PI LEVEL + CONO DC0,DCSET+DCIENB+DSKCHN ;ENABLE IDLE INTERRUPT +] +IFN RP10P+RH10P+RH11P,[ + CONO PI,UTCOFF + PUSHJ P,QSTRT1 + CONO PI,UTCON +] + POPJ P, + +IFN RP10P+RH10P+RH11P,[ ;START DISK WITH UTC ALREADY OFF +QSTRT1: SETOM QGTBZY ;NOTE: TURNS UTC BACK ON BUT NOT CLOCK +IFN RP10P, CONSO DPC,20 ;ONLY IF DISK IDLE +IFN RH10P, CONSO DSK,%HIBSY +IFN RH11P, IORDQ TT,%HRCS1 +IFN RH11P, TRNE TT,%HXRDY + CONO PI,DSKRQ + POPJ P, +] + +;TRY TO FLUSH UNNEEDED UFDS FROM CORE. +;ARG IN C IS ROUTINE TO FREE THE MEMORY. +;CALL WITH UDRSW SIEZED, OR WITH PI 2 IN PROGRESS AND UDRSW NOT LOCKED BY ANYONE +;CLOBBERS H, TT. DOESN'T SKIP. +QDFLS: MOVSI H,-QNUD +QDFLS1: SKIPE QSNUD(H) + SKIPE QSNNR(H) +QDFLS2: AOBJN H,QDFLS1 ;CAN'T FLUSH IF SLOT NOT USED OR CHANNELS OPEN IN DIR + JUMPGE H,CPOPJ + MOVE TT,QACTB + TLO TT,600000 + TDNE TT,QSNLCN(H) + JRST QDFLS2 ;CAN'T FLUSH IF LOCKED OR NOT WRITTEN OUT + PUSHJ P,QDFCHK ;CHECK THAT NO POINTERS TO THIS DIRECTORY REMAIN + CLEARM QSNUD(H) ;FLUSH + AOS QFUD + PUSH P,A + HRRZ A,QSNLCN(H) + LSH A,-10. + PUSHJ P,(C) ;RETURN THE MEMORY + POP P,A + JRST QDFLS2 ;TRY FLUSHING SOME MORE + +;CALL WITH UFD SLOT# IN H, WHEN YOU THINK THAT UFD IS FREE. +QDFCHK: PUSH P,C + PUSH P,J + MOVSI C,-NQCHN +QDFCH1: SKIPGE QUSR(C) + AOBJN C,QDFCH1 + JUMPGE C,QDFCH2 + HRRZ J,QUDPR(C) + CAIN J,(H) + BUG ;IT WASN'T REALLY FREE, MAYBE QSNNR IS SCREWED UP? + AOBJN C,QDFCH1 +QDFCH2: POP P,J + POP P,C + POPJ P, + +;FIND A FREE UFD SLOT, RETURN INDEX IN H. PUTS QSNNR ON LSWPR. +;CLOBBERS T, TT. + +QFLDF: PUSHJ P,SWTL + UDRSW + MOVSI H,-QNUD + SKIPLE QFUD + JRST QFLDF1 + PUSH P,C ;ALL UFD SLOTS IN USE, TRY FLUSHING SOME + MOVEI C,MEMR + PUSHJ P,QDFLS + POP P,C + MOVSI H,-QNUD + SKIPLE QFUD + JRST QFLDF1 + PUSHJ P,LSWPOP ;UDRSW + PUSHJ P,UDELAY ;WAIT 1/2 SECOND THEN TRY AGAIN, INCLUDING QDFLS + JRST QFLDF + +QFLDF1: SKIPN QSNNR(H) ;SLOT ALREADY GOBBLED + SKIPE QSNUD(H) ;OR ALREADY OCCUPIED + AOBJN H,QFLDF1 ;MEANS CAN'T TAKE IT + SKIPL H + BUG ;NONE FREE, QFUD OUT OF PHASE WITH REALITY + HRRZS H + SOS QFUD + MOVSI TT,600000 ;DOUBLE LOCK + MOVEM TT,QSNLCN(H) + AOSG QSNNR(H) + BUG + PUSHJ P,LSWPOP ;UDRSW + PUSHJ P,LOSSET + QFLDRT + POPJ P, + +;LOSSET ROUTINE +QFLDRT: SKIPL A,AC0S+H(U) + CAIL A,QNUD + BUG ;H CLOBBERED + SOSGE T,QSNNR(A) + BUG + JUMPG T,CPOPJ ;HOW DID SOMEONE ELSE GET IT? + SKIPN QSNUD(A) + AOS QFUD ;READ-IN NEVER STARTED, SLOT BECOMES FREE + POPJ P, ;OK TO LEAVE 600000,, SET IN QSNLCN + +;C HAS DIR NAME. +;IF IN CORE, SET H TO UFD SLOT#, AOS QSNNR, PUT ON LSWPR, AND SKIP. +;IF DIRECTORY NOT IN CORE, NO SKIP. CLOBBERS T,TT. +QFLD: PUSHJ P,SWTL + UDRSW +QFLD1A: MOVSI H,-QNUD +QFLD1: CAME C,QSNUD(H) + AOBJN H,QFLD1 + JUMPGE H,LSWPOP ;JUMP ON FAILED TO FIND USER. +QFLD2A: AOSG QSNNR(H) + BUG ;MUST HAVE GOTTEN NEGATIVE SOMEHOW + PUSHJ P,LSWPOP ;UDRSW +; PUSHJ P,SOSSET +; QSNNR(H) +;THIS IS AN ATTEMPT TO FIND A BUG. + PUSH P,T + MOVEI T,QSNNR(H) + MOVEM T,IOTBTS(U) + PUSHJ P,LOSSET + [ SOSGE @IOTBTS(U) + BUG + POPJ P, ] + POP P,T +;END TEMPORARY CODE + JRST POPJ1 + +;C <=SYS NAME, RETURNS TRACK ADDR OF DIR IN J, SKIPS IF FINDS LOSER +QFL: PUSHJ P,QMLOCK + PUSHJ P,QFL0 + JRST QMULK + AOS (P) + JRST QMULK + +QFL0: PUSH P,Q + HRRZ Q,QMDRO + ADD Q,MDNAMP(Q) ;PTR TO USER AREA +QFL1: LDB J,[1200,,Q] + JUMPE J,QFL3 + CAMN C,MNUNAM(Q) + JRST QFL2 + ADDI Q,LMNBLK + JRST QFL1 + +QFL2: SUBI J,2000-LMNBLK*NUDSL ;J <= TRACK ADDR OF USER DIR + LSH J,-1 + AOS -1(P) ;SUCCESS +QFL3: POP P,Q + POPJ P, + +;ROUTINE TO ASSIGN A DISK CHANNEL. +;ARGS: U USER TO GO IN QUSR, H UFD SLOT# TO GO IN QUDPR, I DSK# TO GO IN QDSKN +;RETURNS QSK CHNL INDX IN E. +;DOESN'T DO A LOSSET OF QCHNRT, BUT CALLER MAY WANT TO. +;CLOBBERS T. NEVER SKIPS. + +QCHNF: PUSHJ P,SWTL ;PREVENT ANYONE ELSE FROM ALLOCATING CHANNELS + QCHSW + MOVSI E,-NQCHN + SKIPLE QFCHN + JRST QCH2 ;SOME CHANNELS ARE AVAILABLE, GO FIND ONE + PUSHJ P,LSWPOP ;QCHSW + SKIPG QFCHN + PUSHJ P,UFLS + JRST QCHNF + +QCH2: SKIPGE QSRAC(E) .SEE %QALOK + JRST QCH3 + SKIPGE QUSR(E) + JRST QCH1 +QCH3: AOBJN E,QCH2 + BUG ;WHERE DID THAT FREE CHANNEL GO? + +QCH1: HRRZS E ;CHANNEL ALLOCATED, INITIALIZE VARIABLES + HRRZM I,QDSKN(E) + SETOM QSCABN(E) + SETOM QSGL(E) + SETOM QSLGL(E) ;IN CASE OF WRITE-OVER ON 0-LENGTH FILE. + SETZM QBFP(E) + SETZM QSBFS(E) + CLEARM QSLBLK(E) + SETOM QSMDN(E) + SETZM QSCRW(E) + SETZM QSBI(E) + SETZM QSRAC(E) .SEE %QMIDL + CLEARM QFBLNO(E) + SETZM QSMPRC(E) + SETZM QSMPRP(E) + MOVE T,[444400,,1] ;ASSUME BYTES=WORDS, WILL BE FIXED LATER + MOVEM T,QSBYTE(E) + SETZM QPCLSR(E) + HRRZM H,QUDPR(E) + SETZM QUDFPR(E) ;NOT YET SET UP TO ANY PARTICULAR FILE + MOVEM U,QUSR(E) ;CHANNEL IS NOW IN-USE + SOSGE QFCHN + BUG + JRST LSWPOP ;QCHSW + +;LOSSET ROUTINE TO RETURN TENTATIVELY ASSIGNED QSK CHNL +;E HAD BETTER CONTAIN THE QSK CHANNEL NUMBER AT "ALL" TIMES +QCHNRT: SKIPL T,AC0S+E(U) + CAIL T,NQCHN + BUG ;E CLOBBERED + HRRZ A,U ;LSWPOP MESSES WITH LH(U) + CAME A,QUSR(T) + BUG + SETOM QUSR(T) + AOS QFCHN + POPJ P, + +SUBTTL DELETE, RENAME +;COME HERE FOR DELETE, OR RENAME NOT WHILE OPEN, ON DISK. + +QRNAM: SKIPN SRN3(U) + JRST QDEL + PUSH P,A + PUSH P,B + SKIPN B,SRN4(U) + JRST QPNL11 + MOVE A,SRN3(U) + PUSHJ P,MFDCK + JRST .+2 + JRST QPNL13 + PUSHJ P,FLDRCK + JRST .+2 + JRST QPNL13 + POP P,B + POP P,A + PUSH P,SRN3(U) + PUSH P,SRN4(U) + PUSHJ P,QUDLK + PUSHJ P,QLOOK + JRST [ SUB P,[2,,2] + JRST QROR1C ] ;GIVE FILE NOT FOUND OR FILE LOCKED + MOVE I,Q + POP P,B + POP P,A + PUSHJ P,QGRLSC + JRST QPNLBN ;FILE ALREADY EXISTS + PUSHJ P,QFNG +QRNAM4: PUSHJ P,QLOOK + JRST QRNAM3 + CAME I,Q ;ALLOW RENAME THAT DOESN'T CHANGE NAMES. + JRST QPNL13 +QRNAM3: MOVE Q,I + MOVSI TT,UNDUMP ;SAY FILE NOT DUMPED. + ANDCAM TT,UNRNDM(Q) + MOVNI E,1 ;TELL QFREF NOT TO CLOBBER NON-EX DISK CHNL. + PUSHJ P,QFREF ;"REFERENCE" FILE + PUSHJ P,QRELOC ;STORE NEW NAMES IN DIR +QRNAM2: MOVE TT,QACTB + IORM TT,QSNLCN(H) +QRNAM1: MOVE U,USER ;U MAY NOT HAVE USER IF CAME HERE FROM LOGOUT + PUSHJ P,LSWCLR + JRST POPJ1 + +QGRLSC: CAME A,[SIXBIT />/] ;SKIP NONE IF BOTH A+B ARE SPECIAL + CAMN A,[SIXBIT //] ;AND TWICE IF NEITHER + CAMN B,[SIXBIT / LOOK UP FILE TO DELETE +;Q .NE. 0 => DELETE FILE POINTED TO BY QUDFPR OF CHNL IN D +;H MUST HAVE DIR SLOT INDEX +QDELA: MOVEI Q,0 +QDLA1: PUSHJ P,SLUGH + QCHSW + 1000,,QSNLCN(H) + 1000,,QTUTO(I) + JUMPN Q,QDLA2 + PUSHJ P,QLOOK + JRST QDEL4A ;FNF + SETO D, ;NO ASSOCIATED CHANNEL +QDLA3: LDB A,[UNLNKB+UNRNDM(Q)] + LDB TT,[UNPKN+UNRNDM(Q)] + CAME TT,J + JUMPE A,QDELA1 ;ON DIFFERENT DISK (DIDN'T LOCK RIGHT TUT TRY AGAIN) + MOVE A,Q + SUB A,QSNLCN(H) + MOVSI J,-NQCHN +QDEL1: CAIN D,(J) + JRST QDEL2 ;IGNORE CHANNEL (IF ANY) WHOSE CLOSING CAUSED THIS + HRRZ TT,QUDPR(J) + SKIPL QSCRW(J) ;ONLY LOOK AT READ CHNLS + CAIE TT,(H) + JRST QDEL2 + HRRZ TT,QUDFPR(J) + SKIPL QUSR(J) + CAIE TT,(A) + JRST QDEL2 + MOVSI TT,%QADEL ;FOUND CHNL WITH THIS FILE OPEN + IORM TT,QSRAC(J) ;DELETE FILE WHEN THIS CHNL CLOSED + MOVSI TT,UNCDEL ;SET DELETED BIT + IORM TT,UNRNDM(Q) +QDEL4: MOVE TT,QACTB + IORM TT,QSNLCN(H) + MOVE TT,DCHBT(I) + IORM TT,QTUTO(I) +QDEL4B: PUSHJ P,QTULK + PUSHJ P,QUDULK + PUSHJ P,LSWPOP + JRST POPJ1 + +QDLA2: MOVE Q,QUDFPR(D) ;COMPUTE FILE ADR FROM CHNL IN D + ADD Q,QSNLCN(H) ;DIR MAY HAVE MOVED + JRST QDLA3 + +QDEL4A: SOS (P) + JRST QDEL4B + +QCDLWO: PUSH P,R ;OUTPUT CLOSE BUT FILE WAS DELEWO'ED + SETZM QSCRW(D) ;FAKE OUT ERROR CHECK AT QSQSH6 + PUSHJ P,QUDULK +QSICLD: MOVE H,QUDPR(D) ;ENTRY FROM INPUT CLOSE, FILE WAS DELETED + MOVE I,QDSKN(D) + PUSHJ P,QUDLK + MOVE Q,QSNLCN(H) + ADD Q,QUDFPR(D) + MOVE J,QPKID(I) + PUSHJ P,QUDULK + PUSH P,D + PUSHJ P,QDLA1 + BUG ;FILE ISNT THERE? + POP P,D + MOVE H,QUDPR(D) ;DIRECTORY NUMBER + SETOM QUSR(D) ;FREE THE DISK CHANNEL + AOS QFCHN + JRST QICLX + +QDELA1: PUSHJ P,QDEL4B ;NOT OUR DISK IN J + JFCL + MOVE J,TT ;DISK ITS REALLY ON +QDELA2: MOVSI I,-NQS ;TRANSLATE PACK # IN J TO DRIVE # IN I + CAME J,QPKID(I) + AOBJN I,.-1 + JUMPGE I,QPKNF1 + JRST QDELA + +QSOCLD: PUSH P,D ;DELETE FILE WHEN CLOSING OVER IT + PUSH P,R + LDB J,[UNPKN+UNRNDM(Q)] + PUSHJ P,QUDULK + PUSHJ P,QDELA2 + JFCL +QPKNF7: POP P,R + POP P,D + POPJ P, + +QPKNF1: PUSHJ P,QPKNFP ;MAYBE TUT NOT IN YET? + JRST QDELA2 ;YUP, TRY AGAIN + PUSHJ P,QUDLK + PUSHJ P,QLOOK + JRST QUDULK ;GONE AWAY BETWEEN LOCKS + JRST QDFPK ;GO DELETE OFF OF NON-MOUNTED PACK + +QDL2: PUSHJ P,QTULK ;DELETE LINK + MOVEI T,2 + PUSHJ P,LSWPON ;UNLOCK QCHSW +QDLINK: LDB E,[UNDSCP+UNRNDM(Q)] + IDIVI E,UFDBPW + ADD E,QSNLCN(H) + ADDI E,UDDESC + HLL E,QBTBLI(TT) + ILDB A,E + SKIPN E + BUG ;NULL LINK? + MOVEI B,0 +QDL1: DPB B,E ;CLEAR OUT THE CHAR + CAIN A,': + IDPB B,E ;CLEAR A QUOTED CHAR WITHOUT LOOKING AT IT + ILDB A,E + JUMPN A,QDL1 + PUSHJ P,QSQSH ;REMOVE ENTRY + MOVE TT,QACTB + IORM TT,QSNLCN(H) + PUSHJ P,QUDULK + JRST POPJ1 + +QDEL2: AOBJN J,QDEL1 ;CHECK NEXT DISK CHANNEL + MOVE C,UNRNDM(Q) ;NOT OPEN, SO REALLY DELETE IT + TLNE C,UNLINK + JRST QDL2 + ANDI C,.BM UNDSCP + IDIVI C,UFDBPW + ADD C,QSNLCN(H) + ADDI C,UDDESC + HLL C,QBTBLI(D) ;GET DESCRIPTOR POINTER IN C AND TT + MOVE TT,C + MOVEI A,0 + PUSHJ P,NFLLN1 ;A GETS NUMBER OF BLOCKS IN FILE + PUSH P,A + SKIPN D,QSFBT(H) ;SEE IF ENOUGH QSFBT STORAGE EXISTS + JRST QDEL11 +QDEL10: HLRE B,(D) ;NUMBER OF FREE LOCATIONS IN THIS PAGE + ADD A,B ;DECREASE LOCATIONS NEEDED + MOVE D,1(D) ;CDR + JUMPN D,QDEL10 +QDEL11: JUMPLE A,QDEL12 ;JUMP IF SUFFICIENT STORAGE EXISTS + PUSHJ P,TCALL ;GET MORE + JRST IOMQ + JRST [ MOVE U,USER ;U MAY NOT HAVE USER IF CAME FROM LOGOUT + PUSHJ P,LSWCLR ;HAVE TO WAIT FOR MEMORY + PUSHJ P,MQTEST ;AVOID DEADLOCKS BY UNLOCKING EVERYTHING + PUSHJ P,UFLS + JRST UUOTRO ] + MOVEI D,MU23FB + DPB D,[MUR,,MEMBLT(A)] + LSH A,10. + MOVEI D,2(A) + HRLI D,-1776 + MOVEM D,(A) + MOVE D,A + EXCH A,QSFBT(H) ;ADD TO FRONT OF LIST + MOVEM A,1(D) + MOVE A,(P) ;GET BACK NUMBER OF BLOCKS NEEDED + JRST QDEL10 ;SEE IF THERE ARE ENOUGH NOW + +QDEL12: POP P,A ;GET RID OF BLOCKS COUNT + PUSHJ P,QSQSH ;REMOVE ENTRY, CANNOT PCLSR AFTER THIS + CLEARB J,D ;J GETS NUMERIC TRACK NUMBER, D BYTE POINTER TO TUT + MOVE TT,QTUTO(I) ;D ZERO SO WILL HALT IF DESC DOESN'T START WITH LOAD-ADDR! + MOVE Q,QSFBT(H) ;Q -> AOBJN POINTER FOR STORING BLOCK NUMBERS +QDEL3: ILDB B,C ; INTO QSFBT AS DESCRIPTORS ARE ZEROED OUT + MOVEI A,0 ;I DISK, C BP TO DESCRIPTOR, A,B,E TEMP. + DPB A,C + JUMPE B,QDEL4 ;END OF FILE DESCRIPTION + TRNE B,40 + JRST QDEL6 + CAILE B,UDTKMX + JRST QDEL7 +QDEL8: SKIPN Q + BUG ;OOPS, OUT OF QSFBT STORAGE + SKIPL E,(Q) ;PICK UP AOBJN POINTER + JRST [ MOVE Q,1(Q) ;THIS PAGE FULL, TRY NEXT + JRST QDEL8 ] + MOVEM J,(E) ;STORE DISK,,BLOCK FOR LATER FREEING + AOBJN E,.+1 + MOVEM E,(Q) ;INCREMENT POINTER + MOVE E,QSNLCN(H) ;DECREASE DIR'S BLOCKS-USED + HRRZ A,UDBLKS(E) + SOSL A + HRRM A,UDBLKS(E) + ILDB A,D ;CHECK TUT + SKIPN A + BUG ;TUT SHOWS TRACK NOT USED + AOS J ;DO NEXT BLOCK IN CONTIGUOUS GROUP + SOJG B,QDEL8 + JRST QDEL3 + +IFN NXLBYT-2, .ERR THIS ROUTINE AND OTHERS KNOW IMPLICITLY THAT NXLBYT=2 +QDEL6: MOVEI D,0 ;LOAD ADDRESS + DPB B,[140500,,D] + ILDB B,C + DPB B,[060600,,D] + DPB A,C ;A HAS ZERO FROM QDEL3 + ILDB B,C + DPB B,[0600,,D] + DPB A,C + MOVE J,D + HRL J,I + PUSHJ P,TUTPNT + ADD D,[TUTBYT_14,,] ;MAKE INTO ILDB-TYPE POINTER + JRST QDEL7A + +QDEL7: CAIN B,UDWPH + JRST QDEL3 + SUBI B,UDTKMX + ADD J,B + IBP D + SOJG B,.-1 +QDEL7A: MOVEI B,1 ;LOAD ADDRESS OR SKIP AND TAKE, SO ONLY ONE TRACK + JRST QDEL8 + +QDFNF: PUSHJ P,OPNL4 + JRST URET + +QDELB: CONO PI,UTCON + JRST QDELA + +;PERFORM BLOCK-FREEING SPECIFIED BY QFBTS +QDLFBT: CONO PI,UTCOFF ;PROTECT QFBTS + SKIPN B,QFBTS + JRST UTCONJ + MOVE T,1(B) + MOVEM T,QFBTS + CONO PI,UTCON + HRRZ T,(B) ;FIRST FREE LOCATION + SUBI T,2(B) ;NUMBER OF LOCATIONS TO DO + HRLO A,T + EQVI A,1(B) + AOBJP A,QDLFB9 ;A NOW -> BLOCKS TO FREE, & CHECK FOR EMPTY + SETO I, ;NO TUT LOCKED YET +QDLFB1: HLRZ J,(A) ;DISK NUMBER + CAMN J,I ;MAKE SURE RIGHT TUT IS LOCKED + JRST QDLFB2 + SKIPL I + PUSHJ P,QTULK + MOVE I,J + PUSHJ P,QTLOCK +QDLFB2: HRRZ D,(A) ;BLOCK NUMBER TO FREE + PUSHJ P,TUTPNT + CAIGE B,TUTMNY ;USED IN "MANY" FILES(1,2,...,TUTMNY,TUTLK) + SOJL B,[JRST 4,.] ;HALT IF TUT SHOWS TRACK NOT USED + JUMPN B,QDLFB3 ;NOT LAST USE + HRRZ T,(A) ;BLOCK NUMBER AGAIN + MOVE TT,QTUTO(I) + CAML T,QSWAPA(TT) + AOSA QSFT(I) + AOS QSFTS(I) ;TRACK IN SWAPPING AREA +QDLFB3: DPB B,D ;DECREASE USAGE COUNT IN TUT + AOBJN A,QDLFB1 + PUSHJ P,QTULK +QDLFB9: MOVEI A,-1(A) ;GET AN ADDRESS ON THAT PAGE + LSH A,-10. ;DONE WITH THIS PAGE, FREE IT + PUSHJ P,TMEMR ;RETURN PAGE TO FREE AND TRY FOR MORE + MU23FB + JRST QDLFBT + +;REMOVE HOLE FROM NAME AREA AT Q +QSQSH: PUSH P,A + PUSH P,B + PUSH P,C + PUSH P,TT + HRRZ TT,QSNLCN(H) + MOVE A,UDNAMP(TT) + CAILE A,2000 + BUG ;UDNAMP BAD + ADDI A,(TT) + HRRZ C,Q + SUB C,A + SKIPL C + CAIL C,2000-UDDESC + BUG ;Q BAD + HRRZ C,Q +QSQSH1: SUBI C,LUNBLK + CAMLE A,C + JRST QSQSH2 + HRLZ B,C + HRRI B,LUNBLK(C) + BLT B,2*LUNBLK-1(C) + JRST QSQSH1 + +QSQSH2: +REPEAT LUNBLK,SETZM .RPCNT(A) + SUBI A,-LUNBLK(TT) + HRRZM A,UDNAMP(TT) + HRRZ C,Q + SUBI C,(TT) ;INDEX OF DELETED FILE + HRRZI TT,-LUNBLK(A) ;INDEX OF OLD BEGINNING OF NAME AREA + MOVSI A,-NQCHN +QSQSH3: HRRZ B,QUDPR(A) + SKIPL QUSR(A) + CAIE B,(H) + JRST QSQSH4 + SKIPN B,QUDFPR(A) + JRST QSQSH4 + CAIGE B,(TT) + BUG + CAIN B,(C) + JRST QSQSH6 ;PNTR TO FLUSHED HOLE, CHECK IF READ CHNL + CAIG B,(C) ;IF AFTER DELETED FILE DON'T RELOCATE + ADDI B,LUNBLK + HRRZM B,QUDFPR(A) + SKIPL QSCRW(A) + JRST QSQSH4 ;READ CHNL + ADD B,QSNLCN(H) + MOVE B,UNRNDM(B) + TLNN B,UNWRIT + BUG ;CHNL WRITING BUT BEING WRITTEN BIT NOT SET +QSQSH4: AOBJN A,QSQSH3 + POP P,TT + POP P,C + POP P,B + POP P,A + POPJ P, + +QSQSH6: MOVE B,QSRAC(A) ;FOUND PNTR TO DELETED FILE + TLNE B,%QADEL ;SKIP IF NOT DELETE AFTER CLOSE + SKIPGE QSCRW(A) ;ALSO ERROR IF NOT READ CHNL + BUG + JRST QSQSH4 ;WAS DELETE AFTER CLOSE ON READ CHNL + +SUBTTL DIRECTORY LOOK UP, > FEATURE + +;A contains the FN1 and B contains the FN2. +;H is the index of the directory slot. The dir must be locked. + +;Returns the address of the filename block in Q. +;Clobbers C. + +;Internally, J and Q point to the bottom and top of the +;area of the dir we are still searching. +;Bit 4.9 of J is set to indicate one of the names is ">". +;C used as a flag: sign bit says creating a file. +;Bit 1.1 of C says FN2 is > or <. + +;Look for place to create new file, +;and generate new version for >. +QFNG: MOVEM Q,EPDL3(U) + SKIPA C,[SETZ] +;Look for existing files only +QLOOK: MOVEI C,0 + PUSH P,J + HRRZ J,QSNLCN(H) + MOVEI Q,2000-LUNBLK(J) + ADD J,UDNAMP(J) + CAMN A,[SIXBIT />/] + TLOA J,400000 + CAMN A,[SIXBIT / + CAMN B,[SIXBIT />/] + TLOA J,400000 + CAMN B,[SIXBIT //] + JRST POPJJ ;MUST BE READ RETN FILE NOT FOUND +QLOOK1: JUMPGE C,QLOOK9 + CAMN B,[SIXBIT /" +QLOOK9: PUSH P,D + PUSH P,TT + PUSH P,I + PUSH P,[-1] ;BEST INDEX + PUSH P,[SETZ] ;BEST "NUMERIC" PART + PUSH P,[SETZ] ;BEST ALPHA PART +QLOOK4: CAIGE Q,(J) + JRST QLOOK2 + XCT QLKI1(C) + JRST QLOOK3 + MOVE D,UNRNDM(Q) + TLNE D,UNIGFL + JUMPGE C,[ SKIPGE -2(P) ;FILE LOCKED, REMEMBER IT IF WE HAVE NO BETTER, + HRRM Q,-2(P) ; BUT DON'T CONSIDER IT IF READING + JRST QLOOK3 ] ;BUT IF WRITING, CONSIDER ALL FILES + SKIPE TT,@QLKI1+1(C) +QLOOK6: TRNE TT,77 ;RIGHT ADJ + JRST QLOOK5 + LSH TT,-6 + JRST QLOOK6 + +QLOOK5: MOVEI I,0 +QLOOK8: LDB D,[600,,TT] + CAIL D,'0 + CAILE D,'9 + JRST QLOOK7 ;NOT A DIGIT +QLOK5B: TRNE I,77 ;RIGHT ADJ LOW NON NUM PART + JRST QLOK5A + LSH I,-6 + JUMPN I,QLOK5B +QLOK5A: TLC TT,400000 ;AVOID CAM LOSSAGE + TLC I,400000 + SKIPGE -2(P) + JRST QLOK5D ;FIRST MATCH + JUMPGE J,QLOK5E ;GET LEAST + CAMGE TT,-1(P) ;GET GREATEST + JRST QLOOK3 + CAME TT,-1(P) + JRST QLOK5D + CAMGE I,(P) + JRST QLOOK3 ;NOT AS GOOD +QLOK5D: HRRZM Q,-2(P) + MOVEM TT,-1(P) + MOVEM I,(P) +QLOOK3: SUBI Q,LUNBLK + JRST QLOOK4 + +QLOK5E: CAMLE TT,-1(P) + JRST QLOOK3 + CAME TT,-1(P) + JRST QLOK5D + CAMLE I,(P) + JRST QLOOK3 + JRST QLOK5D + +QLOOK7: LSHC TT,-6 ;LOW DIGIT NOT NUMERIC + JUMPN TT,QLOOK8 ;NO NUMERIC DIGITS AT ALL ("BIN", MAYBE?) + JUMPL J,QLOK5B ;IF LOOKING FOR GREATEST, LET THIS BE LEAST + MOVNI TT,1 ;GREATEST IF LOOKING FOR LEAST + JRST QLOK5B + +QLOOK2: JUMPL C,QFNG1 ;REALLY WANT TO MAKE F.N.'S FOR WRITE + SUB P,[1,,1] + POP P,C ;BEST "NUMERIC" PART + POP P,Q ;ADR + POP P,I + POP P,TT + POP P,D + AOJE Q,POPJJ + MOVE A,UNFN1-1(Q) ;ACTUAL MATCHED FILE NAMES + MOVE B,UNFN2-1(Q) + SOJGE Q,POPJJ1 ;FOUND A FILE THAT WASN'T LOCKED + MOVEI Q,-LUNBLK(Q) + JRST POPJJ + +QFNG1: SKIPGE -2(P) + JRST QFNG2 ;NOT FOUND START W/ 1 + MOVE TT,-1(P) + TLC TT,400000 + MOVE I,[600,,TT] +QFNG3: LDB D,I + CAIL D,'0 + CAILE D,'9 + JRST QFNG4 ;REACH END OF NUMERIC FIELD + AOS D + CAILE D,'9 + JRST QFNG5 + DPB D,I +QFNG5A: TLNE TT,770000 + JRST QFNG3A + LSH TT,6 + JRST QFNG5A + +QFNG2: MOVSI TT,(SIXBIT /1/) +QFNG3A: MOVEM TT,A(C) ;STORE INTO A OR B AS APPRO + SUB P,[3,,3] + POP P,I + POP P,TT + POP P,D + MOVE Q,EPDL3(U) + JRST POPJJ + +QFNG5: MOVEI D,'0 + DPB D,I + ADD I,[60000,,] + JUMPL I,QFNG5A + JRST QFNG3 + +QFNG4: TLNN TT,770000 ;SKIP ON ALREADY 6 CHAR NAME + LSH TT,6 + MOVEI D,'1 + DPB D,I + MOVEI D,'0 +QFNG4B: TLNN I,770000 + JRST QFNG5A + IDPB D,I + JRST QFNG4B + +QLKI1: CAME B,UNFN2(Q) + CAME A,UNFN1(Q) + UNFN2(Q) + +QPKNF: MOVE C,QSNUD(H) + PUSHJ P,QUDULK ;UNLOCK DIR + PUSHJ P,LSWPOP ;QUSR ENTRY + PUSHJ P,LSWPOP ;QSNNR ENTRY + PUSHJ P,QPKNFP + JRST QSKOL + PUSHJ P,OPNL16 ;PACK NOT MOUNTED + JRST URET + +QPKNFP: MOVSI I,-NQS +QPKNF3: SKIPGE QACT(I) + JRST QPKNF4 + MOVE TT,QTUTO(I) + SKIPL QDPWF(I) + TLNE TT,40000 + JRST QPKNF2 ;PACK NOT IN OR NOT PAWED OVER +QPKNF4: AOBJN I,QPKNF3 + JRST POPJ1 + +QPKNF2: JRST QTCH1 ;MAYBE THIS UNIT HAS GOODIES + +QFDF: PUSHJ P,OPNL5 ;FILE DIR FULL ON WRITE + JRST URET + +QPNL13: PUSHJ P,OPNL13 + JRST URET + +QPNL22: PUSHJ P,OPNL22 + JRST URET + +QPNLBN: +QPNL11: PUSHJ P,OPNL11 + JRST URET + +;ROUTINE TO FIND PLACE IN DIRECTORY WHERE A B WOULD GO +;SKIPS ONLY IF DIRECTORY CONTAINS AT LEAST ONE FILE +;FOR INSERTION, FILE GOES BEFORE PNTR RETURNED IN J +;RETURNS PNTR IN Q TO BEGINNING OF NAME AREA +;(ONLY WORKS FOR LUNBLK = 5) +QLGLK: HRRZ J,QSNLCN(H) + HRRZ Q,UDNAMP(J) + ADDI Q,(J) + CAIL Q,2000(J) + POPJ P, ;DIRECTORY EMPTY + TLC A,(SETZ) + TLC B,(SETZ) + PUSH P,D + PUSH P,E + ADDI J,600 ;128. NAME BLOCKS FROM END +REPEAT 7,[ ;THIS CODE DELIBERATELY NOT INDENTED. NEED 4 DIMENSIONS. + CAMGE J,Q + JRST .+6 + MOVE D,UNFN1(J) + TLC D,(SETZ) + CAMN A,D + JSP E,QLGLE + CAML A,D + ADDI J,<1_<7-.RPCNT>>*LUNBLK + SUBI J,<1_<6-.RPCNT>>*LUNBLK +] + CAMGE J,Q + ADDI J,LUNBLK + CAMGE J,Q + BUG + MOVE D,UNFN1(J) + TLC D,(SETZ) + CAME A,D + JRST QLGL1 + MOVE D,UNFN2(J) + TLC D,(SETZ) + CAMLE B,D +QLGL2: ADDI J,LUNBLK +QLGL3: TLC A,(SETZ) + TLC B,(SETZ) + POP P,E + POP P,D + JRST POPJ1 + +QLGL1: CAML A,D + JRST QLGL2 + JRST QLGL3 + +;CALL BY JSP E,QLGLE +QLGLE: MOVE D,UNFN2(J) + TLC D,(SETZ) + CAMN B,D + JRST QLGL3 + CAML B,D + JRST 1(E) + JRST 2(E) + +SUBTTL LOCKING ROUTINES + +QMLOCK: PUSHJ P,LSWTL + QMDRO + POPJ P, + +QMULK: PUSH P,U + MOVE U,USER + MOVE U,LSWPR(U) + HRRZ U,(U) + CAIE U,QMDRO + BUG + POP P,U + JRST LSWPOP + +QTLOCK: PUSHJ P,LSWTL + QTUTO(I) + POPJ P, + +QTULK: PUSH P,U + MOVE U,USER + MOVE U,LSWPR(U) + HRRZ U,(U) + CAIE U,QTUTO(I) + BUG + POP P,U + JRST LSWPOP + +QUDLK: PUSHJ P,LSWTL + QSNLCN(H) + POPJ P, + +QUDULK: PUSH P,U + MOVE U,USER + MOVE U,LSWPR(U) + HRRZ U,(U) + CAIE U,QSNLCN(H) + BUG + POP P,U + JRST LSWPOP + +SBTBLI: +QBTBLI: 440600,, ;IF GOING TO ILDB +SBTBL: +QBTBL: 360600,, + 300600,, + 220600,, + 140600,, + 060600,, + 000600,, + +TBTBL=.+1 +TBTBLI: REPEAT 1+TUTEPW, TUTBP-<.RPCNT*TUTBYT*010000,,> + +SUBTTL DIRECTORY GARBAGE COLLECTOR + +; MOVE H, directory number +; lock the directory +; PUSHJ P,QGC +; return if directory full. +; return if won. +; No ACs clobbered. +; All pointers to directory relocated appropriately. + +; Called from disk open routines if a new file is to be created +; and there are less than 6+LUNBLK words in the free area of the directory. +; Called from QSBWG if %QAFUL is set in QSRAC. +; %QAFUL means "must have successful GC before committing another track to this file." + +;NOTE NOTE NOTE: +; This GC allocates an extra block of core for temporary storage. +; If no memory is free in low half, waits without unlocking directory. +; Can possibly PCLSR. No deadly embrace to not unlock directory since +; it can't be flushed from core anyway and it's not holding anything else in. + +QAPBMN==NXLBYT+3 ;minimum number of descriptor bytes which + ; must be available at the end of a file to + ; commit another track to the file. + ;1 for a take-N, NXLBYT+1 for jump, 1 for ending zero. +QAPBMX==36. ;maximum number of descriptor bytes to allocate at a time. + +QGC: IRPC X,,ABCDQIJTR + PUSH P,X + TERMIN + +;Old GC prints message on system console. Any reason to with fast one? + +; validate the directory + +QGC00: SKIPL A,QSNLCN(H) + BUG ;directory not locked + MOVE C,UDNAME(A) + MOVEM C,LASTGC ;save name of last dir GCed + CAME C,QSNUD(H) + BUG ;directory clobbered + SKIPLE C,UDNAMP(A) + CAILE C,2000 + BUG ;name pointer out of bounds + IMULI C,UFDBPW + SKIPL D,UDESCP(A) + CAIL D,-UDDESC*UFDBPW(C) + BUG ;descriptor/name overlap + +; Get a block of core to use for temporary storage. +; The block is left in the "in-process" state. + + HRRZ Q,A + PUSHJ P,TCALL + JRST IOMQ + JRST [ PUSHJ P,UDELAY ;no core available in low half + JRST QGC00 ] ;so wait, then loop back to beginning + LSH A,10. + MOVEI B,1(A) ;zero it out + HRL B,A + SETZM (A) + BLT B,1777(A) + EXCH Q,A ;A -> directory, Q -> temporary core +;Drops through + ;Drops in +; Scan the directory and count: +; I all files +; J files open for writing +; R active bytes of descriptor + + SETZB I,J + SETZ R, + MOVEI B,2000(A) ;end of name area + ADD A,UDNAMP(A) ;start of name area +QGC10: CAML A,B + JRST QGC19 ;jump if all files done + SKIPE UNFN2(A) + SKIPN UNFN1(A) + BUG ;zero name block? + AOJA I,QGC12 ;file exists + +QGC11: ADDI A,LUNBLK ;advance to next file + AOJA R,QGC10 ;also count the zero byte that ends the descriptor + +QGC12: MOVE C,UNRNDM(A) + TLNE C,UNWRIT + ADDI J,1 + ANDI C,.BM UNDSCP ;get descriptor ptr (undscp has pos=0) + IDIVI C,UFDBPW + HLL C,QBTBLI(D) + ADDI C,UDDESC-2000(B) + MOVE D,UNRNDM(A) + TLNE D,UNLINK + JRST QGC14 +QGC13: ILDB T,C ;get byte of descrip + JUMPE T,QGC11 ;eof + CAIG T,UDWPH + AOJA R,QGC13 ;1-byte desc +REPEAT NXLBYT, IBP C ;multi-byte desc + ADDI R,NXLBYT+1 + JRST QGC13 + +QGC14: ILDB T,C ;count bytes of link descriptor + JUMPE T,QGC11 + CAIN T,': + AOJA R,[IBP C ;quoted + AOJA R,QGC14 ] + AOJA R,QGC14 + + +; Compute number of bytes of descriptor to add after each +; file open for output. If > QAPBMX, set to QAPBMX. +; If < QAPBMN, take directory-full exit. + +QGC19: MOVE C,I ;save number of files + IMULI I,LUNBLK*UFDBPW ;number of bytes in name area + ADDI R,UDDESC*UFDBPW(I) ;R := total number of bytes claimed + MOVEI A,2000*UFDBPW-1 + SUB A,R ;A := number of bytes left + SKIPE J + IDIV A,J ;number of bytes available to extend open files + CAIGE A,QAPBMN + JRST QGC69 ;if < minimum, dir. full + CAILE A,QAPBMX + MOVEI A,QAPBMX ;limit to at most QAPBMX bytes at a time +;Drops through + ;Drops in +; A = number of bytes of room to leave after each file open for writing +; B -> name block under consideration +; C -> old descriptors +; D = disk channel number under consideration. Also D = C+1 +; J counts new descriptor bytes generated +; Q -> new descriptors (in temporary core block) +; R -> base of directory + + SETZ J, + HRRZ R,QSNLCN(H) ;old dir + ADDI Q,UDDESC ;new dir + HLL Q,QBTBLI + MOVE B,UDNAMP(R) + ADD B,R + +; Loop over files + +QGC20: CAIL B,2000(R) + JRST QGC40 ;all files done + LDB C,[UNDSCP UNRNDM(B)] ;get old desc ptr + DPB J,[UNDSCP UNRNDM(B)] ;store new desc ptr + +; Loop over all disk channels, relocating the ones that point to this file + + MOVSI D,-NQCHN +QGC31: HRRZ T,QUDPR(D) + SKIPL QUSR(D) + CAIE T,(H) + AOBJN D,QGC31 ;not in use or not same directory + JUMPGE D,QGC39 ;jump if all disk channels done + LDB T,[1200,,B] + CAME T,QUDFPR(D) + JRST QGC32 ;not same file + MOVE T,J ;relocate descriptor pointer + SUB T,C + ADDM T,QDIRP(D) +QGC32: AOBJN D,QGC31 + +QGC39: IDIVI C,UFDBPW ;make desc pntr into byte pointer + HLL C,QBTBLI(D) + ADDI C,UDDESC(R) + MOVE T,UNRNDM(B) + TLNE T,UNLINK + JRST QGC22 +QGC21: ILDB T,C ;copy descriptor bytes of a file into temporary core + IDPB T,Q + JUMPE T,QGC23 + CAIG T,UDWPH + AOJA J,QGC21 +REPEAT NXLBYT,[ + ILDB T,C + IDPB T,Q +] ADDI J,NXLBYT+1 + JRST QGC21 + +QGC22: ILDB T,C ;copy descriptor bytes of a link into temporary core + IDPB T,Q + JUMPE T,QGC23 + CAIN T,': + AOJA J,[ILDB T,C + IDPB T,Q + AOJA J,QGC22 ] + AOJA J,QGC22 + +QGC23: MOVE T,UNRNDM(B) + TLNN T,UNWRIT + JRST QGC25 + ADD J,A ;file being written, increase desc area + MOVE T,A + IBP Q + SOJG T,.-1 + +QGC25: ADDI B,LUNBLK ;next file + AOJA J,QGC20 ;also account for final zero at end of descriptor + +; Paranoia: check that all disk channels to this directory look OK + +QGC40: MOVEM J,UDESCP(R) ;store free-desc pointer + LDB A,[1200,,Q] ;last word used by descriptors + CAML A,UDNAMP(R) + BUG ;overlap + ANDI Q,-2000 ;base of temp core block again + MOVSI A,-NQCHN +QGC41: HRRZ T,QUDPR(A) + SKIPL QUSR(A) + CAIE T,(H) + AOBJN A,QGC41 ;channel not in use, or to some other dir + JUMPGE A,QGC49 ;all channels done + SKIPN B,QUDFPR(A) ;get file open on this channel + JRST QGC42 ;channel not set up to any particular file + CAIGE B,2000 + CAMGE B,UDNAMP(R) + BUG ;file pointer screwed + ADD B,R + SKIPL J,QDIRP(A) ;get descriptor pointer + CAMLE J,UDESCP(R) + BUG ;descriptor pointer screwed + LDB C,[UNDSCP UNRNDM(B)] + CAIGE B,2000-LUNBLK(R) ;skip if last file in dir + LDB D,[UNDSCP UNRNDM+LUNBLK(B)] ;else get desc pntr for next file + CAIL B,2000-LUNBLK(R) + MOVEI D,2000*UFDBPW ;but if last file, get infinity + CAML J,C ;verify that QDIRP points to this file + CAML J,D + BUG +QGC42: AOBJN A,QGC41 ;do next channel + +; If you thought that was paranoid, get a load of this: + +QGC49: MOVE B,UDNAMP(R) + ADD B,R +QGC50: CAIL B,2000(R) + JRST QGC60 + LDB C,[UNDSCP UNRNDM(B)] + SOS C + IDIVI C,UFDBPW ;NOTE if UNDSCP = 0 we depend on bytes + HLL C,QBTBL(D) ; off left end of word LDB'ing as zero + ADDI C,UDDESC(Q) + LDB T,C + SKIPE T + BUG ;descriptor not preceeded by zero + MOVE J,UNRNDM(B) + TRZ J,#.BM UNDSCP ;LH(J) flags, RH(J) just desc pntr + TLNE J,UNLINK + JRST QGC52 +QGC51: ILDB T,C + JUMPE T,QGC53 + CAIG T,UDWPH + AOJA J,QGC51 +REPEAT NXLBYT, IBP C + ADDI J,NXLBYT+1 + JRST QGC51 + +QGC52: ILDB T,C + JUMPE T,QGC53 + CAIE T,': + AOJA J,QGC52 + IBP C + ADDI J,2 + JRST QGC52 + +QGC53: TLNE J,UNWRIT ;RH(J) has desc pntr to the zero that ends the file + ADDI J,QAPBMN ;if being written, needs room for one more track + CAIL B,2000-LUNBLK(R) ;now set D to point to next descriptor area + SKIPA D,UDESCP(R) ;do this instr if last file in dir + LDB D,[UNDSCP UNRNDM+LUNBLK(B)] ;else get next file's desc pntr + CAIG D,(J) + BUG ;descriptors overlap + ADDI B,LUNBLK + JRST QGC50 + +; Copy the descriptors back into the directory + +QGC60: MOVSI C,UDDESC(Q) ;make BLT pointer to copy it back + HRRI C,UDDESC(R) + MOVE B,UDNAMP(R) ;use same BLT to zero out the free area + ADD B,R + BLT C,-1(B) + +; Take win return. + + AOS -9(P) +QGC69: LDB A,[121000,,Q] ;core block number of temporary page + PUSHJ P,TMEMR ;return it + MUINP ;verifying that it is the right one. + IRPC X,,RTJIQDCBA + POP P,X + TERMIN + POPJ P, + +SUBTTL INTERPRET DESCRIPTORS + +QFNTR: MOVE H,QUDPR(A) ;BYTE # IN Q CHNL # IN A + PUSHJ P,QUDLK ;DONT SKIP IF OFF FILE + MOVE T,QSNLCN(H) ;RETN BLOCK IN QSLGL(A) AND QSBI(A) DIR PNTR IN QDIRP(A) + ADD T,QUDFPR(A) ;FIRST ADR OF BLOCK IN QFBLNO(A) + LDB TT,[UNDSCP+UNRNDM(T)] ;CHAR ADR OF FILE BEG + MOVEM TT,QDIRP(A) ;SKIPS IF FINDS BLOCK AND LEAVES USER DIR LOCKED + CLEARM QSBI(A) + CLEARM QFBLNO(A) + CLEARB J,QSLGL(A) ;J HAS ORG OF FIRST NON-EX-BLOCK IF OFF END OF FILE +QFNT1A: PUSHJ P,QFNT1 + JRST QUDULK ;OFF END OF FILE RETN NOT SKIPPING + CAMLE J,Q + JRST QFNT7 ;LOCATED BLOCK CONTAINING WORD + MOVEM J,QFBLNO(A) + JRST QFNT1A + +QFNTN: MOVE H,QUDPR(A) ;LIKE ABOVE BUT SCAN FORWARD ONLY FROM CURRENT SPOT + PUSHJ P,QUDLK + PUSHJ P,QFNT1 + CAIA ;EOF, DON'T SKIP RETURN + AOS (P) + MOVEM J,QFBLNO(A) + JRST QUDULK + +QFNT1: SKIPE QSBI(A) ;DECODE NEXT BLOCK, CHNL IN A, SKIP UNLESS EOF. + JRST QFNT2 ;BLOCK # IN QSLGL FILE ADR IN J (TAKE N PENDING) +QFNT3: PUSHJ P,QMPDCH ;GOBBLE NEXT CHR OF DESC IN R (POINTED TO BY QDIRP) INCR QDIRP + CAIN R,UDWPH ;ALSO RET BYTE PNTR IN TT + JRST QFNT3 ;NULL + JUMPN R,QFNT8 ;NOT OFF END OF FILE + SOS QDIRP(A) + POPJ P, + +QFNT8: TRNE R,40 + JRST QFNT4 + CAILE R,UDTKMX + JRST QFNT6 ;SKIP AND TAKE + MOVEM R,QSBI(A) +QFNT2: SOS QSBI(A) + AOS QSLGL(A) +QFNT5: MOVEI J,2000 ;ACTIVE BYTES IN BLOCK + IMULI J,@QSBYTE(A) + ADD J,QFBLNO(A) + JRST POPJ1 + +QFNT7: MOVSI T,%QALBK ;SET UP PROC LAST BLOCK FLG AND RETN + ANDCAM T,QSRAC(A) ;CLEAR LAST BLOCK OF FILE BIT + SKIPE QSBI(A) + JRST QFNT7A ;NOT LAST BLOCK + ILDB R,TT ;GET NEXT CHR IN DIR + JUMPN R,QFNT7A + IORM T,QSRAC(A) ;PROCESSING LAST BLOCK +QFNT7A: AOS QSBI(A) ;FAKE OUT PI ROUTINE WHICH WILL TRY TO INCREMENT + SOS QSLGL(A) + JRST POPJ1 + +QFNT4: MOVEI J,0 ;LOAD ADR + DPB R,[140400,,J] + PUSHJ P,QMPDCH + DPB R,[060600,,J] + PUSHJ P,QMPDCH + DPB R,[0600,,J] + MOVEM J,QSLGL(A) + JRST QFNT5 + +QFNT6: MOVEI J,1-UDTKMX(R) + ADDM J,QSLGL(A) + JRST QFNT5 + EBLK + +SUBTTL DISK CHANNEL DATA AREAS + +QBFP: BLOCK NQCHN ;BUFFER LIST LH LAST RH FIRST + ;READ: PI IN MP OUT. WRITE: MP IN PI OUT. +SINLST: BLOCK NQS ;SWAP-IN LISTS FOR EACH DISK +SOUTLS: BLOCK NQS ;SWAP-OUT LISTS FOR EACH DISK + +;READ/WRITE LISTS LINK THROUGH MLO IN MEMBLT. +;LH(MEMPNT) HAS DISK ADDR, RH(MEMPNT) HAS # BYTES IN BLOCK IF FILE READ +;MWC IN MEMBLT HAS WORD COUNT IF WRITE (FOR EXTRA-WORDS) + +QFCHN: NQCHN ;NUMBER OF FREE QSK CHNLS (NOT COUNTING DIR WRITE AND SWAP CHANNELS) + +QUSR: REPEAT NQCHN,-1 ;USER +DWUSR: -1 ;0 IF DIR WRITE ACTIVE +SWUSR: REPEAT NQS,-1 ;0 IF SWAP XFER ACTIVE +QDIRP: BLOCK NQCHN ;CHAR ADR PNTR TO DESC AREA FOR FILE +QSLBLK: BLOCK NQCHN+NQS+1 ;LAST BLOCK NUMBER OF FILE WRITTEN +QSLGL: BLOCK NQCHN ;LAST QSGL +QSGL: REPEAT NQCHN+NQS+1,-1 ;-1 IDLE + ACTIVE TRACK + ;LAST NQS+1 FOR FD WRITE AND SWAPPING +QSBI: BLOCK NQCHN ; COUNT CONSECUTIVE BLOCKS +QSBFS: BLOCK NQCHN ;NUMBER OF BUFFS THIS CHNL +1 IF EOF AT PI WITH QSBFS=0 +QPCLSR: BLOCK NQCHN ;PCLSR STATUS OF MAIN PROGRAM - LOAD SYSTEM CALL +QSMDN: BLOCK NQCHN ;MAIN PRGM ACTIVE BUFFER NUM +OLDRDT: BLOCK NQCHN ;STORAGE FOR PREVIOUS REFERENCE DATE +QSRAC: BLOCK NQCHN+1 + REPEAT NQS, %QMSWP ;SWAPPING CHANNELS START OUT IN SWAP MODE + %QA==525252(1) + %QALOK==400000 ;4.9 CHNL LOCKED (NOT USED) + %QAEFR==200000 ;4.8 EOF REACHED READ + %QAEFW==100000 ;4.7 EOF WRITE + %QACTH==40000 ;4.6 DONT RELOAD. CORE JOB HUNG ON ACTIVE BUFFER + %QAFUL==20000 ;4.5 GC DIR BEFORE COMMITTING ANOTHER BLOCK TO FILE + %QADEL==10000 ;4.4 DELETE WHEN CLOSED + %QAACC==4000 ;4.3 FILE ADDRESS ALTERED BY .ACCESS OR OTHERWISE + %QAPAR==2000 ;4.2 NON RECOV PARITY ERR (OR OTHER DISK ERR) AT PI + %QAOUT==1000 ;4.1 ASSOC USER OUT DONT RELOAD (NOT IMPLEM.) + %QALBK==400 ;3.9 READ CHNL PROCESSING LAST BLOCK FLAG + %QAMPU==200 ;3.8 UPDATE QSMPRP, QSMPRC ON NEXT BUFFER GOBBLE + %QAWOV==100 ;3.7 FILLING OUT LAST BLK OF FILE IN WRITE OVER MODE PAST ORIG EOF + %QALNK==40 ;3.6 FILE IS REALLY A LINK + %QALOP==20 ;3.5 LINKS WERE TRACED IN OPENING THIS FILE. + %QARWT==10 ;3.4 MAKE WOULD-BE READERS WAIT (RATHER THAN GETTING FILE LOCKED ERROR) + %QAFNY==4 ;3.3 "FUNNY BLOCK", WORD COUNT IN LAST WORD + ; 8/20/90 No longer ever gets set. + $QAMOD==220200 ;3.2-3.1 READ/WRITE MODE 0 NORMAL 1 WRITE OVER 2 COPY OVER WRITE + %QAMWO==1 ;3.1=1 => WRITE-OVER MODE. + %QM==777777 ;RH CHANNEL MODE. INDEX INTO ACTION TABLES USED AT PI LEVEL. +.SEE %QMIDL ;FOR TABLE OF CHANNEL MODES + +QDSKN: BLOCK NQCHN ;DISK UNIT NUMBER +DWSKN: 0 ;DISK WRITING DIR ON +SWSKN: REPEAT NQS,.RPCNT ;DISK SWAP XFER +QSCRW: BLOCK NQCHN ;0 READ -1 WRITE + -1 ;D.W. + BLOCK NQS ;SWAP +QSCABN: BLOCK NQCHN ;ACTIVE BUFFER NUMBER PI LEVEL OR -1 IF NONE +DWABN: -1 ;DISK D.W. A.B.N +SWABN: REPEAT NQS,-1 ;SWAP ABN +QUDPR: BLOCK NQCHN ;NUMBER OF ASSOCIATED USER DIR PNTR +QUDFPR: BLOCK NQCHN ;RELATIVE PNTR TO FILE AREA, ZERO IF NO PARTICULAR FILE +QMPTN: BLOCK NQCHN ;HAS LAST TRACK STORED IN DIRECTORY +QMPTC: BLOCK NQCHN ;MAIN PRGM TRACK COUNT +QMTTR: BLOCK NQCHN ;TRACK RESERVED OR -1 +QMFTP: BLOCK NQCHN+1 ;TRACK NUMBER FOR SCAN FOR FREE TRACKS IN TUT ON WRITE + REPEAT NQS,NUDSL; DITTO FOR SWAP CHANNELS +QERRS: BLOCK NQCHN+NQS+1 ;NUMBER ERRORS TRYING LAST OP +QSMPRP: BLOCK NQCHN ;MAIN PRGM BYTE POINTER +QSMPRC: BLOCK NQCHN ;M.P. COUNT (BYTES LEFT IN BUFFER) +QSBYTE: BLOCK NQCHN ;LH BYTE PNTR (P=44), RH BYTES PER WORD +QSBSIZ==300600,,QSBYTE ;BYTE POINTER TO CHANNEL BYTE SIZE +QFBLNO: BLOCK NQCHN ;BYTE # IN FILE OF BEG OF BLOCK BEING PROCESSED AT M.P. LEVEL +QRADAD: BLOCK NQCHN ;DESIRED BYTE ADR (LOOKED AT IF %QAACC OR %QAMPU IN QSRAC SET) +QPIBSZ: BLOCK NQCHN ;NUMBER OF BYTES IN BLOCK ACTIVE AT P.I. LEVEL (READ) + ;BIT 4.9 => GET FROM LAST WORD IN BLOCK (%QAFNY) + ; 8/20/90 %QAFNY can no longer happen. +QMPBSZ: BLOCK NQCHN ;NUMBER OF BYTES IN MN PROG ACTIVE BUFFER +QLDPTR: BLOCK NQCHN .SEE NLDSBQ ;DURING SBLK LOADING, HOLDS THE AOBJN POINTER + ;INTO USER CORE FOR DOING A DISK TRANSFER ON. +QSMMP: BLOCK NQS ;MMP ADDRESS OF BLOCK ACTIVE ON SWAPPING CHANNEL + +;VARIABLES FOR CURRENT TRANSFER + +QSDU: -1 ;UNIT TRANSFERING DATA, -1 IF NONE. +QSDCH: -1 ;CHNL READY TO BE TRANSFERED ON QSDU +QERS1: -1 ;ERR VERIFY SWITCH -1 NO ERR 0 EXPECTING COMPLETION OF VERIFY OP +QDWIP: 0 ;NUMBER OF DIR WRITE IN PROGRESS 4.9=1=>MASTER + +IFN T300P,[ +QSDU1: -1 ;QSDU FOR OTHER CONTROLLER +QSDCH1: -1 ;ASSOCIATED CHANNEL +QTUNT1: -1 ;UNIT TO TRANSFER NEXT +QTCHN1: -1 ;CHANNEL TO TRANSFER NEXT +NRXFR1: 0 ;METERS +NWXFR1: 0 +NSRXF1: 0 +NSWXF1: 0 +LQTM1: 0 ;TIME LAST TRANSFER STARTED +];T300P + +;MASTER FILE DIRECTORY + +QMDRO: -1 ;ORIGIN OF MASTER DIR 4.9 IF LOCKED + ;-2 ON WAY IN + ;4.6 NOT IN + ;4.5, 4.4, 4.3, ... CHANGED + NOT WRITTEN UNIT 0, 1, 2, ... + ;3.2=1 NOT RECONCILED (NQFUS NOT SET UP) + ;3.1-3.5 MUST BE ZERO (AT LEAST AFTER ITS RECONCILED) +QAMDNO: -1 ;ASCENDING MASTER DIRECTORY NUMBER, -1 NOT SET UP +NQFUS: 0 ;NUMBER OF FREE LOSER SLOTS IN MFD + +;TRACK UTILIZATION TABLES + +QTUTO: REPEAT NQS,-1 ;ADDRESS OF TUT. LH SIMILAR TO QMDRO + ;4.9 LOCK + ;4.8 READ-IN NOT STARTED YET + ;4.6 NOT READ IN YET + ;CHANGED AND NOT WRITTEN ON UNIT + ;0 = 4.5 1 = 4.4 2 = 4.3 3 = 4.2 4 = 4.1 + ;5 = 3.9 6 = 3.8 + ;3.1-3.5 MUST BE ZERO +QDPWF: BLOCK NQS ;-1 TUT NOT RECONCILED (CALL QTCH1) +QTWRTM: BLOCK NQS ;TIME TUT LAST WRITTEN +QSFT: REPEAT NQS,-1 ;NUMBER TRACKS FREE IN USER AREA +QSFTS: BLOCK NQS ;NUMBER TRACKS FREE IN SWAPPING AREA +QPKNM: BLOCK NQS ;NAME OF PACK +QPKID: REPEAT NQS,-1 ;PACK ID OF DISK ON DRIVE +IFN QRSRVP,[ +QRESRV: REPEAT NQS,-1 ;NON-ZERO => PACK ON THIS DRIVE RESERVED. SET FROM TUT. + ;NOT 0 AND NOT -1 => SIXBIT DEVICE NAME FOR "SECONDARY" PACK +];QRSRVP +NTBL: ;NUMBER OF BLOCKS IN TUT ON THIS DRIVE +IFE T300P, REPEAT NQS, NTUTBL +IFN T300P,[ + REPEAT T300P, NTUTBL + REPEAT NQS-T300P, NTUTB1 +];T300P + +;POSITIONER VARIABLES (INDEXED BY PHYSICAL DRIVE) + +QSKT1: REPEAT NQS,-1 ;CHANNEL POSITIONER SET FOR OR -1 IF NONE +QRCAL: REPEAT NQS,0 ;-1 IF RECALIBRATING +QSPPS: REPEAT NQS,-1 ;INTENDED POSITIONER POSITION (NOT USED???) +QSEEK: BLOCK NQS ;-1 IF SEEKING +QPOS: REPEAT NQS,-1 ;CURRENT CYLINDER +QPOSGL: BLOCK NQS ;CYLINDER TRYING TO POSITION TO +IFN DC10P,[ +QRCTIM: BLOCK NQS ;RECALIBRATE TIMEOUT IN HALF SECONDS. THE ATTNS +];DC10P ; TEND TO GET LOST FOR SOME REASON + +;MISCELLANEOUS DISK VARIABLES + +QACT: REPEAT NQS,0 ;ONLY USE UNITS WITH 0 +QACTB: 0 ;4.5 UNIT 0 ACT 4.4 1 ACT 4.3 2 4.2 3 4.1 4 + ;3.9 5 3.8 6 +QWBUFS: 0 ;TOTAL NUMBER OF WRITE BUFFERS ACTIVE + +QWBFMX: 10.*DC10P+15.*RP10P+30.*RH10P+20.*RH11P ;MAX # ALLOWED. SHOULD BE + ; ABOUT 1 SEC DISK XFER. +QHUNGF: 0 ;-1 => DISK CONTROL HUNG, PI LEVEL SHOULD RESET, RECALIBRATE, RETRY +NTQHNG: BLOCK NQS ;NUMBER OF TIMES TRANSFER HUNG ON THIS UNIT + +QTUNT: 0 ;UNIT TO TRANSFER ON NEXT +QTCHN: 0 ;CHNL .. +QLCHN: 0 .SEE QINT2C +QWRU: -1 ;DEFAULT WRITE UNIT (-1 if there isn't a default unit yet) +MDSK: 0 ;DRIVE # OF MASTER DISK +QACTTM: -1 ;SETOM ON READ OR WRITE DATA TRANSFER + ;AOS AT SSLCK IF + OK TO WRITE DIRS + ;IE DON'T TIE UP DISK TO WRITE DIR UNLESS THINGS ARE QUIET +QDWFAR: -10. .SEE QINT3 ;WRITE DIRS SOME OF THE TIME ANYWAY +LQTM: 0 ;TIME AT WHICH LAST COMMAND GIVEN TO DISK +QFTTHR: 600. ;IF FREE TRKS ON QWRU GOES BELOW THIS, SWITCH TO UNIT WITH MOST FREE TRACKS +QRDAHD: IFE MCOND DM,[0] .ELSE 2 ;NUMBER OF BLOCKS TO READ AHEAD + +LASTGC: 0 ;NAME OF LAST DIRECTORY TO GET GC'ED + +;USER DIRECTORIES + +QNUD==40. ;NUMBER USER DIRECTORIES + +QFUD: QNUD ;NUMBER OF FREE UFD SLOTS + +QSNUD: BLOCK QNUD ;USER NAME OR 0 IF FREE +QSNLCN: BLOCK QNUD ;4.9 LOCKED, 4.8 ALSO NOT IN CORE RH CORE ADR + .SEE DCHBT ;4.6 =1 NOT PAWED OVER 4.5 CHNGD AND NOT WRITTEN ON UNIT 0 + ;4.4 UNIT 1 4.3 UNIT 2 4.2 UNIT 3 4.1 UNIT 4 + ;3.9 UNIT 5 3.8 UNIT 6 3.7 UNIT 7 + %QUDWM==40 ;3.6 WRITE IMMEDIATELY ON MASTER DISK + ;@ + XR BITS MUST = 0 + +QSNNR: BLOCK QNUD ;NUMBER PC'S LOOKING AT THIS IE + ;+1 FOR FILE OPEN AND USER IN CORE(?) +QSNMI: BLOCK QNUD ;TRACK N OF USER DIR IF NOT NEWLY CREATED +QSFBT: BLOCK QNUD ;FREED-BLOCKS-TABLE. HEAD OF A LIST OF PAGES, + ;THREADED THROUGH THE SECOND WORD AND ENDING WITH + ;ZERO. FIRST WORD IS AOBJN POINTER TO FREE PART + ;OF PAGE. FROM THIRD WORD UP TO BELOW WHERE AOBJN + ;POINTS ARE WORDS UNIT,,BLOCK WHICH RECORD DISK + ;BLOCKS TO BE FREED ONCE THE DIR HAS BEEN WRITTEN + ;OUT TO THE MASTER DISK. ELIMINATES REUSED ADDRESS + ;PROBLEMS BY GUARANTEEING THAT IF THE SYSTEM SHOULD + ;CRASH AT ANY TIME, THERE CANNOT BE TWO DIRECTORIES + ;ON DISK THAT BOTH POINT TO THE SAME BLOCK. + +IFN QRSRVP,[ +QSALLO: BLOCK QNUD ;-1 OR DRIVE # DIRECTORY ALLOCATED TO +] + +;LOCKS + +UDRSW: -1 ;USER DIR AREA LOCKED + 0 +QCHSW: -1 ;CHNL AREA LOCKED + 0 +QSKOSW: -1 ;QSKO1 LOCKED (USER DIR READIN) + 0 + +;LIST OF PAGES CONTAINING BLOCKS WHICH CAN NOW BE FREED. MOVED TO +;HERE FROM QSFBT WHEN THE DIR IS WRITTEN OUT. THE ACTUAL FREEING +;IS DONE BY THE CORE JOB. + +QFBTS: 0 + +;VARIABLES FOR SYSTEMS CONCEPTS DISK CONTROL + +IFN DC10P,[ +QRCSW: 105 ;- NO READ COMPARE 0 COMPARE WRITES + COMPARE ALL +QCST: 0 ;CONI DC0, AT QINT +QERST: 0 ;HAS CONI DC1, BITS WHEN AN ERROR HAPPENS +PKIDM: 0 ;-1 WAITING FOR PACK ID TO BE READ +RPKID: -1 ;PACK ID READ INTO HERE BY DISK CONTROL +QDRSTS: 0 ;DRIVE STATUS WORD STORED BY DISK CONTROL +] +IFE DMDSK,[ + 0 ;FOR BLT INTO QXWDS +QXWDS: BLOCK NXWDS +] +IFN DC10P,[ +QCHPRG: 0 +QCHPR2: DCOPY (-2000_2&37774) + DCOPY (-NXWDS_2&37774)QXWDS +QCHPR4: DHLT ;OR DRC +QCHPR3: DCCOMP (-2000_2&37774) + DCCOMP (-NXWDS_2&37774)QXWDS + DHLT + +GPKID: DSPC+DSCRHD+DSWNUL+DUNENB+TUTCYL_11.+TUTSRF_6+TUTSEC + DCOPY RPKID(37774) + DHLT +QRECAL: DSPC+DSRCAL+DUNENB +] + +;VARIABLES FOR DEC RP10 DISK CONTROL + +IFN RP10P,[ +QERST: 0 ;CONI DPC, ON ERROR +QERDTI: 0 ;DATAI DPC, ON ERROR +QCST: 0 ;CONI DPC, AT QINT +QCHPRG: 0 ;SEEK COMM +IFN KA10P, QIOWD: -2000,, ;XFER DATA (HRRM ADR-1 IN RH) +IFE DMDSK,[ + -NXWDS,,QXWDS-1 + -200+NXWDS,,0 +];DMDSK + 0 + +QRECAL: 700000,, +QGTBZY: 0 ;FLAG FOR SOFTWARE AT INT +];RP10P +IFN QRDCMP,[ +QRCSW: 0 ;NON-ZERO TO ENABLE READ-COMPARING +RDCPHS: 0 ;0 NORMAL, -1 DOING OPERATION WHICH SHOULD BE READ-COMPARED + ; AFTERWARD, + DOING READ-COMPARE +IFN KA10P,[ +RCIOWD: BLOCK 2 ;CHANNEL PROGRAM FOR READ INTO QRCBUF +];KA10P ;ON KL WE HAVE TO PUT IT IN THE EPT! +QRCBUF: BLOCK 2000 +];QRDCMP + +;VARIABLES FOR DEC RH10 DISK CONTROL + +IFN RH10P,[ +QCHPRG: 0 ;DATA TRANSFER COMMAND +QCHPGA: 0 ;ADDRESS (CYL IN LH, TRACK-SECTOR IN RH) +NCSHI: 0 ;NUMBER OF CACHE INVALIDATES +NCSHIL: 0 ;NUMBER OF LOOPS WAITING FOR CACHE INVALIDATES +NCSHU: 0 ;NUMBER OF CACHE UNLOADS +NCSHUL: 0 ;NUMBER OF LOOPS WAITING FOR CACHE UNLOADS +QERST: 0 ;CONI AT LAST ERROR (LEAVE THIS THROUGH QECPAT IN SAME ORDER) + 0 ;DATAI AT LAST ERROR +QERSTS: 0 ;%HRSTS AT LAST ERROR +QERER1: 0 ;%HRER1 AT LAST ERROR +QERER2: 0 ;%HRER2 AT LAST ERROR +QERER3: 0 ;%HRER3 AT LAST ERROR (IBM WOULD CALL THIS A CHANNEL LOGOUT AREA) +QERDCL: 0 ;%HRDCL AT LAST ERROR +QECPOS: 0 ;%HRPOS AT LAST ERROR +QECPAT: 0 ;%HRPAT AT LAST ERROR +QCST: 0 ;CONI AT LAST INTERRUPT +QGTBZY: 0 ;FLAG FOR SOFTWARE-CAUSED INTERRUPT +QECCS: BLOCK NQS ;NUMBER OF ECC CORRECTED ERRORS, PER DRIVE +QECCAD: BLOCK NQS ;DISK ADDRESS OF MOST RECENT ECC CORRECTED ERROR +RHDATO: -1 ;LAST DATAO DSK, FOR DEBUGGING +ECCPAG: BLOCK 8 ;TEMP FOR SAVING PAGE MAP VARS AT QECC (WITH SPM) +NQDRE: BLOCK NQS ;# MASSBUS TIMEOUTS PER DRIVE. +NQSATN: BLOCK NQS ;# SPURIOUS ATTENTIONS IN MID-TRANSFER +NQEATN: BLOCK NQS ;# ATTENTIONS REPORTING ERRORS +] + +;VARIABLES FOR DEC RH11 DISK CONTROL (ON THE KS10 UNIBUS) + +IFN RH11P,[ +QCHPRG: 0 ;DATA TRANSFER COMMAND +QCHPGA: 0 ;ADDRESS (CYL IN LH, TRACK-SECTOR IN RH) +QIOWD: 0 ; BA,,WC for RH11 +QCST: 0 ;CS1 AT LAST INTERRUPT +QGTBZY: 0 ;FLAG FOR SOFTWARE-CAUSED INTERRUPT + +QERST:: ;Gubbish saved at last error +QERCS1: 0 ; CS1 Control & Status 1 +QERCS2: 0 ; CS2 Control & Status 2 +QERSTS: 0 ; STS Drive status +QERBA: 0 ; BA Unibus address for transfer +QERWC: 0 ; WC Word count for transfer +QERER1: 0 ; ER1 Error 1 +QERER2: 0 ; ER2 Error 2 +QERER3: 0 ; ER3 Error 3 +QERPOS:: +QECPOS: 0 ; POS ECC position +QERPAT:: +QECPAT: 0 ; PAT ECC pattern +QERMAP: 0 ? 0 ; Unibus map to disk buffer + +QECCS: BLOCK NQS ;NUMBER OF ECC CORRECTED ERRORS, PER DRIVE +QECCAD: BLOCK NQS ;DISK ADDRESS OF MOST RECENT ECC CORRECTED ERROR + +NQSATN: BLOCK NQS ;# SPURIOUS ATTENTIONS IN MID-TRANSFER +NQEATN: BLOCK NQS ;# ATTENTIONS REPORTING ERRORS +NQOFFL: BLOCK NQS ;# TIMES DISK WENT OFFLINE +] + +DIRHNG: 0 ;LH POINTS TO LIST OF DIRHNG DEVICE CHANNELS, + ;CHAINED THROUGH LH'S OF IOCHNM WORDS. + ;0 MEANS END OF LIST + ;MODIFY ONLY WITH THE CLOCK OFF. + ;EACH DIRHNG DEVICE CHANNEL'S IOCHST WORD RH CONTAINS THE + ;TRACK NUMBER OF THE DIRECTORY IT IS LOOKING AT. + +BBLK + +;DISK CONSTANTS + +IFN RP10P,[ +QATTNS: REPEAT NQS,500000+.RPCNT_14,,1_<10-.RPCNT> +;WORDS TO CLEAR ATTNS AND SELECT DRIVES +] + +SWAPL: SINLST(Q) + SOUTLS(Q) + +DCHBT: 20000,, ;BIT SET IF DIR NOT WRITTEN OUT ON UNIT + 10000,, + 4000,, + 2000,, + 1000,, + 400,, + 200,, + 100,, +IFL .-DCHBT-NQS,.ERR YOU BETTER FIND ANOTHER BIT FOR QACTB,QSNLCN,QTUTO + +IFN DC10P,[ +QTRAN: 0 ;FORMERLY MAPPED 203 CYL VIRTUAL DRIVES TO 406 CYL CALCOMPS + 1 ;4.9 => 2ND HALF OF PHYSICAL DRIVE + 2 ;(DOESN'T DO ANYTHING NOW THAT MEMOWRECKS ARE GONE, + 3 ; BUT KEEP AROUND IN CASE EVER NEEDED AGAIN.) + 4 + 5 + 6 + 7 +IFL .-QTRAN-NQS, .ERR BARF AT QTRAN +] + +SUBTTL DISK CLOSE ROUTINES + +QICL: PUSH P,R + SKIPGE QUSR(A) + BUG + MOVSI Q,%QAACC + ANDCAM Q,QSRAC(A) ;FLUSH RANDOM ACCESS HACKERY + PUSHJ P,QICLW1 ;WAIT FOR INPUT TO STOP + MOVE TT,QSRAC(D) + TLNE TT,%QADEL ;DELETE? + JRST QSICLD ;YES + MOVE H,QUDPR(D) ;DIRECTORY NUMBER + SETOM QUSR(D) + AOS QFCHN +QICLX: SOSGE QSNNR(H) ;FREE DIRECTORY CHANNEL HAD BEEN USING + BUG + POP P,R + SETZM (R) + POPJ P, + +QICLW1: MOVE D,A ;IDLE CHANNEL AND FLUSH READ BUFFERS + CONO PI,UTCOFF + SKIPGE QSGL(D) + JRST QSICL3 + SKIPL QSCABN(D) + JRST QSICL4 + SETOM QSGL(D) + +QSICL3: HLLZS QSRAC(D) .SEE %QMIDL ;STOP PI + CONO PI,UTCON +QSICL5: PUSHJ P,QSBRB1 ;RETURN M.P. BUFFER IF ANY +QOCL7: HRRZ A,QBFP(D) ;ALSO ENTER TO RETURN UNUSED READ BUFFER ON WRITE OVER MODE +QSICL2: JUMPE A,QSICL6 + LDB C,[MLO,,MEMBLT(A)] + PUSHJ P,MEMR + MOVE A,C + SOS QSBFS(D) + JRST QSICL2 + +QSICL6: SETZM QBFP(D) + POPJ P, + +QSICL4: MOVEI A,%QMRD1 ;STOP PI AFTER THIS BLOCK + HRRM A,QSRAC(D) + CONO PI,UTCON + SKIPL QSGL(D) ;WAIT FOR CHANNEL TO DEACTIVATE + PUSHJ P,UFLS + JRST QSICL5 + +;OUTPUT CLOSE +QOCL: PUSHJ P,QSOCL5 ;CLEAN UP THE DISK CHANNEL +QSOCL4: MOVE D,A ;ENTRY FROM QALINK +QSOCL6: MOVE Q,QUDFPR(D) + MOVE H,QUDPR(D) + ADD Q,QSNLCN(H) + MOVE TT,QSRAC(D) + TLNE TT,%QADEL + JRST QCDLWO ;DELETED (PRESUMABLY VIA DELEWO) + MOVE A,UNFN1(Q) ;Get names of file being hacked. + MOVE B,UNFN2(Q) + PUSHJ P,QLOOK ;FILING OVER ANYTHING? + JRST QSOCL3 + HRRZ I,QSNLCN(H) + ADD I,QUDFPR(D) + CAMN I,Q ;BEING WRITTEN BITS WENT AWAY? + BUG ;TRYING TO DELETE THE FILE WE'RE WRITING + PUSHJ P,QSOCLD ;YES FLUSH IT + PUSHJ P,QUDLK ;RELOCK DIR UNLOCKED BY QSOCLD ETC + JRST QSOCL6 ;MAKE SURE ONE HASN'T REAPPEARED WHILE DIR UNLOCKED + +QSOCL5: LDB H,[$QAMOD,,QSRAC(A)] + JUMPN H,QOCL6 ;DONT HACK ACTIVE WD COUNT IN WRITEOVER MODE +QOCL6A: MOVN D,QSMPRC(A) ;- NUMBER OF BYTES IN BLOCK NOT USED + ADDB D,QMPBSZ(A) ;ADJUST BYTE COUNT OF LAST BLOCK TO REFLECT WHATS USED + CLEARM QSMPRC(A) ;SO WILL BE A NOOP IF PCLSR OUT AND COME BACK THRU HERE +QOCL4: MOVSI Q,%QAEFW + IORM Q,QSRAC(A) ;SET EOF BIT FOR QSBWW AND QUDS + JUMPN H,QOCL5 + SKIPL QSMDN(A) ;NO M.P. BUFFER ANYWAY + JUMPE D,QOCL1 ;ABOUT TO WRITE NULL BLOCK, DON'T +QOCL5: PUSHJ P,QSBWW +QOCL2: MOVE T,A + PUSHJ P,[ SKIPGE QSCRW(T) ;WAIT FOR CHANNEL EITHER LEAVING WRITE MODE + SKIPN QSBFS(T) ;OR WRITING OUT ALL ITS BUFFERS, I.E. PI LEVEL + JRST POPJ1 ;ISN'T GOING TO DO ANYTHING MORE TO IT. + POPJ P, ] + PUSHJ P,UFLS + SKIPE QBFP(A) ;MAKE SURE IF QSBFS NON-ZERO THAT IS ONLY EOF + BUG ;NOT A BUFFER SITTING AROUND FORGOTTEN +QOCL3: MOVE H,QUDPR(A) + PUSHJ P,QUDLK + SKIPN D,QMPTC(A) ;SKIP ON NEXT "N" STILL PENDING + POPJ P, + PUSHJ P,QUDS ;STORE IT AWAY + CLEARM QMPTC(A) + POPJ P, + +QOCL6: SKIPGE QSCRW(A) ;WAIT FOR CHANNEL TO IDLE OR HANG UP IN READ + PUSHJ P,UFLS + SKIPL QSGL(A) + PUSHJ P,UFLS + MOVE D,A + PUSHJ P,QOCL7 + MOVE A,D + MOVE Q,QSRAC(A) + MOVE B,QSBFS(A) + JUMPE B,QOCL6B + TLNE Q,%QAEFW + JRST QOCL6B + TLNE Q,%QAEFR + SOS B,QSBFS(A) ;COMPENSATE FOR EXTRA AOS ON EOF READ +QOCL6B: CAILE B,1 + BUG + TLNE Q,%QAWOV + JRST QOCL6A ;HACKING LAST BLOCK PAST EOF, UPDATE ACTIVE WD COUNT + JRST QOCL4 + +QOCL1: PUSHJ P,QSBRB ;DISCARD BUFFER + SOS QSBFS(A) + SOS QWBUFS + MOVE D,QDSKN(A) + AOS QSFT(D) ;RESTORE TRACK + JRST QOCL2 + +QSOCL3: MOVE Q,QUDFPR(D) + MOVE TT,QSNLCN(H) + ADDI Q,(TT) + MOVSI T,UNWRIT + ANDCAM T,UNRNDM(Q) ;CLEAR WRITE IN PROG + MOVE TT,QSNLCN(H) + MOVE T,UDNAMP(TT) ;MAKE SURE IT GOES BEFORE * FILE OF SAME NAME + ADDI T,(TT) + CAMN T,Q + JRST QSOC3E ;NO PREV FILE + MOVE J,Q +QSOC3A: SUBI J,LUNBLK + CAMN A,UNFN1(J) + CAME B,UNFN2(J) + JRST QSOC3B ;PREV FILE HAS DIFFERENT NAME + CAILE J,(T) + JRST QSOC3A +QSOC3C: CAMN J,Q + JRST QSOC3E +REPEAT LUNBLK, PUSH P,.RPCNT(J) + MOVE T,J + HRL T,Q + BLT T,LUNBLK-1(J) +REPEAT LUNBLK, POP P,LUNBLK-.RPCNT-1(Q) + SUB Q,J + SUBI J,(TT) + MOVSI T,-NQCHN +QSOC3D: HRRZ A,QUDPR(T) + SKIPL QUSR(T) + CAIE A,(H) + JRST QSOC3F + HRRZ A,QUDFPR(T) + CAIN A,(J) + ADD A,Q + MOVEM A,QUDFPR(T) +QSOC3F: AOBJN T,QSOC3D +QSOC3E: SETOM QUSR(D) ;FREE THE DISK CHANNEL + AOS QFCHN + MOVE C,QSNUD(H) +IFN TPLP+UNSPLP,[ + MOVEI TT,SCRTPC + CAMN C,[SIXBIT /.LPTR./] + IORM TT,SUPCOR ;CLOSING FILE ON TPL DEVICE SO SET FLAG FOR SYS JOB +];TPLP + CAMN C,[SIXBIT/.MAIL./] + AOS NQMFWR ;CLOSING FILE ON .MAIL. => BUMP COUNT TO WAKE MAILER DEMON +IFN XGP,[ + CAMN C,[SIXBIT/.XGPR./] + AOS NXGPFW ;WAKE XGPSPL +];XGP + MOVE A,QSNMI(H) ;TELL DIRHNG DEVICE ABOUT IT + PUSHJ P,DIRSIG + MOVE TT,QACTB ;DIR CHANGED (AT LEAST WRITE-IN-PROG BIT TURNED OFF) + IORM TT,QSNLCN(H) + PUSHJ P,QUDULK + SOSGE QSNNR(H) + BUG + PUSHJ P,QSTRTR + SETZM (R) ;CLEAR IOCHNM WORD. + POPJ P, + +QSOC3B: ADDI J,LUNBLK + JRST QSOC3C + +QOCLR: MOVE Q,QSRAC(A) ;CLOSE UNIT ASCII OUTPUT + TLNN Q,%QAWOV + TLNN Q,%QAMWO+%QALNK + PUSHJ P,QOCLPD ;PUT NEEDED PADDING UNLESS NOT A FILE OR NOT AT END + JRST QOCL + +QOCLPD: LDB Q,[360600,,QSMPRP(A)] ;NUMBER OF BITS NOT WRITTEN IN LAST WORD + CAIL Q,44 + POPJ P, ;LAST WORD NOT WRITTEN AT ALL + LSH Q,18.+6 ;FILL THOSE BITS WITH ^CS + HRR Q,QSMPRP(A) + MOVE C,[EOFWRD] + SKIPLE QSMPRC(A) ;INHIBIT STORE IF NO BUFFER ETC. + DPB C,Q + POPJ P, + +SUBTTL DISK INTERRUPT ROUTINES + +OVHMTR QIN ;DISK INTERRUPT LOW-LEVEL + +IFN RP10P,[ + +QINT: AOS QGTBZY + MOVEM TT,QCST +IFN DMDSK,[ + TRNN TT,200000 ;END OF CYLINDER + JRST QINT0 + SKIPGE C,QSDCH + BUG + MOVE D,QSGL(C) + IDIVI D,NBLKSC ;IS IT LEGITIMATE? + SKIPL QSDU ;IF NO TRANSFER IN PROGRESS, IGNORE + CAIN E,NBLKSC-1 ;IS LEGITIMATE FOR LAST BLOCK IN CYLINDER + CAIA ;IGNORE + BUG PAUSE,[MAYBE DISK CONTROL IS WRITING ALL OVER THE DISK AGAIN] +QINT0: ];DMDSK + TDNE TT,[17177700] ;ANY ERRORS? + JRST QINTE +QINTN2: DATAI DPC,R + SKIPGE QSDU ;DONT CLOB CMD BUF TO CLR ATTS DURING DATA XFER + TRNN R,776 ;ANY ATTNS + JRST QINTA ;NO + LDB I,[11000,,R] ;YES,FIND WHICH DRIVE + JFFO I,.+1 ;CLOBBERS Q + SUBI Q,28. + +QINTAT: DATAO DPC,QATTNS(Q) ;CLEAR ATTNS + DATAI DPC,E + TLNN E,40 + JRST QRECAT ;NOT ON CYLINDER, RECALIBRATE + LDB A,[DCYLI E] + TRNE E,.BM DCYLXI + ADDI A,400 + CAME A,QPOSGL(Q) + JRST QRECAT ;SEEK TO THE WRONG PLACE (CALCOMPS LIKE TO DO THIS) + MOVEM A,QPOS(Q) ;REMEMBER WHERE IT IS AT + SETZM QSEEK(Q) + SETZM QRCAL(Q) + JRST QINT ;TRY AGAIN + +QINTA: SKIPGE Q,QSDU + JRST QINT1 ;NOT EXPECTING DATA COMPLETION - FIND NEW TRANSFER + CONSO DPC,400000 + CONSO DPC,10 + JRST DSKEX ;TRANSFER STILL IN PROGRESS, DISMISS + CONSZ DPC,20 + JRST .-1 ;BUSY? + AOSN QHUNGF + JRST QHE ;XFER HUNG, RECALIBRATE AND RETRY + JRST QINTA1 ;TRANSFER COMPLETE... + +QINTE: DATAI DPC,R + CONI DPC,TT ;THIS LOOKS REDUNDANT BUT APPARENTLY IS NECESSARY + ;DUE TO TIMING OF THE DISK-NOT-READY CONDITION + CONO DPC,175700+DSKCHN ;RESET CONDITIONS + MOVEM TT,QERST + MOVEM R,QERDTI + CONSZ DPC,20 ;WAIT FOR UNBUSY + JRST .-1 + MOVE Q,QSDU ;FOR QOVR + MOVE E,QCHPRG + TRNE TT,20000 ;OVERRUN + JRST QOVR + TRNE TT,2000 ;NOT READY + JRST QNRDY + TDNE TT,[12010700] ;BITS 14,16,23,27-29 ARE LOSERS + BUG HALT,[DSK: TOTALLY FATAL ERROR, CONI=],OCT,QERST + TLNE TT,5 ;WD OR SECTOR PARITY ERROR + JRST QDE + TRNE TT,1000 ;WRITE LOCKED + JRST QIRWRE + TRNE TT,40000 ;SEARCH FAILED + JRST QHE + TRNN TT,100000 ;POWER FAILURE + JRST QINTE1 + CONSZ DPC,100000 ;TRY IT AGAIN + JRST 4,.-1 + JRST QHE + +QINTE1: TLNE R,10 ;FILE UNSAFE--NEED OPERATOR INTERVENTION + BUG PAUSE,[DSK: FILE UNSAFE UNIT ],DEC,Q + TLNE R,4 + BUG ;NO SUCH DRIVE + TLNE R,110 ;POSITION FAILURE (OR PROCEEDED FILE UNSAFE) + JRST QHE + AOS NQSE(Q) ;SPURIOUS ERROR + JRST QINTX ;IGNORE + +QIRWRE: BUG PAUSE,[DSK: WRITE LOCKED UNIT ],DEC,Q + JRST QHE + +QNRDY: LDB Q,[410300,,R] ;WHICH DPC + SKIPN QSEEK(Q) + SKIPGE QRCAL(Q) ;NOT SEEKING OR RECALIBRATING IS ERROR + JRST QINTN2 + BUG PAUSE,[DSK: UNIT ],DEC,Q,[NOT READY] + JRST QREC +] ;END IFN RP10P + +IFN DC10P,[ + +QINT: MOVEM TT,QCST + SKIPL PKIDM ;GETS SPURIOUS DIPE WHEN READING PACK ID + CONSO DC1,7777 ;RUMOR THAT DSSERR DOESN'T ALWAYS SET + TRNE TT,DSSERR + JRST QINTE + TRNE TT,DSSATT + JRST QINTAT +QINTA: SKIPGE Q,QSDU + JRST QINT1 ;NOT EXPECTING DATA COMPLETION, FIND NEW TRANSFER + CONSZ DC0,DSSRUN+DSSACT + JRST DSKEX ;ACTIVE OR RUN, TRANSFER IN PROGRESS, DISMISS + AOSN PKIDM ;SKIP IF NOT FINISHED READING PACK ID + JRST QSPKID + AOSN QHUNGF + JRST QHE ;XFER HUNG, RECALIBRATE AND RETRY + SKIPL QERS1 + JRST QEROK ;OK ON VERIFY + JRST QINTA1 ;TRANSFER COMPLETE... + +QINTE: CONI DC1,TT + CONO DC0,DCCLR+DCERR+DSKCHN ;CLEAR ERRORS + MOVEM TT,QERST + MOVE Q,QSDU + CONSZ DC0,DSSRUN+DSSACT + JRST .-1 ;ACTIVE OR RUN? + SKIPL QERS1 + JRST QERL1 ;VERIFY ALSO LOST + TRNE TT,DOFFL+DPROT+DDOBSY+DNXM+DCPERR + JRST QINTE1 ;REALLY LOST BIG + TRNE TT,DOVRRN + JRST QOVR + TRNE TT,DWTHER+DFUNSF ;SEEK INC, END DISK, WATCHDOG, OR UNSAFE + JRST QHE ;TRY TO RECALIBRATE + SKIPGE PKIDM + TRZ TT,DRLNER ;IGNORE LENGTH ERROR IF READING PACK # + TRNE TT,DIPE+DRLNER+DRCER+DCKSER + JRST QDE ;TRY AGAIN + SKIPGE PKIDM + TRNE TT,-1 + AOS NQSE ;SPURIOUS ERROR (NOT LENGTH ERROR IN PKIDM) + JRST QINTX ;SPURIOUS ERROR + +QINTE1: TRNE TT,DOFFL + BUG PAUSE,[DSK: UNIT ],DEC,Q,[OFFLINE] + TRNE TT,DPROT + BUG PAUSE,[DSK: UNIT ],DEC,Q,[WRITE PROTECTED] + TRNE TT,DDOBSY + BUG PAUSE,[DSK: DATAO WHEN BUSY] + TRNE TT,DNXM+DCPERR + BUG PAUSE,[DSK: MEM PAR OR NXM ERROR] + JRST QOVR + +QINTAT: CONI DC1,Q + CONO DC0,DCCLR+DCCATT+DSKCHN ;CLEAR ATTENTION + LDB Q,[DSATDN Q] ;ATTENTION DRIVE NUMBER + CAIGE Q,NQS + SKIPL QRCAL(Q) + JRST QINTX + SETZM QRCAL(Q) + CONO DC0,DCCLR+DCATEB+DSKCHN ;CLEAR ATTENTION ENABLE + JRST QINTX + +;THIS IS CALLED EVERY HALF SECOND +QRCTMO: MOVEI Q,NQS-1 + SKIPL QRCAL(Q) +QRCTM1: SOJGE Q,.-1 + JUMPL Q,CPOPJ + SOSL QRCTIM(Q) + JRST QRCTM1 + BUG INFO,[DSK: RECAL TIMEOUT UNIT],DEC,Q + SETZM QRCAL(Q) + CONO DC0,DCCLR+DCATEB+DSKCHN ;CLEAR ATTENTION ENABLE I GUESS + JRST QRCTM1 +];DC10P + +IFN RH11P,[ + +;;; RHCLRC(Q) Clear controller errors and select drive Q +;;; RHSLCT(Q) Select drive Q +;;; RHCMD(A) Command in A to current drive +;;; RHCLRD Clear current drive +;;; RHCHEK Check for immediate bad news +;;; All return CS1 in A + +RHSLCT: IOWRQ Q,%HRCS2 +RHCHEK: IORDQ A,%HRCS1 + TRNE A,%HXTRE+%HXMCP + BUG HALT,[DSK: MASSBUS ERROR, CS1=],OCT,A + POPJ P, + +RHCLRC: IOWRQ Q,%HRCS2 ; Must select drive before clearing controller + MOVEI A,%HXTRE+%HXIE+%HMNOP +RHCMD: TROA A,%HXIE +RHCLRD: MOVEI A,%HXIE+%HMCLR + IOWRQ A,%HRCS1 + JRST RHCHEK + +EBLK +DSKBRK: 0 +BBLK + JSR UTCSAV +QINT: AOS QGTBZY + MOVE Q,QSDU + IORDQ TT,%HRCS1 + MOVEM TT,QCST + TRNE TT,%HXTRE+%HXMCP + JRST QINTE + TRNN TT,%HXSC ; Perhaps some drive needs attention? + JRST QINT0 ; Not unless SC is set! + IORDQ A,%HRATN + JFFO A,QINTAT +QINT0: SKIPGE Q,QSDU + JRST QINT1 ; Not expecting completion of transfer. + TRNN TT,%HXRDY + JRST DSKEX ; Transfer still in progress. + AOSN QHUNGF + JRST QHE ; Transfer hung, recalibrate and retry. + PUSHJ P,RHSLCT ; Select that drive. + IORDQ A,%HRSTS ; Get its status. + TRNE A,%HSERR ; Just in case %HXTRE didn't get set (by + JRST QINTE ; analogy with RH10)... + JRST QINTA1 ; Transfer complete... + +QINTAT: MOVNI Q,-35.(B) + HRRZS Q + MOVEI A,1 + LSH A,(Q) + IOWRQ A,%HRATN ; Turn off attention bit. + CAIL Q,NQS + JRST QINT0 + CAMN Q,QSDU + JRST [ AOS NQSATN(Q) ; Ignore attention in mid-transfer. + JRST QINTA2 ] + SKIPE QACT(Q) + JRST QINTA2 ; Ignore this drive. + PUSHJ P,RHSLCT + IORDQ B,%HRSTS ; Get status of drive with attention. + TRC B,%HSMOL+%HSDPR+%HSRDY + TRNN B,%HSMOL+%HSDPR+%HSRDY+%HSVV + PUSHJ P,QOFFL ; Went offline and came back online + TRNE B,%HSERR+%HSPIP + JRST [ PUSHJ P,RHCLRD ; Drive barfing not during transfer + AOS NQEATN(Q) ; so clear it + JRST .+1] ;THEN CLEAR SEEK AND RECALIBRATE FLAGS + SETZM QSEEK(Q) ;POSITIONING COMPLETION +IFDEF %HRCCY,[ ;Current Cyl register only on RP disks + IORDQ A,%HRCCY + MOVEM A,QPOS(Q) ;UPDATE CURRENT CYLINDER + CAME A,QPOSGL(Q) + SETOM QSKT1(Q) ;SEEK TO WRONG PLACE +];IFDEF %HRCCY +IFNDEF %HRCCY,[ + MOVE A,QPOSGL(Q) ;On RMxx, jump to conclusion + MOVEM A,QPOS(Q) +];IFNDEF %HRCCY + SETZM QRCAL(Q) ;NO LONGER RECALIBRATING + JRST QINT0 ;IF NO XFER ACTIVE, MAYBE CAN START ONE ON + ; THIS UNIT NOW + +QINTA2: SETOM QSKT1(Q) ;DON'T TRUST POS + JRST DSKEX + +; Went offline and came back online +QOFFL: TRC B,%HSMOL+%HSDPR+%HSRDY ;Recover %HRSTS + IORDQ C,%HRER1 + IORDQ D,%HRER2 +IFDEF %HRER3,[ + IORDQ E,%HRER3 + BUG INFO,[DSK: UNIT #],DEC,Q,[CAME BACK ONLINE, CS1=],OCT,A,[STS=],OCT,B,[ER1=],OCT,C,[ER2=],OCT,D,[ER3=],OCT,E +] +IFNDEF %HRER3,[ + BUG INFO,[DSK: UNIT #],DEC,Q,[CAME BACK ONLINE, CS1=],OCT,A,[STS=],OCT,B,[ER1=],OCT,C,[ER2=],OCT,D +] + + AOS NQOFFL(Q) + MOVEI A,%HMCLR ;Clear the drive + PUSHJ P,RHCMD + MOVEI A,%HMRDP ;I said, clear the drive! + PUSHJ P,RHCMD + MOVEI A,0 + IOWRQ A,%HROFS ;No offset, 18 bits, ECC on, HCI off + MOVEI A,%HMACK ;Turn %HSVV back on so drive will work + PUSHJ P,RHCMD + POPJ P, + +QINTE: +IRPS X,,[CS1 CS2 BA WC POS PAT] ; First get status of controller + IORDQ A,%HR!X + MOVEM A,QER!X +TERMIN + IORDQ A,UBAPAG+QUBPG_1 ; Unibus map counts as part of + MOVEM A,QERMAP ; controller status. + IORDQ A,UBAPAG+QUBPG_1+1 + MOVEM A,QERMAP+1 + SKIPGE Q ; Try hard to guess the drive. + LDB Q,[$HYDSK QERCS2] + PUSHJ P,RHCLRC ; Clear controller errors and select drive + ; so that we can read its status too. + TRNN A,%HXRDY ; Why would controller be busy? (RH10 + BUG ; code checks for this...) + +IRPS X,,[STS ER1 ER2] + IORDQ A,%HR!X + MOVEM A,QER!X +TERMIN + MOVE A,QERCS1 ; A: CS1 + MOVE R,QERCS2 ; R: CS2 +IFDEF %HRER3,[ ; Disks with ER2 -and- ER3 + IORDQ A,%HRER3 + MOVEM A,QERER3 + SKIPN QERER2 ; Bad news + SKIPE QERER3 + JRST UNSAFE +] +IFNDEF %HRER3,[ ; Disks with just ER2 + SKIPE QERER2 + JRST UNSAFE +] + TRNN A,%HXMCP ; Real bad news + TRNE R,%HYWCE+%HYPE+%HYNED+%HYNEM+%HYPGE+%HYMXF + BUG HALT,[DSK: UNIT #],DEC,Q,[LOSING. CS1=],OCT,A,[ CS2=],OCT,R + TRNE R,%HYDLT+%HYMDP ; Data bus losing? + JRST QINTE1 + MOVE A,QERSTS ; Check Drive Status + TRC A,%HSVV+%HSRDY+%HSDPR+%HSMOL ; Better be all on! + TRCE A,%HSVV+%HSRDY+%HSDPR+%HSMOL + BUG + TRNN A,%HSERR + JRST [ AOS NQSE(Q) ; Spurious? + JRST QINT0] + MOVE B,QERER1 ; Check the main error register + TRNE B,#<%H1ECC+%H1DTE+%H1CRC+%H1HCE+%H1ECH+%H1FER+%H1PAR> + JRST UNSAFE ; Those not listed above are considered "hard" + CAIN B,%H1ECC ; Correct correctable error if that is the + JRST QECC ; only problem. + PUSHJ P,QINTER ; Else print message and reset drive + TRNE B,%H1DTE+%H1CRC+%H1HCE+%H1FER ; These require recalibration + JRST QHE + TRNE B,%H1ECC+%H1ECH+%H1PAR ; These require reread + JRST QDE + JRST QOVR ; No error bits set? (How can this + ; happen?) Go and retry... + +;;; Controller error: +QINTE1: BUG INFO,[DSK: ERR UNIT #],DEC,Q,[CS1=],OCT,QERCS1,[CS2=],OCT,QERCS2 + JRST QOVR + +;;; Drive error: +IFDEF %HRER3,[ +QINTER: BUG INFO,[DSK: ERR UNIT #],DEC,Q,[ER1=],OCT,QERER1,[ER2=],OCT,QERER2,[ER3=],OCT,QERER3,[STARTING DISK ADDR=],OCT,QCHPGA +] +IFNDEF %HRER3,[ +QINTER: BUG INFO,[DSK: ERR UNIT #],DEC,Q,[ER1=],OCT,QERER1,[ER2=],OCT,QERER2,[STARTING DISK ADDR=],OCT,QCHPGA +] + JRST RHCLRD ; Reset error status in drive + +;;; Come here for drive unsafe and similar bad things. May be set to +;;; either halt or attempt retry (via USFHLT variable). Note that when we +;;; get here the state of the drive has not yet been disturbed. +UNSAFE: SKIPE USFHLT + BUG PAUSE,[DSK: TOO MANY ERRORS] + MOVEI A,2 ;HALT IF ANOTHER ERROR WITHIN 1/2 - 1 SECOND + MOVEM A,USFHLT + PUSHJ P,QINTER ;GIVE ERROR MESSAGE AND RESET DRIVE + SKIPL QSDU + JRST QHE ;RECALIBRATE AND RETRY + JRST QREC ;Just recalibrate, no transfer to retry + +QECC: PUSHJ P,RHCLRD ; Reset drive + CAME Q,QSDU ; ECC error better be for transfer in + BUG ; progress... + MOVE A,QCHPRG + TRNN A,10 .SEE %HMRED + BUG ; ECC error should only happen during read. + LDB A,[$UPPAG QERMAP] + IORI A,600000 + DPB A,[.PAREP+EXEUMP] ; Point parity error page at buffer. + CLRPT 400000+PAREP_12 ; Get it into our map now. + CLRPT 401000+PAREP_12 ; Both halves... + MOVE J,QERBA + SUBI J,1000+QUBPG_14 ; Correct to relative byte address of start + ; of losing sector. + TRNE J,770777 ; Should always be aligned on sector boundary + BUG ; and within a single block, right? + LSH J,-2 ; J: Address of first word of losing sector + ; within block. + MOVE A,QECPOS ; Get error position + SOJL A,QDE ;HARDWARE POS IS OFF BY 1; IF 0 NOT CORRECTABLE + IDIVI A,36. ;CONVERT TO WORD NO AND BIT NO + CAIL A,177 + JRST [ ADDI B,36. ;LAST WORD IN SECTOR - HACK IT TO AVOID NXM + SOJA A,.+1] + ADDI J,400000+PAREP_12(A) ; J: Address of losing word-pair + ; (In parity error page.) + MOVE U,B ;SAVE BIT NUMBER + MOVS B,(J) ;GET FIRST LOSING WORD + MOVS C,1(J) ;GET SECOND LOSING WORD + MOVE D,QECPAT ;GET ERROR PATTERN + SETZ E, ;MAKE INTO DOUBLE-WORD + ROTC D,(U) ;ALIGN IT + XOR B,D ;FIX THE BAD BITS + XOR C,E + MOVSM B,(J) ;PUT CORRECTED DATA BACK + MOVSM C,1(J) + MOVEI A,0 + DPB A,[.PAREP+EXEUMP] ;FLUSH THE DISK BUFF FROM MAP + CLRPT 400000+PAREP_12 + CLRPT 401000+PAREP_12 ; Both halves... + + AOS QECCS(Q) ;LOG THE LOSS + LDB E,[111000,,QERBA] ; E: Number of sectors transferred (including + SUBI E,QUBPG_3 ; ECC sector) + MOVE A,QCHPGA + LDB B,[$HASEC A] ;Compute disk address of failing sector: + ADDI B,-1(E) + IDIVI B,NSECS ; C: sector + DPB C,[$HASEC A] + LDB D,[$HATRK A] + ADD B,D ; B: track + DPB B,[$HATRK A] + MOVEM A,QECCAD(Q) + HLRZ A,A ; A: cylinder + MOVE D,QSDCH ; D: chnl + BUG INFO,[DSK: ECC CORRECTED ERROR, UNIT #],DEC,Q,[CYL ],DEC,A,[HEAD ],DEC,B,[SEC ],DEC,C,[QSRAC],OCT,QSRAC(D) + CAIL E,SECBLK + JRST QINTA1 ;XFER COMPLETE + + LDB B,[$HASEC QCHPGA] ;NOW DETERMINE WHERE TO RESUME TRANSFER + ADD B,E + IDIVI B,NSECS + DPB C,[$HASEC QCHPGA] + LDB C,[$HATRK QCHPGA] + ADD C,B + DPB C,[$HATRK QCHPGA] ;NO NEED TO IDIVI A,NHEDS SINCE NEVER CROSS + ; CYLINDERS + + HRL E,QERWC ; Reassemble "iowd" from + HRR E,QERBA ; saved parts. (Don't trust stuff saved + MOVEM E,QIOWD ; in controller more than we have to.) + HRRZ C,QSDCH ;FOR QECCX + JRST QECCX ;MORE TO DO, CONTINUE XFER + +] ;RH11P + +IFN RH10P,[ + +QINT: AOS QGTBZY + MOVE Q,QSDU + MOVEM TT,QCST + TRNE TT,%HIERR + JRST QINTE + TRNN TT,%HIATN + JRST QINT0 + MOVSI A,%HRATN ;FIND DRIVES NEEDING ATTENTION + PUSHJ P,RHGET + JFFO A,QINTAT +QINT0: SKIPGE Q,QSDU + JRST QINT1 ;NOT EXPECTING COMPLETION OF TRANSFER + TRNN TT,%HIDON + JRST DSKEX ;NO COMPLETED TRANSFER + CONSZ DSK,%HIBSY + JRST 4,.-1 ;TRANSFER STILL IN PROGRESS?? + AOSN QHUNGF + JRST QHE ;XFER HUNG, RECALIBRATE AND RETRY + MOVSI A,%HRSTS(Q) ;SOMETIMES %HSERR SETS AND %HIERR DOESN'T! + PUSHJ P,RHGET + TRNE A,%HSERR + JRST QINTE + JRST QINTA1 ;XFER COMPLETE... + +QINTAT: MOVNI Q,-35.(B) ;LOW BIT IS DRIVE 0 + HRRZS Q + MOVEI A,1 ;TURN OFF ATTENTION (DRIVE MAY BE LOSING + LSH A,(Q) ;IN SUCH A WAY THAT READING %HRSTS DOESN'T CLEAR ATTN) + HRLI A,%HRATN + PUSHJ P,RHSET + CAMN Q,QSDU + JRST [ AOS NQSATN(Q) ;IGNORE ATTN IN MID-TRANSFER + JRST QINTA2 ] + MOVSI A,%HRSTS(Q) ;GET STATUS OF DRIVE WITH ATTENTION + PUSHJ P,RHGET ;THIS ALSO CLEARS THE ATTENTION BIT + SKIPE QACT(Q) + JRST QINTA2 ;IGNORE THIS DRIVE + TRNE A,%HSERR+%HSPIP + JRST [ MOVSI A,%HRDCL(Q) + HRRI A,%HMCLR ;DRIVE REPORTING ERROR NOT DURING TRANSFER + PUSHJ P,RHSET ;SO CLEAR THE DRIVE + AOS NQEATN(Q) + JRST .+1 ] ;THEN CLEAR SEEK AND RECALIBRATE FLAGS + SETZM QSEEK(Q) ;POSITIONING COMPLETION + MOVSI A,%HRCCY(Q) + PUSHJ P,RHGET + MOVEM A,QPOS(Q) ;UPDATE CURRENT CYLINDER + CAME A,QPOSGL(Q) + SETOM QSKT1(Q) ;SEEK TO WRONG PLACE + SETZM QRCAL(Q) ;NO LONGER RECALIBRATING + JRST QINT0 ;IF NO XFER ACTIVE, MAYBE CAN START ONE ON THIS UNIT NOW + +QINTA2: SETOM QSKT1(Q) ;DON'T TRUST POS + JRST DSKEX + +;INPUT FROM MASSBUS - ADDRESS IN LH(A), RETURNS DATA IN A + +RHGET: TLZA A,%HRLOD + +;OUTPUT TO MASSBUS - ADDRESS IN LH(A), DATA IN RH(A) + +RHSET: TLO A,%HRLOD + DATAO DSK,A + MOVEM A,RHDATO ;SAVE FOR REBUGGING + MOVEI A,5 ;WAIT 3 USEC FOR BUS CYCLE + SOJG A,. + DATAI DSK,A + TLNE A,%HDERR + BUG HALT,[DSK: MASSBUS ERROR, DATAO=],OCT,RHDATO,[DATAI=],OCT,A + ANDI A,177777 ;RETURN 16-BIT REGISTER CONTENTS + POPJ P, + +QINTE: CONI DSK,TT + DATAI DSK,R + CONO DSK,%HOCLR+%HORAE+%HOATN+DSKCHN ;RESET CONTROLLER SO DRIVE STATUS MAY BE READ + CONSZ DSK,%HIBSY + JRST .-1 ;SOMETIMES CONTROLLER IS BUSY?? + MOVEM TT,QERST + MOVEM R,QERST+1 + SKIPGE Q ;TRY HARD TO GUESS THE RIGHT DRIVE! + LDB Q,[$HCDRV R] ;CURRENTLY SELECTED DRIVE + IRPS X,,[%HRSTS %HRER1 %HRER2 %HRER3 %HRDCL %HRPOS %HRPAT] + MOVSI A,X(Q) ;GET STATUS OF DRIVE + PUSHJ P,RHGET + MOVEM A,QERST+.IRPCNT+2 + TERMIN + SKIPN QERER2 ;FILE UNSAFE + SKIPE QERER3 + JRST UNSAFE + TRZE TT,%HIDRE + AOS NQDRE(Q) ;THIS BIT SUSPECTED OF BEING SET RANDOMLY. + ;;CHECK FOR IRRECOV (?) HARDWARE LOSSAGE. EVEN MORE SO THAN 'UNSAFE' + TDNE TT,[%HIILF+%HISDE+%HINXM+%HIDRE+%HIILC+%HIPWR] + BUG HALT,[DSK: UNIT ],DEC,Q,[ LOSING. RH10 CONI= ],OCT,QERST +IFN KS10P, .ERR So whats this all about? +IFN KL10P,[ + TLNN TT,(%HIDPE+%HICPE) ;IF CHANNEL DETECTS PARITY ERROR, CAUSE + JRST QINTE0 ;PROCESSOR PARITY SWEEP WHICH WILL PROBABLY + MOVSI A,SCLPAR ;CRASH THE SYSTEM ANYWAY. BEATS LOOPING! + TDNN A,SUPCOR ;BUT DON'T CAUSE CLKB1E+7 HALT + CONO 10407 + BUG CHECK,[DSK: MEM PAR ERR, QICWA/],OCT,QICWA,OCT,QICWA+1,[QIOWD/],OCT,QIOWD +QINTE0: +];KL10P + TDNE TT,[%HIOVR+%HICOV+%HIDPE+%HICPE+%HIBPE] + JRST QINTE1 ;OVERRUN OR PARITY ON CONTROL BUS OR CHANNEL BUS - RETRY + MOVE A,QERSTS ;DRIVE EXCEPTION, CHECK DRIVE STATUS + TRC A,%HSVV+%HSRDY+%HSDPR+%HSMOL ;THESE BITS BETTER ALL BE ON + TRCE A,%HSVV+%HSRDY+%HSDPR+%HSMOL + BUG ;DRIVE TURNED OFF? MAYBE 11 HACKING THIS DRIVE? + TRNN A,%HSERR + JRST [ AOS NQSE(Q) ;SPURIOUS? + JRST QINT0 ] + MOVE B,QERER1 ;CHECK THE MAIN ERROR REGISTER + TRNE B,#%H1SOF ;ANY HARD ERRORS? + JRST UNSAFE + CAIN B,%H1ECC ;IF JUST A CORRECTABLE ERROR, + JRST QECC ;GO CORRECT IT + PUSHJ P,QINTER ;OTHER SOFT ERROR, PRINT MESSAGE AND RESET DRIVE + TRNE B,010620 ;SEARCH ERROR, OR HEADER READ OR FORMAT ERROR OR DRIVE TIMING + JRST QHE ;REQUIRES RECALIBRATE + TRNE B,100110 ;BUS PARITY OR ECC "HARD" + JRST QDE ;REQUIRES RE-READ, GIVE UP AFTER N + JRST QOVR ;NO ERROR BITS, PRINT MESSAGE AND RETRY + +;CONTROLLER ERROR +QINTE1: BUG INFO,[DSK: ERR UNIT #],DEC,Q,[CONI=],OCT,QERST,[DCL=],OCT,QERDCL + JRST QOVR + +;DRIVE ERROR +QINTER: BUG INFO,[DSK: ERR UNIT #],DEC,Q,[ER1=],OCT,QERER1,[ER2=],OCT,QERER2,[ER3=],OCT,QERER3,[STARTING DISK ADDR=],OCT,QCHPGA + MOVSI A,%HRDCL(Q) ;NOW RESET ERROR STATUS IN DRIVE + HRRI A,%HMCLR + JRST RHSET + +;COME HERE FOR DRIVE UNSAFE AND SIMILAR BAD THINGS. MAY BE SET TO +;EITHER HALT OR ATTEMPT RETRY (VIA USFHLT VARIABLE). NOTE THAT WHEN +;WE GET HERE THE STATE OF THE DRIVE HAS NOT YET BEEN DISTURBED. +UNSAFE: SKIPE USFHLT + BUG PAUSE,[DSK: TOO MANY ERRORS] + MOVEI A,2 ;HALT IF ANOTHER ERROR WITHIN 1/2 - 1 SECOND + MOVEM A,USFHLT + PUSHJ P,QINTER ;GIVE ERROR MESSAGE AND RESET DRIVE + JRST QHE ;RECALIBRATE AND RETRY + +QECC: MOVSI A,%HRDCL(Q) ;RESET ERROR STATUS IN DRIVE + HRRI A,%HMCLR + PUSHJ P,RHSET + CAME Q,QSDU ;CORRECT AN ECC ERROR + BUG ;BARF ... NO TRANSFER IN PROGRESS + MOVE A,QCHPRG + TRNN A,10 + BUG ;BARF ... SHOULDN'T HAPPEN DURING WRITE + SKIPN A,QICWA+1 ;GET ADDRESS OF LAST WORD READ + JRST 4,.-1 ;CHANNEL OUGHT TO HAVE STORED CONTROL WORD BY NOW + SOS J,A + TDZ J,[177+.BM $DFCWA] ;J := ADDRESS OF FIRST WORD IN LOSING SECTOR + LDB A,[$DFCAD QIOWD] + SUBM J,A + SOS H,A ;# WORDS SUCCESSFULLY XFERED. + CAIL H,0 ;CHECK IF CHANNEL STORED BAD ADDRESS + CAILE H,2000-200 + JRST QDE ;THIS SHOULD NEVER HAPPEN, BUT IT DOES, FREQUENTLY + MOVE A,QECPOS ;GET ERROR POSITION + SOJL A,QDE ;HARDWARE POS IS OFF BY 1; IF 0 NOT CORRECTABLE + IDIVI A,36. ;CONVERT TO WORD NO AND BIT NO + CAIL A,177 + JRST [ ADDI B,36. ;LAST WORD IN SECTOR - HACK IT TO AVOID NXM + SOJA A,.+1] + ADD J,A ;J := ADDRESS OF LOSING WORD-PAIR + LDB A,[121400,,J] + ANDI J,1777 ;GET ADDR OF PAR ERR PAG + ADDI J,400000+2000*PAREP ;IN EXEC ADDRESS SPACE + IORI A,600000 ;MAKE THAT PAGE POINT TO THE DISK BUFFER + DPB A,[.PAREP+EXEUMP] + SPM ECCPAG ;GET IT INTO OUR MAP. + LPMR ECCPAG + MOVE U,B ;SAVE BIT NUMBER + MOVS B,(J) ;GET FIRST LOSING WORD + MOVS C,1(J) ;GET SECOND LOSING WORD + MOVE D,QECPAT ;GET ERROR PATTERN + SETZ E, ;MAKE INTO DOUBLE-WORD + ROTC D,(U) ;ALIGN IT + XOR B,D ;FIX THE BAD BITS + XOR C,E + MOVSM B,(J) ;PUT CORRECTED DATA BACK + MOVSM C,1(J) + MOVEI A,0 + DPB A,[.PAREP+EXEUMP] ;FLUSH THE DISK BUFF FROM MAP + LPMR ECCPAG + + AOS QECCS(Q) ;LOG THE LOSS + MOVE A,QCHPGA + MOVEI E,200(H) + LSH E,-7 ;NUMBER OF SECTORS TRANSFERRED (INCLUDING ECC SECTOR) + LDB B,[$HASEC A] ;GET DISK ADDR OF FAILING SECTOR + ADDI B,-1(E) + IDIVI B,NSECS + DPB C,[$HASEC A] + LDB D,[$HATRK A] + ADD B,D + DPB B,[$HATRK A] ;NO NEED TO DIVIDE BY NHEDS SINCE NEVER CROSS CYLINDERS + MOVEM A,QECCAD(Q) + HLRZ A,A + MOVE D,QSDCH + BUG INFO,[DSK: ECC CORRECTED ERROR, UNIT ],DEC,Q,[CYL ],DEC,A,[HEAD ],DEC,B,[SEC ],DEC,C,[QSRAC],OCT,QSRAC(D) + LDB B,[$HASEC QCHPGA] ;NOW DETERMINE WHERE TO RESUME TRANSFER + ADD B,E + IDIVI B,NSECS + DPB C,[$HASEC QCHPGA] + LDB C,[$HATRK QCHPGA] + ADD C,B + DPB C,[$HATRK QCHPGA] ;NO NEED TO IDIVI A,NHEDS SINCE NEVER CROSS CYLINDERS + HRRZ C,QSDCH ;FOR QECCX + LDB A,[$DFCWA QICWA+1] ;LAST CONTROL WORD PROCESSED + SUBI A,1 ;CRETINOUS DF10 + CAIE A,QIOWD + BUG ;CHANNEL STORED BAD ADDRESS? + HRRZM A,QICWA + MOVEI A,200(H) ;# WORDS ALREADY DONE. + DPB A,[$DFWC A] ;PUT IT IN BOTH FIELDS. + ADDB A,@QICWA ;ADVANCE C.W. TO REMAINING STUFF + TLNE A,(.BM $DFWC) + JRST QECCX ;MORE TO DO, CONTINUE XFER + AOS QICWA ;ELSE ADVANCE TO NEXT C.W. + SKIPE @QICWA + JRST QECCX ;MORE TO DO, CONTINUE XFER + JRST QINTA1 ;XFER COMPLETE +] + +IFN T300P,[ +T3INT: SETZM DSCDON ;CLEAR DONE FLAG THAT GOT US HERE + SKIPGE QSDU1 ;OPERATION COMPLETE? + JRST QINT1 ;NO, GO FIND SOMETHING TO DO + HRRZ Q,DSCDRV ;YES, GET DRIVE OPERATION WAS ON + ADDI Q,T300P + CAIGE Q,NQS + CAME Q,QSDU1 ;TERMINATION ON DRIVE WE EXPECTED? + BUG ;DRIVE NUMBER CLOBBERED? + SETZM QRCAL(Q) ;PRESUMABLY NOT RECALIBRATING ANY MORE. + MOVE A,DSCCMD ;COMMAND THAT JUST COMPLETED + CAIN A,%DMREC ;WAS IT A RECALIBRATE? + JRST QINT1E ;IF SO, CONTROLLER IS IDLE NOW + MOVE C,QSDCH1 ;CHANNEL + HRLZ E,DSCFLT ;CHECK FOR ERRORS + HRR E,DSCSTS + JUMPE E,QINTI ;OPERATION COMPLETED UNEVENTFULLY + MOVE D,DSCHED ;GET DISK ADDRESS AS CYL,,HEAD_9+SECTOR + LSH D,9 + IOR D,DSCSEC + HRL D,DSCCYL + SKIPN QERRS(C) ;PRINT ONLY ONCE, NOT ON RETRIES + BUG INFO,[DSK: T-300 ERR UNIT ],DEC,Q,[FAULT=],OCT,DSCFLT,[STATUS=],OCT,DSCSTS,[CMD=],OCT,DSCCMD,[CYL-SURF-SEC=],OCT,D + TRZE E,%DSRTR+%DSECC ;THESE ARE NOT ERRORS + AOS QECCS(Q) + JUMPE E,QINTI ;OPERATION COMPLETED SUCCESSFULLY (WITH INTERVENTION OF 2561) + MOVE T,E + TRZ T,%DSECH+%DSIDE+%DSHCE + JUMPN T,T3INT2 ;CONSIDER USING ERROR RECOVERY FEATURES + TRNE A,%DMRED ;IF COMMAND IS A READ + TRNE A,10 ;AND WE HAVEN'T TRIED THEM ALL + JRST T3INT2 + AOS NQSE(Q) ;COUNT "SOFT ERRORS" (NOT "SPURIOUS" IN T-300 CASE) + AOJA A,T3IO1 ;GO RETRY OPERATION USING NEXT FEATURE + +T3INT2: TLNN E,-1 ;ANY FAULT? PROBABLY UNRECOVERABLE BUT TRY RECALIBRATE + TRNE E,%DSIDE+%DSHCE+%DSSKE+%DSOFL+%DSFLT ;DISK CONDITION THAT CALLS FOR RECAL + JRST T3HE + JRST T3DE ;TRY OPERATION AGAIN. PROBABLY WILL LOSE BUT TRY. +];T300P + +OVHMTR QSC ;DISK SCHEDULER (AND HIGHER-LEVEL INTERRUPT STUFF) + +QINTA1: SKIPL C,QSDCH ;XFER COMPLETE +QINTI: SKIPGE A,QSCABN(C) ;CHANNEL IN C + BUG ;MEMBLT INDEX IN A + MOVE R,A ;BUFFER ADDRESS IN R +IFN KL10P,[ ;QSRAC IN D, QSK# IN Q + SKIPL QSCRW(C) ;IF READ, FLUSH CACHE AGAIN + JRST [ PUSHJ P,CSHSWP ;SINCE USER MIGHT HAVE TOUCHED ABS PAGE + CAIA + MOVE A,R ;A WAS CLOBBERED + JRST .+1 ] +] +IFN KS10P,[ + SKIPL QSCRW(C) ;ON KS, CAN ONLY CLEAR THE WHOLE CACHE + CLRCSH +] + LSH R,10. + MOVE D,QSRAC(C) +IFN RP10P,[ + HRRZ TT,QICWA+1 + CAIE TT,1777(R) + TLNE D,%QAPAR ;IGNORE IF LOSING ANYWAY (E.G. SEARCH ERR) + CAIA + JRST QDFLOS +];RP10P +IFN QRDCMP,[ + SKIPE TT,RDCPHS ;NEED TO READ-COMPARE? + JRST QRC1 ;READ-COMPARE STARTING OR FINISHED +QRC0: +];QRDCMP + TRNE D,-%QMMAX + BUG + XCT .+1(D) ;INVOKE COMPLETION HANDLER + OFFSET -. +%QMIDL::JRST 4,QINT1 ;IDLE - SHOULDN'T BE ACTIVE +%QMRD:: JRST QRDFIN ;READ +%QMWRT::JRST QWRFIN ;WRITE +%QMWOV::JRST QWOVFN ;WRITE-OVER MODE +%QMRD1::JRST QRD1FN ;READ BLOCK AT A TIME MODE + JRST 4,QINT1 ;ILL CODE +%QMUDR::JRST QUDRIN ;USER DIR IN +%QMMDR::JRST QMDRIN ;MASTER DIR IN +%QMTTR::JRST QTUTIN ;TUT IN +%QMUDW::JRST QUFDWF ;USER DIR WRITE +%QMMDW::JRST QMFDWF ;MASTER DIR WRITE +%QMTTW::JRST QTUTWF ;TUT WRITE +%QMSWP::JRST QSWPFN ;SWAP FINISHED + JRST 4,QINT1 ;ILL CODE + JRST 4,QINT1 ;ILL CODE + JRST 4,QINT1 ;ILL CODE +%QMMAX::OFFSET 0 +IFN %QMMAX-20, .ERR %QMMAX MUST BE A POWER OF 2 + +IFN RP10P,[ +;CHANNEL DIDN'T TRANSFER EXACTLY 2000 WORDS +QDFLOS: MOVEI D,1777(R) ;EXPECTED TERMINATION ADDRESS + HRRZ B,QICWA+1 ;ACTUAL TERMINATION ADDRESS + CAIL B,(D) + SKIPL QSCRW(C) + JRST QDFLZ1 + BUG HALT,[DSK: CHANNEL TRANSFERRED UP TO ],OCT,B,[RATHER THAN],OCT,D,[DISK IS CLOBBERED NOW.] + +QDFLZ1: BUG PAUSE,[DSK: CHANNEL TRANSFERRED UP TO ],OCT,B,[RATHER THAN],OCT,D + JRST QOVR +];RP10P + +;;; SOFTWARE READ-COMPARE ROUTINES + +IFN QRDCMP,[ +IFE RP10P+RH10P, .ERR READ-COMPARE ONLY CODED FOR RP-10 AND RH10 +;IFE KA10P, .ERR READ-COMPARE ONLY CODED FOR KA-10 + +;;; REGULAR OPERATION COMPLETE, DO A READ-COMPARE TO BE SURE +QRC1: +IFN T300P, CAIGE Q,T300P ;NO READ/COMPARE IF THIS IS T-300 CONTROLLER + TLNE D,%QAPAR ;GIVING UP WITH FATAL ERR? + JRST QRC0 ;NO READ-COMPARE THEN + JUMPG TT,QRC2 ;JUMP IF READ-COMPARE COMPLETED + MOVE E,QSGL(C) ;DISK BLOCK + PUSHJ P,QPOSR ;E GETS DATAO WORD +IFN RP10P,[ + IOR E,[DREADC+7000+RCICWA] ;MAKE READ COMMAND + CONO DPC,175700+DSKCHN + MOVE T,[-2000,,QRCBUF-1] ;STORE CHANNEL PROGRAM + MOVEM T,RCIOWD + SETZM RCIOWD+1 + MOVEI T,RCIOWD + MOVEM T,RCICWA + SETZM RCICWA+1 + DATAO DPC,E ;START DISK +];RP10P +IFN RH10P,[ + MOVE T,[-2000_4,,QRCBUF-1] ;DF10-C CHANNEL PROGRAM + MOVEM T,RCIOWD + SETZM RCIOWD+1 + MOVEI T,RCIOWD + MOVEM T,RCICWA + SETZM RCICWA+1 + SWPUA ;DUMP CACHE + CONSZ 200000 ;IT'S INEFFICIENT, BUT WHAT THE HELL + JRST .-1 + CONO DSK,%HOCLR+%HORAE+%HOATN+DSKCHN + MOVSI A,%HRADR(Q) + HRR A,E ;HEAD AND SECTOR (CYL DOESN'T CHANGE) + PUSHJ P,RHSET + MOVEI A,%HMRED+ + TLO A,%HRCTL(Q) + PUSHJ P,RHSET ;START DISK +];RH10P + MOVEM T,RDCPHS ;RDCPHS POSITIVE MEANS DOING RD/CMP NOW + JRST DSKEX ;AWAIT COMPLETION + +;;; READ-COMPARE COMPLETED. CHECK IT. +QRC2: SPM PARPG ;SET UP MAP TO PAGE BEING READ/WRITTEN + MOVEI T,600000+PMCSHM(A) + DPB T,[.PAREP+EXEUMP] + LPMR PARPG + MOVEI H,0 ;H DIFFERENCE COUNT +IFN KA10P,[ + PUSH P,A ;WILL DO COMPARE LOOP IN ACS + PUSH P,C + PUSH P,D + MOVSI E,-2000 ;E ADDRESS WITHIN PAGE + MOVSI D,[ MOVE T,400000+PAREP*2000(E) ;A + CAMN T,QRCBUF(E) ;B + AOBJN E,A ;C + JRST QRC3 ] ;D + HRRI D,A + BLT D,D + JRST A +];KA10P +.ELSE [ + MOVSI E,-2000 ;E ADDRESS WITHIN PAGE + MOVE T,400000+PAREP*2000(E) + CAMN T,QRCBUF(E) +QRC2A: AOBJN E,.-2 +];NOT KA10P +QRC3: JUMPGE E,QRC5 ;JUMP IF DONE + JUMPG H,QRC4 ;COMPARE ERROR, REPORT IT + AOS NQCMPE(Q) +IFN KA10P,[ + MOVE T,-1(P) ;SAVED C + BUG INFO,[DSK: READ-COMPARE ERROR #],DEC,NQCMPE(Q),[UNIT=],DEC,Q,[BLK=],OCT,QSGL(T) +];KA10P +.ELSE BUG INFO,[DSK: READ-COMPARE ERROR #],DEC,NQCMPE(Q),[UNIT=],DEC,Q,[BLK=],OCT,QSGL(C) +QRC4: ADDI H,1 + HRRZ T,E + CAIG H,4 ;ONLY REPORT FIRST 4 BAD WORDS + BUG INFO,[DSK: READ-COMPARE DIFFERENCE ],OCT,T,OCT,400000+PAREP*2000(E),OCT,QRCBUF(E) +IFN KA10P,JRST C +.ELSE JRST QRC2A + +QRC5: +IFN KA10P,[ + POP P,D + POP P,C + POP P,A +];KA10P + MOVEI T,0 ;CLEAR MAP + DPB T,[.PAREP+EXEUMP] + LPMR PARPG + JUMPE H,QRC0 ;NO DIFFERENCE, I/O OPERATION IS DONE + CAILE H,4 ;FAILED, DO IT ALL OVER AGAIN + BUG INFO,[DSK: READ-COMPARE DIFFERENCES TOTAL],DEC,H + JRST QOVR +];QRDCMP + +QUFDWF: MOVE TT,QDWIP + CAMN Q,MDSK ;WRITTEN TO MASTER DISK? + SKIPN E,QSFBT(TT) ;AND HAVE SOME BLOCKS TO FREE? + JRST QUDWF1 + SETZM QSFBT(TT) ;YES, TRANSFER THEM TO QFBTS LIST + MOVE T,E ;E FINDS LAST OF LIST, T RPLACD'D IN THERE + EXCH T,QFBTS ;NCONC QSFBT ONTO FRONT OF QFBTS + SKIPE 1(E) + JRST [ MOVE E,1(E) + JRST .-1 ] + MOVEM T,1(E) + SKIPN T + AOS NCORRQ ;WAKE UP CORE JOB IF QFBTS HAD BEEN EMPTY +QUDWF1: JSP D,QDWF + QSNLCN(TT) + +QMFDWF: JSP D,QDWF + QMDRO + +QTUTWF: AOS T,QSGL(C) ;NEXT BLOCK TO GO OUT + AOS QSCABN(C) ;FROM NEXT CORE PAGE + CAIGE T,MFDBLK ;SKIP IF DONE + JRST QINT1E ;WRITE MORE + JSP D,QDWF + QTUTO(TT) + +QDWF: MOVSI E,(SETZ) ;UNLOCK DIR THAT WAS WRITTEN + IOR E,DCHBT(Q) ;COPY ON THIS DISK IS NOW UP TO DATE + MOVE TT,QDWIP + ANDCAM E,@(D) + HLLZS QSRAC(C) .SEE %QMIDL ;IDLE THE CHANNEL + SETOM DWUSR + JRST QINT1A ;DON'T COUNT THIS AS DISK ACTIVITY + +QUDRIN: MOVE TT,QUDPR(C) ;USER DIR IN OK + MOVE D,UDNAME(R) + CAME D,QSNUD(TT) ;COMPARE UNAME IN DIR WITH RQ'ED + JRST QUDER1 + TLO R,40000 ;NOT PAWED OVER + MOVEM R,QSNLCN(TT) + MOVE R,QSLGL(C) + MOVEM R,QSNMI(TT) + MOVEI R,MU23UD ;USER DIRECTORY + PUSH P,A + PUSH P,C + MOVE C,TT + PUSHJ P,QDIRCK ;VERIFY NOT TOTALLY BASHED TO BEGIN WITH + POP P,C ;CLOBBERS A,B,I + POP P,A +QINTU4: DPB R,[MUR,,MEMBLT(A)] + DPB TT,[MNUMB,,MEMBLT(A)] +QTUTI1: SETOM QUSR(C) ;FREE THE DISK CHANNEL + AOS QFCHN + JRST QINT1A + +QMDRIN: TLO R,2 ;NOT RECONCILED + MOVEM R,QMDRO ;MASTER DIRECTORY IN + MOVE TT,MDCHK(R) + CAME TT,[SIXBIT /M.F.D./] + BUG HALT,[MFD CLOBBERED] + MOVE TT,MDNUDS(R) + CAIE TT,NUDSL + BUG HALT,[MFD HAS WRONG NUMBER OF DIRECTORIES] + MOVE TT,(R) ;ASCENDING DIR # + SKIPGE QAMDNO + MOVEM TT,QAMDNO ;FIRST DISK IN STORE ASCENDING # + MOVEI R,MU23MD ;MASTER DIRECTORY + MOVE TT,Q ;DISK NO + JRST QINTU4 + +QTUTIN: AOS T,QSGL(C) ;NEXT BLOCK TO COME IN + AOS QSCABN(C) ;INTO NEXT CORE PAGE + CAIGE T,MFDBLK ;SKIP IF DONE + JRST QINT1E ;READ MORE + HRRZS QTUTO(Q) ;UNLOCK TUT, BUT QDPWF IS STILL SET + JRST QTUTI1 + +QSWPFN: MOVE Q,QDSKN(C) + TLNE D,%QAPAR + JRST QSWPF2 ;SWAP READ ERROR (I HOPE) + MOVSI E,MMPTMP ;PAGE NO LONGER IN TRANSIT + TDNN E,@QSMMP(Q) + BUG ;ALREADY WASN'T? + ANDCAM E,@QSMMP(Q) + SKIPL QSCRW(C) + JRST QSWPIF + PUSHJ P,IMEMR ;SWAP-OUT COMPLETE, RETURN MEMORY + MOVSI E,MMPPGB + ANDCAM E,@QSMMP(Q) + MOVSI E,MMPWOD ;PAGE HAS BEEN WRITTEN ON DISK. AND NO LONGER + IORB E,@QSMMP(Q) ;BEING PAGED BEHIND. + TLNN E,MMPGON + JRST QSWPF2 + MOVE A,QSMMP(Q) ;WE'RE SUPPOSED TO RETURN THE MMP ENTRY + PUSHJ P,RETMMP +QSWPF2: SETOM SWUSR(Q) ;SWAPPING IDLE + JRST QINT1B + +QSWPIF: +;SOME ERROR CHECKING + MOVE E,QSMMP(Q) + HLLZ TT,1(E) + JUMPE TT,QSWPF3 ;ON INITIAL-SWAP-IN, ADDRESS IN MMP IS SUPPOSED TO BE ZERO + LDB TT,[$MMPUN,,(E)] + CAME TT,Q + BUG + HLRZ TT,1(E) + CAME TT,QSGL(C) + BUG +QSWPF3: LDB TT,[MMMPX,,MEMBLT(A)] + CAIE TT,-MMP(E) + BUG +;END ERROR CHECKING + MOVEI TT,MURUSR ;SWAP IN OF PAGE COMPLETED + DPB TT,[MUR,,MEMBLT(A)] + SETZM MMSWP(A) + MOVE D,(E) + SKIPL CIRPSW + JRST QSWPF2 ;CAN'T PUT IN MAPS IF CIRPSW NOT AVAILABLE. + MOVSI D,(TDNE T,) ;SET UP CHECK USED BY PRIVELEGED USER FEATURE + HRR D,QSMMP(Q) + PUSH P,C + PUSH P,Q + MOVE C,[2200,,MEMPNT(A)] + PUSHJ P,PPIUM ;PUT PAGE INTO USERS' MAPS + POP P,Q + POP P,C + JRST QSWPF2 + +QWOVFN: CLEARM QSCRW(C) ;WRITE OVER SWITCH TO READ MODE + HRRI D,%QMRD1 + TLZE D,%QAEFW + HRRI D,%QMIDL ;TRYING TO CLOSE, STOP CHANNEL + MOVEM D,QSRAC(C) + AOS QWBUFS ;COMPENSATE FOR EXTRA SOS BELOW + +QWRFIN: TLNN D,%QACTH ;WRITE COMPLETE, RETURN BUFFER + PUSHJ P,IMEMR + TLNE D,%QACTH + PUSHJ P,CIMEMR + SOS QSBFS(C) + SOS QWBUFS + MOVE TT,QSGL(C) + MOVEM TT,QSLBLK(C) + JRST QINT1B + +QRD1FN: HLLZS QSRAC(C) .SEE %QMIDL ;BLOCK-AT-A-TIME READ COMPLETE, IDLE THE CHANNEL + +QRDFIN: MOVEI B,.BM MLO ;NORMAL READ COMPLETED + ANDCAM B,MEMBLT(A) ;THREAD ONTO CHANNEL LIST + HLRZ B,QBFP(C) + SKIPE B + DPB A,[MLO,,MEMBLT(B)] + SKIPN B + MOVEM A,QBFP(C) + HRLM A,QBFP(C) + SKIPL B,QPIBSZ(C) ;GET BYTE COUNT OF BLOCK + JRST QRDFN1 + HRRZ B,1777(R) ;FUNNY BLOCK, GET FROM LAST WORD + ; 8/20/90 No more funny blocks + HRRZ TT,QSBYTE(C) ;AND MAKE SURE IT'S NOT TOO BIG + IMULI TT,2000 + CAMLE B,TT + MOVE B,TT +QRDFN1: HRRZM B,MEMPNT(A) ;PASS TO MAIN PROGRAM + AOS QSBFS(C) +IFE DMDSK, LDB B,[XWBLK QXWDS] + .ALSO MOVEM B,QSLBLK(C) + +;XFER COMPLETE, DEACTIVATE CHANNEL + +QINT1B: SETOM QACTTM +QINT1A: SETOM QSGL(C) + SETOM QSCABN(C) +QINT1E: +IFE DC10P, SETOM QSKT1(Q) +IFN DC10P,[ + MOVE TT,QTRAN(Q) + SETOM QSKT1(TT) +] ;DC10P +IFN T300P,[ + CAIL Q,T300P + SETOM QSDU1 + CAIGE Q,T300P + SETOM QSDU +];T300P +.ELSE SETOM QSDU +;DROPS THROUGH + ;DROPS IN + +;ACTIVATE CHANNELS, LOOK FOR SEEKS AND TRANSFERS TO BE DONE + +QINT1: SETZM QHUNGF + SETOM QTUNT ;NO UNIT SELECTED YET +IFN T300P, SETOM QTUNT1 + MOVE C,QTCHN ;START SCAN IN SUITABLE PLACE + MOVEM C,QLCHN + JRST QINT2D + +QINT2L: CAIGE C,NQCHN ;IF DIR-WRITE OR SWAP CHANNEL, DON'T CHECK QUSR + SKIPL QUSR(C) + SKIPGE D,QSRAC(C) .SEE %QALOK + JRST QINT2C ;CHANNEL LOCKED OR NOT OPEN, SKIP IT + MOVE Q,QDSKN(C) + SKIPL E,QSGL(C) + JRST QINT4 ;JUMP IF CHANNEL ACTIVE ALREADY + TLNE D,%QACTH+%QAOUT + JRST QINT2C ;CHANNEL BLOCKED BY CORE JOB, DON'T ACTIVATE + TRNE D,-%QMMAX + BUG + XCT .+1(D) ;INVOKE ACTIVATE HANDLER + OFFSET -. +%QMIDL::JRST QINT2C ;IDLE - DON'T ACTIVATE +%QMRD:: JRST QRDACT ;READ +%QMWRT::JRST QWRACT ;WRITE +%QMWOV::JRST QWRACT ;WRITE OVER +%QMRD1::JRST QRDACT ;READ 1 BLOCK + JRST 4,QINT2C ;ILL CODE +%QMUDR::JRST QDRACT ;UFD READ +%QMMDR::JRST QDRACT ;MFD READ +%QMTTR::JRST QDRACT ;TUT READ +%QMUDW::JRST 4,QINT2C ;UFD WRITE - SHOULDN'T LEAVE THIS MODE AROUND +%QMMDW::JRST 4,QINT2C ;MFD WRITE - .. +%QMTTW::JRST QINT5 ;TUT WRITE - MAY BE WRITING SECOND PAGE +%QMSWP::JRST SWPACT ;SWAP + JRST 4,QINT2C ;ILL CODE + JRST 4,QINT2C ;ILL CODE + JRST 4,QINT2C ;ILL CODE +%QMMAX::OFFSET 0 + +; ACTIVATION ROUTINES + +SWPACT: SKIPL SWUSR(Q) + BUG ;SWAPPING ALREADY ACTIVE ON THIS DISK + MOVE A,MEMFR + SUB A,NCBCOM + MOVEI B,0 ;CHECK FIRST FOR SWAP IN OR OUT + CAIGE A,6 ;ACCORDING TO AVAIL MEM + MOVEI B,1 + SKIPN @SWAPL(B) ;IF NO TRAFFIC THAT DIRECTION, CHECK THE OTHER. + TRC B,1 + HRRZ E,@SWAPL(B) + JUMPE E,QINT2C ;NO SWAPPING TRAFFIC THIS DISK. + LDB A,[MLO,,MEMBLT(E)] ;TAKE BLOCK OFF LIST + SKIPN A + SETZM @SWAPL(B) ;LAST BLOCK, LIST IS NOW EMPTY + HRRM A,@SWAPL(B) ;SET NEW FIRST BLOCK + LDB D,[MMMPX,,MEMBLT(E)] + ADD D,MMPEAD ;GET MMP ADDRESS + LDB TT,[410200,,(D)] + TRNN TT,1 + BUG ;THIS PAGE SHOULD BE MARKED IN TRANSIT + HRRZM D,QSMMP(Q) + SOS SILNG(B) + CAIGE E,TSYSM + CAIGE E,SYSB + BUG + HRRZM E,QSCABN+NQCHN+1(Q) + CLEARM SWUSR(Q) ;CHNL ACTIVE + HLRZ E,MEMPNT(E) + MOVEM E,QSGL+NQCHN+1(Q) ;DISK BLOCK + HRRZS QSRAC+NQCHN+1(Q) .SEE %QMSWP + MOVNM B,QSCRW+NQCHN+1(Q) ;DIRECTION + CLEARM QERRS+NQCHN+1(Q) ;NO ERRORS (YET) + JRST QINT4 ;CHANNEL SUCCESSFULLY ACTIVATED + + +; MORE ACTIVATION ROUTINES + +QRDACT: TLNE D,%QAACC ;ACTIVATE READ CHANNEL + JRST QINT2C ;NOT IF USER HACKING RANDOM ACCESS NOW + SETZM QERRS(C) + MOVE J,QUDPR(C) + SKIPGE QSNLCN(J) + JRST QINT2C ;USER DIRECTORY OUT OR LOCKED + MOVE A,QSBFS(C) + SKIPL QSMDN(C) + AOS A ;A := TOTAL NUMBER OF BUFFERS + CAMLE A,QRDAHD ;HOW MUCH SHOULD BE READ AHEAD + JRST QINT2C ;BLOATED, DON'T ACTIVATE + SKIPE QSBI(C) + JRST QINT4A ;BLOCKS LEFT FROM LAST TIME +QINT4B: PUSHJ P,QIDRCH ;GET NEXT DESC BYTE IN A, ALSO RET BYTE PNTR IN TT + CAIN A,UDWPH + JRST QINT4B + JUMPE A,QEOF ;REACHED READ EOF + TRZE A,40 + JRST QINT4C + CAILE A,UDTKMX + JRST QINT4D ;SKIP AND TAKE + MOVEM A,QSBI(C) ;TAKE NEXT N +QINT4A: SOS QSBI(C) + AOS E,QSLGL(C) +QINT4G: MOVEM E,QSGL(C) + MOVSI B,%QALBK + ANDCAM B,QSRAC(C) ;CLEAR PROCESSING LAST BLOCK IN FILE BIT + HRRZ A,QSBYTE(C) + IMULI A,2000 ;NUMBER OF BYTES IN A FULL BLOCK +IFN DMDSK,[ + MOVSI D,%QAFNY ;FUNNY FILE + TDNE D,QSRAC(C) + SETO A, +] + MOVEM A,QPIBSZ(C) ;SET FUNNY BIT + SKIPE QSBI(C) + JRST QINT4 ;IF MORE BLOCKS FOLLOW DON'T CHECK EOF + PUSHJ P,QIDRCH ;GET NEXT DESCR BYTE + SOS QDIRP(C) ;CORRECT PNTR + JUMPN A,QINT4 + MOVE A,QUDFPR(C) ;THIS IS LAST BLOCK + ADD A,QSNLCN(J) + LDB D,[UNBYTE+UNREF(A)] + PUSHJ P,QBDCD + IMUL D,E ;NUMBER OF UNUSED BITS IN LAST WORD + LDB E,[QSBSIZ(C)] ;(DEPEND ON DIVIDE ROUNDING DOWN) + IDIV D,E ;NUMBER OF UNUSED BYTES (IN SIZE OPEN) + LDB E,[UNWRDC+UNRNDM(A)];NUMBER OF USED WORDS IN LAST BLOCK + SKIPN E + MOVEI E,2000 + IMULI E,@QSBYTE(C) ;CONVERT TO NUMBER OF BYTES + SUB E,D ;NUMBER OF VALID BYTES IN BLOCK + HRRM E,QPIBSZ(C) ;STORE BYTE COUNT OF LAST BLOCK + IORM B,QSRAC(C) .SEE %QALBK + MOVE E,QSGL(C) + JRST QINT4 + +QINT4D: MOVEI E,1-UDTKMX(A) ;SKIP N AND TAKE 1 + ADDB E,QSLGL(C) + JRST QINT4G + +QWRACT: SKIPN I,QBFP(C) ;ACTIVATE WRITE CHANNEL + JRST QINT2C ;END OF WRITE LIST FOR NOW + HRRZM I,QSCABN(C) + LDB H,[MLO,,MEMBLT(I)] + HRRM H,QBFP(C) + SKIPN H + SETZM QBFP(C) ;LAST BLOCK, LIST NOW EMPTY + HLRZ E,MEMPNT(I) + MOVEM E,QSGL(C) + JRST QINT4 + +QDRACT: MOVE E,QSLGL(C) ;ACTIVATE DIRECTORY-READ CHANNEL + MOVEM E,QSGL(C) +; JRST QINT4 ;DROPS THROUGH + ;DROPS IN +QINT4: SKIPL QSCABN(C) ;SKIP IF NEED MEMORY + JRST QINT5 + PUSHJ P,IOMQ ;GET MEMORY FOR READ BUFFER + JRST QINT2C ;CAN'T +QINT5A: MOVEM A,QSCABN(C) + MOVEI D,MU23B + DPB D,[MUR,,MEMBLT(A)] + DPB C,[MNUMB,,MEMBLT(A)] + +QINT5: +IFN DC10P, MOVE TT,QTRAN(Q) +.ELSE MOVE TT,Q + SKIPN QSEEK(TT) ;IGNORE SEEKING DRIVE + SKIPGE QRCAL(TT) ;IGNORE RECALIBRATING DRIVE + JRST QINT2C +IFN T300P,[ ;IGNORE IF FOR CONTROLLER THAT IS NOT READY + CAIL TT,T300P + JRST [ SKIPGE QSDU1 + SKIPL QTUNT1 ;NOTE CODE HERE IS SIMILAR TO THAT AT QINT2F + JRST QINT2C ;T-300 CONTROLLER BUSY OR ALREADY COMMITTED + HRRZM Q,QTUNT1 ;WILL TRANSFER ON THIS UNIT + HRRZM C,QTCHN1 ;FOR THIS CHANNEL + JRST QINT2C ] ;T-300 CODE IS SIMPLIFIED SINCE NO SEEK OVERLAPS + SKIPL QSDU + JRST QINT2C +];T300P + HRRZ B,QSKT1(TT) + CAIN B,(C) + JRST QINT2F ;ALREADY SET FOR ME + SKIPL QSKT1(TT) + JRST QINT2C ;SET FOR SOME OTHER CHNL + HRRZM C,QSKT1(TT) ;AVAILABLE, SET IT FOR ME + PUSHJ P,QPOSR ;CONVERT DISK ADDRESS TO PHYSICAL +IFN DC10P,[ ;AND INITIATE SEEK + ADD E,[DSEEK] + CONSZ DC0,DSSRUN+DSSACT + JRST .-1 + DATAO DC0,E + LDB B,[DCYL E] + MOVE TT,QTRAN(Q) ;PRETEND SEEK ALREADY COMPLETE + MOVEM B,QPOSGL(TT) + MOVEM B,QPOS(TT) + JRST QINT2F ;DON'T WAIT FOR SEEK, START TRANSFER RIGHT AWAY +] ;DC10P +IFN RP10P,[ + TLO E,(DSEEKC) ;DSK SEEK + CONSZ DPC,20 + JRST 4,.-1 + LDB TT,[DCYL E] + TRNE E,.BM DCYLXB + ADDI TT,400 + CAMN TT,QPOS(Q) + JRST QINT2F ;IF WE'RE THERE, DON'T SEEK + MOVEM TT,QPOSGL(Q) + DATAO DPC,E + MOVEM E,QSEEK(Q) + JRST QINT2C ;THIS ONE SEEKING, GO GET ANOTHER +] ;RP10P +IFN RH11P,[ + PUSHJ P,RHSLCT ; Select drive + HRRZ A,E + IOWRQ A,%HRADR ; Set track and sector + HLRZ A,E + IOWRQ A,%HRCYL ; Set cylinder + CAMN A,QPOS(Q) + JRST QINT2F ; On cylinder, don't seek + MOVEM A,QPOSGL(Q) + MOVEI A,%HMSEK + PUSHJ P,RHCMD ; Start seeking + SETOM QSEEK(Q) + JRST QINT2C ; Start other drives now? +] ;RH11P +IFN RH10P,[ + MOVSI A,%HRCYL(Q) ;STORE ADDRESS IN DRIVE + HLR A,E + PUSHJ P,RHSET + MOVSI A,%HRADR(Q) + HRR A,E + PUSHJ P,RHSET + HLRZ TT,E ;GET CYLINDER PART OF ADDRESS + CAMN TT,QPOS(Q) + JRST QINT2F ;ON CYLINDER, DON'T SEEK + MOVEM TT,QPOSGL(Q) + MOVSI A,%HRDCL(Q) ;START SEEK + HRRI A,%HMSEK + PUSHJ P,RHSET + SETOM QSEEK(Q) + JRST QINT2C ;THIS ONE SEEKING, START OTHER DRIVES +] ;RH10P + +IFN KL10P,[ +;CALL HERE TO SWEEP THE CACHE. CORE PAGE # IN R. +;INSTRUCTION AT CALL+1 SHOULD SKIP IF READING INTO CORE. +;CLOBBERS A,B,D,E,TT. + +CSHSWP: SETZB A,B ;A COUNTS WAIT TIME, B IS SWEEP INSTRUCTION + XCT @(P) + TLOA B,(SWPUO (R)) ;WRITE - UNLOAD PAGE FROM CACHE + MOVSI B,(SWPIO (R)) ;READ - CLEAR PAGE FROM CACHE + LSH R,1 ;HARDWARE PAGES ARE 1/2 K + XCT B ;SWEEP FIRST HALF-PAGE + MOVE D,[CONSZ 200000] + MOVE E,[AOJA A,D] + MOVSI TT,(POPJ P,) + PUSHJ P,D ;WAIT IN ACS TO MINIMIZE MBOX INTERFERENCE + AOS R ;SWEEP SECOND HALF-PAGE + XCT B + PUSHJ P,D + XCT @(P) + AOSA NCSHU ;COUNT NUMBER OF TIMES THIS DONE + AOSA NCSHI + JRST [ ADDM A,NCSHUL ? JRST .+2 ] + ADDM A,NCSHIL ;AND COUNT NUMBER OF LOOPS IN ACS + LSH R,-1 + JRST POPJ1 +] + +;VARIOUS EXITS FROM CHANNEL-CHECKING ROUTINES + +QINT2F: SKIPL QTUNT ;THIS CHANNEL IS READY TO TRANSFER + JRST QINT2C ;ALREADY FOUND A TRANSFER + HRRZM Q,QTUNT ;WILL TRANSFER ON THIS UNIT + HRRZM C,QTCHN ;FOR THIS CHANNEL +QINT2C: CAMN C,QLCHN ;CONTINUE CHANNEL SCAN + JRST QINT2E ;UNLESS CHECKED ALL CHANNELS +QINT2D: CAIL C,NQCHN+1+NQS-1 ;SKIP IF NOT TIME TO WRAP AROUND + SETO C, + AOJA C,QINT2L ;CHECK ANOTHER + +QINT2E: +IFN T300P,[ + MOVE C,QTCHN1 + SKIPL Q,QTUNT1 ;FOUND XFER FOR T-300? + JRST QDE1 ;YES +];T300P + SKIPGE Q,QTUNT ;FOUND XFER? + JRST QINT3 ;IDLE + MOVE C,QTCHN +;Q DISK TO TRANSFER ON, C CHANNEL. START (OR RESTART) TRANSFER ON THEM. +QDE1: MOVE R,QSCABN(C) +IFN KL10P,[ + PUSHJ P,CSHSWP + SKIPGE QSCRW(C) +];KL10P +IFN KS10P,[ + SKIPL QSCRW(C) + CLRCSH +];KS10P +IFE T300P, MOVEM C,QSDCH +IFN T300P,[ + CAIL Q,T300P + JRST T3IO + CAIGE Q,T300P + MOVEM C,QSDCH +];T300P + SKIPGE B,QSCRW(C) ;LOAD R/W STATUS IN B + JRST QINT6W + ;READ - DROPS IN +IFN RP10P,[ + MOVSI T,(DREADC) +QINT6A: IORI T,7000+QICWA ;DON'T STOP FOR PARITY ERRORS (PLUS INITIAL CHNL ADR) + MOVEM T,QCHPRG + DPB Q,[DUNFLD+QCHPRG] + HLLZS QIOWD + DPB R,[121000,,QIOWD] + LDB E,[100300,,R] ;MA15-17 + TRC E,7 + DPB E,[410300,,QIOWD] ;SET UP HIGH ADDR BITS. + MOVE TT,QIOWD + SOS TT + HRRM TT,QIOWD + SETZM QIOWD+1 + MOVEM Q,QSDU + MOVE E,QSGL(C) + PUSHJ P,QPOSR + IORM E,QCHPRG +QOVR: CONSZ DPC,20 + JRST QOVR + SKIPGE Q,QSDU + BUG + CONO DPC,175700+DSKCHN +IFN QRDCMP,[ + SETZM RDCPHS ;ASSUME NO READ-COMPARE WANTED + SKIPE QRCSW + SETOM RDCPHS ;REMEMBER TO READ-COMPARE LATER +];QRDCMP + MOVEI TT,QIOWD + HRRZM TT,QICWA + MOVE E,QCHPRG + LDB TT,[DCYL E] + TRNE E,.BM DCYLXB + ADDI TT,400 + CAME TT,QPOS(Q) + BUG ;DONT DO ANYTHING IF NOT WHERE YOU SHOULD BE + SETZM QICWA+1 + DATAO DPC,QCHPRG ;ENTRY ON OVERRUN + MOVE A,TIME + MOVEM A,LQTM + MOVEM Q,QSDU + CAILE C,NQCHN + JRST .+5 + SKIPL B + AOSA NRXFR + AOS NWXFR + JRST QINTX + SKIPL B + AOSA NSRXFR + AOS NSWXFR +QINTX: JRST DSKEX + +QHUNG: CONO DPC,DCLEAR+20+DSKCHN ;DISK NOTICED TO BE HUNG, RESET IT + SETOM QHUNGF ;TELL P.I. LEVEL TO RETRY OPERATION + MOVE Q,QSDU + AOS NTQHNG(Q) + BUG INFO,[DSK: HUNG ON UNIT ],DEC,QSDU,[QCHPRG=],OCT,QCHPRG + POPJ P, +] + ;READ - DROPS IN + +IFN RH11P,[ + MOVEI T,%HMRED +QINT6A: MOVEM T,QCHPRG + MOVEM Q,QSDU + LSH R,1 ; Set up Unibus map for RH11 to point at + TRO R,%UQVAL+%UQFST ; the block in question. + IOWRQ R,UBAPAG+QUBPG_1 + ADDI R,1 + IOWRQ R,UBAPAG+QUBPG_1+1 + MOVE E,[-4000,,QUBPG_14] + MOVEM E,QIOWD + MOVE E,QSGL(C) + PUSHJ P,QPOSR + MOVEM E,QCHPGA +QOVR: IORDQ TT,%HRCS1 ; Enter here to recover from PI level lossage + TRNN TT,%HXRDY + JRST QOVR + SKIPGE Q,QSDU + BUG +QECCX: ;; Enter here from ECC correction code + PUSHJ P,RHCLRC ; Clear controller errors and select drive + HLRZ TT,QCHPGA + CAME TT,QPOS(Q) + JRST DSKEX ; Punt if not positioned in right place + IOWRQ TT,%HRCYL ; Store cylinder in drive + HRRZ TT,QCHPGA + IOWRQ TT,%HRADR ; Store track and sector + HLRZ TT,QIOWD + IOWRQ TT,%HRWC ; Store halfword count + HRRZ TT,QIOWD + IOWRQ TT,%HRBA ; Store Unibus base address + MOVE A,QCHPRG + PUSHJ P,RHCMD ; Go! + MOVE A,TIME + MOVEM A,LQTM + CAILE C,NQCHN + JRST .+5 + SKIPL B + AOSA NRXFR + AOS NWXFR + JRST QINTX + SKIPL B + AOSA NSRXFR + AOS NSWXFR +QINTX: JRST DSKEX + +QHUNG: MOVEI A,%HYCLR ; Sock controller in jaw + IOWRQ A,%HRCS2 + MOVE Q,QSDU + PUSHJ P,RHSLCT ; Select drive + PUSHJ P,RHCLRD ; Redundantly clear drive + SETOM QHUNGF + AOS NTQHNG(Q) + BUG INFO,[DSK: HUNG ON UNIT #],DEC,QSDU,[ADDR=],OCT,QCHPGA + POPJ P, + +] ;RH11P + ;READ - DROPS IN + +IFN RH10P,[ + MOVEI T,%HMRED +QINT6A: IORI T,QICWA_6 .SEE $HCICWA + TLO T,%HRCTL(Q) + MOVEM T,QCHPRG + MOVEM Q,QSDU + LSH R,10. ;ASSEMBLE DF10-C CONTROL WORD + SUBI R,1 + MOVNI E,2000 + DPB E,[$DFWC R] + MOVEM R,QIOWD + SETZM QIOWD+1 + MOVE E,QSGL(C) + PUSHJ P,QPOSR + MOVEM E,QCHPGA +QOVR: CONSZ DSK,20 ;ENTER HERE FOR RECOVER FROM PI HALT, OVERRUN + JRST QOVR + SKIPGE Q,QSDU + BUG + MOVEI TT,QIOWD + HRRZM TT,QICWA +QECCX: SETZM QICWA+1 ;ENTER HERE FROM ECC CORRECTION CODE + CONO DSK,%HOCLR+%HORAE+%HOATN+DSKCHN + HLRZ TT,QCHPGA + CAME TT,QPOS(Q) + JRST DSKEX ;DONT DO ANYTHING IF NOT WHERE YOU SHOULD BE + MOVSI A,%HRCYL(Q) ;STORE ADDRESS IN DRIVE + HLR A,QCHPGA + PUSHJ P,RHSET + MOVSI A,%HRADR(Q) + HRR A,QCHPGA + PUSHJ P,RHSET + MOVE A,QCHPRG + PUSHJ P,RHSET +IFN QRDCMP,[ + SETZM RDCPHS ;ASSUME NO READ-COMPARE WANTED + SKIPE QRCSW + SETOM RDCPHS ;REMEMBER TO READ-COMPARE LATER +];QRDCMP + MOVE A,TIME + MOVEM A,LQTM + CAILE C,NQCHN + JRST .+5 + SKIPL B + AOSA NRXFR + AOS NWXFR + JRST QINTX + SKIPL B + AOSA NSRXFR + AOS NSWXFR +QINTX: JRST DSKEX + +QHUNG: CONO DSK,%HOCLR+%HORST+%HOSTP+DSKCHN ;HUNG, CLEAR CONTROLLER + SETOM QHUNGF + MOVE Q,QSDU + AOS NTQHNG(Q) + MOVSI A,%HRDCL(Q) + HRRI A,%HMCLR ;CLEAR DRIVE + PUSHJ P,RHSET + BUG INFO,[DSK: HUNG ON UNIT ],DEC,QSDU,[ADDR=],OCT,QCHPGA + POPJ P, +] + ;READ - DROPS IN +IFN DC10P,[ + MOVSI T,(DREAD) +QINT6A: MOVEM T,QCHPRG + MOVEM Q,QSDU + DPB R,[DCBN+QCHPR2] ;MEM BLOCK # + DPB R,[DCBN+QCHPR3] ;FOR POSSIBLE READ COMPARE + MOVE E,QSGL(C) + PUSHJ P,QPOSR ;QPOSR ALSO STORES MAPPED UNIT IN QCHPRG + IORB E,QCHPRG + CLEARM QCHPR4 ;STORE DHALT FOR NO RCC + CAILE C,NQCHN + JRST QINT6S ;SWAPPING CHNL + SKIPL B + AOSA NRXFR + AOS NWXFR + CAIE C,NQCHN ;ALWAYS R COMPARE DIR WRITES + SKIPLE QRCSW ;SKIP ON NOT READ COMP EVERYTHING + JRST QINT6B ;RCC + SKIPL QRCSW + JUMPL B,QINT6B ;RCC WRITES + HRRZ D,QSRAC(C) + CAIL D,%QMUDR + CAILE D,%QMTTR + JRST QINT6C ;NOT DIR READ +QINT6B: TLZ E,340000 ;CHANGE TO READ COMPARE + MOVEM E,QCHPR4 +QINT6C: SETOM QERS1 ;ERR VERIFY IND +QOVR: CONSZ DC0,DSSRUN+DSSACT + JRST QOVR + DATAO DC0,[DJMP QCHPRG] ;ENTRY ON OVERRUN +QOVR1: CONO DC0,DCSET+DCIENB+DSKCHN ;INTERRUPT WHEN DONE + MOVE A,TIME + MOVEM A,LQTM +QINTX: JRST DSKEX + +QINT6S: SKIPL B + AOSA NSRXFR + AOS NSWXFR + JUMPL B,QINT6B ;RCC WRITES + JRST QINT6C ;NOT READS + +QHUNG: CONO DC0,DCCSET+DSKCHN ;HUNG, CLEAR CONTROLLER + SETOM QHUNGF + MOVE Q,QSDU + AOS NTQHNG(Q) + BUG INFO,[DSK: HUNG ON UNIT ],DEC,QSDU,[QCHPRG=],OCT,QCHPRG + POPJ P, +] + +QINT6W:IFE DMDSK,[ + MOVE T,[QXWDS-1,,QXWDS] + BLT T,QXWDS+3 + CAIL C,NQCHN + JRST QNT6W2 ;SWAP OR DIR WRITE + MOVE A,QUDPR(C) + MOVE T,QSNUD(A) + MOVEM T,QXWDS+XWSYSN + HRRZ A,QSNLCN(A) + ADD A,QUDFPR(C) + MOVE T,UNFN1(A) + MOVEM T,QXWDS+XWFN1 + MOVE T,UNFN2(A) + MOVEM T,QXWDS+XWFN2 + MOVE T,QSLBLK(C) + DPB T,[XWBLK+QXWDS] + LDB T,[MWC,,MEMBLT(R)] + DPB T,[XWAWC+QXWDS] +QNT6W2: +] +IFN DC10P, MOVSI T,(DWRITE) +IFN RP10P, MOVSI T,(DWRITC) +IFN RH10P, MOVEI T,%HMWRT +IFN RH11P, MOVEI T,%HMWRT + JRST QINT6A + +IFN T300P,[ +T3IO: MOVEM C,QSDCH1 ;THIS IS MORE OR LESS QINT6A FOR T-300 + MOVEM Q,QSDU1 + MOVEI A,%DMRED + SKIPGE B,QSCRW(C) + MOVEI A,%DMWRT +T3IO1: MOVE R,QSCABN(C) ;RE-ENTER HERE TO RETRY WITH COMMAND IN A + LSH R,10. ;FIRST ADDRESS IN TRANSFER + TLO R,730000 ;12-BIT BYTES, START WITH FIRST BYTE IN WORD + MOVSI E,-4 ;SET UP BYTE POINTERS + MOVEM R,DSCPNT(E) + ADDI R,400 + AOBJN E,.-2 + MOVE D,QSGL(C) ;DO LIKE QPOSR + CAIL D,NBLKS1 + BUG + IDIVI D,NBLKC1 + MOVEM D,DSCCYL + IMULI E,SECBL1 + IDIVI E,NSECS1 + MOVEM E,DSCHED + MOVEM TT,DSCSEC + PUSHJ P,T3CMD + CAILE C,NQCHN + JRST .+5 + SKIPL B + AOSA NRXFR1 + AOS NWXFR1 + JRST QINTX + SKIPL B + AOSA NSRXF1 + AOS NSWXF1 + JRST QINTX + +;START T-300, COMMAND IN A, DRIVE IN Q +T3CMD: MOVEI TT,2561 + MOVEM TT,DSCCHK + MOVE TT,TIME + MOVEM TT,LQTM1 + MOVEI TT,-T300P(Q) + MOVEM TT,DSCDRV + HRRZM A,DSCCMD + SETZM DSCDON + MOVEI T,1 + MOVEM T,DSCREQ + CONO DLC,100040+TTYCHN ;INTERRUPT 11 + POPJ P, + +QHUNG1: MOVE Q,QSDU1 + AOS NTQHNG(Q) + BUG INFO,[DSK: HUNG ON T-300 UNIT ],DEC,QSDU + MOVEI TT,5*60.*30. ;SHUT UP FOR FIVE MINUTES + ADDM TT,LQTM1 + POPJ P, +];T300P + +QDE: MOVE C,QSDCH +IFN RP10P, PUSHJ P,QERSOFT +IFN DC10P, AOSE PKIDM + SKIPGE Q,QSDU + BUG +IFN DC10P,[ + TRNE TT,DCKSER + JRST .+3 ;GET CKS ERR + TRNE TT,DRCER + AOS NQCMPE(Q) ;# COMPARE ERRORS [WITH NO OTHER ERROR] +];DC10P +IFN T300P,T3DE: ;ENTER HERE FOR ERROR ON T-300 + AOS NQDE(Q) + SKIPL R,QSCRW(C) + AOSA NQRDE(Q) + AOS NQWDE(Q) +IFN DC10P, JUMPL R,QERV1 ;DO ANOTHER RD/COMP TO SEE IF OK ON DSK (IF WRITE) +QERV2: AOS R,QERRS(C) + TRNN R,10 ;TRY 8 TIMES BEFORE AND AFTER REPOSITION + JRST QDE1 + TRNN R,1000 + JRST QDE2 ;TRY REPOSITION ONCE +QERV3: MOVE D,QSRAC(C) + TRNE D,-%QMMAX + BUG + XCT .+1(D) ;INVOKE IRRECOV ERROR HANDLER +QERV: OFFSET -. +%QMIDL::JRST 4,QERV+. ;IDLE CHANNELS SHOULDN'T GET HERE +%QMRD:: JRST QPE2D ;USER DATA +%QMWRT::JRST QDE1 ;WRITE KEEP TRYING +%QMWOV::JRST QDE1 ;.. +%QMRD1::JRST QPE2D + JRST 4,QERV+. ;ILL CODE +%QMUDR::JRST QUDER1 +%QMMDR::JRST QDE1 +%QMTTR::JRST QDE1 +%QMUDW::JRST QDE1 +%QMMDW::JRST QDE1 +%QMTTW::JRST QDE1 +%QMSWP::JRST QSWPER + JRST 4,QERV+. ;ILL CODE + JRST 4,QERV+. ;ILL CODE + JRST 4,QERV+. ;ILL CODE +%QMMAX::OFFSET 0 + +QSWPER: SKIPGE CIRPSW ;TRY XFER AGAIN IF CIRPSW NOT AVAILABLE + SKIPGE QSCRW(C) + JRST QDE1 ;DON'T TRY TO DO ANYTHING ABOUT WRITE ERRORS + MOVE A,QSCABN(C) ;READ - GIVE ALL USERS OF PAGE PARITY ERR + PUSH P,C + PUSH P,Q + MOVE C,[2200,,MEMPNT(A)] + PUSHJ P,UCPRL + 400000,,QSWER1 + LDB Q,[2200,,MEMPNT(A)] + DPB Q,C ;REMOVE MEM FROM LOOP + PUSHJ P,IMEMR ;AND GIVE BACK MEM + POP P,Q ;ALTERNATIVELY, COULD LEAVE THE MEM BUT SET MMPBAD + POP P,C ;TO INDICATE THAT THAT MEM COPY OF THE PAGE IS NO GOOD. + MOVEI D,2 + DPB D,[410200,,@QSMMP(Q)] ;PAGE IS OUT + JRST QPE2D + +QSWER1: PUSH P,T + MOVSI T,%PJPAR + IORM T,PIRQC(U) + JRST POPTJ + +IFN DC10P,[ +QERV1: SKIPN QCHPR4 + JRST QERV2 ;NOT SET FOR RCC + CLEARM QERS1 +QERL2: CONSZ DC0,DSSRUN+DSSACT + JRST .-1 + DATAO DC0,[DJMP QCHPR4] + JRST QOVR1 + +QERL1: AOS Q,QERS1 + CAIGE Q,50. + JRST QERL2 + AOSA NQWIRE +QEROK: AOS NQWRE + MOVE C,QSDCH + MOVE Q,QSDU + SETOM QERS1 + JRST QERV2 +] +QDE2: MOVEI R,1000 + MOVEM R,QERRS(C) ;CLOBBER QERRS + JRST QREC ;AND TRY REPOSITIONING + +IFN RP10P,[ +QERSOFT:LDB A,[DCYL+QCHPRG] ;PARSE STARTING DISK ADDRESS + LDB B,[DCYLXB+QCHPRG] + LSH B,8 + IOR A,B + LDB B,[DSURF+QCHPRG] + LDB D,[DSECT+QCHPRG] + SKIPN QERRS(C) ;PRINT ONLY ONCE, NOT ON RETRIES + BUG INFO,[DSK: SOFT ERR UNIT ],DEC,Q,[CYL ],DEC,A,[STARTING HEAD ],DEC,B,[SEC ],DEC,D,[CONI=],OCT,QERST,[DATAI=],OCT,QERDTI + POPJ P, + +QRECAT: CONI DPC,A + BUG INFO,[DSK: SEEK ERR DATAO=],OCT,QSEEK(Q),[CONI=],OCT,A,[DATAI=],OCT,E + SETZM QSEEK(Q) + JRST QREC +];RP10P + +QHE: MOVE C,QSDCH +IFN RP10P, PUSHJ P,QERSOFT + SKIPGE Q,QSDU + BUG +IFN T300P,T3HE: ;ENTER HERE FOR ID ERROR ON T-300 + AOS NQHE(Q) + AOS E,QERRS(C) + CAIL E,5. + JRST QHE2 +QREC: +IFN T300P,[ + CAIL Q,T300P + JRST [ SETOM QRCAL(Q) + MOVEI A,%DMREC + PUSHJ P,T3CMD + MOVEM Q,QSDU1 ;CONTROLLER IS TIED UP BY RECAL BECAUSE + JRST QINT1 ] ;IT'S TOO DAMNED PSEUDO-INTELLIGENT +];T300P +IFN DC10P,[ + MOVE TT,QTRAN(Q) +QREC0: DPB TT,[DUNFLD+QRECAL] + SETOM QRCAL(TT) + SETOM QSKT1(TT) + CLEARM QSPPS(TT) + CLEARM QPOSGL(TT) + SETOM QPOS(TT) + MOVEI T,10. ;5-SECOND RECALIBRATE TIMEOUT + MOVEM T,QRCTIM(TT) + DATAO DC0,QRECAL + CONO DC0,DCSET+DCATEB+DSKCHN ;ENABLE ATTENTION +] +IFN RP10P,[ + DPB Q,[DUNFLD+QRECAL] + SETOM QPOS(Q) + DATAO DPC,QRECAL + CLEARM QSPPS(Q) + SETOM QSKT1(Q) + SETOM QRCAL(Q) ;INDICATE RECALIBRATING THIS DISK + CLEARM QPOSGL(Q) +] +IFN RH11P,[ + PUSHJ P,RHSLCT ; Select drive + PUSHJ P,RHCLRD ; Clear errors + MOVEI A,%HMREC + PUSHJ P,RHCMD ; Recalibrate + CLEARM QSPPS(Q) + CLEARM QPOSGL(Q) + SETOM QPOS(Q) + SETOM QSKT1(Q) + SETOM QRCAL(Q) +] ;RH11P +IFN RH10P,[ + MOVSI A,%HRDCL(Q) + HRRI A,%HMCLR + PUSHJ P,RHSET ;CLEAR ERROR OUT OF DRIVE. + MOVSI A,%HRDCL(Q) + HRRI A,%HMREC ;RECALIBRATE + PUSHJ P,RHSET ;MAYBE SHOULD TRY OFFSET FIRST? + CLEARM QSPPS(Q) + CLEARM QPOSGL(Q) + SETOM QPOS(Q) + SETOM QSKT1(Q) + SETOM QRCAL(Q) +] + SETOM QSDU + JRST QINT1 ;LOOK FOR SOME OTHER TRANSFER + +QHE2: SKIPL QSCRW(C) ;HANG UP OR POSITIONING ERR (AFTER 5 TRIES) + JRST QERV3 ;IF READ, PERFORM RECOVERY + +QPE2D: MOVSI R,%QAPAR ;IRRECOVERABLE ERROR + IORM R,QSRAC(C) + AOS QIRRCV + MOVE D,QSGL(C) + MOVEM D,QIRCBK ;BLOCK # AT IRRCV ERR + MOVEM Q,QIRUNT ;SAVE UNIT TOO + CAILE C,NQCHN + AOS NIRSWE ;# IRRCV SWAPPING ERRS + MOVE I,Q + SKIPGE QTUTO(I) + JRST QPE2E ;DON'T MESS WITH LOCKED TUT + PUSHJ P,TUTPNT + CAIN B,TUTLK ;PRINT MESSAGE IF NOT YET LOCKED OUT + JRST QINTI + MOVEI B,TUTLK + DPB B,D +QPE2E: BUG INFO,[DSK: IRREC DATA ERR #],DEC,QIRRCV,[UNIT=],DEC,QIRUNT,[BLK=],OCT,QIRCBK + JRST QINTI + +QUDER1: MOVEI R,1(Q) ;TRY TO READ DIR FROM OTHER DISKS +QUDER2: CAIL R,NQS + MOVEI R,0 + CAME R,QDSKN(C) + JRST QUDER4 + JRST QDE1 ;NO OTHER DISK AVAIL TO READ FROM, TRY AGAIN + +QUDER4: SKIPGE QACT(R) + AOJA R,QUDER2 + HRRZM R,QDSKN(C) ;TRY THIS DISK +IFN T300P,[ + CAIL Q,T300P + JRST [ SETOM QSDU1 ;FREE DRIVE FORMERLY HACKING + SETOM QTUNT1 + JRST T3UDE4 ] +];T300P +IFE DC10P, SETOM QSKT1(Q) ;FREE DRIVE FORMERLY HACKING +IFN DC10P,[ + MOVE TT,QTRAN(Q) + SETOM QSKT1(TT) +] + SETOM QSDU + SETOM QTUNT +IFN T300P,T3UDE4: + MOVE E,QSGL(C) + MOVE Q,QDSKN(C) + SETZM QERRS(C) + JRST QINT5 + +QIDRCH: MOVE TT,QDIRP(C) ;CHNL IN C PNTR TO QSNUD IN J LOAD NEXT CHR INTO A + AOS QDIRP(C) ;ALSO RET BYTE PNTR IN TT + IDIVI TT,UFDBPW + HLL TT,QBTBL(I) + HRRZ I,QSNLCN(J) + ADDI TT,UDDESC(I) + LDB A,TT + POPJ P, + +QMPDCH: MOVE TT,QDIRP(A) ;CHNL IN A PNTR TO QSNUD IN H LOADS NEXT CHR IN R + AOS QDIRP(A) ;USED AT M.P. LEVEL +QMPDC1: IDIVI TT,UFDBPW ;ALSO RETN BYTE PNTR IN TT + HLL TT,QBTBL(I) + HRRZ I,QSNLCN(H) + ADDI TT,UDDESC(I) + LDB R,TT + POPJ P, + +;REACHED EOF ON READ +QEOF: SOS QDIRP(C) ;AVOID GC UNHAPPINESS + MOVSI I,%QAEFR + IORM I,QSRAC(C) + HLLZS QSRAC(C) .SEE %QMIDL ;IDLE THE CHANNEL + AOS QSBFS(C) ;TO UNHANG M.P. WHICH IS WAITING FOR BUF TO APPEAR + JRST QINT2C + +QINT4C: +; 8/20/90 DM "funny" bit no longer supported. Allows for huge RP07 block +; numbers. Commenting this out means that %QAFNY can no longer get set +; under any circumstances, so I am leaving a certain amount of dead code in +; other places. +; IFN DMDSK,[ +; MOVSI E,%QAFNY +; ANDCAM E,QSRAC(C) +; TRZE A,20 ; FUNNY FILE BLOCK +; IORM E,QSRAC(C); INDICATE SO +; ] + MOVEI E,0 + DPB A,[140500,,E] + PUSHJ P,QIDRCH + DPB A,[060600,,E] + PUSHJ P,QIDRCH + DPB A,[0600,,E] + MOVEM E,QSLGL(C) + JRST QINT4G + +;DECODE UNBYTE SPEC IN D. +;RETURNS BYTE SIZE IN D, NUMBER OF UNUSED BYTES IN LAST WORD IN E. +QBDCD: TRZE D,400 + JRST [ IDIVI D,100 ? POPJ P, ] + TRZE D,200 + JRST [ IDIVI D,20 ? POPJ P, ] + SUBI D,44 + JUMPGE D,[ IDIVI D,4 ? POPJ P, ] + MOVNS D + SETZ E, + POPJ P, + +;ENCODE BYTE SIZE IN Q AND RESIDUE IN R INTO UNBYTE SPEC IN RH(Q) +QBENC: CAIG Q,3 + JRST [ IMULI Q,100 ? ADDI Q,400(R) ? POPJ P, ] + CAIG Q,7 + JRST [ IMULI Q,20 ? ADDI Q,200(R) ? POPJ P, ] + CAIG Q,18. + JRST [ IMULI Q,4 ? ADDI Q,44(R) ? POPJ P, ] + MOVNI Q,-44(Q) + POPJ P, + +QINT3: SKIPL DWUSR + JRST QINT3X ;DIR CHNL IN USE +IFN T300P,[ + SKIPGE QSDU ;DON'T GET PAST HERE UNLESS BOTH CONTROLLERS ARE IDLE + SKIPL QSDU1 + JRST QINT3X +];T300P + AOSL QDWFAR + JRST [ MOVNI H,10. + MOVEM H,QDWFAR + JRST .+3 ] + SKIPG QACTTM ;LAST ACTIVITY TOO RECENT + JRST QUDW + SKIPGE H,QMDRO + JRST QTDW + MOVE J,QACTB + TDNN J,H + JRST QTDW + MOVSI Q,-NQS +QMDW: SKIPGE QACT(Q) + JRST QMDWA ;UNIT NOT ACTIVE + MOVE J,DCHBT(Q) + TDNN J,QMDRO + JRST QMDWA + HRLI Q,(SETZ) ;INDICATE MFD WRITE IN PROGRESS + MOVEM Q,QDWIP + HRRZM Q,DWSKN + MOVEI TT,%QMMDW + HRRZM TT,QSRAC+NQCHN + MOVSI TT,(SETZ) + IORB TT,QMDRO + MOVE C,MDCHK(TT) + CAME C,[SIXBIT /M.F.D./] + BUG HALT,[MFD CLOBBERED] + HRRZ C,Q + CAMN C,MDSK + AOSA C,QAMDNO + MOVE C,QAMDNO + MOVEM C,MDNUM(TT) + SETZM DWUSR + MOVEI TT,MFDBLK + MOVEM TT,QSGL+NQCHN + HRRZ TT,QMDRO + LSH TT,-10. + MOVEM TT,QSCABN+NQCHN + JRST QINT1 + +QMDWA: AOBJN Q,QMDW +QTDW: SKIPG QACTTM + JRST QUDW + MOVSI Q,-NQS +QTDW1: SKIPGE QACT(Q) + JRST QTDWA + MOVE J,DCHBT(Q) + SKIPL QTUTO(Q) + TDNN J,QTUTO(Q) + JRST QTDWA + MOVSI H,240000 + TDNE H,QTUTO(Q) + JRST QTDWA1 + MOVE TT,TIME ;DON'T WRITE TUTS TOO OFTEN + SUB TT,QTWRTM(Q) ;BECAUSE THE TUT IS LOCKED WHILE IT'S BEING WRITTEN + CAIGE TT,100. + JRST QTDWA + ADDM TT,QTWRTM(Q) + HRLI Q,200000 + MOVEM Q,QDWIP + HRRZM Q,DWSKN + MOVEI TT,%QMTTW + HRRZM TT,QSRAC+NQCHN + MOVSI TT,(SETZ) + IORB TT,QTUTO(Q) + MOVE H,QPKNM(Q) ;VERIFY THAT TUT IS NOT BEING CLOBBERED + MOVE C,QPKID(Q) + CAMN H,QPAKID(TT) + CAME C,QPKNUM(TT) + BUG HALT,[TUT ],DEC,Q,[CLOBBERED] + SETZM DWUSR + MOVEI TT,MFDBLK ;INITIATE WRITING OF FIRST BLOCK OF TUT + SUB TT,NTBL(Q) + MOVEM TT,QSGL+NQCHN + LDB TT,[121000,,QTUTO(Q)] + MOVEM TT,QSCABN+NQCHN + JRST QINT1 + +QTDWA1: ANDCAM J,QTUTO(Q) +QTDWA: AOBJN Q,QTDW1 +QUDW: MOVSI C,-QNUD +QDW4A: MOVE J,QACTB ;BITS CORRESP TO ACTIVE DISKS +QDW4: SKIPE TT,QSNUD(C) + SKIPGE QSNLCN(C) + JRST QDW3 ;SLOT VACANT OR LOCKED + TDNE J,QSNLCN(C) + JRST QUDW1 ;NEEDS TO BE WRITTEN ON SOME UNIT +QDW3: AOBJN C,QDW4A +QINT3X: ;HERE IF DISK GOING IDLE. CLEAR DONE FLAG. + ;IN 2-CONTROLLER CASE, MAKE SURE WE ONLY DO IT TO THE RIGHT CONTROLLER. +IFN T300P,[ + SKIPL QSDU + JRST DSKEX ;STUFF NEEDS TO BE DONE BUT CANT NOW +] ;T300P +IFN DC10P, CONO DC0,DCCLR+DCIENB+DSKCHN +IFN RP10P, CONO DPC,177710+DSKCHN ;MUST CLEAR "DONE" +IFN RH10P, CONO DSK,%HOCLR+%HOATN+%HORAE+DSKCHN +IFN RH11P, ;; RH11 doesn't need this? + JRST DSKEX ;STUFF NEEDS TO BE DONE BUT CANT NOW + +QUDW1: MOVSI J,%QUDWM ;WRITE RIGHT AWAY IF %QUDWM IS ON + TDNN J,QSNLCN(C) + SKIPE QSFBT(C) ;OR DISK BLOCKS (AND CORE) WAITING TO BE FREED + JRST QUDW6 + SKIPG QACTTM ; ACTIVITY TOO RECENT + SKIPN QSNNR(C) ; THEN ONLY WRITE IF NOTHING POINTING TO DIRECTORY + SKIPA + JRST QDW3 + MOVSI Q,-NQS +QUDW4: SKIPGE QACT(Q) + JRST QUDW3 + MOVE J,DCHBT(Q) + TDNE J,QSNLCN(C) + JRST QUDW2 +QUDW3: AOBJN Q,QUDW4 + JRST QDW3 + +QUDW6: ANDCAM J,QSNLCN(C) ;TURN OFF %QUDWM + MOVE Q,MDSK ;AND WRITE ON MASTER DISK (ASSUME MDSK IS ACTIVE AND BIT IN QSNLCN IS SET) + +QUDW2: MOVE I,QMDRO + TLNE I,40000 ;IS THIS CODE OBSOLETE? LEFT FROM DAYS OF 1 MFD PER DRIVE? + JRST QUDW2B ;MASTER DIR NOT IN + HRRZS Q + CAMN Q,MDSK ;SKIP IF NOT WRITING ON MASTER DISK + PUSHJ P,QDIRCK ;BLESS THIS UFD!!! + MOVSI TT,(SETZ) + IORB TT,QSNLCN(C) ;LOCK USER DIRECTORY + MOVEI J,%QMUDW + HRRZM J,QSRAC+NQCHN + MOVE A,1(TT) ;NAME AREA PTR + MOVE J,QSNUD(C) + CAMN J,UDNAME(TT) ;MAKE SURE NOT ABOUT TO WRITE BAD DIRECTORY + CAILE A,2000 + JSP TT,QUDCLB + SUBI A,11. + IMULI A,6 + SKIPL J,(TT) + CAMLE J,A ;FS PTR BAD? + JSP TT,QUDCLB + CLEARM DWUSR + MOVEM Q,DWSKN + MOVE TT,QSNMI(C) + MOVEM TT,QSGL+NQCHN + HRRZ TT,QSNLCN(C) + LSH TT,-10. + MOVEM TT,QSCABN+NQCHN + HRRZM C,QDWIP + CLEARM QERRS+NQCHN + JRST QINT1 + +QUDW2B: ANDCAM J,QSNLCN(C) ;CLEAR BIT + GO AWAY + JRST QUDW3 + +;GENERALLY GET HERE BY JSP TT, +QUDCLB: BUG HALT,[DIR ],OCT,C,SIXBIT,QSNUD(C),[CLOBBERED] + +QDIRCK: PUSH P,TT ;CHECKS FILES FOR REASONABLE DESCRIPTORS - + ; PRECEDING BYTE =0, FIRST BYTE NOT=0 + HRRZ A,QSNLCN(C) + MOVEI B,1777(A) ;END OF NAMES + ADD A,1(A) ;BEGIN NAMES +QDIRC1: CAMG B,A + JRST POPTTJ ;DONE + SKIPN (A) + JRST QDIRC2 ;0 NAME=NO FILE + LDB TT,[1500,,UNRNDM(A)] ;DESC PTR + SOS TT ;TRICK - IF DESC PTR = 0 LDB BELOW GETS 0 BECAUSE P FIELD = 44 + IDIVI TT,6 + HLL TT,SBTBL(I) ;BYTE POINTER + ADDI TT,UDDESC-1777(B) + LDB I,TT + JUMPN I,QUDCLB + ILDB I,TT + JUMPE I,QUDCLB +QDIRC2: ADDI A,LUNBLK + JRST QDIRC1 + +IFN RP10P,[ +QPOSR: CAIL E,MBLKS + BUG ;TOO BIG EVEN FOR RP03 +IFN DMDSK,[ + IMULI E,SECBLK + IDIVI E,NSECS + SETZM D + DPB TT,[DSECT+D] + IDIVI E,NHEDS + DPB TT,[DSURF+D] + DPB E,[DCYL+D] + MOVEM E,QSPPS(Q) + LSH E,-8 + DPB E,[DCYLXB+D] + DPB Q,[DUNFLD+D] +] +IFE DMDSK,[ + MOVEI D,0 + IDIVI E,NBLKSC + DPB E,[DCYL+D] + MOVEM E,QSPPS(Q) + LSH E,-8 + DPB E,[DCYLXB+D] + MOVE E,TT + IMULI E,NSSECS + IDIVI E,NHSECS + DPB E,[DSURF+D] + DPB TT,[DSECT+D] + DPB Q,[DUNFLD+D] +] + MOVE E,D + POPJ P, +] +IFN RH10P+RH11P,[ +IFE DMDSK, .ERR CHANGE QPOSR FOR 9-SECTOR BLOCKS! +QPOSR: CAIL E,NBLKS + BUG + IDIVI E,NBLKSC + HRLZ D,E ;CYLINDER IN LH + MOVEM E,QSPPS(Q) + MOVE E,TT + IMULI E,SECBLK + IDIVI E,NSECS + LSH E,8 + IOR E,D ;SURFACE IN 1.9-2.4 + IOR E,TT ;SECTOR IN 1.1-1.5 + POPJ P, +] ;RH10P+RH11P + +IFN DC10P,[ +QPOSR: CAIL E,NBLKS + BUG + IDIVI E,NSECS + MOVSI D,(DUNENB) + DPB TT,[DSECT+D] + IDIVI E,NHEDS + DPB TT,[DSURF+D] + SKIPGE TT,QTRAN(Q) + ADDI E,NCYLS+XCYLS + DPB E,[DCYL+D] + MOVEM E,QSPPS(TT) + MOVE E,D + DPB TT,[DUNFLD+E] + DPB TT,[DUNFLD+QCHPRG] + SKIPGE TT,QPKID(Q) + JRST QPOSRI + DPB TT,[DPKID+E] + POPJ P, + +QPOSRI: MOVE TT,QTRAN(Q) ;NEED PACK ID BEFORE PROCEEDING + DPB TT,[DUNFLD+GPKID] + SETOM QSKT1(TT) + MOVEI A,TUTCYL + SKIPGE QTRAN(Q) + ADDI A,NCYLS+XCYLS + DPB A,[DCYL+GPKID] + MOVEM A,QPOS(TT) ;WILL SEEK TO HERE AUTOMATICALLY + MOVEM A,QPOSGL(TT) + DATAO DC0,[DJMP GPKID] + MOVEM Q,QSDU + SETOM PKIDM + JRST QINTX + +QSPKID: CONSZ DC1,1777 + BUG ;ERRORS + LDB TT,[DPKID+RPKID] + MOVEM TT,QPKID(Q) + SETOM QSDU + JRST QINT1 +] + +SUBTTL DISK IOT ROUTINES + +OVHMTR UUO ;MORE RANDOM UUOS + +;BECAUSE .ACCESS MERELY DROPS ITS ARG IN A VARIABLE AND SETS %QAACC, +;ALL IOT ROUTINES MUST TEST %QAACC AND DO THE REAL WORK OF CHANGING +;THE ACCESS POINTER IF NECESSARY. + +QBO: MOVEI T,BLKT + JRST QUO1 + + SKIPA T,[SIOKT] +QUIO: +QUAO: MOVEI T,CHRKT +QUO1: PUSH P,T + PUSH P,TT + PUSH P,D + MOVE T,QSRAC(A) + TLNE T,%QAACC+%QALNK + PUSHJ P,QBWRA1 ;RANDOM ACCESS MODE HACK + POP P,D + POP P,TT + MOVE E,QSBYTE(A) + JSP B,CPOPJ ;TRANSFER TO CHRKT, SIOKT, OR BLKT +QBOV: SETZ QSMPRP(A) + QSMPRC(A) + QSBWG + SETZ QSBWW + JRST QOCL + TRNA + +QBI: MOVEI T,BLKT + JRST QUI1 + + SKIPA T,[SIOKT] +QUII: +QUAI: MOVEI T,CHRKTI +QUI1: PUSH P,T + PUSH P,TT + MOVE T,QSRAC(A) + TLNE T,%QAACC+%QALNK + PUSHJ P,QBRRA1 + POP P,TT + MOVE E,QSBYTE(A) + JSP B,CPOPJ ;TRANSFER TO CHRKTI, SIOKT, OR BLKT +QBIV: QSMPRP(A) + QSMPRC(A) + QSBGB + QSBRB + JRST QICL + SKIPG QSBFS(A) + +QBWRA1: TLNE T,%QALNK + JRST IOCR10 + LDB T,[$QAMOD,,QSRAC(A)] ;SET RANDOM ACCESS PNTRS ON WRITE + SOJN T,QBWRA2 ;IN ORDINARY WRITE MODE + SKIPGE QSCRW(A) ;WAIT FOR CHANNEL TO BECOME IDLE OR HANG UP IN READ + PUSHJ P,UFLS ; WAITING FOR %QAACC TO TURN OFF + SKIPL QSGL(A) + PUSHJ P,UFLS + SKIPGE QSMDN(A) + JRST QBWRA2 + MOVE T,QRADAD(A) ;DESIRED ADDRESS + SUB T,QFBLNO(A) ;ACTUAL ADDRESS OF BEG OF CURRENT BUFFER + JUMPL T,QBWRA2 ;XFER ON BEFORE CURRENT BLOCK + MOVE Q,T + SUB T,QMPBSZ(A) ;SIZE OF CURRENT BUFFER IN BYTES + JUMPL T,QBWRA3 ;SAME BLOCK AS NOW +QBWRA2: PUSH P,R + PUSH P,I + PUSH P,C + PUSHJ P,QSOCL5 ;CLEAR ANY CURRENT BUFFERS ETC + PUSHJ P,QUDULK + MOVE Q,QRADAD(A) + PUSHJ P,QFNTR ;LOCKS DIR IF SKIPS + JRST QBWRA4 ;OFF END OF FILE +QBWRA5: PUSHJ P,QUDULK +QBWRA9: POP P,C + POP P,I + POP P,R + CLEARM QSCRW(A) ;SWITCH TO WRITE OVER MODE + MOVSI Q,%QAMPU+%QAMWO ;SET UPDATE ADR AND WRITE OVER + IORM Q,QSRAC(A) + CLEARM QSMPRC(A) + MOVSI Q,%QAEFR+%QAEFW+%QAACC ;CLEAR EOF, WRITE EOF, AND ACCESS FLAGS + ANDCAM Q,QSRAC(A) + MOVEI Q,%QMRD1 ;AND READ IN THE CURRENT BLOCK + HRRM Q,QSRAC(A) + POPJ P, + +QBWRA4: JUMPE Q,QBWRA0 + CAME J,Q ;MIGHT BE ADDING TO END OF FULL BLOCK + JRST IOCER2 + JRST QBWRA9 + +QBWRA0: PUSHJ P,QLWO ;OFF END OF FILE AND WAS ACCESSING WD 0 + MOVSI C,%QAACC ;SO SWITCH TO NORMAL WRITE MODE AND + ANDCAM C,QSRAC(A) ;TURN OFF RANDOM ACCESS BIT + POP P,C + POP P,I + POP P,R + POPJ P, + +QBWRA3: SKIPGE TT,QSMDN(A) + BUG ;NO BUFFER REALLY ACTIVE AT M.P. + MOVSI J,%QAWOV + TDNN J,QSRAC(A) + JRST QBWRA7 + ANDCAM J,QSRAC(A) ;WAS WRITING IN LAST BLK PAST EOF, + MOVN D,QSMPRC(A) ; UPDATE ACTIVE BYTE COUNT + ADDM D,QMPBSZ(A) ;DECREASE SIZE OF BUFFER TO AMT ACTUALLY WRITTEN +QBWRA7: LSH TT,10. ;ADDRESS OF BUFFER + MOVE T,Q ;SAVE RELATIVE BYTE ADDR WITHIN BUFFER + IDIVI Q,@QSBYTE(A) ;Q = WDS, J = BYTES + ADD TT,Q ;ADDRESS OF DESIRED WORD + HLL TT,QSBYTE(A) ;BYTE POINTER TO FIRST BYTE IN THAT WORD + JUMPE J,.+3 ;ADVANCE TO APPROPRIATE BYTE + IBP TT + SOJG J,.-1 + MOVEM TT,QSMPRP(A) + SUB T,QMPBSZ(A) ;MINUS # BYTES LEFT IN BLOCK + MOVNM T,QSMPRC(A) +QBRRA4: MOVSI Q,%QAACC + ANDCAM Q,QSRAC(A) + POPJ P, + +QSKFRC: MOVN B,QSMPRC(A) + ADD B,QMPBSZ(A) ;NUMBER OF BYTES WRITTEN IN BLOCK + MOVE C,QSRAC(A) + TLNE C,%QAMWO + TLNE C,%QAWOV + JRST [MOVEM B,QMPBSZ(A) ;IS LAST BLOCK, CHANGE LENGTH + PUSHJ P,QOCLPD ;AND PAD IT (GUARANTEED NO-OP IF WORD MODE CHNL) + JRST .+1 ] + SETZM QSMPRC(A) ;BUFFER WILL BE DISPOSED OF + MOVSI E,%QUDWM + SKIPGE QSMDN(A) + SETZB B,E ;NO BUFFER AFTER ALL + ADD B,QFBLNO(A) ;CURRENT POSITION IN FILE + MOVSI C,%QAACC + TDNN C,QSRAC(A) + MOVEM B,QRADAD(A) ;ACCESS BACK ON NEXT IOT + IORB C,QSRAC(A) + PUSHJ P,[TLNE C,%QAWOV ;WRITE OUT THE BUFFER + JUMPN E,QSBWO2 + JRST QSBWW ] + SKIPE QMPTC(A) + MOVSI E,%QUDWM + PUSHJ P,QOCL2 ;STORE QMPTC IF NECESSARY + IORM E,QSNLCN(H) ;WRITE OUT DIR FAST IF CHANGED + PUSHJ P,QUDULK + JRST POPJ1 + +;.CALL FINISH ON DISK OUTPUT CHANNEL +QSKFIN: HRRZ T,QSRAC(A) + CAIN T,%QMWOV ;IF WRITE-OVER MODE + JRST [ SKIPE QSCRW(A) ;THEN WAIT FOR IT TO SWITCH TO READ MODE + PUSHJ P,UFLS + JRST QSKFIN ] + CAIN T,%QMWRT ;IF WRITE MODE + JRST [ SKIPE QSBFS(A) ;THEN WAIT FOR ALL BUFFERS TO GET WRITTEN + PUSHJ P,UFLS + JRST .+1 ] + MOVE H,QUDPR(A) + MOVE T,MDSK ;HAS THE DIR BEEN CHANGED AND NOT WRITTEN + MOVE T,DCHBT(T) ;YET TO THE MASTER DISK? + TDNN T,QSNLCN(H) + JRST POPJ1 + MOVSI TT,%QUDWM ;YES, WRITE IT OUT IMMEDIATELY + IORM TT,QSNLCN(H) ;AND DON'T RETURN UNTIL IT IS WRITTEN + TDNE T,QSNLCN(H) + PUSHJ P,UFLS + JRST POPJ1 + +QBRRA1: TLNE T,%QALNK + JRST IOCR10 + SKIPGE QSMDN(A) + JRST QBRRA2 ;NO MAIN PRGM BUFFER + MOVE T,QRADAD(A) + SUB T,QFBLNO(A) + JUMPL T,QBRRA2 + MOVE Q,T + SUB T,QMPBSZ(A) ;SIZE OF CURRENT BUFFER + JUMPL T,QBRRA3 ;SAME BLOCK AS NOW +QBRRA2: PUSH P,R + PUSH P,I + PUSH P,C + PUSHJ P,QICLW1 ;STOP THE CHANNEL AND FLUSH CURRENT BUFFERS + MOVE A,D + CLEARM QSBFS(A) ;FLUSH POSSIBLE EXTRA AOSES WHEN PI HIT EOF + MOVE Q,QRADAD(A) + PUSHJ P,QFNTR + JRST QBRRA5 ;OFF END OF FILE (DIR ALREADY UNLOCKED) + POP P,C + POP P,I + POP P,R + CLEARM QSMPRC(A) + MOVSI Q,%QAMPU + IORM Q,QSRAC(A) ;SET FLAG TO SET QSMPRP AND QSMPRC ON NEXT BUFFER LOAD + MOVSI Q,%QAEFR+%QAACC ;CLEAR EOF AND .ACCESS FLAGS + ANDCAM Q,QSRAC(A) + MOVEI Q,%QMRD ;START READING AGAIN + HRRM Q,QSRAC(A) + JRST QUDULK + +QBRRA5: POP P,C + POP P,I + POP P,R + CAME J,Q + JRST IOCER2 ;ACCESS OFF END OF FILE IS ERROR + MOVSI TT,%QAEFR ;BUT ACCESS TO EXACTLY EOF IS OK + IORM TT,QSRAC(A) ;IMITATES WHAT QEOF DOES + AOS QSBFS(A) + SETZM QSMPRC(A) ;AND READS ZERO WORDS + JRST QBRRA4 + +QBRRA3: SKIPGE TT,QSMDN(A) + JRST QBRRA2 + JRST QBWRA7 + +;BLKT-SIOKT-CHRKT GET BUFFER ROUTINE FOR WRITE-OVER MODE. +QWOG1: SKIPGE QSCRW(A) ;FETCH BLOCK WRITEOVER MODE + JRST QWOG2 ;STILL WRITING PREVIOUS ONE, WAIT + MOVEI Q,%QMRD1 ;SWITCH INTO READ MODE + SKIPG QSBFS(A) ;IF A BUFFER HAS TO BE READ + HRRM Q,QSRAC(A) + SKIPG QSBFS(A) + PUSHJ P,UFLS + POP P,A +;BLKT-SIOKT-CHRKT GET-BUFFER ROUTINE FOR DISK INPUT. +QSBGB: MOVSI Q,%QAPAR + TDNE Q,QSRAC(A) + JRST QSBGB2 + CONO PI,UTCOFF + HRRZ Q,QBFP(A) + JUMPE Q,[MOVSI J,%QAEFR ;SAID TO BE BUFFERS, BUT NONE THERE + TDNN J,QSRAC(A) + BUG ;SHOULDN'T HAPPEN EXCEPT AT EOF + JRST QSBGB5 ] + LDB J,[MLO,,MEMBLT(Q)] + HRRM J,QBFP(A) + SKIPN J + SETZM QBFP(A) ;LAST BLOCK, LIST NOW EMPTY + HRRZ J,MEMPNT(Q) ;GET SIZE OF BUFFER IN BYTES + MOVEM J,QMPBSZ(A) + LDB TT,[$QAMOD,,QSRAC(A)] + SKIPN TT ;DONT SOS IF IN WRITE OVER MODE + SOS QSBFS(A) +QSBWG4: MOVE TT,Q + LSH TT,10. ;RETURN ADDR OF BUFFER + MOVEM Q,QSMDN(A) + CONO PI,UTCON + HLL TT,QSBYTE(A) + MOVSI Q,%QAMPU + TDNN Q,QSRAC(A) + JRST SIOBG2 + MOVE Q,QRADAD(A) ;DIDDLE PNTRS TO TAKE CARE OF RANDOM ACCESS WITHIN BLOCK + SUB Q,QFBLNO(A) ;DESIRED OFFSET WITHIN BLOCK + SUB J,Q + JUMPL J,IOCER2 ;OFF END OF FILE + JUMPL Q,IOCER2 ;OFF FRONT OF FILE (NEGATIVE .ACCESS PNTR) + PUSH P,J + IDIVI Q,@QSBYTE(A) + ADD TT,Q ;ADJUST BYTE POINTER + JUMPE J,.+3 + IBP TT + SOJG J,.-1 + POP P,J + MOVSI Q,%QAMPU ;NOW IS SAFE TO TURN OFF FLAG + ANDCAM Q,QSRAC(A) + JRST SIOBG2 + +;GET-BUFFER DETECTED EOF ON INPUT OR WRITE-OVER. +QSBGB5: CONO PI,UTCON + MOVE Q,QSRAC(A) + TLNE Q,%QALNK + JRST IOCR10 + LDB Q,[$QAMOD,,QSRAC(A)] + SOJN Q,POPJ2 ;ON INPUT, SKIP TWICE TO SIGNAL EOF. + PUSHJ P,QLWO ;LEAVE WRITE OVER MODE + JRST QSBWG ;START NORMAL WRITE + +QWOG2: SKIPGE QSCRW(A) ;WAIT FOR WRITE TO FINISH + PUSHJ P,UFLS + JRST POPAJ ;NOW RECYCLE AND WAIT FOR READ + +;LEAVE WRITE OVER MODE +QLWO: MOVE H,QUDPR(A) + PUSHJ P,QUDLK + CONO PI,UTCOFF + SETZM QBFP(A) ;WRITEOVER MODE EXTEND FILE (SWITCH TO NORMAL MODE) + CLEARM QSBFS(A) + SETOM QSCRW(A) + MOVE Q,QSLGL(A) + HRRZM Q,QMPTN(A) ;STORE BASE TRACK + MOVSI Q,%QAEFR+%QAMWO ;CLEAR EOF AND WRITEOVER + ANDCAM Q,QSRAC(A) + MOVEI Q,%QMWRT ;NORMAL WRITE MODE + HRRM Q,QSRAC(A) + CLEARM QMPTC(A) ;TRACK COUNT FOR TAKE N + SETOM QMTTR(A) ;NO TRACK RESERVED + SETOM QMFTP(A) ;GET NEW DECADE RESERVATION + CONO PI,UTCON + MOVE TT,QDIRP(A) ;SEE IF GARBAGE COLLECTION NEEDED + PUSH P,R + PUSH P,I + PUSHJ P,QMPDC1 ;CONV CHAR ADR TO BYTE PNTR (AND LDB IN R) + POP P,I + SKIPE R + BUG + MOVE R,QDIRP(A) + ADDI R,NXLBYT+2 + CAMGE R,@QSNLCN(H) + JRST QLWO1 ;DON'T NEED TO EXPAND F.S. + MOVEI R,LUNBLK(TT) + MOVE Q,QSNLCN(H) + SUBI R,(Q) + CAML R,UDNAMP(Q) + JRST QSBWG7 ;DON'T HAVE ROOM. GC + MOVEI R,3*6 ;HAVE ROOM + ADDM R,(Q) +QLWO1: +REPEAT NXLBYT+2,[ + ILDB R,TT + JUMPN R,QSBWG7 +] + JRST QSBWG8 ;OK + +QSBWG7: MOVSI R,%QAFUL ;NO ROOM, GC BEFORE COMMITTING NEXT TRACK + IORM R,QSRAC(A) +QSBWG8: POP P,R + JRST QUDULK + +QSBGB2: ANDCAM Q,QSRAC(A) ;DISK READ ERROR + JRST IOCER3 ;TELL USER + +;DISK OUTPUT GET-BUFFER ROUTINE. PRESERVES D FOR BENEFIT OF PDUMP. +QSBWG: MOVE Q,QSRAC(A) + TLNE Q,%QALNK+%QAACC ;DON'T WRITE TO LINK, DON'T LET PDUMP GET + JRST IOCR10 ; FAKED OUT BY USE FORCE OR ACCESS + PUSH P,A + TLNE Q,%QAMWO + JRST QWOG1 ;JUMP IF WRITE OVER MODE + HRRZ Q,QBFP(A) ;NORMAL MODE + JUMPE Q,QSBWG1 ;CAN ALWAYS HAVE ONE BUFFER + MOVE Q,QWBUFS + CAML Q,QWBFMX + JRST POPAJ ;TOO MANY WRITE BUFFERS QUEUED +QSBWG1: PUSHJ P,QSTWG + PUSHJ P,TCALL + JRST IOMQ + JRST QSBWG5 ;MEM FROZE OR NOT AVAILABLE + MOVE Q,(P) ;DISK CHNL # + DPB Q,[MNUMB,,MEMBLT(A)] + MOVEI Q,MU23B + DPB Q,[MUR,,MEMBLT(A)] + MOVE Q,A + POP P,A + AOS QSBFS(A) + AOS QWBUFS + HRRZ J,QSBYTE(A) + IMULI J,2000 + MOVEM J,QMPBSZ(A) ;FRESH BLOCK SIZE + JRST QSBWG4 + +QSTWG: MOVSI Q,%QAFUL + TDNE Q,QSRAC(A) ;ROUTINE TO COMMIT A TRACK + JRST QSTWG1 ;DIR FULL, NEED GC BEFORE GROWING FILE + MOVE H,QUDPR(A) ;IF THIS DIRECTORY HAS AN ALLOCATION + MOVE Q,QSNLCN(H) ; ENFORCE IT +IFN QRSRVP,[ + HRRZ J,UDALLO(Q) + JUMPE J,QSTWG0 ;NO ALLOCATION + HRRZ H,UDBLKS(Q) ;GET BLOCKS USED + CAML H,J + JRST IOCR13 ;HAS ALLOCATION AND USER IS TRYING TO EXCEED IT +] +QSTWG0: MOVE J,QDSKN(A) + SOSL QSFT(J) ;RESERVE A TRACK + POPJ P, + AOS QSFT(J) ;DISK FULL, GIVE BACK THE TRACK + SKIPE QFBTS ;WAIT FOR ANY PENDING FILE DELETIONS + PUSHJ P,UFLS ; TO COMPLETE AND FREE THEIR BLOCKS + SOSL QSFT(J) ;GOT SPACE NOW? + POPJ P, + AOS QSFT(J) ;NO, GIVE UP AND ERR OUT + JRST IOCER9 + +QSTWG1: MOVE H,QUDPR(A) + PUSHJ P,QUDLK + PUSHJ P,QGC + JRST IOCR12 ;DIR FULL + PUSHJ P,QUDULK + ANDCAM Q,QSRAC(A) .SEE %QAFUL + JRST QSTWG + +QSBWG5: POP P,A ;GET BACK QSK CHANNEL # + MOVE J,QDSKN(A) + AOS QSFT(J) ;NO MEMORY; GIVE EVERYTHING BACK + POPJ P, + +;DISK OUTPUT RELEASE-BUFFER ROUTINE FOR BLKT, SIOKT, CHRKT. +QSBWW: SKIPGE QSMDN(A) ;WRITE BUFFER FROM MN PROG TO CHAIN FOR PI + POPJ P, ;NO WRITE BUFFER ACTIVE + LDB TT,[$QAMOD,,QSRAC(A)] + SOJE TT,QSBWO1 ;WRITE OVER MODE + SKIPL D,QMTTR(A) + JRST QTG1 ;TRACK ALREADY RESERVED + PUSH P,I + MOVE I,QDSKN(A) + PUSHJ P,QGTRK ;GET A TRACK + POP P,I + MOVEM D,QMTTR(A) +QTG1: MOVE H,QUDPR(A) ;TRACK IN D + PUSHJ P,QUDLK + MOVE TT,QSNLCN(H) + AOS UDBLKS(TT) + MOVE TT,QMPTN(A) ;GET PREVIOUS TRACK# + CAIN D,1(TT) + JRST QTG2 ;THIS TRACK IS CONSECUTIVE + SKIPN QMPTC(A) ;THIS TRACK NOT CONSEC CHECK COUNT OF PREV CONSEC BLOCKS + JRST QTG3 + PUSH P,D ;NON-ZERO SO STORE IN USER DIRECTORY + MOVE D,QMPTC(A) + CLEARM QMPTC(A) + PUSHJ P,QUDS + POP P,D +QTG3: MOVE J,QMTTR(A) ;DESCRIPTOR WILL BE STORED + MOVEM J,QMPTN(A) + SUB D,QMPTN(A) ;CAN TRACK BE SKIPPED TO? + SOJL D,QTG4 ;CAN'T BE SKIPPED TO (NOTE QMPTN HAS NOT BEEN AOS'D) + CAILE D,UDWPH-UDTKMX-1 + JRST QTG4 ;ALSO NO + ADDI D,UDTKMX ;NEXT BLOCK WITHIN N + PUSHJ P,QUDS ;STORE APPROPRIATE SKIP +QTG5A: +QTG5: MOVE Q,QSMDN(A) ;CORE BLOCK NUM BEING WRITTEN + MOVE D,QMPTN(A) ;TRACK NUM OF BLOCK ADDING TO FILE + HRLZM D,MEMPNT(Q) ;STORE TRACK NUM + SETOM QMTTR(A) ;INDICATE TRACK USED + MOVE J,QMPBSZ(A) ;LENGTH OF THIS BLOCK + ADDM J,QFBLNO(A) ;INCR BYTE ADR OF START OF CURRENT BLOCK IN FILE + HRRM J,MEMPNT(Q) ;SAVE BYTE COUNT + PUSH P,R + IDIVI J,@QSBYTE(A) ;CONVERT TO WORD COUNT + JUMPE R,QTG7 ;EXACT MULTIPLE OF WORD + AOS J + MOVNS R + ADDI R,@QSBYTE(A) ;# BYTES RESIDUE IN LAST WORD +QTG7: DPB J,[MWC,,MEMBLT(Q)] ;STORE ACTIVE WORD COUNT + MOVE D,QSRAC(A) + LDB TT,[$QAMOD,,QSRAC(A)] + TLNN D,%QALBK ;LAST BLOCK OF WRITE OVER POSSIBLY + SOJE TT,QTG6 ;WRITEOVER MODE AND NOT LAST BLOCK, DONT UPDATE LAST BLOCK WORD COUNT + MOVE H,QUDPR(A) ;SET UP DIRECTORY CHANNEL + MOVE D,QUDFPR(A) + ADD D,QSNLCN(H) + DPB J,[UNWRDC+UNRNDM(D)] ;SET WORD COUNT OF LAST BLOCK + LDB Q,[QSBSIZ(A)] + PUSHJ P,QBENC ;ENCODE BYTE CRUFT + DPB Q,[UNBYTE+UNREF(D)] + MOVE J,QACTB + IORM J,QSNLCN(H) +QTG6: POP P,R + PUSHJ P,QUDULK + MOVE Q,QSMDN(A) + MOVEI J,.BM MLO + ANDCAM J,MEMBLT(Q) ;SET END OF LIST INDICATOR IN MEMORY BLOCK + CONO PI,UTCOFF + HLRZ J,QBFP(A) ;STORE MEMORY BLOCK IN OUTPUT LIST + JUMPE J,QSBWW1 + DPB Q,[MLO,,MEMBLT(J)] +QSBWW2: HRLM Q,QBFP(A) + CONO PI,UTCON + SETOM QSMDN(A) ;MN PROG BUFFER NOW WRITTEN + JRST QSTRTR ;START ACTION IF 2311 IDLE AND RETURN + +QSBWO1: MOVE Q,QSRAC(A) ;PUT BUFFER IN WRITE-OVER MODE + TLNE Q,%QALBK ;IF NOT HACKING LAST BLOCK + TLNE Q,%QAEFW ;OR HACKING CLOSE + JRST QSBWO2 ;THEN JUST WRITE IT + HRRZ D,QSBYTE(A) + IMULI D,2000 + SUB D,QMPBSZ(A) + JUMPE D,QSBWO2 ;BLOCK REALLY FULL + TLNE Q,%QAMPU ;DID WE IOCER2 AT QSBWG4? + JRST IOCER2 ;YES, QSMPRP NOT SET UP, DON'T WRITE ANYTHING + MOVEM D,QSMPRC(A) ;LAST BLOCK NOT REALLY USED UP ("SPRUNG BACK TO LIFE") + ADDM D,QMPBSZ(A) ;EXTRA ROOM IN LAST BLOCK TO FILL UP + MOVSI D,%QAWOV + IORM D,QSRAC(A) ;FILLING LAST BLK PAST ORIG EOF + POPJ P, ;FINISH OUT BLOCK + +QSBWO2: MOVSI D,%QAWOV + ANDCAM D,QSRAC(A) + MOVE D,QSLGL(A) ;WRITE TRACK BACK WHERE IT CAME FROM + MOVEM D,QMPTN(A) ;PUT TRACK NO WHERE QTG5 CAN FIND IT + MOVE H,QUDPR(A) + PUSHJ P,QUDLK + SETOM QSCRW(A) ;SWITCH TO WRITE MODE + MOVEI Q,%QMWOV + HRRM Q,QSRAC(A) + JRST QTG5 + + +QTG4: LDB D,[140500,,QMTTR(A)] ;WRITE LOAD ADDRESS + IORI D,40 + PUSHJ P,QUDS + LDB D,[060600,,QMTTR(A)] + PUSHJ P,QUDS + LDB D,[0600,,QMTTR(A)] + PUSHJ P,QUDS + JRST QTG5A + +QGTRK: PUSHJ P,QTLOCK ;GET TRK CHNL IN A DSK IN I RET IN D CLOBBERS E,TT,Q,J,B +QGTK4: PUSH P,R ;ENTER HERE FROM SWAP OUT WITH UTCOFF + PUSH P,B + PUSH P,E + HRRZ R,QTUTO(I) +QGTK4A: SKIPGE Q,QMFTP(A) + JRST QGTK3A ;FIRST TRACK + IDIVI Q,DECADE + HRREI J,-DECADE(J) ;COMPUTE TRACKS REMAINING IN DECADE + MOVE D,QMFTP(A) + PUSHJ P,TUTPNT + ADD D,[TUTBYT_14,,] ;MAKE INTO ILDB-TYPE POINTER + MOVE TT,QMFTP(A) + EXCH D,TT +QGTK3: CAML D,QLASTB(R) + JRST QGTK3A ;REACHED END OF DISK + ILDB Q,TT + JUMPE Q,QGTK2 + AOJGE J,QGTK3A ;DECADE OUT + AOJA D,QGTK3 + +QGTK3A: CAILE A,NQCHN + JRST QGTK3C ;SWAP CHANNEL +QGTK3D: MOVEI Q,DECADE + ADDB Q,QTUTP(R) +QGTK3B: MOVEM Q,QMFTP(A) + CAMGE Q,QLASTB(R) + JRST QGTK4A + MOVE Q,QSWAPA(R) ;REACHED END OF DSK, RESET TO END OF SWAPPING AREA + ADDI Q,DECADE-1 ;ROUND UP TO A MULTIPLE OF A DECADE + IDIVI Q,DECADE + IMULI Q,DECADE + MOVEM Q,QTUTP(R) + JRST QGTK3B + +QGTK2: MOVEI B,1 + DPB B,TT + MOVEM D,QMFTP(A) + MOVE J,DCHBT(I) + IORM J,QTUTO(I) + POP P,E + POP P,B + POP P,R + CAILE A,NQCHN + POPJ P, ;CALLED FROM SWAP OUT + JRST QTULK + +QGTK3C: CAML D,QSWAPA(R) + JRST QGTK3D ;IN NON-SWAP AREA + AOS D + CAMN D,QSWAPA(R) + MOVEI D,NUDSL + MOVEM D,QMFTP(A) + JRST QGTK4A + ;STORE CHR IN D CHNL IN A USER DIR PNTR IN H +;CANNOT PCLSR NOR GC + +QUDS: PUSH P,I + PUSH P,Q + MOVE I,QDIRP(A) + CAIGE I,2000*UFDBPW + CAML I,@QSNLCN(H) ;UDESCP + BUG ;WRITING ABOVE F.S. PNTR? + AOS QDIRP(A) + IDIVI I,UFDBPW + MOVE Q,QBTBL(Q) + ADD Q,I + SKIPL I,QSNLCN(H) + BUG ;UFD WAS NOT LOCKED + ADDI Q,UDDESC(I) + LDB I,Q + CAIE I,UDWPH ;OK TO CLOBBER UDWPH (NORMALLY DOES AT START OF FILE) + JUMPN I,[JRST 4,.] ;ABOUT TO CLOBBER SOMETHING IN UFD + DPB D,Q + ILDB I,Q ;MAKE SURE FILE DESC WILL ALWAYS BE FOLLOWED BY ZERO + SKIPE I + BUG +REPEAT NXLBYT+2,[ ;MAKE SURE THERE'S ROOM FOR ONE MORE TRACK + ILDB I,Q + JUMPN I,QUDS1 +] + MOVE I,QDIRP(A) + ADDI I,NXLBYT+2 + CAMGE I,@QSNLCN(H) ;UDESCP + JRST QUDSX ;DESC AREA NOT COLLIDING WITH LIM OF DESC SPACE + MOVEI Q,LUNBLK(Q) + MOVE I,QSNLCN(H) + SUBI Q,(I) + CAML Q,UDNAMP(I) + JRST QUDS1 ;NO ROOM. + MOVEI Q,3*UFDBPW ;EXPAND DESC AREA + ADDM Q,UDESCP(I) + JRST QUDSX + +QUDS1: MOVSI Q,%QAFUL ;NEED GC BEFORE STARTING ON NEXT TRACK + IORM Q,QSRAC(A) +QUDSX: MOVE Q,QACTB + IORM Q,QSNLCN(H) ;SET DIRECTORY CHANGED + POP P,Q + POP P,I + POPJ P, + +QSBWW1: HRRM Q,QBFP(A) + JRST QSBWW2 + +QSBRB1: MOVE A,D +QSBRB: PUSH P,A + SKIPGE A,QSMDN(A) + JRST POPAJ + PUSHJ P,MEMR + POP P,A + HRRZ TT,QMPBSZ(A) + ADDM TT,QFBLNO(A) ;INCREMENT BYTE ADR IN FILE OF BEG OF NEXT BLOCK + SETOM QSMDN(A) + JRST QSTRTR + +QTG2: MOVE J,QMTTR(A) ;INDICATE WE WILL STORE DESCRIPTOR FOR NEXT TRACK. + MOVEM J,QMPTN(A) + AOS D,QMPTC(A) ;NEXT BLOCK IS CONSECUTIVE + CAIGE D,UDTKMX + JRST QTG5A + SETZM QMPTC(A) ;MAX # CONSECUTIVE BLOCKS, STORE DESC NOW + PUSHJ P,QUDS + JRST QTG5A + +SUBTTL DIRHNG DEVICE + +;WHENEVER THE DIRECTORY SPECIFIED AS THE SNAME WHEN DIRHNG IS OPENED +;IS MODIFIED, YOU GET AN INTERRUPT ON THE DIRHNG DEVICE CHANNEL. + +;HERE TO OPEN THE DIRHNG DEVICE. IOCHNM ADDR IN R, SNAME IN USYSN1(U). +DIRHO: MOVE C,USYSN1(U) + PUSHJ P,QFL ;LOOK UP THIS DIRECTORY + JRST OPNL20 ;CALL FAILS IF DIRECTORY DOES NOT EXIST. + HRRZM J,IOCHST-IOCHNM(R) ;DIR EXISTS; STORE TRACK NUMBER IN IOCHST. +DIRHP1: CONO PI,CLKOFF + HLLZ A,DIRHNG ;ADD THIS CHANNEL'S IOCHNM TO THE LIST OF DIRHNG CHANNELS. + HRRI A,DNDIRH + MOVEM A,(R) ;SET UP THE IOCHNM WITH IOTTB INDEX AND LIST CHAIN. + HRLZM R,DIRHNG + JRST CLKOJ1 + +;CLOSE A DIRHNG DEVICE CHANNEL. +DIRHCL: PUSHJ P,DIRHPS ;REMOVE IT FROM THE LIST, AND + SETZM (R) ;MARK IT CLOSED. + POPJ P, + +;IOPUSH A DIRHNG DEVICE CHANNEL. REMOVE IT FROM THE LIST OF ALL SUCH. +DIRHPS: MOVEI A,DIRHNG + CONO PI,CLKOFF +;FIND THE PLACE THAT POINTS AT THIS IOCHNM WORD. +DIRHC1: HLRZ B,(A) + CAIN B,(R) + JRST DIRHC2 + SKIPN A,B ;END OF LIST REACHED => + BUG ;THIS IOCHNM ISN'T IN THE LIST. BUT IT IS SUPPOSED TO BE! + JRST DIRHC1 + +;A POINTS AT IOCHNM THAT POINTS AT THIS ONE. PATCH THIS ONE OUT OF LIST. +DIRHC2: HLRZ B,(B) ;THE ONE AFTER THIS ONE + HRLM B,(A) + JRST CLKONJ + +;IOPUSH OR IOPOP THE DIRHNG CHANNEL WITH R -> IOCHNM WORD. I SAYS WHICH OPERATION. +DIRHIP: JUMPE I,DIRHPS ;IOPUSH REMOVES CHANNEL FROM LIST OF ALL DIRHNG CHANNELS. + +;IOPOP A DIRHNG DEVICE CHANNEL. JUST LIKE OPENING IT EXCEPT THAT +;THE DIRECTORY TRACK NUMBER IS ALREADY IN THE IOCHST. +;ALSO, WE SHOULD GIVE AN INTERRUPT NOW, +;IN CASE THE DIRECTORY WAS WRITTEN IN WHILE THE CHANNEL WAS PUSHED. +DIRHPP: PUSHJ P,DIRHP1 ;FIRST, REOPEN THE CHANNEL. LINK IT INTO THE DIRHNG LIST. + BUG + MOVE A,R + SUBI A,IOCHNM(U) ;COMPUTE CHANNEL NUMBER FROM IOCHNM WORD ADDRESS. + MOVE A,CHNBIT(A) ;GET BIT CORRESPONDING TO CHANNEL. + AND A,MSKST2(U) ;GIVE THE INT IF THE INT IS ENABLED. + IORM A,IFPIR(U) + POPJ P, + +;HERE WITH A/ DIRECTORY'S TRACK NUMBER (AS RETURNED BY QFL) +;TO SIGNAL A WRITE IN THAT DIRECTORY TO ALL DIRHNG DEVICES THAT ARE LOOKING. +;CLOBBERS B, C, D. +DIRSIG: CONO PI,CLKOFF + MOVEI B,DIRHNG +DIRSI0: HLRZ B,(B) ;GET IOCHNM ADDR OF NEXT DIRHNG DEVICE. + JUMPE B,CLKONJ + HRRZ C,IOCHST-IOCHNM(B) + CAIE C,(A) ;DOES IT LOOK AT THIS DIRECTORY? + JRST DIRSI0 + MOVEI C,-IOCHNM(B) ;YES => FIGURE OUT USER INDEX OF JOB IT BELONGS TO. + IDIVI C,LUBLK + IMULI C,LUBLK ;C NOW HAS USER INDEX. + MOVNI D,IOCHNM(C) + ADD D,B ;D GETS CHANNEL NUMBER + MOVE D,CHNBIT(D) + AND D,MSKST2(C) ;INTERRUPT THE USER ON THAT CHANNEL, IF IT'S ENABLED. + IORM D,IFPIR(C) + JRST DIRSI0 diff --git a/src/system/dmpcpy.11 b/src/system/dmpcpy.11 new file mode 100755 index 00000000..a099bb6e --- /dev/null +++ b/src/system/dmpcpy.11 @@ -0,0 +1,153 @@ +; -*- MIDAS -*- + + TITLE DMPCPY - COPY DUMPS FROM SWAP AREA TO FILE AREA + +A=1 +B=2 +C=3 +D=4 +E=5 +T=6 +TT=7 +P=17 + +CHDIRI=10 +CHDSKI=11 +CHDSKO=12 + +.INSRT SYSENG;FSDEFS > + +PDL: -20,,. + BLOCK 20 + +;DIRECTORIES WHERE STUFF MIGHT GET DUMPED OUT OF TIMESHARING +DIRLST: SIXBIT/./ + SIXBIT/CRASH/ + SIXBIT/CRASH2/ +NDIRS==.-DIRLST + +DIR: BLOCK 2000 +BUF: BLOCK 2000 + +USRVAR: SIXBIT /OPTION/ ? TLO %OPINT\%OPOPC + SIXBIT /MASK/ ? MOVE [%PIIOC\%PIPDL] +LUSRVAR==:.-USRVAR + +GO: .CLOSE 1, ;RUNS AS DAEMON + MOVE P,PDL + MOVE TT,[-LUSRVAR,,USRVAR] + .CALL [ SETZ ? SIXBIT /USRVAR/ + MOVEI %JSELF + SETZ TT ] + .LOSE %LSSYS +CHKTIM: .CALL [ SETZ ? SIXBIT /RQDATE/ ; don't frob with files + SETZM A ] ; if system doesn't know the time + .LOSE %LSSYS + AOJN A,KNOTIM + MOVEI A,30.*15. ; 15 seconds + .SLEEP A, + JRST CHKTIM + +KNOTIM: MOVSI E,-NDIRS +CHKDIR: .CALL [ SETZ ? SIXBIT/OPEN/ + [.BII,,CHDIRI] + [SIXBIT/DSK/] + [SIXBIT/.FILE./] + [SIXBIT/(DIR)/] + SETZ DIRLST(E)] + JRST NXTDIR ; Hey, there might not -be- such a directory! + MOVE TT,[-2000,,DIR] + .IOT CHDIRI,TT + .CLOSE CHDIRI, + MOVE D,UDNAMP+DIR +CHKFIL: CAIL D,2000 + JRST NXTDIR + MOVE TT,UNRNDM+DIR(D) + SKIPGE UNDATE+DIR(D) + TLNE TT,UNDUMP\UNIGFL\UNREAP\UNLINK ; Don't screw with files + JRST NXTFIL ; you don't understand. + ;HERE WE HAVE FOUND A FILE WRITTEN OUT OF TIMESHARING + ;COPY IT SO AS TO (1) SET THE FILE DATE AND (2) GET IT OUT + ; OF THE SWAPPING AREA. NTS FILES ARE WRITTEN IN THE SWAPPING + ; AREA TO DECREASE THE PROBABILITY OF CLOBBERING SOME OTHER FILE. + .CALL [ SETZ ? SIXBIT/OPEN/ + MOVES TT + [.BII,,CHDSKI] + [SIXBIT/DSK/] + UNFN1+DIR(D) + UNFN2+DIR(D) + SETZ DIRLST(E) ] + JSP T,[ CAIE TT,%ENSFL ; perhaps a hacker deleted it + CAIN TT,%ENAPK ; perhaps that pack had to go offline + JRST NXTFIL + JRST LOSE ] + .CALL [ SETZ ? SIXBIT/OPEN/ + MOVES TT + [.BIO,,CHDSKO] + [SIXBIT/DSK/] + [SIXBIT/_DMPCP/] + [SIXBIT/OUTPUT/] + SETZ DIRLST(E) ] + JSP T,[ CAIE TT,%EFLDR + JRST LOSE + MOVEI TT,30.*60.*5 ; 5 minutes + .SLEEP TT, + JRST .-1 ] +CPYFIL: MOVE TT,[-2000,,BUF] + .IOT CHDSKI,TT + MOVEI T,-BUF(TT) + JUMPE T,ENDFIL + MOVNS T + MOVSS T + HRRI T,BUF + .IOT CHDSKO,T + JRST CPYFIL + +ENDFIL: .CLOSE CHDSKI, + .CALL [ SETZ ? 'RENMWO + MOVEI CHDSKO + UNFN1+DIR(D) + SETZ UNFN2+DIR(D) ] + .LOSE %LSSYS + .CLOSE CHDSKO, +NXTFIL: ADDI D,LUNBLK + JRST CHKFIL + +NXTDIR: AOBJN E,CHKDIR + .LOGOUT 1, + .VALUE + +; JSP T,LOSE is like .LOSE %LSFIL(TT) +LOSE: .CALL [ SETZ ? SIXBIT /LOSE/ + MOVEI %LSFIL(TT) + SETZI -2(T) ] + .LOSE %LSSYS + +TSINT: +LOC 42 + -LTSINT,,TSINT +LOC TSINT + P + %PIIOC ? 0 ? %PIIOC ? 0 ? IOCINT +LTSINT==:.-TSINT + +; If there is a disk or directory full problem, wait for someone to notice. +IOCINT: PUSH P,T + .SUSET [.RBCHN,,T] + CAIE T,CHDSKO + .LOSE + .STATUS CHDSKO,T + LDB T,[330500,,T] + CAIE T,11 ; DEVICE FULL + CAIN T,14 ; DIRECTORY FULL + JRST WAIT + .VALUE + +WAIT: MOVEI T,30.*60.*5 ; 5 minutes + .SLEEP T, + POP P,T + .CALL [ SETZ ? SIXBIT /DISMIS/ + SETZ P ] + .LOSE %LSSYS + +END GO diff --git a/src/system/dskdmp.215 b/src/system/dskdmp.215 new file mode 100755 index 00000000..fa5a92f2 --- /dev/null +++ b/src/system/dskdmp.215 @@ -0,0 +1,1882 @@ +;;; -*-Midas-*- + +TITLE DSKDMP + +.MLLIT==1 + +DEFINE SETF TEXT,FLG +IFDEF FLG,.STOP +.TAG FOOBAR +PRINTC "TEXT +FLG=" +.TTYMAC FLAG +.TTYFLG==.TTYFLG+1 +PRINTX/FLAG +/ +.TTYFLG==.TTYFLG-1 +IFSE FLAG,YES,FLG==1 +IFSE FLAG,NO,FLG==0 +IFSE FLAG,Y,FLG==1 +IFSE FLAG,N,FLG==0 +IFNDEF FLG,FLG==FLAG +TERMIN +IFNDEF FLG,.GO FOOBAR +TERMIN + +IF1,[ +PRINTC "Configuration (KSRP06, KSRP07, KSRM03, KSRM80 or ASK) ? " +.TTYMAC MACH +IFSE MACH,KSRP06,[ + HRIFLG==0 + RP06P==1 + KS10P==1 + NUDSL==500. +] ;KSRP06 +IFSE MACH,KSRP07,[ + HRIFLG==0 + RP06P==0 + RP07P==1 + KS10P==1 + NUDSL==500. +] ;KSRP07 +IFSE MACH,KSRM03,[ + HRIFLG==0 + RP06P==0 + RP07P==0 + RM03P==1 + KS10P==1 + NUDSL==500. +] ;KSRM03 +IFSE MACH,KSRM80,[ + HRIFLG==0 + RP06P==0 + RP07P==0 + RM03P==0 + RM80P==1 + KS10P==1 + NUDSL==500. +] ;KSRM80 +IFSN MACH,ASK,[ +IFNDEF NUDSL,[ PRINTC /No known configuration for "MACH". +/ ]] +TERMIN +] ;IF1 + +SETF [Readin Mode Paper Tape?]HRIFLG +SETF [Assemble BOOT? (If no, full DSKDMP)]BOOTSW + +SETF [RH11/RP06 disk system?]RP06P +IFE RP06P,[ +SETF [RH11/RP07 disk system?]RP07P +IFE RP07P,[ +SETF [RH11/RM03 disk system?]RM03P +IFE RM03P,[ +SETF [RH11/RM80 disk system?]RM80P +IFE RM80P,[ +SETF [RH10 (MC-KL) disk control?]RH10P +IFE RH10P,[ +SETF [AIKA disk control? (no => RP02/RP03)]DC10P +]]]]] +IFN RP06P, RP07P==0 +IFN RP06P+RP07P, RM03P==0 +IFN RP06P+RP07P+RM03P, RM80P==0 +IFN RP06P+RP07P+RM03P+RM80P, RH10P==0 +IFN RP06P+RP07P+RM03P+RM80P+RH10P, DC10P==0 +IFN RP06P+RP07P+RM03P+RM80P+RH10P+DC10P, RP10P==0 +IFE RP06P+RP07P+RM03P+RM80P+RH10P+DC10P, RP10P==1 + +IFE BOOTSW, SETF [Number of dirs? (DM-KA: 200., ML-KA: 250., AI-KA: 440., all others: 500.)]NUDSL + +SETF [KS10 processor?]KS10P +IFE KS10P, SETF [KL10 processor? (no => KA10)]KL10P +IFN KS10P, KL10P==0 +IFN KS10P+KL10P, KA10P==0 +IFE KS10P+KL10P, KA10P==1 + +RH11P==:RP06P+RP07P+RM03P+RM80P + +DEFINE RP +IFN RP10P!TERMIN +DEFINE SC +IFN DC10P!TERMIN +DEFINE RH +IFN RH10P!TERMIN +DEFINE PH +IFN RH11P!TERMIN + +DEFINE KA +IFN KA10P!TERMIN +DEFINE KL +IFN KL10P!TERMIN +DEFINE KS +IFN KS10P!TERMIN + +IFN HRIFLG,[ +NOSYMS ;MAKE PAPER TAPE SHORTER +RIM10 +] + +C=1 ;C-A-B FOR LINKS +A=2 +B=3 +D=4 +BLKIN=5 ;PSEUDO-CORE BLOCK IN CBUF +WRITE=6 ;NEG MEANS DUMP, RH 0 OR WRBIT +DIFF=7 ;DIFF CONO ALSO TEMP +HEAD=10 ;HEAD CONO ALSO TEMP +P=11 ;JSP AC +BLOK=12 +UNIT=13 ;UNIT AND M.A. DATAO +CMD=14 ;COMMAND CHAR +T=15 ;VERY TEMP +TT=16 ;ANOTHER JSP AC, ALSO VERY TEMP +BUFP=17 ;DBUF PNTR--LAST WORD USED + +IF1,[ ;DON'T TAKE A WEEK AND A HALF TO ASSEMBLE. +RP, .INSRT SYSTEM;RP10 > +SC, .INSRT SYSTEM;DC10 > +RH, .INSRT SYSTEM;RH10 > +PH, .INSRT SYSTEM;RH11 > +IFN RP06P, .INSRT SYSTEM;RP06 > +IFN RP07P, .INSRT SYSTEM;RP07 > +IFN RM03P, .INSRT SYSTEM;RM03 > +IFN RM80P, .INSRT SYSTEM;RM80 > +IFE BOOTSW, .INSRT SYSTEM;FSDEFS > +IFE BOOTSW, KL, .INSRT SYSTEM;EPT > +KS, .INSRT SYSTEM;KSDEFS > +KA, TTY==120 +] + +;PARAMETER FILE FOR DSKDMP + +MEMSIZ=1000000 ;ACTUAL SIZE OF MEM +IFNDEF DBGSW,DBGSW==0 ;1 TO DEBUG THIS WITH DDT +DDT==MEMSIZ-4000 +IFN DBGSW,MEMSIZ==MEMSIZ-10000 ;MOVE DOWN UNDER DDT IF DEBUG MODE +CORE==MEMSIZ-10000-<2000*NTUTBL> ;HIGHEST ADR ALWAYS IN CORE+1 +CORES==CORE_<-12> ;BLK # OF ABOVE (FIRST OF BLKS SWAPPED OUT FOR BUFFER AREAS) +NSWBL==4+NTUTBL ;# BLOCKS SWAPPED OUT FOR BUFFER AREAS, +1 FOR DSKDMP ITSELF +HIGH==MEMSIZ-100 ;HIGHEST ADR LOADED/DUMPED+1 + +NDSK==8 ;MAX POSSIBLE. L$n$ DEFINES WHICH ARE REALLY THERE +RP,ICWA=34 +RH,ICWA=34 + +PH, UBPG==:17 ; Use last (usable) page in Unibus map + +KA, LPM=102000,, +KA, LPMR=LPM 2, +KL, PAG=- + +DEFINE INFORM A,B +IF1,[ PRINTX  A = B +] TERMIN + +;COMMANDS ARE: +; L$file LOAD FILE INTO CORE +; T$file LOAD FILE INTO CORE AND GIVE SYMBOLS TO DDT AND START DDT +; M$file LOAD FILE INTO CORE WITHOUT CLEARING CORE FIRST, DOESN'T LOAD SYMBOLS +; K$file DELETE FILE +; D$file DUMP CORE INTO FILE +; I$file VERIFY FILE AGAINST CORE +; G$ START AT STARTING ADDRESS +; U$dir; LIST DIRECTORY +; F$ LIST CURRENT DIRECTORY +; S$ LIST PACK IDS THEN MFD +; nnn$ SET STARTING ADDRESS TO nnn +; L$n$ PUT DISK n ONLINE +; K$n$ TAKE DISK n OFFLINE + +;ERROR MESSAGES ARE: +; CMPERR VERIFY FAILED TO MATCH +; DIRFUL DIRECTORY FULL +; EOF UNEXPECTED EOF +; DIRNF DIRECTORY DOES NOT EXIST +; FNF FILE NOT FOUND +; PKNMTD FILE IS ON PACK THAT IS NOT MOUNTED +; CKSERR CHECKSUM ERROR +; DSKFUL DISK FULL +; NODDT CAN'T ADDRESS DDT SYMBOL TABLE (BUG) +; ?BUG? BUG +; SEEKFL DISK SEEK ERROR +; CLOBRD DISK READ ERROR +; CLOBWR DISK WRITE ERROR +; DIRCLB DIR NAME DIFFERS, TUT DISAGREES WITH DIR +; MFDCLB M.F.D. CLOBBERED +; DSKLUZ DISK LOSSAGE (OFFLINE OR UNSAFE OR MASSBUS ERROR) + +KS, LOC 4000 ; Avoid MTBOOT and KSRIM + +IFE BOOTSW,[ +ZZZ: IFE DBGSW,[ + MOVE T,.... ;THIS CODE BLTS THE FOLLOWING OFFSET CODE + BLT T,MEMSIZ-1-1 ;INTO HIGH MEMORY AND WRITES DSKDMP ON ITS + MOVE T,PROG+MEMSIZ-2-BEG+1 + MOVEM T,BEG+MEMSIZ-2-BEG+1 ;AVOID LOSING DUE TO -1 BLT LOSSAGE +] + MOVSI T,-NDSK+1 ;MAKE ALL BUT DISK 0 BE DEAD (MUST DO L$ TO MAKE THEM ALIVE) + SETOM QDED+1(T) + MOVNS QDED+1(T) + AOBJN T,.-2 + SETZM QDED+0 +RP,[ MOVEI T,ICWA+2 ;SET UP CHANNEL JUMP + MOVEM T,ICWA ;IN INITIAL CHANNEL ADDRESS + SETZM ICWA+1 ;AND CLEAR REMAINING STUFF + SETZM ICWA+3 + DATAO DPC,SUNIT0 + DATAI DPC,B + TRNN B,RP03BT + JRST WBOOT1 + MOVEI B,MBLKS ;UNIT 0 IS AN RP03, ADJUST WORLD + HRRM B,CBLK + MOVE B,RP3ADJ + MOVSI A,-NSWBL + XORM B,SWPSK(A) + AOBJN A,.-1 +WBOOT1: HLLZS BOOT0 + MOVEI UNIT,BEG ;MAGIC BLOCK THEN STARTS IT + HRRZ BLOK,CBLK + ADDI BLOK,NSWBL ;FIRST BLOCK AFTER CORE BUFFER IS WHERE DSKDMP LIVES + MOVEI WRITE,10 + JSP TT,WRD3 + HRRZ BLOK,CBLK + ADDI BLOK,NSWBL+1 + MOVEI WRITE,10 + JSP TT,WRD3 + CONSZ DPC,ALLER +IFN DBGSW,JRST DDT +IFE DBGSW,JRST 4,. ;FORMERLY JRST MEMSIZ-400 (??) + JRST BEG +];RP +PH,[ MOVEI T,%HYCLR ; Clear controller + IOWRQ T,%HRCS2 ; (Selects drive 0) +WBOOT0: IORDQ T,%HRCS1 + TRNN T,%HXDVA + JRST WBOOT0 ; Await drive available (well, it is a dual + ; ported drive... perhaps someday?) + MOVEI UNIT,BEG + HRRZ BLOK,CBLK + ADDI BLOK,NSWBL ; FIRST BLOCK AFTER CORE BUFFER IS WHERE + ; DSKDMP LIVES + MOVEI WRITE,10 + JSP TT,WRD3 + HRRZ BLOK,CBLK + ADDI BLOK,NSWBL+1 + MOVEI WRITE,10 + JSP TT,WRD3 + IORDQ TT,%HRCS1 + TRNE TT,%HXTRE+%HXMCP +IFN DBGSW, JRST DDT +IFE DBGSW, JRST 4,. ; Formerly JRST MEMSIZ-400 (??) + JRST BEG +];PH +RH,[ MOVEI T,ICWA+2 ;SET UP CHANNEL JUMP + MOVEM T,ICWA ;IN INITIAL CHANNEL ADDRESS + SETZM ICWA+1 ;AND CLEAR REMAINING STUFF + SETZM ICWA+3 +WBOOT0: DATAO DSK,[%HRDCL,,] + MOVEI A,20 + SOJG A,. + DATAI DSK,A + TRNN A,%HCDVA + JRST WBOOT0 ;AWAIT DRIVE AVAILABLE + MOVEI UNIT,BEG ;MAGIC BLOCK THEN STARTS IT + HRRZ BLOK,CBLK + ADDI BLOK,NSWBL ;FIRST BLOCK AFTER CORE BUFFER IS WHERE DSKDMP LIVES + MOVEI WRITE,10 + JSP TT,WRD3 + HRRZ BLOK,CBLK + ADDI BLOK,NSWBL+1 + MOVEI WRITE,10 + JSP TT,WRD3 + CONSZ DSK,%HIERR +IFN DBGSW,JRST DDT +IFE DBGSW,JRST 4,. ;FORMERLY JRST MEMSIZ-400 (??) + JRST BEG +];RP +SC,[ MOVEI UNIT,BEG ;MAGIC BLOCK THEN STARTS IT + MOVEI BLOK,NBLKS+NSWBL + MOVEI WRITE,60 + JSP TT,WRD3 + MOVEI BLOK,NBLKS+NSWBL+1 + MOVEI WRITE,60 + JSP TT,WRD3 + DATAO DC0,..... + CONSZ DC0,DSSACT + JRST .-1 + CONSZ DC0,DSSERR +IFN DBGSW,JRST DDT +IFE DBGSW,JRST 4,. ;FORMERLY JRST MEMSIZ-400 (??) + JRST BEG + +.....: DJMP .+1 + DWRITE + DCOPY ......(-LRIBLK_2&37774) + DHLT + +......: DWRITE+DUNENB+DADR ;FOR READIN + DCOPY BEG(-2000_2&37774) + DREAD+DADR1 + DCOPY BEG(-2000_2&37774) + DHLT +];SC + +IFE DBGSW,[ +....: PROG,,BEG + +KA, LOC 2000 ; MAKE OFFSET CONVENIENT +KL, LOC 2000 +KS, LOC 6000 ; Avoid MTBOOT and KSRIM +PROG: OFFSET CORE+<*2000>-. +]IFN DBGSW,LOC MEMSIZ-2000 + +BEG: +KA,[ CONO 635550 ;ENTER HERE, CLEAR WORLD + JRST .+1 + JFCL 1,[JRST 4,.] ;A PDP6?? + LPMR [0]-2 ;TURN OFF EXEC PAGING +] +KL,[ CONO 327740 ;CLEAR APR + CONSZ PAG,660000 ;PAGING AND CACHE BETTER BE OFF + JRST 4,. +] +KS,[ CONO 127760 ; Enable, and Clear all. + RDEBR B + TRNE B,60000 ; Paging and Tops-20 better be off. + JRST 4,. + SETZM 8SWIT0 ; Clear 8080 Communications area to prevent + MOVE B,[8SWIT0,,8SWIT0+1] ; mysterious IO behavior. + BLT B,8RHBAS-1 + ;; If the machine has just been powered on, there is likely to be + ;; bad parity all over the place. I guess that isn't our problem + ;; as long as we don't touch any of it... +] + MOVSI B,-NDSK ;FOR NUMBER OF DISKS + SETOM PKNUM(B) ;SET DISK TO UNKNOWN + AOBJN B,.-1 + MOVE T,[JRST LOADG1] ;SET BOOTSTRAP TO MIDDLE OF WORLD + MOVEM T,BOOT + MOVE D,['DSKDMP] ;ANNOUNCE SELF + JSP TT,PD + JRST READ ;CRLF AND BEGIN READING COMMANDS + +ERROR: 0 + CLEARM MEMSIZ-1 ;DON'T READ ANY MORE COMMANDS FROM MEMORY + SOS T,ERROR ;PICK UP ERROR CODE FROM THE AC FIELD OF + LDB T,[270400+T,,] ;THE JSR ERROR + MOVE D,ERMESS(T) + JSP TT,PD ;PRINT OUT APPROPRIATE COMMENT + CAIL T,EBUG + JRST READ ;BAD ERROR - NO MORE DISKING +LOADG1: +KA, DATAI TTY,C ;FLUSH RANDOM CHARACTER +KS, SETZM 8CTYIN ; ".RESET" + TRO CMD,10 ;MAKE SURE PSEUDO-CORE IN CORE + JRST LOADG ;BY SIMULATING END OF LOADING, NON-GOING COMMAND + +ERMESS: IRP XX,,[ECMP,EDIR,EEOF,ESNF,EFNF,EPNM,ECKS +EDSK,EDDT,EBUG,EC63,ECRD,ECWR,ECDR,EMFC,EDLZ]YY,,[CMPERR,DIRFUL +EOF,DIRNF,FNF,PKNMTD,CKSERR,DSKFUL,NODDT,?BUG?,SEEKFL +CLOBRD,CLOBWR,DIRCLB,MFDCLB,DSKLUZ] +XX==.-ERMESS + SIXBIT \YY\ +TERMIN + +PD: JSP P,CRLF ;TYPE A CR +PD2: MOVEI C,40 + JSP P,TYO ;AND A SPACE + MOVE B,[440600,,D] +PD1: ILDB C,B ;AND THE SIXBIT CONTENTS OF D + ADDI C,40 + JSP P,TYO + TLNE B,770000 + JRST PD1 + JRST (TT) + +PNO: +C12: IDIVI C,10. ;PRINT CONTENTS OF C AS A TWO-DIGIT + DPB C,[60600,,A] ;DECIMAL NUMBER PRECEDED + MOVEI D,(SIXBIT /#00/+A) ;BY # + MOVE B,[300600,,D] + JRST PD1 + +WRCB: MOVEI UNIT,CBUF ;WRITE OUT CONTENTS OF CBUF + LSH BLKIN,-12 ;ON APPROPRIATE BLOCK + HRRZ BLOK,CBLK + ADDI BLOK,-CORES(BLKIN) + JRST WRM + +LODUMP: MOVEI UNIT,CORE ;DEPENDING ON SIGN BIT OF WRITE, LOAD OR DUMP + HRRZ BLOK,CBLK ;PSEUDO-CORE (766000-775777) +LODMP1: JSP TT,WRDM + ADDI UNIT,2000 + CAIGE UNIT,BEG + AOJA BLOK,LODMP1 + MOVEI BLKIN,CORE + JRST (P) + +FD: HRRZ C,B ;SET UP POINTER IN C TO FETCH OR DEPOSIT + ;CONTENTS OF ADDRESS IN RIGHT HALF OF B +IFN DBGSW, SKIPGE WRITE ;LOAD DDT WHEN IN DEBUG MODE + CAIGE C,HIGH + CAIGE C,40 + JRST (P) + CAIGE C,CORE ;IF ADDR IS IN REAL CORE, RETURN IMMEDIATELY + JRST 1(P) +FDX: CAIL C,(BLKIN) ;ADDR IS IN PSEUDO-CORE--CHECK IF RIGHT + CAILE C,1777(BLKIN) ;BLOCK IS IN CBUF + JRST FD3 ;IT'S NOT THERE--READ IT IN +FD4: SUBI C,-CORE(BLKIN) ;IT'S THERE--SET UP RIGHT POINTER IN C + JRST 1(P) ;AND RETURN +FD3: JUMPLE WRITE,FD3A ;IF DUMP OR VERIFY DON'T BOTHER + ;TO WRITE OUT CURRENT BLOCK +FD3B: JSP TT,WRCB ;IF LOAD, WRITE CURRENT BLOCK FIRST +FD3A: MOVEI UNIT,CBUF + MOVE BLKIN,C + ANDI BLKIN,776000 + LDB BLOK,[121000,,BLKIN] + ADD BLOK,CBLK + MOVEI BLOK,-CORES(BLOK) + JSP TT,RDM ;READ IN CORRECT BLOCK + JRST FD4 ;SET UP POINTER AND RETURN + +GBP: IDIVI C,6 ;TURN USER DIRECTORY CHARACTER ADDR IN C + IMULI A,-60000 ;INTO A BYTE POINTER + HRLI C,440600(A) + ADDI C,DIR+UDDESC + JRST (TT) + +WD: AOBJN BUFP,WD1 ;READ, WRITE, OR VERIFY WORD IN D FROM, INTO, + JSP TT,NXTBLK ;OR AGAINST WORD IN DBUF + JSP TT,WRDB ;TIME TO REFILL OR EMPTY DBUF + MOVSI BUFP,-2000 ;RESET BUFFER POINTER +WD1: JUMPG WRITE,WD2 ;JUMP ON LOAD + JUMPL WRITE,WD3 ;JUMP ON WRITE + CAME D,DBUF(BUFP) ;HERE IF VERIFY + JSR ECMP,ERROR ;VERIFY COMPARE LOST + JRST (P) +WD2: SKIPA D,DBUF(BUFP) ;LOAD +WD3: MOVEM D,DBUF(BUFP) ;DUMP + JRST (P) + +NXTTUT: HRRZ B,CU ;SELECT NEXT UNIT AND READ ITS TUT + AOJ B, + CAIN B,NDSK + MOVEI B,0 + HRRM B,CU + CAIN B,@MU + JRST 1(TT) ;SKIP IF NO MORE + SKIPE QDED(B) + JRST NXTTUT ;UNIT NOT ON LINE +RDTUT: MOVEI BLOK,TUTBLK ;READ TUT OF CURRENT UNIT + MOVEI UNIT,TUT + SETOM PKNUM(B) ;ALWAYS READ HEADER FOR TUT +IFG NTUTBL-1,[ ;READ IN MULTI-BLOCK TUT + HRRM TT,RDTUTX ;SAVE RETURN ADDRESS +REPEAT NTUTBL-1,[ + JSP TT,RD + ADDI UNIT,2000 + AOS BLOK +] +RDTUTX: MOVEI TT,. +] + JRST RD + +NXTBW3: 0 + IBP DIRPT ;DO AN IDPB T,DIRPT CHECKING TO SEE IF + LDB DIFF,[1200,,DIRPT] ;RUNNING INTO NAME AREA + CAML DIFF,DIR+UDNAMP + JSR EDIR,ERROR + DPB T,DIRPT + JRST @NXTBW3 + +NXTBW: MOVE BLOK,LBLOCK ;FIND NEXT FREE BLOCK TO WRITE + MOVEI HEAD,1(BLOK) + ILDB T,TUTPT + JUMPN T,NXTBW1 ;JUMP IF VERY NEXT BLOCK NOT FREE + AOSG T,BLKCNT +NXTBW5: SOJA HEAD,NXTBW4 ;GENERATE LOAD ADR IF FIRST TIME (COMPENSATE FOR LBLOCK OFF BY 1) + CAIG T,UDTKMX-1 + JRST NXTBW2 ;NO NEED TO MODIFY DIRECTORY YET + CLEARM BLKCNT ;14 IN A ROW--RESET COUNTER AND +NXTBW6: JSR NXTBW3 ;DPB BYTE INTO DIRECTORY +NXTBW2: MOVE BLOK,HEAD + CAML BLOK,TUT+QLASTB + JSR EDSK,ERROR ;NO MORE DISK LEFT + MOVEI T,1 + DPB T,TUTPT ;MARK BLOCK USED IN TUT + JRST WRDB1 + +NXTBW1: ADDI HEAD,1 ;SEARCH FOR NEXT FREE BLOCK + ILDB T,TUTPT + JUMPN T,NXTBW1 + SUBM HEAD,BLOK + SKIPLE T,BLKCNT ;COME UP WITH DESC BYTE FOR LAST FEW BLOCKS + JSR NXTBW3 + CLEARM BLKCNT + JUMPL T,NXTBW5 ;FIRST TIME + MOVEI T,UDTKMX-1(BLOK) + CAIGE T,UDWPH ;CAN WE SAY SKIP N--TAKE 1? + JRST NXTBW6 ;YES +NXTBW4: MOVEI BLOK,NXLBYT + MOVE T,HEAD + ROT T,-NXLBYT*6 + ADDI T,UDWPH+1 + JSR NXTBW3 + ROT T,6 + SOJG BLOK,.-2 + JRST NXTBW6 + +NXTBLK: JUMPL WRITE,NXTBW ;GET NEXT BLOCK OF FILE--IF DUMP, FIND FREE + MOVE BLOK,LBLOCK ;BLOCK +NXTB6: SOSLE BLKCNT ;HAVE WE RUN OUT OF "TAKE N"? + AOJA BLOK,WRDB1 ;NO--TAKE NEXT BLOCK + ILDB T,DIRPT ;YES--GET NEXT DESC BYTE + CAILE T,UDWPH + JRST NXTB1 ;IT'S A LOAD ADDR + CAIE T,UDWPH + JUMPN T,NXTB2 ;IT'S A TAKE OR SKIP + CAIE CMD,'D ;IT'S 0 OR NULL--IF THIS IS A LOAD, IT'S AN + CAIN CMD,'K ;UNEXPECTED END OF FILE + JRST KILL1 ;IF DUMP OR KILL, O.K. + JSR EEOF,ERROR + +NXTB1: MOVEI BLOK,-UDWPH-1(T) ;LOAD ADR + MOVEI BUFP,NXLBYTS +NXTB1A: MOVEI T,0 + CAIE CMD,'D + CAIN CMD,'K + DPB T,DIRPT ;IF KILLING FILE, ZERO THIS BYTE (OTHERS ZEROED AT KILL) + LSH BLOK,6 + ILDB T,DIRPT + ADD BLOK,T ;GET COMPLETE BLOCK NUMBER + SOJG BUFP,NXTB1A + JRST NXTB3 + +NXTB2: MOVEM T,BLKCNT + CAIG T,UDTKMX + AOJA BLOK,WRDB1 ;TAKE N STARTING WITH NEXT ONE + ADDI BLOK,-UDTKMX+1(T) ;SKIP N- AND TAKE 1 +NXTB3: CLEARM BLKCNT +WRDB1: MOVEM BLOK,LBLOCK + JRST (TT) + ;RP10 IO ROUTINE +RP,[ +WRDM: SKIPL WRITE ;SEE WHETHER LOAD OR DUMP/VERIFY +RDM: TRZA WRITE,(WRITE) ;READ FROM MASTER UNIT +WRM: HRRI WRITE,10 ;WRITE ON MASTER UNIT +MU: IORI WRITE,0 ;MASTER UNIT SELECT STORED HERE + JRST WRD3A + +WRDB: MOVEI UNIT,DBUF ;READ OR WRITE DBUF FROM/ON CURRENT UNIT +WRD: SKIPL WRITE ;READ OR WRITE FROM/ON CURRENT UNIT +RD: TRZA WRITE,(WRITE) ;READ FROM CURRENT UNIT +WR: HRRI WRITE,10 ;WRITE ON CURRENT UNIT +CU: IORI WRITE,0 ;CURRENT UNIT SELECT STORED HERE +WRD3A: +WRD3: DPB WRITE,[360600,,DBLK] ;SET OP, UNIT SEL + DPB WRITE,[DUNFLD SEEK] + DPB WRITE,[DUNFLD RECAL] + HRLI UNIT,-2000 ;ADDRESS COMES IN IN `UNIT' + MOVEM UNIT,@ICWA + SOS @ICWA + LDB UNIT,[300,,WRITE] ;ISOLATE FROM GARBAGE + MOVNI DIFF,16. ;INITIALIZE ERROR COUNTER + MOVEM DIFF,ERRCT ;15. LOSSES PERMITTED +WRD5: HRRZ DIFF,BLOK + IMULI DIFF,SECBLK + IDIVI DIFF,NSECS + DPB HEAD,[DSECT DBLK] + IDIVI DIFF,NHEDS + DPB HEAD,[DSURF DBLK] + DPB DIFF,[DCYL DBLK] + DPB DIFF,[DCYL SEEK] + DATAO DPC,CLATT ;CLEAR ATTENTIONS + LSH DIFF,-8 ;EXTRA CYLINDER BIT FOR RP03 + DPB DIFF,[DCYLXB DBLK] + DPB DIFF,[DCYLXB SEEK] + DATAO DPC,SEEK + DATAI DPC,DIFF + TRNN DIFF,ALLATT + JRST .-2 + DATAO DPC,CLATT + TLNN DIFF,(ONCYL) + JRST WRD0 + DATAO DPC,DBLK + CONSO DPC,DONE + JRST .-1 + CONSO DPC,ALLER + JRST WRDX + HRRZM BLOK,BADBLK + AOSG ERRCT ;HARDWARE ERROR--CHECK COUNTER + JRST WRD5 ;TRY AGAIN + TRNE WRITE,10 ;GIVE UP--DISTINGUISH BETWEEN + JSR ECWR,ERROR ;WRITE ERRORS AND + JSR ECRD,ERROR ;READ ERRORS + +WRDX: HRRZ UNIT,@ICWA ;RESTORE ADDR + ADDI UNIT,1 ;COMPENSATE FOR IOWD LOSSAGE + TRZ WRITE,-1 ;FLUSH GARBAGE + JRST (TT) + +WRD0: AOSLE ERRCT + JSR EC63,ERROR + DATAO DPC,RECAL + DATAI DPC,DIFF + TRNN DIFF,ALLATT + JRST .-2 + JRST WRD5 + +DBLK: ICWA +SEEK: DSEEKC +RECAL: DRCALC +CLATT: DEASEC ALLATT +];RP + ;RH11 IO ROUTINE +PH,[ +WRDM: SKIPL WRITE ;SEE WHETHER LOAD OR DUMP/VERIFY +RDM: TRZA WRITE,(WRITE) ;READ FROM MASTER UNIT +WRM: HRRI WRITE,10 ;WRITE ON MASTER UNIT +MU: IORI WRITE,0 ;MASTER UNIT SELECT STORED HERE + JRST WRD3A + +WRDB: MOVEI UNIT,DBUF ;READ OR WRITE DBUF FROM/ON CURRENT UNIT +WRD: SKIPL WRITE ;READ OR WRITE FROM/ON CURRENT UNIT +RD: TRZA WRITE,(WRITE) ;READ FROM CURRENT UNIT +WR: HRRI WRITE,10 ;WRITE ON CURRENT UNIT +CU: IORI WRITE,0 ;CURRENT UNIT SELECT STORED HERE +WRD3A: +WRD3: TRNE UNIT,1777 ; Better be on a page boundary! + JRST 4,. + LDB DIFF,[111100,,UNIT] ; Point Unibus map at page in question + TRO DIFF,%UQFST+%UQVAL + IOWRQ DIFF,UBAPAG+UBPG_1 + ADDI DIFF,1 + IOWRQ DIFF,UBAPAG+UBPG_1+1 + LDB DIFF,[000300,,WRITE] ; Select drive + IOWRQ DIFF,%HRCS2 + JSP HEAD,RHCHEK ; Check for immediate trouble + MOVEI DIFF,%HMRDP ; Init the drive + IOWRQ DIFF,%HRCS1 + MOVNI DIFF,16. ;INITIALIZE ERROR COUNTER + MOVEM DIFF,ERRCT ;15. LOSSES PERMITTED +WRD5: MOVNI DIFF,4000 + IOWRQ DIFF,%HRWC ; 4000 half words + MOVEI DIFF,UBPG_14 + IOWRQ DIFF,%HRBA ; "Byte" base address + HRRZ DIFF,BLOK + IDIVI DIFF,NBLKSC + IOWRQ DIFF,%HRCYL ; Desire cylinder + MOVE DIFF,HEAD + IMULI DIFF,SECBLK + IDIVI DIFF,NSECS + DPB DIFF,[$HATRK HEAD] + IOWRQ HEAD,%HRADR ; Desire track and sector + MOVEI DIFF,%HMRED + TRNE WRITE,10 + MOVEI DIFF,%HMWRT + IOWRQ DIFF,%HRCS1 ; Do it (implied seek) +WRD7: IORDQ DIFF,%HRCS1 + TRNN DIFF,%HXRDY ; Wait for controller to finish + JRST WRD7 + TRNN DIFF,%HXTRE+%HXMCP ; Trouble? + JRST WRDX ; Nope, exit + HRRZM BLOK,BADBLK + AOSG ERRCT ;HARDWARE ERROR--CHECK COUNTER + JRST WRD0 ;RECALIBRATE AND TRY AGAIN + TRNE WRITE,10 ;GIVE UP--DISTINGUISH BETWEEN + JSR ECWR,ERROR ;WRITE ERRORS AND + JSR ECRD,ERROR ;READ ERRORS + +WRDX: TRZ WRITE,-1 ;FLUSH GARBAGE + JRST (TT) + +WRD0: MOVEI DIFF,%HYCLR ; Clear controller + IOWRQ DIFF,%HRCS2 + LDB DIFF,[000300,,WRITE] ; Select drive + IOWRQ DIFF,%HRCS2 + MOVEI DIFF,%HMCLR ; Clear drive + IOWRQ DIFF,%HRCS1 + JSP HEAD,RHCHEK ; Immediate lossage? + MOVEI DIFF,%HMREC ; Recalibrate + IOWRQ DIFF,%HRCS1 + MOVEI HEAD,100000. +WRD0A: SOSGE HEAD + JSR EC63,ERROR + IORDQ DIFF,%HRSTS + TRNE DIFF,%HSPIP ; WAIT FOR DRIVE TO FINISH + JRST WRD0A + ANDI DIFF,%HSDPR+%HSMOL+%HSVV+%HSRDY+%HSERR + CAIE DIFF,%HSDPR+%HSMOL+%HSVV+%HSRDY + JSR EDLZ,ERROR + JRST WRD5 + +;;; JSP HEAD,RHCHEK to check for errors. +RHCHEK: IORDQ DIFF,%HRCS1 + TRNE DIFF,%HXTRE+%HXMCP + JSR EDLZ,ERROR + JRST (HEAD) +];PH + ;RH10 IO ROUTINE +RH,[ +WRDM: SKIPL WRITE ;SEE WHETHER LOAD OR DUMP/VERIFY +RDM: TRZA WRITE,(WRITE) ;READ FROM MASTER UNIT +WRM: HRRI WRITE,10 ;WRITE ON MASTER UNIT +MU: IORI WRITE,0 ;MASTER UNIT SELECT STORED HERE + JRST WRD3A + +WRDB: MOVEI UNIT,DBUF ;READ OR WRITE DBUF FROM/ON CURRENT UNIT +WRD: SKIPL WRITE ;READ OR WRITE FROM/ON CURRENT UNIT +RD: TRZA WRITE,(WRITE) ;READ FROM CURRENT UNIT +WR: HRRI WRITE,10 ;WRITE ON CURRENT UNIT +CU: IORI WRITE,0 ;CURRENT UNIT SELECT STORED HERE +WRD3A: +WRD3: HRLI UNIT,-2000 ;ADDRESS COMES IN IN `UNIT' + CONI DSK,HEAD ;SET WORD COUNT TO ONE BLOCK + TLNE HEAD,(%HID22) ;ACCORDING TO TYPE OF CHANNEL + HRLI UNIT,-2000_4 + MOVEM UNIT,@ICWA + LDB UNIT,[300,,WRITE] ;ISOLATE FROM GARBAGE + SOS @ICWA ;ADJUST FOR DF10 LOSSAGE + MOVNI DIFF,16. ;INITIALIZE ERROR COUNTER + MOVEM DIFF,ERRCT ;15. LOSSES PERMITTED +WRD5: MOVSI DIFF,%HRDCL(UNIT) + HRRI DIFF,%HMRDP ;INIT THE DRIVE + JSP HEAD,RHSET + HRRZ DIFF,BLOK + IDIVI DIFF,NBLKSC + EXCH DIFF,HEAD + MOVEM HEAD,DBLK ;SAVE CYLINDER + IMULI DIFF,SECBLK + IDIVI DIFF,NSECS + EXCH DIFF,HEAD + DPB HEAD,[$HATRK DIFF] + TLO DIFF,%HRADR(UNIT) + JSP HEAD,RHSET + MOVE DIFF,DBLK + TLO DIFF,%HRCYL(UNIT) + JSP HEAD,RHSET + MOVSI DIFF,%HRCTL(UNIT) + IORI DIFF,ICWA_6 + TRNE WRITE,10 + TROA DIFF,%HMWRT + TRO DIFF,%HMRED + JSP HEAD,RHSET ;DO IT (USE IMPLIED SEEK) + CONSO DSK,%HIDON + JRST .-1 + CONSO DSK,%HIERR + JRST WRDX + HRRZM BLOK,BADBLK + AOSG ERRCT ;HARDWARE ERROR--CHECK COUNTER + JRST WRD0 ;RECALIBRATE AND TRY AGAIN + TRNE WRITE,10 ;GIVE UP--DISTINGUISH BETWEEN + JSR ECWR,ERROR ;WRITE ERRORS AND + JSR ECRD,ERROR ;READ ERRORS + +WRDX: HRRZ UNIT,@ICWA ;RESTORE ADDR + ADDI UNIT,1 ;COMPENSATE FOR IOWD LOSSAGE + TRZ WRITE,-1 ;FLUSH GARBAGE + JRST (TT) + +WRD0: MOVSI DIFF,%HRDCL(UNIT) + HRRI DIFF,%HMCLR + JSP HEAD,RHSET + MOVSI DIFF,%HRDCL(UNIT) + HRRI DIFF,%HMREC + JSP HEAD,RHSET + MOVEI DIFF,100000. + MOVEM DIFF,DBLK +WRD0A: SOSGE DBLK + JSR EC63,ERROR + MOVSI DIFF,%HRSTS(UNIT) + JSP HEAD,RHGET + TRNE DIFF,%HSPIP + JRST WRD0A + ANDI DIFF,%HSVV+%HSRDY+%HSMOL+%HSERR + CAIE DIFF,%HSVV+%HSRDY+%HSMOL + JSR EDLZ,ERROR + JRST WRD5 + +;RH10 HACKING ROUTINES. CALL BY JSP HEAD,. DIFF HAS REGISTER ADDRESS IN LH, DATA IN RH. +RHSET: TLOA DIFF,%HRLOD +RHGET: TLZ DIFF,%HRLOD + DATAO DSK,DIFF + MOVEI DIFF,20 + SOJG DIFF,. + DATAI DSK,DIFF + TLNE DIFF,%HDERR + JSR EDLZ,ERROR + ANDI DIFF,177777 + JRST (HEAD) + +DBLK: 0 +];RH + ;SC DISK IO ROUTINE +SC,[ +WRDM: SKIPL WRITE ;SEE WHETHER LOAD OR DUMP/VERIFY +RDM: TRZA WRITE,(WRITE) ;READ FROM MASTER UNIT +WRM: HRRI WRITE,60#120 ;WRITE ON MASTER UNIT +MU: IORI WRITE,0 ;MASTER UNIT SELECT STORED HERE + JRST WRD3A + +WRDB: MOVEI UNIT,DBUF ;READ OR WRITE DBUF FROM/ON CURRENT UNIT +WRD: SKIPL WRITE ;READ OR WRITE FROM/ON CURRENT UNIT +RD: TRZA WRITE,(WRITE) ;READ FROM CURRENT UNIT +WR: HRRI WRITE,60#120 ;WRITE ON CURRENT UNIT +CU: IORI WRITE,0 ;CURRENT UNIT SELECT STORED HERE +WRD3A: TRC WRITE,120 +WRD3: DPB WRITE,[330700,,DBLK] ;SET OP, UNIT SEL + DPB UNIT,[DCCA DBLK+1] ; & CORE ADDR + DPB UNIT,[DCCA DBLK1+1] + LDB UNIT,[400,,WRITE] ;ISOLATE FROM GARBAGE + MOVNI DIFF,16. ;INITIALIZE ERROR COUNTER + MOVEM DIFF,ERRCT ;15. LOSSES PERMITTED +WRD5: HRRZ DIFF,BLOK + IDIVI DIFF,NSECS + DPB HEAD,[DSECT DBLK] + IDIVI DIFF,NHEDS + DPB HEAD,[DSURF DBLK] + DPB DIFF,[DCYL DBLK] + CONO DC0,DCCSET\DCDENB ;RESET ALL, THEN SET DCDENB + CAIL DIFF,NCYLS + TDZA DIFF,DIFF + SKIPLE DIFF,PKNUM(UNIT) + JRST WRD4 ;PKID IN + MOVE DIFF,QTRAN(UNIT) ;READ PACK ID + DPB DIFF,[DUNFLD GPKID] + MOVEI DIFF,TUTCYL + SKIPGE QTRAN(UNIT) + ADDI DIFF,NCYLS+XCYLS + DPB DIFF,[DCYL GPKID] + DATAO DC0,[DJMP GPKID] + CONSZ DC0,DSSACT + JRST .-1 + CONSZ DC0,DSSERR + JRST WRD0 + CONO DC0,DCCSET\DCDENB ;RESET POSSIBLE "FUTURE" IP OR RLCERR + LDB DIFF,[DPKID RPKID] + MOVEM DIFF,PKNUM(UNIT) +WRD4: DPB DIFF,[DPKID DBLK] + MOVE DIFF,DBLK + DPB DIFF,[3300,,DBLK1] + MOVE DIFF,QTRAN(UNIT) + DPB DIFF,[DUNFLD DBLK] + JUMPGE DIFF,WRD4A + LDB DIFF,[DCYL DBLK] ;2ND HALF UNIT + ADDI DIFF,NCYLS+XCYLS + DPB DIFF,[DCYL DBLK] +WRD4A: DATAO DC0,[DJMP DBLK] + CONSZ DC0,DSSACT + JRST .-1 + CONSO DC0,DSSERR + JRST WRDX ;XFER OK + MOVE DIFF,ERRCT + TRNN DIFF,2 ;DO RECALIBRATE 2 OUT OF 4 RETRIES + JRST WRD2 +WRD0: AOSLE ERRCT ;POSITIONER ERROR--CHECK ERROR COUNT + JSR EC63,ERROR ;TOO MANY--GIVE UP + DATAO DC0,[DSPC+DSRCAL+DSWINF] + CONSO DC0,DSSATT + JRST .-1 + JRST WRD5 ;TRY AGAIN AFTER RESETTING UNIT + +WRD2: HRRZM BLOK,BADBLK + AOSG ERRCT ;HARDWARE ERROR--CHECK COUNTER + JRST WRD5 ;TRY AGAIN + TRNE WRITE,40 ;GIVE UP--DISTINGUISH BETWEEN + JSR ECWR,ERROR ;WRITE ERRORS AND + JSR ECRD,ERROR ;READ ERRORS + +WRDX: DPB BLOK,[XWBLK XWDS] ;PNTR TO PREV BLOCK + LDB UNIT,[DCCA DBLK+1] ;RESTORE ADR + TRZ WRITE,-1 ;FLUSH GARBAGE + JRST (TT) + +DBLK: DREAD+DUNENB + DCOPY .(-2000_2&37774) + DCOPY XWDS(-4_2&37774) +DBLK1: DRC + DCOPY .(-2000_2&37774) + DCOPY XWDS(-4_2&37774) + DHLT + +GPKID: DSPC+DSCRHD+DSWIDX+DSWNUL+DUNENB+TUTCYL_11.+TUTSRF_6+TUTSEC + DCOPY RPKID(37774) + DHLT +];SC + +;JSP P,TYI RETURNS CHAR IN C. +;JSP P,TYI0 ALSO SKIPS IF NO INPUT AVAILABLE. +TYI: ILDB C,MEMSIZ-1 ;CHECK FOR COMMANDS FROM MEMORY + JUMPN C,(P) ;FOUND ONE--RETURN + CLEARM MEMSIZ-1 +TYI0: ;ENTRY TO SKIP IF NO INPUT AVAILABLE +KA,[ CONSO TTY,40 + JRST TYI1 + DATAI TTY,C +] +KS,[ SKIPN C,8CTYIN + JRST TYI1 + ANDI C,177 + SETZM 8CTYIN +] +KL,[ MOVEI C,3400 ;DDT MODE INPUT + SETZM DTEFLG + MOVEM C,DTECMD + CONO DTE,%DBL11 + SKIPN DTEFLG + JRST .-1 + MOVE C,DTEF11 + SETZM DTEFLG + JUMPE C,TYI1 +] ANDI C,177 + CAIGE C,175 + CAIN C,33 + JRST (P) ;DON'T ECHO GRITCHES +;DROP INTO TYO + +;JSP P,TYO TYPES OUT CHAR IN C. CLOBBERS A,C. +TYO: ;SKIPE MEMSIZ-1 + ; JRST (P) ;DON'T ECHO COMMANDS FROM MEMORY +KA,[ HRRZ A,C ;COMPUTE PARITY + IMULI A,40201 + AND A,[1111111] + IMUL A,[1111111] + TLNE A,1 + IORI C,200 + CONSZ TTY,20 + JRST .-1 + DATAO TTY,C + ANDCMI C,200 +] +KS,[ MOVE A,C + ANDI A,177 + TRO A,400 + MOVEM A,8CTYOT + CONI A + IORI A,80INT + CONO (A) + SKIPE 8CTYOT + JRST .-1 +] +KL,[ MOVE A,C + ANDI A,177 + SETZM DTEFLG + MOVEM A,DTECMD + CONO DTE,%DBL11 + SKIPN DTEFLG + JRST .-1 + SETZM DTEFLG +] + JUMPGE C,(P) ;CHECK FOR CRLF (AS OPPOSED TO ECHOING A CR) + SKIPA C,C12 ;TYPE AN LF +CRLF: HRROI C,15 + JRST TYO + +TYI1: HRRZ C,-1(P) ;NO INPUT AVAILABLE + CAIE C,TYI0 + JRST TYI ;WAIT FOR IT + JRST 1(P) ;CALL WAS TO TYI0, SKIP RETURN + +LINK: CAIE CMD,'D + CAIN CMD,'K + MOVSI WRITE,-1 ;MAKE THIS INFO MORE CONVENIENT + MOVE D,[440600,,C] + MOVEI T,0 +LINKL: ILDB TT,DIRPT + SKIPGE WRITE + DPB T,DIRPT ;CLOBBER CHARS READ FOR DUMP OR KILL + CAIN TT,'; + JRST LINKN + CAIN TT,': + JRST LINKQ + JUMPE TT,LINKN +LINKQ1: IDPB TT,D + TLNE D,770000 + JRST LINKL +LINKN1: CAMGE D,[600,,B] ;THROUGH WITH FN2? + JRST LINKL + JUMPL WRITE,KILL1 + MOVEM A,FN1 + MOVEM B,FN2 + JRST MLOOK2 + +LINKN: TLNN D,770000 + JRST LINKN1 + IDPB T,D ;FILL OUT WITH SPACES + JRST LINKN + +LINKQ: ILDB TT,DIRPT + JUMPGE WRITE,LINKQ1 + DPB T,DIRPT + JRST LINKQ1 + +READ: MOVEI BLKIN,CORE + JSP P,CRLF + MOVEI CMD,0 ;INITIALIZE COMMAND +READ1A: MOVEI WRITE,0 ;INITIALIZE NUMBER + MOVSI B,(SIXBIT \@\) ;INITIALIZE 1ST FILE NAME +READ1: MOVEM B,FN1 +READ3A: MOVSI B,(SIXBIT \@\) ;INITIALIZE CURRENT FILE NAME + MOVE D,[440600,,B] +READ2: JSP P,TYI + CAIN C,177 + JRST READ ;IF RUBOUT START OVER + CAIGE C,175 + CAIN C,33 + JRST ALTMOD ;JUMP IF 33, 175, 176 + ASH WRITE,3 ;DOES NOT CHANGE SIGN OF WRITE + CAIL C,"0 + CAILE C,"7 + TLOA WRITE,400000 ;NON-NUMERIC CHAR--MAKE WRITE NEGATIVE + ADDI WRITE,-"0(C) ;NUMERIC CHAR--ACCUMULATE NUMBER + CAIN C,"; + JRST READ3 ;SET SYSTEM NAME + CAIN C,40 + JRST READ1 ;SET FIRST FILE NAME + CAIN C,^Q + JSP P,TYI ;QUOTED CHARACTER + CAIGE C,140 ;CHECK FOR LOWER CASE + SUBI C,40 + JUMPL C,DOIT ;IF LESS THAN 40 (EXC. ^Q) END OF COMMAND + TLNE D,770000 ;SKIP IF ALREADY SIX CHARS + IDPB C,D + JRST READ2 + +READ3: MOVEM B,SYSN + CAIE CMD,'U + JRST READ3A + JRST DOIT ;IF COMMAND IS U GO LIST DIRECTORY + +ONOFF: CAIGE WRITE,NDSK + DPB CMD,[100,,QDED(WRITE)] ;LOW BIT OF CMD DETERMINES ON/OFF LINE STATUS + JRST READ ; (K=13, L=14) + +ALT1: LDB CMD,D ;PICK UP COMMAND CHAR + CAIE CMD,'K + TRNN CMD,2 + JRST READ1A ;GET FILE NAME + JRST DOIT ;DON'T WANT FILE NAME--GO TO WORK + +ALTMOD: MOVEI C,"$ + JSP P,TYO ;ECHO DOLLAR SIGN + JUMPLE WRITE,ALT2 ;JUMP IF NOT LAST TYPED + JUMPN CMD,ONOFF ;JUMP IF + HRRM WRITE,SADR ;SET STARTING ADDR + JRST READ + +ALT2: TLC D,360000 + TLCN D,360000 ;SKIP IF SINGLE CHARACTER BEFORE + JUMPE CMD,ALT1 ;JUMP IF NO COMMAND ALREADY TYPED +DOIT: MOVEM B,FN2 ;STORE SECOND FILE NAME + HRRZ B,MU + HRRM B,CU ;MAKE MASTER UNIT CURRENT UNIT + MOVNI WRITE,1 + JSP P,LODUMP ;DUMP OUT PSEUDO-CORE + CAIN CMD,'G + JRST LOADG0 ;GO + JSP TT,RDTUT + MOVE C,SYSN +MLOOK2: MOVSI WRITE,1 ;MAKE WRITE INDICATE LOAD + MOVEI BLOK,MFDBLK + MOVEI UNIT,DIR + JSP TT,RD ;READ MASTER DIRECTORY TO FIND WHERE USER DIRECTORY IS + MOVE T,DIR+MDCHK + CAME T,[SIXBIT/M.F.D./] + JSR EMFC,ERROR + MOVE T,DIR+MDNUDS + CAIE T,NUDSL + JSR EMFC,ERROR + CAIN CMD,'S + JRST LISTS ;LIST DISK ID'S AND SYSTEM NAMES + MOVE T,DIR+MDNAMP +MLOOK: CAMN C,DIR+MNUNAM(T) ;LOOK UP SYSTEM NAME + JRST MLOOK1 + ADDI T,LMNBLK + CAIGE T,2000 + JRST MLOOK + JSR ESNF,ERROR ;NOT FOUND + +MLOOK1: MOVEI BLOK,2*NUDSL-2000(T) ;CONVERT USER SLOT TO BLOCK NUMBER + LSH BLOK,-1 + HRRM BLOK,UDBLK ;REMEMBER FOR KILL OR DUMP + MOVEI UNIT,DIR + JSP TT,RDM ;READ USER DIRECTORY +ULOOK: CAME C,DIR+UDNAME + JSR ECDR,ERROR ;WRONG ONE?? + CAIE CMD,'F + CAIN CMD,'U + JRST LISTFC ;LIST USER DIRECTORY + MOVSI TT,UNIGFL + MOVE T,DIR+UDNAMP + MOVE A,FN1 + MOVE B,FN2 +ULOOK1: CAMN A,DIR+UNFN1(T) ;LOOK UP FILE NAME + CAME B,DIR+UNFN2(T) + JRST ULOOK2 + TDNN TT,DIR+UNRNDM(T) ;IS THIS FILE FOR REAL? + JRST ULOOK3 +ULOOK2: ADDI T,LUNBLK + CAIGE T,2000 + JRST ULOOK1 + CAIE CMD,'D ;IF NOT FOUND BETTER BE DUMP + JSR EFNF,ERROR + MOVE T,DIR+UDNAMP +ULOOK4: SKIPN DIR+UNFN1(T) ;FIND FREE SLOT FOR NEW FILE + JRST DUMP + ADDI T,LUNBLK + CAIGE T,2000 + JRST ULOOK4 + MOVNI T,LUNBLK ;NO FREE SLOTS--TRY TO EXTEND NAME AREA DOWN + ADDM T,DIR+UDNAMP + MOVE T,DIR+UDESCP + IDIVI T,6 + ADDI T,UDDESC + CAMGE T,DIR+UDNAMP ;DID WE RUN INTO DESCRIPTOR AREA? + JRST DUMP0 + JSR EDIR,ERROR ;YES + +ULOOK3: HRRM T,DMP4 ;IF FILE FOUND, SAVE SLOT NUMBER FOR DUMP + LDB C,[UNDSCP DIR+UNRNDM(T)] + JSP TT,GBP + MOVEM C,DIRPT ;SET UP DESCRIPTOR AREA BYTE POINTER + MOVSI TT,UNLINK + TDNE TT,DIR+UNRNDM(T) + JRST LINK ;FILE IS A LINK + LDB A,[UNPKN DIR+UNRNDM(T)] +ULOOK5: CAMN A,TUT+QPKNUM ;SEE IF IT'S MOUNTED + JRST LOAD + JSP TT,NXTTUT + JRST ULOOK5 + JSR EPNM,ERROR + +LOAD: CAIE CMD,'D ;GET HERE IF FILE FOUND + CAIN CMD,'K ;IF DUMP OR KILL, DELETE IT + JRST KILL +ZERO: MOVEI TT,CORE-1 + TRNN CMD,20 ;SKIP IF T$ SYMBOL LOADING COMMAND + JRST ZERO1 + MOVEI B,DDT-1 ;ASSUME ALWAYS USING MOBY DDT + JSP P,FD ;GET DDT'S SYMBOL TABLE POINTER + JSR EDDT,ERROR ;CAN'T GET IT?? + HRROS B,(C) ;TELL DDT ITS SYMBOL TABLE WAS BUGGERED + CAME B,[-1,,DDT-2] ;VERIFY THAT IT'S REALLY A MOBY DDT LIKE WE THOUGHT + JSR EDDT,ERROR + SKIPE D,-2(C) ;FLUSH ALL BUT INITIAL SYMBOLS + MOVEM D,-1(C) + MOVE D,-1(C) + MOVEI TT,CORE-1 + CAILE TT,-1(D) + MOVEI TT,-1(D) ;DON'T ZERO SYMBOL TABLE NOR DDT +ZERO1: TRNE CMD,1 + JRST LOAD1 ;NON-ZEROING COMMAND + SETZM 40 ;BEGIN CLEARING CORE + MOVE T,[40,,41] ;SET UP BLT POINTER +;CODE TO SKIP OVER NXM +ZERO2: CAIG TT,10*2000-1(T) ;MORE THAN 8K LEFT TO ZERO? + JRST ZERO4 ;NO, ZERO REMAINING WORDS AND PROCEED + MOVE D,T ;AVOID KA/KL INCOMPAT BY COPYING BLT PNTR + BLT D,10*2000-1(T) ;ZERO NEXT 8K +ZERO3: ADDI T,10*2000 ;MOVE DEST OF BLT PNTR UP 8K + ANDCMI T,1777 ;ROUND DOWN TO 1K BOUNDARY +KA, CONO 10000 ;CLEAR NXM + MOVES (T) ;SET NXM IF HOLE +KA, CONSZ 10000 ;NXM GENERATED? +KA, JRST ZERO3 ;YES, GO TO NEXT 8K + JRST ZERO2 ;NO, CLEAR THIS 8K + +ZERO4: BLT T,(TT) ;AND CLEAR TO TOP BOUNDARY + TRNE CMD,20 + JRST LOAD1 ;IF SYMBOL-LOADING COMMAND, STOP THERE + CLEARM CBUF + MOVE T,[CBUF,,CBUF+1] + BLT T,CBUF+1777 + MOVEI UNIT,CBUF + MOVE BLOK,CBLK ;-NSWBL IN LH + JSP TT,WRM ;CLEAR PSEUDO-CORE + AOBJN BLOK,.-1 +LOAD1: SETZB BUFP,BLKCNT ;SET UP BUFP SO FIRST CALL TO WD WILL READ +LOAD2: JSP P,WD ;FIRST BLOCK OF FILE + CAME D,[JRST 1] ;LOOK FOR END OF SBLK LOADER + JRST LOAD2 + CAIN CMD,'I ;IF VERIFY, START SIMULATING DUMP + JRST DUMP.5 +LOAD3: JSP P,WD ;READ BLOCK HEADER + JUMPGE D,LOADS ;IT'S A JUMP BLOCK + MOVE A,D + MOVE B,D + JSR LOADB ;LOAD LOGICAL BLOCK INTO CORE + JRST LOAD3 + +LOADB: 0 +LOAD4: JSP P,WD ;LOAD A LOGICAL BLOCK--AOBJN POINTER IN B, + ROT A,1 ;BLOCK HEADER IN A (FOR CHECKSUM) + ADD A,D ;ADD NEW WORD INTO CHECKSUM + JSP P,FD ;AND PREPARE TO SMASH IT AWAY + JRST .+2 ;LOCATION CAN'T BE LOADED + MOVEM D,(C) ;SMASH WORD AWAY + AOBJN B,LOAD4 + JSP P,WD + CAMN A,D ;CHECK THE CHECKSUM + JRST @LOADB + JSR ECKS,ERROR ;BAD CHECKSUM + +LOADS: CAIN CMD,'M + JRST LOADG0 ;DON'T LOAD SYMBOLS NOR SADR + MOVEM D,NXTBW3 ;SAVE S.A. + MOVEI B,DDT-1 ;ASSUME IS ALWAYS MOBY DDT. + JSP P,FD ;GET DDT'S SYMBOL TABLE POINTER + JSR EDDT,ERROR ;CAN'T GET IT?? + SKIPN (C) + JRST LOADJ ;AIN'T GOT NO DDT, IGNORE SYMBOLS + HRROS B,(C) ;TELL DDT ITS SYMBOL TABLE WAS BUGGERED + CAMN B,[-1,,DDT-2] ;VERIFY THAT IT'S REALLY A MOBY DDT LIKE WE THOUGHT + JSP P,FD ;FETCH SYMBOL TABLE POINTER + JSR EDDT,ERROR + MOVE D,(C) + MOVEM D,DDTM2 +LOADS1: MOVE B,DDTM2 ;GET LOWEST SYMBOL LOC SO FAR + JSP P,WD ;GET SYMBOL BLOCK HEADER + JUMPGE D,LOADS2 ;JUMP IF END OF SYMBOLS + TRNE D,-1 ;SKIP IF REALLY SYMBOLS AND NOT SOME OTHER BRAIN-DAMAGED CRUFT + JRST LOADBD + MOVSS D + HRLI D,-1(D) + ADD B,D ;EFFECTIVELY SUBTRACTS LENGTH OF BLOCK FROM BOTH HALVES + MOVEM B,DDTM2 ;OF SYMBOL TABLE POINTER + HRL B,D ;SET UP AOBJN POINTER IN B + HRLZ A,D ;AND RECREATE HEADER IN A + JSR LOADB ;LOAD THE SYMBOLS + JRST LOADS1 + +LOADBD: HLRO B,D ;-# WORDS TO SKIP (NOT COUNTING CHECKSUM) + JSP P,WD + AOJLE B,.-1 + JRST LOADS1 ;TRY NEXT SYMBOL BLOCK + +LOADS2: MOVE D,DDTM2 ;GET UPDATED DDT SYMBOL PNTR +LOADS4: MOVEI B,DDT-2 ;WE KNOW WHERE IT ALWAYS GOES + JSP P,FD ;PUT BACK SYMBOL TABLE POINTER + JSR EBUG,ERROR ;CAN'T PUT IT BACK?? + MOVEM D,(C) + MOVEI B,DDT-4 ;GIVE STARTING ADDRESS TO DDT + JSP P,FD + JSR EBUG,ERROR + MOVE D,NXTBW3 + MOVEM D,(C) + MOVEI D,DDT ;AND SET DSKDMP START ADDRESS TO DDT +LOADJ: HRRM D,SADR ;SET STARTING ADDRESS FROM JUMP BLOCK +LOADG0: MOVE T,BOOTNS ;APPROP DISK WAIT FOR NON BUSY INSTR + MOVEM T,BOOT +LOADG: JSP TT,WRCB ;MAKE SURE ALL LOADED CRUFT IN PSEUDO-CORE IS OUT + MOVEI WRITE,0 + JSP P,LODUMP ;AND LOAD IT ALL IN + TRNE CMD,10 + JRST READ ;NON-GOING COMMAND +GO: +PH,[ MOVSI B,-LSWPADR +GO1: IORD DIFF,SWPCS1 + TRNN DIFF,%HXRDY ; Wait for controller + JRST GO1 + HRRZ DIFF,SWPVAL(B) + IOWR DIFF,SWPADR(B) + AOBJN B,GO1 +];PH +RH,[ MOVE B,ERRWD + CONI DSK,HEAD + TLNE HEAD,(%HID22) + HRLI B,-1700_4 + MOVEM B,@ICWA + MOVSI B,-6 +GO1: CONSZ DSK,%HIBSY + JRST .-1 + MOVE DIFF,SWPOU1(B) + JSP HEAD,RHSET + AOBJN B,GO1 +];RH +RP,[ MOVE B,ERRWD + MOVEM B,@ICWA + DATAO DPC,SWPSK + JSP P,SKWAIT + DATAO DPC,SWPOU1 + CONSO DPC,DONE + JRST .-1 + DATAO DPC,SWPOU2 +];RP +SC, DATAO DC0,[DJMP SWPOUT] + JRST WAIT + +LISTS: JSP P,CRLF +LISTS2: JSP P,TYI0 + JRST LOADG1 ;SHUT UP IF KEY HIT + MOVE C,TUT+QPKNUM ;TYPE PACK NUMBER + JSP TT,PNO + MOVE D,TUT+QPAKID ;AND I.D. + JSP TT,PD2 + JSP TT,NXTTUT ;SAME FOR ALL DIRECTORIES + JRST LISTS2 + MOVE T,DIR+MDNAMP +LISTS1: CAIGE T,2000 + JSP P,TYI0 ;STOP TYPING IF TTI FLAG ON + JRST LOADG1 + SKIPE D,DIR+MNUNAM(T) + JSP TT,PD ;TYPE OUT USER NAME + ADDI T,LMNBLK + JRST LISTS1 + +LISTFC: MOVE T,DIR+UDNAMP +LISTF1: +KA, CONSO TTY,40 ;STOP TYPING IF TTI FLAG ON +KS, SKIPN 8CTYIN ; Stop typing if character waiting + CAIL T,2000 + JRST LOADG1 + SKIPN DIR+UNFN1(T) ;SKIP IF FILE IN THIS SLOT + JRST LISTF2 + JSP P,CRLF + LDB C,[UNPKN DIR+UNRNDM(T)] + JSP TT,PNO ;TYPE PACK NUMBER + MOVE D,DIR+UNFN1(T) + JSP TT,PD2 ;TYPE FIRST FILE NAME + MOVE D,DIR+UNFN2(T) + JSP TT,PD2 ;AND SECOND FILE NAME +LISTF2: ADDI T,LUNBLK + JRST LISTF1 + +KILL: JSP TT,NXTB6 ;GET HERE ON KILL OR DUMP OF EXISTING FILE + MOVEI T,0 ;ZERO BYTES IN USER DIRECTORY DESCIPTOR AREA + DPB T,DIRPT ;NXTB6 JUMPS TO KILL1 AT END OF FILE + MOVE C,BLOK + JSP TT,GTP + ILDB T,C + CAIGE T,TUTLK-1 ;SOS USAGE OF THIS BLOCK + SOJL T,[JSR ECDR,ERROR] + DPB T,C + JRST KILL + +KILL1: HRRZ T,DMP4 ;CLEAR OUT USER DIRECTORY SLOT + CLEARM DIR+UNFN1(T) + CLEARM DIR+UNFN2(T) + CLEARM DIR+UNRNDM(T) + MOVSI WRITE,-1 + CAIN CMD,'K + JRST KILDMP ;IF KILL DON'T DUMP + JRST DMP4 ;MUST DUMP ON SAME UNIT + +DUMP0: MOVE T,DIR+UDNAMP ;GET HERE IF SLOT CREATED AT BOTTOM OF NAME AREA +DUMP: HRRM T,DMP4 ;GET HERE IF EMPTY SLOT FOUND IN NAME AREA +DMP0: MOVEI D,0 ;GET HERE IF USING SLOT OF OLD FILE +DMP1: ;MOVE C,TUT+QSWAPA + MOVEI C,0 ;NOTE START AT 0 NOT QSWAPA + MOVE B,C + SUB B,TUT+QLASTB + HRLZ B,B ;LH(B) COUNTS BLOCKS, RH(B) COUNTS FREE BLOCKS + JSP TT,GTP +DMP2: ILDB T,C + SKIPE T +KA, SUBI B,1 ;THIS RELIES ON CARRY PROPAGATING FROM RH TO LH IN AOBJN +KL, HRRI B,-1(B) ;ON KI10, KL10 CHANGE SUBI B,1 TO HRRI B,-1(B) +KS, HRRI B,-1(B) ;KS too... + AOBJN B,DMP2 + CAIG B,(D) ;RH OF D IS HIGHEST SO FAR, LH SAYS WHICH UNIT + JRST DMP5 ;NOT BETTER THAN RECORD + MOVE D,B ;NEW RECORD--RECORD IT + HRL D,CU +DMP5: JSP TT,NXTTUT ;TRY NEXT + JRST DMP1 + ;FALLS THROUGH AT END +DMP3: HLRM D,CU ;SET CURRENT UNIT TO ONE WITH MOST FREE BLOCKS + JSP TT,RDTUT ;GET ITS TUT +DMP4: MOVEI T,. + MOVE A,FN1 + MOVE B,FN2 + MOVEM A,DIR+UNFN1(T) ;PUT CRUFT INTO SLOT + MOVEM B,DIR+UNFN2(T) + SETOM DIR+UNDATE(T) ; Unknown creation date + HRROI C,777000 ; Unknown reference date + MOVEM C,DIR+UNREF(T) ; Unknown author, 36. bit bytes +SC,[ MOVEM A,XWDS+XWFN1 + MOVEM B,XWDS+XWFN2 + MOVE C,SYSN + MOVEM C,XWDS+XWSYSN +] MOVE C,DIR+UDESCP ;PUT DESCRIPTOR CHARACTER ADDRESS + MOVE B,TUT+QPKNUM ;AND PACK NUMBER + DPB B,[UNPKN C] + MOVEM C,DIR+UNRNDM(T) ;INTO USER DIRECTORY SLOT + ;MOVE C,TUT+QSWAPA ;COMMENTED OUT INSN DUMPS INTO FILE AREA + MOVEI C,0 ;DUMP INTO SWAPPING AREA TO AVOID Y FILES + MOVEM C,LBLOCK ;A DAEMON WILL COPY INTO FILE AREA AFTER SALVAGE + JSP TT,GTP + MOVEM C,TUTPT ;INITIALIZE TUT POINTER + MOVE C,DIR+UDESCP + JSP TT,GBP + MOVEM C,DIRPT ;INITIALIZE DESCRIPTOR AREA POINTER + SETOB WRITE,BLKCNT ;FORCE NXTBW TO LOAD ADR +KA, HRLOI BUFP,-2001-1 ;SET UP BUFP SO FIRST WORD GOES IN DBUF+0 +KL, HRLOI BUFP,-2001 +KS, HRLOI BUFP,-2001 + MOVE D,[JRST 1] + JSP P,WD ;END OF SBLK LOADER +;DROPS THROUGH + +;DROPS IN +DUMP.5: MOVSI WRITE,-'I(CMD) ;GET HERE IF VERIFY--SET WRITE NEGATIVE IF + MOVEI B,40 ;DUMP AND ZERO IF VERIFY--FIRST ADDR DUMPED IS 40 + HRRM B,DUMP4 + HLLOS DUMP6 + SETZM DUMP9S + SETZM DUMP9J + SETZM DUMP9K + MOVEI B,DDT-3 ;SET UP TO NOT DUMP SYMBOLS AS PART OF CORE IMAGE + JSP P,FD + JSR EBUG,ERROR + SKIPN A,(C) ;GET PNTR TO BUILT IN SYMBOLS + JRST DUMP4 ;NO DDT, DON'T HACK THIS + HRRM A,DUMP7 ;THIS IS WHERE WE START DUMPING AGAIN + MOVEM A,DUMP9K ;THIS WILL BE INITIAL SYMBOL TABLE PNTR WHEN DDT LOADED + MOVNI A,(A) + ADD A,1(C) ;GET MINUS SIZE OF NON-BUILTIN SYMBOL TABLE IN RH(A) + HRL A,1(C) ;GET PNTR TO SYMBOL TABLE + HLRM A,DUMP6 ;THIS IS WHERE WE STOP DUMPING + MOVSM A,DUMP9S ;SAVE AOBJN PNTR TO NON-BUILTIN SYMBOLS + MOVE A,-1(C) ;PICK UP START ADDRESS + MOVEM A,DUMP9J ;SAVE + MOVE B,-2(C) ;DUMP LOW CORE (ACS) OUT OF PLACE SAVED IN DDT + HLLZ A,B ;HERE B HAS ADDRESS DUMPING FROM + JRST DUMP3B ;AND A AND D HAVE VIRTUAL ADDRESS + +DUMP1: ;SKIP OVER NXM ON DUMPING +KA,[ CONSO 10000 ;NXM SET? + JRST DUMP1A ;NO, CONTINUE IN SEQUENCE + ADDI B,10*2000-1 ;SKIP 8K + TRZ B,1777 ;ROUND DOWN TO 8K BOUDARY + CONO 10000 ;CLEAR NXM +DUMP1A: +];KA +DUMP6: CAIGE B,. ;SKIP IF REACHED SYMBOL TABLE + JRST DUMP8 +DUMP7: MOVEI B,. ;SKIP OVER SYMBOLS, DUMP DDT + HLLOS DUMP6 ;DEFUSE TEST +DUMP8: JSP P,FD + JRST DUMPJ ;TIME TO WRITE JUMP BLOCK AND SYMBOL TABLE + SKIPN (C) ;LOOK FOR NON-ZEROES + AOJA B,DUMP1 + MOVE A,B ;SAVE START OF BLOCK +DUMP2: TLZ A,-1 ;LOOK FOR TWO CONSECUTIVE ZEROES +DUMP2A: CAIL B,200(A) ;BUT DON'T DUMP MORE THAN 200 WORDS AT A TIME + JRST DUMP3 + XCT DUMP6 + JSP P,FD + JRST DUMP3 ;END OF CORE, WRITE OUT LAST BLOCK + SKIPE (C) + AOJA B,DUMP2 ;NONZERO + TLON A,-1 ;ZERO, WAS PREV LOC ZERO ALSO? + AOJA B,DUMP2A ;NO, CHECK FOLLOWING LOC + SOJA B,DUMP3 ;YES, DUMP THE NON-ZERO THAT PRECEDES IT + +DUMP3: HRRM B,DUMP4 ;SAVE ADDRESS TO CONTINUE SEARCH + SUBM A,B ;RH(B) GETS MINUS THE LENGTH OF THE BLOCK + HRL A,B ;SET UP HEADER IN A + MOVE B,A ;AND B +DUMP3B: MOVE D,A ;AND D + JSP P,WD ;WRITE HEADER +DUMP3A: JSP P,FD + JSR EBUG,ERROR ;CAN'T FETCH WORD WE FETCHED BEFORE?? + MOVE D,(C) + ROT A,1 + ADD A,D ;COMPUTE CHECKSUM + JSP P,WD ;WRITE DATA WORD + AOBJN B,DUMP3A + MOVE D,A + JSP P,WD ;WRITE OUT CHECKSUM +DUMP4: MOVEI B,. ;AND CONTINUE SEARCHING + JUMPN B,DUMP1 ;IF MRC EVER SEES THIS --SELFMODIFYING CODE-- .... + JRST DUMP9 ;FINISHED DUMPING SYMBOLS + +DUMPJ: SKIPN DUMP9K + JRST DMP9J1 + HRROI D,DDT-2 ;BUGGER THE SYMBOL TABLE + MOVE A,D + JSP P,WD + MOVE D,DUMP9K + ROT A,1 + JSP P,WD + ADD D,A + JSP P,WD +DMP9J1: SKIPN D,DUMP9J + MOVE D,SADR + JSP P,WD ;WRITE OUT JUMP BLOCK + SKIPN B,DUMP9S ;WRITE SYMBOLS + JRST DUMP9 ;NO SYMBOLS + HLLZ A,B + HLLZS DUMP4 ;DUMP SYMBOL BLOCK, RETURN TO DUMP9 + JRST DUMP3B + +DUMP9: JUMPE WRITE,LOADG1 ;IF VERIFY, THAT'S ALL + SKIPN D,DUMP9J + MOVE D,SADR + JSP P,WD ;SECOND JUMP BLOCK + HRRZ T,DMP4 ; GET POINTER TO NAME AREA + AOS BUFP + DPB BUFP,[UNWRDC+DIR+UNRNDM(T)] + JSP TT,NXTBLK + JSP TT,WRDB ;WRITE OUT LAST BLOCK + SKIPE T,BLKCNT + JSR NXTBW3 ;STORE LAST DESCRIPTOR BYTE + MOVEI T,0 + JSR NXTBW3 ;AND INDICATE END OF FILE + LDB T,[360600,,DIRPT] + IDIVI T,6 + HRRZ TT,DIRPT + IMULI TT,6 + SUBI TT,6*-5-1(T) + HRRZM TT,DIR+UDESCP ;INDICATE NEW END OF DESCRIPTOR AREA +KILDMP: MOVEI UNIT,TUT + MOVEI BLOK,TUTBLK + JSP TT,WRD ;WRITE OUT TUT ON THIS UNIT +REPEAT NTUTBL-1,[ + ADDI UNIT,2000 + ADDI BLOK,1 + JSP TT,WRD +] + HRRZ B,CU + HRRM B,KD2 ;WRITE OUT USER DIRECTORY ON ALL UNITS +KD1: ADDI B,1 + CAIN B,NDSK + MOVEI B,0 + HRRM B,CU + SKIPE QDED(B) + JRST KD2 + MOVEI UNIT,DIR +UDBLK: MOVEI BLOK,. + MOVE TT,DIR+UDNAME + CAME TT,SYSN + JSR EBUG,ERROR + JSP TT,WR +KD2: CAIN B,. + JRST LOADG1 + JRST KD1 + +GTP: SKIPGE TUT+QPKNUM + JSR EBUG,ERROR ;MUST BE OLD-STYLE TUT? + SUB C,TUT+QFRSTB + JUMPL C,[JSR EBUG,ERROR] + IDIVI C,TUTEPW + IMULI A,-10000*TUTBYT + HRLI C,440000+TUTBYT_6(A) + ADDI C,TUT+LTIBLK + JRST (TT) + +SC,[ ;LOGICAL TO PHYSICAL DISK MAPPING +QTRAN: 0 ;INDEX BY LOG DSK # + 1 ;4.9 => USE HIGH HALF OF DRIVE, RH = PHYS DRIVE # + 2 ;(NO LONGER DOES ANYTHING, NOW THAT MEMOWRECKS ARE GONE, + 3 ; BUT KEEP AROUND JUST IN CASE EVER NEEDED AGAIN.) + 4 + 5 + 6 + 7 +IFL .-QTRAN-NDSK,.ERR QTRAN LOSES!! +];SC + +ERRCT: 0 ;ERROR COUNTER +DDTM2: 0 ;DDT SYMBOL TABLE POINTER +DUMP9J: 0 ;START INSTRUCTION (AT DUMP9) +DUMP9S: 0 ;SYMBOL TABLE POINTER (AT DUMP9) +DUMP9K: 0 ;INITIAL SYMBOL TABLE PNTR (AT DUMP9) +LBLOCK: 0 ;LAST BLOCK WRITTEN OR READ +BLKCNT: 0 ;NUMBER OF BLOCKS READ OR WRITTEN CONSECUTIVELY +DIRPT: 0 ;DESCRIPTOR AREA BYTE POINTER +TUTPT: 0 ;TUT BYTE POINTER +FN1: 0 ;FILE NAME 1 +FN2: 0 ;FILE NAME 2 +PKNUM: REPEAT NDSK,-1 ;PACK NUMBER INDEXED BY DRIVE NUMBER +QDED: BLOCK NDSK ;-1 IF DRIVE NOT TO BE USED +XWDS: BLOCK 4 +RPKID: 0 +BOOTNS: RP, CONSZ DPC,BUSY + SC, CONSZ DC0,DSSACT + RH, CONSZ DSK,%HIBSY + PH, IORD B,SWPCS1 ; UGH! + + CONSTANTS + +IFL BEG+1677-., .ERR BLOAT +INFORM SPACE LEFT,\BEG+1677-. +BLOCK BEG+1677-. + +BADBLK: 0 ;BLOCK WITH HDWE ERROR +INFORM BADBLK,\.-1-BEG+ + +];END IFE BOOTSW +IFN BOOTSW,[ +BEG=MEMSIZ-2000 +LOC MEMSIZ-100 +] + +CBOOT: CLEARM MEMSIZ-1 ;BOOTSTRAP +RP,[ +BOOT: +IFE BOOTSW, JRST BEG ;OR CONSZ DPC,BUSY OR JRST LOADG1 +IFN BOOTSW, CONSZ DPC,BUSY + JRST .-1 + MOVEI B,ICWA+2 ;SET UP CHANNEL PROG + MOVEM B,ICWA + SETZM ICWA+1 + SETZM ICWA+3 + DATAO DPC,CLATT1 + DATAO DPC,SUNIT0 + DATAI DPC,B +BOOT0: TRNN B,RP03BT + JRST BOOT1 + MOVEI B,MBLKS ;UNIT 0 IS AN RP03, ADJUST WORLD + HRRM B,CBLK + MOVE B,RP3ADJ + MOVSI A,-NSWBL + XORM B,SWPSK(A) + AOBJN A,.-1 +BOOT1: HLLZS BOOT0 ;PREVENT TRNN FROM SKIPPING AGAIN + MOVE B,ERRWD + MOVEM B,@ICWA + DATAO DPC,SWPSK + JSP P,SKWAIT + DATAO DPC,SWPIN1 + CONSO DPC,DONE + JRST .-1 + DATAO DPC,SWPIN2 + CONSO DPC,DONE + JRST .-1 + JRST BEG + +ERRWD: -1700,,BEG-1 +CLATT1: DEASEC ALLATT +SWPSK: DSEEKC+200._22. +SWPIN1: DWRITC+200._22.+3_17.+2._12.+ICWA ;NBLKS 4 +SWPIN2: DREADC+200._22.+4_17.+8._12.+ICWA +SWPOU1: DWRITC+200._22.+4_17.+8._12.+ICWA +SWPOU2: DREADC+200._22.+3_17.+2_12.+ICWA +IFN NSWBL-5, .ERR THE PRECEDING 4 CONSTANTS ARE WRONG! +CBLK: -NSWBL,,NBLKS ;DISK ADDR OF CORE BUFFER, - # BLOCKS IN LH +RP3ADJ: <&377>_22.+<.BM DCYLXB> +SUNIT0: DNOOPC + +SKWAIT: DATAI DPC,A ;AWAIT SEEK DONE UNIT 0 + TRNN A,ALLATT + JRST SKWAIT + DATAO DPC,CLATT1 + MOVEI A,30. + SOJG A,. + DATAI DPC,A + TLNN A,(ONCYL) + JRST SKWAIT + JRST (P) + +WAIT: CONSO DPC,DONE + JRST .-1 +];RP + +PH,[ ;; Initially we could not use IORDQ or IOWRQ because they were + ;; macros that used a literal. There is nothing to stop us now, + ;; except the fact that this code works fine and is as small as you + ;; could possibly want. + +BOOT: +IFE BOOTSW, JRST BEG ; or IORD B,SWPCS1 or JRST LOADG1 +IFN BOOTSW, IORD B,SWPCS1 + TRNN B,%HXRDY + JRST BOOT +KS, WREBR 0 ; No paging or caching + MOVEI A,0 + IOWR A,SWPCS2 ; Select drive +BOOT0: IORD A,SWPCS1 + TRNN A,%HXDVA + JRST BOOT0 ; Await drive available + MOVSI B,-LSWPADR +BOOT1: HLRZ A,SWPVAL(B) + IOWR A,SWPADR(B) +BOOT2: IORD A,SWPCS1 + TRNN A,%HXRDY ; Wait for controller + JRST BOOT2 + TRNE A,%HXTRE+%HXMCP ; Lossage? + JRST 4,. ; Foo! + AOBJN B,BOOT1 + JRST BEG + +ZZ1==*SECBLK ;BLOCK CONTAINING CORE SWAPPED OUT TO BRING DSKDMP IN +ZZ2==*SECBLK ;DSKDMP RESIDENCE BLOCK +ZZ3==ZZ1/NSECS +ZZ4==ZZ2/NSECS +ZZ1==ZZ3*400+ ;CONVERT ADDR TO DISK FORMAT +ZZ2==ZZ4*400+ + +SWPADR: UBAQ,,UBAPAG+UBPG_1 ; Set up Unibus map + UBAQ,,UBAPAG+UBPG_1+1 + UBAQ,,%HRCS2 ; Clear controller +SWPCS2: UBAQ,,%HRCS2 ; Select drive +SWPCS1: UBAQ,,%HRCS1 ; Initialize + UBAQ,,%HRCYL ; Desire cylinder + UBAQ,,%HRWC ; Set (half) word count + UBAQ,,%HRBA ; Set Unibus address + UBAQ,,%HRADR ; Desire track and sector + UBAQ,,%HRCS1 ; Write + UBAQ,,%HRWC ; Reset (half) word count + UBAQ,,%HRBA ; Reset Unibus address + UBAQ,,%HRADR ; Desire track and sector + UBAQ,,%HRCS1 ; Read +LSWPADR==:.-SWPADR + +IFN BEG&1777, .ERR BEG does not lie on a page boundary? + +;;; LH FOR SWAP IN, RH FOR SWAP OUT +SWPVAL: %UQVAL+%UQFST+BEG_-9,,%UQVAL+%UQFST+BEG_-9 ; Set up Unibus map + %UQVAL+%UQFST+BEG_-9+1,,%UQVAL+%UQFST+BEG_-9+1 + %HYCLR,,%HYCLR ; Clear controller + 0,,0 ; Select drive + %HMRDP,,%HMRDP ; Initialize + NCYLS,,NCYLS ; Desire cylinder + -1700*2,,-1700*2 ; Set (half) word count + UBPG_14,,UBPG_14 ; Set Unibus address + ZZ1,,ZZ2 ; Desire track and sector + %HMWRT,,%HMWRT ; Write + -1700*2,,-1700*2 ; Reset (half) word count + UBPG_14,,UBPG_14 ; Reset Unibus address + ZZ2,,ZZ1 ; Desire track and sector + %HMRED,,%HMRED ; Read +IFN .-SWPVAL-LSWPADR, .ERR SWPVAL wrong length. + +CBLK: -NSWBL,,NBLKS + +WAIT: IORD B,SWPCS1 + TRNN B,%HXRDY + JRST WAIT +];PH + +RH,[ +BOOT: +IFE BOOTSW, JRST BEG ;OR CONSZ DSK,%HIBSY OR JRST LOADG1 +IFN BOOTSW, CONSZ DSK,%HIBSY + JRST .-1 +KL, CONSZ PAG,660000 ;PAGING AND CACHE MUST BE DISABLED +KL, JRST 4,. + MOVEI B,ICWA+2 ;SET UP CHANNEL PROG + MOVEM B,ICWA + SETZM ICWA+1 + SETZM ICWA+3 +BOOT0: DATAO DSK,[%HRDCL,,] + MOVEI A,20 + SOJG A,. + DATAI DSK,A + TRNN A,%HCDVA + JRST BOOT0 ;AWAIT DRIVE AVAILABLE + MOVE B,ERRWD + CONI DSK,A + TLNE A,(%HID22) + HRLI B,-1700_4 + MOVEM B,@ICWA + MOVSI B,-6 +BOOT1: DATAO DSK,SWPIN1(B) + MOVEI A,20 + SOJG A,. + CONSZ DSK,%HIBSY + JRST .-1 + AOBJN B,BOOT1 + CONSZ DSK,%HIERR + JRST 4,. + JRST BEG + +ZZ1==*SECBLK ;BLOCK CONTAINING CORE SWAPPED OUT TO BRING DSKDMP IN +ZZ2==*SECBLK ;DSKDMP RESIDENCE BLOCK +ZZ3==ZZ1/NSECS +ZZ4==ZZ2/NSECS +ZZ1==ZZ3*400+ ;CONVERT ADDR TO DISK FORMAT +ZZ2==ZZ4*400+ + +ERRWD: -1700,,BEG-1 +SWPIN1: %HRLOD+%HRDCL,,%HMRDP +SWPIN2: %HRLOD+%HRCYL,,NCYLS+1 ;AVOID CYLINDER 406 WHICH KLDCP USES +SWPIN3: %HRLOD+%HRADR,,ZZ1 +SWPIN4: %HRLOD+%HRCTL,,%HMWRT+ICWA_6 +SWPIN5: %HRLOD+%HRADR,,ZZ2 +SWPIN6: %HRLOD+%HRCTL,,%HMRED+ICWA_6 + +SWPOU1: %HRLOD+%HRDCL,,%HMRDP +SWPOU2: %HRLOD+%HRCYL,,NCYLS+1 ;AVOID CYLINDER 406 WHICH KLDCP USES +SWPOU3: %HRLOD+%HRADR,,ZZ2 +SWPOU4: %HRLOD+%HRCTL,,%HMWRT+ICWA_6 +SWPOU5: %HRLOD+%HRADR,,ZZ1 +SWPOU6: %HRLOD+%HRCTL,,%HMRED+ICWA_6 + +CBLK: -NSWBL,,NBLKS+NBLKSC ;AVOID CYLINDER 406 WHICH KLDCP USES + +WAIT: CONSO DSK,%HIDON + JRST .-1 +];RH + +SC,[ +BOOT: +IFE BOOTSW, JRST BEG ;OR CONSZ DC0,DSSACT OR JRST LOADG1 +IFN BOOTSW, CONSZ DC0,DSSACT + JRST .-1 + DATAO DC0,SWPINJ + CONSZ DC0,DSSACT + JRST .-1 + JRST BEG + +SWPINJ: DJMP SWPIN + +DADR==NCYLS_13+</2>_6+<&1> ;ADDR OF LAST BLOCK IN CORE BUFFER +DADR1==NCYLS_13+_6+ ;ADDR OF NEXT BLOCK (CONTAINS +SWPIN: DWRITE+DUNENB+DADR ; WORKING COPY OF DSKDMP) + DCOPY BEG(-2000_2&37774) + DCSKIP (-4_2&37774) + DRC+DADR + DCOPY BEG(-2000_2&37774) + DCSKIP (-4_2&37774) + DREAD+DADR1 + DCOPY BEG(-1700_2&37774) + DCSKIP (-104_2&37774) + DRC+DADR1 + DCOPY BEG(-1700_2&37774) + DCSKIP (-104_2&37774) + DHLT + +SWPOUT: DWRITE+DUNENB+DADR1 + DCOPY BEG(-2000_2&37774) + DCSKIP (-4_2&37774) + DRC+DADR1 + DCOPY BEG(-2000_2&37774) + DCSKIP (-4_2&37774) + DREAD+DADR + DCOPY BEG(-1700_2&37774) + DCSKIP (-104_2&37774) + DRC+DADR + DCOPY BEG(-1700_2&37774) + DCSKIP (-104_2&37774) + DHLT + +CBLK: -NSWBL,,NBLKS ;DISK ADDR OF CORE BUFFER, - # BLOCKS IN LH +WAIT: CONSZ DC0,DSSACT + JRST .-1 +];SC +SADR: JRST BOOT ;AND GO TO PROGRAM TO BE STARTED +SYSN: SIXBIT /./ ;CURRENT DIRECTORY +IFG .+1-MEMSIZ,.ERR BOOT BLOAT + +IFE BOOTSW,{ ;CURLY BRACKETS TO AVOID ERROR MESSAGE + OFFSET 0 + LOC CORE + +;THESE ARE THE BLOCKS THAT GET WRITTEN ON DISK +; STARTING AT THE BEGINNING OF THE FIRST EXTRA CYLINDER + +CBUF: BLOCK 2000 ;PSEUDO-CORE BUFFER +DBUF: BLOCK 2000 ;DISK BUFFER +DIR: BLOCK 2000 ;DIRECTORY BUFFER +TUT: BLOCK 2000*NTUTBL ;TUT BUFFER +IFN .-BEG,.ERR BLOCKS LOST +; BLOCK 2000 ;CORE OVERLAYED BY DSKDMP +; BLOCK 2000 ;COPY OF DSKDMP +; BLOCK 2000 ;SPARE COPY OF DSKDMP + +END ZZZ +};END IFE BOOTSW +IFN BOOTSW, END CBOOT diff --git a/src/system/dz11.10 b/src/system/dz11.10 new file mode 100755 index 00000000..b44c5ad0 --- /dev/null +++ b/src/system/dz11.10 @@ -0,0 +1,56 @@ +;-*-MIDAS-*- +; DZ11 definitions + +DZLNLN==3 +DZNLN==1_DZLNLN ;Number of DZ terminal lines per board +DZLNM==DZNLN-1 ;Line number mask given DZ number of TTY + +%DZLM==3400 ;Line Number Mask +%DZLS==8. ;Line number shift + +%DZRCS==0 ;Control & Status register +; CSR Bits and fields +%DZCMN==10 ;Maintenance +%DZCCL==20 ;Clear +%DZCMS==40 ;Master Scan Enable +%DZCRE==100 ;Receiver Interrupt Enable +%DZCRD==200 ;Receiver Done +%DZCSE==10000 ;Silo Alarm Enable +%DZCSA==20000 ;Silo Alarm +%DZCTE==40000 ;Transmitter Interrupt Enable +%DZCTR==100000 ;Transmitter Ready + +%DZRLP==2 ;Line Parameter register +; LPR Bits and fields +%DZLLM==7 ;Line number mask +%DZLCL==10 ;Character Length position +%DZLSC==40 ;Stop code bit +%DZLPY==100 ;Parity bit +%DZLOP==200 ;Odd parity +%DZLSP==400 ;Speed code position +%DZLSS==8. ;Speed code shift +%DZLRO==10000 ;Receiver on + +%DZRDR==2 ;Read Data register +; RDR Bits and fields +%DZDCM==377 ;Character mask +%DZDPE==10000 ;Parity Error +%DZDFE==20000 ;Frame Error (break key) +%DZDOR==40000 ;Overrun +%DZDDV==100000 ;Data valid + +%DZRTC==4 ;Transmitter Control & Data Terminal registers + +%DZRTD==6 ;Transmitter Buffer & Break registers +; TDR and BR fields +%DZTCM==377 ;Character mask +%DZTBM==177400 ;Break mask + +%DZRMS==6 ;Modem status +; MSR fields +%DZMRI==377 ;Ring detect +%DZMCD==177400 ;Carrier detect + +; To do: +; - Add modem control. + diff --git a/src/system/ept.defs16 b/src/system/ept.defs16 new file mode 100755 index 00000000..f8024ba4 --- /dev/null +++ b/src/system/ept.defs16 @@ -0,0 +1,160 @@ +IFN 0,[ +.AUXIL +] + +IF1,[ +.TYO6 .IFNM1 +.TYO 40 +.TYO6 .IFNM2 +PRINTX / included in this assembly. +/ +];IF1 + +IFNDEF DEFSYM,[ ;ALLOW USER TO USE SYMBOLS IN OTHER WAYS IF HE WISHES. + ;BUT NORMALLY, DEFSYM FOO==BAR DOES FOO==BAR WITH ERROR CHECK. +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ + $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` +] +.ISTOP +TERMIN TERMIN + +IFLE .MLLIT,.ERR .MLLIT MUST BE 1; SETTING IT TO 1. +.MLLIT==1 +$$TEMP==1 +] +.ELSE $$TEMP==0 + + + +IFNDEF EPT, EPT=1000 ;ABSOLUTE LOCATION OF EPT + ;LOCS 0-1777 UNCACHED + ;BUT THE HARDWARE CACHES EPT REFERENCES ANYWAY + +DEFSYM PI0LOC=EPT+40 ;PI0LOC+2*PICHN = ADDRESS OF INSTR PAIR FOR PICHN + +DEFSYM DTEBPO=EPT+140 ;DTE20 OUTPUT (BYTE TRANSFER) BYTE POINTER +DEFSYM DTEBPI=EPT+141 ;DTE20 INPUT (BYTE TRANSFER) BYTE POINTER +DEFSYM DTELOC=EPT+142 ;DTE20 INTERRUPT INSTRUCTION +DEFSYM DTEPRO=EPT+144 ;DTE20 OUTPUT (EXAMINE) PROTECTION WORD +DEFSYM DTERLO=EPT+145 ;DTE20 OUTPUT (EXAMINE) RELOCATION WORD +DEFSYM DTEPRI=EPT+146 ;DTE20 INPUT (DEPOSIT) PROTECTION WORD +DEFSYM DTERLI=EPT+147 ;DTE20 INPUT (DEPOSIT) RELOCATION WORD + +DEFSYM EPTCLK=EPT+510 ;DOUBLE WORD FOR CALENDAR CLOCK (TIME BASE) +DEFSYM EPTPRF=EPT+512 ;DOUBLE WORD FOR PERFORMANCE COUNTER +DEFSYM EPTEBC==EPT+504 ;DOUBLE WORD EBOX COUNT WHEN UPT=EPT +DEFSYM EPTMBC==EPT+506 ;DOUBLE WORD MBOX COUNT WHEN UPT=EPT +DEFSYM TIMLOC=EPT+514 ;INTERRUPT INSTRUCTION FOR INTERVAL TIMER + +DEFSYM EPTTR1=EPT+421 ;EXEC MODE ARITH OVFL TRAP +DEFSYM EPTTR2=EPT+422 ;EXEC MODE PDL OV TRAP +DEFSYM EPTTR3=EPT+423 ;EXEC MODE TRAP 3 (1 PROCEED) + +;UPT LOCATIONS - IN NON-TIME SHARING AND AT CLOCK LEVEL IN ITS UPT=EPT + +;424 MUUO STORED HERE +;425 MUUO PC STORED HERE +;426 MUUO DATAI PAG, HERE +;430 MUUO NEW PC KERNEL NO TRAP +;431 . . K T +;432 . . S N T +;433 . . S T +;434 . . C N T +;435 . . C T +;436 . . P N T +;437 . . P T +;500 PAGE FAIL WORD STORED HERE IN DEC PAGING MODE +;501 PAGE FAIL PC STORED HERE IN DEC PAGING MODE +;502 PAGE FAIL NEW PC FROM HERE IN DEC PAGING MODE +;504-5 EBOX COUNT +;506-7 MBOX COUNT + +DEFSYM EPTPFW=EPT+500 ;PAGE FAIL WORD STORED HERE IN ITS PAGING MODE +DEFSYM PFOPC=EPT+501 ;PAGE FAIL OLD PC STORED HERE IN ITS PAGING MODE +DEFSYM PFNPC=EPT+502 ;PAGE FAIL NEW PC OBTAINED FROM HERE IN ITS PAGING MODE + +;LOW CORE +;0-200 DF10S CHANNEL PROGRAMS, INTERRUPT LOCATIONS FOR IMP INTERFACE +;400-500 DTE20 COMMUNICATION AREA (COMMUNICATE WITH KLDCP AND IOELEV) +;500-1000 DL10 COMMUNICATION AREA AND BUFFERS (COMMUNICATE WITH IOELEV) + +DEFSYM QICWA=32 ;ITS DISK ICWA +DEFSYM QIOWD=160 ;ITS DISK IOWD AREA +DEFSYM RCIOWD=162 ;.. FOR READ COMPARE + +DEFSYM MICWA=30 ;ITS TAPE ICWA +DEFSYM MIOWD=170 ;ITS TAPE IOWD AREA + +;LUUO IN EXEC MODE LOCATIONS 40,41 + +DEFSYM SLVICW=60 ;SALVAGER ICWA +DEFSYM SLVIOW=62 ;SALVAGER IOWD AREA + +;EXEC DDT'S DISK ROUTINES USE LOCATIONS 20 AND 21, BUT THEY SAVE AND RESTORE THEM + +DEFSYM IMPILC=70 ;IMPTERFACE INPUT INTERRUPT INSTRUCTION PAIR +DEFSYM IMPOLC=72 ;IMPTERFACE OUTPUT INTERRUPT INSTRUCTION PAIR + +;DTE20 STUFF AS DEFINED BY KLDCP, ETC. +;THE DOCUMENTATION CLAIMS THIS STUFF IS IN THE EPT, BUT ACTUALLY +;IT'S IN FIXED LOCATIONS IN LOW CORE. + +DEFSYM EPTDIA=440 ;DIAGNOSTIC (SALV) START ADDRESS +DEFSYM EPTDDT=441 ;DDT START ADDRESS +DEFSYM EPTSTL=442 ;LOADER (DSKDMP) START ADDRESS +DEFSYM EPTITS=443 ;MONITOR (ITS) START ADDRESS + +DEFSYM DTEFLG=444 ;DTE20 OPERATION COMPLETE FLAG (SET BY 11, CLEARED BY 10) +DEFSYM DTECLK=445 ;DTE20 CLOCK INTERRUPT FLAG (SET BY 11, CLEARED BY 10) +;DEFSYM DTECI=446 ;DTE20 CLOCK INTERRUPT INSTRUCTION (USED BY 10 SOFTWARE) +DEFSYM DTET11=447 ;DTE20 10->11 ARGUMENT (SET BY 10) (NOT USED?) +DEFSYM DTEF11=450 ;DTE20 11->10 ARGUMENT (SET BY 11) +DEFSYM DTECMD=451 ;DTE20 10->11 COMMAND WORD (SET BY 10) +DEFSYM DTESEQ=452 ;DTE20 OPERATION SEQUENCE NUMBER (AOS BY 10) +DEFSYM DTEOPR=453 ;DTE20 OPERATION IN PROGRESS FLAG (SET/CLEARED BY 10) +DEFSYM DTECHR=454 ;DTE20 LAST TYPED CHARACTER (SET BY 11, CLEARED BY 10) +DEFSYM DTEMTO=455 ;DTE20 MONITOR-MODE TYPEOUT DONE FLAG (SET BY 11, CLEARED BY 10) +DEFSYM DTEMTI=456 ;DTE20 MONITOR-MODE TYPEIN DONE FLAG (SET BY 11, CLEARED BY 10) +DEFSYM DTESWR=457 ;DTE20 SIMULATED SWITCH REGISTER (SET BY 11 ON START) + +DEFSYM DTE==200 ;DTE20 #0 DEVICE CODE +DEFSYM %DBL11==20000 ;CONO BIT TO "DOORBELL" 11 +DEFSYM %DBL10==1000 ;CONI BIT FOR DOORBEL FROM 11. CONO BIT TO CLEAR. +;1.1-1.3 DTE20 PIA + +;WORDS STORED IN DTECMD + +DEFSYM %DTTTI==2400 ;BUFFERED INPUT. CHAR RETURNED IN DTEF11 AFTER LINE TYPED. +;NUMBER 0-377 IS CHAR TO BE TYPED OUT (FLUSHES INPUT. BUFFER NOT PRINTED UNTIL LF/^G/^@) +DEFSYM %DTTTO==2000 ;THIS + CHAR ALSO = TTY OUTPUT +DEFSYM %DTTYI==3400 ;"DDT" INPUT, CHAR RETURNED IN DTEF11, ZERO IF NO CHAR TYPED +DEFSYM %DTTYO==4000 ;THIS + CHAR = ITS (MONITOR) TTY OUTPUT. + ;WHEN TYPEOUT DONE, INTERRUPT WITH DTEMTO SET. + ;TYPEIN CAUSES INTERRUPT WITH DTEMTI SET, CHAR IN DTEF11. +DEFSYM %DTMMN==4400 ;MONITOR MODE ON (DEFAULT WHEN START) +DEFSYM %DTMMF==5000 ;MONITOR MODE OFF (TYPEIN OF A ^X DOES THIS ALSO) +DEFSYM %DTMMS==5400 ;RETURN MONITOR MODE STATE IN DTEF11 +;DEFSYM %DTNRM==3000 ;NORMAL PRINT MODE +;DEFSYM %DTFRC==3001 ;FORCED PRINT MODE +DEFSYM %DTCLN==1001 ;CLOCK ON (60 CYCLE SIMULATED CLOCK) +DEFSYM %DTCLF==1000 ;CLOCK OFF +;DEFSYM %DTCLW==1002 ;"CLOCK WAIT" DTET11 HAS COUNT (? WHAT THE HECK IS THIS?) +;DEFSYM %DTCLR==1003 ;RETURN "CLOCK COUNT" IN DTEF11 (? WHAT THE HECK IS THIS?) +DEFSYM %DTHLT==400 ;HALT +;DEFSYM %DTFTL==401 ;DIAG FATAL ERROR (ACTUALLY JUST TURNS OFF CLOCK) +;DEFSYM %DTERR==402 ;DIAG ERROR HALT (ACTUALLY JUST TURNS OFF CLOCK) +;DEFSYM %DTEPG==403 ;END OF DIAGNOSTIC PROGRAM +;DEFSYM %DTEOP==404 ;END OF DIAGNOSTIC PASS +;DEFSYM %DTCLK==405 ;GET "CLOCK DEFAULT WORD" +;DEFSYM %DTFSL==406 ;DIAMON FILE SELECT (NAME.EXT MUST HAVE BEEN %DTTTO'ED) +;DEFSYM %DTFRD==407 ;DIAMON FILE READ (5 CHARS OR -1 (EOF) RETURNED IN DTEF11) +;DEFSYM %DTCMD==410 ;KLDCP COMMAND EXECUTED FROM OUTPUT BUFFER (%DTTTO IT) +;DEFSYM %DTRSW==1400 ;RETURN SIMULATED SWITCHES IN DTEF11. 10 SHOULD THEN STORE IN DTESWR + + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/evsyms.21 b/src/system/evsyms.21 new file mode 100755 index 00000000..e6687ccb --- /dev/null +++ b/src/system/evsyms.21 @@ -0,0 +1,278 @@ +;This purports to be a table of all ITS symbols +;referenced by user programs, not counting sys$j in DDT. +;to sort in TECO, do J6FXA 12U0 <:S0; -DK> CS;$:LL :FWLFWLL J<50L .-Z; 12I 13I 10I> JGA +;The "5" is chosen to count these 4 comment lines, and the blank line. +;Commented-out symbols are those for obsolete devices, used from PEEK/FIDO but not essential. + +%QAACC ;used by PEEK +%QACTH ;used by PEEK +%QADEL ;used by PEEK +%QAEFR ;used by PEEK +%QAEFW ;used by PEEK +%QAFUL ;used by PEEK +%QAPAR ;used by PEEK +%QAWOV ;used by PEEK +%QMMDR ;used by PEEK +%QMMDW ;used by PEEK +%QMTTR ;used by PEEK +%QMTTW ;used by PEEK +%QMUDR ;used by PEEK +%QMUDW ;used by PEEK +AC0S ;used by PEEK +APRC ;used by PEEK +AUSOPG ;used by PEEK +BADBTS ;used by DDT +CALSXB ;used by PEEK +CLSTB ;used by PEEK +CUSER ;used by PEEK +DCHSTB ;used by FIDO (.EVAL and core mapping) +DCHSTB ;used by PEEK +DEDTIM ;used by PFTHMG DRAGON +DEVTAB ;used by PEEK +;DG2 ;used by PEEK +DIRCHN ;used by PEEK +;DISUSR ;used by FIDO (.EVAL and core mapping) +;DISUSR ;used by PEEK +DMNBC ;used by PFTHMG DRAGON +DMNBD ;used by NAMDRG +DMNBD ;used by PFTHMG DRAGON +DMNBEL ;used by NAMDRG +DMNBEL ;used by PFTHMG DRAGON +DMNBF ;used by NAMDRG +DMNBF ;used by PFTHMG DRAGON +DMNBFE ;used by PFTHMG DRAGON +DMNSZ ;used by NAMDRG +DPKBAS ;used by LOCK +;DRTM ;used by PEEK +EDEVS ;used by PEEK +;EUPOS ;used by PEEK +FLSINS ;used by PEEK +HUSRAD ;used by PEEK +IDF1 ;used by PEEK +IDF2 ;used by PEEK +IDLRCE ;used by PEEK +IFPIR ;used by PEEK +IMPBPQ ;used by PEEK +IMPSTL ;used by PEEK +IMPUP ;used by FIDO (.EVAL and core mapping) +IMPUP ;used by PEEK +IMPUP ;used by TELNET (and by other network programs I think - MRC) +IMPUS ;used by COMSAT (.EVAL) +IMPUS ;used by DDT +IMPUS ;used by NAMDRG +IMPUS ;used by NAME +IMPUS ;used by QMAIL (.EVAL) +IMSOC1 ;used by PEEK +IMSOC2 ;used by PEEK +IMSOC3 ;used by PEEK +IMSOC4 ;used by PEEK +IMSOC4 ;used by NAME and NAMDRG +IMSOC5 ;used by PEEK +IMSOC6 ;used by PEEK +IMSOC7 ;used by PEEK +IMSOC8 ;used by PEEK +IOCHNM ;used by FIDO (.EVAL and core mapping) +IOCHNM ;used by PEEK +IOCHNM ;used by NAME and NAMDRG +IOCHST ;used by FIDO (.EVAL and core mapping) +IOCHST ;used by PEEK +IOTLSR ;used by PEEK +IOTTB ;used by PEEK +JBDEV ;used by PEEK +JNAME ;used by FIDO (.EVAL and core mapping) +JNAME ;used by NAMDRG +JNAME ;used by NAME +JNAME ;used by PEEK +JNAME ;used by PFTHMG DRAGON +JTMU ;used by PEEK +LIOBLK ;used by PFTHMG DRAGON +LOSRCE ;used by PEEK +LOUTIM ;used by PEEK +LPTUSR ;used by FIDO (.EVAL and core mapping) +LPTUSR ;used by PEEK +LSCALL ;used by PEEK +LUBLK ;used by COMSAT +LUBLK ;used by FIDO (.EVAL) +LUBLK ;used by NAMDRG +LUBLK ;used by NAME +LUBLK ;used by PEEK +LUBLK ;used by PFTHMG DRAGON +LUBLK ;used by CLU +LUIOP ;used by PEEK +MAXJ ;used by COMSAT +MEMBLT ;used by PEEK +MEMFR ;used by PEEK +MEMPNT ;used by PEEK +MMMPG ;used by PEEK +MMPNP ;used by PEEK +MMSWP ;used by PEEK +;MPXBUF ;used by PEEK +MSKST ;used by PEEK +MSKST2 ;used by PEEK +MTUSR ;used by PEEK +MUR ;used by PEEK +MURUSR ;used by PEEK +N11TYS ;used by FIDO (.EVAL) +N11TYS ;used by NAMDRG +N11TYS ;used by NAME +NCBCOM ;used by PEEK +NCT ;used by FIDO (.EVAL) +NCT ;used by LOCK +NCT ;used by NAMDRG +NCT ;used by NAME +NCT ;used by PEEK +NDPTYS ;used by LOCK +NETDBO ;used by NAME and NAMDRG +NETDUI ;used by NAME and NAMDRG +NETP ;used by COMSAT (.EVAL) +NETP ;used by QMAIL (.EVAL) +NF11TY ;used by FIDO (.EVAL) +NF11TY ;used by NAMDRG +NF11TY ;used by NAME +NFDPTY ;used by LOCK +NFSTTY ;used by NAMDRG +NFSTTY ;used by NAME +NFSTTY ;used by PEEK +NIOCHN ;used by NAME and NAMDRG +NMPGS ;used by PEEK +NNTYS ;used by LOCK +NPGSWO ;used by PEEK +NQCHN ;used by PEEK +NQMFWR ;used by COMSAT (.EVAL and core mapping) +NQS ;used by PEEK +NSTTYS ;used by NAMDRG +NSTTYS ;used by NAME +NSTTYS ;used by PEEK +NSWPGS ;used by PEEK +NULTIM ;used by PEEK +NUNITS ;used by PEEK +NUTIC ;used by PEEK +NUTOC ;used by PEEK +;NVDUSR ;used by PEEK +NXGPFW ;used by XGPSPL +OIPBIT ;used by DDT +OPRSXB ;used by PEEK +PARERR ;used by PEEK +;PDPUSR ;used by FIDO (.EVAL and core mapping) +;PDPUSR ;used by PEEK +PICLR ;used by PEEK +PIRQC ;used by PEEK +PLTUSR ;used by PEEK +PRVUSR ;used by PEEK +PSWOUS ;used by PEEK +PTPUSR ;used by PEEK +PTRUSR ;used by PEEK +QFBLNO ;used by PEEK +QIRRCV ;used by PEEK +QSCRW ;used by PEEK +QSMDN ;used by PEEK +QSMPRP ;used by PEEK +QSNLCN ;used by PEEK +QSNUD ;used by PEEK +QSRAC ;used by PEEK +QUDFPR ;used by PEEK +QUDPR ;used by PEEK +QUSR ;used by PEEK +RNABLU ;used by PEEK +RPCL ;used by PEEK +SCHHB ;used by PEEK +SCLNET ;used by LOCK +SHUTDN ;used by NAMDRG +SHUTDN ;used by NAME +SILNG ;used by PEEK +SLOADU ;used by DDT +SLOADU ;used by PEEK +SOLNG ;used by PEEK +SSCHDB ;used by PEEK +STYSTS ;used by NAMDRG +STYSTS ;used by NAME +STYSTS ;used by PEEK +SUEXIT ;used by PEEK +SUPCOR ;used by LOCK +SUPPRO ;used by COMSAT +SUPPRO ;used by FIDO (.EVAL and core mapping) +SUPPRO ;used by NAMDRG +SUPPRO ;used by NAME +SUPPRO ;used by PEEK +SUPPRO ;used by PFTHMG DRAGON +SUUOH ;used by PEEK +SV40 ;used by PEEK +SWPOPR ;used by PEEK +SWRCE ;used by PEEK +SYSUSB ;used by DDT +SYSUSE ;used by DDT +SYSYMB ;used by DDT +SYSYME ;used by DDT +;TABUSR ;used by PEEK +TCTYP ;used by FIDO (.EVAL and core mapping) +TIME ;used by NAMDRG +TIME ;used by NAME +TIME ;used by PEEK +TIME ;used by PFTHMG DRAGON +TRNLS1 ;used by PEEK +TRNLST ;used by PEEK +TRUMM ;used by PEEK +TRUNTM ;used by PEEK +TRUNTM ;used by PFTHMG DRAGON +TSIPRQ ;used by PFTHMG DRAGON +TSYSM ;used by PEEK +TT11P ;used by NAMDRG +TT11P ;used by NAME +TTITM ;used by NAMDRG +TTITM ;used by NAME +TTYCHN ;used by LOCK +TTYSTS ;used by FIDO (.EVAL and core mapping) +TTYSTS ;used by NAMDRG +TTYSTS ;used by NAME +TTYTBL ;used by FIDO (.EVAL and core mapping) +TTYTBL ;used by NAMDRG +TTYTBL ;used by NAME +TTYTBL ;used by PEEK +TTYTYP ;used by FIDO (.EVAL and core mapping) +TTYTYP ;used by LOCK +TTYTYP ;used by NAMDRG +TTYTYP ;used by NAME +;UDIR ;used by PEEK +;UDIRO ;used by PEEK +;UGOAL ;used by PEEK +;ULCTM ;used by PEEK +UMASTER ;used by FIDO (.EVAL and core mapping) +UMASTER ;used by PEEK +UMNTR ;used by PEEK +UNAME ;used by COMSAT +UNAME ;used by FIDO (.EVAL and core mapping) +UNAME ;used by NAMDRG +UNAME ;used by NAME +UNAME ;used by PEEK +UNAME ;used by PFTHMG DRAGON +UPC ;used by PEEK +UPGCP ;used by PEEK +UPGSEC ;used by PEEK +UREALT ;used by PEEK +USRSTG ;used by COMSAT +USIPRQ ;used by PEEK +USIPRQ ;used by PFTHMG DRAGON +USIPRQ ;used by CLU +USRHI ;used by COMSAT +USRHI ;used by FIDO (.EVAL and core mapping) +USRHI ;used by PEEK +USRHI ;used by PFTHMG DRAGON +USRRCE ;used by PEEK +USTP ;used by PEEK +USWPRI ;used by PEEK +USWSCD ;used by PEEK +USWST ;used by PEEK +USYSN1 ;used by PEEK +USYSNM ;used by PEEK +;UTASS ;used by PEEK +;UTBFS ;used by PEEK +UTMPTR ;used by NAMDRG +UTMPTR ;used by NAME +UTMPTR ;used by PEEK +UTRNTM ;used by PEEK +UTRNTM ;used by PFTHMG DRAGON +;UTTNO ;used by PEEK +;UTUSR ;used by PEEK +UUAC ;used by PEEK +XJNAME ;used by COMSAT +XUNAME ;used by COMSAT diff --git a/src/system/fsdefs.43 b/src/system/fsdefs.43 new file mode 100755 index 00000000..3c9853be --- /dev/null +++ b/src/system/fsdefs.43 @@ -0,0 +1,216 @@ +.AUXIL + +IFNDEF DEFSYM,[ ;ALLOW USER TO USE SYMBOLS IN OTHER WAYS IF HE WISHES. + ;BUT NORMALLY, DEFSYM FOO==BAR DOES FOO==BAR WITH ERROR CHECK. +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ + $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` +] +.ISTOP +TERMIN TERMIN + +IFLE .MLLIT,.ERR .MLLIT MUST BE 1; SETTING IT TO 1. +.MLLIT==1 +$$TEMP==1 +] +.ELSE $$TEMP==0 + +;FILE SYSTEM PARAMETERS - APPLIES TO ALL ITS MACHINES + +;9/5/79 - tut format changed! +;8/19/90 - DM "funny" bit flushed + +;MFD INFO + +IFDEF NBLKS,[ ;MFDBLK KNOWN ONLY IF .INSRT APPROPRIATE PHYSICAL PARAMS FILE +DEFSYM MFDBLK==NBLKS/2-1 ;LOC ON DISK +DEFSYM MFDCYL==MFDBLK/NBLKSC +DEFSYM MFDSRF==*SECBLK/NSECS +DEFSYM MFDSEC==*SECBLK-MFDSRF*NSECS +] + ;RANDOM INFO IN MFD +DEFSYM MDNUM==0 ;ASCENDING DIR NUM +DEFSYM MDNAMP==1 ;PNTR TO ORG OF USER NAME BLOCK AREA +DEFSYM MDYEAR==2 ;CURRENT YEAR +DEFSYM MPDOFF==3 ;DE-CORIOLIS CLOCK OFFSET +DEFSYM MPDWDK==4 ;PREFERRED WRITING DISK (PHYSICAL DRIVE #) +DEFSYM MDCHK==5 ;THIS WORD MUST BE M.F.D. (FOR CHECKING) +DEFSYM MDNUDS==6 ;NUMBER USER DIRECTORIES (FOR CHECKING ONLY) +DEFSYM LMIBLK==7 ;TOTAL STG USED BY HACKS LIKE THIS + ;USER NAME BLKS FROM C(MDNAMP) TO END +DEFSYM LMNBLK==2 ;# WDS/BLK +DEFSYM MNUNAM==0 ;6BIT USER NAME + ;SECOND WORD OF A USER-NAME BLOCK IS ZERO. + ;DECUUO CONTAINS A KLUDGE WHICH DEPENDS ON THIS, + ;PLEASE NOTIFY BUG-DECUUO BEFORE CHANGING IT. + +;TUT INFO + +IFDEF NBLKS,[ +DEFSYM TUTBLK==MFDBLK-NTUTBL ;LOC ON DISK +DEFSYM TUTCYL==TUTBLK/NBLKSC +DEFSYM TUTSRF==*SECBLK/NSECS +DEFSYM TUTSEC==*SECBLK-TUTSRF*NSECS +] +DEFSYM TUTBYT==3 ;SIZE OF BYTES (USED TO BE 4) +DEFSYM TUTBP==<440000+TUTBYT_6>,, +DEFSYM TUTEPW==36./TUTBYT ;NUMBER OF ENTRIES PER WORD +DEFSYM TUTMAX==1_TUTBYT +DEFSYM TUTLK==TUTMAX-1 ;HIGHEST CODE MEANS LOCKED OUT +DEFSYM TUTMNY==TUTLK-1 ;TUT MANY OR MORE REFS + +;RANDOM INFO IN TUT (AT THE FRONT) +DEFSYM QPKNUM==0 ;PACK # +DEFSYM QPAKID==1 ;PACK ID +DEFSYM QTUTP==2 ;FREE SPACE POINTER TO TRACK AREA. ADVANCE BY CYLINDERS +DEFSYM QSWAPA==3 ;SWAPPING AREA. FIRST TRACK OF NON-SWAPPING AREA + ;NEW FILES WILL NOT BE WRITTEN LOWER THAN THIS. +DEFSYM QFRSTB==4 ;FIRST BLOCK TUT'ED +DEFSYM QLASTB==5 ;LAST BLOCK TUT'ED +DEFSYM QTRSRV==6 ;-1 IF ONLY ALLOCATED DIRS CAN HAVE FILES ON THIS PACK + ;IF NOT 0 AND NOT -1, SIXBIT NAME OF "SECONDARY" PACK + ;STG FOR RANDOM INFO ^ +DEFSYM LTIBLK==20 ;BYTES MAPPING THE DISK START HERE + +;UFD INFO +;IF A IS RELATIVE LOCATION OF MFD ENTRY, USER DIR IS LOCATED IN +;TRACK NUMBERED /2 (SEE QFL2) + +DEFSYM UFDBYT==6 ;SIZE OF BYTES (Do not change!) +DEFSYM UFDBPW==36./UFDBYT ;NUMBER OF BYTES PER WORD + + ;RANDOM INFO IN UFD +DEFSYM UDESCP==0 ;FS PNTR TO DESC AREA +DEFSYM UDNAMP==1 ;PNTR TO ORG OF NAME AREA +DEFSYM UDNAME==2 ;USER NAME (FOR CHECKING) +DEFSYM UDBLKS==3 ;LEFT HALF HAS AMOUNT OF SPACE ALLOCATED (NOT USED + ; CURRENTLY BY SYSTEM), RIGHT HALF HAS NUMBER OF BLOCKS USED. +DEFSYM UDALLO==4 ;IF NONZERO, LEFT HALF HAS DISK NUMBER, RIGHT + ; HALF HAS AMOUNT OF SPACE ALLOCATED +DEFSYM UDDESC==11. ;FIRST LOC AVAIL FOR DESC + +; 8/19/90 Due to the larger size of RP07s it was necessary to officially +; flush the DM "funny" bit. This change only changes the comments in this +; file, but any program that interprets UFD descriptors needs to be fixed +; to not mask that bit out (as most of them currently do). Fortunately all +; the known ITS filesystems have zeros in all their "funny" bits, so the +; change is upward compatible. + +; UFD descriptor format described: +; +; Each 6-bit byte is taken in turn and used to compute a sequence of block +; numbers. If N is the current descriptor byte, and B is the current block +; number (initially undefined), then N is interpreted as follows: +; +; 0 Marks the end of the file description. +; +; 1 to UDTKMX (1 to 14) "Take" N blocks. +; Blocks B through B + N - 1 are the next N blocks of the file. +; Set B := B + N . +; +; UDTKMX+1 to UDWPH-1 (15 to 36) "Skip" B - UDTKMX blocks. +; Set N := N + B - UDTKMX . +; (ITS has been broken for years such that it never uses this +; UFD descriptor code!) +; +; UDWPH (37) Write Place Holder +; A noop. Used to reserve space in directories for files that are +; being written. Just skip over it and read the next byte. +; +; 40 - 77 Load address and take 1. +; Read the next NXLBYT descriptor bytes (NXLBYT=2), N2 and N3. +; Set B := LSH(AND(N, 37), 12.) + LSH(N2, 6) + N3 . +; Block B is the next block in the file. +; Set B := B + 1 . +; +; A zero length file is described as two bytes: UDWPH then 0. UDWPH does +; not otherwise normally appear in UFD descriptions for closed files. +; Note that a legal description must use codes 40 - 77 before it can use +; any code other than UDWPH. + +; Links are described as a sequence of SIXBIT characters terminated with a +; 0 byte. The directory, first and second name are stored in order. +; The first two components are terminated with a ";" if they are less than +; 6 characters long. ";" (73), ":" (72) and " " (0) are quoted by +; preceding them with a ":". Some examples: +; +; Link target names: Bytes stored in directory: +; +; 123456 123456 123456 "123456123456123456 " +; ALAN FOO BAR "ALAN;FOO;BAR " +; .MAIL. NAMES > ".MAIL.NAMES;> " +; .MAIL. LISTS MSGS ".MAIL.: LISTS: : MSGS " +; MOON LUNAR :EJ "MOON;LUNAR;::EJ " +; +; There are a lot of illegal or wasteful possibilities for link descriptors +; ("A;B ", "A;B;C;D ", ":A;:B;:C ", etc.), which is suprising since +; somebody was clearly trying to compress them into as few bytes as +; possible. + +; Here is the pre 8/19/90 comment describing UFD descriptors: +; +; ;UFD DESCRIPTORS +; ;0 => FREE 1-UDTKMX => TAKE NEXT N +; ;UDTKMX+1 THRU UDWPH-1 => SKIP N-UDTKMX AND TAKE ONE +; ;UDWPH => WRITE-PLACE-HOLDER +; ;40 BIT SET => LOAD ADDRESS. LOWER 5 BITS PLUS NEXT NXLBYT (2) +; ; CHARS (17 BITS IN ALL) +; ;40 BIT & 20 BIT => "FUNNY" BLOCK IF DMDSK. WHAT IS THIS, ANYWAY? +; ;END BY 0 +; +; ;IF LINK DESCR +; ;6 CHAR OR UNTIL ; = SYS NAME. MUST HAVE NO CHAR = 0 IN THIS OR +; ; NEXT 2 NAMES +; ;NEXT CHAR QUOTED BY : (FOR NAMES WITH : OR ;) +; ;NEXT CHAR N1 +; ;NEXT CHAR N2 +; ;END BY 0 + +DEFSYM UDTKMX==12. ;HIGHEST "TAKE N" CODE +DEFSYM UDWPH==31. ;PLACE HOLDER ON WRITE (OR NULL FILE) +DEFSYM UDSKMX==UDWPH-UDTKMX-1 ;# BLOCKS THAT CAN BE SKIPPED +DEFSYM NXLBYT==2 ;# ADDITIONAL BYTES FOR LOAD ADDR + ;IN SYSTEM THIS IS DEFINED AT FRONT OF FILE + + ;NAME AREA DATA + +DEFSYM LUNBLK==5 ;WDS/NAME BLK +DEFSYM UNFN1==0 ;FIRST FN +DEFSYM UNFN2==1 ;SECOND FN +DEFSYM UNRNDM==2 ;ALL KINDS OF RANDOM INFO +DEFSYM UNDSCP==1500,, ;PNTR TO DESC +DEFSYM UNPKN==150500,, ;PACK # +DEFSYM UNLINK==1 ;LINK BIT +DEFSYM UNLNKB==220100,, +DEFSYM UNREAP==2 ;IF 1, DONT REAP FILE +DEFSYM UNWRIT==4 ;OPEN FOR WRITING +DEFSYM UNMARK==10 ;GC MARK BIT +DEFSYM UNCDEL==20 ;DEL WHEN CLOSED +DEFSYM DELBTS==20 ;DELETED -- IGNORE +DEFSYM UNIGFL==24 ;BITS TO IGNORE FILE +DEFSYM UNWRDC==301200,, ;WORD COUNT OF LAST BLOCK MOD 2000 +DEFSYM UNDUMP==400000 ;HAS BEEN DUMPED +DEFSYM UNDATE==3 ;DATE ETC. +DEFSYM UNTIM==2200,, ;COMPACTED TIME OF CREATION +DEFSYM UNYMD==222000,, ;Y,M,D OF CREATION +DEFSYM UNMON==270400,, ;MONTH +DEFSYM UNDAY==220500,, ;DAY +DEFSYM UNYRB==330700,, ;YEAR +DEFSYM UNREF==4 ;REFERENCE DATE SAME AS LEFT HALF OF UNDATE +DEFSYM UNREFD==222000,, ;REFERENCE DATE BYTE POINTER +DEFSYM UNAUTH==111100,, ;MFD INDEX OF AUTHOR, ALL 1=> NO DIRECTORY +DEFSYM UNBYTE==001100,, ;FILE BYTE SIZE AND LENGTH INFO. + ;LET S=BITS PER BYTE, C=COUNT OF UNUSED BYTES IN LAST WD + ;400+100xS+C S=1 TO 3 C=0 TO 35. + ;200+20xS+C S=4 TO 7 C=0 TO 8 + ;44+4xS+C S=8 TO 18. C=0 TO 3 + ;44-S S=19. TO 36. C=0 + ;NOTE THAT OLD FILES HAVE UNBYTE=0 => S=36. + +IF1 IFDEF NUDSL, IFG NUDSL*LMNBLK+LMIBLK-2000,.ERR MFD LOSES + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/imp.365 b/src/system/imp.365 new file mode 100755 index 00000000..30b687e1 --- /dev/null +++ b/src/system/imp.365 @@ -0,0 +1,931 @@ +;;; -*- Mode:MIDAS -*- + +IMPVRS==.IFNM2 ; Version of IMP code + +IFN NCPP,.FATAL IMP Code doesn't support NCP any more! +IFE KSIMP,.FATAL Wrong IMP driver file included! + +OVHMTR IMP ;Charge all this stuff to the IMP + +$INSRT LHDH + +; IMP 1822 PROTOCOL INFORMATION (EXTENDED-LEADER VERSION) + +; The IMP leader is 96 bits long, usually organized as 3 words of 32 bits. +; For further details, these documents are available from the Network +; Information Center: +; IMP-HOST protocol: BBN Report No. 1822 +; NCP protocol: NIC 8246, Host-to-Host Protocol for the ARPANET +; IP, TCP: Internet Protocol Transition Workbook, and +; Internet Protocol Implementor's Guide +; +; Here is the leader format used by the IMP code. This format uses +; no IMP padding, assumes IP only, and expects all IMP<->HOST data +; transfers in 32-bit mode. +; +; Previous versions of this code which supported NCP used a much more +; complicated leader formatting scheme based on 36 bit transfers and +; IMP padding. That scheme is dead, see SYSTEM;IMPOLD WTHNCP for details. +; +; All data from the IMP interface ends up in the -10 as left-justified +; 32-bit words. Objects of less than 32 bits length, such as IP octets, +; are stored in PDP10 ILDB byte order. +; +;------------------------------------------------------------------------ +;1: 4.9-4.6 not used (0) +; 4.5-4.2 all 1's for new format, else old msg type (4=old nop) +; 4.1-3.3 network number (0) +; 3.2-2.8 not used (0) +; 2.7 trace (ignored) +; 2.6-2.4 leader flags (2.6 is to be ignored, 2.5-2.4 are not used!) +; 2.3-1.5 message type +; +;2: 4.9-4.2 Handling type (7 for big buffers, 4 for small buffers, +; 0 for the control link) +; 4.1-3.3 Host number on IMP +; 3.2-1.5 IMP number +; +;3: 4.9-4.2 Link Number (High 8 bits of Message ID) +; 4.1-3.7 Low 4 bits of Message ID (0) +; 3.6-3.3 Sub-type +; 3.2-1.5 Message length +;------------------------------------------------------------------------ +;4: 4.9-1.5 First word of IP datagram +; .... +;------------------------------------------------------------------------ +; +;In message types 2 and 6, the going-down status 16-bit word is +;in word 3 bits 4.9-3.3. + +;3.6-3.3 of word 3 are the padding count for type 4 (nop) from host. +;This is currently 0 (none). Padding is only put on type-0 messages. + +IMPLDS==3 ;IMP local leader size + + ;Byte pointers to fields of input leader +IMOTBP: 340400,,IMPILB+0 ;Message format type +IMTBP: 041000,,IMPILB+0 ;Message type field +IMSABP: 043000,,IMPILB+1 ;Source address field (host+IMP) +IMSHBP: 241000,,IMPILB+1 ;Source host field +IMSIBP: 042000,,IMPILB+1 ;Source IMP field +IMLNBP: 341000,,IMPILB+2 ;Link number field +IMSTBP: 240400,,IMPILB+2 ;Subtype field +IMMLBP: 042000,,IMPILB+2 ;Message length field + + + +SUBTTL ARPANET VARIABLES AND TABLES + +EBLK + +%IMXLN==:<<8159.-96.>+31.>/32. ; Max # of 32-bit words in IMP regular msg, + ; exclusive of leader and leader padding. = 252. + +%IMMTU==:251.*4 ; Used by IP/TCP. Driver currently rounds to PDP10 words, + ; forcing this to be 1004 instead of 1007. + +; ACTIVE HOST TABLE. Entries herein are allocated as needed, using garbage +; collection. Most "host number" fields are really indices into this table. +; +LIMPHT== ; TCP conns plus a few extra + +IMPHTF: -1 ;Host table free list, threaded through IMPHTB, end with -1 + +IMPHTS: ;Start of table area +IMPHTN: BLOCK LIMPHT ; Host number. 1.1-1.8 HOST, 2.1-3.7 IMP +IMPHTB: BLOCK LIMPHT ;Bits: + ;4.9 UNUSED + ;4.8 GC MARK BIT + ;4.7-4.3 UNUSED + ;4.2-4.1 STATUS OF HOST 0 DOWN, 1 RST SENT, 2 UP + ;3.9-3.1 UNUSED + .SEE IMPHDS ;RH Last message from IMP about "host dead status" +IMPHTC: BLOCK LIMPHT ; # active messages outstanding for host (8 max) +IMPHTT: BLOCK LIMPHT ; Time of last RFNM received +IMPHTE==.-1 ;Last location in table + +;Status variables +; +IMPUP: -1 ;0 => IMP up ;-1 => down ;-2 => coming up, PI still off + ;1 => down for good, until next time IMP ready line changes +IMPTCU: 0 ;0 IMP up/down status not changing + ;>0 Trying to reinitialize, SYSJOB hasn't done so yet + ;-1 Has been reinitialized, haven't exchanged NOPs yet +IMPUCT: 0 ;IMP coming up timeout, if 4 NOPs don't go through promptly. +IMPDWN: BLOCK 3 ;Last message from IMP that it is going down + ;WD0: "Reason" claimed by IMP (see ch 3 of BBN report 1822) + ;WD1: Time when expected down + ;WD2: Time when expected up (SYS time=1/30 sec since up) + +IMERCN: -1 ;CONI into here when net goes down + +BBLK + +EBLK + +;Input side variables +; +IMPILB: BLOCK IMPLDS ;Input leader buffer +IMPCSH: -1 ;Current source host (IMPHTB index). -1 when idle. +IMPCLN: 0 ;Current link number +IMIFLS: 0 ;Flushing output at interrupt handler +IMPIEC: 0 ;Count of input errors while down. +IMPIBC: 0 ;Count of words available in DMA input buffer +IMPIBP: 0 ;Pointer into DMA input buffer + +;Output side variables +; + ;Output leader buffer +IMOLDR: <17_10.>,,0 ;Regular new-format message +IMOLAD: 0 ;Filled in with destination IMP address + <233_10.>,,0 ;IP link field + +IMNOPC: 0 ;< 0 => Send NOPs +IMPOAC: -1 ;>= 0 => Output active, don't restart +IMPBZY: 0 ;-1 == Waiting for output interrupt +IMPODP: 0 ;Pointer to IP datagram being output at PI level +IMPOS: 0 ;Output state + %ISODL==:0 ; Not expecting output done (i.e. between messages) + %ISONP==:1 ; Sending NOP + %ISOID==:2 ; Sending IP Datagram + +;Meters + +;IP meters +IMNIPI: 0 ; # of IP datagrams input (rcvd) +IMNIPF: 0 ; # of IP datagrams flushed (input threw away) +IMNIPO: 0 ; # of IP datagrams output (sent) +IMNIPR: 0 ; # of IP RFNMs received +IMNIP7: 0 ; # of IP Type 7 (Dest Host Dead) messages received +IMNIP8: 0 ; # of IP Type 8 (Error) msgs rcvd +IMNIP9: 0 ; # of IP Type 9 (Incomplete Transmission) msgs rcvd +IMNWIG: 0 ; # words ignored by "Ignore" state (%ISIGN) +IMNWIF: 0 ; # words flushed by IMPRM5 + +;IMP meters +IMNSRF: 0 ;Number of spurious RFNMs on non-IP links +IMNBLK: 0 ;Number of times blockage avoided (output held up by ITS) + +IMPMSR: BLOCK 20;Count of IMP messages rcvd +IMPM1S: BLOCK 4 ; # Type 1 (Error in Leader) subtype msgs +IMPM9S: BLOCK 2 ; # Type 9 (Incomplete Transmission) subtype msgs +IMPMSS: BLOCK 1 ;Count of IMP msg sent (we only send regular msgs) +IMCT1: 0 ;# Unvectored interrupts +IMCT2: 0 ;# Valid input interrupts +IMCT3: 0 ;# Valid output interrupts +BBLK + +SUBTTL ARPANET MAIN-PROGRAM LEVEL +;IMPIBF, IMPOBF defined as low-memory buffer page in ITS +IF2,IFN IMPIBF&777,.FATAL IMPIBF not on DEC page boundary + +;(Re)Start IMP. Called from SYSJOB to start IMP, or on error or +; user requested cycle through LOCK +; +IMPINI: SETOM IMPUP ;Not up yet, + SETOM IMPTCU ; but thinking about it. + MOVEI A,IMPIBF_-9. ;DEC page # of IMP buffer page + TRO A,%UQ16B\%UQVAL ;Valid mapping, 16 bit device + IOWRI A,UBAPAG+IUIMPG_1 ;Set up 1 DEC page of UBA mapping. Note that + ; the second half of IUIMPG isn't mapped at all + CONO PI,NETOFF ;Freeze things while IMP bashing occurs + MOVEI A,%LHRST + IOWRI A,%LHOCS ;Reset output side + IOWRI A,%LHICS ;Reset Input side + + ;IMP now shut down. Reset variables + SKIPE A,IMPODP ;Have an output datagram ? + PUSHJ P,IPIODN ;Yep, release it. + SETZM IMPODP ;No output datagram + SETZM IMPOS ;Output idle + SETOM IMPOAC ;Output interrupt level inactive + SETZM IMPBZY ;No pending output interrupt + + SETZM IMPIBC ;No input available + SETZM IMPIEC ;No input errors yet + SETZM IMIFLS ;Not flushing input at interrupt level + SETOM IMPCSH ;No current host table index + SETOM IMPDWN+1 ;Time for IMP to go down, not known + CONO PI,NETON ;Allow interrupts again + + ;Wait one sec for IMP to notice rdy line drop + MOVE T,TIME + ADDI T,30. + CAMLE T,TIME + PUSHJ P,UFLS + + MOVNI A,30. ;Allow 15 seconds to come up + MOVEM A,IMPUCT + MOVE T,TIME ;Note when we last started IMP + MOVEM T,LNETIM + PUSHJ P,IMPHRS ;Set host ready + PUSHJ P,IMPIST ;Start input + + MOVE T,TIME + ADDI T,15. ;Wait 1/2 sec before we try to output + CAMLE T,TIME + PUSHJ P,UFLS + MOVNI A,4 + MOVEM A,IMNOPC ;Send 4 NOPs to start + ;Falls through to start output + +;Start IMP output +; +IMPOST: +IMPIOS: CONO PI,PIOFF ;Freeze. + AOSE IMPOAC ;Do nothing if output already active. + JRST PIONJ + SETOM IMPBZY ;Note we want an IMP interrupt + CONO PI,NETRQ ;Force nonvectored IMP interrupt + JRST PIONJ + +;Check if IMP ready line is set +; Called from SYSJOB. +; Return +1 if IMP not ready, +2 if so +; +IMPCKR: IORDI A,%LHICS ;Get input CSR + TRNN A,%LHINR ;Skip if IMP not ready + AOS (P) ;Return +2 if ready + POPJ P, ;That's all + +;Set HOST READY. From SYS job only, please, loops waiting. +; +IMPHRS: IORDI T,%LHICS + TRNN T,%LHRDY ;Can we mung? + BUG + IORI T,%LHHRC\%LHSE ;Turn on HR. SE prevents dropping messages + IOWRI T,%LHICS + MOVEI A,777777 ;I don't know why this takes so long. +IMPHR1: IORDI T,%LHICS ;Get the bits back + TRNE T,%LHHR ;LHDH thinks host ready is ready + RET ;HR line set + SOJG A,IMPHR1 ;Timed out yet? + BUG CHECK,[IMP: Timed out setting Host Ready] + RET + +SUBTTL HOST-TABLE MANAGEMENT + +;IMPHTI - Initialize host table +; Performed whenever IMP announces that it has been reset +; +IMPHTI: SETOM IMPHTF ;Force GC of IMPHTB on first reference + SETZM IMPHTS ;Clear table of old information + MOVE A,[IMPHTS,,IMPHTS+1] + BLT A,IMPHTE + POPJ P, + +; FNDHST - Look up host-table index for a given IMP host address. +; Call with NETOFF or NETCHN PI in progress. +; T/ IMP host address (maybe someday other nets?) +; Returns .+1 if failed (no room in table) +; Returns .+2 +; H/ host-table index +; Smashes W. + +FNDHST: MOVEI H,LIMPHT-1 ;Search for an entry for this host + CAME T,IMPHTN(H) + SOJGE H,.-1 + JUMPGE H,POPJ1 ;Found + SKIPGE H,IMPHTF ;Not found, cons one off free list + JRST FNDHS1 ;Oops, must garbage collect + MOVE W,IMPHTB(H) + CAIGE H,LIMPHT ;Make sure H is valid idx + CAIL W,LIMPHT ;ditto W + BUG HALT,[NET: FNDHST idx clobbered!!!] + MOVEM W,IMPHTF + MOVEM T,IMPHTN(H) + SETZM IMPHTB(H) ;Nothing is known about this host + SETZM IMPHTC(H) ;Assume no RFNMs outstanding + SETZM IMPHTT(H) ;Clear out time of last RFNM. + JRST POPJ1 + +; Host-Table full, attempt to GC it and flush unused entries, by +; scanning all possible pointers into table. +; IMP pointers are IMPCSH and IMPHTC(H) +; TCP pointers are XBNADR(I) + +; GC mark phase - mark entries in use +FNDHS1: PUSH P,I + MOVSI W,200000 ;Mark bit + MOVEI H,LIMPHT-1 ;Clear all mark bits + ANDCAM W,IMPHTB(H) + SOJGE H,.-1 + SKIPL H,IMPCSH ;Mark from IMPCSH + IORM W,IMPHTB(H) +IFN TCPP,[ + MOVEI I,XBL-1 + SKIPL H,XBNADR(I) ; See if TCP conn has a net addr specified + IORM W,IMPHTB(H) ; Yes, set the mark bit. + SOJGE I,.-2 +] ;IFN TCPP + +; GC sweep phase - free all unmarked entries + SETO I, ;Free pointer + MOVEI H,LIMPHT-1 + MOVSI W,601000 ;Protect if RFNM-WAIT, RST-WAIT, or marked +FNDHS4: + SKIPG IMPHTC(H) ;Also protect if any outstanding RFNMs + TDNE W,IMPHTB(H) + SOJGE H,FNDHS4 + JUMPL H,FNDHS5 + SETZM IMPHTN(H) ;Don't belong to any host + MOVEM I,IMPHTB(H) ;Cons onto free list + MOVE I,H + SOJGE H,FNDHS4 +FNDHS5: MOVEM I,IMPHTF ;Free list + POP P,I + SKIPGE IMPHTF + POPJ P, ;GC-overflow + JRST FNDHST ;Try again, should win + +;See if IMP code is willing to handle a particular datagram right now. +; A/ IP DGM pointer +; C/ Immediate destination address +; Returns +1, can't send right now, +2, OK to send +; +IMPCTS: MOVE T,C ;Set up for FNDHST + AND T,[<377_16.>+377] ;Mask out all but host and IMP field + CALL FNDHST ;Get host index in H + POPJ P, ;No host entry, don't send + JSP T,IMPBLI ;See if OK to send + POPJ P, ;IMP wants to block, no send + JRST POPJ1 ;Skip return if OK to send. + + +;;; IMP Blockage avoidance +; The current IMP software will not accept more than 8 active +; messages to a single host; attempting to send a 9th message will block +; ALL output to the interface, until the first message has been ack'd +; by means of one of the following message types: +; Type 5, RFNM - Message delivered OK +; Type 7, Host dead - transmit failed ("permanent") +; Type 8, Error in data - interface spazzed +; Type 9, Incomplete Transmission - temporary failure +; If for some reason the first message simply becomes lost, the IMP timeout +; (and blockage) can last for up to 30-45 seconds. +; More details in BBN Report 1822. +; ITS attempts to fix this by keeping a count of active un-ACKed +; messages for each host it is communicating with. A timeout is also +; associated with each host; if output to a given host is blocked by ITS +; because there are 8 active messages, trying to send a 9th message +; will check the last-RFNM-received time and if this was more than +; 30 or so seconds then the IMP is probably not giving us what it should +; and we should reset things for that host. + +%IMPMA==:8. ; # of maximum active IMP messages allowed + +; IMPBLI, IMPBLD - routines to hack active-message counts, called via JSP T, +; IMPBLD decrements count. +; IMPBLI increments count and skips if successful (else failed, +; and must NOT output another message to this host!) +; Also clobbers Q. +; +IMPBLI: AOS Q,IMPHTC(H) + CAIGE Q,%IMPMA ;Trying to send max or more messages? + JRST 1(T) ;No, can return safely. + CAIG Q,%IMPMA ;Is this the maximum # allowed? + JRST [ MOVE Q,TIME ;Yes, set up blockage timeout + ADDI Q,60.*30. ; for one minute. + MOVEM Q,IMPHTT(H) + JRST 1(T)] ;And allow this one to be sent + + ; Trying to send too many messages, block it (check for timeout though) + SOS IMPHTC(H) ;Restore original count + AOS IMNBLK ;Increment # of times softwarily blocked. + MOVE Q,IMPHTT(H) + CAML Q,TIME ;See if timeout still in the future + JRST (T) ;Yes, just take failure-return to block. + BUG INFO,[IMP: RFNM-wait timeout! Hst=],OCT,IMPHTN(H) + SETZM IMPHTC(H) ;This may be dangerous... oh well. + SETZM IMPHTT(H) + JRST (T) ;Block one last time, next try will win. + +;Decrement block count on receipt of any kind of ACK +; +IMPBLD: SOSL Q,IMPHTC(H) + JRST IMPBL2 + BUG INFO,[IMP: negative RFNM-wait cnt, Hst=],OCT,IMPHTN(H) + SETZB Q,IMPHTC(H) +IMPBL2: CAIL Q,%IMPMA-1 ;If we were blocking on this host, + PUSHJ P,IMPIOS ;Ensure IMP output started up so blocked stuff + JRST (T) ; gets sent promptly. + + +SUBTTL ARPANET INPUT INTERRUPT LEVEL + +;First level interrupt handling for input side. Here from UBA vector hardware. + +IFN NETCHN-UTCCHN,.ERR NETCHN assumed == UTCCHN at IMPIBK + + EBLK +IMPIBK: 0 + BBLK + JSR UTCSAV ;Save AC's, get a stack + AOS IMCT2 ;Count input interrupts + IORDI TT,%LHICS ;Get CS register + TRNE TT,%LHERR\%LHNXM + JRST IMPRST ;Try resetting the IMP + TRNE TT,%LHMRE ;Ready line flapped + JRST IMPIER ;Go directly to error routine + TRNN TT,%LHRDY ;Device ready for new operation? + JRST IMPRST ;Try resetting. + TRNN TT,%LHEOM ;Saw EOM from IMP? + JRST IMPIB1 ;No, word count ran out before message + SKIPGE IMIFLS ;Flushing output? + JRST [ SETZM IMIFLS ;Not any more! + JRST IMPIRT ] ;But flush last piece by queueing new request + IORDI A,%LHIWC ;End of message. Get remaining UB word count + SKIPE A ;This would be a surprise, really + TDO A,[-1,,600000] ;36bit number of UBA words remaining in bfr + IDIVI A,2 ;Number of PDP10 words (cleverly rounded) + ADDI A,IMPBFS ;Number of PDP10 words of message + MOVEM A,IMPIBC ;Set current count of available data words + MOVEI A,IMPIBF + MOVEM A,IMPIBP ;Set pointer to available data words + JRST IMPLDD ;Go process input message + +;Here when finished processing current message. +IMPIRT: SETOM IMPCSH ;Note no current host + PUSHJ P,IMPIST ;Restart input listener + JRST IMPEX + +;Message didn't fit in input buffer. Shouldn't ever get here, but +;might if messages concatenated due to ready line randomness +; +IMPIB1: BUG INFO,[IMP: Huge message] + SETOM IMIFLS ;Say we are flushing output + JRST IMPIRT ;And go queue up another read + +;Here if error during IMP message transfer +; Currently the only error handled is the IMP going non-ready + +IMPIER: SKIPE IMPUP ;Is the IMP supposed to be up? + JRST IMPIE1 ;No, handle errors differently + BUG INFO,[IMP: Input Ready Error] + JRST IMPRST ;Ready line flapped while up, cycle interface + +IMPIE1: AOS T,IMPIEC + CAIG T,10. ;Huge number of errors while down? + JRST IMPIRT ;No, just ignore this input and start another + SETZM IMPIEC ;Reset + BUG INFO,[IMP: Excessive input errors while down] + JRST IMPRST ;Cycle the interface + +IMPRST: IORDI T,%LHICS ;Record IMP status for sysjob + HRLZM T,IMERCN + IORDI T,%LHOCS + HRRM T,IMERCN + MOVEI A,%LHRST ;Avoid randomness by resetting HW now. + IOWRI A,%LHOCS ;Reset output side + IOWRI A,%LHICS ;Reset Input side + SETOM IMPUP ;IMP is down + MOVEI T,1 + MOVEM T,IMPTCU ;But trying to come up (sysjob poked) + MOVSI J,SCLNET ;Ask SYSJOB to cycle the IMP + IORM J,SUPCOR + JRST IMPEX + + SUBTTL IMP leader dispatch handling + +IMPLDD: SKIPG B,IMPIBC ;Get count of available data + POPJ P, ;None, nothing to do. + CAILE B,IMPLDS ;More than a leader worth? + MOVEI B,IMPLDS ;Yep, only want leader now + MOVS A,IMPIBP ;Copy and reformat leader to IMPILB + HRRI A,IMPILB + BLTUB A,IMPILB-1(B) + ADDM B,IMPIBP ;Increment buffer pointer, + MOVN C,B + ADDM C,IMPIBC ; and decrement count + + LDB T,IMOTBP ;Examine new-format flag bits of leader + CAIL B,IMPLDS ;Large enough to be a valid leader? + CAIE T,17 ;Verify that leader is "new" 96-bit fmt. + JRST IMPLDE ;Go process error in leader + + LDB T,IMLNBP ;Extract link number (high 8 bits of msg-id) + MOVEM T,IMPCLN ;Save link message arrived on + LDB T,IMSABP ;Get arpanet address (source host+imp) +IFN 0,[ + LDB T,IMSHBP ;Source host + LDB A,IMSIBP ;Source imp + DPB A,[112000,,T] ;Form host address +];IFN 0 + PUSHJ P,FNDHST ;H gets host table index + JRST IMPLHE ;Host table full + MOVEM H,IMPCSH ;Save current host + LDB A,IMTBP ;Get message type in A + CAIL A,IMTDTS + JRST IMPUN ;Unknown type? + AOS IMPMSR(A) ;Count IMP msgs rcvd + JRST @IMTDT(A) ;Dispatch + +IMTDT: IMPRM ; 0 Regular Message + IMPBE1 ; 1 Error in Leader (no msg-id) + IMPGD ; 2 IMP Going Down + IMPUN ; 3 - + IMPIN ; 4 NOP + IMPRFN ; 5 RFNM - Ready For Next Message (transmit succeeded) + IMPHDS ; 6 Host Dead Status (general info) + IMPDHD ; 7 Destination Host Dead (transmit failed) + IMPBE8 ; 8 Error in Data (has msg-id) + IMPINC ; 9 Incomplete Transmission (transmit failed temporarily) + IMPIRS ;10 Interface Reset - IMP dropped its ready line +IMTDTS==.-IMTDT + +IMPLHE: BUG INFO,[IMP: Message discarded due to host table full],OCT,IMPILB,OCT,IMPILB+1,OCT,IMPILB+2 + JRST IMPIRT + +;Here if leader is too short or of wrong format. +; B/ Leader length +IMPLDE: SKIPE IMPUP ;If IMP is not up, we'll take anything. + JRST IMPIRT + CAIGE B,IMPLDS ;Announce short leader if so. + BUG INFO,[IMP: Short leader, ],DEC,B,[wds. WD1=],OCT,IMPILB,[WD2=],OCT,IMPILB+1 + LDB A,IMOTBP ;Get message format type + CAIN A,4 ;Old-type NOP? + JRST IMPIRT ; Just ignore it. +IFN 0,[ ;;For the moment this is a problem because the IMP is marked + ;;up too soon, before all incoming NOPS are received. + CAIN A,16 ;Is it 1822L format? + BUG INFO,[IMP: 1822L leader],OCT,IMPILB + CAIE A,17 ;Is it not the long-leader format? + BUG INFO,[IMP: Old-type leader],OCT,IMPILB +] + JRST IMPIRT ;Ignore rest of message, if any + +;;; IMP->Host Type X (e.g. 3, 11-255) - bad type + +IMPUN: BUG INFO,[IMP: Unknown msg type ],OCT,A,[ leader ],OCT,IMPILB,OCT,IMPILB+1,OCT,IMPILB+2 + JRST IMPIRT + +;;; IMP->Host Type 1 - Error in leader (msg-id not given) +;;; IMP->Host Type 8 - Error in data (msg-id given) + +IMPBE1: LDB T,IMSTBP ;Get subtype (4 bits) + ANDI T,3 ;Only 2 bits should be used + AOS IMPM1S(T) ;Increment count of Type 1 subtype messages +IMPBE8: SKIPN IMPUP ;Ignore error during initial syncronization + BUG INFO,[IMP: Type ],DEC,A,[err msg, leader],OCT,IMPILB,OCT,IMPILB+1,OCT,IMPILB+2 + MOVE B,IMPCLN ;Get link msg came in on + CAIN B,233 ;Internet link? + AOS IMNIP8 ;Yes, count IP meter + CAIN A,8. ;Error identified with a particular message? + JSP T,IMPBLD ;Decrement count of active messages + JRST IMPIRT + +;;; IMP->Host Type 2 - IMP going down + +IMPGD: LDB B,[420200,,IMPILB+2] ;Reason (see 1822) + MOVEM B,IMPDWN + LDB B,[360400,,IMPILB+2] ;How soon going down * 5 mins + MOVE H,B + IMULI B,5*60.*30. ;Ticks in 5 mins + ADD B,TIME + MOVEM B,IMPDWN+1 + LDB C,[241200,,IMPILB+2] ;How long to be down * 5 minutes + MOVE Q,C + IMULI C,5*60.*30. ;Downtime in ticks + ADD C,B ;Add to time down + MOVEM C,IMPDWN+2 ;Store time when will be up + IMULI H,5 ;Minutes + IMULI Q,5 + BUG INFO,[IMP: Going down in ],DEC,H,[mins for ],DEC,Q,[mins, reason],DEC,IMPDWN + JRST IMPIRT + +;;; IMP->Host Type 4 - NOP + +IMPIN: JRST IMPIRT ;One more NOP from IMP + +;;; IMP->Host Type 5 - RFNM (Ready For Next Message) + +IMPRFN: JSP T,IMPBLD ;Decrement outstanding message count for host + MOVE A,IMPCLN ;Get link # + CAIE A,233 ;IP link number? + JRST IMRFNX ;No, skip IP code + AOS IMNIPR ;Bump count of IP RFNMs received + JRST IMPIRT ; and do nothing else about it, ugh. + +IMRFNX: BUG INFO,[IMP: Spurious RFNM from ],OCT,IMPHTN(H),[link],OCT,IMPCLN + AOS IMNSRF + JRST IMPIRT + +;;; IMP->Host Type 6 - Host Down Status +; H/ host index + +IMPHDS: LDB A,[301400,,IMPILB+2];Bits 65-76 of leader, 4.9-3.7 3rd word + HRRM A,IMPHTB(H) ;Store, hope user read RFC 611 + JRST IMPIRT + +;;; IMP->Host Type 7 - Destination Host Dead + +IMPDHD: MOVEI E,%NCDED + JRST IMPHNR + +;;; IMP->Host Type 9 - Incomplete Transmission + +IMPINC: LDB T,IMSTBP ;Get subtype field (4 bit reason for failure) + AOS IMPM9S(T) ;Bump count of subtypes + MOVEI E,%NCINC ;This is an incomplete msg response + +IMPHNR: JSP T,IMPBLD ;Decrement active IMP msg count for this host + MOVE A,IMPCLN ;Link for this message? + CAIE A,233 ;IP Link? + JRST IMPHN1 + CAIN E,%NCINC ;Yes, count IP meters + AOS IMNIP9 + CAIN E,%NCDED + AOS IMNIP7 + JRST IMPIRT + +IMPHN1: BUG INFO,[IMP: DHD or IT msg rcvd on non-IP link] + JRST IMPIRT + +;;; IMP->Host Type 10 - Interface Reset + +IMPIRS: PUSHJ P,IMPHTI ;Initialize host table + BUG INFO,[IMP: Interface reset] + JRST IMPIRT + + +;;; IMP->Host Type 0 - Regular Host-Host message +; Unless the source host screwed up and sent a dataless message, +; there is at least one word waiting to be read in the buffer. +; +IMPRM: SKIPG A,IMPIBC ;Get available input word count + JRST IMPIRT ;None left, just ignore message + MOVE B,IMPCLN ;Is link number the magic cookie for IP? + CAIE B,233 + JRST IMPIRT ;No, ignore it + +;IP datagram. Copy into IP buffer and pass it up. +; + AOS IMNIPI ;Bump count of IP datagrams received + PUSHJ P,IPGIPT ;Ask IP for buffer of size (A) + JRST [ AOS IMNIPF ;Punted, bump cnt of datagrams lost + JRST IMPIRT ] ;Flush this message (err msg already printed) + MOVE B,PK.BUF(A) ;Destination + HRL B,IMPIBP ;Source + MOVE C,IMPIBC ;Input words available + ADDI C,-1(B) ;Last destination address + BLTUB B,(C) ;Copy and reformat data to IP buffer + MOVE B,IMPIBC ;Get word count back to B + SETZB C,IMPIBC ;Say zero offset to IP header, and clear count. + MOVE J,IMPCSH ;Set idx to host-table entry dgm received from. + PUSHJ P,IPRDGM ;Hand off rcvd datagram to IP + JRST IMPIRT ;Return from PI level, setting up for next msg + +;Start listening for new input from IMP +; +IMPIST: HRREI T,-IMPBFS*2 + IOWRI T,%LHIWC ;Read up to a buffer full of data + MOVEI T,+<4*> + IOWRI T,%LHICA ;Read data to here + MOVEI T,%LHIE\%LHHRC\%LHSE\%LHGO ;Interrupt, store data, go + IOWRI T,%LHICS ;Start read + RET + + +SUBTTL ARPANET OUTPUT INTERRUPT LEVEL + +;Here on unvectored interrupt caused by call to IMPIOS + +IMPINT: AOS IMCT1 ;Count unvectored interrupts + JRST IMPOBZ ;Go try to start output + ;Returns directly to interrupt dispatcher + +;First-level interrupt handling, from hardware dispatch. +; Crash on severe interface errors +; Restart IMP on ready line flappage. +; Else, go look for more output to send. + +IFN NETCHN-UTCCHN,.ERR NETCHN assumed == UTCCHN at IMPOBK + + EBLK +IMPOBK: 0 + BBLK + JSR UTCSAV ;Save AC's, get a stack + AOS IMCT3 ;Count output interrupts + IORDI TT,%LHOCS ;Get CS register + TRNE TT,%LHERR\%LHNXM ;Interface lost? + JRST IMPOEC ;Try cycling + TRNE TT,%LHMRE ;Somebody bounce a ready line? + JRST IMPOER +IMPOBE: TRNN TT,%LHRDY ;Device ready for new operation? + JRST IMPOEC ;Try cycling + PUSHJ P,IMPOBZ ;No IMP error. Perform planned action. + JRST IMPEX ;Dismiss interrupt. + +;Error while outputting datagram. Currently, just means ready line flapped. +; If IMP was up, finish up IP output if necessary to free buffer, then +; cycle the interface. +; If trying to send NOPS to come up, just send a few more to resynch. +; +IMPOER: SKIPE IMPUP ;IMP up? + JRST IMPOE1 ;Not running normally, maybe OK. + BUG INFO,[IMP: Output RDY error] +IMPOEC: SKIPE A,IMPODP ;Have an output datagram ? + PUSHJ P,IPIODN ;Yep, release it. + SETZM IMPOS ;Doing nothing useful + JRST IMPRST ;Go poke SYSJOB to cycle the IMP + +;Here if interface wasn't fully up. +IMPOE1: MOVE T,IMPOS + CAIE T,%ISONP ;Were we sending a NOP? + BUG CHECK,[IMP: Confusing output error] + SOS IMNOPC ;Add another NOP to make up for this one + SETZM IMPOS ;NOt doing anything anymore + JRST IMPOBE ;Go continue processing. + +;IMPOBZ - Toplevel output processing routing. +; Called from output done interrupt handler or from MP/CLOCK level with +; NETOFF to start output. + +IMPOBZ: SKIPL B,IMPOS + CAIL B,IMPODL + BUG HALT,[IMP: Bad output state] + JRST @IMPODT(B) + +IMPODT: OFFSET -. +%ISODL:: IMPOB0 ; 0 Idle, look for something to send +%ISONP:: IMPOB1 ; 1 Finished NOP +%ISOID:: IMPOB2 ; 2 Finished IP datagram messge +IMPODL::OFFSET 0 + +;Here when interrupt has finished processing a complete message. +; Attempt to find something else to do. +; +IMORET: + ;JRST IMPOB0 ;Fall through to try for more + +; Idle - Look for output to send. First ensure we can send stuff, +; then try things in the order: +; (1) Send NOP if net coming up +; (2) Check IP datagram queue +; +IMPOB0: HRRZ T,IMPUP ;Get current IMP state. + CAIE T,-2 ;Don't say it's up when it's still going down + CAIN T,1 ;or when it is broken + JRST IMPOBN + + ; First check to see if NOP needs to be sent. + AOSG IMNOPC ;Check to see if sending NOPs + JRST IMONOP ;Output a NOP + SETZM IMPUP ;Say IMP is up + SETZM IMPTCU ;Say no longer trying to come up + + ; Now see if there is any real traffic to send + PUSHJ P,IPGIOQ ;Check IP. Get IP IMP output queue entry if any + JRST IMPOBN ;Nothing there, we're done. + + ; Returns A/ ptr to IP dgm struct + ; B/ BLKO pointer to 32-bit words (unused) + ; C/ Arpanet address + ; + ;Build an IMP-format datagram at IMPOBF. + ; Set correct address in prototype leader. + ; BLT and reformat leader to IMPOBF. + ; BLT and reformat datagram to IMPOBF + leader size. + + MOVEM A,IMPODP ;Save ptr to datagram being output + AOS IMNIPO ;# of IP datagrams sent + + ;Put together the IMP leader in IMOLDR. +IFN 0,[ ;First and third word initialized at assembly time + MOVE B,[17_10.,,0] ;Regular message + MOVEM B,IMOLDR + MOVSI B,233_10. ;IP link # in left 8 bits + MOVEM B,IMOLDR+2 ;Set up third word +] + AND C,[<377_16.>+377] ;Mask out all but host and IMP field + LSH C,4. ;Move net address to correct field + MOVEM C,IMOLAD ;set up second word of leader + + ;Copy leader and datagram to IMPOBF + MOVE B,[IMOLDR,,IMPOBF] + BLTBU B,IMPOBF+IMPLDS-1 ;Move IMP leader into place + MOVS B,PK.BUF(A) ;SOURCE,,COUNT + MOVEI A,IMPLDS(B) ;Size including leader to A + HRRI B,IMPOBF+IMPLDS ;Put d'gram immediately after leader. + BLTBU B,IMPOBF-1(A) + PUSHJ P,IMPSOH ;Go start hardware + MOVEI C,%ISOID ;Remember we are outputting IP leader + MOVEM C,IMPOS + POPJ P, + + + +;Here if nothing to output. +; Flag output inactive and disable interface +; +IMPOBN: SETOM IMPOAC ;No more output + IORDI TT,%LHOCS + TRZ TT,%LHIE\%LHGO ;Deactivate interface for a bit + IOWRI TT,%LHOCS + POPJ P, + +;IMONOP - Send a NOP, here from IMPOBZ only. +; +IMONOP: MOVEI A,IMPNOS ;Length of NOP message + MOVE B,[IMPNOP,,IMPOBF] ;BLT (and reformat) NOP to output buffer + BLTBU B,IMPOBF-1(A) + PUSHJ P,IMPSOH ;Start output of (A) words from IMPOBF to IMP + MOVEI C,%ISONP ;Set correct output FSM state + MOVEM C,IMPOS + POPJ P, + +;Prefabricated NOP Host-IMP leader +IMPNOP: 17_10.,,4_4 ;New format, type 4 = NOP + 0 + 0 ;No padding required on regular messages +IMPNOS==.-IMPNOP + +;Finished sending NOP, from IMPOBZ +; +IMPOB1: SETZM IMPOS ;Reset state + JRST IMORET ;Go look for something else to do. + +;Was sending IP datagram, from IMPOBZ +; +IMPOB2: SETZB A,IMPOS ;Reset output state. + EXCH A,IMPODP ;Get active datagram and reset pointer + PUSHJ P,IPIODN ;Tell IP level that datagram was output + JRST IMORET ;Go see if there is anything else to do. + +;Start output hardware. +; A/ Count of PDP10 words to write to net. +; Data to output in IMPOBF. +; Must be NETOFF or at NETCHN interrupt level. Bashes A only. + +IMPSOH: ASH A,1 ;Convert PDP10 word count to... + MOVNS A ; negative unibus word count. + IOWRI A,%LHOWC ;Tell the interface + MOVEI A,+<4*> + IOWRI A,%LHOCA ;Unibus address of output buffer + MOVEI A,%LHIE\%LHELB\%LHGO ;Enable interrupts, send EOM, GO + IOWRI A,%LHOCS ;Start DMA transfer + POPJ P, ;And forget it. + +SUBTTL ARPANET CLOCK LEVEL + +IMRSTO: RET ;Nothing to do any more? + +OVHMTR UUO + +;NETHST (HOST INFO) +; ARG 1 - HOST => VAL 1 - STATUS, VAL 2 - HOST NUMBER +; ARG 1 - -1 => VAL 1 - (STATUS), VAL 2 - OUR HOST NUMBER +;NOT CURRENTLY IMPLEMENTED- ARG 1 - -1, ARG 2 - OUR GOING-DOWN REASON +; +ANETHST:HRRE T,A ;Let immediate -1 win (777777 not a valid host) + AOJE T,ANETH2 ;Jump if want local status and host number + MOVE T,A + JSP J,STDHST ;Standardize and error-check host number + MOVE B,T ;Return new format + TLO B,(NW%ARP) + MOVEI H,LIMPHT-1 + CONO PI,NETOFF ;Do we have status for this host? + CAME T,IMPHTN(H) ;Scan table + SOJGE H,.-1 + JUMPGE H,ANETH1 ;Yes, return it + CONO PI,NETON ;No, have to go get it + MOVEM T,SRN3(U) + POPJ P, ;Oh, too bad + +;Here to return status of foreign ARPAnet host +ANETH1: MOVE A,IMPHTB(H) ;Get status + CONO PI,NETON + EXCH A,B + CALL CVH2NA ;Convert to HOSTS2 for compat + EXCH A,B + JRST LSWCJ1 ;Return IMSOC, NETLST if not done already + +;Here to return our status, host +ANETH2: +REPEAT 0,[ + CAIL W,2 ;(This is a crock) + MOVEM B,NTHDSW ;If 2 args, set our reason for going down. +] + SKIPE IMPUP ;Fake up our status + TDZA A,A ;We're down + MOVSI A,2000 ;We are up + MOVEI B,IMPUS ;And our host umber + JRST POPJ1 + + +;NETIMP (REASON,TIMEDOWN,TIMEUP) READ/SET +; +ANETIM: JUMPLE W,ANETM1 ;No args, return current data + CAIGE W,3 ;Must have 3 args if any + JRST OPNL30 + MOVEM A,IMPDWN ;Set data + MOVEM B,IMPDWN+1 + MOVEM C,IMPDWN+2 + JRST POPJ1 + +ANETM1: MOVE A,IMPDWN ;Get data to return + MOVE B,IMPDWN+1 + MOVE C,IMPDWN+2 + SKIPE IMPUP ;Note current condition of IMP, too + TLO A,400000 + JRST POPJ1 diff --git a/src/system/impold.wthncp b/src/system/impold.wthncp new file mode 100755 index 00000000..bcc9905a --- /dev/null +++ b/src/system/impold.wthncp @@ -0,0 +1,1974 @@ +;;; -*- Mode:MIDAS -*- +SUBTTL ARPANET HARDWARE DEFINITIONS + +IFNDEF BLIMPP,BLIMPP==INETP ; Use IMP blockage avoidance code +IMPVRS==.IFNM2 ; Version of IMP/NCP code + +IFN KAIMP,[ +; Hardware description of AI-KA/ML/MC IMP interface, device "IMP". +; For a more detailed description, see AI Hardware Memo #10, +; "ARPA Network Interface". +; In particular, the "channel 1 multiplexing" feature of the ITS KA's +; is used, so that: +; When PI level 2 (NETCHN) is assigned, the IMP interface takes +; all interrupts on the normal channel (goes to IMPINT). +; When PI level 1 (IMPCHN) is assigned, +; IMPID+(-IMPLIW) => Pseudo channel 4, location 70 (IMPILC)-> various +; IMPOD => Pseudo channel 5, location 72 (IMPOLC)-> various +; else normal PI channel 1 (PI0LOC+2)-> IMPBRK + +; CONI bits - starred items cause interrupt on PIA channel + ; 1.1-1.3 => PIA +IMPID==10 ;* INPUT DONE - Turned on when interface has word for DATAI +IMPI32==20 ; Input in 32 bit mode +;IMPIB==40 ; Input Busy +IMPOD==100 ;* OUTPUT DONE - Interface has finished giving word to IMP +;IMPO32==200 ; Output in 32 bit mode +;IMPOB==400 ; Output Busy +IMPERR==1000 ;* Imp Error (interrupt if IMPIC zero) +IMPR==2000 ;* Imp Ready (interrupt if IMPIC set) +;IMPIC==4000 ; Imp interrupt condition (0 = int on IMPERR, 1= int on IMPR) +IMPHER==10000 ;* Host Error (interrupt if IMPIHE zero) +;IMPHR==20000 ; Host Ready +;IMPIHE==40000 ; Inhibit interrupt on Host Error (IMPHER) +IMPLW==100000 ;* Last Imp Word + +; CONO bits - starred flags are always copied directly to set states + ;* 1.1-1.3 => PIA set from these bits +IMPIDC==10 ; Clear Input Done +IMI32S==20 ; Set input to 32 bit mode +IMI32C==40 ; Clear input in 32 bit mode +IMPODC==100 ; Clear Output Done +IMO32S==200 ; Set output to 32 bit mode +IMO32C==400 ; Clear output in 32 bit mode +IMPODS==1000 ; Set Output Done +IMPIR==4000 ;* Copied to IMPIC; 1= Enable int on imp ready +IMPHEC==10000 ; Clear Host Error +;IMIIHE==40000 ;* Copied to IMPIHE; 1= Inhibit int on host error +IMPLHW==200000 ; Set Last Host Word (do this before last DATAO of msg) + +];DMIMP + IFN DMIMP,[ ;HARDWARE DESCRIPTION OF DM IMP INTERFACE (PER RMM) + +; Note that all PI level 2 interrupts go to normal ITS location +; and thence vectored to IMPINT. +; However, PI 1 interrupts go to different places: +; Input Done -> loc 70 (IMPILC) +; Output Done -> loc 72 (IMPOLC) +; Control -> Should never get control interrupt at PI 1. +; Thus for example "Last Imp Word" interrupts go to +; IMPINT even though input side PIA is 1, because LIW is +; a control interrupt and control ints are always kept at PI 2. + + ;IMP INTERFACE CONO FLAG DESCRIPTION + +;COMMON FLAG BITS TO CONTROLLER + + ;18-> 0 FOR INPUT SIDE, 1 FOR OUTPUT SIDE + ;19->CLEAR TEST MODE (200000) + ;20->SET TEST MODE (100000) + + ;21->CLEAR HOST READY + ;22->SET HOST READY (20000) + ;23->CLEAR IMP-WAS-DOWN (10000) + + ;24->FI DEVICE RESET (CLEAR ALL INPUT AND OUTPUT FLAGS) (4000) + +;CONO FI (424) TO OUTPUT SIDE + ;BIT ;18->IS '1' INDICATING TO OUTPUT + ;25->CLEAR OUTPUT 32-BIT MODE + ;26->SET OUTPUT 32-BIT MODE + + ;27->SET OUTPUT EOT (CLEAR DONE, SET BUSY) (400) + ;28->SET OUTPUT DONE (200) + ;29->RESET OUTPUT (CLEAR ALL OUTPUT FLAGS) (100) + + ;30-32->CONTROL PI ASSIGNMENT + + ;33-35->OUTPUT DONE PI ASSIGNMENT + +;CONO FI (424) TO INPUT SIDE + ;BIT ;18->IS '0' INDICATING TO INPUT + ;25->CLEAR 32-BIT MODE (2000) + ;26->SET 32-BIT MODE (1000) + + ;27->SUSPEND INPUT (400) DATAI WONT SET BUSY NOW + ;28->SET INPUT BUSY (LISTENING TO NETWORK) (200) + ;29->RESET INPUT (CLEAR ALL INPUT FLAGS!) (100) + + ;30-32->CONTROL PI ASSIGNMENT + + ;33-35->INPUT DONE PI ASSIGNMENT + + ;FI CONI FLAG DESCRIPTION + + ;BIT ;00->TEST MODE IS ENABLED + ;08->OUTPUT IS IN 32-BIT MODE + ;17->INPUT IS IN 32-BIT MODE + + ;18->IMP IS DOWN + ;19->IMP WAS DOWN + ;20->HOST READY (?) + + ;21->OUTPUT EOT ON + ;22->OUTPUT BUSY + ;23->OUTPUT DONE + ;24-26->OUTPUT-DONE PI ASSIGNMENT + + ;27->INPUT EOT ON + ;28->INPUT BUSY + ;29->INPUT DONE + + ;30-32->CONTROL INTERRUPT PI ASSIGNMENT + + ;33-35->INPUT DONE PI ASSIGNMENT + +; SYMBOL ASSIGNMENTS FOR DM HARDWARE + +; CONO BITS + +FIIN==000000 ;(SIC) SPECIFY CONO FOR INPUT +FIOUT==400000 ;SPECIFY CONO FOR OUTPUT SIDE +;FITSTC==200000 ;CLEAR TEST MODE +;FITSTS==100000 ;SET TEST MODE + +;FIHSTC==040000 ;CLEAR HOST READY +FIHSTS==020000 ;SET HOST READY +FIIWDC==010000 ;CLEAR "IMP WAS DOWN" + +FIRSET==004000 ;DO LOCAL IOB RESET FOR FI DEVICE + +;INPUT SIDE ONLY + +FII32C==002000 ;CLEAR 32 BIT MODE, INPUT +FII32S==001000 ;SET 32 BIT MODE, INPUT + +FISUSP==000400 ;"SUSPEND INPUT" CLEAR FLAG, NOT SET BUSY +FIIBSY==000200 ;SET INPUT BUSY, ALLOWS BITS IN FROM IMP +FIIDC==000100 ;CLEAR INPUT DONE + +; 0000X0 ;CONTROL PIA + +; 00000X ;INPUT DONE PIA + +;OUTPUT SIDE ONLY + +FIO32C==402000 ;CLEAR 32 BIT MODE, OUTPUT +FIO32S==401000 ;SET 32 BIT MODE, OUTPUT + +FILHW==400400 ;SET "LAST HOST BIT TO IMP" +FIODS==400200 ;SET OUTPUT DONE +FIODC==400100 ;CLR OUTPUT DONE + +; 0000X0 ;CONTROL PIA + +; 40000X ;OUTPUT DONE PIA + +; CONI BITS + +; LEFT HALF OF CONI WORD FOR FOLLOWING 3 BITS + +;FITSTM==400000 ;TEST MODE IS ON +;FIO32==001000 ;OUTPUT IS IN 32 BIT MODE +FII32==000001 ;INPUT IS IN 32 BIT MODE + +; RIGHT HALF OF CONI + +FIDOWN==400000 ;IMP IS DOWN +FIWASD==200000 ;IMP WAS DOWN (OR IS) SINCE LAST RESET +;FIHSTR==100000 ;HOST READY IS SET ON + +;FIOEOT==040000 ;OUTPUT LAST IMP BIT IS ON +;FIOBSY==020000 ;OUTPUT IS BUSY AFTER DATAO +FIOD==010000 ;OUTPUT IS DONE, (INTERRUPTING) + +; 00X000 ;OUTPUT DONE PIA + +FILW==000400 ;LAST BIT SET FROM IMP +FIIBSY==000200 ;INPUT IS BUSY, WORD BEING ASSEMBLED FROM IMP +FIID==000100 ;INPUT IS DONE (INTERRUPTING) TO DO DATAI + +; 0000X0 ;CONTROL PIA + +; 00000X ;INPUT PIA + +IMPLW==FILW ;USEFUL TO TEST IN AC +IMP==FI ;USEFUL FOR BLKO, DATAO INSTR +] + +; IMP 1822 PROTOCOL INFORMATION (EXTENDED-LEADER VERSION) + +; The IMP leader is 96 bits long, usually organized as 3 words of 32 bits. +; For further details, these documents are available from the Network +; Information Center: +; IMP-HOST protocol: BBN Report No. 1822 +; NCP protocol: NIC 8246, Host-to-Host Protocol for the ARPANET +; IP, TCP: Internet Protocol Transition Workbook, and +; Internet Protocol Implementor's Guide +; +; For the benefit of the NCP code, ITS reads in the leader as 36-bit words +; with sufficient IMP padding (5 16-bit wds) to cause NCP data to be aligned +; on a word boundary. The first 4 words of the leader are read +; in 36-bit mode: +;------------------------------------------------------------------------ +;1: 4.9-4.6 not used (0) +; 4.5-4.2 all 1's for new format, else old msg type (4=old nop) +; 4.1-3.3 network number (0) +; 3.2-2.8 not used (0) +; 2.7 trace (ignored) +; 2.6-2.4 leader flags (2.6 is to be ignored, 2.5-2.4 are not used!) +; 2.3-1.5 message type (as of yore, but more bits) (see IMTDT) +; 1.4-1.1 high 4 bits of handling type (0) +; +;2: 4.9-4.6 Low bits of handling type (7 for big buffers, 4 for small buffers, +; 4.5-3.7 host number and 0 for the control link) +; 3.6-1.9 Imp number +; 1.8-1.1 Link number (high 8 bits of message-id) +; +;3: 4.9-4.6 Low 4 bits of message-id (0) +; 4.5-4.2 Sub-type +; 4.1-2.4 Message length (ignored) +; 2.3-1.1 Padding +;------------------------------------------------------------------------ +; All non-regular messages (ie Host-Imp, not Host-Host) +; stop here, since padding and data only exist for regular +; messages (Type 0). +;------------------------------------------------------------------------ +;4: 4.9-1.1 Padding +;------------------------------------------------------------------------ +; At this point there are still 32 bits of padding left. The +; Internet Protocol messages are vectored off here (they are +; identified by a message-type of 0 and a link-number of 233). +;------------------------------------------------------------------------ +; HOST-HOST REGULAR MESSAGES +; NETWORK CONTROL PROTOCOL (NCP) - read in 36-bit mode +;5: 4.9-1.5 Padding +; 1.4-1.1 M1 Host-host padding +; +;6: 4.9-4.6 M1 Host-host padding ; NCP leader contained in this word. +; 4.5-3.7 S Byte size +; 3.6-1.9 C Byte count +; 1.8-1.1 M2 Host-host padding +;------------------------------------------------------------------------ +; HOST-HOST REGULAR MESSAGES +; INTERNET PROTOCOL (IP) - read in 32-bit mode +;5: 4.9-1.5 Padding +;6: 4.9-1.5 First word of IP datagram +;------------------------------------------------------------------------ + +;In message types 2 and 6, the going-down status 16-bit word is +;in word 2 1.8-1.1 and word 3 4.9-4.2. + +;4.5-4.2 of word 3 are the padding count for type 4 (nop) from host. +;This is 5. Padding is only put on type-0 messages. + +IMTBP: 041000,,IMPILB+0 ;BYTE POINTER FOR MESSAGE TYPE FIELD +IMOTBP: 340400,,IMPILB+0 ; Byte ptr for message format type +IMLNBP: 001000,,IMPILB+1 ;BYTE POINTER FOR LINK NUMBER FIELD +IMSABP: 103000,,IMPILB+1 ; Byte ptr for source address field (host+imp) +IMSHBP: 301000,,IMPILB+1 ;BYTE POINTER FOR SOURCE HOST FIELD +IMSIBP: 102000,,IMPILB+1 ;BYTE POINTER FOR SOURCE IMP FIELD +IMSTBP: 340400,,IMPILB+2 ; Byte ptr for subtype field +IMCBBP: 301000,,IMPILB+5 ;BYTE POINTER FOR CONNECTION BYTE SIZE FIELD +IMBCBP: 102000,,IMPILB+5 ;BYTE POINTER FOR BYTE COUNT FIELD + + +SUBTTL ARPANET VARIABLES AND TABLES + +IFN NCPP,[ +IMPSTL==NNETCH ;SOCKET TABLE LENGTH (MUST BE .LE. 70) +IFG NNETCH-70,.ERR NNETCH SHOULD BE LESS THAN 70 OCTAL, PER BBN SPECS +];NCPP + +IFN INETP,[ +IMPCLP: 0 ; HACK!! # to use for control-link link field. +] +EBLK + +IMPN:: ;IMP DATA AREA CLEARED WHEN IMPUP +IFN INETP,[ +%IMXLN==:<<8159.-96.>+31.>/32. ; Max # of 32-bit words in IMP regular msg, + ; exclusive of leader and leader padding. = 252. +IMPIBS: 0 ; Saved initial BLKI pointer for IP datagram read +IMPIDP: 0 ; Pointer to IP datagram being input at PI level +IMPODP: 0 ; Pointer to IP datagram being output at PI level +IMPPSW: 0 ; Flip-flop to alternate output of IP and NCP msgs +] +IFN KAIMP,[ +IMPI: 0 ;-1 => IMPCHN INPUT INTERRUPT OCCURRED +IMPO: 0 ;-1 => IMPCHN OUTPUT INTERRUPT OCCURRED +IMPB: 0 ;-1 => IMPCHN FLAG INTERRUPT OCCURRED +IMPIH: 0 ;-1 => INPUT WANTS PIA = IMPCHN +IMPOH: 0 ;-1 => OUTPUT WANTS PIA = IMPCHN +] +IMPIS: 0 ;INPUT STATE + %ISIDN==:-1 ; Network shut off + %ISIDL==:0 ; Normal - idle, not expecting input (i.e. between msgs) + %ISIGN==:1 ; Ignore input until end of current message (36 bit mode) + %ISIML==:2 ; Reading IMP initial leader (36 bit mode) + %ISINC==:3 ; Reading NCP control message (32 bit mode) + %ISIND==:4 ; Reading NCP data message (32 or 36 bit mode) + %ISINL==:5 ; Reading NCP-type IMP leader (36 bit mode) + %ISIIL==:6 ; Reading IP-type IMP leader (32 bit mode) + %ISIID==:7 ; Reading IP datagram (32 bit mode) + +IMPOS: 0 ;OUTPUT STATE + %ISODL==:0 ; Not expecting output done (i.e. between messages) + %ISONC==:1 ; Sending NCP control message + %ISOND==:2 ; Sending NCP data message + %ISOID==:3 ; Sending IP Datagram + +IMPHI: 0 ;-1 TO HOLD UP INPUT + ;-2 INPUT IS SUCCESSFULLY HELD UP +IMRFCT: 0 ;NUMBER OF HOST TABLE ENTRIES WITH PENDING + ;TIMEOUTS FOR CONTROL-LINK RFNM OR RST-RRP. + +; ACTIVE HOST TABLE. Entries herein are allocated as needed, using garbage +; collection. Most "host number" fields are really indices into +; this table. +LIMPHT==+ ; NCP conns plus TCP conns plus a few extra +IMPHTN: BLOCK LIMPHT ; Host number. 1.1-1.8 HOST, 2.1-3.7 IMP +IMPHTB: BLOCK LIMPHT ;BITS: + ;4.9 1=RFNM WAIT ON LINK 0 (NCP) + ;4.8 GC MARK BIT + ;4.7-4.3 UNUSED + ;4.2-4.1 STATUS OF HOST 0 DOWN, 1 RST SENT, 2 UP + ;3.9-3.1 TIME (MOD 2**9) LAST RFNM SENT ON LINK 0 (NCP) + .SEE IMPHDS ;RH LAST MESSAGE FROM IMP ABOUT "HOST DEAD STATUS" +IMPHTC: BLOCK LIMPHT ; # active messages outstanding for host (8 max) +IMPHTT: BLOCK LIMPHT ; Time of last RFNM received + +IMNCS: 0 ;NUMBER OF CHANNELS BEING CLOSED +IMNAS: 0 ;NUMBER OF CHANNELS WITH 4.8 IN IMSOC5 SET +LIMPN==.-1 ;LAST LOCATION BLT'ED TO ZERO WHEN INITIALIZED +IMNBLK: 0 ; Number of times blockage avoided (output held up by ITS) +IMPHTF: -1 ;HOST TABLE FREE LIST, THREADED THROUGH IMPHTB, END WITH -1 +IMPUP: -1 ;0 => IMP UP ;-1 => DOWN ;-2 => COMING UP, PI LVL STILL OFF + ;1 => DOWN FOR GOOD, UNTIL NEXT TIME IMP READY LINE CHANGES +IMPTCU: 0 ;0 IMP UP/DOWN STATUS NOT CHANGING + ;>0 TRYING TO REINITIALIZE, SYS JOB HASN'T DONE SO YET + ;-1 HAS BEEN REINITIALIZED, HAVEN'T EXCHANGED NOPS YET +IMPUCT: 0 ;IMP COMING UP TIMEOUT, IF 4 NOOPS DON'T GO THROUGH PROMPTLY. +IMPDWN: BLOCK 3 ;LAST MESSAGE FROM IMP THAT IT IS GOING DOWN + ;WD0 "REASON" CLAIMED BY IMP (SEE CH 3 OF BBN REPORT 1822) + ;WD1 TIME WHEN EXPECTED DOWN + ;WD2 TIME WHEN EXPECTED UP (SYS TIME=1/30 SEC SINCE UP) +IFN KAIMP,IMPPIA: 0 ;CURRENT IMP PIA +IMPCNI: 0 ;CONI INTO HERE AT SLOW CLOCK LEVEL +IMERCN: -1 ;CONI INTO HERE WHEN NET GOES DOWN +IMNOPC: 0 ;< 0 => SEND NOPS +IMPA: 0 ;SAVE A AT IMPCHN PI LEVEL +IMPOAC: -1 ;-1 => OUTPUT INACTIVE +IMPERB: BLOCK 5 ;LAST "ERR" MESSAGE FROM A HOST + ;WD 0 TIME WHEN RCVD, WD 1 HOST, WD2-4 11. 9-BIT BYTES OF DATA +IFN DMIMP,IMPSUS: 0 ;HOLDS INPUT WORD WHILE INPUT IS HELD UP +IMPILB: BLOCK 6 ;INPUT LEADER BUFFER +IMPINB: BLOCK 30.+5 ;30. WORDS @ 32 BITS/WD = 120. 8 BIT BYTES + ;+5 WORDS FOR GOOD MEASURE + ;THIS BUFFER IS FOR CONTROL-LINK MESSAGES +BBLK + +IMHSBT: 330200,,IMPHTB(H) ;RST/RRP STATUS + +EBLK + +IMPCSH: -1 ;CURRENT SOURCE HOST (IMPHTB INDEX). -1 WHEN IDLE. +IMPCLN: 0 ;CURRENT LINK NUMBER +IMPCBS: 0 ;CURRENT BYTE SIZE +IMPCBC: 0 ;CURRENT BYTE COUNT +IMPNIW: 0 ;EXPECTED LAST BLKI ADDRESS +IMNWSI: 0 ;SECOND BLKI POINTER, ZERO IF NONE +IMPSVP: 0 ;SAVE PIA AT IMPRMP +IMPSVQ: 0 ;SAVE CONTROL MESSAGE QUEUE POINTER AT IMPOB2 +IMBLKI: 0 ;PLACE TO STORE BLKI POINTER +IMBLKO: 0 ;PLACE TO STORE BLKO POINTER +IMPNBI: 0 ;AMOUNT TO INCREMENT IMSMPC(I) BY, I.E. # OF DATA BYTES + ; IN MESSAGE CURRENTLY COMING IN AT P.I. LEVEL +IMPNBO: 0 ;AMOUNT TO INCREMENT IMSMPC(I) BY, I.E. # OF DATA BYTES THAT WILL BE + ; MADE FREE IN BUFFER BY MESSAGE CURRENTLY GOING OUT AT P.I. LEVEL +IMPNBT: 0 ;# BITS ACTUALLY BEING SENT, USED TO ADJUST ALLOCATION +IMPNPT: 0 ;NEW VALUE FOR IMSPIP(I) AFTER MSG IS SENT +IMPIPI: -1 ;IMSOC INDEX ACTIVE FOR INPUT AT P.I. LEVEL, OR -1 IF NONE +IMPOPI: -1 ;IMSOC INDEX ACTIVE FOR OUTPUT AT P.I. LEVEL, OR -1 IF NONE +IMOB0Z: 0 ;IMSMPP AT IMOBD1, FOR DEBUGGING + +;IMP OUTPUT LIST. EXECUTED AT PI LEVEL 1. +;NEGATIVE = BLKO POINTER, 0=STOP, 1=SET LAST WORD, 2=32-BIT MODE, 3=NOP +IMOPNT: 0 ;INDEX OF NEXT "INSTRUCTION" IN IMP OUTPUT LIST: +IMOLST: 0 ;BLKO FOR SECOND THROUGH SIXTH LEADER WORDS (FIRST IS DATAO'ED) +IMOMOD: 2 ;SWITCH TO 32-BIT MODE IF NECESSARY +IMOBK1: 0 ;FIRST BLKO POINTER +IMOBK2: 0 ;SECOND BLKO POINTER + 1 ;SET LAST WORD +IMOBK3: 0 ;THIRD BLKO POINTER (SEND LAST WORD, NOT USED WITH DM INTERFACE) + 0 ;STOP +IMOLDR: BLOCK 6 ;BUILD PREAMBLE HERE FOR DATA MESSAGES + +IMPNEA: 0 ;NUMBER OF ECOS IN COMMAND MESSAGE THAT HAVE BEEN ANSWERED +IMPNRA: 0 ;NUMBER OF RSTS ANSWERED + +;METERS +IFN INETP,[ +IMNIPI: 0 ; # of IP datagrams input (rcvd) +IMNIPF: 0 ; # of IP datagrams flushed (input threw away) +IMNIPO: 0 ; # of IP datagrams output (sent) +IMNIPR: 0 ; # of IP RFNMs received +IMNIP7: 0 ; # of IP Type 7 (Dest Host Dead) messages received +IMNIP8: 0 ; # of IP Type 8 (Error) msgs rcvd +IMNIP9: 0 ; # of IP Type 9 (Incomplete Transmission) msgs rcvd +IMNWIG: 0 ; # words ignored by "Ignore" state (%ISIGN) +IMNWIF: 0 ; # words flushed by IMPRM5 +] ;INETP +IFN NCPP,[ +IMNOSH: 0 ;# OF SHUFFLES OF NET OUTPUT BUFFERS +IMNISH: 0 ;# OF SHUFFLES OF NET INPUT BUFFERS +IMNSCM: 0 ;NUMBER OF SHORT CONTROL LINK MESSAGES +IMPNEI: 0 ;NUMBER OF ERPS NOT SENT +IMPNRI: 0 ;NUMBER OF RRPS NOT SENT +IMNRFC: 0 ;NUMBER OF RFCS CLSED +IMNRFI: 0 ;NUMBER OF RFCS IGNORED +IMNCLI: 0 ;NUMBER OF CLS IGNORED +IMNALI: 0 ;NUMBER OF ALLS IGNORED +IMNPIL: 0 ;NUMBER OF TIMES PI CONTROL QUEUE EXCEEDED +IMNCNS: 0 ;NUMBER OF CLS NOT SENT +IMNANS: 0 ;NUMBER OF ALLS NOT SENT +IMNMNC: 0 ;NUMBER OF REGULAR MESSAGES FOR NON-EXISTANT CONNECTIONS +IMNMAE: 0 ;NUMBER OF TIMES MSG ALL EXCEEDED +IMNMSS: 0 ;NUMBER OF TIMES MSG SHORT +IMNBAE: 0 ;NUMBER OF TIMES BIT ALL EXCEEDED +] ;IFN NCPP +IMPNPE: 0 ;NUMBER OF PROTOCOL ERRORS +IMNSRC: 0 ;NUMBER OF SPURIOUS RFNMS ON CONTROL LINK +IMNSRF: 0 ;NUMBER OF SPURIOUS RFNMS ON REG CONNECTIONS +IMNRFN: 0 ;NUMBER OF RFNMS NOT SENT +IMSTAS: 0 ;STATUS OF INPUT AT TIME HELD UP +IMPNIH: 0 ;NUMBER OF TIMES INPUT SUCCESSFULLY HELD UP +IMPNUH: 0 ;NUMBER OF TIMES INPUT HOLDUP UNDONE +IMRFTO==60.*30. ;RFNM WAIT TIME OUT +IFN NCPP,[ +IMNORH: 0 ;NUMBER OF STYNET OUTPUT RESETS DELAYED +;IMPRTO==30.*60. ;RESET TIME OUT (IDENTICALLY = IMRFTO) +IMPCTO==30.*30. ;CLS TIME OUT +IMFCTO==55.*30. ;RFC QUEUE TIME OUT - SHOULD BE LESS THAN 2*IMPCTO +IMPCMR: BLOCK 20 ;COUNT OF CONTROL MESSAGES RCD +IMPCMS: BLOCK 20 ;COUNT OF CTL MSG SENT +] ;IFN NCPP +IMPMSR: BLOCK 20 ;COUNT OF IMP MESSAGES RCD +IMPM1S: BLOCK 4 ; # Type 1 (Error in Leader) subtype msgs +IMPM9S: BLOCK 20 ; # Type 9 (Incomplete Transmission) subtype msgs +IMPMSS: BLOCK 1 ;COUNT OF IMP MSG SENT (WE ONLY SEND REGULAR MSGS) +IMCT1: 0 ;# TIMES AT IMPBKZ +IMCT2: 0 ;# TIMES AT IMPIBZ +IMCT3: 0 ;# TIMES AT IMPOBZ +BBLK + +SUBTTL ARPANET MAIN-PROGRAM LEVEL + +IMPINI: +IFN KAIMP,[ + CONO IMP,IMI32C + DATAI IMP,A + CONO IMP,IMPODC ;CLEAR OUTPUT DONE AND PIA + CONSZ IMP,IMPOD+7 ;CHECK OUTPUT DONE, PIA, CAUSE HOST READY + JRST 4,. ;CONO DIDN'T CLEAR SOME BITS? + CONO IMP,IMPIR+IMPHEC ;CLEAR HOST ERR, ENABLE INT ON IMP READY +] +IFN DMIMP,[ + CONO FI,FIRSET ;RESET IMP INTERFACE, SET HOST READY + CONO FI,FIHSTS +] + SETOM IMPIPI + SETOM IMPOPI + MOVE T,TIME + ADDI T,15. + CAMLE T,TIME + PUSHJ P,UFLS ;WAIT FOR HALF SECOND +IFN KAIMP,[ + CONO IMP,0 ;CLEAR "ENABLE IMP READY" INT (TURNS OFF IMP ERROR) + MOVEI A,NETCHN ;IDLE PIA + MOVEM A,IMPPIA + MOVE A,[JSR IMPIBK] + MOVEM A,IMPILC + MOVE A,[JSR IMPOBK] + MOVEM A,IMPOLC +] +IFN DMIMP,CONO FI,FIIWDC ;CLEAR "IMP WAS DOWN" +IFN NCPP,[ + MOVSI I,-IMPSTL +IMPINA: SKIPE IMSOC6(I) + JRST 4,. + SETZM IMSOC1(I) + AOBJN I,IMPINA +] ;IFN NCPP + SETZM IMPILC+1 + SETZM IMPOLC+1 + SETOM IMPOAC + SETOM IMPUP ;NOT UP YET + MOVNI A,20. ;ALLOW 10 SECONDS TO COME UP + MOVEM A,IMPUCT + SETOM IMPTCU ;TRYING TO COME UP + SETOM IMPHTF ;WILL GC IMPHTB ON FIRST REFERENCE +IFN NCPP,[ + SETOM IMPMPU + SETOM IMPMPL + SETOM IMPNCQ + SETOM IMPLCQ + MOVEI I,IMNPIC + MOVEM I,IMFCQL + MOVEI A,IMPCQ + MOVEM A,IMFFCQ + JRST IMPIN1 + +IMPIN2: ADDI A,IMPMQS+1 + MOVEM A,-IMPMQS-1(A) +IMPIN1: SOJG I,IMPIN2 + SETOM (A) + SETOM IMPBPQ + SETOM IMPEPQ + MOVEI A,IMPPQ + MOVEM A,IMFFPQ + MOVEI I,IMNPQ + JRST IMPIN4 + +IMPIN3: ADDI A,4 + MOVEM A,-4(A) +IMPIN4: SOJG I,IMPIN3 + SETOM (A) + MOVEI A,NETSRS + MOVEM A,NRSOC +];NCPP + MOVE A,[IMPN,,IMPN+1] + SETZM IMPN + BLT A,LIMPN + SETOM IMPIS ; Say IMP shut off + MOVE T,TIME + MOVEM T,LNETIM +IFN KAIMP,CONO IMP,NETCHN +IFN DMIMP,[ + CONSZ FI,FIDOWN+FIWASD ;SKIP IF STILL UP + POPJ P, ;LOSE IF NOT IMP UP + CONO FI,FIIN\FIIBSY+NETCHN*11 + CONO FI,FIOUT+NETCHN*11 +] + SETOM IMPDWN+1 ;TIME FOR IMP TO GO DOWN, NOT KNOWN + ;MOVE T,TIME + ADDI T,15. + CAMLE T,TIME + PUSHJ P,UFLS + SETZM IMPIS ; Say up but idle + MOVNI A,4 + MOVEM A,IMNOPC ;SEND 4 NOPS +IMPOST: CONO PI,NETOFF +IFN DMIMP,[ + CONSO FI,70 ;SKIP IF PIA NON-ZERO + JRST NETONJ ;IF NO PIA, THEN DONT SET INT +] +IFN KAIMP,MOVE TT,IMPPIA ;MAIN PROGRAM OUTPUT START + AOSN IMPOAC ;SKIP IF OUTPUT ALREADY ACTIVE +IFN KAIMP, CONO IMP,IMPODS(TT) ;GENERATE OUTPUT INTERRUPT +IFN DMIMP, CONO FI,FIODS+NETCHN*11 + JRST NETONJ + +IMPIOS: +IFN KAIMP,[ + AOSE IMPOAC ;PI LEVEL OUTPUT START + POPJ P, + PUSH P,TT + CONO PI,400 ;TURN PI OFF, IMP MAY HAVE PIA = 1 + MOVE TT,IMPPIA + CONO IMP,IMPODS(TT) + CONO PI,200 + POP P,TT +]IFN DMIMP,[ + AOSN IMPOAC + CONO FI,FIODS+NETCHN*11 +] + POPJ P, + + + +;Check if IMP ready line is set +; Called from SYSJOB. +; Return +1 if IMP not ready, +2 if so +; +IMPCKR: +IFN DMIMP,[ + .ERR IMPCKR Missing for DMIMP! +] +IFN KAIMP,[ + CONSZ IMP,IMPR ;Skip if IMP not ready + AOS (P) ;Return +2 if ready + POPJ P, +] + + +SUBTTL HOST-TABLE MANAGEMENT + +; FNDHST - Look up host-table index for a given IMP host address. +; Call with NETOFF or NETCHN PI in progress. +; T/ IMP host address (maybe someday other nets?) +; Returns .+1 if failed (no room in table) +; Returns .+2 +; H/ host-table index +; Smashes W. + +FNDHST: MOVEI H,LIMPHT-1 ;SEARCH FOR AN ENTRY FOR THIS HOST + CAME T,IMPHTN(H) + SOJGE H,.-1 + JUMPGE H,POPJ1 ;FOUND + SKIPGE H,IMPHTF ;NOT FOUND, CONS ONE OFF FREE LIST + JRST FNDHS1 ;OOPS, MUST GARBAGE COLLECT + MOVE W,IMPHTB(H) +IFN INETP,[ ; Later make this check standard! + CAIGE H,LIMPHT ; Make sure H is valid idx + CAIL W,LIMPHT ; ditto W + BUG HALT,[NET: FNDHST idx clobbered!!!] +] + MOVEM W,IMPHTF + MOVEM T,IMPHTN(H) + SETZM IMPHTB(H) ;NOTHING IS KNOWN ABOUT THIS HOST + SETZM IMPHTC(H) ; Assume no RFNMs outstanding + SETZM IMPHTT(H) ; Clear out time of last RFNM. + JRST POPJ1 + +; Host-Table full, attempt to GC it and flush unused entries, by +; scanning all possible pointers into table. +; IMP pointers are IMPCSH and IMPHTC(H) +; NCP pointers are IMSOC4<3.9-4.7>, RFC queue, PI ctl msg queue, +; and the RFNM-wait and RST-sent bits in table. +; TCP pointers are XBNADR(I) + + ; GC mark phase - mark entries in use +FNDHS1: PUSH P,I + MOVSI W,200000 ;MARK BIT + MOVEI H,LIMPHT-1 ;CLEAR ALL MARK BITS + ANDCAM W,IMPHTB(H) + SOJGE H,.-1 + SKIPL H,IMPCSH ;MARK FROM IMPCSH + IORM W,IMPHTB(H) + +IFN TCPP,[ + MOVEI I,XBL-1 + SKIPL H,XBNADR(I) ; See if TCP conn has a net addr specified + IORM W,IMPHTB(H) ; Yes, set the mark bit. + SOJGE I,.-2 +] ;IFN TCPP +IFN NCPP,[ + MOVEI I,IMPSTL-1 ;MARK FROM IMSOC4 +FNDHS2: SKIPN IMSOC1(I) ;SKIP IF IMSOC4 IS BEING USED BY ANYONE + SOJGE I,FNDHS2 + JUMPL I,FNDHS3 + LDB H,IMSCFH + CAIE H,377 + IORM W,IMPHTB(H) + SOJGE I,FNDHS2 +FNDHS3: MOVE I,IMPBPQ ;MARK RFC PENDING QUEUE + JUMPGE I,[ LDB H,[101000,,3(I)] + IORM W,IMPHTB(H) + MOVE I,(I) + JRST . ] + MOVE I,IMPNCQ ;MARK CONTROL QUEUE + JUMPGE I,[ HLRZ H,1(I) + IORM W,IMPHTB(H) + MOVE I,(I) + JRST . ] +] ;NCPP + + ; GC sweep phase - free all unmarked entries + SETO I, ;FREE POINTER + MOVEI H,LIMPHT-1 + MOVSI W,601000 ;PROTECT IF RFNM-WAIT, RST-WAIT, OR MARKED +FNDHS4: + SKIPG IMPHTC(H) ; Also protect if any outstanding RFNMs + TDNE W,IMPHTB(H) + SOJGE H,FNDHS4 + JUMPL H,FNDHS5 + SETZM IMPHTN(H) ;DON'T BELONG TO ANY HOST + MOVEM I,IMPHTB(H) ;CONS ONTO FREE LIST + MOVE I,H + SOJGE H,FNDHS4 +FNDHS5: MOVEM I,IMPHTF ;FREE LIST + POP P,I + SKIPGE IMPHTF + POPJ P, ;GC-OVERFLOW + JRST FNDHST ;TRY AGAIN, SHOULD WIN + +SUBTTL ARPANET INPUT INTERRUPT LEVEL + +COMMENT | + The IMP interrupt level structure is fairly complicated and +deserves some explanation. Because the IMP interface is not a DMA +device, all I/O is done "by hand", a word at a time; for this reason +all I/O is done at PI level IMPCHN=1 (the highest) whenever possible. +However, to prevent general IMP processing from taking complete +precedence over everything else, all non-I/O handling is done at +PI level NETCHN=2, which is the same level as disk devices. + The MIT-DMS interface (DMIMP) is much more complicated than the +AI-KA/ML/MC interface and was designed to facilitate this dual-level +interrupt processing by providing different PI channel assignments +for each of 3 possible conditions: + Input Done (must usually read next word) + Output Done (must usually output next word) + Control Int (some unusual condition, including Last-IMP-Word) + +Because the non-DM interface only has one PI assignment available, +the software to switch levels is much more complicated. For either +case, the code will not make sense unless you understand the channel 1 +multiplexing feature (see interface CONI bit descriptions). +| + +; Here when IMP interface is interrupting at PI level 2 (NETCHN) +; TT has CONI bits. Can clobber most ACs + +IMPINT: +IFN KAIMP,[ + AOSN IMPB ; PI 1 control interrupt? + JRST IMPBKZ ; Yes + AOSN IMPI ; PI 1 Input Done interrupt? + JRST IMPIBZ ; Yes + AOSN IMPO ; PI 1 Output Done interrupt? + JRST IMPOBZ ; Yes already + TRNE TT,IMPLW+IMPHER+IMPERR ; No PI 1 ints, check status bits + JRST IMPBKZ ; PI 2 Control interrupt (error or Last Imp Word) + TRNE TT,IMPID + JRST IMPIBZ ; PI 2 Input Done + TRNE TT,IMPOD + JRST IMPOBZ ; PI 2 Output Done +]IFN DMIMP,[ + TRNE TT,FILW+FIWASD+FIDOWN + JRST IMPBKZ ; PI 2 Control interrupt (error or Last Imp Word) + TRNE TT,FIID + JRST IMPIBZ ; PI 2 Input Done + TRNE TT,FIOD + JRST IMPOBZ ; PI 2 Output Done +] + JRST 4,. ; Must be one of above!! + +IFN KAIMP,[ +; IMPIBK - Default PI 1 Input Done routine, called from IMPILC. +; We're idling, switch to PI 2 to handle the input +; (normally 1st word of new IMP message) +EBLK +IMPIBK: 0 +BBLK + SETOM IMPI ; Set flag saying PI 1 Input Int seen + CONO IMP,NETCHN ; Switch PIA to 2 + JRST 12,@IMPIBK ; Go re-interrupt, will get to IMPINT->IMPIBK +] + +IFN KAIMP,[ + +; IMPBRK - PI 1 Control interrupt, called from PI0LOC+2 (= 42 on KA's) +; which is the standard PI 1 vector location. +; Again, switch to PI 2 to handle the condition +; (typically Last Imp Word seen on input) +EBLK +IMPBRK: 0 ; This interrupt is to 42, may not be the IMP +BBLK + CONSO IMP,IMPLW+IMPHER+IMPERR ; This really from the IMP? +IFE NEWDTP,JRST RC1INT +IFN NEWDTP,JRST IMPBR1 + SETOM IMPB ; Yes, re-interrupt and handle at NETCHN level + CONO IMP,NETCHN ; Switch PIA to 2 (NETCHN) + JRST 12,@IMPBRK ; Go re-interrupt, will get to IMPINT->IMPBKZ + +IFN NEWDTP,[ +IMPBR1: CONSZ DTC,70 ; Allow for non-IMP interrupt on PI chan 1 + JRST 12,@IMPBRK +] + +RC1INT: MOVEM 17,R1NTAC+17 + MOVEI 17,R1NTAC + BLT 17,R1NTAC+16 + MOVEI J,1 + JSP E,SPUR + MOVSI 17,R1NTAC + BLT 17,17 + JRST 12,@IMPBRK +];IFN KAIMP + +; IMPRM4 - PI 1 Input-Done handler during readin of IMP data (not leader) +; BLKI has run out but haven't yet gotten Last Imp Word! +; Either read more (if 2nd ptr specifed) or ignore following data. +EBLK +IMPRM4: 0 +BBLK + MOVEM A,IMPA ; Save A + SKIPL A,IMNWSI ; Second BLKI pointer exists? + JRST IMPRM6 ; Nope, none now + MOVEM A,IMBLKI ; Yes, store it! + SETZM IMNWSI ; Clear this flag so don't do it again + MOVE A,IMPA ; Restore A + JRST 12,@IMPRM4 ; Return, continuing BLKI. + +IMPRM6: MOVE A,[JSR IMPRM5] ; Ugh! Ignore additional input + MOVEM A,IMPILC ; Set up new vector to "ignore" routine + MOVE A,IMPA + JRST 12,@IMPRM4 + +; IMPRM5 - PI 1 Input-Done handler while ignoring IMP data, only +; set up by IMPRM6 above. +; Just reads a word and ignores it. This loop is broken +; by a control interrupt when Last-Imp-Word is seen. +EBLK +IMPRM5: 0 ; Hmm? Flush input at PI 1 +BBLK + DATAI IMP,IMPA +IFN INETP,AOS IMNWIF ; See how often we come here. + JRST 12,@IMPRM5 + +; IMPIBZ - PI 2 (NETCHN) "Input Done" interrupt, via IMPINT. +; Note there is one input word waiting in the IMP interface, +; but it is NOT the last IMP word (if it was, we would get a +; control interrupt and go to IMPBKZ instead). This situation +; should only happen while reading the IMP leader and there is +; more input than just the leader, i.e. it is a NCP or IP message. +; This is also where we come after being in idle state. +; TT/ IMP CONI word + +IMPIBZ: AOS IMCT2 +IFN DMIMP,[ + TRC TT,IMPCHN ;FIND IF INPUT PIA=IMPCHN + TRNN TT,7 + JRST IMPRET ;YES, ALREADY HANDLED BY IMPCHN +];DMIMP +IFE INETP,[ ; Note IP datagram is read in 32-bit mode! +IFN DMIMP,TLNE TT,FII32 +IFN KAIMP,TRNE TT,IMPI32 + JRST 4,. ; NCP-only, leader should always be read in 36-bit mode +] ;IFE INETP + MOVE C,IMPHI + SKIPN B,IMPIS ; Skip hold-up check unless at start of msg (idle) + AOJE C,IMPBKW ; Jump if input needs to be held up (can only do at start or end of msg) +IFE INETP,CAILE B,%ISIML +IFN INETP,CAILE B,%ISIID + JRST 4,. ; Unknown input state + JRST @.+2(B) ; Dispatch, note data not read yet + + IMPIGN ;-1 Supposed to be shut off, go ignore message. + OFFSET -. + %ISIDL:: IMSTR1 ; 0 Was idle, this is start of a message! + %ISIGN:: IMPIGN ; 1 Ignoring this message. +IFE INETP,%ISIML:: IMPLD2 ; 2 Reading IMP leader, see what we got. +IFN INETP,[ + %ISIML:: [JRST 4,.] ; 2 Should only see %ISINL or %ISIIL + %ISINC:: [JRST 4,.] ; 3 Was reading control msg! Runout is error. + %ISIND:: [JRST 4,.] ; 4 Was reading NCP data msg! Runout is error. + %ISINL:: IMPLD2 ; 5 Was reading NCP IMP leader + %ISIIL:: IMPLD2 ; 6 Was reading IP IMP leader. + %ISIID:: [JRST 4,.] ; 7 Was reading IP datagram! Runout is error. +] ;INETP + OFFSET 0 + +IMPIGN: DATAI IMP,A ; Ignore input (only come here via table above) +IFN INETP,AOS IMNWIG ; See how often we come here. + ;JRST IMPRET + + ; All routines dispatched to from IMPIBZ should return via IMPRET. +IMPRET: +IFN DMIMP,CONI FI,A + SKIPN IMPIS ; Skip if input not in normal (idle) state +IFN KAIMP, CONSO IMP,IMPI32 ; It is, see if input is in 32-bit mode +IFN DMIMP, TLNN A,FII32 + JRST .+2 + JRST 4,. ; Shouldn't be in 32 bit mode in normal state +IFN KAIMP,CONO IMP,@IMPPIA ; Switch to desired exit PIA + JRST IMPEX + +; IMPBKZ - PI 2 (NETCHN) Control interrupt, via IMPINT. +; Error or Last Imp Word on input. +; TT/ IMP CONI word + +IMPBKZ: AOS IMCT1 ; Bump count of control interrupts +IFN KAIMP,TRNE TT,IMPERR+IMPHER ; See if error or last-imp-word. +IFN DMIMP,TRNE TT,FIWASD+FIDOWN + JRST IMPBER ; Jump if IMP Error or Host Error + + ; Not an error, interface has Last Imp Word ready for DATAI'ing! + MOVE B,IMPHI ; Check here to see if input should be held up + AOJN B,IMPBKX ; Jump if not. + + ; Input must be held up. Also enter here from IMPIBZ if + ; at start of message (only other time input can be held up). +IMPBKW: +IFN KAIMP,CONO IMP,IMPIDC ; Clear Input Done so we don't re-interrupt +IFN DMIMP,[ + CONO FI,FISUSP ; Suspend input, no bits accepted after DATAI + DATAI FI,IMPSUS ; Have to read word now + CONO FI,FIIDC+NETCHN_3 ; Have to do this to clear IMP Last Word +] ; (also to clear Input-Done PIA) + SOS IMPHI ; Set -2 to indicate successfully held up + MOVEM TT,IMSTAS ; Save status (CONI bits) + AOS IMPNIH ; Bump meter - count of times input was held up. + JRST IMPRET + +; IMPBKX - Auxiliary to IMPBKZ, PI 2 Control Interrupt +; Have got Last Imp Word and not holding up input, so go +; handle end of IMP message. + +IMPBKX: +IFN KAIMP,[ + MOVE A,[JSR IMPIBK] ; Get rid of input BLKI + MOVEM A,IMPILC ; Replace with default switch-PIA vector + SETZM IMPIH ; Say don't need PI 1 for input any more. + MOVEI A,NETCHN ; And change exit PIA to 2 + SKIPL IMPOH ; Unless output side still needs PI 1. + MOVEM A,IMPPIA ; Set value of PI level desired on exit. + CONO IMP,IMI32C ; Put back in 36 bit mode to start next msg + DATAI IMP,A ; Get the last input word for processing +]IFN DMIMP,[ + CONO FI,FII32C+FISUSP ; Hold up bits for following clear + DATAI FI,A ; Get last input word + CONO FI,FIIDC+FIIBSY+NETCHN*11 ; Now clear Last-Imp-Word +] + ; Enter here from IMOB6 if input had been held up. +IMPBKV: SKIPGE B,IMPIS ; Unless network has been shut off + JRST IMPRET ; (in which case ignore input) + JRST @IMSDT2(B) ; then go process end of IMP message. + +IMSDT2: OFFSET -. + %ISIDL:: IMPBKN ; 0 Was idle - leader only 1 word long?? + %ISIGN:: IMPIRT ; 1 Ignore input + %ISIML:: IMPLD1 ; 2 End of IMP leader - can't be regular msg + %ISINC:: IMPBK3 ; 3 End of NCP control message + %ISIND:: IMPRMB ; 4 End of NCP data input +IFN INETP,[ + %ISINL:: IMPLD1 ; 5 End of NCP IMP leader?? Probably error. + %ISIIL:: IMPLD1 ; 6 End of IP IMP leader?? Probably error. + %ISIID:: IMPRMI ; 7 End of IP datagram +] ;INETP + OFFSET 0 + +; Here from table above for old-type leader (1 word) +; IMPBN1 is used by IMPLD2 if long leader has wrong format. + +IMPBKN: MOVEM A,IMPILB ; Store first (and only) word of leader +IMPBN1: LDB A,IMOTBP ; Get message format type + CAIN A,4 ; Old-type NOP? + JRST IMPIRT ; Just ignore it. + CAIN A,16 ; Is it 1822L format? + BUG INFO,[IMP: 1822L leader],OCT,IMPILB + CAIE A,17 ; Is it not the long-leader format? + BUG INFO,[IMP: Old-type leader],OCT,IMPILB + JRST IMPIRT ; Ignore rest of message, if any + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; IMP LEADER READING/DISPATCH ;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Code on this page handles the initial processing of +;;; IMP messages and dispatches to the appropriate +;;; routines for each message type. Only Type 0 ("Regular") +;;; messages carry Host-Host traffic. + +; Here from IMPIBZ only, to handle first word of an IMP message. +; (It's not the last word or IMPBKZ would complain about it) +; Set up a BLKI to get the rest of the leader. + +IMSTR1: DATAI IMP,A ; Get 1st word from interface + ; Entry point from IMPOB6 only to restart input from "held-up" state + ; First word already in A +IMSTRT: MOVEM A,IMPILB ; Store first word of leader + MOVEI C,%ISIML ; Set new state = reading rest of IMP leader +IFE INETP,MOVE B,[-4,,IMPILB] ; If not diverting IP, ask for it all. +IFN INETP,MOVE B,[-2,,IMPILB] ; Must vector IP, ask for max 36-bit wds + JRST IMPRM9 ; Go read the leader. + +; The code at IMPLD5 will switch to 32-bit mode at right place if +; the message turns out to be an IP datagram. Otherwise the message +; is either a NCP Host-Host message, or an IMP-to-Host note of some kind; +; both stay in 36-bit mode. + +; Here from IMPBKX only for a leader not followed by any data. +; Last word in A, IMPLW flag in TT. +IMPLD1: AOS B,IMBLKI ; Update pointer to buffer + MOVEM A,(B) ; and store last word in right place. + ; Fall through to handle what should be an IMP-Host note. + ; The IMPLW flag distinguishes this entry point from IMPLD2, + ; so we know there isn't a data word in the interface. + +; Here from IMPIBZ only, for an IMP leader with more data following; +; almost certainly a "Regular" host-host message. The 2 possible +; states are: +; %ISINL - NCP, in 36-bit mode, have read 5 wds and 6th awaits. +; %ISIIL - IP, in 32-bit mode, have read 4 wds and 5th awaits. +; We can't DATAI the current word from the interface until we know +; what mode the remaining data should be read in. + +IMPLD2: +IFN KAIMP,TRNE TT,IMPI32 +IFN DMIMP,TLNE TT,FII32 +IFE INETP, JRST 4,. ; Input was in 32 bit mode when shouldn't! +IFN INETP,[JRST [MOVE B,IMPIS ; If reading IP IMP leader then 32 bit OK. + CAIE B,%ISIIL ; Leader read in 32-bit mode, must be IP. + JRST 4,. ; It isn't??? + JRST .+1] +] ;INETP + LDB T,IMOTBP ; Examine new-format flag bits of leader + CAIN A,16 ; Is it 1822L format? + BUG INFO,[IMP: 1822L leader],OCT,IMPILB + CAIE T,17 ; to verify that leader is "new" 96-bit fmt. + JRST IMPBN1 ; Something else?? Go discard. + HRRZ B,IMBLKI ;-> LAST WORD READ + CAIGE B,IMPILB+2 ;MUST BE AT LEAST 3 WORDS TO BE VALID + JRST IMPLD3 + LDB T,IMLNBP ; Extract link number (high 8 bits of msg-id) +IFN INETP,[ + CAMN T,IMPCLP ; HACK! If it matches our specified ctl link + SETZ T, ; number, then make it look like ctl link! +] + MOVEM T,IMPCLN + LDB T,IMSABP ; Get arpanet address (source host+imp) +IFN 0,[ LDB T,IMSHBP ;SOURCE HOST + LDB A,IMSIBP ;SOURCE IMP + DPB A,[112000,,T] ;FORM HOST ADDRESS +] ;ifn 0 + PUSHJ P,FNDHST ;H GETS HOST TABLE INDEX + JRST IMPLD9 ;HOST TABLE FULL + MOVEM H,IMPCSH ;SAVE CURRENT HOST + LDB A,IMTBP ;GET MESSAGE TYPE IN A + CAILE A,10. + JRST IMPUN ;UNKNOWN TYPE + AOS IMPMSR(A) ;COUNT IMP MSGS RCD + JRST @IMTDT(A) ;DISPATCH + +IMTDT: IMPRM ; 0 Regular Message + IMPBE1 ; 1 Error in Leader (no msg-id) + IMPGD ; 2 IMP Going Down + IMPUN ; 3 - + IMPIN ; 4 NOP + IMPRFN ; 5 RFNM - Ready For Next Message (transmit succeeded) + IMPHDS ; 6 Host Dead Status (general info) + IMPDHD ; 7 Destination Host Dead (transmit failed) + IMPBE8 ; 8 Error in Data (has msg-id) + IMPINC ; 9 Incomplete Transmission (transmit failed temporarily) + IMPIRS ;10 Interface Reset - IMP dropped its ready line + +IMPLD9: BUG INFO,[IMP: Message discarded due to host table full],OCT,IMPILB,OCT,IMPILB+1,OCT,IMPILB+2 + JRST IMPIRT + +; Here from IMPLD2 if leader is too short +IMPLD3: SUBI B,IMPILB-1 ;# WDS READ + BUG INFO,[IMP: Short leader, ],DEC,B,[wds. WD1=],OCT,IMPILB,[WD2=],OCT,IMPILB+1 + ;JRST IMPIRT ;FLUSH REST OF MESSAGE + +;;; IMP->Host Type 4 - NOP + +IMPIN: JRST IMPIRT ; One more nop from IMP + +;;; IMP->Host Type 10 - Interface Reset + +IMPIRS: BUG INFO,[IMP: Interface-reset msg] + JRST IMPIRT ; Probably nothing useful to do about it. + +;;; IMP->Host Type X (e.g. 3, 11-255) - bad type + +IMPUN: BUG INFO,[IMP: Unknown msg type ],OCT,A,[ leader ],OCT,IMPILB,OCT,IMPILB+1,OCT,IMPILB+2 + ;JRST IMPIRT + +IFE NCPP,[ +IMPBK3:: ;Ignore NCP messages +IMPRMB:: +];NCPP + +; Here from all over, to flush rest of this message. +; All non-regular messages (not type 0) return here, as well as some +; errors with regular msgs. +; TT says whether there is any more data to read from this message. +IMPIRT: SETZM IMPIS ; Assume end of message, reset to normal state + TRNN TT,IMPLW ; But if we haven't yet read the last word, + AOSA IMPIS ; then change state to "Ignore" and flush input. + ; Note skip over following SETZM. + +; Regular messages (type 0) return here, when we already know this message +; was completely read. TT isn't valid. +IMPIR1: SETZM IMPIS ; Reset to normal idle state + SETOM IMPCSH ; Say no current host +IFN KAIMP,CONO IMP,IMI32C ; Put world back in 36 bit input mode +IFN DMIMP,CONO FI,FII32C+NETCHN*11 + JRST IMPRET + +;;; IMP->Host Type 0 - Regular Host-Host message +; Unless the source host screwed up and sent a dataless message, +; there is a word waiting to be read from the interface. +; For IP this is the 5th word and we are in 32-bit mode. +; For NCP it's the 6th (the NCP leader) and we're in 36-bit mode. +; TT/ IMP CONI bits, +; B/ addr of last wd input (counted-out BLKI pointer) + +IMPRM: TRNE TT,IMPLW + JRST IMPRM3 ; Foo, message shouldn't end so soon. Go barf. +IFE INETP,[ + CAIE B,IMPILB+4 ; Check that host-host leader word is next in + JRST IMPLD3 ; Barf + SKIPE IMPCLN ; Skip if link 0 - NCP control msg + JRST IMPRMD ; Data message, go read into user buffer. +] +IFN INETP,[ + SKIPN A,IMPCLN ; Skip unless NCP control link message + JRST IMPRM1 ; NCP control message, go handle it. + CAIE A,233 ; Is link number the magic cookie for IP? +IFN NCPP, JRST IMPRMD ; No, go handle as NCP data message. +IFE NCPP, JRST IMPIRT ; No, ignore it if we don't have NCP + + ; This is an Internet Protocol datagram. Make sure we are + ; in right mode for reading. + AOS IMNIPI ; Bump count of IP datagrams received +IFN KAIMP,TRNN TT,IMPI32 ; Should already be in 32-bit mode +IFN DMIMP,TLNN TT,FII32 + BUG PAUSE,[IMP: Reading IP dgm in 36-bit mode] + DATAI IMP,IMPILB+4 ; Okay, read in the padding and get going. + MOVEI A,%IMXLN ; Specify max size of IMP message + ; (we can't trust msg-len leader field) + PUSHJ P,IPGIPT ; Call IP module - get input buffer pointer + JRST [ AOS IMNIPF ; Punted, bump cnt of datagrams lost + JRST IMPIRT] ; Flush this message (err msg already printed) + MOVEM A,IMPIDP ; Save datagram pointer + MOVEM B,IMPIBS ; Save input BLKI pointer for later check + MOVEI C,%ISIID ; Set state = reading IP datagram + JRST IMPRM9 ; Go do it. + +IMPRM1: CAIE B,IMPILB+4 ; NCP control message, check that NCP leader is next + JRST IMPLD3 ; Barf, short message?? +] ;INETP +IFN KAIMP,CONO IMP,IMI32S ; NCP control message, set 32-bit mode +IFN DMIMP,CONO FI,FII32S+NETCHN*11 + DATAI IMP,IMPILB+5 ; Get NCP leader word + LDB A,IMCBBP + MOVEM A,IMPCBS ; Byte size + LDB B,IMBCBP + MOVEM B,IMPCBC ; Byte count + CAIN A,8 ; Byte size should be 8 for control link + CAILE B,120. ; Byte count shouldn't be > 120. + JRST IMPBCM + ADDI B,3 + LSH B,-2 ; Number of words necessary + MOVEM B,IMPNIW ; Number of input words expected + HRLOI B,-1(B) + EQVI B,IMPINB-1 ; BLKI pointer + MOVEI C,%ISINC ; New state = reading NCP control message + +; Set up BLKI. Pointer in B, state in C. +; This place is jumped to by several things that initiate IMP input, +; specifically IMSTRT, IMPRMT, and IMPRM. + +IMPRM9: MOVEM C,IMPIS + MOVEM B,IMBLKI + MOVE B,[BLKI IMP,IMBLKI] + MOVEM B,IMPILC + MOVE B,IMPBRO(C) ; Get BLKI runout instruction and set vector; + MOVEM B,IMPILC+1 ; will execute when ptr counts out. +IFN KAIMP,[ + SETOM IMPIH ; Say that input wants high pri + MOVEI B,IMPCHN ; And set our exit PIA to it (IMP) + MOVEM B,IMPPIA +] +IFN DMIMP,CONO FI,NETCHN_3+IMPCHN ; Set control PIA = NET, input done = IMP + + JRST IMPRET + + ; This table holds the instruction to execute after the input + ; BLKI has counted out the ptr and stored the current input word. + ; Note that if the IMP message ends during the BLKI, a control + ; interrupt will happen instead and control goes to IMPBKZ->IMPBKX + ; where there is another state dispatch table. + ; Normally only %ISIML and %ISINL actually use these instructions; + ; the other states are impossible or expect to read the entire + ; remaining message. +IMPBRO: OFFSET -. + %ISIDL:: JRST 4,IMPBRO ; 0 Idle - shouldn't be BLKI'ing. + %ISIGN:: JRST 4,IMPBRO+1 ; 1 Ignore - shouldn't be BLKI'ing. + %ISIML:: + IFE INETP,JSR IMPLD4 ; 2 Reading IMP leader (5 wds partial msg) + IFN INETP,JSR IMPLD5 ; 2 Reading IMP leader (4 wds partial msg) + %ISINC:: JSR IMPRM4 ; 3 Reading NCP control message (get all) + %ISIND:: JSR IMPRM4 ; 4 Reading NCP data (get all) +IFN INETP,[ + %ISINL:: JSR IMPLD4 ; 5 Reading NCP IMP leader (partial msg) + %ISIIL:: JSR IMPLD4 ; 6 Reading IP IMP leader (partial msg) + %ISIID:: JSR IMPRM4 ; 7 Reading IP datagram (get all) +] ;INETP + OFFSET 0 + +IMPRM3: LDB B,IMBCBP ;BYTE COUNT OF EMPTY CONTROL LINK MESSAGE + JUMPE B,IMPIRT + AOS IMPNPE ;NO TEXT BUT BYTE COUNT NOT ZERO + BUG INFO,[NCP: CTL MSG NO TXT, BC NOT 0. HST ],OCT,IMPHTN(H),[BC],DEC,B + JRST IMPIRT + +IFN INETP,[ +EBLK ; PI 1 Input Done interrupt (from IMPILC+1, runout) +IMPLD5: 0 ; JSR here on BLKI runout after reading 3rd wd of IMP leader. +BBLK ; Input Done is not set, because BLKI just turned it off. + MOVEM A,IMPILC ; Save A + MOVE A,[JSR IMPLD6] ; Make very next input word interrupt to IMPLD6 + EXCH A,IMPILC ; Do it, restore A + JRST 12,@IMPLD5 + +EBLK ; PI 1 Input Done interrupt (from IMPILC) +IMPLD6: 0 ; JSR here with 4th wd of leader in interface. +BBLK ; Must decide whether to continue reading leader in + ; 36-bit mode (NCP) or 32-bit mode (IP). + MOVEM A,IMPILC ; Save A + MOVE A,IMPILB+1 ; Get word with link number in it + ANDI A,377 ; Mask off + CAIN A,233 ; Internet Protocol "link"? + JRST IMPLI3 ; Yes! Go handle it. + + ; NCP read will immediately store current 36-bit word (4th), + ; store another 36-bit word (5th), and then run out to IMPLD4. + MOVE A,[-2,,IMPILB+2] ; Reading NCP message. + MOVEM A,IMBLKI + MOVEI A,%ISINL ; Reading NCP leader, set state thereto. + MOVEM A,IMPIS + MOVE A,[JSR IMPLD4] ; And change dispatch vector. + MOVEM A,IMPILC+1 + MOVE A,[BLKI IMP,IMBLKI] + EXCH A,IMPILC ; Set up BLKI and restore A + JRST 12,@IMPLD6 ; Return. Note current input word is still waiting. + + ; IP read will immediately store current 36-bit word (4th), + ; then set up so next input-done interrupt (on 5th, 32-bit word) + ; goes directly to IMPIBZ->IMPLD2 with NETCHN PI. + ; (For AI-KA/MC/ML, perhaps by way of IMPIBK if output is active) +IMPLI3: MOVEI A,%ISIIL ; Say reading IP type leader. + MOVEM A,IMPIS +IFN KAIMP,CONO IMP,IMI32S+IMPCHN ; Set further input to 32-bit mode +IFN DMIMP,CONO FI,FII32S+NETCHN_3+IMPCHN + DATAI IMP,IMPILB+3 ; Store the 4th 36-bit word immediately; this + ; also starts interface reading the 5th word. +IFN KAIMP,[ + MOVE A,IMPLD6 ; Now must set up for next interrupt. + MOVEM A,IMPLD4 ; Fake out the common code below + JRST IMPLI4 ; Set up for next Input-Done interrupt +] +IFN DMIMP,[ + MOVE A,[JSR IMPLD4] ; Shouldn't need this, but just in case... + EXCH A,IMPILC ; Restore A, set int vector to safe rtn + CONO FI,NETCHN*11 ; DM interface can simply set Input-Done PIA! + JRST 12,@IMPLD6 +] ;DMIMP +] ;INETP + +EBLK ; PI 1 Input Done interrupt (from IMPILC+1, runout) +IMPLD4: 0 ; JSR here on BLKI runout after reading IMP leader +BBLK ; There is still one word to go, to be gotten at NETCHN level +IFN KAIMP,[ + MOVEM A,IMPILC ; Save A + ; Drop through to common code + +IMPLI4: SETZM IMPIH ; Say input no longer needs PI 1 + MOVEI A,NETCHN ; Make PI 2 (NETCHN) the exit PIA, + SKIPL IMPOH ; unless output side needs PI 1. + MOVEM A,IMPPIA ; Set desired PIA channel on exit + CONO IMP,@IMPPIA ; Set PIA to whatever it was! + MOVE A,[JSR IMPIBK] ; Reset PI 1 Input-Done vector back to std. + EXCH A,IMPILC ; and restore A. +];DMIMP +IFN DMIMP, CONO FI,NETCHN*11 ; DM interface can simply set Input-Done PIA! + JRST 12,@IMPLD4 + +IMPBCM: BUG INFO,[NCP: CTL MSG BS NOT 8 OR CT>120. HST ],OCT,IMPHTN(H),[BS ],DEC,IMPCBS,[BC ],DEC,IMPCBC + JRST IMPIRT + +;;; IMP->Host Type 6 - Host Down Status +; H/ host index + +IMPHDS: MOVE A,IMPILB+1 ;1.8-1.1 AND 4.9-4.2 ARE THE INFO + MOVE B,IMPILB+2 + LSHC A,8 + ANDI A,177777 + HRRM A,IMPHTB(H) ;STORE, HOPE USER READ RFC 611 + JRST IMPIRT + +;;; IMP->Host Type 1 - Error in leader (msg-id not given) +;;; IMP->Host Type 8 - Error in data (msg-id given) + +IMPBE1: LDB T,IMSTBP ; Get subtype (4 bits) + ANDI T,3 ; Only 2 bits should be used + AOS IMPM1S(T) ; Increment count of Type 1 subtype messages +IMPBE8: MOVE T,TIME + SUB T,LNETIM + CAIL T,60. ;IGNORE ERROR DURING INITIAL SYNCHRONIZATION + BUG INFO,[IMP: Type ],DEC,A,[err msg, leader],OCT,IMPILB,OCT,IMPILB+1,OCT,IMPILB+2 +IFN INETP,[ + MOVE B,IMPCLN + CAIN B,233 + AOS IMNIP8 +] + CAIN A,8. + JRST IMPBEB ; Process "Error in data" (decrement RFNM wait cnt) + JRST IMPIRT + +IMPBER: SKIPGE IMPUP ;SKIP IF UP, OR THOUGHT TO BE BROKEN + JRST IMPBE2 ;ALREADY DOWN, LET IT COME UP IN PEACE + MOVSI J,SCLNET ;THINKS IT'S UP, RESET IT + IORM J,SUPCOR + CONI IMP,IMERCN ;RECORD IF IMP ERROR FLIP/FLOP SET + SETOM IMPUP ;IMP IS DOWN + SETZM IMPTCU ;AND NOT TRYING TO COME UP +IFN INETP,.ERR IP/TCP code needs handling for IMP crashing. +IFN NCPP,[ + MOVSI T,200000 ;CLEAR ALL BUFFERS ACTIVE AT PI LEVEL + MOVSI I,-IMPSTL ;SINCE CORE JOB MAY BE WAITING ON THIS + ANDCAM T,IMSOC6(I) + AOBJN I,.-1 +] ;NCPP +IMPBE2: +IFN KAIMP,[ + SETZM IMPPIA + CONO IMP,0 +] +IFN DMIMP,CONO FI,FIRSET + JRST IMPEX + +;;; IMP->Host Type 2 - IMP going down + +IMPGD: LDB B,[060200,,IMPILB+1] ;WHY + MOVEM B,IMPDWN + LDB B,[020400,,IMPILB+1] ;HOW SOON GOING DOWN * 5 MINS + MOVE H,B + IMULI B,5*60.*30. ;TICKS IN 5 MINS + ADD B,TIME + MOVEM B,IMPDWN+1 + MOVE C,IMPILB+1 ;HOW LONG TO BE DOWN, SPANS WORD BOUNDARY + MOVE D,IMPILB+2 + LSHC C,8 + ANDI C,1777 + MOVE Q,C + IMULI C,5*60.*30. + ADD C,B ;ADD TO TIME DOWN + MOVEM C,IMPDWN+2 ;STORE TIME WHEN WILL BE UP + IMULI H,5 ;MINUTES + IMULI Q,5 + BUG INFO,[IMP: Going down in ],DEC,H,[mins for ],DEC,Q,[mins, reason],DEC,IMPDWN + JRST IMPIRT + +;;; IMP Blockage avoidance +; The current IMP software will not accept more than 8 active +; messages to a single host; attempting to send a 9th message will block +; ALL output to the interface, until the first message has been ack'd +; by means of one of the following message types: +; Type 5, RFNM - Message delivered OK +; Type 7, Host dead - transmit failed ("permanent") +; Type 8, Error in data - interface spazzed +; Type 9, Incomplete Transmission - temporary failure +; If for some reason the first message simply becomes lost, the IMP timeout +; (and blockage) can last for up to 30-45 seconds. +; More details in BBN Report 1822. +; ITS attempts to fix this by keeping a count of active un-ACKed +; messages for each host it is communicating with. A timeout is also +; associated with each host; if output to a given host is blocked by ITS +; because there are 8 active messages, trying to send a 9th message +; will check the last-RFNM-received time and if this was more than +; 30 or so seconds then the IMP is probably not giving us what it should +; and we should reset things for that host. + +%IMPMA==:8. ; # of maximum active IMP messages allowed + +; IMPBLI, IMPBLD - routines to hack active-message counts, called via JSP T, +; IMPBLD decrements count. +; IMPBLI increments count and skips if successful (else failed, +; and must NOT output another message to this host!) +; Also clobbers Q. +IMPBLI: AOS Q,IMPHTC(H) + CAIGE Q,%IMPMA ; Trying to send max or more messages? + JRST 1(T) ; No, can return safely. + CAIG Q,8. ; Is this the maximum # allowed? + JRST [ MOVE Q,TIME ; Yes, set up blockage timeout + ADDI Q,60.*30. ; for one minute. + MOVEM Q,IMPHTT(H) + JRST 1(T)] + + ; Trying to send too many messages, block it (check for timeout though) + SOS IMPHTC(H) ; Restore original count + AOS IMNBLK ; Increment # of times softwarily blocked. + MOVE Q,IMPHTT(H) + CAML Q,TIME ; See if timeout still in the future + JRST (T) ; Yes, just take failure-return to block. + BUG INFO,[IMP: RFNM-wait timeout! Hst=],OCT,IMPHTN(H) + SETZM IMPHTC(H) ; This may be dangerous... oh well. + SETZM IMPHTT(H) + JRST (T) ; Block one last time, next try will win. + +IMPBLD: SOSL Q,IMPHTC(H) + JRST IMPBL2 + BUG INFO,[IMP: neg RFNM-wait cnt, Hst=],OCT,IMPHTN(H) + SETZB Q,IMPHTC(H) +IMPBL2: CAIL Q,8.-1 ; If we were blocking on this host, + CALL IMPIOS ; Ensure IMP output started up so blocked stuff + JRST (T) ; gets sent promptly. + +;;; IMP->Host Type 8 - Error in Data +; Actually this is secondary routine that IMPBE1 jumps to. + +IMPBEB: JSP T,IMPBLD ; Decrement count of active messages + JRST IMPIRT + + + +;;; IMP->Host Type 5 - RFNM (Ready For Next Message) + +IFN INETP,.ERR INETP needs handling for RFNM on link 233 +IMPRFN: +IFN BLIMPP,JSP T,IMPBLD ; Decrement count of active IMP messages for this host + SKIPE IMPCLN ;LINK NUMBER + JRST IMRFN1 ;DATA LINK +IMRFN6: SKIPL IMPHTB(H) + JRST IMRFN7 + SKIPN IMPHTN(H) + BUG HALT,[IMP: IMRFN6 sees free IMPHTB entry ],OCT,H + MOVSI D,400000 + ANDCAM D,IMPHTB(H) ;SET RFNM RECEIVED + SOS IMRFCT +IFN NCPP,[ + SKIPL IMPNCQ ;SKIP IF NO PENDING CONTROL-LINK OUTPUT + PUSHJ P,IMPIOS ;START OUTPUT +];NCPP + JRST IMPIRT + +IMRFN7: AOS IMNSRC + BUG INFO,[IMP: Spurious RFNM from ],OCT,IMPHTN(H),[LNK 0] + JRST IMPIRT + +; RFNM on non-zero link message +IMRFN1: +IFN INETP,[ + MOVE A,IMPCLN ; Get link # + CAIE A,233 ; IP link number? + JRST IMRFNX ; No, skip IP code + AOS IMNIPR ; Bump count of IP RFNMs received + JRST IMPIRT ; and do nothing else about it, ugh. +IMRFNX: +];INETP +IFN NCPP,[ + MOVE A,IMPCSH + LSH A,8 + IOR A,IMPCLN ;HEADER + MOVSI I,-IMPSTL + MOVEI W,1 +IMRFN2: LDB D,IMSCHL ;HEADER + SKIPGE IMSOC1(I) ;SKIP IF SLOT NOT IN USE + CAME A,D ;SKIP IF HEADER AGREES + JRST IMRFN3 + HRRZ J,IMSOC4(I) ;STATE + MOVEI W,0 + CAIN J,%NSRFN + SOJA J,IMRFN4 ;RFNM WAIT + MOVSI J,20000 ;MIGHT BE EXPECTING RFNM AFTER CLOSE + TDNE J,IMSOC5(I) + JRST [ ANDCAM J,IMSOC5(I) + JRST IMPIRT ] +IMRFN3: AOBJN I,IMRFN2 + BUG INFO,[IMP: Spurious RFNM from ],OCT,IMPHTN(H),[link],OCT,IMPCLN,SIXBIT,[(W)[SIXBIT/NOWAITNOLINK/]] +];NCPP +.ELSE BUG INFO,[IMP: Spurious RFNM from ],OCT,IMPHTN(H),[link],OCT,IMPCLN + AOS IMNSRF + JRST IMPIRT + +IFN NCPP,[ +IMRFN4: HRRM J,IMSOC4(I) ;CONNECTION OPEN + MOVSI J,30000 ;TURN OFF CLOSE-AWAITING-RFNM BIT, AND + ANDCAM J,IMSOC5(I) ; RFNM-TIMEOUT-DURING-CLOSE BIT + MOVE T,IMSPIP(I) + CAME T,IMSMPP(I) ;SKIP IF OUTPUT BUFFER EMPTY + PUSHJ P,IMPIOS ;START OUTPUT + JRST IMPIRT +];NCPP + + +;;; IMP->Host Type 9 - Incomplete Transmission + +IMPINC: LDB T,IMSTBP ; Get subtype field (4 bit reason for failure) + AOS IMPM9S(T) ; Bump count of subtypes + SKIPA E,[%NCINC] + +;;; IMP->Host Type 7 - Destination Host Dead + +IMPDHD: MOVEI E,%NCDED +IFN BLIMPP,JSP T,IMPBLD ; Decrement count of active IMP messages for this host +IFN INETP,[ + MOVE A,IMPCLN + CAIN A,233 + JRST [ CAIN E,%NCINC + AOS IMNIP9 + CAIN E,%NCDED + AOS IMNIP7 + JRST IMPIRT] ; Don't bother with NCP stuff or anything. +] + MOVSI C,1000 ;RST SENT? + TDNE C,IMPHTB(H) + SOS IMRFCT ;GOING TO CLEAR IT, DECREASE TIMEOUT RQ + MOVSI C,3000 + ANDCAM C,IMPHTB(H) ;CLEAR RST STATUS, RFNM SIMULATED LATER +IFN NCPP,[ + MOVSI I,-IMPSTL +IMDHD: LDB T,IMSCFH + SKIPGE C,IMSOC1(I) ;SKIP IF NOT IN USE + CAME T,IMPCSH + JRST IMDHDA + HRRZ T,IMSOC4(I) + TLNN C,200000 ;THIS GUY IS CLOSING ANYWAY + CAIG T,%NSLSN + JRST IMDHDA ;THIS SOCKET'S HOST NUMBER FIELD IS MEANINGLESS + CAIGE T,%NSCLI .SEE %NSINP + TDZA T,T .SEE %NSCLS + MOVEI T,%NSCLI + HRRM T,IMSOC4(I) + DPB E,IMSCLS ;CLS REASON + PUSHJ P,IMPUIN +IMDHDA: AOBJN I,IMDHD +];NCPP + JRST IMRFN6 ;CONTROL LINK, TAKE AS RFNM SO AS NOT TO HANG THINGS + +IFN INETP,[ +; IMPRMI - End of IP datagram, PI in progress on NETCHN, here from IMPBKX +; A/ Last IMP word (32-bit) +; TT/ CONI bits as of interrupt (note already returned to 36-bit mode) + +IMPRMI: AOS B,IMBLKI ; Get address to store last word in + MOVEM A,(B) ; Store it away + SUB B,IMPIBS ; Get # words read into datagram buffer + MOVEI B,(B) + MOVE A,IMPIDP ; Get pointer to IP datagram buffer we were using + SETZ C, ; Say zero offset to IP header. + MOVE J,IMPCSH ; Set index to host-table entry dgm received from. + PUSHJ P,IPRDGM ; Call IP module to process received datagram at PI lvl + SETZM IMPIDP ; Clear PI level pointer + JRST IMPIR1 ; Return from PI level, setting up for next msg + +] ;INETP + +SUBTTL ARPANET OUTPUT INTERRUPT LEVEL + +; See comments at IMPINT for a description of the overall IMP interrupt +; structure. Output is simpler than input, however. +; Each IMP message is output at PI level 1 except for the initial DATAO; +; the setup and takedown for each message is done at PI level 2. +; The code on this page is not referenced by anything outside the page +; except interrupt vector setup at IMPINI (to IMPOBK) and IMOB9 (to IMPCH1). + +; IMPCH1 - PI 1 Output-Done interrupt, from IMPOLC. +; Comes here when last word DATAO'd has been sent to IMP. +EBLK +IMPCH1: 0 +BBLK + MOVEM A,IMPOLC ; Save A + MOVE A,IMOPNT +IMCH1A: SKIPGE A,IMOLST(A) ; Get next "instruction" + JRST IMCH1B ; Jump if it's a BLKO pointer + CAILE A,3 ; Ensure valid operation + JRST 4,. + XCT IMCH1I(A) ; Do it + AOS A,IMOPNT ; Still here? Point to next operation + JRST IMCH1A ; and loop to do it. + +IMCH1I: JRST IMCH1C ;0 Stop - end of output list +IFN KAIMP,CONO IMP,IMPLHW+IMPCHN ;1 Set Last Word +IFN DMIMP,CONO FI,FILHW+11*NETCHN +IFN KAIMP,CONO IMP,IMO32S+IMPCHN ;2 Set 32-bit mode +IFN DMIMP,CONO FI,FIO32S+10*NETCHN+IMPCHN + JFCL ;3 NOP + +IMCH1B: MOVEM A,IMBLKO ; Set up BLKO - store the pointer + MOVE A,[JSR IMCH1D] ; Set dispatch for BLKO runout + MOVEM A,IMPOLC+1 + MOVE A,[BLKO IMP,IMBLKO] + EXCH A,IMPOLC ; Store the BLKO and restore A + AOS IMOPNT ; Increment output list ptr past this op. + JRST 12,@IMPCH1 ; Will interrupt immediately for first BLKO + ; word, since Output-Done wasn't cleared. + +; PI 1 Output-Done, from IMPOLC+1 (BLKO runout) +; Final word of the BLKO pointer is now in interface, being sent +; to IMP, and Output-Done flag is off. +EBLK +IMCH1D: 0 +BBLK + MOVEM A,IMPOLC + MOVE A,[JSR IMPCH1] ; Interrupt back when output of final word done + EXCH A,IMPOLC + JRST 12,@IMCH1D + +; Here from IMPCH1, PI 1 Output-Done interrupt +; Output list has hit "stop" operation (previous op had better be +; 1 to set Last-Host-Word!) +; This code reverts control back to PI level 2 (IMPOBK). +IMCH1C: +IFN DMIMP,[ + CONO FI,FIOUT+11*NETCHN ; Reset PIA to normal 2 + MOVE A,[JSR RINT1] ; and ensure any further output PI 1 ints +] ; are classified as spurious. + +IFN KAIMP,[ ; Non-DM interface needs more hair. + SETZM IMPOH ; Say output side doesn't need PI 1 anymore + MOVEI A,NETCHN ; And set exit PIA to 2, + SKIPL IMPIH ; unless input side still needs PI 1 + MOVEM A,IMPPIA ; Set it. + CONO IMP,NETCHN ; Shouldn't this be CONO IMP,@IMPPIA?? + SETOM IMPO ; Tell IMPINT we have output-done interrupt. + MOVE A,[JSR IMPOBK] ; Point PI 1 channel at switch-PIA routine, +] ; in case we interrupt on PI 1 again anyway. + EXCH A,IMPOLC + JRST 12,@IMPCH1 + +IFN KAIMP,[ + +; PI 1 Output Done interrupt, when we should really be interrupting +; at IMPINT on PI 2. +EBLK +IMPOBK: 0 +BBLK + SETOM IMPO ; Tell IMPINT what kind of interrupt + CONO IMP,NETCHN ; Reset PIA to 2 + JRST 12,@IMPOBK +] + +; IMPOBZ - PI 2 (NETCHN) "Output Done" interrupt, via IMPINT. +; Come here when we have finished sending stuff out at PI 1, +; also when something wants output to start and tickled the "Done" +; flag. +; TT/ IMP CONI word. + +IMPOBZ: AOS IMCT3 +IFN DMIMP,[ + TRC TT,IMPCHN_9 ;CHECK IF OUTPUT PIA=IMPCHN + TRNN TT,7_9 + JRST IMPRET ;IGNORE, ALREADY HANDLED BY IMPCHN +] + SKIPL B,IMPOS + CAIL B,IMPODL + JRST 4,. + JRST @IMPODT(B) + +IMPODT: OFFSET -. +%ISODL:: IMPOB1 ; 0 Idle, look for something to send +%ISONC:: IMPOB6 ; 1 Finished NCP control message +%ISOND:: IMPOBG ; 2 Finished NCP data message +IFN INETP,%ISOID::IMPOBI ; 3 Finished IP datagram messge +IMPODL::OFFSET 0 + +IFE NCPP,[ +IMPOB6: SETZM IMPOS + SKIPN A,IMPSVQ + JRST IMPRET ;THAT WAS A NOP +IMPOBG: JRST 4,. ;Can't get here +];not NCPP + +; Idle - Look for output to send. First ensure we can send stuff, +; then try things in the order: +; (1) Send NOP if net coming up +; (2) Check NCP control queue, then (3) NCP data output queue +; OR +; (2) Check IP datagram queue +; +; Note that we alternate between checking the NCP and IP queues first, +; so that neither protocol can totally wedge the other up even if +; going at full blst. + +IMPOB1: HRRZ T,IMPUP + CAIE T,-2 ; Don't say it's up when it's still going down + CAIN T,1 ; or when it is broken + JRST IMPOB9 + + ; First check to see if NOP needs to be sent. + AOSG IMNOPC ; Check to see if sending NOPs + JRST IMONOP ; Output a NOP + SETZM IMPUP ; Say IMP is up + SETZM IMPTCU ; Say no longer trying to come up + + ; Now see whether to check NCP or IP. +IFN INETP,[ + SETCMB T,IMPPSW ; Complement IMP output protocol switch + JUMPN T,IMOBNN ; Jump for NCP + PUSHJ P,IPGIOQ ; Check IP! Get IP IMP output queue entry if any + JRST IMOBN ; Nothing there, go check NCP. + ; Returns A/ ptr to IP dgm struct + ; B/ BLKO pointer to 32-bit words + ; C/ Arpanet address + ; The output list should be set up as: + ;IMOLST: -3,,IMOLDR + ;IMOMOD: 2 ; switch to 32-bit mode + ;IMOBK1: -1,,IMOLDR+3 ; Send 5th word of padding + ;IMOBK2:output BLKO ; Send datagram minus last word + ; 1 + ;IMOBK3: -1,,lstwd-1 ; BLKO to last word of datagram + ; 0 +IMOBI1: + MOVEM A,IMPODP ; Save ptr to datagram being output + AOS IMNIPO ; # of IP datagrams sent + ADD B,[1,,] ; Reduce BLKO count by one + MOVEM B,IMOBK2 ; Store in output list + HLRO D,B ; Get -<# wds-1> + MOVN D,D ; Get <#wds-1> + ADDI D,(B) ; Get addr for last-word BLKO + HRROM D,IMOBK3 ; Store -1,,lastwd-1 + MOVE B,[-3,,IMOLDR] + MOVEM B,IMOLST + MOVE B,[-1,,IMOLDR+3] + MOVEM B,IMOBK1 + + ; Output list set up, now must put together the IMP leader + ; in IMOLDR. + MOVE B,[17_10.,,0] ; Regular message + MOVEM B,IMOLDR + LSH C,8. ; Move net address over + IORI C,233 ; Get link # for IP + MOVEM C,IMOLDR+1 ; Store 2nd word + SETZM IMOLDR+2 ; 3rd word can be zero + SETZM IMOLDR+3 ; rest is padding + SETZM IMOLDR+4 ; ditto + +IFN KAIMP,CONO IMP,IMO32C +IFN DMIMP,CONO FI,FIO32C ;SET 36 BIT MODE FOR LEADER, CLEAR PIA + DATAO IMP,IMOLDR ; Start it going! + + MOVEI C,%ISOID ; State = outputting IP datagram. + JRST IMOB9 + +IMOBN: SKIPE IMPPSW ; If no IP, check NCP only if havent already + JRST IMOBI9 ; Skip NCP check, just return. +IMOBNN: +] ;INETP + +IFN NCPP,[ + ; Check NCP control message queue. +IFN BLIMPP,[ + MOVEI C,IMPNCQ +IMPOBV: SKIPGE A,(C) + JRST IMPOBW + HLRZ H,1(A) ; Got one! Go send NCP control msg, + SKIPL IMPHTB(H) ; unless control link waiting for RFNM + JSP T,IMPBLI ; or too many msgs active for that host. + CAIA + JRST [MOVEI T,(C) ? JRST IMPOB2] ; Compat hack + MOVEI C,(A) + JRST IMPOBV +] ;BLIMPP +.ELSE [ + MOVEI T,IMPNCQ +IMPOBV: SKIPGE A,(T) + JRST IMPOBW + HLRZ B,1(A) ;HOST TABLE INDEX + SKIPL IMPHTB(B) ;SKIP IF WAITING FOR RFNM + JRST IMPOB2 ; Got one! Go send NCP control message. + MOVE T,A + JRST IMPOBV +] ;IFE BLIMPP + + ; Check NCP data output queue. This simply runs through + ; all the sockets to see if any want to output something. +IMPOBW: MOVSI I,-IMPSTL + MOVEI W,1 +IMPOBB: SKIPGE IMSOC1(I) ;SKIP IF NOT IN USE + TDNN W,IMSOC2(I) ;SKIP IF SEND + JRST IMOBA9 + HRRZ A,IMSOC4(I) + CAIN A,%NSOPN ;SKIP IF WRONG STATE + SKIPGE IMSOC6(I) ;SKIP IF NOT LOCKED BY CORE JOB +IMOBA9: +IFE BLIMPP,IMPOBA: + AOBJN I,IMPOBB +IFN BLIMPP,[ + JUMPGE I,IMPOB9 + LDB H,IMSCFH ; Get fgn host index for this NCP conn + JSP T,IMPBLI ; Make sure not too many active msgs + JRST IMOBA9 ; Sigh, too many, keep looking. + JRST IMPOBD ; OK, can send! +IMPOBA: JSP T,IMPBLD ; Couldn't send data msg after all, decr cnt + JRST IMOBA9 +] +.ELSE JUMPL I,IMPOBD ; Got one! Go send NCP data message. +];NCPP + + ; No more NCP output for IMP. +IMPOB9: +IFN INETP,[ + SKIPN IMPPSW ; If we didnt check IP queue yet, + JRST IMOBI9 + PUSHJ P,IPGIOQ ; then do it now, after NCP check. + JRST IMOBI9 ; Nothing, really no more output. + JRST IMOBI1 ; Aha, have stuff! Go get it. +IMOBI9: +] + SETOM IMPOAC ; No more output, couldn't find anything to send. +IFN KAIMP,CONO IMP,IMPODC ; Clear Output-Done interrupt bit +IFN DMIMP,CONO FI,FIODC+NETCHN*11 + JRST IMPRET + + +; IMONOP - Send a NOP, here from IMPOBZ only. + +IMONOP: MOVEI A,IMPNOP-2 + SETZM IMPSVQ ; Set flag => this msg not really from control queue + MOVEI B,1 ; No text, but one extra wd (needed to make BLKO win) + JRST IMPOB3 + + ; NOP Host-IMP leader +IMPNOP: 17_10.,,4_4 ; New format, type 4 = NOP + 0 + 5_10.,,0 ; 5 16-bit words of padding desired + +; IMPOB2 - Send a NCP control message, from IMPOBZ only + +IMPOB2: HRL A,T + MOVEM A,IMPSVQ ;SAVE CTL MSG QUEUE PNTR + HRRE B,1(A) ;GET COUNT + JUMPG B,IMPOB3 + JRST 4,. ;ERROR, COUNT NOT > 0 +IMPOB3: ; Entry pt from NOP sending code +IFN KAIMP,CONO IMP,IMO32C +IFN DMIMP,CONO FI,FIO32C ;SET 36 BIT MODE FOR LEADER, CLEAR PIA + DATAO IMP,2(A) ;OUTPUT FIRST LEADER WORD + MOVEI C,2(A) ;SET UP BLKO POINTER FOR REST OF LEADER + SKIPN IMPSVQ + JRST [ HRLI C,-2 ;KLUDGE, SENDING NOP + JRST IMPOB4 ] + HRLI C,-5 + AOS IMPMSS+0 ;COUNT REGULAR MSGS SENT +IFN INETP,[ + MOVE T,IMPCLP ; HACK! Get specified # to use for ctl link + DPB T,[001000,,3(A)] ; Deposit in link field of leader. +];INETP +IFN NCPP,[ + LDB T,[341000,,10(A)] ;FIRST BYTE OF CONTROL MESSAGE + CAIGE T,20 + AOS IMPCMS(T) +];NCPP +IMPOB4: MOVEM C,IMOLST ;STORE BLKO POINTER THAT SENDS LEADER + MOVEI C,2 ;DO TEXT WORDS IN 32-BIT MODE + MOVEM C,IMOMOD +IFN DMIMP,MOVNI B,(B) ;GET MINUS WORD COUNT +IFN KAIMP,MOVNI B,-1(B) ;ALSO -1 FOR LAST WORD SENT SEPARATELY. + HRLI B,7(A) ;ADDR-1 FOR BLKO + MOVSM B,IMOBK1 ;STORE FOR PI 1 +IFN KAIMP,[ + MOVNI B,(B) + ADD B,IMOBK1 ;LAST WORD SENT SEPARATELY + HRROM B,IMOBK3 + MOVEI B,3 ;CHECK FOR SCREW CASE, ONLY SENDING ONE WORD, IT'S THE + SKIPL IMOBK1 ; LAST, SO NOP OUT THE MAIN BLKO + MOVEM B,IMOBK1 +] +.ELSE MOVEI B,3 + MOVEM B,IMOBK2 ;NO 2ND BLKO + MOVEI C,%ISONC ;STATE FOR CONTROL RETURN TO NETCHN +IMOB9: MOVEM C,IMPOS + SETZM IMOPNT + MOVE C,[JSR IMPCH1] + MOVEM C,IMPOLC +IFN KAIMP,[ + SETOM IMPOH ;OUTPUT SIDE WANTS IMP TO RUN ON CHANNEL 1 + MOVEI A,IMPCHN + MOVEM A,IMPPIA +] +IFN DMIMP,CONO FI,FIOUT+NETCHN_3+IMPCHN ;SET PIA FOR OUTPUT + JRST IMPRET + +IFN INETP,[ +; Here when IP datagram transmission completed + +IMPOBI: SETZM IMPOS ; Reset output state + MOVE A,IMPODP + PUSHJ P,IPIODN ; Tell IP level that datagram was output + SETZM IMPODP + JRST IMPRET +] ;INETP + +SUBTTL ARPANET CLOCK LEVEL + +OVHMTR IMP ;NETWORK INTERRUPT LEVEL (NOT STYNET STUFF) + +IMRSTO: SKIPN IMRFCT ;CALLED AT 15 SEC CLK LEVEL TO UNHANG RFNM WAITS +IFE NCPP,POPJ P, +IFN NCPP,JRST IMFCT1 + MOVEI H,LIMPHT-1 ;SOME CONTROL LINKS WAITING FOR RFNM, CHECK FOR TIME OUT + MOVSI TT,401000 ;4.9 AND 4.1 - RFNM AND RRP TIMEOUTS + TDNN TT,IMPHTB(H) +IMRS4: SOJGE H,.-1 +IFN NCPP,JUMPL H,IMFCT1 +IFE NCPP,JUMPL H,CPOPJ + CONO PI,NETOFF + SKIPE IMPHTN(H) ;MAKE SURE IT'S A REAL HOST, NOT A FREE ENTRY + TDNN TT,IMPHTB(H) ;AND THAT THE BITS DIDN'T TURN OFF DUE TO INTERRUPT + JRST IMRS1 + LDB E,[221100,,IMPHTB(H)] + LDB D,[051100,,TIME] ;GET TIME IN SECONDS (APPROX) + CAMLE E,D + ADDI D,1_9 + SUB D,E + CAIGE D,IMRFTO_<-5> + JRST IMRS1 ;HASN'T TIMED OUT YET. + LDB D,IMHSBT ;TIMED OUT. CHECK RST/RRP STATUS. + SOJE D,IMRS2 + MOVSI D,400000 + ANDCAM D,IMPHTB(H) ;RFNM SENT, CLEAR IT + AOS IMNRFN + SOS IMRFCT + BUG INFO,[NET: CTL LNK RFNM TIMEOUT HST],OCT,IMPHTN(H) +IMRS1: CONO PI,NETON + JRST IMRS4 + +IMRS2: DPB D,IMHSBT ;RST SENT, SET STATE TO DOWN + BUG INFO,[NET: RST TIMEOUT HST=],OCT,IMPHTN(H) + SOS IMRFCT + JRST IMRS1 + +;NETHST (HOST INFO) +; ARG 1 - HOST => VAL 1 - STATUS, VAL 2 - HOST NUMBER +; ARG 1 - -1 => VAL 1 - (STATUS), VAL 2 - OUR HOST NUMBER +;NOT CURRENTLY IMPLEMENTED- ARG 1 - -1, ARG 2 - OUR GOING-DOWN REASON + +ANETHST:HRRE T,A ;LET IMMEDIATE -1 WIN (777777 NOT A VALID HOST) + AOJE T,ANETH2 ;JUMP IF WANT LOCAL STATUS AND HOST NUMBER + MOVE T,A + JSP J,STDHST ;STANDARDIZE AND ERROR-CHECK HOST NUMBER + MOVE B,T ;RETURN NEW FORMAT ******* + TLO B,(NW%ARP) + MOVEI H,LIMPHT-1 + CONO PI,NETOFF ;DO WE HAVE STATUS? + CAME T,IMPHTN(H) + SOJGE H,.-1 + JUMPGE H,ANETH1 ;YES, RETURN IT + CONO PI,NETON ;NO, HAVE TO GO GET IT + MOVEM T,SRN3(U) +IFN NCPP,[ + PUSHJ P,NETO00 ;GET IMSOC, RETURN WITH NETLST, IMSOC LOCKED + POPJ P, ;DEVICE FULL OR SOMETHING + PUSHJ P,NETOR ;OPEN COMMUNICATIONS WITH HOST + JFCL ;IT'S DOWN, THAT'S OK +];NCPP +.ELSE POPJ P, ;OH, TOO BAD +ANETH1: MOVE A,IMPHTB(H) ;GET STATUS + CONO PI,NETON + EXCH A,B + CALL CVH2NA ; Convert to HOSTS2 for compat + EXCH A,B + JRST LSWCJ1 ;RETURN IMSOC, NETLST IF NOT DONE ALREADY + +ANETH2: ;CAIL W,2 ;(THIS IS A CROCK) + ;MOVEM B,NTHDSW ;IF 2 ARGS, SET OUR REASON FOR GOING DOWN. + SKIPE IMPUP ;FAKE UP OUR STATUS + TDZA A,A ;WE'RE DOWN + MOVSI A,2000 ;WE ARE UP + MOVEI B,IMPUS ;AND OUR HOST #. + JRST POPJ1 + + +;NETIMP (REASON,TIMEDOWN,TIMEUP) READ/SET + +ANETIMP:JUMPLE W,ANETM1 ;NO ARGS, RETURN + CAIGE W,3 ;MUST HAVE 3 ARGS IF ANY + JRST OPNL30 + MOVEM A,IMPDWN + MOVEM B,IMPDWN+1 + MOVEM C,IMPDWN+2 + JRST POPJ1 + +ANETM1: MOVE A,IMPDWN + MOVE B,IMPDWN+1 + MOVE C,IMPDWN+2 + SKIPE IMPUP + TLO A,400000 + JRST POPJ1 diff --git a/src/system/inet.138 b/src/system/inet.138 new file mode 100755 index 00000000..026a7017 --- /dev/null +++ b/src/system/inet.138 @@ -0,0 +1,1430 @@ +;:;; -*- Mode:MIDAS -*- +; Insert new buffer stuff... +$INSRT TCPBUF + +IP%VER==740000,, ; 0 IP Version # (= 4) +IP%IHL==036000,, ; 0 IP Header Length in 32-bit wds - at least 5 +IP%TOS==001774,, ; 0 Type Of Service +IP%TOL==000003,,777760 ; 0 Total Length in octets (including header) +IP%ID== 777774,, ; 1 Identification +IP%FLG== 3,,400000 ; 1 Flags + IP%FDF== 1,,0 ; Don't-Fragment flag + IP%FMF== 400000 ; More-Fragments flag +IP%FRG== 0,,377760 ; 1 Fragment Offset +IP%TTL==776000,, ; 2 Time To Live +IP%PTC== 1774,, ; 2 Protocol +IP%CKS== 3,,777760 ; 2 Header Checksum +IP%SRC==777777,,777760 ; 3 Source Address +IP%DST==777777,,777760 ; 4 Destination Address + ; 5 Start of options +IP$VER==<.BP IP%VER,0> +IP$IHL==<.BP IP%IHL,0> +IP$TOS==<.BP IP%TOS,0> +IP$TOL==<.BP IP%TOL,0> +IP$ID== <.BP IP%ID, 1> +IP$FLG==<.BP IP%FLG,1> +IP$FRG==<.BP IP%FRG,1> +IP$TTL==<.BP IP%TTL,2> +IP$PTC==<.BP IP%PTC,2> + %PTCIC==:1 ; Protocol ICMP + %PTCTC==:6. ; Protocol TCP + %PTCUD==:17. ; Protocol UDP +IP$CKS==<.BP IP%CKS,2> +IP$SRC==<.BP IP%SRC,3> +IP$DST==<.BP IP%DST,4> + + ; UDP fields +UD$SRC==<242000,,0> ; 0 wd 1 Source port +UD$DST==<042000,,0> ; 0 wd 2 Dest port +UD$LEN==<242000,,1> ; 1 wd 1 # octets in data +UD$CKS==<042000,,1> ; 1 wd 2 UDP checksum +UD$DAT==<441000,,2> ; 2 Data - actually an ILDB pointer! + + ; ICMP fields +IC$TYP==<341000,,0> ; 0 Type of message +IC$COD==<241000,,0> ; 0 Code (subtype) +IC$CKS==<042000,,0> ; 0 ICMP Checksum +IC$GWA==<044000,,1> ; 1 Random arg, usually Gateway Addr +IC$IPH==2 ; 2 Random data, usually an IP header + +; Hack metering macro, since we'll want lots of 'em to start with. +; You know, MR% used to be MTR%, except that when %NMTRS is over 100 +; you get duplicated symbols, and since they used to be defined with +; == instead of ==: you didn't hear about it, either. + +%NMTRS==:140 ; Allow this many meters +DEFINE MTRCOD ; Put this macro someplace after last meter. +EBLK +MTRCNT: BLOCK %NMTRS ; Holds actual meter AOS'd +BBLK +MTRNAM: BLOCK %NMTRS ; Holds ,, + LOC MTRNAM + REPEAT %%%MTR,CONC MR%,\.RPCNT +IF2, REPEAT %%%MTR,CONC EXPUNGE MR%,\.RPCNT + LOC MTRNAM+%NMTRS + +TERMIN + +; METER - Must be used as in following example: +; METER("IP: # of bad cksums") +%%%MTR==0 +DEFINE METER &(NAME) +IFGE %%%MTR-%NMTRS,.ERR Too many meters! +AOS MTRCNT+%%%MTR +CONC MR%,\%%%MTR,==:<.,,[ASCIZ NAME]> +;CONC MR%,\%%%MTR,==:<.,,> +;IF1 SHOMTR %%%MTR,NAME +%%%MTR==%%%MTR+1 +TERMIN + +DEFINE SHOMTR #OFF#,&STR& +PRINTX /;;;;;;;; METER :::: MTRCNT+!OFF! => / +PRINTX STR +PRINTX / +/ +TERMIN + +EBLK +IPMDFL: 0 ; # of flushed input datagrams +IPMCKF: 0 ; # of input datagrams with bad checksum +IPMFRG: 0 ; # of fragments received +IPMFRD: 0 ; # of sucessfully reassembled datagrams +BBLK + +SUBTTL IP Input Interrupt Level + +; IPGIPT - Get datagram input buffer +; Clobbers Q,T +; A/ Max size of buffer in words +; Returns .+1 if failure (error message already printed) +; Returns .+2 +; A/ Pointer to datagram structure associated with buffer +; B/ Input BLKI pointer to buffer, -<# wds>,, + +IPGIPT: CAILE A,PKBSIZ ; Make sure size needed will fit in a packet buffer + JRST IPGIP9 + CALL PKTGFI ; Get a packet at int level + RET ; Failed, none available. + TRCPKT A,"IPGIPT Net input alloc" + MOVE T,PK.BUF(A) ; Get addr of buffer + HRLOI B,-PKBSIZ ; -<#wds>,,-1 + ADDI B,(T) ; Now get BLKI pointer into buffer + JRST POPJ1 ; Win! +IPGIP9: BUG CHECK,[IP: Too-big buff reqd =],OCT,A + RET ; Fail. + + +; IPRDGM - Process a received datagram at PI level +; Must put datagram into one of the following lists: +; User IP input queue (IPQ) +; IP reassembly table +; ICMP processing +; TCP connection queue +; A/ Pointer to datagram structure +; B/ # words read in datagram +; C/ # wds offset to start of IP header +;;; J is not used, and not supplied by all callers +;;; J/ host-table index of address datagram came from +; Returns .+1 always +; Can clobber all ACs except P +; Sets up +; R/ addr of packet entry +; W/ addr of IP header +; H/ addr of IP data + +IPRDGM: METER("IP: IDs rcvd") + MOVEI R,(A) ; Set up packet entry ptr in canonical place + TRCPKT R,"IPRDGM Input from net" + CAIGE B,5(C) ; Make sure it's big enough + JRST IPRDG9 + HRLM B,PK.BUF(R) ; Store # words read + ADD C,PK.BUF(R) ; Find addr of start of IP header + HRLZM C,PK.IP(R) ; and set it. + MOVEI W,(C) + LDB H,[IP$IHL (W)] ; Find claimed length of IP header + ADDI H,(W) ; Get addr of start of IP data + HRLZM H,PK.TCP(R) ; Set that too. + + ; Do initial vectoring test. + SKIPE IPUQUS ; Check Queue 0 (SysIn) + JRST IPRDG2 ; It exists!! Always vector for it. + + ; Perform initial checking for address, checksum, and so forth + ; to verify datagram is good; also dispatch to handle fragments. + ; This is entry point for re-vectors from SysIn IP queue. +IPRDGV: CALL IPCKSM ; Compute checksum for IP header + LDB B,[IP$CKS (W)] ; and get what the datagram had, + CAIE A,(B) ; in order to compare them... + JRST [ METER("IP: Ifl bad cksm") + AOS IPMCKF ; Bump two meters + JRST IPRD90] ; Go flush it forthwith. + MOVE B,IP$DST(W) ; Get destination host, should be us +IFE IPUNCP, CAME B,[IMPUS3_4] + CAMN B,[IMPUS4_4] + JRST IPRD10 + ; Packet is to be forwarded + METER("IP: Packets forwarded") + LDB B,[IP$TTL(W)] ; Decrement time to live + SOJLE B,[ METER("IP: Packets expired") + JRST IPRD90 ] +ICMEK1: DPB B,[IP$TTL(W)] + CALL IPCKSM ; Update the checksum + DPB A,[IP$CKS(W)] + MOVEI A,(R) ; Transmit it + CALRET IPKSNQ + +IPRD10: HRRE B,IP$FRG(W) ; HACK! Get both IP%FMF and IP%FRG! + JUMPN B,IPRD50 ; Jump if this is a fragment. + + ; Do datagram vectoring. This code is temporarily (?) crude, + ; it just scans the whole Internet Queue table. + ; This is entry point for re-vectoring. W must point to IP + ; header, and H to IP data. I should point at 1st queue entry + ; to start checking at. +IPRD20: MOVEI I,2 ; If drop in, start at 2 (leave 0+1 alone) + LDB B,[IP$PTC (W)] ; Get protocol number + CAIN B,%PTCTC ; Is it TCP? + JRST TCPIS ; Yes, go process TCP input segment. + CAIN B,%PTCUD ; Well, is it UDP? + JRST IPRD30 ; Yeah, can handle that one. + CAIN B,%PTCIC ; Maybe ICMP? + JRST ICMP ; Yup, hack it. +IPRD90: MOVEI A,(R) + CALL PKTRT ; Bah, nothing we handle, flush it. + AOS IPMDFL ; Bump count of flushed dgms. + RET + + ; Here to dispatch a UDP datagram +IPRD30: LDB A,[IP$TOL (W)] ; Make sure it's long enough! Find dgm length + LDB B,[IP$IHL (W)] ; and get IP header length + IMULI B,4 ; in octets + SUBI A,(B) ; to subtract from dgm length. + CAIGE A,2*4 ; Must have enough data for UDP header! + JRST [ METER("IP: Ifl bad UDP len") + JRST IPRD90] ; Flush this dgm. +IPRD31: CAIL I,NIPUQ + JRST [ METER("IP: Ifl no UDP port") ; Didn't find any queues, + JRST IPRD90] ; so flush it. + SKIPN IPUQUS(I) ; Check each active UDP queue + AOJA I,IPRD31 + LDB B,[UD$DST (H)] ; Get UDP dest port number + HRRZ T,IPUQCT(I) ; and port # we're watching for + CAIE B,(T) + AOJA I,IPRD31 ; No match, try another. + METER("IP: # UDP dgms queued") + CAIA +IPRDG2: SETZ I, ; Entry point for SysIn queueing + MOVEI Q,IPUQHD(I) ; Hurray, got it! Add to queue + MOVE B,(Q) ; Save prev contents of header + MOVEI A,(R) + CALL PKQPL(PK.IP) ; Put at end of input IP queue + JUMPE B,IPQUSI ; If nothing previously there, give user int. + RET + +IPRDG9: BUG INFO,[IP: Netin dgm too small, size ],OCT,B,[ offset ],OCT,C + JRST IPRD90 ; Try flushing the packet buffer. + +; IP Datagram Reassembly - Handle received fragment. + +IPRD50: AOS IPMFRG ; Bump count of fragments received + + LDB D,[IP$ID (W)] ; Get datagram ID field + LDB C,[IP$PTC (W)] ; Then protocol field + HRLI D,(C) ; Make ,, + MOVE E,IP$SRC(W) ; Then source address + MOVEI I,NIPF-1 +IPRD51: CAME D,IPFDID(I) +IPRD52: SOJGE I,.-1 + JUMPL I,IPRD70 ; If no more, must add to table. + MOVE B,IPFDPE(I) ; Matching ID! Get buffer ptr + HLRZ T,PK.IP(B) ; Get IP header ptr for existing fragment + CAME E,IP$SRC(T) ; Ensure same source host + JRST IPRD52 ; Nope, go check next entry. + HLRZ H,PK.TCP(B) ; Get ptr to start of data in reassembly buff + + ; OK, we matched up a fragment! Now start reassembly procedure. + ; If fragment is first one (offset 0) then must copy IP header, + ; unless already done. Safe to BLT since we always reserve + ; enough room for a full 15-word IP header. + ; If fragment is last one (IP%FMF 0) then must set IP$TOL to + ; the total # octets in full datagram. This gets fixed + ; to include the IP header length when datagram is complete. + ; I/ idx of reassembly entry + ; T/ ptr to IP header in reassembly buff + ; H/ ptr to data in reassembly buff + ; R, W as for entry to IPRD50 +IPRD55: LDB A,[IP$IHL (W)] ; Get IP header length in 4-octet wds + LDB E,[IP$TOL (W)] ; Get total length of this dgm in octets + HRRE D,IP$FRG(W) ; Hack - get frag offset and more-frag flag + TRNN D,IP%FRG ; Is frag offset 0 - 1st part of dgm? + JRST [ LDB C,[IP$FRG (T)] ; Yeah. Already copied header? + JUMPE C,.+1 ; Jump if so, don't do again. + MOVEI B,(T) + HRLI B,(W) ; Set up BLT from,,to + MOVEI C,(T) + ADDI C,(A) ; Get to+IHL + MOVE Q,IP$CKS(T) ; Save ptr to hole list + LDB TT,[IP$TOL (T)] ; Save TOL, might already be set. + BLT B,-1(C) ; Copy the IP header + HRRM Q,IP$CKS(T) ; Restore hole list head + DPB TT,[IP$TOL (T)] + JRST .+1] + ASH D,-3 ; Get frag.first in terms of 4-octet words + JUMPGE D,[ ; Jump for special processing if last frag + MOVNI B,(A) + ASH B,2 ; Get -<# octets in header> + ADDI B,(E) ; Find # octets of data in this fragment + MOVEI C,(D) + LSH C,2 ; Get # octets data is offset + ADDI B,(C) ; Finally get total # data octets of full dgm + DPB B,[IP$TOL (T)] + ADDI E,3 ; Okay, round UP to full word + LSH E,-2 ; Get rounded-up length in terms of 4-octet wds + SUBI E,1(A) ; Get # whole wds of data (minus 1) + JRST IPRD56] ; Go rejoin normal processing + + ; Not last frag. Only special check is to ensure length of data + ; is rounded down to a fragment boundary (frags are 8-octet chunks). + TRZ D,-1# ; Not last frag, clean up RH of frag.first + LSH E,-2 ; Get rounded length in terms of 4-octet words + SUBI E,1(A) ; Get # whole words of data, minus 1 + TRNN E,1 ; Paranoia: ensure # wds of data was EVEN + SUBI E,1 ; If not, round DOWN to ensure 8-octet boundary + +IPRD56: JUMPL E,IPRD80 ; Flush if bad length + ADDI E,(D) ; Get frag.last + CAIL E, ; Make sure datagram won't be too big. + JRST [ METER("IP: Ifl huge dgm") + CALL IPFDFL ; Ugh, must flush whole datagram entry! + JRST IPRD90] ; Would it be better instead to just + ; truncate it, and accept anyway since TCP + ; can ACK up to that much? Probably not. + + ; Each hole descriptor is 1 word of format + ; hole.first: ,, + ; + ; During re-configuration of the hole descriptor list, following + ; ACs are used + ; A/ scratch + ; B/ hole.first (wd offset) + ; C/ hole.last + ; D/ ,,frag.first ; lastflg is 0 if last fragment. + ; E/ frag.last + ; Q/ ptr to current hole descriptor + ; TT/ ptr to previous hole descriptor + ; H/ ptr to start of data in reassembly buffer (base for offsets) + ; W/ ptr to IP header of just-arrived fragment + ; T/ ptr to IP header of reassembly buffer + ; R/ ptr to packet entry of just-arrived fragment + MOVEI Q,IP$CKS(T) ; Get ptr to 1st hole descriptor +IPRD61: MOVEI TT,(Q) ; Save old ptr + HRRE Q,(Q) ; Get next descriptor + JUMPL Q,IPRD68 ; Jump if end of list + MOVEI B,(Q) ; Set hole.first + ADDI Q,(H) ; Make ptr to hole descriptor + HLRZ C,(Q) ; Get hole.last + CAIGE C,(D) ; If hole.last < frag.first, + JRST IPRD61 ; back to try next hole farther on. + CAIGE E,(B) ; If frag.last < hole.first, + JRST IPRD68 ; passed affected area, so can stop now. + + ; New fragment interacts with current hole in some way! + ; Remove current hole from the list, but keep Q pointing to + ; start of hole. TT points to the last valid hole descriptor. + MOVE A,(Q) ; Get hole.first of next hole + HRRM A,(TT) ; Store in prev hole, so current is skipped. + CAIL B,(D) ; If hole.first < frag.first, skip. + JRST IPRD66 + + ; Create new hole descriptor at start of old hole + ; with new.first = hole.first and new.last = frag.first-1 + ; i.e. hole.first: ,, + ; First get ptr to new hole and put it on list. + HRRM B,(TT) ; Point prev hole to new hole. + HRLI A,-1(D) ; Make ,, + MOVEM A,(Q) ; Store new hole descriptor. + MOVEI TT,(Q) ; Make prev be current, in case test below wins + ; Drop thru to check high bound of old hole + +IPRD66: CAIL E,(C) ; If frag.last < hole.last then hole not all filled + JRST IPRD61 ; (hole all filled, so go check further holes) + CAIL D, ; Some hole left; is this the last fragment? + JRST [ HLLOS (TT) ; Yes! Zap prev hole to ensure list ends. + JRST IPRD68] ; and get out of loop now. + + ; Fragment didn't fill last part of hole, so need to create + ; new hole descriptor for it, + ; with new.first = frag.last+1 and new.last = hole.last + ; i.e. frag.last+1: ,, + MOVEI Q,1(E) ; Get frag.last+1 + HRRM Q,(TT) ; Point previous to new hole + ADDI Q,(H) ; Make abs ptr to new hole + HRLI A,(C) ; Make ,, + MOVEM A,(Q) ; Store new hole descriptor. + ; Can drop through to end loop, since no further holes + ; are affected. + + ; No more holes on list, we can copy the data now! +IPRD68: HLL D,PK.TCP(R) ; Get ,, + ADDI D,(H) ; Now have BLT pointer + ADDI E,(H) ; and now have terminating address + CAIN E,(D) ; But if only moving 1 word, + JRST [ HLRZ D,D ; Can't use BLT? + MOVE A,(D) ; So just move by hand + MOVEM A,(E) + JRST .+2] ; Skip over it. + BLT D,(E) ; Here we go! + + ; Now see if any holes left... + MOVEI W,(T) ; Save ptr to reassembly IP hdr (H already set) + MOVEI A,(R) ; No need for arrived dgm any more, + CALL PKTRTA ; so flush it now. + HRRE A,IP$CKS(W) ; See if any holes left + JUMPGE A,CPOPJ ; Jump if some left, nothing else to do. + + HRRZ R,IPFDPE(I) ; Win!!! Get back packet-entry ptr + LDB A,[IP$IHL (W)] ; Must perform final TOL fixup. Get IHL + LSH A,2+4 ; in octets, shifted to TOL field + ADDM A,IP$TOL(W) ; Now have proper length! + SETZM IPFDPE(I) + SETOM IPFDID(I) + HRLOI A,377777 + MOVEM A,IPFTTL(I) + AOS IPMFRD ; Bump cnt of # datagrams reassembled! + JRST IPRD20 ; Go dispatch the datagram! + + + ; Create entry in table to store 1st fragment in. +IPRD70: MOVEI I,NIPF-1 + SKIPE IPFDPE(I) + SOJGE I,.-1 + JUMPL I,[METER("IP: Ifls Fragtab full") ; Barf, fragment table full. + JRST IPRD90] + LDB A,[IP$TTL (W)] ; Get time-to-live + JUMPE A,IPRD90 ; Might as well hack zero case + IMULI A,30. ; Turn into 30ths + ADD A,TIME + MOVEM A,IPFTTL(I) ; Store timeout value + MOVEM D,IPFDID(I) ; Store ptcl,,ID + HRRZM R,IPFDPE(I) ; Store PE ptr + + ; Messy stuff, must get data set up into right place in buffer. + ; If this is the 1st fragment we are OK, and can use original + ; datagram buffer, else we have to shuffle data. Simplest way + ; to handle latter case is to just get a new buffer and copy + ; it over. + LDB A,[IP$FRG (W)] ; Get fragment offset field + JUMPN A,IPRD75 ; If not zero, jump to do copy. + LDB A,[IP$TOL (W)] ; Hurray, 1st fragment! Get total length + LSH A,-2 ; Round down to # words + LDB B,[IP$IHL (W)] + SUBI A,(B) ; Find # words that fragment uses + TRZ A,1 ; Ensure # wds is rounded down to 8-octet chunk + JUMPLE A,[CALL IPFDFL ; Sigh, flush entry. + RET] ; Just return, only flushing one PE. + HRRM A,IP$CKS(W) ; Store first hole.next in header. + MOVEI B,(A) + ADDI B,(H) ; Get addr of start of hole + SETOM (B) ; Make it an infinite hole. + RET + + ; Fragment entry must be stored, but it isn't the 1st thing in + ; the datagram. We must cons up a fake initial fragment and + ; then copy normally into that fragment. + ; Note that this fake fragment must be carefully initiallized + ; since certain IP fields are referred to in the reassembly code + ; (via pointer in T) +IPRD75: CALL PKTGFI ; Get a PE ptr at PI lvl + JRST IPFDFL ; Failed, must flush entry + TRCPKT A,"Reassembly alloc" + MOVEM A,IPFDPE(I) ; Store it + HRRZ T,PK.BUF(A) + HRLM T,PK.IP(A) ; Say IP header at start of buffer. + MOVEI H,15. ; Use maximum IHL for offset + HRRZM H,IP$CKS(T) ; Store this offset as ptr to 1st hole desc + ADDI H,(T) ; and make data start at end of max IP hdr. + HRLM H,PK.TCP(A) + SETOM (H) ; Make 1st hole descriptor be infinite + SETOM IP$FRG(T) ; Put crap in frag offset field + MOVE B,IP$SRC(W) ; and ensure source host copied too. + MOVEM B,IP$SRC(T) + JRST IPRD55 ; Now go do the copy... + +IPRD80: METER("IP: Ifl bad len") ; Bad IP length field + JRST IPRD90 ; Go flush the dgm. + +; IPFCLK - Called every few seconds at clock level to check +; reassembly tables and flush any partially filled datagrams +; which have timed out. + +IPFCLK: MOVEI I,NIPF-1 + MOVE B,TIME + CONO PI,NETOFF ; Hack with net ints deferred. + CAML B,IPFTTL(I) + CALL IPFDFL ; Flush the partial dgm + SOJGE I,.-2 + CONO PI,NETON ; Done, re-enable net ints. + RET + +; IPFDFL - Flush reassembly entry in I +; Clobbers A, Q, T + +IPFDFL: SKIPE A,IPFDPE(I) + CALL PKTRTA ; Flush the packet buffer + SETZM IPFDPE(I) + SETOM IPFDID(I) ; Clear out other table stuffs. + HRLOI A,377777 + MOVEM A,IPFTTL(I) + RET + + +; Datagram Fragment table. +; Free entries have IPFDPE 0, IPFDID -1, and IPFTTL SETZ-1 (max pos time) +EBLK +NIPF==:30 ; Max # of outstanding IP datagram reassembly buffers +IPFDPE: BLOCK NIPF ; +IPFDID: REPEAT NIPF,-1 ; ,, +IPFTTL: REPEAT NIPF,SETZ-1 ; Sys time after which entry flushed. +BBLK + +SUBTTL IP Output Interrupt Level + +IFE IPUNCP,[ + +EBLK +IPOUTQ: 0 +IPOBLQ: 0 +BBLK + +; IPGIOQ - Get IP Output Queue entry for IMP +; Returns .+1 if nothing in queue +; Returns .+2 +; A/ Pointer to datagram structure +; B/ Output BLKO pointer to buffer, -<# wds>,, +; C/ Arpanet host address +; H/ host-table index +; Clobbers Q,T,W,D,E + +IPGOQ1: METER("IP: ODs flushed") + CALL PKTRT ; Internal looping point + +IPGIOQ: MOVEI Q,IPOUTQ + CALL PKQGF(PK.IP) ; Get first thing off IP output list + JUMPE A,IPGOQ9 ; Jump and return if nothing there. + MOVE T,PK.FLG(A) ; Get packet flags + TLNE T,(%PKFLS) ; Should we flush this one? + JRST IPGOQ1 ; Yes, down the drain it goes. + TLO T,(%PKPIL) + IORM T,PK.FLG(A) ; Say packet locked at PI level. + + SKIPLE C,PK.BUF(A) + CAMG C,[2,,0] + BUG HALT,[IP: Null dgm on queue] +IFE KS10P,[ + ;KS doesn't care, save 2 usec.. + MOVN B,C ; Straightforward way to put together AOBJN ptr. + HRRI B,-1(C) ; Now have BLKO +] + MOVE C,PK.DST(A) ; Get destination address + + ; IMP-specific!!! + ; Ask interface if it wants this particular datagram right now. + ; + CALL IMPCTS + JRST IPGOQ5 ; Can't send, requeue + + ; Got valid dgm, must ensure that block queue is merged back + ; onto beginning of output queue. +IPGOQ6: METER("IP: ODs sent") + SKIPN D,IPOBLQ ; See if anything was blocked + JRST POPJ1 ; Nope, just take win return. + SETZM IPOBLQ ; Yes, block queue exists! + SKIPN T,IPOUTQ ; Get ptr to 1st node on output queue + JRST [ MOVEM D,IPOUTQ ; If nothing was left on output queue, + JRST POPJ1] ; can simply move the list. + HLRZ E,D ; Get ptr to last node on blocked queue + HRRM T,PK.IP(E) ; Point end of blocked Q to start of output Q + HRRM D,IPOUTQ ; and point start of output Q to start of block Q + JRST POPJ1 ; and return with nice winning dgm. + + ; Come here to handle blockage of IP datagram. +IPGOQ5: MOVSI T,(%PKPIL) + ANDCAM T,PK.FLG(A) ; Say not locked at PI after all + MOVEI Q,IPOBLQ + CALL PKQPL(PK.IP) ; Put blocked dgm onto block queue + JRST IPGIOQ ; Now go try next dgm. + + ; Output queue empty, just shift block queue back. +IPGOQ9: SKIPN A,IPOBLQ ; See if anything was put on block queue + RET ; Nope, all's clear. + MOVEM A,IPOUTQ ; Aha, move it to standard output queue + SETZM IPOBLQ ; and clear the block-queue ptr. + RET ; Nothing to send from IP at moment. + +] ;IFE IPUNCP + +; IPIODN - Output of IP datagram complete, wrap up. +; Called by all device drivers. +; A/ pointer to datagram structure +; Clobbers T,Q +; Returns .+1 always + +IPIODN: TRCPKT A,"IPIODN Packet output complete" + MOVE T,PK.FLG(A) ; Get flags for packet + TLO T,(%PKODN) ; Say output done, + TLZ T,(%PKPIL) ; and unlock PI level output flag. + MOVEM T,PK.FLG(A) ; Store flags back. + CALRET PKTRT ; Return to freelist if not otherwise queued + + +SUBTTL ICMP - Internet Control Message Protocol + +; ICMP called at NET interrupt level to process just-received ICMP +; datagram. + +ICMP: + + ; First compute and verify checksum for ICMP data. + + ; Then dispatch on type for processing. + LDB E,[IP$SRC (W)] ; Load up source addr (commonly needed) + LDB A,[IC$TYP (H)] ; Get ICMP type field + CAIL A,NICMPT + JRST ICMP19 + AOS ICMPCT(A) ; Bump count of types + JRST @ICMPTB(A) ; Dispatch on type + + ; Bad type +ICMP19: BUG INFO,[ICMP: Bad type ],DEC,A,[from ],OCT,E +ICMP90: MOVEI A,(R) + CALL PKTRTA + RET + +ICMPTB: ICMP90 ; 0 Echo Reply (ignored) + ICMP19 ; 1 - + ICMP19 ; 2 - + ICMP90 ; 3 Destination Unreachable (ignored) + ICMP90 ; 4 Source Quench (ignored) + ICMRD ; 5 Re-direct + ICMP19 ; 6 - + ICMP19 ; 7 - + ICMEK ; 8 Echo + ICMP19 ; 9 - + ICMP19 ; 10 - + ICMP90 ; 11 Time Exceeded (ignored) + ICMPP ; 12 Parameter Problem + ICMP90 ; 13 TimeStamp (ignored) + ICMP90 ; 14 TimeStamp Reply (ignored) + ICMP90 ; 15 Information Request (ignored) + ICMP90 ; 16 Information Reply (ignored) +NICMPT==.-ICMPTB +EBLK +IPMICM: 0 ; # of ICMP datagrams +ICMPCT: BLOCK NICMPT ; # of ICMP datagrams, by type +BBLK + +; Type 8 - Echo + +ICMEK: MOVEI A,0 ; Set type to Echo Reply + DPB A,[IC$TYP (H)] + LDB A,[IC$CKS (H)] ; Fix checksum for change of 8 to 0 + ADDI A,8_8 + TRNE A,1_16. + ADDI A,1 + DPB A,[IC$CKS (H)] + MOVE A,IP$SRC(W) ; Exchange source and destination + EXCH A,IP$DST(W) + MOVEM A,IP$SRC(W) + MOVEI B,60. ; Reset time to live + JRST ICMEK1 ; Go send packet + +; Type 12 - Parameter Problem. + +ICMPP: LDB B,[IC$COD (H)] ; Get code field + JUMPE B,ICMPP2 + BUG INFO,[ICMP: Param err, code ],OCT,B,[from ],OCT,E + JRST ICMP90 +ICMPP2: LDB A,[341000,,1(H)] ; Get pointer into bad IP header + MOVEI B,(A) + LSH B,-2 ; Find word # error is in + ADDI B,IC$IPH(H) ; Make addr to word + BUG INFO,[ICMP: Param err, ptr ],OCT,A,[wd ],OCT,(B),[from ],OCT,E + JRST ICMP90 + +; ICMP type 5 - Redirect + +ICMRD: MOVEI D,IC$IPH(H) + MOVE A,IP$SRC(D) ; Get source addr of alleged IP header + CAME A,[IMPUS4_4] ; Must be a datagram WE sent. +IFE IPUNCP,[ + CAMN A,[IMPUS3_4] + CAIA + ] + JRST ICMP90 ; Bah, flush. Probably should log it. + LDB A,[IP$DST (D)] ; Get dest addr we used + GETNET A ; Derive net number + LDB B,[IC$GWA (H)] ; Get gateway addr recommended for this net + MOVEI C,NIPGW-1 ; Scan backwards thru gateway table + SETOB T,TT ; Index of free slot, index of oldest slot +ICMRD2: CAMN A,IPGWTN(C) + JRST [ SKIPN IPGWTG(C) ; Don't change a direct-route entry! + JRST ICMP90 + JRST ICMRD3 ] + CAIL C,NIPPGW ; Skip if prime gateway, not replaceable + JRST [ SKIPN IPGWTN(C) + MOVEI T,(C) ; Save index of last free slot found + SKIPL TT + CAML D,IPGWTM(C) + MOVEI TT,(C) ; Save index of least recently used slot + MOVE D,IPGWTM(TT) + SOJA C,ICMRD2 ] + SOJGE C,ICMRD2 + + ; Network not found in gateway table, must make new entry. + SKIPL C,T ; If there was one free, + JRST ICMRD3 ; go use that one. + MOVE C,TT ; Otherwise use least recently used entry + MOVE T,TIME + SUB T,IPGWTM(C) + CAIGE T,60.*60.*30. ; Flushing entry less than 1 hour old? + BUG INFO,[ICMP: GW table full, net/gw ],OCT,IPGWTN(C),OCT,IPGWTG(C),[=>],OCT,A,OCT,B +ICMRD3: GETNET D,B ; Figure out which interface this gateway is on + MOVEI T,NIPPGW-1 + SKIPN IPGWTG(T) + CAME D,IPGWTN(T) + SOJGE T,.-2 + JUMPL T,ICMP90 ; I can't figure out how to get to this gateway anyway + MOVEM A,IPGWTN(C) ; Set network number + MOVEM B,IPGWTG(C) ; and its corresponding gateway addr + MOVE T,IPGWTI(T) ; and its interface + MOVEM T,IPGWTI(C) + MOVE T,TIME ; Pretend it was used so it + MOVEM T,IPGWTM(C) ; stays around for a while + JRST ICMP90 ; Done! + +SUBTTL IPQ Device - Internet Protocol Queues + +; Internet Protocol User Datagram Queue stuff, manipulated with +; IPKIOT system call. +; Queue 0 is special: +; Must be asked for explicitly +; All Input datagrams are vectored through it. +; No limit on input queue length +; Can put datagrams back into system for further processing +; Can send datagrams (like ordinary queue actually in this respect) +; Queue 1 is also special: +; Must be asked for explicitly +; All output datagrams are vectored through it. +; No limit on queue length +; Can put datagrams back onto device output queue. + +IFNDEF NIPUQ,NIPUQ==10 ; # User queues allowed +EBLK +IPUQUS: BLOCK NIPUQ ; ,, + IQ%CH==<77,,> ; Field for channel # + IQ$CH==<.BP IQ%CH,IPUQUS> ; BP to channel # +IPUQHD: BLOCK NIPUQ ; Input queue header +IPUQCT: BLOCK NIPUQ ; # datagrams on input queue,,vector args + +IPQOSW: -1 ? 0 ; IP Queue assignment lock + BBLK + +; IPQO - IPQ OPEN routine +; Control bits currently defined are + %IQSYS==100 ; Set up System Queue (0 or 1) + %IQSOU==200 ; System Queue 1 if set, otherwise 0 + %IQUDP==400 ; Set up random queue for UDP (port # in FN1) + +IPQO: CALL SWTL ; Only one job at a time hacking IQ allocation. + IPQOSW + SETZB E,I ; Set up convenient zeros + TLNE C,%IQSYS ; Asking for system queue? + JRST [ TLNE C,%IQSOU ; Yes, want input or output? + MOVEI I,1 ; Output, use queue 1 + SKIPE IPUQUS(I) ; Skip if it's free + JRST OPNL23 ; Nope, say "file locked". + JRST IPQO2] ; Can grab it, do so! + MOVE I,[-,,2] ; Scan tables, skipping 0'th entry + SKIPE IPUQUS(I) ; Look for free slot + AOBJN I,.-1 + JUMPGE I,OPNL6 ; If none available, claim "device full" + TLNN C,%IQUDP ; Got it. If will use UDP vectoring, + JRST OPNL33 ; No, complain "meaningless args" + ; since nothing else understood yet. + TLO E,%IQUDP ; then set flag for IPUQUS. + HRRZM A,IPUQCT(I) ; Store FN1 as UDP port number + CAIA +IPQO2: SETZM IPUQCT(I) + SETZM IPUQHD(I) ; Clear input queue + MOVEI A,IPQDN ; IOCHNM device index to use + HRLI A,(I) ; Save IQ index in LH + MOVEM A,(R) + MOVEI A,-IOCHNM(R) ; Start putting together the IPUQUS entry. + SUBI A,(U) ; Get channel # + DPB A,[.BP IQ%CH,E] ; Remember it in IPUQUS word + HRRI E,(U) ; Put user index in RH + MOVEM E,IPUQUS(I) ; Store, queue is now activated! + ; Note this must be last thing, to avoid + ; timing errors. + CALRET LSWPJ1 ; Unlock switch and return! + +; IPQCLS - IPQ CLOSE routine + +IPQCLS: HLRZ I,(R) ; Get IQ idx + CAILE I,1 ; Is it the Sys In or Out queue? + JRST IPQCL5 ; Nope, can handle normal case. + CONO PI,NETOFF ; Keep anything from being added meanwhile + SETZM IPUQUS(I) ; Mark queue not active, to avoid revector loops. + SETZM IPUQCT(I) ; Be tidy and clear other stuff too. + JUMPE I,IPQCL3 + + ; Close down System Output queue. This means all output + ; on this queue gets moved directly onto the real output + ; queue. +IPQCL1: MOVEI Q,IPUQHD(I) + CALL PKQGF(PK.IP) ; Get first thing queued up + JUMPE A,[CONO PI,NETON ; Exit if no more. + CALRET IPOGO] ; Ensure output fired up. + MOVEI Q,IPOUTQ + CALL PKQPL(PK.IP) ; Put at end of real output queue + JRST IPQCL1 + + ; Close down System Input queue. This means all currently + ; queued input gets processed immediately. Note I gets + ; clobbered, but isn't necessary since we know this is queue 0. +IPQCL3: MOVEI Q,IPUQHD ; Get header for queue 0 + CALL PKQGF(PK.IP) ; Get A/ packet ptr + JUMPE A,NETONJ + HLRZ B,PK.BUF(A) ; Get B/ # words in packet + SETZ C, ; Get C/ # wds offset to IP header + CALL IPRDGM ; Process and vector it. + JRST IPQCL3 ; Get next + + + ; Normal datagram input queue. Doesn't need NETOFF since + ; PI level ignores the queue entry if it's inactive. Just + ; need to keep another job from assigning it... +IPQCL5: CONO PI,CLKOFF + SETZM IPUQUS(I) ; Clear its "active" entry word to stop queueing + CALL IPQRS2 ; Flush its input queue (clears IPUQHD) + SETZM IPUQCT(I) + CONO PI,CLKON + RET + +; IPQRST - IPQ RESET routine. Clears queue for channel. +; This is pretty drastic for the System I/O queues. + +IPQRST: HLRZ I,(R) ; Get IQ idx + CONO PI,NETOFF ; Prevent new dgms from arriving meanwhile. + CALL IPQRS2 ; Flush the queue + JRST NETONJ + +IPQRS2: MOVEI Q,IPUQHD(I) + CALL PKQGF(PK.IP) ; Pull off 1st thing + JUMPE A,CPOPJ ; Return when no more + MOVE T,PK.FLG(A) + CAIN I,1 ; If queue is the Sys Output queue + JRST [ TLNE T,(%PKFLS) ; Then do special stuff. + JRST IPQRS3 ; Flush only if explicitly requested + TLZ T,(%PKPIL) ; Otherwise clear PI-Locked bit + TLO T,(%PKODN) ; and claim "output done" (ha ha) + MOVEM T,PK.FLG(A) + JRST IPQRS2] +IPQRS3: CALL PKTRT ; Put all stuff on freelist. + JRST IPQRS2 + +; IPQIO - IPQ I/O routine (if anything actually tries using this) + +IPQIO: JRST OPNL34 ; Say "Wrong Type Device" + POPJ P, + +; IPQSTA - IPQ STATUS routine + +IPQSTA: + POPJ P, + +; IPQWHY - IPQ WHYINT routine + +IPQWHY: + JRST POPJ1 + +; IPQRCH - IPQ RFNAME/RCHST routine + +IPQRCH: + POPJ P, + +; IPQRFP - IPQ RFPNTR routine + +IPQRFP: JRST OPNL34 + +; IPQIOP - IPQ IOPUSH/IOPOP routine + +IPQIOP: MOVEI T,(R) + SUBI T,IOCHNM(U) + CAIN I, + MOVEI T,77 ; IOPUSH, use 77 + HLRZ I,(R) ; Get IPQ index + DPB T,[IQ$CH (I)] ; Deposit channel # + POPJ P, + +; IPQFRC - IPQ FORCE routine + +IPQFRC: + JRST POPJ1 + +; IPQFIN - IPQ FINISH routine + +IPQFIN: + JRST POPJ1 + +; IPQUSI - Give User Interrupt on I/O channel. Not a system call, +; but called by PI level routines when input arrives for +; a previously empty queue. +; Clobbers T,Q +; I/ index to IP Queue + +IPQUSI: LDB Q,[IQ$CH (I)] ; Get channel # + CAIN Q,77 ; If IOPUSHed, no interrupt. + RET + PUSH P,U + HRRZ U,IPUQUS(I) ; Get user index + CAIN U, + BUG +; MOVSI T,(SETZ) ; Needn't force PCLSR'ing. +; IORM T,PIRQC(U) + MOVE T,CHNBIT(Q) + AND T,MSKST2(U) + IORM T,IFPIR(U) + POP P,U + RET + + + +SUBTTL .CALL IPKIOT - IPQ data transfer + +; .CALL IPKIOT - Internet Protocol Packet Transfer. +; Arg 1 is channel (must be open on IPQ:, specifies queue #) +; Arg 2 is address of buffer +; Arg 3 is count of words +; Val 1 is count of words read into user space (if any) +; Control bits specify function. If none, "read" is assumed. +; Get datagram from: + %IPIUS==100 ; 1 = Get datagram from user space, not from a queue + %IPNOC==200 ; Global input no-check flag, suppresses normal check. + ; For User Space, "check" means verify, set cksum. + ; For Input Queue, "check" means verify IP header. + ; For SysIn Queue, "check" means verify IP hdr. + ; For SysOut Queue, means nothing. + %IPNOH==400 ; Don't Hang waiting for datagram (Queues only) + %IPIQK==1000 ; Keep on queue, don't remove (only for %IPOUS) +; Put datagram to: + %IPOUS==0 ; User space + %IPOUT==1 ; Output to network (bypasses SysOut queue) + %IPOFL==2 ; Flush it + %IPORV==3 ; Re-vector to input queues past this one + +IPKIOT: + HRRZ A,(R) + CAIE A,IPQDN ; Must be right type device (IPQ) + JRST OPNL34 ; Wrong device + HLRZ I,(R) ; Get IP input queue index + CAIL I,NIPUQ ; Ensure it's valid. + BUG HALT,[Bad IPUQ idx in IOCHNM] + MOVE E,CTLBTS(U) ; Get control bits for this call + MOVEI J,(E) + ANDI J,3 ; Get output type in J + + TRNN E,%IPIUS ; Getting datagram from user? + JRST [ CAIN J,%IPOUS ; Giving datagram to user? + CAIL W,3 ; Yes, ensure at least 3 args. + JRST IPKIO2 ; All's OK, go check input queue. + JRST OPNL30] ; Will write to user, but too few args! + CAIGE W,3 ; Must have at least 3 args for this one. + JRST OPNL30 ; Too few args. + + ; Get datagram from user. + ; B/ user addr of buffer + ; C/ # of 32-bit words in buffer + TRZ E,%IPIQK ; Flush "keep" bit since won't be on any list! + CAIL C,5 ; Must have at least 5 words for IP + CAIL C,%IMXLN ; Must be less or eq to maximum datagram size + JRST OPNL33 ; Too big, say meaningless args. + CAIN J,%IPOUS ; Outputting back to self? + JRST POPJ1 ; Yeah, just turn into a NOP. + CALL PKTGF ; Get a free packet buffer (hangs until got it) + PUSHJ P,LOSSET ; Must put back on freelist if we PCLSR on BLT fault + PKTPCL ; Standard routine expects ptr in A + TRCPKT A,"IPKIOT Alloc" + MOVSI B,(B) + HRR B,PK.BUF(A) + MOVEI D,(C) + ADDI D,-1(B) ; Find last address copying into + XCTR XBR,[BLT B,(D)] ; Gobble up user's buffer! May fault. + PUSHJ P,LSWDEL ; Made it through, can flush PCLSR protection + HRLM C,PK.BUF(A) ; Set # words used in buffer + MOVE B,PK.BUF(A) ; Find addr of start of buffer + HRLZM B,PK.IP(A) ; and set start of IP header. + LDB D,[IP$IHL (B)] ; Find claimed length of IP header + ADDI D,(B) ; Get addr of start of IP data + HRLZM D,PK.TCP(A) ; Set that too. + JRST IPKIO3 ; Now decide about checking datagram! + + ; Get datagram from input queue. +IPKIO2: CONO PI,NETOFF + SKIPN A,IPUQHD(I) ; Anything in the queue? + JRST [ CONO PI,NETON + TRNE E,%IPNOH ; No, see if ok to hang. + JRST POPJ1 ; Don't hang, win-return zero wds-read in A. + SKIPN IPUQHD(I) ; Hang, here we go. + CALL UFLS + JRST IPKIO2] + TRNN A,-1 ; Make sure something was there! + BUG + CAIN I,1 ; Is this SysOut queue? + JRST [ MOVE T,PK.FLG(A) ; Yes, get flags + TLNN T,(%PKFLS) ; Actually wants to flush now? + JRST .+1 ; No, let's go with it. + MOVEI Q,IPUQHD(I) + CALL PKQGF(PK.IP) ; Remove from queue + CAIN A, + BUG + CALL PKTRT ; Flush it. + JRST IPKIO2] + CONO PI,NETON + MOVE T,PK.BUF(A) ; Verify that something exists + TLNE T,-1 ; in both <# wds> field + TRNN T,-1 ; and field. + BUG HALT,[IPQ: Null dgm found on queue] + HLRZ T,PK.IP(A) ; Should also be an IP pointer + CAIN T, + BUG HALT,[IPQ: IP-less dgm on queue] + + ; Now have pointer in A to a datagram. It is still linked + ; on the input queue, unless %IPIUS is set. +IPKIO3: TRNE E,%IPNOC ; Should we check the contents at all? + JRST IPKIO5 ; Nope, just go straight ahead. + JFCL ; Here we should verify/set checksum, but... + + ; Now figure out where datagram wants to go! +IPKIO5: JRST @.+1(J) ; Only have 4 possibilities so far. + IQIO70 ; %IPOUS Output to user + IQIO60 ; %IPOUT Output to network + IQIO55 ; %IPOFL Flush it + IQIO80 ; %IPORV Re-vector through input queues + + ; %IPOFL Flush datagram. +IQIO55: TRNN E,%IPIUS ; Is it from input queue list? + CALL IPIQGF ; Yes, take it off input queue list + CALL PKTRT ; Now can return to packet freelist! + JRST POPJ1 ; Win return. + + ; %IPOUT Output datagram to network. +IQIO60: TRNN E,%IPIUS ; Is it still on an input list? + CALL IPIQGF ; Yes, take it off input queue list + CAILE I,1 ; If not from Sys I/O queue, + JRST [ CALL IPKSNQ ; Possibly send onto SysOut queue. + JRST POPJ1] + CALL IPKSNI ; Dgm from Sys queue, never goes back to SysOut + JRST POPJ1 + + + ; %IPOUS Output datagram to user (a "read" from user viewpoint) + ; This is the only place where we can PCLSR on "output". Note + ; that we cannot get here if datagram came from user, so the + ; datagram we point to is always still on input queue, and + ; we can safely PCLSR without any special backup. +IQIO70: HLRZ D,PK.BUF(A) ; Find # words available + JUMPLE C,OPNL33 ; Neg or zero count -> meaningless arg error + CAILE C,(D) ; If asking for more wds than exist, + MOVEI C,(D) ; only furnish what we've got. + MOVEI D,(B) + ADDI D,-1(C) ; Find last user word to write + HRL B,PK.BUF(A) + XCTR XBW,[BLT B,(D)] ; Shove it at him; can PCLSR here. + TRNE E,%IPIQK ; Done! Should we keep datagram around? + JRST IQIO75 ; Yes, don't flush it. + CALL IPIQGF ; Take datagram off the input queue. + CALL PKTRT ; Return entry/buffer to freelist. +IQIO75: MOVEI A,(C) ; Return count as 1st val! + JRST POPJ1 + + ; Must re-vector through stuff... + ; Note that it is illegal to re-vector a datagram from the SysOut + ; queue, because it still shares pointers and stuff with + ; (for example) TCP retransmit queues. Later, could add code to + ; get another packet buffer and copy it over, but this is better + ; done at the device driver level probably. +IQIO80: TRNN E,%IPIUS ; Came from user? + JRST [ CAIN I,1 ; No, from a queue; is it the SysOut queue? + JRST OPNL2 ; Yes, illegal. Say "Wrong direction". + CALL IPIQGF ; No, is OK. Take it off input list. + JRST .+1] + MOVEI R,(A) + HLRZ W,PK.IP(R) ; Get pointer to IP header + HLRZ H,PK.TCP(R) ; and to IP data. + SETZ J, + CONO PI,NETOFF + CALL IPRDGV ; Go vector and process the datagram. + CONO PI,NETON + JRST POPJ1 + + ; Auxiliary, clobbers D to do checking. +IPIQGF: MOVEI D,(A) + MOVEI Q,IPUQHD(I) ; Is from list, must take it off. + CALL PKQGF(PK.IP) ; Remove from IP queue list + CAME A,D + BUG ; Something added in meantime??? + RET + +SUBTTL IP TCP Interface Routines + +; IPMTU - Size of largest datagram we want to send to a given destination +; A/ Destination address +; Returns T/ MTU + +SUBN27==: ; Damn macro generates an error inside literal +NW%CHW==: ; Old CHAOS-wrapping scheme, probably unused + +IPMTU: +IFE IPUNCP,[ + PUSH P,A ; Save address for a bit + MOVEI T,576. ; Default value + GETNET A ; Network part only + CAMN A,[NW%ARP] ; Arpanet? + MOVEI T,%IMMTU ; MTU of IMP + CAMN A,[NW%AI] + MOVEI T,%IMMTU ; AI net. We know we have a good path + CAMN A,[NW%CHW] ; Wrapped chaos packets + MOVEI T,488. ; Smaller MTU + CAME A,[NW%LCS] ; Net 18 is ugly, must check subnets + JRST IPMTU1 + MOVE A,(P) ; Get full address back + TRZ A,177777 ; Mask off all but 18. + CAMN A,[SUBN27] ; Subnet 27 is fed by chaos-wrapping. + SKIPA T,[488.-40.] ; Giving it a very small MTU + MOVEI T,%IMMTU ; Good path to all others +IPMTU1: POP P,A +] ;IFE IPUNCP +IFN IPUNCP, MOVEI T,488.-40. ; This should be small enough... + RET + +IF1,.ERR Amazing MIT-Specific crocks near IPMTU... + +; IPBSLA - Best Local Address for a given destination +; A/ Destination IP Address +; Return A/ Local Address to use + +IPBSLA: +IFE IPUNCP,[ + GETNET A + CAMN A,NW%CHW + SKIPA A,[IMPUS4] ; Local Address on wrapped-chaos net + MOVE A,[IMPUS3] ; Default local host address to IMP +] ;IFE IPUNCP +IFN IPUNCP, MOVE A,[IMPUS4] + RET + +; IPLCLH - Skip return if address in A is one of us. +; Called with JSP T,IPLCLH + +IPLCLH: +IFE IPUNCP, CAME A,[IMPUS3] + CAMN A,[IMPUS4] + JRST 1(T) + JRST (T) + +; IPKSND - Invoked by TCP to send off a segment. +; Fills in the IP header fields, checksums, and puts on output queue. +; R, W, H set up pointing to segment +; The out-of-TCP information is contained in the "IP header" that +; W points to: +; IP$SRC - Source addr +; IP$DST - Dest Addr +; IP$TOL - Length of segment in bytes (must add IP header length) +; Clobbers A,B,C,D,E,Q,T +EBLK +IPIDCT: 0 ; IP identification #, incremented for each datagram +BBLK + +IPKHDR: MOVE A,IP$VER(W) ; Get first word + ADDI A,<5*4>_4 ; Add length of IP header (5 wds for now) + HRLI A,212000 ; Fill in Ver, IHL, TOS + MOVEM A,IP$VER(W) ; Set 1st wd + ADDI A,3_4 ; Now, to get # of words, round up + LSH A,-<4+2> ; (note flush 4 spare bits then divide by 4) + ANDI A,37777 ; 14 bit field now + HRLM A,PK.BUF(R) ; Store # of words, for device driver. + MOVSI A,170030 ; TTL and PTC (TCP) + MOVEM A,IP$TTL(W) ; Set 3rd wd + +IPKHD2: AOS A,IPIDCT ; Get new ID number + LSH A,<16.+4> ; Left justify it + MOVEM A,IP$ID(W) ; Use to set up 2nd wd (no flags/frags) + CALL IPCKSM ; Get IP header checksum + DPB A,[IP$CKS (W)] ; In it goes! + RET + +IPKSND: TRCPKT R,"IPKSND output call" + CALL IPKHDR + MOVEI A,(R) ; Set up PE ptr arg for following stuff. + +; IPKSNQ - entry point from IPKIOT, to send a datagram. +; A/ PE ptr to datagram - PK.BUF must be set up. +; Clobbers A,B,T,Q + +IPKSNQ: MOVSI T,(%PKODN) ; Clear the "output-done" flag. + ANDCAM T,PK.FLG(A) + TRCPKT A,"IPKSNQ output call" + SKIPE IPUQUS+1 ; Check - have System Output queue? + JRST IPKSN5 ; Yes, put on that queue. + ; No, drop into IPKSNI + +; IPKSNI - Route packet to appropriate gateway and interface +; A/ PE ptr to datagram - PK.BUF must be set up. +; Clobbers A,B,T,Q +IPKSNI: PUSH P,C + SKIPLE C,PK.BUF(A) ; Get the packet buffer from the PE + CAMG C,[2,,0] + BUG HALT,[IP: Null dgm being sent] + LDB C,[IP$DST(C)] ; Get destination address + + ;; This is where to apply final gateway routing code, based on Internet address in C. + GETNET T,C ; Get network # into T + MOVSI Q,-NIPGW ; Search table of gateways and direct routes + CAME T,IPGWTN(Q) ; Skip if network # matches + AOBJN Q,.-1 + JUMPL Q,IPSNI1 ; Jump if found entry in table + AOS Q,IPGWPG ; No gateway known for this network, so try a + CAIL Q,NIPMGW ; prime gateway and hope for an ICMP redirect! + SETZB Q,IPGWPG ; Try a different prime gateway each time +IPSNI1: MOVE T,TIME ; Remember that this gateway entry was used + MOVEM T,IPGWTM(Q) + SKIPE IPGWTG(Q) ; Skip if this is a direct route + MOVE C,IPGWTG(Q) ; Get gateway address + MOVEM C,PK.DST(A) ; Save gateway address for interface to use + CALL @IPGWTI(Q) ; Dispatch to interface + POP P,C + RET + +EBLK +IPGWPG: 0 ; Index of current prime gateway + + ; Network number +IPGWTN: + NW%LCS ; LCS net + NW%AI ; MIT-AI-NET +NIPMGW==<.-IPGWTN> ; Number of prime gateways +IFE IPUNCP, NW%ARP ; ARPA Net + HOSTN 128,31,0,0 ; MIT Chaosnet +NIPPGW==<.-IPGWTN> ; Number of permanent gateways + BLOCK 64. ; Extra stuff to patch in and for redirects +NIPGW==<.-IPGWTN> + +; Internet address of gateway servicing given net number +IPGWTG: +IFE IPUNCP,[ + HOSTN 10,0,0,77 ; MIT-GW + HOSTN 10,3,0,6 ; MIT-AI-GW +] ;IFE IPUNCP +IFN IPUNCP,[ + HOSTN 128,31,6,1 ; ??? + HOSTN 128,31,6,2 ; ??? +] ;IFN IPUNCP +IFE IPUNCP, 0 ; Send direct to Arpanet + 0 ; Send direct to Chaosnet +IFN .-IPGWTG-NIPPGW, .ERR Permanent gateway table at IPGWTG wrong size +LOC IPGWTG+NIPGW + +IPGWTI: +IFE IPUNCP,[ + IPKSNA ; MIT-GW + IPKSNA ; MIT-AI-GW +] ;IFE IPUNCP +IFN IPUNCP,[ + IPKSNC ; ??? + IPKSNC ; ??? +] ;IFN IPUNCP +IFE IPUNCP, IPKSNA ; direct to Arpanet + IPKSNC ; direct to Chaosnet +IFN .-IPGWTI-NIPPGW, .ERR Permanent gateway table at IPGWTI wrong size +REPEAT NIPGW-NIPPGW,IPKSNA + +IPGWTM: BLOCK NIPGW ; TIME entry last used + +BBLK + +IFE IPUNCP,[ + +; Queue packet for Arpanet interface +IPKSNA: MOVEI Q,IPOUTQ ; Otherwise use direct IP output queue. + MOVE B,(Q) ; Save previous contents of queue header + CALL PKQPL(PK.IP) ; Put on IP output queue + CAIE B,0 ; Kick off IP output if necessary. + RET ; Not necessary, queue was not empty +IPOGO: CALRET IMPIOS ; Just means kicking IMP for now. + +] ;IFE IPUNCP + +; Queue packet for Chaosnet interface +; A has the pe +; PK.DST(A) has the Internet address to send to, 128.31.subnet.host +; The low 16 bits are Chaosnet address to send an UNC to +IPKSNC: PUSH P,H + PUSH P,J + PUSH P,E + PUSH P,W + MOVE J,A ;J has address of PE + MOVE H,PK.BUF(A) ;H has address of IP header + MOVEI E,0 ;E has number of bytes sent so far +IPKSC1: CALL CHABGI ;Get a Chaosnet buffer in A + JRST IPKSC9 ;Give up if can't get one + MOVSI T,-%CPKDT ;Zero out the Chaosnet header + HRRI T,(A) + SETZM (T) + AOBJN T,.-1 + MOVEI T,%COUNC + DPB T,[$CPKOP(A)] + MOVE C,PK.DST(J) + DPB C,[$CPKDA(A)] + MOVEI T,MYCHAD + DPB T,[$CPKSA(A)] + MOVEI T,8_8 ;DOD Internet #x0800 + DPB T,[$CPKAN(A)] ;Protocol number + AOS CHNIPO ;Meter Internet packets out to Chaosnet + LDB Q,[IP$IHL(H)] ;Internet header length in words + MOVE T,Q ;Save header length for later + MOVSI B,(H) ;BLT IP header into Chaos packet + HRRI B,%CPKDT(A) + ADDI Q,(B) + BLT B,-1(Q) ;Q saves address of first data word + LDB B,[IP$TOL(H)] ;Total length in octets including header + SUB B,E ;Number of bytes remaining to be sent + MOVEI C,IPKSC9 ;Continuation if no more fragments needed + CAIG B,%CPMXC ;Skip if need to fragment + JRST IPKSC2 + MOVEI B,%CPMXC/4 ;Compute number of 32-bit data words in fragment + SUB B,T + TRZ B,1 ;Round down to even multiple of 8 octets + ADD B,T + LSH B,2 ;Number of bytes in this fragment including header + MOVEI W,IP%FMF ;Set more-fragments flag + IORM W,IP$FLG+%CPKDT(A) + MOVEI C,IPKSC1 ;Continuation sends another fragment +IPKSC2: DPB B,[IP$TOL+%CPKDT(A)] ;Total length of this fragment + DPB B,[$CPKNB(A)] + PUSH P,C ;Save continuation address + MOVE W,E ;Get fragment offset + LSH W,-3 ;8-octet units + LSH T,2 ;Number of bytes in header + SUB B,T ;Number of data bytes + LDB C,[IP$FRG+%CPKDT(A)];Set fragment offset + ADD C,W + DPB C,[IP$FRG+%CPKDT(A)] + ADD T,E ;Byte offset of start of data to send + LSH T,-2 ;Word offset + ADD T,H ;Word address + HRL Q,T ;BLT pointer to copy data + MOVEI T,3(B) + LSH T,-2 ;Number of words to copy + ADDI T,-1(Q) ;Address of last word to store + BLT Q,(T) ;Copy the data + ADD E,B ;Offset for next fragment + MOVEI W,%CPKDT(A) + CALL IPCKSM ;Compute header checksum + DPB A,[IP$CKS (W)] ;Store header checksum + MOVEI A,-%CPKDT(W) ;Restore address of chaos packet + SETOM -2(A) ;Not on any packet lists + PUSH P,J ;Save registers clobbered by CHAXMT + PUSH P,D + PUSH P,E + PUSH P,TT + CALL CHAXMT ;Launch packet into Chaosnet + POP P,TT + POP P,E + POP P,D + POP P,J + POPJ P, ;Take continuation + +IPKSC9: MOVE A,J ; The PE + CALL IPIODN ; Say we're done transmitting this packet, + POP P,W ; although it's still in Chaos NCP somewhere + POP P,E + POP P,J + POP P,H + POPJ P, + +IPKSN5: MOVEI Q,IPUQHD+1 ; Put on System Output queue + MOVE B,(Q) ; Save prev contents of header + CALL PKQPL(PK.IP) + CAIE B, ; If stuff already there, + RET ; Just return, else + PUSH P,I ; Nothing there before, give user interrupt. + MOVEI I,1 ; On IPQ SysOut queue. + CALL IPQUSI + POP P,I + RET + +; IPCKSM - Computes checksum for IP header. +; W/ points to IP header. +; Clobbers B,C +; Returns A/ checksum + +IFNDEF JCRY0,JCRY0==: ; Jump on Carry from bit 0 (and clear flag) + +IPCKSM: SETZ A, + LDB C,[IP$IHL (W)] ; Get IP header length + MOVE B,IP$CKS(W) ; Get 3rd word + ANDCM B,[IP%CKS] ; Mask out the checksum field + JFCL 17,.+1 ; Clear flags + ADD B,IP$VER(W) ; Add 1st wd + JCRY0 [AOJA A,.+1] + ADD B,IP$ID(W) ; Add 2nd + JCRY0 [AOJA A,.+1] + ADD B,IP$SRC(W) ; Add 4th + JCRY0 [AOJA A,.+1] + ADD B,IP$DST(W) ; Add 5th + JCRY0 [AOJA A,.+1] + CAILE C,5 + JRST IPCKS4 ; Longer than 5 words, must hack options. +IPCKS2: LSHC A,16. ; Get high 2 bytes (plus carries) in A + LSH B,-<16.+4> ; Get low 2 bytes in B +IPCKS3: ADDI A,(B) ; Get total sum + CAILE A,177777 ; Fits? + JRST [ LDB B,[202400,,A] ; No, must get overflow bits + ANDI A,177777 ; then clear them + JRST IPCKS3] ; and add in at low end. + ANDCAI A,177777 ; Return ones complement + RET + +IPCKS4: SUBI C,5 ; C has a 4 bit value. + MOVN C,C ; Get neg of # words left + LSH C,1 ; Double it + JUMPL C,IPCKS5(C) + RET ; Something is wrong, so just return bad val. + +REPEAT 10.,[ + ADD B,5+<10.-.RPCNT>(W) + JCRY0 [AOJA A,.+1] +] +IPCKS5: JRST IPCKS2 ; Options all added, now go fold sum. + +IFN 0,[ ; Old version +IPCKSM: MOVEI C,(W) + HRLI C,442000 ; Gobble 16-bit bytes + ILDB A,C ; wd 0 byte 1 + ILDB B,C + ADDI A,(B) ; Add 2nd byte of 1st wd + ILDB B,C ? ADDI A,(B) ? ILDB B,C ? ADDI A,(B) ; 1 ID,frag + ILDB B,C ? ADDI A,(B) ? IBP C ; 2 Skip chksum field + ILDB B,C ? ADDI A,(B) ? ILDB B,C ? ADDI A,(B) ; 3 source addr + ILDB B,C ? ADDI A,(B) ? ILDB B,C ? ADDI A,(B) ; 4 dest addr +IPCKS8: CAIG A,177777 + JRST IPCKS9 + LDB B,[202400,,A] ; Get any overflow + ANDI A,177777 + ADDI A,(B) + JRST IPCKS8 +IPCKS9: ANDCAI A,177777 + RET + +] ;IFN 0 diff --git a/src/system/ioelev.432 b/src/system/ioelev.432 new file mode 100755 index 00000000..059311bd --- /dev/null +++ b/src/system/ioelev.432 @@ -0,0 +1,4944 @@ +;;; -*-PALX-*- + .TITLE IOELEVEN + + .SBTTL DEFINITIONS + +;;; note that the .IFM macro must be used only at toplevel +;;; (non-conditionalized) in PALX because it doesn't do the expansion of .IFM +;;; when conditionalized out, therefore it doesn't match it with the +;;; following .ENDC and the .ENDC will be seen at toplevel and end the +;;; conditionalization one is in. This will screw the code running on +;;; another one of the machines even if it doesn't signal an error in your +;;; assembly. --PGS + +.LIF NZ 0 + .FATAL USE PALX DUMMY!! + +;NOTE THAT THIS PROGRAM IS DESIGNED FOR 11/40'S. TO RUN ON AN +;11/10, MACRO OUT THE SOB INSTRUCTIONS. DOES NOT USE EIS NOR FIS. + +A=%0 ;TEMP/ARG/CHAR +B=%1 ;TEMP/ARG +C=%2 ;TEMP/ARG +D=%3 ;TEMP/ARG +H=%4 ;USUALLY INDEX IN HARDWARE UNIT TABLES +I=%5 ;USUALLY LINE NUMBER TIMES 2 +SP=%6 ;STACK POINTER +PC=%7 ;PROGRAM POINTER +PS=177776 ;PROGRAM STATUS +SWR=177570 ;SWITCHES + +.MACRO RTI +.ENDM ;FUCKING PALX! + +RTI=RTT ;11/40 HARDWARE MISFEATURE + +.IF P1 +.PRINT /MACHINE NAME = / +.TTYMAC MNAM +%TTYFLG==%TTYFLG+1 +.PRINT /MNAM +/ +%TTYFLG==%TTYFLG-1 +.MACRO .IFM MCHN ;REFERS TO PDP11 NAME +.IF IDN MCHN,MNAM +.ENDM .IFM +.MACRO MCONDX MCHN ;REFERS TO ITS SYSTEM NAME, USUALLY THE SAME +.IF IDN MCHN,MNAM +.ENDM MCONDX +.MACRO FUBAR +.ENDC +.ENDC +.ENDM FUBAR +.MACRO MNAME BODY ;INSERT ITS SYSTEM NAME INTO BODY IN PLACE OF "MCHN" +.IRP MCHN, +BODY +.ENDM +.ENDM MNAME +.ENDM ;TTYMAC +.ENDC ;P1 + +VERSION==%FNAM2 + +.IFM MX-DL ;MX'S DL-10 PDP11 +.MACRO MCONDX MCHN +.IF IDN MCHN,MX +.ENDM MCONDX +.MACRO FUBAR +.ENDC +.ENDM FUBAR +.MACRO MNAME BODY +.IRP MCHN, +BODY +.ENDM +.ENDM MNAME + +DL10P==1 ;HAS DL10 +DTE20P==0 ;DOES NOT HAVE DTE20 +NODDT==0 ;HAS DDT +NFTTY==102 ;2 * # OF FIRST TTY THIS 11 +NDHS==1 ;NUMBER OF DH11'S +NDHUN==15 ;NUMBER OF UNUSED DH11 LINES +DHIBAS==320 ;DH11 INTERRUPT VECTOR BASE +DHCBAS==160020 ;CSR of first DH11 +NDLS==1 ;NUMBER OF DL11'S +CTYP==0 ;FIRST DL11 NOT T00 (CTY) +NMPTYS==0 ;NUMBER OF TTYS ON MULTIPLEXED LINE (REST IN PEACE) +;MPXIDX==2*27 ;TTY INDEX OF LINE THAT MULTIPLEXED TTYS RUN OVER +NDMS==0 ;HAS DM11BB MODEM SCANNER (BUT IT'S NOT CONNECTED TO ANYTHING) +GOULDP==0 ;DOESN'T HAVE GOULD LPT (ANYMORE) +T300P==1 ;TRIDENT T-300 AND 2561 CONTROLLER +CHAOSP==2 ;HAS TWO CHAOS NET INTERFACES +CHSBTB=0 ;CHAOSNET INTERFACE IS NEW, DOESN'T GET HUNG ANY MORE +CHAD0==440 ;CHAOSNET ADDRESS OF THIS PDP11 ITSELF +DLCADR==1440 ;CHAOSNET ADDRESS OF PDP10 CONNECTED VIA DL10 (MX) +CHAD1==3040 ;SECOND INTERFACE +TEN11P==0 ;NO TEN-11 INTERFACE +ETHERP==0 ;NO ETHERNET +FTPULS==0 ;INITIALLY, MX DOES NOT GENERATE TEST PACKETS +FTGARB==1 ;SAVE LAST GARBAGE PACKET RECEIVED +MAXBSZ==250. ;MAXIMUM TYPEOUT BUFFER SIZE +.MACRO ASPIRP BODY ;DEFINE LINE NUMBERS WITH AUTOSPEED +.ENDM ASPIRP +.ENDC ;MX-DL + +.IFM MX ;MX CONSOLE 11 +DL10P==0 ;DOES NOT HAVE DL10 +DTE20P==1 ;HAS DTE20 +NODDT==0 ;HAS DDT AND KLDCP +NFTTY==0 ;2 * # OF FIRST TTY THIS 11 +NDHS==2 ;NUMBER OF DH11'S +NDHUN==0 ;NUMBER OF UNUSED DH11 LINES +DHIBAS==310 ;DH11 INTERRUPT VECTOR BASE +DHCBAS==160020 ;CSR of first DH11 +NDLS==1 ;NUMBER OF DL11'S +CTYP==1 ;FIRST DL11 IS T00 (CTY) +NMPTYS==0 ;NUMBER OF TTYS THAT GO THROUGH MULTIPLEXED LINE (NONE) +NDMS==2 ;has 2 DM11BB modem scanners (really DH11AD) +GOULDP==0 ;DOESN'T HAVE GOULD LPT +T300P==0 ;TRIDENT T-300 AND 2561 CONTROLLER +CHAOSP==0 ;NO CHAOS NET INTERFACE +TEN11P==0 ;NO TEN-11 CHAOS INTERFACE +ETHERP==0 ;NO ETHERNET +MAXBSZ==250. ;MAXIMUM TYPEOUT BUFFER SIZE + +.MACRO ASPIRP BODY ;DEFINE LINE #S WITH AUTOSPEED +.IRP N,<1,3,4,5,6,7,10,11,12,13,14,15,16,17> + BODY +.ENDM +.ENDM ASPIRP + +TKS==177560 +TKB==177562 +TPS==177564 +TPB==177566 +.ENDC ;MX + +.IFM AI ;AI'S CHAOS-ETHER-GATEWAY PDP11 + +;THIS IS A PDP11/10, WE HAVE TO REDEFINE A FEW THINGS +.MACRO RTT +.ENDM +RTI==2 +RTT==2 +.MACRO SOB REG,TAG + DEC REG + BNE TAG +.ENDM SOB + +DL10P==0 ;HAS NO DL10 +DTE20P==0 ;DOES NOT HAVE DTE20 +NODDT==1 ;DOESN'T HAVE DDT (USE CARPET) +NFTTY==0 ;2 * # OF FIRST TTY THIS 11 +NDHS==0 ;NUMBER OF DH11'S +NDHUN==0 ;NUMBER OF UNUSED DH11 LINES +DHIBAS==320 ;DH11 INTERRUPT VECTOR BASE +DHCBAS==160020 ;CSR of first DH11 +NDLS==0 ;NUMBER OF DL11'S (ACTUALLY HAS ONE, BUT WE'RE NOT USING IT NOW) +CTYP==0 ;FIRST DL11 NOT T00 (CTY) +NMPTYS==0 ;NUMBER OF TTYS ON MULTIPLEXED LINE +NDMS==0 ;HAS NO DM11BB MODEM SCANNERS +GOULDP==0 ;DOESN'T HAVE GOULD LPT +T300P==0 ;TRIDENT T-300 AND 2561 CONTROLLER +CHAOSP==2 ;HAS TWO CHAOS NET INTERFACES +CHSBTB==0 ;CHAOSNET INTERFACE IS NEW-STYLE, DOES NOT GET HUNG +CHAD0==426 ;CHAOSNET ADDRESS OF THIS PDP11 ITSELF (AI-MC-CROSS-STREET SUBNET) +CHAD1==3072 ;SECOND INTERFACE (9TH FLOOR LISP MACHINE SUBNET) +CHADD==426 ;The DOVER protocol translator only works for this address +TEN11P==0 ;USES TEN-11 INTERFACE FOR CHAOS NET TO AI-10 (NOT ANY MORE!) +T11ADR==2026 ;CHAOSNET ADDRESS OF PDP10 CONNECTED VIA TEN-11 INTERFACE (AI) +NT11BF==3 ;THREE BUFFERS IN EACH DIRECTION FOR TEN-11 INTERFACE +ETHERP==1 ;ETHERNET +ETHHSN==6 ;MY HOST NUMBER BYTE, JNC SAYS I SHOULD USE 6 +NDVRBF==6 ;6 DOVER BUFFERS +DVRADR==1002 ;PUP ADDRESS OF DOVER +FTPULS==0 ;INITIALLY, AI DOES NOT GENERATE TEST PACKETS +FTGARB==1 ;DON'T SAVE LAST GARBAGE PACKET RECEIVED (LOW ON CORE) (not that low) +MAXBSZ==250. ;MAXIMUM TYPEOUT BUFFER SIZE +.MACRO ASPIRP BODY ;DEFINE LINE NUMBERS WITH AUTOSPEED +.ENDM ASPIRP +.ENDC ;AI + +.IIF NDF NDHS, .ERROR MACHINE NAME NOT RECOGNIZED + +.IIF NZ DL10P, .IIF Z NFTTY, .ERROR TTY # 0 DOESN'T WORK WITH DL10 PROTOCOL + +;ASSIGN TTY INDICES, HARDWARE INDICES, ETC. + +TX==NFTTY ;TTY INDEX +HX==0 ;HARDWARE INDEX +NCT==0 ;NUMBER OF TTYS + +;SYSTEM CONSOLE (OUT OF ORDER) +.IFNZ CTYP + TX==TX+2 + NCT==NCT+1 +.ENDC + +;DH11 LINES + NFDHTY==TX + TX==TX+<32.*NDHS> + NCT==NCT+<16.*NDHS> + HX==HX+<2*NDHS> + NLDHHX==HX-2 ;UNITS 0-NLDHHX INCLUSIVE ARE DH11S + + TX==TX-<2*NDHUN> ;COMPENSATE FOR UNUSED LINES + NLDHTY==TX-2 ;LAST DH11 LINE INCLUSIVE + NCT==NCT-NDHUN + +;DL11 LINES + NFDLTY==TX + NFDLHX==HX + TX==TX+<2*NDLS>-<2*CTYP> + HX==HX+<2*NDLS> + NLDLHX==HX-2 + NCT==NCT+NDLS-CTYP + +;MULTIPLEXOR LINES + NFMPTY==TX + MPKHWR==HX + TX==TX+<2*NMPTYS> + HX==HX+2 + NCT==NCT+NMPTYS + +NLTTY==NFTTY+<2*NCT> ;2 * # OF FIRST TTY NOT THIS 11 +LASTTY==NLTTY-2 ;LAST VALID TTY INDEX + +.IFNZ NDMS ;DM11-BB MODEM SCANNER + + ;1.1-1.4 MODEM CHANNEL # + DMBSY==20 ;1.5 SCAN BUSY (R.O.) + DMSCN==40 ;1.6 SCANNER ON + DMIEN==100 ;1.7 INTERRUPT ENABLE + DMDON==200 ;1.8 DONE - SCANNER HAS FOUND SOMETHING + DMSTP==400 ;1.9 STEP SCANNER TO NEXT LINE (W.O.) 1.2 USEC. + ;2.1 MAINTENANCE MODE + DMCLR==2000 ;2.2 CLEAR RTS, DTR, SEC TX, LINE EN FOR ALL LINES (W.O.) + DMCSN==4000 ;2.3 CLEAR SCAN - CLEAR CSR AND MODEM STATUS MEMORY (W.O.) 19 USEC + DM2RX==10000 ;2.4 SECONDARY RECIEVE CHANGED ON SELECTED MODEM (R.O.) + DMCTS==20000 ;2.5 CLEAR TO SEND CHANGED ON SELECTED MODEM (R.O.) + DMCAR==40000 ;2.6 CARRIER DETECT CHANGED ON SELECTED MODEM (R.O.) + DMRNG==100000 ;2.7 RING CHANGED ON SELECTED MODEM (R.O.) + + LINENB==1 ;1.1 ENABLE SCANNING OF LINE + LINDTR==2 ;1.2 DATA TERMINAL READY + LINRQS==4 ;1.3 REQUEST TO SEND (FORCE BUSY ON 103E) + LIN2TX==10 ;1.4 SECONDARY TRANSMIT + LIN2RX==20 ;1.5 SECONDARY RECEIVE (R.O.) + LINCTS==40 ;1.6 CLEAR TO SEND (R.O.) + LINCAR==100 ;1.7 CARRIER DETECT (R.O.) + LINRNG==200 ;1.8 RING (R.O.) +.ENDC ;NDMS + +; KW11-L LINE FREQ CLOCK + +LKS=177546 ;1.8 CLOCK FLAG + ;1.7 INTER ENB +HNGDLY==3*60. ;CLEAR TO SEND OFF FOR 3 SECONDS => HANGUP + +.IFNZ GOULDP +;DEFINITIONS FOR GOULD LPT + +GLPCSR=166000 ;COMMAND STATUS REGISTER (NONSTANDARD) + ;COMMAND CODES + %GCFF==0 ;TOP-OF-FORM COMMAND + %GCGRF==1 ;GRAPHIC MODE COMMAND + %GCCUT==2 ;CUT COMMAND (NO CUTTER ON THIS MACHINE, THOUGH) + %GCON==3 ;TURN PRINTER ON + %GCOFF==4 ;TURN PRINTER OFF + %GCLSL==5 ;LAST LINE (GRAPHIC MODE). => 2 MORE SCAN LINES. + %GCION==6 ;INTERRUPT ON + %GCIOF==7 ;INTERRUPT OFF + %GCADV==201 ;ADVANCE ONE LINE + ;STATUS BITS + %GSNRD==400 ;NOT READY + %GSDON==2000 ;TRANSFER COMPLETE + %GSBSY==4000 ;BUSY + %GSVAC==10000 ;VACUUM FAULT + %GSPAP==20000 ;PAPER LOW + %GSTIM==40000 ;TIMEOUT + %GSERR==50400 ;ALL ERROR BITS + +GLPWC=166002 ;NEGATIVE WORD COUNT REG + +GLPCA=166004 ;CURRENT ADDRESS REG + +GLPBSZ==132. ;BUFFER SIZE (# CHARS PER LINE) + +NGLPBF==7 ;NUMBER OF BUFFERS + GB.STA==0 ;BUFFER STATE - DON'T CHANGE ORDER OF %GB CODES + %GBIDL==0 ;0 IDLE + %GBMP==2 ;2 ACTIVE AT M.P. LEVEL + %GBWRT==4 ;4 IN WRITE QUEUE + %GBPI==6 ;6 ACTIVE AT P.I. LEVEL + %GBDMA==8 ;8 ACTIVE AT D.M.A. LEVEL + GB.NXT==2 ;CIRC POINTER TO NEXT BUFFER + GB.FF==4 ;IF NON-ZERO, FF BEFORE THIS BUFFER + GB.NL==6 ;NUMBER OF BLANK LINES BEFORE THIS BUFFER + GB.PNT==10 ;-> NEXT BYTE TO INSERT + GB.DAT==12 ;DATA BEGINS HERE + GB.LEN==GB.DAT+GLPBSZ ;TOTAL NUMBER OF BYTES PER BUFFER + +.ENDC ;GOULDP + +.IFNZ CHAOSP +;DEFINITIONS OF CHAOS NET HARDWARE + +;USUAL ADDRESS IS 764140 . USUAL INTERRUPT VECTOR IS 270 . + +CAICSR=164140 ;COMMAND STATUS REG +CH%CSR==0 + %CABSY==1 ;0 XMT BUSY (RO) + %CALUP==2 ;1 LOOP BACK (R/W) + %CASPY==4 ;2 RECIEVE MSGS FOR ANY DESTINATION (R/W) + %CARCL==10 ;3 CLEAR THE RECEIVER, IT CAN NOW GOBBLE ANOTHER MSG (WO) + %CAREN==20 ;4 RCV INT ENB (R/W) + %CATEN==40 ;5 XMT INT ENB (R/W) + %CATAB==100 ;6 TRANSMIT ABORTED BY ETHER CONFLICT (RO) + %CATDN==200 ;7 TRANSMIT DONE. SET WHEN TRANSMITTER IS DONE + %CATCL==400 ;8 CLEAR THE TRANSMITTER, MAKING IT READY (WO) + ;9-12 LOST COUNT (RO) [# MSGS RCVED WITH RCV BFR FULL] + ; WHEN MSG IS WAITING IN BUFFER, THIS COUNTS + ; THE MESSAGES THAT MATCHED OUR DESTINATION OR + ; WERE BROADCAST, BUT COULDN'T BE RECIEVED. + ; WHEN RECEIVER IS RE-ENABLED (WRITE 1 INTO %CARDN) + ; THE COUNT IS THEN CLEARED. + ; WHEN A MESSAGE IS LOST, RECEIVER ZAPS ETHER + ; SO TRANSMITTER WILL ABORT (IF MESSAGE WAS DESTINED + ; TO US.) + %CARST==20000 ;13 I/O RESET (WO) + %CAERR==40000 ;14 CRC ERROR (RO) + %CARDN==100000 ;15 RCV DONE. + +CAIMYN=164142 ;MY # (READ ONLY) +CH%MYN==2 ;RETURNS THE [SOURCE] HOST# OF THIS INTERFACE. + +CAIWBF=164142 ;WRITE BUFFER (WRITE ONLY) +CH%WBF==2 ;FIRST WAIT FOR TDONE. (OR SET IT VIA CSR) + ;FIRST WORD IN RESETS TRANSMITTER AND CLEARS TDONE. + ;STORE INTO THIS REGISTER TO WRITE WORDS OF MESSAGE, + ;LAST WORD IN IS DESTINATION ADDRESS, THEN READ CAIXMT. + ;SOURCE ADDRESS AND CHECK WORD PUT IN BY HARDWARE. + +CAIRBF=164144 ;READ BUFFER (READ ONLY) +CH%RBF==4 ;THE FIRST WORD READ WILL BE FILLED TO THE LEFT + ;TO MAKE THE MESSAGE RECIEVED A MULTIPLE OF 16 BITS. + ;IF THE NUMBER OF DATA BITS IN THE MESSAGE WAS A + ;MULTIPLE OF 16, THIS WORD WILL BE THE FIRST WORD PUT + ;INTO THE BUFFER BY THE TRANSMITTING HOST. + ;THE LAST 3 WORDS READ ARE DESTINATION, SOURCE, CHECK. + +CAIRBC=164146 ;RECEIVE BIT COUNTER (READ ONLY) +CH%RBC==6 ;WHEN A MESSAGE HAS BEEN RECEIVED THIS IS ONE LESS THAN + ;THE NUMBER OF BITS IN THE MESSAGE (16 X THE + ;NUMBER OF WORDS INCLUDING THE THREE OVERHEAD WORDS.) + ;AFTER THE LAST WORD (THE CRC WORD) HAS BEEN READ, IT IS 7777 + ;BITS 10 AND 11 ARE THE HIGH ORDER BITS, AND IF THEY ARE ONE, + ;THEN THERE WAS A BUFFER OVERFLOW + +CAIXMT=164152 ;READING THIS INITIATES TRANSMISSION (!!) +CH%XMT==12 ;THE VALUE READ IS ONE'S OWN HOST#. + +;REFERENCING ADDRESSES IN THE GROUP OF 8 WORDS NOT LISTED HERE, OR +;USING COMBINATIONS OF READ/WRITE NOT LISTED HERE, WILL TYPICALLY CAUSE +;STRANGE AND BIZARRE EFFECTS. + +;PACKET DEFINITIONS +;THESE ARE FOR 4K PACKET BUFFERS AND FOR THE ORIGINAL CHAOSNET PROTOCOL + +PKMAX==256. ;MAXIMUM LENGTH OF PACKET (INCLUDING ALL HARDWARE WORDS) +DATMAX==488. ;MAXIMUM NUMBER OF DATA BYTES +PKHDW==8 ;NUMBER OF HEADER WORDS +PKTMXW==+PKHDW ;MAX WORDS THROUGH PACKET SWITCH (SEE MOVDH ETC.) + +PKOP==1 ;BYTE INDEX OF THE OPCODE OF THE PACKET + %CORFC==1 + %COOPN==2 + %COCLS==3 + %COANS==5 + %COSNS==6 + %COSTS==7 + %CORUT==10 + %COLOS==11 + %COEOF==14 + %COUNC==15 +PKNBYT==2 ;WORD INDEX OF NUMBER OF BYTES IN PACKET +PKNBMS==170000 ;MASK FOR THE NUMBER OF BYTES +PKFC==2 ;WORD INDEX FOR THE FORWARD COUNT +PKFCMS==7777 ;IT IS THE TOP 4 BITS +PKDHST==4 ;DESTINATION HOST +PKDIND==6 ; " " " INDEX +PKSHST==10 ;SOURCE HOST +PKSIND==12 ;SOURCE INDEX +PKPKN==14 ;THE PACKET NUMBER +PKACN==16 ;THE ACK PACKET NUMBER +PKDAT==20 ;THE START OF THE DATA +.ENDC ;CHAOSP + +;STANDARD MACROS + +.MACRO PUSH X +.IRP Y, + MOV Y,-(SP) +.ENDM +.ENDM + +.MACRO POP X +.IRP Y, + MOV (SP)+,Y +.ENDM +.ENDM + +.MACRO CALL X + JSR PC,X +.ENDM + +.MACRO RET + RTS PC +.ENDM + +.MACRO SETOM LOC + ZZ===%COMPAT ;DON'T CARE WHETHER .+2 OR .+4 GETS STORED + %COMPAT===0 + MOV PC,LOC + %COMPAT===ZZ +.ENDM + +.MACRO MASK LEVEL + PUSH PS + MOV #_5,PS +.ENDM + +.MACRO UNMASK + POP PS +.ENDM + +.MACRO W +.=.+2 +.ENDM + +.MACRO T TAG ;usage is T TAG: STMNT +.=.-NFTTY +TAG +.=.+NFTTY +.ENDM + +.MACRO CONC A,B,C,D,E,F,G +A'B'C'D'E'F'G +.ENDM + +.MACRO INFORM A,B,C,D,E,F,G +.IF P1 +.PRINT /A'B'C'D'E'F'G +/ +.ENDC +.ENDM + +.MACRO MSG X +.NCHR ZZ,^\X\ + .WORD ZZ + .ASCII \X\ + .EVEN +.ENDM + +.MACRO .IREPT N,BOD +.REPT N +BOD +.ENDR +.ENDM + .IFNZ DL10P + .SBTTL DL10 CONTROL AREA + +ZZ==. +.=100000 + +DLXCSR: W ;DL10 11-SIDE CONTROL & STATUS REG + ;1.1-1.2 PIA + DLXIEN==4 ;1.3 ENABLE DLX11I TO INTERRUPT + DLXEEN==10 ;1.4 ENABLE ERRORS TO INTERRUPT + ;1.5 UNUSED + DLXPRT==40 ;1.6 PORT ENABLE (R.O.) + DLXZWC==100 ;1.7 CLEAR DLXWCO (W.O.) + DLXWCO==200 ;1.8 WORD COUNT OVERFLOW + DLXZPA==400 ;1.9 CLEAR DLXPAR (W.O.) + DLXPAR==1000 ;2.1 PAR ERR IN 10 MEM + DLXZNX==2000 ;2.2 CLEAR DLXNXM (W.O.) + DLXNXM==4000 ;2.3 NXM IN 10 MEM + DLXZ10==10000 ;2.4 CLEAR DLX10I (W.O.) + DLX10I==20000 ;2.5 INTERRUPT PDP10 + DLXZ11==40000 ;2.6 CLEAR DLX11I (W.O.) + DLX11I==100000 ;2.7 INTERRUPT PDP11 + +VERS: W ;.BYTE FIRST LINE, # OF LINES + ;SET BY -10. USED TO CHECK CONSISTENCY. + +DLXUP: W ;CHECK FOR UP-NESS IN BOTH DIRECTIONS + ;INCREMENTED BY 11 EVERY 1/60 SECOND, SETOM'ED BY 10 EVERY 1/2 SEC. + +TTYST: W ;LINE# TO START OUTPUT ON (I.E. SET OUTPUT DONE) + ;SET BY 10, CLEARED BY 11 + +TYILIN: W ;TYPEIN STATUS WORD - LINE NUMBER + ;SET BY 11, CLEARED BY 10 - INTERRUPTS 10 +TYICHR: W ;TYPEIN CHARACTER - GOES WITH PRECEDING WORD + +TYOSTS: W ;STATUS WORD (OUTPUT DONE LINE #) + ;SET BY 11, CLEARED BY 10 - INTERRUPTS 10 +TYOBSZ: W ;BUFFER SIZE FOR LINE WITH OUTPUT DINE (SET BY 11) + +TYOPNT: W ;BUFFER POINTER FOR TTY OUTPUT + ;SET BY 10 +TYOCNT: W ;BUFFER LENGTH FOR TTY OUTPUT + ;SET BY 10 +TYOLIN: W ;LINE NUMBER FOR TTY OUTPUT + ;SET BY 10, CLEARED BY 11 + +HNGLIN: W ;0000NN - LINE # NN HUNG UP + ;01RTNN - LINE # NN HAS SPEED RCV=R, XMT=T (SEE TTYTYP FOR CODES) + ;SET BY 11, CLEARED BY 10 - INTERRUPTS 10 + +LPRLIN: W ;LINE NUMBER FOR SETTING LINE PARAMETERS + ;SET BY 10, CLEARED BY 11 +LPRLPR: W ;DH11 LPR REGISTER FOR SETTING LINE PARAMETERS + ;SET BY 10 +LPRBSZ: W ;BUFFER SIZE FOR SETTING LINE PARAMETERS + ;SET BY 10 + +EXDSTS: W ;STATUS WORD (EXAMINE/DEPOSIT 11 CORE) + ;1 = EXAMINE, 2 = DEPOSIT + ;SET BY 10, CLEARED BY 11 +EXDADR: W ;ADDRESS FOR ABOVE + ;SET BY 10 +EXDDAT: W ;DATA WORD FOR ABOVE + ;SET BY 10 (DEPOSIT) OR 11 (EXAMINE) + +GLPPTR: W ;BUFFER POINTER FOR GOULD OUTPUT +GLPCTR: W ;NUMBER OF BYTES YET TO BE GOBBLED +GLPTER: W ;ERROR STATUS, SET BY 11 +GLPGRF: W ;GRAPHIC MODE IF NON-ZERO, SET BY 10 + +;CHAOS NET SHARED VARIABLES +DLCINI: W ;WHEN THIS IS NON-ZERO, 11 RESETS ITS POINTERS AND CLEARS IT +DLCSP1: W ;SEND PACKET 1 (ILDB POINTER) +DLCSP2: W ;SEND PACKET 2 +DLCSS1: W ;SEND STATE 1 (0 IDLE, 1 TO 11, 2 OUTPUT DONE) +DLCSS2: W ;SEND STATE 2 +DLCRP1: W ;RECEIVE PACKET 1 (ILDB POINTER) +DLCRP2: W ;RECEIVE PACKET 2 +DLCRS1: W ;RECEIVE STATE 1 (0 IDLE, 1 READY FOR INPUT FROM 11, 2 INPUT DONE) +DLCRS2: W ;RECEIVE STATE 2 + +;^ ADD MORE HERE, E.G. IMP + +.IFNZ T300P +;DISK AREA. 14. WORDS 48. WORDS INTO THE DL-10 AREA. +.=100000+<60*2> + +DSCCHK: W ;MUST BE 2561 OCTAL TO MAKE SURE WE HAVE CORRECT PDP-10 PROGRAM +DSCREQ: W ;0 MEANS NO REQUEST. NON-ZERO MEANS 10 HAS PENDING REQUEST TO 11. +DSCDON: W ;0 MEANS NOT DONE, NON-ZERO MEANS 11 IS TELLING 10 IT'S DONE. +;NEXT 2 WORDS WRITTEN BY 11 TO TELL STATUS OF OPERATION +DSCFLT: W ;0 NO FAULT + %DFRST==100000 ; BIT 15=POWER CYCLED OR UNIBUS HUNG, SO CONTROLLER WAS RESET + ; BIT 12=Q ERROR, BIT 11=CMD NXM, BIT 10=CMD PAR + ; IF ONE OF THESE BITS IS ON, BITS 1-0 AND DSCSTS ARE THE ERROR ADDRESS + ; BITS 7-0 SYSTEM FAULT CODE IF LEFT BYTE IS ZERO + ; SEE THE 2561 OEM MANUAL FOR MEANING OF FAULT CODES +DSCSTS: W ;STATUS FROM 2561: + %DSRTR==100000 ;COMMAND WAS RETRIED + %DSECH==40000 ;UNCORRECTABLE DATA ERROR (ECC HARD) + %DSECC==20000 ;CORRECTED DATA ERROR + %DSIDE==10000 ;ID ERROR + %DSHCE==4000 ;ADDRESS ERROR (HEADER COMPARE ERROR) + %DSPRT==2000 ;WRITE-PROTECT STATUS OF SECTOR (ABORTS WRITE COMMAND) + %DSALT==1000 ;ALTERNATE-SECTOR STATUS (ABORTS READ, WRITE, AND CHECK) + %DSOVR==400 ;FIFO OVER-RUN, NOT CORRECTED BY 1 RETRY + %DSSKE==200 ;SEEK ERROR FROM DRIVE + %DSOFL==100 ;DRIVE OFF-LINE OR FAULT + %DSFLT==20 ;DRIVE FAULT + %DSNXM==10 ;NXM ON PDP11 MEMORY + %DSPAR==4 ;PARITY ERROR IN PDP11 MEMORY + %DSSFL==2 ;SYSTEM FAULT, SEE LOW BYTE OF DSCFLT + %DSWLK==1 ;DRIVE WRITE-LOCKED, WRITE ABORTED + +;FOLLOWING WORDS ARE WRITTEN BY 10 TO TELL WHAT TO DO +DSCCMD: W ;COMMAND OPCODE: + ;%DMNOP==0 ;DO NOTHING + ;%DMCST==1 ;READ OUT CONTROLLER STATE (NOT USEFUL SINCE NOT RETURNED TO 10) + %DMSNS==2 ;SENSE DRIVE STATE. DSCSTS GETS CODE FOR DRIVE TYPE IN + ; BITS 14-8 (10 FOR T-300), AND %DSWLK, %DSFLT, %DSOFL, %DSSKE + %DMTST==3 ;TEST SPECIFIED DRIVE (RUNS DIAGNOSTICS) + %DMREC==4 ;RECALIBRATE + %DMSEK==5 ;SEEK + %DMWRT==6 ;WRITE DATA + ;%DMFMT==7 ;WRITE FORMAT + ;%DMPWT==10 ;WRITE AND SET WRITE-PROTECT BIT + ;%DMAWT==11 ;WRITE AND SET ALTERNATE-SECTOR BIT + ;%DMCHK==12 ;READ AND CHECK ECC BUT DON'T STORE DATA + ;%DMLWT==14 ;LONG WRITE, WILL WRITE ECC AS WELL AS DATA + %DMRED==20 ;READ DATA. ADD 1-10 FOR VARIOUS RECOVERY FEATURES AS + ; DOCUMENTED IN THE 2561 OEM MANUAL. + ;%DMRID==40 ;READ IF FIELD, NOT USEFUL SINCE NOT RETURNED TO 10 +DSCDRV: W ;UNIT NUMBER +DSCCYL: W ;CYLINDER ADDRESS (THESE ARE COPIED BACK BY THE 11 IN CASE OF ERROR) +DSCHED: W ;HEAD ADDRESS +DSCSEC: W ;SECTOR ADDRESS +;WORD COUNT IS ALWAYS 12.*256. +;IF WE PUT IN SEEK-OVERLAP AN ATTENTION FEATURE WILL BE NEEDED +;THAT WOULD ALSO BE USED FOR DISK POWER-UP SIGNALLING +;THESE WORDS ARE SET UP BY THE 10 AS BYTE-POINTERS TO THE DATA +;TO BE TRANSFERRED. EACH BYTE POINTER CAN TRANSFER AT MOST 256 PDP10 WORDS +;DUE TO BRAIN-DAMAGE IN THE DL10, SO THERE ARE 4 OF THEM +DSCPNT: .BLKW 4 +.ENDC ;T300P + +DLXHGH:: +.=ZZ +.ENDC ;DL10P + .IFNZ DTE20P + .SBTTL DTE20 CONTROL AREA + +;LOCATIONS 400-437 ARE JUST BETWEEN US AND ITS +;LOCATIONS 440-457 ARE KNOWN ABOUT BY KLDCP ALSO + +;EPTDDT==441 ;START ADDRESS OF PDP10 NON TIME SHARING DDT +DTEFLG==444 ;NON TIME SHARING TYPEIN/TYPEOUT DONE FLAG (SET BY 11, CLEARED BY 10) +DTEF11==450 ;USED BY NON TIMESHARING TYPEIN COMMAND TO RETURN THE CHAR (SET BY 11) +DTECMD==451 ;NON TIME SHARING COMMAND (SET BY 10) +;COMMANDS THAT CAN GO IN DTECMD: + ;0-377 CHAR TO BE TYPED OUT + %DTTYI==3400 ;TYPE IN, CHAR RETURNED IN DTEF11 + %DTCLN==1001 ;60 CYCLE CLOCK ON + %DTCLF==1000 ;60 CYCLE CLOCK OFF + ;THERE ARE MILLIONS OF OTHERS, BUT WHO NEEDS 'EM? +DTECLK==445 ;60 CYCLE CLOCK FLAG (SET BY 11, CLEARED BY 10) +;DTESWR==457 ;SIMULATED SWITCH REGISTER (SET BY 11) + +;THE FOLLOWING LOCATIONS ARE ONLY USED IN TIME SHARING AND NOT KNOWN ABOUT BY KLDCP + +DTEVER==400 ;I/O VERSION NUMBER. .BYTE FIRST LINE, NUMBER OF LINES. + ;SET BY 10, CHECKED BY 11 + +DTECHK==401 ;INCREMENTED BY 11 60 TIMES PER SECOND, SETOMED BY 10 EVERY 1/2 SECOND + ;USED TO CHECK THAT 10 IS GETTING INTERRUPTS OK + +DTEINP==402 ;CONTROLS "BYTE TRANSFERS" FROM 11 TO 10 (INPUT DIRECTION). + ;SET BY 10 TO REQUEST A TRANSFER, SETOM'ED BY 11 WHEN XFER COMPLETE. + ;10 SHOULD SET UP DTEBPI IN EPT AND DO DATAO DTE, BEFORE SETTING DTEINP. + ;SEE COMMENTS BELOW DTEOUT FOR WHAT GOES IN DTEINP. +DTEOUT==403 ;CONTROLS "BYTE TRANSFERS" FROM 10 TO 11 (OUTPUT DIRECTION). + ;SET BY 10 TO REQUEST A TRANSFER, SETOM'ED BY 11 WHEN TRANSFER STARTS. + ;EACH SIDE KNOWS WHEN TRANSFER IS IN PROGRESS, DOESN'T TRY TO START + ; ANOTHER UNTIL IT HAS RECEIVED HARDWARE TRANSFER-DONE INTERRUPT. + ;10 SHOULD SET UP DTEBPO IN EPT BEFORE SETTING DTEOUT. + ;RH IS #BYTES EXPECTED, LH IS COMMAND+LINE#. COMMANDS ARE: + %DTTYO==1000 ;TELETYPE OUTPUT + ;%DTETI==2000 ;ETHERNET INPUT + ;%DTETO==3000 ;ETHERNET OUTPUT + ;^ ADD MORE COMMANDS HERE. NOTE: THE 4.1 BIT IS 1 FOR OUTPUT, 0 FOR INPUT. + +DTELSP==404 ;LINE# TO SET SPEED OF (SET BY 10, SETOMED BY 11) +DTELPR==405 ;DH11 LINE-PARAMETER-REGISTER,,BUFFER SIZE + +DTEOST==406 ;LINE# TO START OUTPUT ON (SET OUTPUT DONE). (SET BY 10, SETOMED BY 11) + + ;407 NOT USED + +DTETYI==410 ;TELETYPE INPUT + ;LH=LINE#, RH=CHAR RECEIVED. (SET BY 11, SETOM'ED BY 10) + +DTEODN==411 ;TELETYPE OUTPUT DONE + ;LH=LINE#, RH=BUFFER SIZE. (SET BY 11, SETOM'ED BY 10) + +DTEHNG==412 ;HANGUP/DIALIN WORD (SET BY 11, SETOM'ED BY 10) + ;0000NN - LINE # NN HUNG UP + ;01RTNN - LINE # NN HAS SPEED RCV=R, XMT=T (SEE TTYTYP FOR CODES) + +;^ ADD MORE HERE, NOT TO EXCEED LOCATION 437 + ;.IFNZ DTE20P + +;IOELEVEN RESIDES IN THE BOTTOM 14K OF THE CONSOLE PDP11, ALONG WITH 11DDT. +;I.E. LOCATIONS 0-70000. BE SURE TO USE .;11DDT 14K VERSION OF DDT. +;THE UPPER 14K CONTAIN KLDCP. THE FOLLOWING CALLS TO KLDCP ARE USED. +;THEY RETURN WITH C-BIT SET IF THEY LOSE (MICROCODE HUNG). + +;NOTE: KLDCP ENJOYS CLOBBERING REGISTER 0 (A). I DON'T +;KNOW IF ALL THESE CALLS DO, BUT WE'LL ASSUME THAT THEY DO. + +TENSW=EMT!145 ;UPDATE LOCATION DTESWR FROM THE SWITCHES + +EXAM=EMT!103 ;EXAMINE PDP10 MEMORY + ;BEFORE CALL, REGISTER A HAS ADDRESS OF 3 BYTES CONTAINING PDP10 ADDRESS (LOW BITS FIRST) + ;AFTER CALL, REGISTER A HAS ADDRESS OF 3 WORDS CONTAINING CONTENTS (LOW BITS FIRST) + +EXAMT=EMT!104 ;EXAMINE PDP10 MEMORY + ;.WORD PDP10-ADDRESS + ;.WORD ADDRESS OF 3-WORD DATA BLOCK + +DPOS=EMT!105 ;DEPOSIT PDP10 MEMORY + ;BEFORE CALL, REGISTER A HAS ADDRESS OF 3 WORDS CONTAINING CONTENTS + ;AND REGISTER B HAS ADDRESS OF 3 BYTES CONTAINING ADDRESS + +DPOST=EMT!106 ;DEPOSIT PDP10 MEMORY + ;.WORD PDP10-ADDRESS + ;.WORD ADDRESS OF 3-WORD DATA BLOCK + +D10MON=EMT!111 ;DEPOSIT PDP10 MEMORY, -1 + ;.WORD PDP10-ADDRESS + +$PMSG=EMT!25 ;PRINT MESSAGE ON TTY + ;.WORD ADDRESS OF ASCIZ MESSAGE + +$CNTLC=100004 ;JUMP HERE TO "CONTROL C" BACK TO KLDCP + +;WHEN KLDCP IS IDLE, AND IN "ITS MODE", IT DOES JSR PC,3000 +;WHICH CALLS IOELEVEN'S MAIN PROGRAM. RETURN WITH "C" SET +;TO READ AND EXECUTE ONE KLDCP COMMAND LINE. RETURN WITH "C" +;CLEAR TO PRINT KL10 HALTED OR CLOCK ERROR STOP MESSAGE. +;LOCATIONS 3004, 3006 MUST CONTAIN .RAD50/IOELEV/ +;IOELEV WILL RUN ON KLDCP'S STACK. + ;.IFNZ DTE20P +;INFORMATION ABOUT THE DTE20. +;EXCEPT FOR BYTE TRANSFER, WE USE THE TIME-TESTED SUBROUTINES PROVIDED BY KLDCP. + +;THE INTERRUPT VECTOR IS AT 774, BUT WE CAN'T USE IT BECAUSE WOULD HAVE +;TO COORDINATE THINGS WITH KLDCP, WHICH IS OBVIOUSLY IMPOSSIBLE. + +DLYCNT=174400 ;2.6-2.7 UNIBUS ADDRESS EXTENSION FOR BYTE TRANSFER DMA + ;1.1-2.5 14-BIT 2'S COMPLEMENT OF NUMBER OF HALF-MICROSECONDS + ; TO DELAY BETWEEN PI0 INTERRUPTS IN BYTE TRANSFER + +TO10AD=174420 ;ADDRESS (WORD OR BYTE) OF TO-10 BYTE TRANSFER DATA + +TO10BC=174414 ;1.1-2.3 NEGATIVE BYTE COUNT, 2.7 LAST XFER + ;NORMALLY SET BY 10 WITH DATAO DTE, + ;TO10 XFER STARTS WHEN BOTH TO10AD AND TO10BC HAVE BEEN LOADED + +TO11AD=174422 ;ADDRESS (WORD OR BYTE) OF TO-11 BYTE TRANSFER DATA + +TO11BC=174416 ;1.1-2.3 NEGATIVE BYTE COUNT FOR TO-11 BYTE TRANSFER + ;2.5=1 => TO-11 TRANSFER IS 8-BIT BYTES, =0 => 16-BIT WORDS + ;2.6=1 => "ASCIZ" MODE (WHICH WE DON'T USE, OF COURSE) + ;2.7=1 => LAST XFER, UPON COMPLETION INTERRUPT BOTH 10 AND 11 + ; =0 => ONLY INTERRUPT 11. 11 CAN CHANGE TO11AD, TO11BC, CONTINUE. + ;TO11 XFER STARTS WHEN BOTH TO11AD AND TO11BC HAVE BEEN LOADED + ;THE TRANSFER HAPPENS USING DMA (NPR) IN 11, PI LEVEL 0 IN 10. + +STATUS=174434 ;DTE20 STATUS REGISTER + ;READS: + %STDNI==100000 ;2.7 TO10 XFER DONE WITHOUT ERROR + %STERI==20000 ;2.5 TO10 XFER ABORTED BY ERROR + ;2.4 DATA OUT OF DTE RAM IS ALL ZERO (MAINT) + %STINV==4000 ;2.3 PDP10 IS INTERRUPTING PDP11 + ;2.2 DEPOST OR EXAMINE WORD ONE (MAINT) + ;2.1 PDP11 MEMORY PARITY ERROR IN TO10 XFER + ;1.9 PDP11 IS INTERRUPTING PDP10 + %STDNO==200 ;1.8 TO11 XFER DONE WITHOUT ERROR + ;1.7 E BUFFER SELECT (MAINT) + ;1.6 TO11 XFER STOPPED DUE TO ZERO BYTE (IN ASCIZ MODE) + ;1.5 TO11 XFER OR PDP10 EXAMINE ENCOUNTERED EBUS PARITY ERROR + ;1.4 1 => RESTRICTED MODE + ;1.3 0 => EXAMINE/DEPOSIT IN PROGRESS, 1 => DONE + %STERO==2 ;1.2 TO11 XFER ABORTED BY ERROR + ;1.1 1 => DTE ENABLED TO INTERRUPT PDP11 + ;WRITES: + %STCLI==51000 ;2.6+2.4+2.1 CLEAR TO10 XFER DONE AND ERROR FLAGS + %STUNV==2000 ;2.2 CLEAR PDP10 INTERRUPTING PDP11 + %STINX==400 ;1.9 SET PDP11 INTERRUPTING PDP10 + %STCLO==121 ;1.7+1.5+1.1 CLEAR TO11 XFER DONE AND ERROR FLAGS + ;1.6 ENABLE INTERRUPTS + ;1.4 DISABLE INTERRUPTS + +DIAG1=174430 ;DIAGNOSTIC WORD 1, INCLUDES FLAGS + %D1ERR==4000 ;2.3 KL10 CLOCK ERROR STOP + %D1RUN==2000 ;2.2 KL10 RUN INDICATOR (1 IF 11 WANTS 10 TO RUN) + %D1HLT==1000 ;2.1 KL10 HALT INDICATOR (1 IF 10 DOES A JRST 4) + +DIAG3=174436 ;DIAGNOSTIC WORD 3, INCLUDES FLAGS + %D3BYT==1 ;1.1 WRITING 0 SETS TO10 XFER IN WORD MODE, 1 BYTE MODE + ;THERE'S NOTHING ELSE OF THE SLIGHTEST USE IN THIS REGISTER, + ;SO IT'S OK TO WRITE IT AT ANY TIME. +.ENDC ;DTE20P + + .SBTTL LOW CORE + +.IFZ DTE20P ;IF USING DTE20, THESE ARE SET UP BY KLDCP +.=4 + TRAP4 + 340 + TRAP10 + 340 +; TRAP14 ;SET UP BY 11DDT +; 340 +.=20 + TRAP10 ;IOT + 340 + PWRFAL + 340 + TRAP10 ;EMT + 340 + TRAP10 ;TRAP + 340 +.ENDC ;DTE20P + +;CHAOS NET INTERRUPT VECTORS ARE UNFORTUNATELY NOT IN A REASONABLE ARRAY +.IFGE CHAOSP-1 +.=270 + .WORD CHS0BK,5_5 + ;274 IS INTERVAL TIMER +.ENDC ;CHAOSP-1 +.IFGE CHAOSP-2 +.=230 + .WORD CHS1BK,5_5 + ;234 IS INTERVAL TIMER +.ENDC ;CHAOSP-2 +.IFGE CHAOSP-3 +.=240 + .WORD CHS2BK,5_5 + ;244 IS INTERVAL TIMER +.ENDC ;CHAOSP-3 +.IFGE CHAOSP-4 + .ERROR WHERE DOES THE FOURTH CHAOSNET INTERRUPT VECTOR GO? +.ENDC ;CHAOSP-4 + +.IFNZ ETHERP +.=400 + ETHOBK + 5_5 + ETHIBK + 5_5 + ETHOBK ;COLLISION + 5_5 +.ENDC ;ETHERP + +.IFNZ T300P +.=254 + DSKBRK + 240 ;BR5 +.ENDC ;T300P + +.=300 +.REPT NDMS ;DM11s go in floating vectors +CONC DM,\.RPCNT+1,BRK + 240 ;INTERRUPTS ON BR4 BUT WE MASK TO BR5 ANYWAY +.ENDR ;NDMS + +.IFNZ NDLS +.=60 + DL1IBK ;FIRST DL11 LINE IS PDP11'S CONSOLE TTY, DIFFERENT ADDRESS + 240 ;AGAIN INTERRUPTS ON BR4 BUT MASK TO BR5 SO CAN USE DH11 ROUTINES W/O FEAR + DL1OBK + 240 +.ENDC ;NDLS +.=310 +.REPT NDLS-1 ;DL11S AFTER THE FIRST ARE IN FLOATING VECTORS +CONC DL,\.RPCNT+2,IBK + 240 +CONC DL,\.RPCNT+2,OBK + 240 +.ENDR + +.=DHIBAS ;DON'T RELY ON RANDOM FLOATING VECTOR TO + ;COME OUT RIGHT, E.G. IF THERE IS A DL11 + ;THERE WHICH WE AREN'T USING. +.REPT NDHS ;DH11S ARE IN FLOATING VECTOR AFTER DL11[E]S +CONC DH,\.RPCNT+1,IBK ;DH11 #n RECEIVE + 240 +CONC DH,\.RPCNT+1,OBK ;DH11 #n TRANSMIT & ERROR + 240 +.ENDR ;NDHS +.=100 + CLKBRK ;KW11-L 60-CYCLE CLOCK + 300 ;ON BR6 + +.IFNZ GOULDP +.=174 + GLPBRK + 300 ;BR5 BUT NEED TO LOCK OUT CLOCK SO MASK 6 +.ENDC ;GOULDP + +.IFG NMPTYS +.=56 +MPXENB::0 ;NONZERO TO ENABLE MULTISCHLUNKER +.ENDC + +.IFZ DTE20P ;IF DTE20, KLDCP SUPPLIES THE STACK +.=1000 +STKBAS:: + JMP INIT ;START AT 1000 IS CONVENTIONAL +.IFF ;DTE20P +.=3000 ;ENTRY VECTOR + JMP @#INIT +SADR=.-2 ;ARG OF THE JMP@# IS CHANGED AFTER INITIALIZATION + .RAD50 /IOELEV/ +.ENDC ;DTE20P + + .SBTTL TEN-11 CHAOSNET COMMUNICATION AREA + +.IFNZ TEN11P +T11BFL==8+<2*PKTMXW> ;BYTE LENGTH OF A PACKET BUFFER + ;FIRST 8 BYTES ARE BUFFER-FULL FLAG AND CKSM +.IIF NE T11BFL-<*4>, .ERROR T11BFL NOT MULTIPLE OF 4 + +.IIF NE .-1004, .ERROR CHAOSNET TEN-11 COMMUNICATION AREA NOT AT RIGHT ADDRESS + +;THIS AREA IS SHARED WITH THE PDP10 VIA TEN-11 INTERFACE. + + .WORD "CH,1 ;ERROR CHECK AND VERSION NUMBER +T11I10: .WORD 0,0 ;SET NON-ZERO BY 11 TO REINITIALIZE 10 +T11I11: .WORD 0,0 ;SET NON-ZERO BY 10 TO REINITIALIZE 11 + .WORD T11BFL,NT11BF ;BUFFER SIZE, NUMBER OF BUFFERS + .BLKW 8 ;SPARE WORDS +T11OBF: .BLKB T11BFL*NT11BF ;TO-10 BUFFERS + T11OBE==. ;END OF TO-10 BUFFERS +T11IBF: .BLKB T11BFL*NT11BF ;FROM-10 BUFFERS + T11IBE==. ;END OF FROM-10 BUFFERS +;THE FIRST 32-BIT WORD OF A BUFFER IS 0 IF IDLE, OR +;NON-ZERO IF BUFFER IS TO BE SENT TO OTHER MACHINE. +;THE SECOND 32-BIT WORD IS THE CHECKSUM, WHICH IS +;COMPUTED BY ADDING ALL THE 32-BIT WORDS, IGNORING OVERFLOW, +; AND LOGICALLY SHIFTING RIGHT ONE BIT AFTER EACH ADD; BITS SHIFTED +; OUT ON THE RIGHT ARE BROUGHT BACK IN ON THE LEFT. +;IF THE NUMBER OF 16-BIT WORDS IS ODD, THE LEFT-OVER ONE BETTER BE 0. +.ENDC ;TEN11P + + .SBTTL CONFIGURATION + +; TABLES INDEXED BY H (PER HARDWARE UNIT) + +.MACRO DHTE AD ;DH11 REGISTER ADDRESS GENERATOR +.REPT NDHS + +<20*.RPCNT> +.ENDR +.ENDM + +.MACRO DLTE AD ;DL11 REGISTER ADDRESS GENERATOR, FIRST IS WIERD +.IFNZ NDLS + 177560+<&7> +.REPT NDLS-1 + +<10*.RPCNT> +.ENDR +.ENDC ;NDLS +.ENDM + +.MACRO DMTE AD ;DM11 register address generator + .REPT NDMS + +<10*.RPCNT> ;a DM11 eats 8 locations + .ENDR +.ENDM + +DMCSR: DMTE 170500 ;first DM11 is at 170500 + +DMLSR: DMTE 170502 ;selected line status at 170502 + +DHSCR: DHTE DHCBAS ;SYSTEM CONTROL REGISTER + ;1.1-1.4 LINE NUMBER + ;1.5-1.6 MEMORY ADDRESS EXTENSION + DHRENB==100 ;1.7 RECEIVER INTERRUPT ENABLE + ;1.8 RECEIVER INTERRUPT + ;1.9 CLEAR NXM FLAG + ;2.1 MAINTENANCE MODE + DHSNXM==2000 ;2.2 NXM FLAG (GENERATES XMT INTERRUPT) + ;2.3 MASTER CLEAR + DHSENB==10000 ;2.4 STORAGE SILO FULL INTERRUPT ENABLE + DHTENB==20000 ;2.5 TRANSMITTER & NXM INTERRUPT ENABLE + ;2.6 STOARGE FULL INTERRUPT + DHTDON==100000 ;2.7 TRANSMITTER DONE INTERRUPT + +DLKS==DHSCR + DLTE 175610 ;KEYBOARD STATUS REGISTER + ;1.1 PAPER TAPE READER ENABLE (WO) + ;1.2 DATA TERMINAL READY (RW) + ;1.3 REQUEST TO SEND (RW) + ;1.4 SECONDARY TRANSMIT DATA [OR MAKE BUSY] (RW) + ;1.5 UNUSED + ;1.6 DATASET INTERRUPT ENABLE (RW) + ;1.7 RECEIVE INTERRUPT ENABLE (RW) + ;1.8 RECEIVE DATA READY (RO) + ;1.9 UNUSED + ;2.1 UNUSED + ;2.2 SECONDARY RECEIVE DATA (RO) + ;2.3 RECEIVE ACTIVE (RO) + ;2.4 CARRIER DETECT (RO) + ;2.5 CLEAR TO SEND (RO) + ;2.6 RING INDICATOR (RO) + ;2.7 DATASET STATUS CHANGE (RO) + +DHNRC: DHTE DHCBAS+2 ;NEXT RECEIVED CHARACTER + ;1.1-1.8 THE CHARACTER + ;1.9-2.3 LINE NUMBER + %DXPAR==10000 ;2.4 CHAR HAS WRONG PARITY + %DXBRK==20000 ;2.5 FRAMING ERROR (BREAK) + %DXOVR==40000 ;2.6 OVERRUN, PREVIOUS CHARS LOST + ;2.7 1 => THIS WORD VALID +DLKB==DHNRC + DLTE 175612 ;KEYBOARD INPUT REGISTER + ;1.1-1.8 RECEIVED DATA + ;2.4 PARITY ERROR (RO) + ;2.5 FRAMING ERROR (RO) + ;2.6 OVERRUN (RO) + ;2.7 OR OF ERROR BITS (RO) + +DHLPR: DHTE DHCBAS+4 ;LINE PARAMETER REGISTER + ;1.1-1.2 CHARACTER LENGTH 0=5, 1=6, 2=7, 3=8 (PARITY BIT EXTRA) + ;1.3 1 => EXTRA STOP BIT + ;1.5 ENABLE PARITY + ;1.6 0 -> EVEN PARITY, 1 => ODD + ;1.7-2.1 RECEIVER SPEED + ; 0 OFF, 1 50, 2 75, 3 110, 4 134.5, 5 150, 6 200, 7 300 + ; 10 600, 11 1200, 12 1800, 13 2400, 14 4800, 15 9600, 16 A, 17 B + ;2.2-2.5 TRANSMITTER SPEED, SAME CODES AS RECEIVER + ;2.6 HALF DUPLEX + ;2.7 ECHOPLEX + +DHCA: DHTE DHCBAS+6 ;CURRENT ADDRESS +DLCA==DHCA + .IREPT NDLS,0 + +DHBC: DHTE DHCBAS+10 ;BYTE COUNT (MINUS) +DLBC==DHBC + .IREPT NDLS,0 ;POSITIVE FOR DLS + +DHBAR: DHTE DHCBAS+12 ;BUFFER ACTIVE REGISTER + ;BIT = 1 IF XMT ACTIVE ON CORRESP LINE, NUMBERED RIGHT TO LEFT +DLPS==DHBAR + DLTE 175614 ;PRINTER STATUS + ;1.1 SEND BREAK (RW) + ;1.3 LOOP BACK (RW) + ;1.6 INTERRUPT ENABLE (RW) + ;1.7 TRANSMITTER READY (RO) + +DHBCR: DHTE DHCBAS+14 ;BREAK CONTROL REGISTER + ;BIT = 1 => SEND BREAK ON CORRESP LINE, NUMBERED RIGHT TO LEFT +DLPB==DHBCR + DLTE 175616 ;PRINTER BUFFER + ;1.1-1.8 DATA TO TRANSMIT + +DHSSR: DHTE DHCBAS+16 ;SILO STATUS REGISTER + ;1.1-1.6 SILO ALARM LEVEL + ;1.7-1.8 READ EXTENDED ADDRESS (R.O.) + ;1.9-2.5 SILO FILL LEVEL (R.O.) + ;2.7 MAINTENANCE PATTERN (W.O.) + +DHOAC: .IREPT NDHS,0 ;BIT ON IF SOFTWARE THINKS LINE'S TRANSMITTER IS ACTIVE +DLOAC==DHOAC + .IREPT NDLS,0 ;NON-ZERO IF LINE'S TRANSMITTER IS ACTIVE + +DHTYNO: .IREPT NDHS, NFDHTY+<32.*.RPCNT> ;TTY INDEX OF FIRST LINE ON THIS DH11 +DLTYNO==DHTYNO +.IIF NZ CTYP,0 ;TTY INDEX OF LINE ON THIS DL11 +.IREPT NDLS-CTYP,NFDLTY+<2*.RPCNT> + +STROUT: .IREPT NDHS, STRDH ;OUTPUT-START ROUTINES + .IREPT NDLS, STRDL +.IIF NZ NMPTYS, STRMPK + + .BLKB NFTTY ;AVOID LABEL OVERLAPPAGE + +;TABLES INDEXED BY I (PER LINE) + +T HDWR: ;HARDWARE UNIT INDEX, GOES IN H +.IIF NZ CTYP, NFDLHX + .REPT NDHS + ZZ==.RPCNT*2 + .REPT 16. + ZZ ;16 LINES ON EACH DH-11 + .ENDR + .ENDR + .=.-<2*NDHUN> +.IREPT NDLS-CTYP,NFDLHX+<2*.RPCNT>+<2*CTYP> +.IREPT NMPTYS, MPKHWR ;MULTIPLEXOR-KLUDGE TTYS + +T DHLSEL: ;DH11 LINE SELECT WORDS +.IIF NZ CTYP, 0 ;NONE FOR CTY + .REPT NDHS + .REPT 16. + DHTENB+DHRENB+.RPCNT + .ENDR + .ENDR + +T DHLBIT: ;BIT CORRESPONDING TO THIS LINE IN DHBAR, ETC. +.IIF NZ CTYP, 0 ;NONE FOR CTY + .REPT NDHS + .REPT 16. + 1_.RPCNT + .ENDR + .ENDR + +T BUFPNT: ;BUFFER POINTERS + .IREPT NCT, BUFFRS+<.RPCNT*MAXBSZ> + +T BUFSIZ: ;BUFFER SIZES (I.E. AMOUNT TO USE AT CURRENT SPEED) + .REPT NCT + 0 ;SET DURING INITIALIZATION + .ENDR + +T NRMIPC: ;NORMAL INPUT CHARACTER PROCESSING ROUTINES +.IIF NZ CTYP, RCV ;CTY NORMAL INPUT + .REPT 16.*NDHS + DHNRMI ;DH11 TTY NORMAL INPUT + .ENDR + .=.-<2*NDHUN> +.IREPT NDLS-CTYP,RCV ;DL11 NORMAL INPUT +.IREPT NMPTYS, RCV ;NORMAL INPUT FOR TTYS ON MULTIPLEXOR-KLUDGE +.IIF NE .-NRMIPC-NLTTY, .ERROR BARF AT NRMIPC +.IFNZ NMPTYS + .=NRMIPC+MPXIDX + MPXINP ;INPUT FROM THE MULTIPLEXED LINE IS SPECIAL + .=NRMIPC+NLTTY +.ENDC + +T TTYIPC: ;CURRENT INPUT CHAR PROCESSING ROUTINES + .BLKW NCT ;SET UP AT INIT TIME +.IIF NE .-TTYIPC-NLTTY, .ERROR BARF AT TTYIPC + +T AUTOSP: ;IF NON-ZERO, LINE GOES INTO AUTOSPEED WHEN DIALED UP + .REPT NCT ;IF MINUS ALSO WHEN BREAK SEEN + ZZ===. + ASPIRP ^\ + .IIF EQ .RPCNT+-N,+1 ;THIS LINE AUTOSPEED ON DIALUP + .IIF EQ .RPCNT++N,-1 ;ALSO ON BREAK + \ + .IIF EQ .-ZZ, 0 ;THIS LINE NOT AUTOSPEED + .ENDR +.IIF NE .-AUTOSP-NLTTY, .ERROR BARF AT AUTOSP + +.IFM MX +M2LMAP: ;MAP FROM DM11-BB CHANNEL NUMBERS TO TTY INDICES + 2*1 ;0 T01 + 0 ;1 NONE + 0 ;2 NONE + 2*4 ;3 T04 + 2*5 ;4 T05 + 2*6 ;5 T06 + 2*7 ;6 T07 + 2*10 ;7 T10 + 2*11 ;10 T11 + 2*12 ;11 T12 + 2*13 ;12 T13 + 2*14 ;13 T14 + 2*15 ;14 T15 + 2*16 ;15 T16 + 2*17 ;16 T17 + 0 ;17 NONE + 2*21 ;20 T21 + 2*22 ;21 T22 + 2*23 ;22 T23 + 2*24 ;23 T24 + 2*25 ;24 T25 + 2*26 ;25 T26 + 2*27 ;26 T27 + 2*30 ;27 T30 + 2*31 ;30 T31 + 2*32 ;31 T32 + 2*33 ;32 T33 + 2*34 ;33 T34 + 2*35 ;34 T35 + 2*36 ;35 T36 + 2*37 ;36 T37 + 2*40 ;37 T40 +.ENDC ;MX + +.IIF NE NDMS, .IIF NE .-M2LMAP-<40*NDMS>, .ERROR Too few M2LMAP entries for DM11s. + +.IFNZ NDMS + +T DIALED: ;0 IF LINE NOT DIALED UP (OR NO MODEM CONTROL ON THIS LINE) + .REPT NCT ;+ IF DIALED UP (CLEAR TO SEND IS ON) + 0 ;- IF CLEAR TO SEND DROPPED, INC EACH TICK, REACHES 0 => HUNG UP + .ENDR + +.ENDC ;NDMS + +T TTYHNG: ;DIALUP/HANGUP STATUS WAITING TO BE SENT TO 10 (0 IF NONE) + .REPT NCT + 0 + .ENDR + +T TYPING: ;POSITIVE IF LINE IS TYPING OUT FOR 10 + .REPT NCT ; WHICH MEANS -10 SHOULD BE INFORMED WHEN TYPEOUT IS FINISHED + 0 ;0 FOR NO -10 TYPEOUT, MINUS TO SEND AFTER TYPEOUT + .ENDR + +;MISC VARIABLES + +DLXOFF: -1 ;NON-ZERO IF DL10 PORT TURNED OFF BY 10 +NO.ITS: -1 ;NON-ZERO IF HAVEN'T ESTABLISHED COMMUNICATION WITH ITS YET +VERSN: .BYTE NFTTY/2,NCT ;I/O VERSION NUMBER +DMINI: 0 ;NON-ZERO => MODEM SCANNER JUST TURNED ON, GETTING INITIAL STS +WAKE: 0 ;CLOCK INTERRUPT WAKE UP MAIN PROGRAM FLAG +HNGSIG: 0 ;NUMBER OF NON-ZERO TTYHNG WORDS +10RQ: 0 ;LIGHT HACKS +LITHSE: 7 +.IFNZ DTE20P +CLKENB: 0 ;KL10 WANTS 11 TO RELAY CLOCK INTERRUPTS +KLDCPF: 0 ;NON-ZERO => USER WANTS TO GIVE A COMMAND TO KLDCP +DDTMOD: 0 ;NON-ZERO => DDT MODE TTY INPUT +DDTCHR: -1 ;NON-NEGATIVE => CHAR TYPED FOR DDT +CURSWR: 52525 ;LAST SWITCHES SENT TO -10 +OUTCMD: 0 ;0 IF OUTPUT TRANSFER IDLE + ;ELSE CURRENT COMMAND / 400 +OUTSVI: -1 ;LINE# OF CURRENT OUTPUT TRANSFER +OUTSVC: -1 ;#BYTES OF CURRENT OUTPUT TRANSFER +INPCMD: 0 ;0 IF INPUT TRANSFER IDLE + ;ELSE CURRENT COMMAND / 400 +INPSVI: -1 ;LINE# OF CURRENT INPUT TRANSFER +INPSVC: -1 ;#BYTES OF CURRENT INPUT TRANSFER +.ENDC ;DTE20P +.IFNZ NMPTYS +MPXOAC: 0 ;0 IDLE, -1 SENDING HEADER, 1 SENDING DATA +MPXOLN: 0 ;2 x MPXK# OUTPUTTING FOR +MPXSEL: NFMPTY ;TTY INDEX SELECTED FOR MPX INPUT +MPXPNT: .IREPT NMPTYS,0 ;POINTER TO CRUFT TO SEND TO EACH MPXED LINE +MPXNBT: .IREPT NMPTYS,0 ;# BYTES TO SEND, 0 IF IDLE +MPXHED: .BYTE 0,0 ;MPX OUTPUT HEADER: 200+MPXK#, BYTE COUNT +.ENDC ;NMPTYS + + .SBTTL CHAOSNET VARIABLES & TABLES + +.IFNZ CHAOSP + +NSUBNT==80. ;MAXIMUM CAPACITY 80. SUBNETS + +.IFNZ DL10P ;DL10 UNSHARED +DLCRBN: 0 ;CURRENT RECEIVE (11 to 10) BUFFER (0 OR 2) +DLCNXT: .WORD 2,0 ;FOR SWITCHING BUFFERS +DLCIBF: .BLKW PKMAX ;DL10 INPUT BUFFER +.ENDC ;DL10P + +.IFNZ TEN11P ;TEN11 UNSHARED +T11OBP: T11OBF ;NEXT BUFFER TO 10 +T11IBP: T11IBF ;NEXT BUFFER FROM 10 +T11IBA: 0 ;NON-ZERO MEANS INPUT BUFFER ACTIVE, T11IBP NEEDS ADVANCING + ;THIS IS SEPARATE FROM CHISTS+CHXT11 FOR GOOD REASONS +T11CKE: 0 ;COUNT OF TEN-11 CHECKSUM ERRORS +T11TIM: 0 ;TIMEOUT ON TRANSMISSION OF PACKET TO 10 +.ENDC ;TEN11P + +.IFNZ ETHERP +ETHSBN==2 ;SUBNET WHICH IS THE ETHERNET +.SEE ETHHSN ;MY HOST NUMBER BYTE (DEFINED IN MACHINE CONFIGURATION AREA) +ETHMXH==15.-1 ;MAXIMUM NUMBER OF HOPS (-1 => BUG IN XEROX PROGRAMS) +ETHIBF: .BLKW PKTMXW+1 ;INPUT FROM ETHERNET BUFFERED HERE (+1 HARDWARE BUG?) +ETHHDW==PKHDW-2 ;ALLOW FOR OVERLAP OF CHAOSNET HEADER AND 2-WORD ETHERNET HEADER + ;THIS IS THE OFFSET (IN WORDS) WHERE THE ETHERNET PACKET STARTS + +;HERE IS A PACKET USED TO BUILD THE ETHERNET BROADCAST GATEWAY INFO. WHAT A CROCK. +EGTBUF: .BLKW PKHDW ;SPACE FOR CHAOSNET HEADER +EGTPLN: 0 ;PUP LENGTH + 201 ;PUP TYPE 201 +EGTPID: .WORD 0,0 ;PUP IDENTIFIER + 0 ;DESTINATION (BROADCAST) + .WORD 0,2 ;DEST SOCKET 2 +EGTSRC: .BYTE ETHHSN,ETHSBN ;SOURCE (ME) + .WORD 0,2 ;SOURCE SOCKET 2 +EGTSBN: ;; FOR EACH SUBNET, .BYTE GATE-NET, TARGET-NET, HOP-COUNT, GATE-HOST + .BLKW 2*NSUBNT + 0 ;PUP CHECKSUM + +.IF DF NDVRBF +DVRHST: 0 ;ZERO IF IDLE, OR FOREIGN HOST USING +DVRIDX: 0 ;FOREIGN INDEX +DVRLIX: 0 ;LOCAL INDEX (AOS EACH TIME) +DVRTIM: 0 ;COUNTS UP TO IDLE THE FOREIGN HOST +DVRRTR: 0 ;COUNTS UP FOR RETRANSMISSION + +DVRBFL==2*+1> ;NUMBER OF BYTES IN A DOVER BUFFER (HOLDS PUP IN CHAOSNET PACKET) +DVRBUF: .BLKB DVRBFL*NDVRBF ;RING OF BUFFERS HERE +DVRBF2: .BLKW PKHDW+2 ;BUFFER FOR SENDING STS/OPN/CLS BACK (ALSO END OF RING) +DVRBFP: DVRBUF ;POINTER TO NEXT BUFFER TO GO OUT TO DOVER +DVRMSK: 0 ;MASK OF WHICH BUFFERS CONTAIN PACKETS (MSB = DVRBFP PKT) + .IIF GT NDVRBF-16., .ERROR NDVRBF MAXIMUM OF 16. ALLOWED +DVRPKP: 0 ;IF NON-ZERO, POINTER TO SPECIAL PACKET TO SEND +DVRID: 0 ;ID FOR NEXT PACKET EXPECTED BY DOVER, THIS PACKET IS OR + ; WILL BE IN THE BUFFER DVRBFP POINTS AT +DVROFS: 0 ;ID OFFSET, SUBTRACT FROM CHAOS ID TO GET PUP ID +NDVRFK: 0 ;*** TEMPORARY KLUDGE *** +.ENDC ;NDVRBF +.ENDC ;ETHERP + +PULSAR: 0 ;COUNTS DOWN TO 0 THEN TRIGGERS TRANSMISSION OF A "TEST MESSAGE" +PULSON: FTPULS ;IF THIS IS NON-ZERO, FEATURE IS ENABLED, VALUE IS TICKS BETWEEN PULSES +USECBL: 0 ;IF NON-ZERO, 10 TALKING TO SELF STILL GOES THROUGH CABLE + +NCHX==DL10P+TEN11P+CHAOSP+<2*ETHERP> ;NUMBER OF ENTRIES IN SOURCE AND SINK TABLES +.IIF DF NDVRBF, NCHX==NCHX+1 + +;METERS ETC. +.IFNZ FTGARB +CHSGBF: .BLKW PKMAX ;HOLDS LAST PACKET THAT CAME IN WITH A CHECKSUM ERROR +CHSGBH: 0 ;UNIBUS ADDRESS OF INTERFACE THAT ABOVE CAME IN ON +CHSGBS: 0 ;STATUS REGISTER THAT GOES WITH ABOVE +CHSGBC: 0 ;BIT COUNT THAT GOES WITH ABOVE +.ENDC ;FTGARB + +;FOLLOWING HAVE SEPARATE ENTRIES FOR EACH CABLE +NPKSGB: .IREPT CHAOSP+ETHERP,0 ;COUNTS THE NUMBER OF PACKETS RECEIVED WITH CHECKSUM ERRORS +HPKSGB: .IREPT CHAOSP+ETHERP,0 ;HIGH-ORDER WORD OF COUNTER +NPKSRL: .IREPT CHAOSP+ETHERP,0 ;COUNTS THE NUMBER OF PACKETS RAM LOST, + ; I.E. DIDN'T COME IN WITH A CHECKSUM ERROR BUT AFTER + ; READING IT OUT HAD ONE. EITHER THE PACKET WAS THE + ; WRONG LENGTH, OR THE RAM IS LOSING, OR HARDWARE + ; CLOBBERAGE. FOR ETHERNET IS PUP CKSM ERR COUNT + ;THIS WORD ALSO IS WHERE BIT COUNT ERRORS WOULD END UP +HPKSRL: .IREPT CHAOSP+ETHERP,0 ;HIGH-ORDER WORD OF COUNTER +CHSRLH: 0 ;UNIBUS ADDRESS OF INTERFACE THAT ABOVE LAST HAPPENED ON. +CHSRLC: 0 ;RESIDUAL BIT COUNT FOR ABOVE +NPKSLS: .IREPT CHAOSP,0 ;NUMBER OF PACKETS LOST ACCORDING TO LOSS COUNT IN HARDWARE +HPKSLS: .IREPT CHAOSP,0 ;HIGH-ORDER WORD OF COUNTER +NPKSAB: .IREPT CHAOSP+ETHERP,0 ;NUMBER OF TRANSMISSIONS ABORTED (BY COLLISION OR RECEIVE-BUSY) +HPKSAB: .IREPT CHAOSP+ETHERP,0 ;HIGH-ORDER WORD OF COUNTER +NPKSI: .IREPT NCHX,0 ;TOTAL NUMBER OF PACKETS IN ON EACH SOURCE +HPKSI: .IREPT NCHX,0 ;HIGH-ORDER WORD OF COUNTER +NPKSO: .IREPT NCHX,0 ;TOTAL NUMBER OF PACKETS OUT ON EACH SINK +HPKSO: .IREPT NCHX,0 ;HIGH-ORDER WORD OF COUNTER +NPKSIG: 0 ;NUMBER OF PACKETS IGNORED AT CHIFLS +NPKSBD: .IREPT NCHX,0 ;NUMBER OF PACKETS BAD AT CHSIHB +HPKSBD: .IREPT NCHX,0 ;HIGH-ORDER WORD OF COUNTER +NPKSRF: 0 ;NUMBER OF PACKETS FOR WHICH ROUTING FAILED +RFSBNT: -1 ;2* SUBNET# OF LAST ROUTING FAILURE + +;"INTERFACE ADDRESSES" +; A NEGATIVE INTERFACE ADDRESS IS THE UNIBUS ADDRESS OF A CHAOS INTERFACE. +; A ZERO INTERFACE ADDRESS MEANS THE DL10 +; A POSITIVE INTERFACE ADDRESS MEANS THE TEN-11, VALUE BETTER BE OCTAL 1011. + +CHSIBF: .BLKW PKMAX*CHAOSP ;INPUT BUFFER FOR PACKETS IN FROM CHAOS HDWR + +;THIS IS WHAT IS SENT BACK IN RESPONSE TO RFC TO "STATUS". +;FOR NOW, JUST THE NAME OF THE MACHINE. +HSTNAM: +.ENDC ;CHAOSP ;FUCK A DOG, PALX! +.IFM MX-DL + .ASCII \MX-IO/11\ +.ENDC +.IFM AI + .ASCII \AI-CHAOS-11\ +.ENDC +.IFNZ CHAOSP ;FUCK A DOG, PALX! +.IIF GE .-HSTNAM-32., .ERROR HSTNAM TOO LONG +.IREPT 32.-<.-HSTNAM>, .BYTE 0 ;PAD ON THE RIGHT WITH 0'S + +;CHAOSNET INPUT SOURCE AND OUTPUT SINK TABLES + + ;NOTE WELL, THE CODE RELIES ON THE ORDER OF THESE INDICES +.IIF NZ DL10P, CHXDLC==0 ;DL10 INDEX +.IIF NZ TEN11P, CHXT11==2*DL10P ;TEN11 INDEX +CHXCHS==2* ;FIRST CHAOS INDEX +.IIF NZ ETHERP, CHXETH==CHXCHS+<2*CHAOSP> ;ETHERNET INDEX +.IIF NZ ETHERP, CHXEGT==CHXETH+2 ;ETHERNET GATEWAY-INFO-BROADCAST KLUDGE INDEX +.IIF DF NDVRBF, CHXDVR==CHXEGT+2 ;DOVER PROTOCOL TRANSLATOR +.MACRO CHXCHK TAG +.IIF NE .-TAG-NCHX-NCHX, .ERROR TAG WRONG LENGTH TABLE +.ENDM CHXCHK + +;CHAOSNET INPUT SOURCE TABLES + +CHIBFP: ;BUFFER POINTER +.IIF NZ DL10P, DLCIBF ;DL10 INPUT BUFFER +.IIF NZ TEN11P, 0 ;CURRENT TEN11 INPUT BUFFER (SET FROM T11IBP+8) +.IREPT CHAOSP, CHSIBF+ ;CHAOS INPUT BUFFER +.IIF NZ ETHERP, ETHIBF ;ETHERNET +.IALSO EGTBUF ;.. +.IIF DF NDVRBF, 0 ;CURRENT DOVER BUFFER, COULD BE CHAOS OR PUP +CHXCHK CHIBFP + +CHIHDL: .IREPT NCHX, 0 ;LENGTH OF HEADER IN WORDS, PACKET CURRENTLY IN BFR + +CHISTS: .IREPT NCHX, 0 ;STATUS (0 IDLE, +1 HAS INPUT, -1 BEING OUTPUT) + +CHILNG: .IREPT NCHX, 0 ;LENGTH OF CONTAINED PACKET IN WORDS + +CHIOUX: .IREPT NCHX, 1 ;DESTINATION OUTPUT SINK INDEX (-1 IF DIRECTED TO PDP11 ITSELF) + +CHICBA: .IREPT NCHX, 0 ;DESTINATION CABLE ADDRESS + +CHIRFL: ;ADDRESS OF REFILL ROUTINE +.IIF NZ DL10P, DLCRFL +.IIF NZ TEN11P, T11RFL +.IREPT CHAOSP, CHSRFL +.IIF NZ ETHERP, ETHRFL ;ETHERNET +.IALSO CPOPJ ;.. +.IIF DF NDVRBF, DVRRFL +CHXCHK CHIRFL + +CHIHWR: ;POINTER TO HARDWARE +.IIF NZ DL10P, 1 ;NOT USED +.IIF NZ TEN11P, 3 ;NOT USED +.IREPT CHAOSP, CAICSR+<400*.RPCNT> ;QUAD-CHAOS INTERFACES HAVE TO BE 200 APART +.IIF NZ ETHERP, 164200 ;AND WE MAKE IT 400 BECAUSE ETHERNET GETS IN WAY +.IALSO 5 ;NOT USED +.IIF DF NDVRBF, 7 ;NOT USED + +;CHAOSNET OUTPUT SINK TABLES + +CHOHWR==CHIHWR ;POINTER TO HARDWARE + +CHOSTS: .IREPT NCHX, 0 ;STATUS (0 IDLE, +1 TRANSMITTING, -1 RETRANSMITTING + ; AFTER TRANS ABORT, +2 DELAYING AFTER TRANSMIT ABORT BEFORE RETRANSM) +CHOINX: .IREPT NCHX, 1 ;CURRENTLY-ACTIVE CHIxxx INDEX + +CHOXMT: ;START TRANSMISSION ROUTINE +.IIF NZ DL10P, DLCXMT +.IIF NZ TEN11P, T11XMT +.IREPT CHAOSP, CHSXMT +.IIF NZ ETHERP, ETHXMT ;ETHERNET +.IALSO 1 ;NOT USED (CHXEGT) +.IIF DF NDVRBF, DVRPKT ;DOVER +CHXCHK CHOXMT + +CHXSBN: ;SUBNET NUMBER +400 FOR STATUS SERVER +.IIF NZ DL10P, DLCADR/400+400 +.IIF NZ TEN11P, T11ADR/400+400 +.REPT CHAOSP + CONC CHAD,\.RPCNT,/400+400 +.ENDR ;CHAOSP +.IIF NZ ETHERP, ETHSBN+400 ;ETHERNET +.IALSO 776 ;NOT REAL (ETHERNET GATEWAY) +.IIF DF NDVRBF, 777 ;NOT REAL (DOVER) +CHXCHK CHXSBN + +CHXRTF: .IREPT NCHX, 0 ;NON-ZERO MEANS BROADCAST ROUTING INFO TO THIS GUY + +.IFNZ CHSBTB +CHSIDL: .IREPT NCHX, 0 ;NUMBER OF TICKS WAITING FOR TRANSMIT-DONE +CHSRST: .IREPT NCHX, 0 ;NUMBER OF TIMES HAD TO RESET HUNG INTERFACE +.ENDC ;CHSBTB + +;;; SUBNET/ROUTING TABLES + +;INDEX BY TWICE SUBNET NUMBER +SBNTYP: .IREPT NSUBNT, 0 ;TYPE OF CONNECTION TO THIS SUBNET: + ; 0 VIA GATEWAY, WITH AUTOMATIC ROUTING + ; -1 VIA GATEWAY, PATCHED IN BY HUMAN, DON'T CHANGE + ; 1 HARDWARE CONNECTION + +SBNADR: ;ADDRESS OF CONNECTION TO THIS SUBNET + ;NETWORK ADDRESS IF SBNTYP NEGATIVE OR ZERO + ;INDEX IN SOURCE/SINK TABLES IF SBNTYP GREATER THAN ZERO + 0 ;0 USED FOR UNKNOWN SUBNETS. WHEN IN DOUBT, BROADCAST. + 0 ;1 9TH FLOOR CABLE + 0 ;2 (NOT CURRENTLY USED) + 440 ;3 MX, ASSUME VIA MX-IO-11 + 426 ;4 AI, ASSUME VIA AI-CHAOS-11 + .IREPT NSUBNT-5, 0 ; WHEN IN DOUBT, BROADCAST + +SBNCST: .IREPT NSUBNT, 1000 ;COST OF ROUTING VIA CURRENT GATEWAY, SEE CHAORD + +;NOW FILL IN TABLES FOR HARDWARE CONNECTIONS THAT EXIST ON THIS MACHINE +;INCLUDING TRANSFINITE HAIR FOR ETHERNET GATEWAY INFO PACKET +ZZ==. +.IFNZ DL10P +DLCSBN==DLCADR/400 ;SUBNET PDP10 ON OTHER END OF DL10 IS ON +.=SBNTYP+ + 1 +.=SBNADR+ + CHXDLC +.=SBNCST+ + 10. ;DIRECT 10/11 CONNECTION COSTS 10. +.ENDC ;DL10P +.IFNZ TEN11P +T11SBN==T11ADR/400 ;SUBNET PDP10 ON OTHER END OF TEN11 IS ON +.=SBNTYP+ + 1 +.=SBNADR+ + CHXT11 +.=SBNCST+ + 10. ;DIRECT 10/11 CONNECTION COSTS 10. +.ENDC ;TEN11P +.ENDC ;CHAOSP + +.IFM MX-DL + CBLCST=11. ;CABLE CONNECTION COSTS 11. +.ENDC +.IFM AI + CBLCST=22. ;AI COSTS MORE 'CAUSE IT'S SICK +.ENDC + +.IFNZ CHAOSP ;sweet fucking jesus, palx +;HAIR FOR MULTIPLE CABLE INTERFACES +.REPT CHAOSP + CONC IZZZ==CHAD,\.RPCNT + IZZ==*2 + .=SBNTYP+IZZ + 1 + .=SBNADR+IZZ + CHXCHS+<.RPCNT*2> + .=SBNCST+IZZ + CBLCST ;THE CABLE COST +.ENDR ;CHAOSP + +.IFNZ ETHERP +.=SBNTYP+ + 1 +.=SBNADR+ + CHXETH +.=SBNCST+ + 11. +.ENDC ;ETHERP + +.=ZZ + +;;; CLOCKS +4SEC: 0 ;4-SECOND CLOCK COUNTER +15SEC: 0 ;15-SECOND CLOCK COUNTER + +.ENDC ;CHAOSP + +;PATCH AREA + +PAT: PATCH: .BLKW 100 + + .SBTTL RING BUFFERS + +.MACRO RING SIZE + 99$ ;IN-POINTER + 99$ ;OUT-POINTER + 0 ;NUMBER OF WORDS IN RING + ;MAX NUMBER ALLOWED + <2*>+99$ ;MAX ADDRESS ALLOWED + 99$ ;MIN ADDRESS ALLOWED +99$: .BLKW ;BUFFER +.ENDM + +RINGIN==0 +RINGOT==2 +RINGCT==4 +RINGSZ==6 +RINGTP==10 +RINGBT==12 +RINGBF==14 + +; DEFINE THE RING BUFFERS + +TYORNG: RING ;OUTPUT-DONE RING, CONTENTS = LINE NUMBER PDP10 STYLE + ;HAS TO BE EXTRA BIG BECAUSE THE OUTPUT DONES PUT IN ON + ;STARTUP FILL IT UP, THEN SOMETIMES ITS PUTS ONE IN + ;BEFORE IT TAKES ANY OUT. + +TYIRSZ==NCT*20 ;8 CHARS PER TTY (2 WORDS PER CHAR) +TYIRNG: RING TYIRSZ ;TTY INPUT RING, FIRST WORD IS CHARACTER, SECOND LINE NUMBER + + + +;MOV #RING,B +;MOV WORD,A +;CALL PUT + +PUT: CMP RINGCT(B),RINGSZ(B) + BLT 1$ + BPT ;BLOATED +1$: PUSH C + MOV RINGIN(B),C + MOV A,(C)+ + CMP C,RINGTP(B) + BLO 2$ + MOV RINGBT(B),C +2$: MOV C,RINGIN(B) + POP C + INC RINGCT(B) + RET + +;MOV #RING,B +;CALL GET +;WORD RETURNED IN A +; IT IS AN ERROR TO CALL THIS IF RING IS EMPTY + +GET: TST RINGCT(B) + BGT 1$ + BPT ;EMPTY +1$: PUSH C + MOV RINGOT(B),C + MOV (C)+,A + CMP C,RINGTP(B) + BLO 2$ + MOV RINGBT(B),C +2$: MOV C,RINGOT(B) + POP C + DEC RINGCT(B) + RET + +CLRING: CLR RINGCT(B) ;CLEAR A RING + MOV RINGBT(B),RINGIN(B) + MOV RINGBT(B),RINGOT(B) + RET + .IFNZ DTE20P + .SBTTL DTE20 SUBROUTINES + +;THE DTE20 MUST NOT BE HACKED AT INTERRUPT LEVEL, BECAUSE KLDCP USES IT TOO. +;THE FOLLOWING THREE LOCATIONS ARE ARGS TO/FROM THE FOLLOWING TWO SUBROUTINES. + +LH: 0 ;LOW 16 BITS OF LEFT HALF +RH: 0 ;LOW 16 BITS OF RIGHT HALF +SNB: 0 ;SIGN BIT (0 IF +, NON-0 IF -) + +;JSR B,HWEXAM +; .WORD ADDR +;EXAMINE PDP10 LOC, SPLIT INTO HALFWORDS, SET LH, RH, SNB +;RETURNS WITH "Z" SET IF LOCATION HAS POSITIVE SIGN, "Z" CLEAR IF MINUS SIGN + +HWEXAM: PUSH ;SAVE REGS + PUSH <#0,(B)+> ;PUT PDP10 ADDRESS ONTO PDL + MOV SP,A ;SET UP POINTER TO ADDRESS + EXAM ;EXAMINE LOCATION, SET A TO POINT TO 3-WORD RESULT BUFFER + BCS UHUNG ;BRANCH IF UCODE HUNG + MOV (A)+,RH ;LOW 16 BITS => RH + MOV (A)+,C ;PICK UP MIDDLE 16 BITS + MOV (A)+,A ;PICK UP HIGH 4 BITS + ROR A ;LSHC ,-2 TO GET PDP10 LH INTO C + ROR C + ROR A + ROR C + MOV C,LH + BIC #177775,A ;LEAVE SIGN BIT IN 1.2 OF A + MOV A,SNB + ADD #4,SP ;POP ADDRESS OFF PDL + POP ;RESTORE REGS + TST SNB + RTS B ;RETURN SKIPPING IN-LINE PARAMETER + +;JSR B,HWDEP +; .WORD ADDR +;ASSEMBLE LH, RH, SNB INTO PDP10 AND DEPOSIT IN ADDR + +HWDEP: PUSH + MOV LH,C + CLR A + TST SNB + BEQ 1$ + MOV #2,A +1$: ASL C + ROL A + ASL C + ROL A + PUSH ;PUSH HIGH, MIDDLE, AND LOW BITS + MOV SP,A ;POINTER TO DATA + PUSH <#0,(B)> ;PUSH HIGH AND LOW ADDRESS + MOV SP,B ;POINTER TO ADDRESS + DPOS ;DO THE DEPOSIT + BCS UHUNG ;BRANCH IF UCODE HUNG + ADD #10.,SP ;POP ADDRESS AND DATA OFF PDL + POP + TST (B)+ ;SKIP TRAILING PARAMETER + RTS B + +UHUNG: $PMSG + .WORD 1$ + SETOM NO.ITS ;GIVING UP + JMP $CNTLC + +1$: .ASCIZ/?MICROCODE HUNG/ + +.ENDC ;DTE20P + .IFNZ DL10P + .SBTTL MAIN LOOP FOR DL10 + +MAIN: +.IIF NZ TEN11P, CALL T11WAK ;CHECK UP ON TEN-11 INTERFACE +.IFNZ ETHERP + TST CHXRTF+CHXETH ;NEED TO BROADCAST ROUTING INFO TO ETHERNET? + BEQ 666$ + CALL ETHRUT +666$: +.ENDC ;ETHERP + BIT #DLXPRT,DLXCSR ;PORT TO 10 ENABLED? + BNE 1$ ;YES + SETOM NO.ITS ;NO, FLAG THERE IS NO ITS + SETOM DLXOFF ;AND THAT WE THINK DL10 PORT IS OFF + BR MAIN ;AND WAIT FOR IT TO TURN ON + +1$: TST DLXOFF ;DID DL10 JUST TURN ON? + BEQ 4$ ;NO, IT WAS ON BEFORE + CLR DLXOFF ;YES, SO REMEMBER THAT + MOV VERS,A ;CHECK VERSION SUPPLIED BY -10 + BEQ 2$ ;ZERO OK (MUST BE SALVAGER) + CMP A,VERSN + BEQ 2$ + BPT ;-10 AND -11 PROGRAMS NOT SAME CONFIG +2$: + +4$: BIT #DLXPAR+DLXNXM,DLXCSR ;ERROR ACCESSING MEMORY? + BEQ 5$ ;NO + BPT ;DON'T GO OFF DESTROYING PEOPLE'S FILES + +;WAIT FOR -10 TO REQUEST SERVICE, OR CLOCK TO TICK + +5$: CLR 10RQ + BIT #DLX11I,DLXCSR ;10 REQUESTING SERVICE? + BEQ 10$ + SETOM 10RQ + BIS #DLXZ11,DLXCSR ;YES, CLEAR FLAG + BR CHKOST ;AND GO CHECK FOR THINGS TO DO + +10$: TST WAKE ;NO, CHECK ANYWAY IF 60 CYCLE CLOCK HAS TICKED + BEQ MAIN ;NEITHER, JUST WAIT + CLR WAKE ;CLOCK HAS TICKED, CLEAR FLAG + INC DLXUP ;AND INCREMENT COUNTER 10 IS SUPPOSED + BEQ 11$ ; TO SETOM EVERY 1/2 SEC + CMP DLXUP,#15.*60. ;IF IT DOESN'T TOUCH IT FOR 15 SECONDS, + BLE 12$ ; CONSIDER IT DOWN. NOTE THAT PARITY SWEEPS + SETOM NO.ITS ; THROUGH LARGE MEMORY CAN TAKE SEVERAL SECONDS + MOV #15.*60.,DLXUP ;DON'T LET COUNTER OVERFLOW + BR 12$ ;BUT CHECK FOR COMMANDS ANYWAY (SALVAGER DISK) + +11$: CLR NO.ITS ;-10 HAS SETOMED COUNTER, IT'S UP +12$: ;FALL INTO CHKOST + +; CHECK FOR OUTPUT-START FROM -10 + +CHKOST: MOV TTYST,A ;LINE# TO START OUTPUT + BEQ CHKOUT ;NONE. + CLR TTYST ;TELL -10 IT'S BEEN PICKED UP + MOV #TYORNG,B + MASK 5 ;DON'T INTERFERE WITH P.I. LEVEL + CALL PUT ;PUT IN RING, LATER WILL SEND IT BACK TO 10 + UNMASK + +; CHECK FOR TTY OUTPUT SENT BY -10 + +CHKOUT: MOV TYOLIN,I ;OUTPUT TO BE DONE? + BEQ CHKIN ;NO. + MOV TYOCNT,C ;YES, GET NUMBER OF CHARS + CALL TYOSER ;CALL OUTPUT HANDLER + CLR TYOLIN ;TELL 10 WE'VE GOBBLED THE OUTPUT + BIS #DLX10I,DLXCSR ;GIVE TRANSFER-COMPLETE INTERRUPT + +; CHECK FOR TTY INPUT TO BE SENT TO -10 + +CHKIN: TST TYIRNG+RINGCT + BEQ CHKDON ;NO STATUS TO BE STORED + TST TYILIN + BNE CHKDON ;PREVIOUS STATUS NOT PICKED UP + MOV #TYIRNG,B + CALL GET + MOV A,TYICHR ;GIVE INPUT CHARACTER TO 10 + CALL GET + MOV A,TYILIN ;GIVE LINE NUMBER TO 10 + BIS #DLX10I,DLXCSR ;SEND INTERRUPT TO 10 + +; CHECK FOR OUTPUT-DONE TO BE SENT TO -10 + +CHKDON: TST TYORNG+RINGCT + BEQ CHKHNG ;NO STATUS TO BE STORED + TST TYOSTS + BNE CHKHNG ;PREVIOUS STATUS NOT PICKED UP + MOV #TYORNG,B + CALL GET + MOV A,I + ASL I + MOV BUFSIZ(I),TYOBSZ ;TELL -10 HOW MANY CHARS TO GIVE + MOV A,TYOSTS ;GIVE OUTPUT DONE TO 10 + BIS #DLX10I,DLXCSR ;WITH INTERRUPT + +; CHECK FOR HANGUPS TO BE SENT TO -10 + +CHKHNG: TST HNGSIG ;ANY HANGUPS TO BE REPORTED? + BEQ CHKLPR ;NO + TST HNGLIN + BNE CHKLPR ;PREVIOUS STATUS NOT PICKED UP + MOV #LASTTY,I ;SCAN OVER ALL LINES +1$: MASK 5 + MOV TTYHNG(I),A ;GET HANG-UP STATUS + BNE 2$ ;BRANCH IF FOUND SOMETHING TO REPORT + UNMASK + TST -(I) + CMP I,#NFTTY + BHIS 1$ + BPT ;HNGSIG OUT OF PHASE WITH TTYHNG + +2$: CLR TTYHNG(I) ;GOT STATUS, CLEAR IT + DEC HNGSIG ;DECREASE COUNT OF FROBS WAITING TO BE SIGNALLED + UNMASK ;NOW IT'S OK TO INTERRUPT AND SET TTYHNG + MOV A,HNGLIN ;GIVE LINE NUMBER AND OTHER DATA TO 10 + BIS #DLX10I,DLXCSR ;WITH INTERRUPT + +; CHECK FOR REQUEST FROM -10 TO SET LINE PARAMETERS + +CHKLPR: MOV LPRLIN,I ;LINE PARAMETERS TO BE SET? + BEQ CHKCHS ;NO. + ASL I ;YES, GET LINE INDEX + MOV LPRLPR,A ;AND DH11 PARAMETER REGISTER VALUE + MOV LPRBSZ,B ;AND BUFFER SIZE + CALL SPARAM ;CALL PARAMETER SETTER + CLR LPRLIN ;TELL 10 IT IS DONE + +; CHECK FOR CHAOS NET ACTIVITY + +CHKCHS: +.IFNZ CHAOSP + CALL DLCWAK ;WAKEUP DL10-CHAOSNET STUFF +.ENDC ;CHAOSP +.IFNZ T300P + CALL DSKSTR ;CHECK FOR DISK REQUEST +.ENDC ;T300P + +; CHECK FOR EXAMINE/DEPOSIT REQUEST FROM -10 + +CHKEXD: TST EXDSTS ;EXAMINE/DEPOSIT? + BEQ CHKGLD ;NO. + MOV EXDADR,A ;GET ADDRESS + CMP EXDSTS,#2 + BNE 21$ + MOV EXDDAT,(A) ;DEPOSIT +21$: MOV (A),EXDDAT ;EXAMINE + CLR EXDSTS ;IT IS DONE + +;CHECK FOR GOULD LPT OUTPUT + +CHKGLD: +.IF EQ GOULDP +; CLR GLPCTR ;IF NO GOULD, FLUSH OUTPUT FOR IT +; SETOM GLPTER ;AND SAY "NOT READY" + TST 10RQ + BEQ 20$ + ;10 WANTED US TO DO SOMETHING, PLAY WITH THE LIGHTS + MOV LITHSE,A + ROL A + ROL LITHSE +20$: MOV LITHSE,GLPTER +.IFF + TST GLPCTR ;ANY BYTES IN BUFFER? + BEQ 1$ + CALL GLPTYO ;YES, OUTPUT THEM +1$: MOV GLPERR,GLPTER ;COPY ERROR STATUS FROM P.I. LEVEL TO -10 +.ENDC ;DONE HERE SO NO USE OF DL10 AT P.I. LEVEL +; BR MAINX + +MAINX: JMP MAIN ;THAT'S IT +MAINE:: +.ENDC ;DL10P + .IFNZ DTE20P + .SBTTL MAIN LOOP FOR DTE20 + +MAIN: BIT #%D1RUN,DIAG1 ;IS KL10 RUNNING? + BEQ TENDED ;NO, LOSE! + BIT #%D1ERR+%D1HLT,DIAG1 ;HAS KL10 CLOCK STOPPED FOR HARDWARE ERROR? OR JRST 4 + BNE TENDED ;YES, LOSE! + TST KLDCPF ;MAYBE USER WANTS TO GIVE A KLDCP COMMAND? + BNE KLDCPR ;YES, RETURN TO KLDCP + TSTB @DLKS+NFDLHX ;CTY INPUT? + BPL 10$ ;TEST KBD BEFORE CLK SINCE MIGHT BE MORE THAN + ; 1/60'TH SECOND PER TRIP AROUND THE LOOP. + MASK 5 ;YES, SIMULATE INTERRUPT + CALL DL1IBK ;CAN'T USE REAL INTS BECAUSE WOULD INTERFERE WITH KLDCP +10$: TSTB LKS ;60 CYCLE CLOCK TICK? + BMI CLKSER ;YES + BIT #%STINV,STATUS ;REQUEST FROM 10? + BNE TENSER ;YES, SERVICE IT. + BIT #%STDNI,STATUS ;TO10 XFER COMPLETE? + BNE INPDON ;YES, SERVICE IT. + BIT #%STDNO,STATUS ;TO11 XFER COMPLETE? + BNE OUTDON ;YES, SERVICE IT. + BIT #%STERI+%STERO,STATUS + BNE LOSSAG ;BYTE TRANSFER LOST + BR MAIN ;CLOSE LOOP + +;60-CYCLE CLOCK SERVICE + +CLKSER: CLR LKS ;CLEAR CLOCK FLAG + TST CLKENB ;DOES 10 WANT CLOCK INTERRUPTS? + BEQ 1$ + D10MON ;YES, GIVE ONE + DTECLK ;SET CLOCK FLAG IN LOW CORE + BCS UHUNG + MOV #%STINX,STATUS ;AND SEND INTERRUPT +1$: CMP SWR,CURSWR ;MAYBE NEED TO UPDATE 10'S SWITCHES + BEQ 2$ + MOV SWR,CURSWR + TENSW ;LET KLDCP DO IT + BCS UHUNG +2$: JSR B,HWEXAM ;INCREMENT COUNTER -10 IS SUPPOSED + DTECHK ; TO SETOM EVERY HALF-SECOND + CLR LH + CLR SNB + INC RH + BEQ 3$ + CMP RH,#15.*60. ;IF IT DOESN'T SETOM IT FOR 15 SECONDS + BLE 4$ ;THEN IT IS DOWN. NOTE THAT PARITY SWEEPS + SETOM NO.ITS ;THROUGH LARGE MEMORY CAN TAKE SEVERAL SECONDS. + MOV #15.*60.,RH ;DON'T LET COUNTER OVERFLOW + BR 4$ + +3$: CLR NO.ITS ;IT SETOMED COUNTER, IT'S UP. +4$: JSR B,HWDEP ;PUT COUNTER BACK + DTECHK + MASK 6 ;NOW SIMULATE BR6 CLOCK INTERRUPT + CALL CLKBRK + BR TENSER ;AND GO SERVICE 10 (IN CASE LOST INTERRUPT) + +; HERE IF KL10 HALTS + +TENDED: SETOM NO.ITS + CLC + RET ;LET KLDCP PRINT THE MESSAGE + +; BYTE TRANSFER ENCOUNTERED HARDWARE LOSSAGE + +LOSSAG: BPT + BR LOSSAG + +; USER WANTS TO GIVE A KLDCP COMMAND + +KLDCPR: CLR KLDCPF + SEC + RET + +TENSER: JMP TENSR0 + +; HERE WHEN TO10 BYTE TRANSFER COMPLETE + +INPDON: MOV #%STCLI,STATUS ;CLEAR FLAGS IN DTE20 + MOV INPCMD,A ;GET COMMAND FOR XFER THAT JUST FINISHED + BNE 1$ + BPT ;WOOPS, NO XFER IN PROGRESS +1$: CLR INPCMD ;NO XFER IN PROGRESS NOW + MOV INPSVI,I + MOV INPSVC,C + CALL @FINAL-2(A) ;CALL APPROPRIATE FINISHER ROUTINE + BR MAIN + +; HERE WHEN TO11 BYTE TRANSFER COMPLETE + +OUTDON: MOV #%STCLO,STATUS ;CLEAR FLAG + MOV OUTCMD,A ;GET COMMAND FOR XFER THAT JUST FINISHED + BNE 1$ + BPT ;WHOOPS, NO XFER IN PROGRESS +1$: CLR OUTCMD ;NO XFER IN PROGRESS NOW + MOV OUTSVI,I + MOV OUTSVC,C + CALL @FINAL-2(A) ;CALL APPROPRIATE FINISHER ROUTINE + BR MAINJ + +; HERE TO START TO10 BYTE TRANSFER. HWEXAM OF DTEINP HAS BEEN DONE. + +INPSER: D10MON ;VALUE HAS BEEN PICKED UP, SETOM IT + DTEINP + BIT #1000,LH ;RIGHT GENDER OF COMMAND? + BEQ OUTSR1 ;YES + BR MAINJ ;(USED TO BE BPT) NO, IGNORE, MAYBE ITS BEING RELOADED + +; HERE TO START TO11 BYTE TRANSFER. HWEXAM OF DTEOUT HAS BEEN DONE. + +OUTSER: D10MON ;VALUE HAS BEEN PICKED UP, SETOM IT + DTEOUT + BIT #1000,LH ;RIGHT GENDER OF COMMAND? + BNE OUTSR1 ;YES + BR MAINJ ;(USED TO BE BPT) NO, IGNORE, MAYBE ITS BEING RELOADED + +OUTSR1: MOV RH,C ;GET BYTE COUNT + MOVB LH,I ;GET LINE# + MOVB LH+1,A ;GET COMMAND TIMES 2 + BEQ MAINJ ;CLEARING CORE? IGNORE ZERO COMMAND + BLE OUTSR2 + CMP A,#LBEGIN + BGT OUTSR2 + CALL @BEGIN-2(A) ;CALL APPROPRIATE BEGIN-XFER ROUTINE + BIT #2,A + BNE 1$ + MOV A,INPCMD ;REMEMBER CRUFT FOR XFER IN PROGRESS + MOV I,INPSVI + MOV C,INPSVC + BR MAINJ + +1$: MOV A,OUTCMD ;REMEMBER CRUFT FOR XFER IN PROGRESS + MOV I,OUTSVI + MOV C,OUTSVC +MAINJ: JMP MAIN + +OUTSR2: BR MAINJ ;BAD COMMAND FROM 10 (USED TO BE BPT) JUST IGNORE IT + +;TABLE OF ROUTINES TO PROCESS DATA TRANSFER COMMANDS FROM -10 + +BEGIN: TYOSER ;%DTTYO + ;ETHISR ;%DTETI + ;ETHOSR ;%DTETO +LBEGIN==.-BEGIN + +;TABLE OF ROUTINES TO FINISH UP DATA TRANSFERS + +FINAL: TYOFIN ;%DTTYO + ;ETHIFN ;%DTETI + ;ETHOFN ;%DTETO + +;CHECK FOR COMMANDS FROM 10, STORE STATUS IN ANY STATUS WORDS +;THAT 10 HAS SET BACK TO -1 + +TENSR0: MOV #%STUNV,STATUS ;CLEAR 10 INTERRUPTING 11 FLAG + JSR B,HWEXAM ;CHECK FOR A NON-TIMESHARING COMMAND + DTECMD + MOV RH,A ;IS THERE ONE? + BEQ TENSR1 ;NO, GO CHECK FOR TIMESHARING STUFF + CLR LH + CLR SNB + CMP A,#377 + BHI 2$ +1$: TSTB TPS ;CHAR TO BE TYPED, WAIT FOR READY + BPL 1$ + MOVB A,TPB ;TYPE IT OUT +9$: CLR RH ;CLEAR OUT THE COMMAND + JSR B,HWDEP + DTECMD + D10MON ;TELL 10 IT'S DONE + DTEFLG + JMP MAIN + +2$: CMP A,#%DTTYI + BNE 5$ + CLR RH ;SNB,LH,RH NOW HAS ZERO + SETOM DDTMOD ;KEYBOARD INPUT WANTED + TST DDTCHR ;TEST IF READY + BMI 3$ ;IF NO INPUT, GIVE ZERO + MASK 5 + MOV DDTCHR,RH ;GIVE THE CHAR + COM DDTCHR ;MAKE NEGATIVE + UNMASK +3$: JSR B,HWDEP + DTEF11 + BR 9$ + +5$: CMP A,#%DTCLN + BNE 6$ + SETOM CLKENB + BR 9$ + +6$: CMP A,#%DTCLF + BNE 7$ + CLR CLKENB + BR 9$ + +7$: BPT ;SOME COMMAND WE DON'T IMPLEMENT + BR 9$ ;IF CONTINUED, IGNORE IT + +;CHECK FOR ITS UP/DOWN + +TENSR1: TST NO.ITS ;IF SYSTEM ISN'T UP, + BNE MAINJ ;DON'T TRY TO HACK TS STUFF + INC DLXOFF ;OTHERWISE, FIRST TIME THROUGH HERE + BNE CHKOST ;WE CHECK THE VERSION + JSR B,HWEXAM + DTEVER + TST RH ;STORED? + BNE 1$ + DEC DLXOFF ;NO, DON'T LOOK AT IT + BR MAINJ ;PROBABLY CORE BEING CLEARED + +1$: CMP RH,VERSN + BEQ CHKOST + BPT ;-10 AND -11 PROGRAMS NOT SAME VERSION + +CHKOST: JSR B,HWEXAM ;CHECK FOR 10 WANTING OUTPUT START + DTEOST + BNE CHKTRN ;BRANCH IF LOCATION DTEOST IS -1 + D10MON ;HAVING PICKED IT UP, SET BACK TO -1 + DTEOST + MOV RH,A + MOV #TYORNG,B + MASK 5 ;DON'T INTERFERE WITH P.I. LEVEL + CALL PUT + UNMASK + CLR DDTMOD ;SYSTEM UP, TURN OFF DDT MODE + MOV #-1,DDTCHR ;.. + +CHKTRN: TST INPCMD + BNE 1$ ;INPUT IN PROGRESS, DON'T START AGAIN + JSR B,HWEXAM ;CHECK FOR DATA TRANSFER COMMAND + DTEINP + BNE 1$ ;DTEINP -1, NO REQUEST + JMP INPSER + +1$: TST OUTCMD + BNE CHKLSP ;OUTPUT IN PROGRESS, DON'T START AGAIN + JSR B,HWEXAM ;CHECK FOR DATA TRANSFER COMMAND + DTEOUT + BNE CHKLSP ;DTEOUT -1, NO REQUEST + JMP OUTSER + +CHKLSP: JSR B,HWEXAM ;CHECK FOR SET LINE SPEED COMMAND + DTELSP + BNE CHKTYI + MOV RH,I ;GET LINE# + ASL I + CMP I,#NFTTY ;VALIDATE IT + BLO 1$ ;IGNORE IF BAD + CMP I,#LASTTY + BHI 1$ + JSR B,HWEXAM ;GET LPR,,BUFFERSIZE + DTELPR + MOV LH,A + MOV RH,B + CALL SPARAM ;DO IT +1$: D10MON ;DONE, SETOM + DTELSP + +CHKTYI: TST TYIRNG+RINGCT + BEQ CHKODN ;NO TTY INPUT WAITING + JSR B,HWEXAM + DTETYI + BEQ CHKODN ;PREVIOUS CHAR NOT PICKED UP + MOV #TYIRNG,B + CALL GET + MOV A,RH ;CHAR + CALL GET + MOV A,LH ;LINE# + CLR SNB + JSR B,HWDEP ;GIVE 10 LINE#,,CHAR + DTETYI + MOV #%STINX,STATUS ;INTERRUPT THE 10 + +CHKODN: TST TYORNG+RINGCT + BEQ CHKHNG ;NO OUTPUT DONES WAITING + JSR B,HWEXAM + DTEODN + BEQ CHKHNG ;PREVIOUS STATUS NOT PICKED UP + MOV #TYORNG,B + CALL GET ;GET LINE# WITH OUTPUT DONE + MOV A,LH + ASL A + MOV BUFSIZ(A),RH + CLR SNB + JSR B,HWDEP ;GIVE 10 LINE#,,BUFFERSIZE + DTEODN + MOV #%STINX,STATUS ;INTERRUPT THE 10 + +CHKHNG: TST HNGSIG + BEQ MAINX ;NO HANGUPS/DIALINS WAITING + JSR B,HWEXAM + DTEHNG + BEQ MAINX ;PREVIOUS STATUS NOT PICKED UP + MOV #LASTTY,I ;SCAN OVER ALL LINES +1$: MASK 5 + MOV TTYHNG(I),A ;GET HANG-UP STATUS + BNE 2$ ;BRANCH IF FOUND SOMETHING TO REPORT + UNMASK + TST -(I) + CMP I,#NFTTY + BHIS 1$ + BPT ;HNGSIG OUT OF PHASE WITH TTYHNG + +2$: CLR TTYHNG(I) ;GOT STATUS, CLEAR IT + DEC HNGSIG ;DECREASE COUNT OF FROBS WAITING TO BE SIGNALLED + UNMASK ;NOW IT'S OK TO INTERRUPT AND SET TTYHNG + MOV A,RH ;GIVE LINE NUMBER AND OTHER DATA TO 10 + CLR LH + CLR SNB + JSR B,HWDEP + DTEHNG + MOV #%STINX,STATUS ;INTERRUPT THE 10 + +MAINX: JMP MAIN +.ENDC ;DTE20P + +.IFZ DL10P+DTE20P + .SBTTL MAIN LOOP FOR AI + +MAIN: +.IIF NZ TEN11P, CALL T11WAK ;CHECK UP ON TEN-11 INTERFACE +.IIF Z TEN11P, CALL CHSRUN ;DAMNED THING GETS WEDGED +.IFNZ ETHERP + TST CHXRTF+CHXETH ;NEED TO BROADCAST ROUTING INFO TO ETHERNET? + BEQ 666$ + CALL ETHRUT +666$: +.ENDC ;ETHERP + TST WAKE ;CLOCK TICK? + BEQ MAIN ;NO, JUST WAIT + CLR WAKE ;CLOCK HAS TICKED, CLEAR FLAG + BR MAIN ;NOT MUCH TO DO, NO TTYS +.ENDC ;DL10P+DTE20P + + .SBTTL OUTPUT HANDLERS + +TYOSER: ASL I ;CONVERT -10 LINE# TO -11 TTY INDEX + CMP I,#NFTTY + BLO 11$ + CMP I,#LASTTY + BLOS 12$ +11$: BPT ;10 GAVE BAD LINE# +12$: MOV HDWR(I),H ;GET HARDWARE INDEX + MOV BUFPNT(I),D ;AND ADDRESS OF TYPEOUT BUFFER + CMP BUFSIZ(I),C ;MAKE SURE THERE IS ROOM IN BUFFER + BHIS 2$ + BPT ;THERE ISN'T +2$: MOV C,B ;MUSTN'T CLOBBER BYTE COUNT IN C +.IFNZ DL10P + MOV #TYOPNT,A ;GET CRUFT FROM DL10 +3$: MOVB @A,(D)+ ;COPY BUFFER + SOB B,3$ +.ENDC ;DL10P +.IFNZ DTE20P + MOV D,TO11AD ;SET UP BYTE TRANSFER + NEG B + BIC #050000,B ;SET LAST, BYTE; CLEAR ASCIZ, 2.4 + MOV B,TO11BC ;START XFER + RET + +TYOFIN: MOV HDWR(I),H ;COMES BACK WHEN XFER COMPLETE +.ENDC ;DTE20P + +;BUFFER HAS BEEN LOADED, START DEVICE + + MASK 5 ;DON'T LET DEVICE INTERRUPT + MOV BUFPNT(I),D + CALL @STROUT(H) ;CALL DEVICE-DEPENDENT ROUTINE + MOV #40000,TYPING(I) ;TELL 10 WHEN OUTPUT FINISHES (LARGE POSITIVE NUMBER) + UNMASK + RET + +;GIVE MESSAGE. A -> .WORD LENGTH,MSG. I HAS LINE NUMBER. + +GIVMSG: PUSH + MOV (A)+,C ;C HAS BYTE COUNT, A HAS ADDRESS + MOV A,D ;PUT ADDRESS IN D + MOV HDWR(I),H + MASK 5 + CALL @STROUT(H) ;START OUTPUT TO LINE + UNMASK + POP + RET + +ASPACK: MNAME ^% + MSG ^\ +‡Connected to MCHN'.\% +DWNMSG: MSG ^\ +‡ITS is down.\ +IBOMSG: MSG ^\IBO\ + +;DEVICE-DEPENDENT OUTPUT START ROUTINES (CALL AT PI LEVEL 5) +;H HDWR IDX, I TTY IDX, D BUFFER POINTER, C NUMBER OF BYTES + +STRDH: BIC DHLBIT(I),@DHBAR(H) ;IF LINE ALREADY TRANSMITTING, STOP IT + ;IT SHOULDN'T OUGHT TO BE... + MOV DHLSEL(I),@DHSCR(H) ;HARDWARILY SELECT THIS LINE + MOV D,@DHCA(H) ;SET XMT ADDRESS + NEG C ;HARDWARE LIKES NEGATIVE BYTE COUNTS + MOV C,@DHBC(H) ;SET XMT COUNT + BIS DHLBIT(I),@DHBAR(H) ;START TRANSMISSION HARDWARILY + BIS DHLBIT(I),DHOAC(H) ;SOFTWARILY ALSO + RET + +STRDL: MOV D,DLCA(H) + MOV C,DLBC(H) + CLR @DLPS(H) + MOV #300,@DLPS(H) ;CAUSE INTERRUPT + SETOM DLOAC(H) +CPOPJ: RET + +.IFNZ NMPTYS +STRMPK: TST MPXENB + BEQ CPOPJ + MOV D,MPXPNT-NFMPTY(I) ;QUEUE OUTPUT + MOV C,MPXNBT-NFMPTY(I) +STRMPX: PUSH I + TST MPXOAC ;START THE MPXR + BNE 10$ ;ALREADY BUSY + CLR I + MOV #NMPTYS,D +2$: MOV MPXNBT(I),C ;FIND MPX KLUDGE LINE WANTS TO OUTPUT + BNE 15$ + TST (I)+ + SOB D,2$ +10$: POP I + RET + +15$: MOV I,MPXOLN ;SAVE LINE# OUTPUT ON + ASR I ;SET UP HEADER + ADD #200,I + MOVB I,MPXHED + MOVB C,MPXHED+1 + MOV #-1,MPXOAC ;SEND HEADER + MOV #MPXIDX,I + MOV HDWR(I),H + MOV #MPXHED,D + MOV #2,C + CALL @STROUT(H) + BR 10$ +.ENDC ;NMPTYS + +.IFNZ GOULDP +.SBTTL GOULD LPT OUTPUT (M.P. LEVEL) +.IIF Z DL10P, .ERROR GOULD LPT ONLY CODED FOR DL10 +.ERR BY THE WAY, THESE ROUTINES DON'T WORK WORTH GUBBISH + +GLPTYO: MOV GLPOIP,H ;GET NEXT BUFFER + CMP GB.STA(H),#%GBMP + BEQ 2$ ;BRANCH IF M.P. ACTIVE + BLT 1$ ;BRANCH IF IDLE BUFFER AVAIL + RET ;NO FREE BUFFERS + +1$: CALL GLPBGB ;GOBBLE A BUFFER +2$: MOV GB.PNT(H),D + MOV GLPCTR,C ;SET UP BYTE COUNTER + MOV GLPGRF,GLPGF1 ;COPY ARG FROM 0 FOR SPEED + TST GLIMBF ;CHAR SAVED FROM LAST TIME? + BEQ GLPNCL + CLR GLIMBF ;YES, PRINT IT + MOVB GLIMBO,A + CALL GLPPUT + MOVB GLIMBO+1,A ;SECOND CHAR? + BEQ GLPNCL + CLR GLIMBO + CALL GLPPUT + +;CHARACTER PROCESSING LOOP +;C HAS # CHARS YET TO GO, D HAS WHERE TO PUT THEM, H -> BUFFER +;A WILL HAVE CHAR + +GLPNCL: MOV GLPPTR,A ;GET NEXT CHAR + TST GLPGF1 + BNE GLPNRM ;GRAPHIC MODE, NO CHARACTER PROCESSING + CMP A,#177 ;ESCAPE? + BEQ GLPESC + CMP A,#40 ;CONTROL? + BGE GLPNRM ;NO, NORMAL PRINTING + CMP A,#14 ;CHECK FOR SPECIAL CONTROLS + BNE 10$ +8$: CLR GLPROW ;START NEW PAGE + TST GLPCOL ;IN MIDDLE OF LINE? + BEQ 9$ ;NO, OK + CALL GLPBWW ;OTHERWISE, HAIR + CLR GLPFIL ;HACK HACK MAKE FF NEXT LINE + BR GLPNB1 + +9$: SETOM GB.FF(H) + BR GLPNXC + +10$: CMP A,#12 + BNE 12$ + INC GLPROW + CMP GLPROW,#GLPRMX + BHIS 8$ ;SKIP OVER PERFORATION + TST GLPCOL + BNE GLPNBF ;IF NOT A BLANK LINE, FINISH BUFFER + INC GB.NL(H) + BR GLPNXC + +12$: CMP A,#11 + BNE 15$ +13$: MOV #40,A ;TAB - SPACE OVER + CALL GLPPUT + BIT #7,GLPCOL + BNE 13$ + BR GLPNXC + +15$: CMP A,#15 + BEQ GLPNXC ;IGNORE CR + CMP A,#33 + BNE 16$ + MOV #'$,A ;PRINT ALTMODE AS DOLLAR + BR GLPNRM + +16$: BIS #100,A ;RANDOM CONTROL AS UPARROW, LETTER + MOVB A,GLIMBO+1 + MOV #'^,A + CALL GLPPUT + MOVB GLIMBO+1,A + CLR GLIMBO +GLPNRM: CALL GLPPUT ;HERE FOR NORMAL CHARACTER +GLPNXC: DEC C ;HERE TO GOBBLE CHARACTER + BGT GLPNCL ;BRANCH IF MORE CHARS TO GO + BR GLPEND ;BUFFER EMPTIED + +GLPNBF: CALL GLPBWW ;HERE TO ADVANCE TO NEXT BUFFER +GLPNB1: CMP GB.STA(H),#%GBIDL ;NEXT BUFFER AVAIL? + BNE GLPEN1 ;NO, STOP + CALL GLPBGB ;YES, GOBBLE IT + BR GLPNXC + +GLPESC: DEC C ;HERE FOR TWO CHAR ESC SEQ + BEQ GLPEND ;-10 FORGOT 2ND CHAR, FLUSH + MOV GLPPTR,A ;GET & DECODE 2ND CHAR + CMP A,#105 ;EOF + BEQ GLPEOF + BR GLPNXC ;OTHER CHARS ARE IGNORED + +GLPEOF: CLR GLPFIL + CLR GLPROW + CALL GLPBWW ;EOF, WRITE LAST BUFFER +GLPEN1: DEC C ;GOBBLE A CHARACTER +GLPEND: MOV C,GLPCTR ;HERE WHEN DONE, RELEASE 10'S BUFFER + CMP GB.STA(H),#%GBMP ;BUFFER ACTIVE AT M.P. LEVEL? + BNE 1$ ;IF NOT, DON'T CLOBBER GB.PNT + MOV D,GB.PNT(H) ;IF SO, REMEMBER AMT OF STUFF IN CURRENT BUFFER +1$: RET ;RETURN TO MAIN LOOP + +;OUTPUT PRINTING CHAR IN A + +GLPPUT: CMP D,GLPLIM ;LINE OVERFLOW? + BLO 5$ ;NO + CALL GLPBWW ;YES, DONE WITH THIS BUFFER + INC GLPROW ;OUGHT TO CHECK FOR PERFORATION, BUT... + CMP GB.STA(H),#%GBIDL ;MORE BUFFERS? + BNE 6$ ;NO + CALL GLPBGB +5$: MOVB A,(D)+ ;DROP CHAR IN BUFFER + INC GLPCOL ;AND ADVANCE COLUMN + RET + +6$: MOVB A,GLIMBO ;NO BUFFERS, SAVE CHAR BEING PRINTED + SETOM GLIMBF ;SET FLAG SO WILL BE PRINTED NEXT TIME + TST (SP)+ ;STOP THE WORLD + BR GLPEN1 + +;GOBBLE IDLE BUFFER H -> FOR M.P. RETURNS GB.PNT(H) IN D. + +GLPBGB: MOV #%GBMP,GB.STA(H) ;ACTIVATE AT M.P. LEVEL + CLR GB.FF(H) ;INIT THE BUFFER + CLR GB.NL(H) + CLR GLPCOL ;START LINE IN COLUMN 0 + MOV H,D ;INIT INSERT POINTER + ADD #GB.DAT,D + MOV D,GB.PNT(H) + MOV H,GLPLIM ;SET UP MAX. VALUE OF GB.PNT + ADD #GB.LEN,GLPLIM + RET + +;GIVE BUFFER H -> TO P.I. LEVEL + +GLPBWW: BIT #1,D ;MUST BE EVEN NUMBER OF BYTES + BEQ 1$ + CLRB (D)+ + +1$: PUSH A ;INTERFACE GETS BYTES IN WRONG ORDER + MOV P,A ;COMPUTE NUMBER OF WORDS IN LINE + SUB H,A + SUB #GB.DAT,A + ASR A + BNE 4$ + CLR (D)+ ;CAN'T HAVE ZERO-LENGTH LINE + INC A +4$: MOV A,GB.PNT(H) ;SAVE WORD COUNT FOR P.I. LEVEL +2$: SWAB -(D) + SOB A,2$ + POP A + TST GLPFIL ;IF STARTING NEW FILE, + BNE 5$ + SETOM GLPFIL + SETOM GB.FF(H) ; BE SURE TO GET NEW PAGE +5$: MOV #%GBWRT,GB.STA(H) ;QUEUE TO P.I. LEVEL + MOV GB.NXT(H),H ;ADVANCE TO NEXT BUFFER + MOV H,GLPOIP + MASK 6 ;STOP P.I. LEVEL (HAVE TO LOCK OUT GLPBRK & CLKBRK) + TST GLPOAC ;PRINTER ON? + BNE 3$ ;YUP + MOV #%GCOFF,@#GLPCSR ;NO, CLEAR OLD STUFF IN INTERFACE + TST GLPGF1 ;AND PUT IN LOW-SPEED GRAPHIC MODE IF NECC + BEQ 6$ + MOV #%GCGRF,@#GLPCSR + MOV #%GCLSL,@#GLPCSR ;LOW SPEED (COME ON, THIS IS ONLY A KL10!) +6$: MOV #%GCON,@#GLPCSR ;TURN IT ON + MOV #%GCION,@#GLPCSR ;TURN ON INTERRUPTS + SETOM GLPOAC +; PUSH @#PS ;FAKE AN INTERRUPT +; CALL GLPBRK ;IS THIS NECESSARY? +3$: UNMASK + RET + +;GOULD LPT VARIABLES + +GLPCOL: 0 ;CURRENT COLUMN NUMBER +GLPROW: 0 ;CURRENT ROW NUMBER + GLPRMX==67. ;NUMBER OF LINES PER PAGE +GLPLIM: 0 ;ADDRESS OF END OF CURRENT BUFFER +GLPOAC: 0 ;NON-ZERO => GOULD LPT P.I. ACTIVE +GLPGF1: 0 ;NON-ZERO => GOULD LPT IN GRAPHIC MODE +GLIMBO: 0 ;SAVE CHAR HERE WHEN RUN OUT OF BUFFERS +GLIMBF: 0 ;NON-ZERO => CHAR IN GLIMBO +GLPFIL: 0 ;NON-ZERO => IN MIDDLE OF A FILE +GLPTIM: 10. ;COUNT DOWN WHEN LOSING +GLPERR: 0 ;NON-ZERO => ERROR STATUS FROM P.I. +.ENDC ;GOULDP + + .SBTTL T-300 DISK + +.IFNZ T300P + +;DISK UNIBUS REGISTERS + +DSKCRA=176700 ;COMPLETION REGISTER A + %DAPON==100000 ;SPONTANEOUS COMPLETION DUE TO POWER-ON. DISK NUMBER + ; IN LOW BITS OF COMMAND-COMPLETION REGISTER B + %DACQE==10000 ;CONSISTENCY ERROR IN COMMAND QUEUE + %DANXM==4000 ;NXM ERROR IN COMMAND QUEUE + %DAPAR==2000 ;PARITY ERROR IN COMMAND QUEUE + ;LOW 2 BITS OF COMMAND COMPLETION REGISTER A AND + ;COMMAND COMPLETION REGISTER B CONTAIN THE ADDRESS + ;OF THE PARITY OR NXM ERROR +DSKCRB=176702 ;COMPLETION REGISTER B +DSKCSR=176704 ;COMMAND/STATUS REGISTER + %DCCPL==100000 ;COMMAND IS COMPLETE, RESET BY %DCACK. READ-ONLY + %DCDER==40000 ;"DMA ERROR", RESET ONLY BY SYSTEM RESET. + ;1=NORMAL, 0=ERROR + ;BITS 30004 ALWAYS ON + %DCMNT==4000 ;HOST-ADAPTOR MAINTENANCE MODE + %DCRST==2000 ;RESET. WRITE-ONLY. + %DCACK==1000 ;ACKNOWLEDGE COMMAND COMPLETION. WRITE-ONLY + %DCCMD==400 ;TAKE COMMAND FROM CTRA/CTRB. WRITE-ONLY + %DCRDY==200 ;READY TO TAKE A COMMAND. READ-ONLY + %DCTIE==100 ;COMMAND TRANSMISSION (%DCRDY) INTERRUPT ENABLE + %DCCIE==40 ;COMMAND COMPLETION (%DCCPL) INTERRUPT ENABLE + %DCPCY==20 ;POWER JUST CYCLED ON OR OFF. READ-ONLY + %DCPON==10 ;POWER ON. READ-ONLY + %DCDMA==2 ;DMA IN PROGRESS. READ-ONLY + %DCBOT==1 ;BOOT (READ DRIVE 0 SECTOR 0 INTO MEMORY 0). WRITE-ONLY +DSKCTA=176706 ;COMMAND TRANSMISSION A (ADDRESS OF RQB HIGH BITS) +DSKCTB=176710 ;COMMAND TRANSMISSION B (ADDRESS OF RQB LOW BITS) +;176714 DUPLICATES DSKCSR FOR UNKNOWN REASONS + +;DISK REQUEST BLOCK. WE ONLY HAVE ONE SINCE NO SEEK OVERLAP. + +RQBACT: 0 ;NON-ZERO IF REQUEST ACTIVE AND EXPECTING COMPLETION + +RQBID: 0 ;RETURNED IN CCRB WHEN COMMAND COMPLETES +RQBSTS: 0 ;STATUS STORED BY 2561, COPIED INTO DSCSTS +RQBFLT: 0 ;FAULT CODE IN HIGH BYTE, BITS 1-0 HIGH BITS OF LINK ADDRESS +RQBLNK: 0 ;LINK ADDRESS TO NEXT RQB (MUST BE ZERO) +RQBCMD: 0 ;COMMAND CODE, COPIED FROM DSCCMD +RQBDRV: 0 ;UNIT NUMBER, COPIED FROM DSCDRV +RQBCYL: 0 ;CYLINDER NUMBER, COPIED FROM DSCCYL +RQBHED: 0 ;HEAD NUMBER, COPIED FROM DSCHED +RQBSEC: 0 ;SECTOR NUMBER, COPIED FROM DSCSEC +RQBWC: 0 ;POSITIVE WORD COUNT (ALWAYS 12.*256.) +RQBMA: 0 ;MEMORY ADDRESS (ALWAYS DSKBUF) +RQBMAH: 0 ;MEMORY ADDRESS HIGH (ALWAYS 0) + ; BITS 1-0 BITS 17-16 OF ADDRESS. BIT 6 MA INCR INH +RQBID1: 0 ;RETURNS RECORD ID 1 +RQBID2: 0 ;RETURNS RECORD ID 2 +RQBMNT: .BLKW 27. ;DIAGNOSTIC DATA MAY BE RETURNED + +;DISK BUFFER. HOLDS ENOUGH 12-BIT BYTES IN 16-BIT WORDS TO MAKE 1024. 36-BIT WORDS +DSKBUF: .BLKW 3.*1024. + +;ROUTINE TO START DISK IF IT IS READY AND THERE IS A REQUEST. +DSKSTR: TST DSCREQ ;ANY REQUEST FROM 10? + BEQ 99$ ;NO, EXIT + CMP DSCCHK,#2561 + BNE 99$ ;CHECK WORD WRONG, DON'T TOUCH DISK + TST RQBACT ;PREVIOUS OPERATION FINISHED? + BEQ 10$ + BPT ;NO, MUST BE BUG IN 10? +10$: TSTB DSKCSR ;TEST IF READY FOR COMMAND TRANSMISSION + BPL 99$ ;NO, WAIT + CLR DSCDON ;YES, CLEAR 10/11 COMMUNICATION FLAGS + CLR DSCREQ + CLR RQBLNK ;SET UP RQB FROM 10'S PARAMETERS + MOV DSCCMD,RQBCMD + MOV DSCDRV,RQBDRV + MOV DSCCYL,RQBCYL + MOV DSCHED,RQBHED + MOV DSCSEC,RQBSEC + MOV #12.*256.,RQBWC + MOV #DSKBUF,RQBMA + CLR RQBMAH + CMP RQBCMD,#%DMWRT ;IF A WRITE COMMAND, MUST COPY DATA BUFFER + BNE 30$ + MOV #DSKBUF,D + .REPT 4 ;TAKES 4 BYTE POINTERS TO DO IT + MOV #DSCPNT+<2*.RPCNT>,H + .REPT 3 ;EACH BYTE POINTER HAS 768 12-BIT BYTES + MOV #256.,C + CALL MOVHD + .ENDR + .ENDR +30$: CLR DSKCTA ;GIVE ADDRESS OF RQB TO 2561 + MOV #RQBID,DSKCTB + SETOM RQBACT ;TELL INTERRUPT LEVEL INTERRUPT EXPECTED + MOV #%DCCMD+%DCCIE,DSKCSR ;GIVE COMMAND, ENABLE COMPLETION INTERRUPT +99$: RET ;DONE + +;CALL HERE WHEN DISK INTERRUPTS +DSKBRK: PUSH ;SAVE ALL REGISTERS + MOV DSKCSR,A + BIT #%DCPCY,A ;POWER CYCLED? + BNE 5$ ;YES, RESET CONTROLLER AND IGNORE INTERRUPT + BIT #%DCMNT,A ;NO, MAINTAINENCE MODE + BEQ 4$ ;OK + BPT ;BLEAH, MUST BE BROKEN + BR 5$ + +4$: BIT #%DCDER,A ;WHAT ABOUT UNIBUS ERROR + BNE 10$ + BPT +5$: MOV #%DCRST,DSKCSR ;RESET THE CONTROLLER AND TURN OFF INTERRUPTS + TST RQBACT ;DID THIS LOSE IN THE MIDDLE OF A DISK OPERATION? + BEQ 99$ ;NO, DISMISS + MOV #%DFRST,A ;YES, GIVE ERROR STATUS + CLR B + BR 20$ + +10$: BIT #%DCCPL,A ;TEST FOR COMMAND COMPLETION + BPL 99$ ;NO, IGNORE INTERRUPT + MOV DSKCRA,A ;GET COMPLETION STATUS + MOV DSKCRB,B + MOV #%DCACK+%DCCIE,DSKCSR ;ACKNOWLEDGE COMPLETION, ENABLE MORE INTERRUPTS + TST RQBACT ;EXPECTED? + BEQ 99$ ;NO, IGNORE + BIT #%DAPON,A ;POWER-UP INDICATION? + BNE 99$ ;FOR NOW, IGNORE IT + BIT #%DACQE+%DANXM+%DAPAR,A + BEQ 30$ ;OK, NO COMMAND-QUEUE ERROR + MOV #%DCRST,DSKCSR ;RESET CONTROLLER (I DON'T KNOW IF IT NEEDS IT) +20$: MOV A,DSCFLT ;COMMAND-QUEUE ERROR, GIVE STATUS TO PDP10 + MOV B,DSCSTS + BR 80$ + +30$: CLR DSCFLT ;CLEAR HIGH BYTE + MOVB RQBFLT+1,DSCFLT ;PICK UP FAULT CODE, PUT IN LOW BYTE + BEQ 35$ ;IF FAULT CODE IS NON-ZERO, THE THING MAY BE FROZEN, + MOV #%DCRST,DSKCSR ;SO RESET IT. OTHERWISE ERROR SEEMS TO HAPPEN OVER AND OVER +35$: MOV RQBSTS,DSCSTS ;GIVE STATUS TO PDP10 + MOV RQBCYL,DSCCYL ;STORE BACK DISK ADDRESS, MAY BE USEFUL TO PDP10 + MOV RQBHED,DSCHED + MOV RQBSEC,DSCSEC + BIT #%DMRED,RQBCMD ;IF COMMAND WAS READ, COPY BUFFER BACK + BEQ 80$ + MOV #DSKBUF,D + .REPT 4 ;TAKES 4 BYTE POINTERS TO DO IT + MOV #DSCPNT+<2*.RPCNT>,H + .REPT 3 ;EACH BYTE POINTER HAS 768 12-BIT BYTES + MOV #256.,C + CALL MOVDH + .ENDR + .ENDR +80$: SETOM DSCDON ;SIGNAL PDP10 OPERATION IS COMPLETE + BIS #DLX10I,DLXCSR ;AND INTERRUPT THE PDP10 + CLR RQBACT ;NO LONGER EXPECTING COMPLETION ON THE RQB +99$: POP ;RESTORE REGISTERS AND EXIT INTERRUPT + RTI +.ENDC ;T300P + + .SBTTL SET LINE PARAMETERS + +;LINE INDEX IN I +;DH11 PARAM REG IN A +;BUFFER SIZE IN B + +SPARAM: CMP I,#NFTTY + BGE 1$ + BPT +1$: CMP I,#LASTTY + BLE 2$ + BPT +2$: CMP B,#1. ;MINIMUM BUFFER SIZE ONE CHARACTER + BGE 3$ + MOV #1.,B +3$: CMP B,#MAXBSZ ;MAXIMUM BUFFER SIZE CHARACTERS + BLE 4$ + MOV #MAXBSZ,B +4$: MOV B,BUFSIZ(I) ;SET AMOUNT OF BUFFER TO BE USED FROM NOW ON + MOV HDWR(I),H ;(BUT NO LONGER DO WE ATTEMPT DYNAMIC BUFFER ALLOCATION) + CMP H,#NLDHHX + BHI 5$ + MASK 5 ;LINE IS A DH11, HAVE TO SET LINE PARAM REG + MOV DHLSEL(I),@DHSCR(H) ;SELECT THE LINE + MOV A,@DHLPR(H) ;GIVE LINE-PARAMETER REG TO DH11 + UNMASK +5$: MOV A,LPRVAL(I) ;STORE LPR IN CASE SOMEONE IS CURIOUS + RET + + .SBTTL DH11 INPUT INTERRUPT + +.REPT NDHS +CONC DH,\.RPCNT+1, + 2*.RPCNT +.ENDR + +DHIBK: MOV (H),H ;PICK UP HARDWARE INDEX + PUSH +1$: MOV @DHNRC(H),A ;RECIEVE A CHARACTER + BPL DHIEX ;EXIT INTERRUPT IF NO MORE CHARS + MOV A,I ;EXTRACT LINE NUMBER + SWAB I + BIC #177760,I + ASL I + ADD DHTYNO(H),I +.IFNZ NDHUN + CMP I,#NLDHTY ;IGNORE NON-EXISTENT LINES + BHI 1$ +.ENDC + CALL @TTYIPC(I) ;CALL LINE HACKER + BR 1$ ;AND CHECK FOR MORE + +DHIEX: POP + RTI + +;NORMAL DH11 INPUT + +DHNRMI: BIT #%DXPAR,A + BEQ 1$ ;IGNORE IF PARITY ERROR +10$: RET +1$: BIT #%DXBRK,A ;IF BREAK, + BEQ RCV + TST AUTOSP(I) ;AND LINE WANTS AUTOSPEED-ON-BREAK FEATURE + BPL 10$ +ASPMD: MOV #DHASP,TTYIPC(I) ;PUT IT IN AUTOSPEED MODE + MOV DHLSEL(I),@DHSCR(H) ;AND SET HARDWARE TO 1200 BAUD + MOV #023103,@DHLPR(H) + RET + +;CHAR IN A RECEIVED FROM LINE IN I +RCV: BIC #177400,A ;8-BIT CHAR RECEIVE +RCV.FW: TST NO.ITS ;ENTER HERE FOR FULL WORD RECEIVE + BEQ 10$ +21$: MOV #DWNMSG,A ;ITS DOWN, GIVE MESSAGE +12$: CALL GIVMSG + RET + +10$: MOV #TYIRNG,B + CMP RINGCT(B),#TYIRSZ-2 + BGT 11$ + CALL PUT ;FIRST PUT THE CHARACTER + MOV I,A + ASR A + CALL PUT ;THEN THE TENNISH LINE NUMBER + RET + +11$: MOV #IBOMSG,A ;INPUT BUFFER OVERFLOW + BR 12$ + +.IFNZ NMPTYS ;HANDLE INPUT FROM THE MULTIPLEXOR LINE +MPXINP: TST MPXENB + BEQ RCV + MOV MPXSEL,I ;CURRENT INPUT LINE + TSTB A ;SPECIAL CHAR? + BMI 1$ + JMP @TTYIPC(I) ;NO, RECEIVE ON APPROP LINE + +1$: MOV A,I ;SPECIAL CHAR, EXTRACT LINE# + BIC #177700,I +;FOLLOWING FEATURE COMMENTED OUT SINCE IT CAUSES 11 TO LOOP +; WHEN NEXT INPUT ARRIVES -- NOT OBVIOUS HOW TO FIX. +; CMP I,#77 ;SELECT NON-MULTIPLEX INPUT? +; BEQ 3$ ;YES, DO SO + ASL I + ADD #NFMPTY,I + CMP I,#LASTTY + BHI 2$ ;OUT OF RANGE, IGNORE + MOV I,MPXSEL ;INPUT SELECT, SAVE LINE# +2$: RET + +3$: MOV #MPXIDX,MPXSEL ;SELECT PASS THROUGH + RET +.ENDC ;NMPTYS + +;AUTOSPEED MODE COMES HERE WHEN CHAR RECIEVED + +DHASP: BIC #177400,A ;CLEAR FRAMING ERR, ETC. + BEQ ASP10 ;11 0'S = 110 BAUD + CMP A,#200 ;7 0'S, 1 = 150 BAUD + BEQ ASP15 + CMP A,#170 ;3 0'S, 4 1'S, 0 = 300 BAUD + BEQ ASP30 + CMP A,#370 ;300/600 IS NOW RUBOUT, NOT I + BEQ ASP36 + CMP A,#146 ;1 0, 2 1'S, 2 0'S, ... = 600 + BEQ ASP60 + CMP A,#340 ;5 0'S, 3 1'S ? MYSTERY TO ME + BEQ ASP60 + CMP A,#015 ;CR = 1200 + BEQ ASP120 + CMP A,#215 ;CR WITH EITHER PARITY + BEQ ASP120 + MOV A,#. ;SAVE GARBAGE FOR DEBUGGING + RET ;SOMETHING ELSE, IGNORE + +ASP10: MOV #006307,A ;110 IN, 110 OUT, NO PARITY, 8 BITS, EXTRA STPBT + MOV #5,B + MOV #12200,-(SP) + BR ASPX + +ASP15: MOV #012503,A ;150 IN, 150 OUT, NO PARITY, 8 BITS + MOV #7,B + MOV #13300,-(SP) + BR ASPX + +ASP30: MOV #016703,A ;300 IN, 300 OUT, NO PARITY, 8 BITS + MOV #15.,B + MOV #14400,-(SP) + BR ASPX + +ASP36: MOV #020703,A ;300 IN, 600 OUT, NO PARITY, 8 BITS + MOV #30.,B + MOV #14100,-(SP) + BR ASPX + +ASP60: MOV #021003,A ;600 BAUD, NO PARITY, 8 BITS + MOV #30.,B + MOV #11100,-(SP) + BR ASPX + +ASP120: MOV #023103,A ;1200 IN, 1200 OUT, NO PAR, 8 BITS + MOV #60.,B + MOV #15500,-(SP) + BR ASPX + +ASPX: CALL SPARAM ;SET BUFFER SIZE AND HARDWARE SPEED + MOV I,A ;SET UP SET-SPEED COMMAND TO -10 + ASR A + BIS (SP)+,A + TST TTYHNG(I) ;IF THIS IS NEW STATUS FOR 10, + BNE 11$ + INC HNGSIG ;INDICATE STATUS WAITING +11$: MOV A,TTYHNG(I) ;SAVE THIS LINE'S LATEST STATUS + MOV #ASPACK,A ;ACKNOWLEDGE TO USER THAT HE WON + CALL GIVMSG + DEC TYPING(I) ;IF NO WAKEUP FOR 10, HIT CALL WHEN TYPING DONE + MOV NRMIPC(I),TTYIPC(I) ;AND TAKE LINE OUT OF AUTOSPEED MODE + RET + + .SBTTL DH11 OUTPUT INTERRUPTS + +.REPT NDHS +CONC DH,\.RPCNT+1, + 2*.RPCNT +.ENDR + +DHOBK: MOV (H),H ;GET HARDWARE UNIT NUMBER + BIT #DHSNXM,@DHSCR(H) ;IS THIS INTERRUPT DUE TO NXM? + BEQ 1$ + BPT ;YES +1$: BIC #DHTDON,@DHSCR(H) ;HARDWARE KLUDGE TO MAKE INTERRUPTS WIN + PUSH + MOV DHOAC(H),C ;SEE WHICH BAR BITS HAVE TURNED OFF + BIC @DHBAR(H),C + BIC C,DHOAC(H) + MOV DHTYNO(H),I + ADD #15.*2,I +2$: BIT DHLBIT(I),C + BEQ 4$ +.IFNZ NMPTYS + CMP I,#MPXIDX + BNE 3$ + CALL MPXDON +.ENDC ;NMPTYS +3$: +.IFNZ NDHUN + CMP I,#NLDHTY ;IGNORE NON-EXISTENT LINES + BHI 4$ +.ENDC + CALL XMTDON +4$: SUB #2,I + CMP I,DHTYNO(H) + BGE 2$ +DHOEX: POP + RTI + +XMTDON: TST TYPING(I) ;HERE WHEN OUTPUT FINISHES + BGT 1$ ;BRANCH IF -10 WANTS TO KNOW ABOUT IT + BEQ 3$ ;BRANCH IF NOTHING TO DO + MOV #32,A ;SEND A CALL + CALL RCV + BR 3$ + +1$: MOV I,A + ASR A ;PUT TENNISH LINE NUMBER INTO RING + MOV #TYORNG,B ;MAIN PROG LEVEL WILL LATER TELL -10 + CALL PUT +3$: CLR TYPING(I) + RET + +.IFNZ NMPTYS ;OUTPUT DONE ON MULTIPLEXED LINE +MPXDON: PUSH + TST MPXOAC + BGE 1$ + NEG MPXOAC ;SENT HEADER, NOW SEND DATA + MOV MPXOLN,A + MOV MPXPNT(A),D + MOV MPXNBT(A),C + CLR MPXNBT(A) + CALL @STROUT(H) + BR 9$ + +1$: MOV MPXOLN,I ;OUTPUT IS DONE ON THAT LINE NOW + ADD #NFMPTY,I + CALL XMTDON + CLR MPXOAC ;MPX IDLE + CALL STRMPX ;LOOK FOR NEW STUFF TO DO +9$: POP + RET +.ENDC ;NMPTYS + + .SBTTL DL11 INTERRUPTS + +.REPT NDLS +CONC DL,\.RPCNT+1, + NFDLHX+<2*.RPCNT> +CONC DL,\.RPCNT+1, + NFDLHX+<2*.RPCNT> +.ENDR + +DLIBK: MOV (H),H ;GET HARDWARE INDEX OF INTERRUPTING UNIT + PUSH + MOV @DLKB(H),A ;GET RECEIVED CHARACTER + MOV DLTYNO(H),I ;GET LINE NUMBER RECEIVED ON +.IFNZ DTE20P + BNE 2$ ;ONLY T00 CAN RETURN TO KLDCP + BIT #20000,A ;IF BREAK KEY IS HIT + BEQ 1$ + SETOM KLDCPF ;USER WANTS TO RETURN TO KLDCP + BR DLBKEX ;FOR ONE COMMAND LINE + +1$: TST DDTMOD ;IF IN DDT MODE, + BEQ 2$ + BIC #-200,A ; HANDLE INPUT DIFFERENTLY + MOV A,DDTCHR + BR DLBKEX + +2$: +.ENDC ;DTE20P + CALL @TTYIPC(I) +DLBKEX: POP + RTI + +DLOBK: MOV (H),H ;GET HARDWARE INDEX OF INTERRUPTING UNIT + TST DLOAC(H) + BEQ DLBKX1 ;NOT SUPPOSED TO BE TYPING OUT, IGNORE INT + DEC DLBC(H) ;GOT ANY MORE CHARACTERS? + BLT DLBKX2 ;NO, GO GIVE OUTPUT DONE + MOV DLCA(H),-(SP) ;YES, GIVE NEXT CHARACTER + MOVB @(SP)+,@DLPB(H) + INC DLCA(H) +DLBKX1: POP H + RTI + +DLBKX2: PUSH ;OUTPUT DONE + MOV DLTYNO(H),I ;GET TTY INDEX OF INTERRUPTING LINE + CLR DLOAC(H) ;OUTPUT NO LONGER ACTIVE ON THIS LINE + CALL XMTDON + BR DLBKEX + + .SBTTL CLOCK INTERRUPT + +;NOTE - IT IS IMPORTANT THAT THIS BE AT A HIGHER INTERRUPT LEVEL THAN THE CHAOS NET +CLKBRK: SETOM WAKE ;WAKE UP MAIN LOOP +.IFNZ GOULDP + PUSH @#PS ;CHECK GOULD LPT + CALL GLPBRK ;(LOSES INTERRUPTS) + DEC GLPTIM ;TIME TO CHECK GOULD LPT? + BGT 13$ ;NOT YET + MOV #10.*60.,GLPTIM + BIT #%GSNRD,@#GLPCSR ;YES, LOSING? + BNE 14$ ;PROBABLY + CLR GLPERR ;PROBABLY NOT + BR 13$ ;(CAN'T TELL FOR SURE IF %GCON NOT DONE) + +14$: MOV @#GLPCSR,GLPERR ;LPT LOSING, TELL 10 + CALL GLPRST ;AND MAKE SURE BUFFERS DON'T CHOKE UP +.ENDC ;GOULDP +13$: PUSH +.IFNZ NDMS ;MODEM SCANNER GETS SHUT OFF SOMEHOW + CLR A ;loop over the DM11s, turning them on + MOV #NDMS,B +259$: BIT #DMSCN,@DMCSR(A) + BEQ 14$ + BIT #DMIEN,@DMCSR(A) + BNE 15$ +14$: MOV #DMSCN+DMIEN,@DMCSR(A) ;ENABLE SCANNER INTERRUPTS +15$: TST (A)+ ;next DM11 + SOB B,259$ ;until all DM11s done + +.ENDC ;NDMS +.IFNZ CHAOSP ;WAKE-UP OUTPUT LINKS IN RE-TRANSMIT DELAY + MOV #CHXCHS,I +50$: MOV CHOHWR(I),A ;ADDRESS OF HARDWARE CSR + TST CHOSTS(I) ;IF ZERO, IS IDLE, DON'T WANT INTERRUPT ENABLE + BEQ 51$ ;NOTE THAT THIS RUNS MASKED HIGHER THAN CHAOS INT LVL + BIS #%CATEN,(A) ;RE-ENABLE INTERRUPT IF OFF +51$: +.IFNZ CHSBTB + BIT #%CATDN,(A) ;TRANSMIT-DONE? + BNE 59$ + INC CHSIDL(I) ;NO, KEEP TIME-OUT + CMP CHSIDL(I),#60. ;IF TRANSMIT-DONE STUCK OFF FOR 1 SECOND, + BLO 59$ + MOV #%CARST,(A) ; THEN RESET THE INTERFACE +; MOV #%CAREN+%CATEN,(A) ;INTERRUPT ENABLES WILL TURN THEMSELVES BACK ON IF NECESSARY! + INC CHSRST(I) ;COUNT NUMBER OF TIMES HAD TO DO THIS +59$: +.ENDC ;CHSBTB +.IFG CHAOSP-1 + TST (I)+ + CMP I,#CHXCHS+CHAOSP+CHAOSP + BLO 50$ +.ENDC ;CHAOSP-1 + DEC PULSAR ;TIME TO GENERATE TEST PACKET TO CHAOS NET? + BGT 66$ ;NOT YET + MOV PULSON,PULSAR ;RE-INITIALIZE COUNTER +.REPT CHAOSP ;YES, AWAKEN ALL TRANSMIT INTERRUPT SIDES + BIS #%CATEN,@CHOHWR+CHXCHS+<2*.RPCNT> +.ENDR +.IFNZ TEN11P + TST CHOSTS+CHXT11 ;AWAITING BUFFER FROM 10? + BNE 65$ ;YES, COUNT TIMEOUT + CLR T11TIM ;NO, RESET TIMEOUT +65$: INC T11TIM +.ENDC ;TEN11P +66$: DEC 4SEC ;TIME FOR 4-SECOND CLOCK? + BGT 90$ + MOV #4*60.,4SEC ;YES + MOV #*2,I ;INCREMENT ROUTING COSTS +71$: TST SBNTYP(I) ;THIS GUY'S COSTS SUPPOSED TO INCREMENT? + BNE 72$ ;NOPE + CMP SBNCST(I),#1000 ;DON'T INCREMENT TOO HIGH AND OVERFLOW + BHIS 72$ + INC SBNCST(I) ;YEP +72$: SUB #2,I + BPL 71$ + DEC 15SEC ;TIME FOR 15-SECOND CLOCK? (REALLY 16) + BGT 90$ + MOV #4,15SEC ;YES +.REPT CHAOSP ;TELL CABLES TO BROADCAST %CORUT PACKETS + SETOM CHXRTF+CHXCHS+<2*.RPCNT> + BIS #%CATEN,@CHOHWR+CHXCHS+<2*.RPCNT> +.ENDR +.IIF NZ ETHERP, SETOM CHXRTF+CHXETH ;TELL ETHERNET TO BROADCAST ROUTING +90$: ;CAN'T DO IT NOW BECAUSE WRONG INTERRUPT LEVEL +.ENDC ;CHAOSP +.IF DF NDVRBF + INC DVRTIM ;TIME OUT DOVER CONNECTION + CMP DVRTIM,#15.*60. ;IF IDLE FOR 15 SECONDS, FLUSH + BLO 15$ + CLR DVRHST + CLR DVRMSK +15$: INC DVRRTR ;COUNT UP RETRANSMISSION COUNTER +.ENDC ;NDVRBF +.IFNZ NDMS ;GOT ANY TTYS WITH MODEM CONTROL? + MOV #NFTTY,I ;CHECK FOR HANGUPS +16$: TST DIALED(I) ;HANGUP IN PROGRESS ON THIS LINE? + BPL 17$ ;NO + INC DIALED(I) ;YES, TIMED OUT? + BMI 17$ + CLR DIALED(I) ;YUP, LINE IS HUNG UP + MOV I,A ;TELL -10 ABOUT IT + ASR A + TST TTYHNG(I) ;IF THIS IS NEW STATUS FOR 10, + BNE 18$ + INC HNGSIG ;INDICATE STATUS WAITING +18$: MOV A,TTYHNG(I) ;SAVE THIS LINE'S LATEST STATUS +17$: ADD #2,I + CMP I,#LASTTY + BLO 16$ +.ENDC ;NDMS + POP + + ROR SWR ;LOW BIT OF SWITCHES => DDT + BCC CLKEX + BPT +CLKEX: RTI + .IFNZ NDMS + .SBTTL MODEM CONTROL + +;;; hack multiple DM interrupt vectors +.REPT NDMS +CONC DM,\.RPCNT+1, + 2*.RPCNT +.ENDR ;NDMS + + +DMBRK: PUSH + MOV (H),A ;get the device offset in A + MOV @DMCSR(A),I ;GET ASSOCIATED TTY INDEX + BIC #177760,I ;gives us channel (0-17) on this DM11 + ;; now add to get offset into table for any DM + MOV A,B ;device offset in B, is 2*device number + ASL B + ASL B + ASL B ;multiply by 8 for offset in B + ADD B,I ;add to I for offset for this channel + ASL I ;now get word offset in I by shifting + ;; get index into map between DM channels and TTY indices + MOV M2LMAP(I),I + BEQ 90$ ;EXIT IF THIS LINE NOT UNDER MODEM CONTROL +; TST @DMCSR(A) .SEE DMRNG +; BPL 10$ +; TST DIALED(I) ;RINGING. IS LINE DIALED UP ALREADY? +; BNE 10$ ;YES, NOT SUPPOSED TO BE RINGING +; MOV #LINENB+LINDTR,@DMLSR(A) ;ANSWER THE PHONE + +10$: BIT #LINCTS,@DMLSR(A) ;DO WE HAVE CLEAR-TO-SEND? + BEQ 20$ ;NO + TST DIALED(I) ;YES, WHAT WAS PREVIOUS STATE? + BEQ 13$ ;WAS OFF, THIS IS A DIALUP + BPL 90$ ;WAS ON, IGNORE + NEG DIALED(I) ;WAS HANGING UP, ABORT IT + BR 90$ + +13$: INC DIALED(I) ;LINE IS NOW DIALED UP + TST DMINI ;IF GETTING INITIAL STATE, + BNE 90$ ;DON'T HACK AUTOSPEED + TST AUTOSP(I) ;IF IT HAS AUTOSPEED, + BEQ 90$ + MOV HDWR(I),H ;HACK THAT + CALL ASPMD + BR 90$ + +20$: TST DIALED(I) ;CTS DROPPED + BMI 90$ ;ALREADY KNOWN ABOUT, IGNORE + MOV #-HNGDLY,DIALED(I) ;OTHERWISE START HANGUP TIMEOUT + +90$: BIC #DMDON,@DMCSR(A) ;RESTART SCANNER + POP + POP H + RTI +.ENDC ;NDMS + +.IFNZ GOULDP +.SBTTL GOULD PRINTER P.I. LEVEL + +GLPBRK: BIT #%GSBSY,@#GLPCSR + BEQ 1$ + RTI ;LPT BUSY, WAIT + +1$: BIT #%GSDON,@#GLPCSR + BNE 2$ + RTI ;LPT BUSY OTHER FLAVOR + +2$: PUSH + BIT #%GSERR,@#GLPCSR ;LPT LOSING? + BEQ GLPBR1 + CALL GLPRST ;YUP, RESET THE BUFFERS + MOV @#GLPCSR,GLPERR ;AND TELL 10 + +GLPOFF: CLR GLPOAC ;HERE TO STOP P.I. + MOV #%GCIOF,@#GLPCSR + MOV #5000.,A ;LPT SOMETIMES BUSY FOR A WHILE +1$: BIT #%GSBSY,@#GLPCSR ;HAVE TO WAIT SO TONER PUMPS WILL + BEQ 2$ ;REALLY TURN OFF + SOB A,1$ +2$: MOV #%GCOFF,@#GLPCSR +GLPEX: POP + RTI + +GLPFIN: MOV #%GBIDL,GB.STA(H) ;DONE WITH THIS BUFFER + MOV GB.NXT(H),H ;CHECK NEXT + MOV H,GLPOOP + +GLPBR1: MOV GLPOOP,H ;CHECK ON BUFFERS + CMP GB.STA(H),#%GBDMA ;FINISH DMA XFER? + BEQ GLPFIN ;YES + CMP GB.STA(H),#%GBWRT ;QUEUED OR ALREADY ACTIVE AT P.I.? + BLT GLPOFF ;NO, STOP + MOV #%GBPI,GB.STA(H) ;YES, ACTIVATE IT AT P.I. + TST GB.FF(H) ;NEED FF? + BEQ 1$ + MOV #%GCFF,@#GLPCSR ;YES + CLR GB.FF(H) + BR GLPEX + +1$: TST GB.NL(H) ;NEED BLANK LINES? + BEQ 2$ + DEC GB.NL(H) ;YES, GIVE ONE + MOV #%GCADV,@#GLPCSR + BR GLPEX + +2$: MOV H,B ;SET UP TEXT ADDR + ADD #GB.DAT,B + MOV GB.PNT(H),A ;SET UP TEXT WORD COUNT + NEG A + MOV A,@#GLPWC + MOV B,@#GLPCA ;START XFER + MOV #%GBDMA,GB.STA(H) ;FLAG BUFFER ACTIVE AT DMA LEVEL + BR GLPEX + +GLPRST: PUSH H + MOV #GLPBFF,H ;FLUSH ALL BUFFERS + MOV H,GLPOOP + MOV H,GLPOIP +3$: CLR (H)+ + MOV (H),H + CMP H,#GLPBFF + BNE 3$ + MOV #60.*10.,GLPTIM ;SET TIMEOUT + POP H + RET + +.ENDC ;GOULDP + +.IFNZ CHAOSP + + .SBTTL CHAOSNET ROUTINES + +;ALL ROUTINES ON THIS PAGE CALLED WITH INTERRUPTS MASKED, INDEX IN I. + +;REFILL FROM CHAOS INTERFACE +CHSRFL: BIS #%CAREN,@CHIHWR(I) ;TURN ON RECEIVER INTERRUPTS + RET ;WILL NOTICE INPUT LATER + +.IFNZ DL10P +;LOOPS BACK TO HERE WHEN DISCARDING A PACKET +DLCRF1: CMP (SP)+,(SP)+ ;POP + POP A + INC DLCSS1(A) ;2 ;INDICATE BUFFER HAS BEEN COPIED + BIS #DLX10I,DLXCSR ;AND INTERRUPT THE PDP10 + ;DROP INTO DLCRFL +;REFILL FROM DL10 +DLCRFL: CALL DLCCHK ;SEE IF DL10 IS DISABLED + BNE 99$ ;BRANCH IF YES + MOV #2,A ;CHECK BOTH 10 TO 11 BUFFERS SO CAN'T GET OUT OF PHASE WITH 10 +10$: CMP DLCSS1(A),#1 ;10 SAYS BUFFER READY? + BEQ 11$ ;YES + SUB #2,A ;NO, TRY NEXT + BPL 10$ + BR 99$ ;NONE READY + +11$: PUSH A ;SAVE CURRENT 10 TO 11 BUFFER + ADD #DLCSP1,A ;OUTPUT READY, GET IT + MOV #DLCIBF,B ;COPY INTO BUFFER +.REPT PKHDW ;FIRST GET HEADER + MOV (A),(B)+ +.ENDR + PUSH + CALL CHSIHD ;PROCESS HEADER, GET LENGTH, DEST + BVS DLCRF1 ;BRANCH IF PACKET NO GOOD + POP + PUSH C + SUB CHIHDL(I),C ;GET NUMBER OF DATA WORDS TO FOLLOW + CALL MOVHD ;MOVE THOSE WORDS + POP ;RESTORE LENGTH, 10 TO 11 BUFFER NUMBER + INC DLCSS1(A) ;2 ;INDICATE BUFFER HAS BEEN COPIED + BIS #DLX10I,DLXCSR ;AND INTERRUPT THE PDP10 + TST B ;SWAB IF NOT TO 10-COMPATIBLE DEST + CALL SWAB10 + INC CHISTS(I) ;INDICATE BUFFER READY TO SEND +99$: RET + +;TRANSMIT TO DL10 OUTPUT SINK +;REQUIRES I TO BE SET UP, SMASHES ALL REGS. +DLCXMT: CALL DLCCHK ;DL10 DISABLED? + BNE 70$ ;YES, DISCARD PACKET + MOV DLCRBN,A ;GET CURRENT 11 TO 10 BUFFER NUMBER + CMP DLCRS1(A),#1 ;BUFFER READY? + BNE 80$ ;NO, WAIT + MOV CHOINX+CHXDLC,D ;GET ADDRESS OF BUFFER TO BE SENT OVER + MOV CHILNG(D),C ;AND LENGTH + MOV CHIBFP(D),D + MOV A,H ;GET POINTER TO DL10 MAGIC IDPB WORD + ADD #DLCRP1,H + CALL MOVDH ;COPY WORDS INTO PDP10 + INC DLCRS1(A) ;SIGNAL DATA AVAILABLE TO PDP10 + BIS #DLX10I,DLXCSR ;AND INTERRUPT IT + MOV DLCNXT(A),DLCRBN ;SWITCH BUFFERS +70$: JMP CHSODN ;TRANSMISSION IS DONE ALREADY + +80$: MOV #1,CHOSTS+CHXDLC ;TRANSMISSION AWAITING BUFFER FROM 10 + RET + +;CALL HERE WHEN DL10 INTERRUPTS, CLOBBERS ALL. +DLCWAK: MASK 5 + TST CHOSTS+CHXDLC ;DL10 HUNG ON TRANSMIT? + BEQ 10$ + MOV #CHXDLC,I ;YES, WAKE IT UP + CALL DLCXMT +10$: TST CHISTS+CHXDLC ;DL10 INPUT ACTIVE? + BNE 20$ + MOV #CHXDLC,I ;NO, TRY TO GET SOME + CALL DLCRFL + TST CHISTS(I) ;GOT SOME? + BLE 20$ + CALL CHSOUT ;YES, START TRANSMISSION +20$: CALL CHSRUN ;DO ANYTHING ELSE REQUIRED + UNMASK + RET + +;RETURN 'NE' IF DL10 IS DISABLED, BASHES NOTHING. +DLCCHK: TST DLXOFF + BNE 99$ + TST NO.ITS + BNE 99$ + TST DLCINI ;RE-INITIALIZE? + BEQ 99$ ;NO, EVERYTHING IS OK. + CLR DLCRBN ;YES + TST CHOSTS+CHXDLC ;WAS OUTPUT HUNG ON DL10? + BEQ 90$ + PUSH ;YES, SIGNAL OUTPUT DONE ON DL10 + MOV #CHXDLC,I + CALL CHSODN + POP +90$: CLR DLCINI ;SIGNAL INIT DONE, RETURN 'EQ' +99$: RET +.ENDC ;DL10P + +;FAST BLOCK MOVE +;THESE CAN MOVE AT MOST 256. WORDS + +;MOV (H),(D)+ +;SOB C,.-2 +MOVHD: SUB #256.,C ;GET -#WDS LESS THAN MAXIMUM + ADD C,C ;CONVERT TO BYTES + SUB C,PC ;JUMP INTO MOVE TABLE + .REPT 256. + MOV (H),(D)+ + .ENDR + RET + +;MOV (D)+,(H) +;SOB C,.-2 +MOVDH: SUB #256.,C ;GET -#WDS LESS THAN MAXIMUM + ADD C,C ;CONVERT TO BYTES + SUB C,PC ;JUMP INTO MOVE TABLE + .REPT 256. + MOV (D)+,(H) + .ENDR + RET + +.IFNZ TEN11P +;REFILL FROM TEN-11 INTERFACE +T11RFL: CALL T11CHK ;CHECK FOR DISABLE + BNE 99$ ;BRANCH IF DISABLED + MOV T11IBP,A + TST T11IBA ;WAS INPUT BUFFER IN USE? + BEQ 10$ + CLR (A)+ ;YES, INDICATE BUFFER IS NOW EMPTY + CLR (A) + CLR T11IBA + ADD #T11BFL-2,A ;ADVANCE POINTER + CMP A,#T11IBE + BLO 7$ + MOV #T11IBF,A +7$: MOV A,T11IBP +10$: TST (A) ;INPUT BUFFER CONTAIN A PACKET? + BEQ 99$ ;NO + SETOM T11IBA ;YES, INPUT BUFFER NOW ACTIVE + ADD #8,A ;GET INPUT FROM PDP10 + MOV A,CHIBFP+CHXT11 ;AS CURRENT INPUT BUFFER + CALL CHSIHD ;PROCESS THE HEADER + BVS T11RFL ;BRANCH IF PACKET NO GOOD + PUSH ;COMPUTE CHECKSUM BEFORE SWABBING + INC C ;C GETS NUMBER OF 32-BIT WORDS + ASR C + CLR D ;CLEAR LOW WORD OF CHECKSUM + CLR H ;CLEAR HIGH WORD OF CHECKSUM + SUB #PKFCMS+1,PKFC(A) ;DECREMENT FWD COUNT (IS HIGH END OF WORD) + ;FWD COUNT HAS TO BE PUT BACK FOR CHECKSUM COMPUTATION +21$: ADD (A)+,H ;ADD HIGH HALFWORD TO HIGH SUM + ADD (A)+,D ;ADD LOW HALFWORD TO LOW SUM + ADC H ;CARRY INTO HIGH SUM + MOV D,B ;NOW ROTATE RIGHT DOUBLE + ROR B + ROR H + ROR D + SOB C,21$ + MOV T11IBP,A ;NOW COMPARE CHECKSUM + CMP H,4(A) + BNE 30$ + CMP D,6(A) + BNE 30$ + POP + ADD #PKFCMS+1,PKFC(A) ;INCREMENT FWD COUNT (IS HIGH END OF WORD) + TST B ;SWAB IF NOT TO 10-COMPATIBLE DEST + CALL SWAB10 + INC CHISTS(I) ;INDICATE BUFFER READY TO SEND +99$: RET + +30$: POP ;CHECKSUM ERROR + INC T11CKE ;COUNT CHECKSUM ERRORS + BR T11RFL ;AND IGNORE PACKET + +;TRANSMIT TO TEN11 OUTPUT SINK +;REQUIRES I TO BE SET UP, SMASHES ALL REGS. +T11XMT: CALL T11CHK ;TEN11 DISABLED? + BNE 70$ ;YES, DISCARD PACKET + TST @T11OBP ;OUTPUT BUFFER EMPTY? + BNE 80$ ;NO, WAIT + MOV CHOINX+CHXT11,D ;GET ADDRESS OF BUFFER TO BE SENT OVER + MOV CHIBFP(D),B + MOV CHILNG(D),C ;AND LENGTH + MOV PKNBYT(B),A + BIT #1,A ;IF ODD NUMBER OF BYTES, CLEAR THE EXTRA ONE + BEQ 5$ + BIC #PKNBMS,A + ADD B,A + CLRB PKDAT-1(A) ;NOTE, AT THIS POINT BYTES ARE SWAPPED +5$: MOV T11OBP,A ;COPY INTO TEN11 OUTPUT BUFFER + ADD #8,A + PUSH +10$: MOV (B)+,(A)+ + SOB C,10$ + MOV (SP),C ;NOW COMPUTE CHECKSUM + INC C ;C GETS NUMBER OF 32-BIT WORDS + ASR C + BCS 11$ + CLR (A)+ ;IF ODD NUMBER OF 16-BIT WORDS, CLEAR THE EXTRA ONE +11$: CLR D ;CLEAR LOW WORD OF CHECKSUM + CLR H ;CLEAR HIGH WORD OF CHECKSUM + MOV T11OBP,A + ADD #8,A +21$: ADD (A)+,H ;ADD HIGH HALFWORD TO HIGH SUM + ADD (A)+,D ;ADD LOW HALFWORD TO LOW SUM + ADC H ;CARRY INTO HIGH SUM + MOV D,B ;NOW ROTATE RIGHT DOUBLE + ROR B + ROR H + ROR D + SOB C,21$ + MOV T11OBP,A ;STORE CHECKSUM INTO OUTPUT BUFFER + MOV H,4(A) + MOV D,6(A) + POP + SETOM (A) ;SIGNAL PRESENCE OF PACKET TO PDP10 + ADD #T11BFL,A ;ADVANCE POINTER + CMP A,#T11OBE + BLO 30$ + MOV #T11OBF,A +30$: MOV A,T11OBP +70$: CLR T11TIM ;NO TIMEOUT, 10 IS TAKING PACKETS + JMP CHSODN ;TRANSMISSION IS DONE ALREADY + +80$: MOV #1,CHOSTS+CHXT11 ;TRANSMISSION AWAITING BUFFER FROM 10 + RET + +;WHACK YOUR TEN11 +T11WAK: MASK 5 + MOV #CHXT11,I + CALL T11CHK ;IS 10 UP? + BNE 30$ ;IT'S DOWN, PUNT IT + TST CHOSTS(I) ;TEN11 HUNG ON TRANSMIT? + BEQ 10$ + CALL T11XMT ;YES, WAKE IT UP +10$: TST CHISTS+CHXT11 ;TEN11 INPUT ACTIVE? + BNE 20$ + MOV #CHXT11,I ;NO, TRY TO GET SOME + CALL T11RFL + TST CHISTS(I) ;GOT SOME? + BLE 20$ + CALL CHSOUT ;YES, START TRANSMISSION +20$: CALL CHSRUN ;DO ANYTHING ELSE REQUIRED + UNMASK + RET + +30$: TST CHOSTS(I) ;TRANSMITTING TO DEAD TEN-11? + BEQ 20$ + CLR T11TIM ;YES, FLUSH IT + CALL CHSODN + BR 20$ + +;CHECK TEN-11 INTERFACE, DO RESET IF NECESSARY, RETURN 'NE' IF DISABLED. +;SMASHES NOTHING. +T11CHK: CMP T11TIM,#5*60. ;10 TAKING 5 SECONDS TO RESPOND? + BLO 5$ + SETOM T11I10 ;YES, DECLARE IT DOWN, REINITIALIZE PROTOCOL +5$: TST T11I10 ;IS 10 DONE INITIALIZING? + BNE 99$ ;NO, DO NOTHING + TST T11I11 ;ARE WE SUPPOSED TO INITIALIZE? + BEQ 99$ ;NO, IT'S OK + MOV #T11OBF,T11OBP ;YES, REINITIALIZE POINTERS + MOV #T11IBF,T11IBP + PUSH A + MOV #T11OBF,A ;INITIALIZE INPUT AND OUTPUT BUFFER HEADERS +10$: CLR (A)+ ;CLEAR INTER-MACHINE SIGNAL WORD + CLR (A)+ + ADD #T11BFL-4,A ;SKIP THE REMAINING WORDS + CMP A,#T11IBE + BLO 10$ + CLR T11IBA ;IDLE THE INPUT + POP A + TST CHOSTS+CHXT11 ;WAS OUTPUT HUNG ON TEN11? + BEQ 90$ + PUSH ;YES, SIGNAL OUTPUT DONE ON TEN11 + MOV #CHXT11,I + CALL CHSODN + POP +90$: CLR T11I11 ;SIGNAL INIT DONE, RETURN 'EQ' + CLR T11I11+2 +99$: RET +.ENDC ;TEN11P + +;THIS ROUTINE PROCESSES THE HEADER OF PACKET IN INPUT BUFFER FOR SOURCE I +;RETURN DESTINATION OUTPUT SINK INDEX IN B (-1 IF THIS IS FOR US (PDP11 ITSELF)), +;PACKET BUFFER POINTER IN A, AND LENGTH IN WORDS IN C. +;RETURNS WITH OVERFLOW SET IF PACKET IS DISCARDED BECAUSE OF +;TOO MUCH FORWARDING, BAD ADDRESS, TOO BIG, CRUFTY, ETC. +;OTHERWISE RETURNS WITH MINUS INDICATOR SET IF PACKET DIRECTED TO 11. +CHSIHD: ADD #1,NPKSI(I) ;COUNT PACKETS IN FROM THIS SOURCE + ADC HPKSI(I) + MOV CHIBFP(I),A ;POINTER TO PACKET + TSTB (A) ;CHECK FOR MUPPET + BNE CHSIHB ;DISCARD, WE DON'T SUPPORT THEM + MOV #PKHDW,CHIHDL(I) ;SET HEADER LENGTH + ADD #PKFCMS+1,PKFC(A) ;INCREMENT FWD COUNT (IS HIGH END OF WORD) + BCS CHSIHB ;BRANCH IF FORWARDING LOOP + MOV PKNBYT(A),C ;GET BYTE COUNT + BIC #PKNBMS,C + CMP C,#DATMAX + BHI CHSIHB ;TOO LONG, LOSES + INC C ;MAKE WORD COUNT + ASR C + ADD CHIHDL(I),C ;ADD IN LENGTH OF HEADER + MOV C,CHILNG(I) ;SAVE FOR LATER USE + ;; NOW ROUTE THIS PACKET + MOV #-1,B ;MAGIC INDEX MEANING "MYSELF" + MOV PKDHST(A),D ;GET DESTINATION ADDRESS + ;HERE WE HAVE HAIR FOR MULTIPLE CHAOSNETS +.REPT CHAOSP + CONC ,\.RPCNT ;ADDRESSED TO PDP11 ITSELF? + BEQ 50$ ;YES, LET CHSRUN HANDLE IT LATER +.ENDR ;CHAOSP + CMPB PKOP(A),#%CORUT ;ROUTING INFO PACKET? + BEQ 40$ ;YES, ADDRESS TO PDP11 + TST USECBL ;SUPPOSED TO USE CABLE EVEN TO TALK TO SELF? + BEQ 20$ + CMP I,#CHXCHS ;YES, IS THIS COMING FROM CABLE? + BHIS 20$ ;YES, ROUTE REGULAR WAY + MOV #CHXCHS,B ;NO, SEND TO SELF ON FIRST CABLE + MOV #CHADD,D + BR 39$ + +20$: MOVB PKDHST+1(A),B ;GET SUBNET ADDRESSED TO + CMP B,#NSUBNT + BLO 21$ + CLR B ;OUT OF RANGE, USE 0 +21$: ASL B ;MAKE INDEX INTO SUBNET TABLES + TST SBNTYP(B) ;IS THIS A DIRECT HARDWARE CONNECTION? + BGT 38$ ;YES, SEND TO IT + MOV SBNADR(B),D ;NO, GO VIA GATEWAY + BEQ CHSIRF ;HAVEN'T GOT A GATEWAY, AND BROADCAST CODE NOT WORKING YET + MOVB SBNADR+1(B),B ;GET SUBNET GATEWAY IS ON + ASL B ;MAKE INDEX INTO TABLES + CMP B,#NSUBNT*2 + BHIS CHSIRF ;OUT OF RANGE, CAN'T GET THERE FROM HERE + TST SBNTYP(B) ;IS THIS A DIRECT CONNECTION? + BLE CHSIRF ;NO, CAN'T GET THERE FROM HERE (SHOULDN'T HAPPEN!) +38$: MOV SBNADR(B),B ;GET SINK INDEX +39$: MOV D,CHICBA(I) ;STORE CABLE ADDRESS OF IMMEDIATE DEST (GATEWAY) +.IIF NDF NDVRBF, 50$: ;IF NO DOVER, ALL TO-11 PACKETS COME HERE +40$: MOV B,CHIOUX(I) ;STORE SINK INDEX, SET INDICATORS + RET ;NOTE THAT MOV CLEARS OVERFLOW + +.IF DF NDVRBF +50$: CMP PKDIND(A),DVRLIX ;DIRECTED TO DOVER? + BNE 40$ ;NO, TO 11 + CMP PKSHST(A),DVRHST + BNE 40$ ;NOT DOVER-CONNECTED HOST + CMP PKSIND(A),DVRIDX + BNE 40$ ;RIGHT HOST, WRONG PROCESS + MOV #CHXDVR,B ;ROUTE PACKET TO DOVER GATEWAY + BR 40$ +.ENDC ;NDVRBF + +;HERE FOR ROUTING FAILURE. METER, RETURN WITH OVERFLOW SET. +CHSIRF: INC NPKSRF + MOV B,RFSBNT ;SAVE 2* SUBNET TRYING TO GET TO + ;FALL INTO CHSIHB +;HERE WHEN CHSIHD SEES A GARBAGE PACKET. RETURN WITH OVERFLOW SET. +CHSIHB: ADD #1,NPKSBD(I) ;GOD-DAMN BRAIN-DAMAGE + ADC HPKSBD(I) + SEV + RET + +;SWAB PACKET COMING FROM PDP-10 OR ETHERNET (BYTES LEFT TO RIGHT) +;IF GOING TO INCOMPATIBLE DESTINATION. CALL RIGHT AFTER CHSIHD. +SWAB10: BMI CHSSWB ;SWAB IF TO-11 + CMP CHOXMT(B),#CHSXMT ;CHECK DESTINATION TYPE + BEQ CHSSWB ;PDP11 OR CHAOSNET, SWAB IT OUT +5$: RET ;PDP10 OR ETHERNET, LEAVE ALONE + +;SWAB PACKET COMING FROM PDP-11 OR CHAOSNET (BYTES RIGHT TO LEFT) +;IF GOING TO INCOMPATIBLE DESTINATION. CALL RIGHT AFTER CHSIHD. +SWAB11=. + BMI 5$ ;RETURN IF TO-11 + CMP CHOXMT(B),#CHSXMT ;CHECK DESTINATION TYPE + BEQ 5$ ;PDP11 OR CHAOSNET, LEAVE ALONE + ;PDP10 OR ETHERNET, SWAB IT OUT + ;DROPS THROUGH INTO CHSSWB +;THIS ROUTINE SWABS THE PACKET FOR THE SOURCE IN I. +;CALLED WITH NUMBER OF WORDS IN PACKET IN C. +;CLOBBERS A, C, AND D. +;SUITABLE FOR CALLING RIGHT AFTER CHSIHD RETURNS. +CHSSWB: MOV CHIBFP(I),A ;ADDRESS OF PACKET + SUB CHIHDL(I),C ;GET LENGTH OF DATA AREA IN WORDS + BLE 99$ ;EMPTY + MOVB PKOP(A),D ;GET OPCODE + BPL 5$ ;BRANCH IF NON-DATA + BIT #100,D ;CHECK FOR BINARY DATA + BEQ 10$ ;NO, GO SWAB +99$: RET + +5$: TSTB CHSBIN(D) ;CONTROL, LOOK UP OPCODE + BNE 99$ ;BINARY, NO SWAB +10$: ADD CHIHDL(I),A ;POINT TO DATA AREA OF BUFFER + ADD CHIHDL(I),A ;BYTES, WATSON, BYTES! + SUB #PKTMXW,C ;GET -#WDS LESS THAN MAXIMUM + ADD C,C ;CONVERT TO BYTES + SUB C,PC ;JUMP INTO SWAB TABLE + .REPT PKTMXW + SWAB (A)+ + .ENDR + RET + +;BYTE TABLE INDEXED BY OPCODE, NON-ZERO IF BINARY +;BINARY OPERATIONS ARE 2 (%COOPN), 7 (%COSTS), 10 (%CORUT) +CHSBIN: .BYTE 0,0,2,0,0,0,0,7,10,0,0,0,0,0 + .BYTE 0,0 ;SPARES IN CASE MORE OPCODES ADDED + .EVEN + +;TRANSMIT PACKET FROM INPUT SOURCE I TO OUTPUT SINK, IN B. +;SMASHES ALL REGISTERS. CHISTS(I), CHIOUX(I), CHICBA(I) MUST BE ALREADY SET UP. +CHSOUT: TST B ;THIS DESTINED TO PDP11? + BMI CHSOUX ;YES, LET CHSRUN PICK IT UP LATER + TST CHOSTS(B) ;IS SINK BUSY? + BNE CHSOUX ;YES, CAN'T SEND NOW, WILL TRY AGAIN LATER + NEG CHISTS(I) ;NO, SET SOURCE STATUS TO CONNECTED + MOV I,CHOINX(B) ;CONNECT SINK TO SOURCE + MOV B,I ;SET UP SINK INDEX + ADD #1,NPKSO(I) + ADC HPKSO(I) + JMP @CHOXMT(I) ;GO START TRANSMISSION TO SINK + +;CALL HERE WHEN OUTPUT IS DONE ON SINK I. +CHSODN: CLR CHOSTS(I) ;IDLE THE SINK + PUSH I + MOV CHOINX(I),I ;GET CORRESPONDING SOURCE + CLR CHISTS(I) ;IDLE IT + CALL @CHIRFL(I) ;TELL SOURCE IT'S DONE, TRY TO GET MORE INPUT + POP I +CHSOUX: RET + +;CALL HERE AFTER EACH PACKET TRANSFER TO INITIATE AS MANY ADDITIONAL TRANSFERS +;AS POSSIBLE. BASHES ALL REGISTERS. ON DL10 AND TEN11, WE COULD ACTUALLY DO SEVERAL +;TRANSFERS BEFORE RETURNING. +CHSRUN: +.IF DF NDVRBF + CALL DVRRFL ;WAKE UP DOVER, MIGHT BE TIME TO RETRANSMIT +.ENDC ;NDVRBF + MOV #*2,I ;SCAN ALL INPUT SOURCES +CHSRN1: TST WAKE ;GIVE UP IF CLOCK HAS TICKED, LET TTYS RUN + BNE CHSOUX + TST CHISTS(I) ;IS THIS SOURCE LOOKING FOR A SINK? + BLE CHSRN3 +CHSRN2: MOV CHIOUX(I),B ;GET SINK IT WANTS TO SEND TO + BMI FOR11 ;BRANCH IF FOR PDP11 + TST CHOSTS(B) ;SINK AVAILABLE? + BNE CHSRN3 ;NO, LET INPUT SIT + CALL CHSOUT ;YES, ATTEMPT TO TRANSMIT + BR CHSRUN ;LOOK FOR MORE WORK + +CHSRN3: SUB #2,I ;NEXT INPUT SOURCE + BGE CHSRN1 + RET ;NOTHING LEFT TO DO + +FOR11: MOV CHIBFP(I),A ;PACKET FOR PDP11, CHECK IT OUT + MOVB PKOP(A),B ;GET OPCODE + CMP B,#%CORUT ;IF ROUTING INFO, GOBBLE IT + BEQ CHARUT + CMP B,#%CORFC ;ALL WE KNOW IS RFC TO CERTAIN CONTACT NAMES + BNE FOR11J ;BARF AT JUNK PACKETS + CALL SERVE ;RUN THE SERVER + BEQ FOR11X ;IT DIDN'T LIKE IT +FOR11R: PUSH ;INTERCHANGE SOURCE AND DESTINATION + MOV PKSHST(A),PKDHST(A) + MOV PKSIND(A),PKDIND(A) + POP + CALL CHSIHD ;ROUTE + BVS FOR11X ;NO GOOD, FLUSH (SOURCE IN PACKET WAS WRONG) + CALL SWAB11 ;SWAB IF GOING TO 11-INCOMPATIBLE DEST + BR CHSRN2 ;FIRE IT OFF (CHISTS IS ALREADY 1) + +FOR11X: CLR CHISTS(I) ;DISCARD THIS PACKET + CALL @CHIRFL(I) + BR CHSRUN ;LOOK FOR MORE WORK + +;PACKET FROM RANDOM PLACE DIRECTED TO 11, TELL HIM TO GO AWAY +FOR11J: CMP B,#%COLOS ;DON'T BARF AT LOS PACKETS + BEQ FOR11X + MOV #<%COLOS*400>,(A) + MOV #6$-5$-1,PKNBYT(A) + MOV #5$,B + MOV A,C + ADD #PKDAT,C +1$: MOVB (B)+,(C)+ + BNE 1$ + BR FOR11R ;SEND OFF THE LOS +5$: .ASCIZ /Packet unrecognized by gateway-11/ +6$: .EVEN + +;ROUTING PACKET +CHARUT: MOV CHILNG(I),C ;GET NUMBER OF DATA WORDS + SUB #PKHDW,C + ASR C ;MAKE NUMBER OF 2 WORD PAIRS + BEQ FOR11X ;MIGHT BE ZERO-LENGTH + MOV A,D + ADD #PKDAT,D ;POINT TO START OF PACKET'S DATA +61$: MOV (D)+,B ;GET SUBNET BEING TALKED ABOUT + CMP B,#NSUBNT ;ONE WE KNOW ABOUT? + BHIS 62$ ;NO, FORGET IT + ASL B ;MAKE WORD INDEX + TST SBNTYP(B) ;IS THIS AN AUTO ROUTING TYPE SUBNET? + BNE 62$ ;NO, DON'T MUNG OUR FIXED ROUTING INFO + CMP (D),SBNCST(B) ;COMPARE COSTS + BHI 62$ ;NEW ONE WORSE (IF EQUAL, SWITCH TO EQUALIZE LOAD) + MOV (D),SBNCST(B) ;SAVE BEST COST + MOV PKSHST(A),SBNADR(B) ;AND HOST ADDRESS THIS CAME FROM AS BEST BET +62$: TST (D)+ ;SKIP COST + SOB C,61$ + BR FOR11X ;DONE WITH PACKET + + .SBTTL CHAOS NET SERVERS + +;CALLED WITH PACKET IN A. +;MUST PRESERVE A,I. +;RETURN 'EQ' IF NO GOOD, 'NE' IF MODIFIED PACKET TO BE RETURNED TO SOURCE + +;CURRENTLY WE SERVE THE FOLLOWING CONTACT NAMES: +; STATUS - RETURNS ANS WITH THE NAME OF THE MACHINE, LATER WILL HAVE OTHER DATA +; PULSAR - RETURNS ANS WITH DATA OF 1 BYTE, VALUE OF PULSON AS AN ASCII DIGIT, +; I.E. "0" MEANS OFF, "1" MEANS 60 PER SECOND, ETC. +; IF CONTACT NAME IN RFC IS FOLLOWED BY A SPACE AND AN ASCII DIGIT, +; SETS PULSON TO THAT STATUS. +; DOVER - DOVER PROTOCOL TRANSLATOR + +;NOTE THAT WE DON'T USE THE MOST WINNING STRING COMPARE IN THE WORLD, +;THIS CODE ASSUMES IT DOESN'T MATTER WHAT HAPPENS IF AN RFC TO +;AN UNKNOWN CONTACT NAME IS DONE, AS LONG AS THE 11 DOESN'T CRASH. + +SERVE: MOV #SRVTBL,B ;ADDRESS OF SERVER TABLE +10$: MOV (B)+,D ;ADDRESS OF CONTACT NAME FOR THAT SERVER + BEQ 99$ ;EXIT IF TABLE EXHAUSTED, 'EQ' IN COND CODE + MOV A,C + ADD #PKDAT,C ;ADDRESS OF CONTACT NAME IN THIS RFC +11$: TSTB (D) ;END OF STRING? + BEQ 20$ ;YUP, RUN THIS SERVER + CMPB (C)+,(D)+ ;DO STRING COMPARE + BEQ 11$ ;MATCHES + TST (B)+ ;DOESN'T MATCH, TRY NEXT + BR 10$ + +99$: RET + +20$: JMP @(B)+ ;CALL SERVER, IT CAN RETURN EQ OR NE + +SRVTBL: .WORD 1$,STSSRV ;STATUS - RETURN HOST NAME AND METERS + .WORD 2$,PLSSRV ;PULSAR - SET AND GET PULSAR RATE +.IIF DF NDVRBF, .WORD 3$,DVROPN ;DOVER - DOVER PROTOCOL TRANSLATOR + .WORD 0 ;END OF TABLE +1$: .ASCIZ /STATUS/ +2$: .ASCIZ /PULSAR/ +3$: .IIF DF NDVRBF, .ASCIZ /DOVER/ + .EVEN + +;SERVERS MUST PRESERVE A (PACKET), AND I, AND RETURN 'NE' IF TO BE SENT BACK TO SOURCE. +;NOTE THAT C POINTS AT THE NEXT BYTE AFTER THE CONTACT NAME + +STSSRV: MOV A,B ;RFC TO "STATUS", CHANGE INTO ANS CARRYING APPROPRIATE DATA. + MOV #32.+<12.*NCHX>+<24.*CHAOSP>+<12.*ETHERP>,PKNBYT(A) ;SET BYTE LENGTH, CLEAR FORWARDING COUNT + ADD #PKDAT,B + MOV #HSTNAM,D ;SEND NAME OF HOST + MOV #32.,C +45$: MOVB (D)+,(B)+ + SOB C,45$ + CLR D ;NOW STORE METERING INFO FOR EACH SUBNET +50$: MOV CHXSBN(D),(B)+ ;STORE SUBNET NUMBER+400 + MOV #4,(B)+ ;ASSUME NOT A CABLE + MOV NPKSI(D),(B)+ + MOV HPKSI(D),(B)+ + MOV NPKSO(D),(B)+ + MOV HPKSO(D),(B)+ +.IFNZ ETHERP + CMP D,#CHXETH ;ETHERNET HAS SOME OF THESE COUNTERS + BNE 55$ + MOV #12.,-10.(B) ;THERE ARE 4 MORE DOUBLE-WORDS + MOV NPKSAB-CHXCHS(D),(B)+ + MOV HPKSAB-CHXCHS(D),(B)+ + CLR (B)+ + CLR (B)+ + MOV NPKSGB-CHXCHS(D),(B)+ + MOV HPKSGB-CHXCHS(D),(B)+ + MOV NPKSRL-CHXCHS(D),(B)+ + MOV HPKSRL-CHXCHS(D),(B)+ + BR 59$ +.ENDC ;ETHERP +55$: CMP CHIRFL(D),#CHSRFL ;CHAOSNET CABLE? + BNE 59$ ;NO, THAT'S ALL + MOV #16.,-10.(B) ;YES, THERE ARE 6 MORE DOUBLE-WORDS + MOV NPKSAB-CHXCHS(D),(B)+ + MOV HPKSAB-CHXCHS(D),(B)+ + MOV NPKSLS-CHXCHS(D),(B)+ + MOV HPKSLS-CHXCHS(D),(B)+ + MOV NPKSGB-CHXCHS(D),(B)+ + MOV HPKSGB-CHXCHS(D),(B)+ + MOV NPKSRL-CHXCHS(D),(B)+ + MOV HPKSRL-CHXCHS(D),(B)+ + CLR (B)+ ;I DON'T KEEP TRACK OF BIT COUNT ERRS SEPARATELY + CLR (B)+ + MOV NPKSBD(D),(B)+ + MOV HPKSBD(D),(B)+ +59$: TST (D)+ + CMP D,#2*NCHX + BLO 50$ +RETANS: MOVB #%COANS,PKOP(A) ;RETURN THIS PACKET TO SOURCE AS AN 'ANS' + RET ;NOTE CONDITION CODES HAVE 'NE' + +PLSSRV: MOVB PKNBYT(A),C ;GET BYTE COUNT, SHOULD BE SMALL + CMP C,#8 ;6 FOR PULSAR, 1 FOR SPACE, 1 FOR CHARACTER + BLO 20$ ;NOT GIVEN AN ARGUMENT, JUST READ STATUS + MOVB PKDAT+7(A),C ;YES, GET THE ARGUMENT + SUB #'0,C ;CONVERT TO BINARY (CHEAPO!) + MOV C,PULSON ;CHANGE PULSON STATUS +20$: MOV #1,PKNBYT(A) ;SET BYTE LENGTH, CLEAR FORWARDING COUNT + MOV PULSON,C ;RETURN PULSAR STATUS + ADD #'0,C ;IN ASCII + MOVB C,PKDAT(A) + BR RETANS + + .SBTTL CHAOSNET INTERRUPT HANDLER + +;INTERRUPT HANDLER ENTRIES +.REPT CHAOSP +CONC CHS,\.RPCNT,BK: + JSR I,CHSBRK + CHXCHS+<.RPCNT*2> +.ENDR + +;SUBROUTINE TO ENABLE CHAOSNET INTERFACE IN H,I TO RECEIVE NEXT PACKET +CHINXT: MOVB 1(H),A ;GET CSR BITS 9-12 (LOST COUNT) + ASR A + BIC #-20,A + ADD A,NPKSLS-CHXCHS(I) + ADC HPKSLS-CHXCHS(I) + BIS #%CARCL+%CAREN,(H) ;MAKE READY TO RECEIVE ANOTHER MESSAGE + RET + +;COMMON CHAOS INTERRUPT ROUTINE +CHSBRK: MOV (I),I ;GET SOURCE/SINK INDEX + PUSH ;SAVE ALL REGISTERS + MOV CHIHWR(I),H ;GET HARDWARE ADDRESS + MOV (H),A .SEE CH%CSR ;GET CSR + BPL CHSBK1 ;TEST RECEIVE DONE, BRANCH IF NOT + .SEE %CARDN ;PALX SCREWS UP IF THIS IS ON PREVIOUS LINE! + TST CHISTS(I) ;MAKE SURE INPUT BUFFER IS IDLE + BNE CHSBK1 ;BUSY, DON'T LOOK AT RECEIVE DONE NOW + BIT #%CAERR,A ;CRC ERROR? + BNE CHICRC ;JUMP IF YES + MOV CH%RBC(H),C ;BIT COUNT -1 + SUB #47.,C ;ADD 1, THEN SUBTRACT 3*16. FOR HARDWARE WORDS + .IREPT 4, ASR C ;CONVERT TO NUMBER OF WORDS + CMP C,#256. + BHI CHIFLS ;THIS CAN ONLY HAPPEN IF HARDWARE BROKEN + ADD #CH%RBF,H ;POINT H TO RECEIVE DATA REG + MOV CHIBFP(I),D ;COPY PACKET INTO BUFFER + CALL MOVHD + TST (H) ;READ OUT THE 3 HARDWARE LEADER WORDS + CMP (H),(H) + SUB #CH%RBF,H ;RESTORE H + BIT #%CAERR,(H) ;WAS IT READ CORRECTLY OUT OF RAM? + BNE CHIGBG ;NO, GARBAGE + CMP CH%RBC(H),#7777 ;WAS PACKET CORRECT LENGTH? + BNE CHIGBG ;NO, GARBAGE + CALL CHINXT ;DONE WITH HARDWARE, ENABLE FOR NEXT + CALL CHSIHD ;PROCESS HEADER, GET LENGTH, DEST + BVS CHIFL0 ;BRANCH IF NO GOOD + CALL SWAB11 ;SWAB IF NOT GOING TO 11-COMPATIBLE DEST + INC CHISTS(I) ;INDICATE BUFFER READY TO SEND + PUSH I + CALL CHSOUT ;SEND IT OUT + POP I + MOV CHIHWR(I),H ;RESTORE H + TST CHISTS(I) ;INPUT BUFFER STILL BUSY? + BEQ CHSBK1 + BIC #%CAREN,(H) ;YES, CLEAR RECEIVE INTERRUPT ENABLE + BR CHSBK1 ;GO CHECK ON OUTPUT SIDE + +;HERE WHEN A PACKET WAS RECEIVED WITHOUT ERROR, BUT AFTER +;READING OUT OF THE RAM, CRC ERROR WAS SET. EITHER THE +;PACKET WAS THE WRONG LENGTH, OR THE RAM FAILED, OR THE +;HARDWARE RANDOMLY CLOBBERED IT. +;WE ALSO GET HERE IF THE BIT COUNT WAS NOT -1 AFTER ALL WORDS WERE READ. +CHIGBG: ADD #1,NPKSRL-CHXCHS(I) ;LOG THE ERROR + ADC HPKSRL-CHXCHS(I) + MOV H,CHSRLH + MOV CH%RBC(H),CHSRLC + BR CHIFLS ;GO RESET RECEIVER AND CHECK OUTPUT STATUS + +;HERE WHEN A PACKET IS RECEIVED WITH A CRC ERROR. DISCARD IT, +;BUT ALSO SAVE IT IN CHSGBF, CHSGBH, CHSGBS, CHSGBC FOR DEBUGGING (IF FTGARB). +CHICRC: ADD #1,NPKSGB-CHXCHS(I) + ADC HPKSGB-CHXCHS(I) +.IFNZ FTGARB + MOV H,CHSGBH + MOV (H),CHSGBS + MOV CH%RBC(H),CHSGBC + ADD #CH%RBF,H + MOV #CHSGBF,D + MOV #PKMAX,C + CALL MOVHD + SUB #CH%RBF,H ;DROP INTO CHIFLS +.ENDC ;FTGARB +;HERE TO IGNORE AN INPUT PACKET AND ENABLE HARDWARE FOR NEXT +CHIFLS: CALL CHINXT +CHIFL0: INC NPKSIG +;HERE TO CHECK ON TRANSMIT SIDE +CHSBK1: TSTB (H) .SEE %CATDN ;TRANSMIT DONE? + BPL CHSBKX ;NO, EXIT +.IFNZ CHSBTB + CLR CHSIDL(I) ;CLEAR TRANSMIT-DONE TIME-OUT +.ENDC ;CHSBTB + MOV CHOSTS(I),A ;WAS OUTPUT IN PROGRESS? + BEQ CHSBK6 ;NO, LOOK FOR OUTPUT + CMP A,#2 ;TRANSMIT ABORT DELAY COMPLETED? + BEQ 10$ + BIT #%CATAB,(H) ;NO, TRANSMIT ABORTED? + BEQ CHSBK4 ;NO + ADD #1,NPKSAB-CHXCHS(I) ;YES, METER IT, AND SET CHOSTS TO + ADC HPKSAB-CHXCHS(I) + INC CHOSTS(I) ;2 IF THIS IS FIRST TIME, OR 0 IF SECOND TIME + BEQ CHSBK4 ;LOST TWICE IN A ROW, GIVE UP + BR CHSBK5 ;TURN OFF INTERRUPT, DELAY FOR A WHILE + +10$: MOV #-1,CHOSTS(I) ;TRANSMIT ABORT DELAY COMPLETED, SET CHOSTS TO -1 + CALL CHSXM0 ;INITIATE RE-TRANSMISSION (CHOSTS ALREADY SET) + BR CHSBKX ;DISMISS + +CHSBK4: CALL CHSODN ;OUTPUT DONE +CHSBK6: PUSH I + CALL CHSRUN ;INITIATE MORE TRANSFERS + POP I + TST CHOSTS(I) ;DID IT INITIATE TRANSMISSION? + BNE CHSBKX ;YES, LEAVE INTERRUPT ENABLED. + MOV CHOHWR(I),H ;RESTORE H + TST CHXRTF(I) ;TIME TO BROADCAST ROUTING INFO? + BNE CHORUT ;YES + TST PULSON ;IS THIS FEATURE TURNED ON? + BEQ CHSBK5 ;NO, FLUSH + CMP PULSAR,PULSON ;NOTHING TO DO. TIME FOR A TEST MESSAGE? + BNE CHSBK5 ;NOPE, GO IDLE + MOV #52525,CH%WBF(H) ;WRITE A PACKET OF 3 HEADER WORDS, 0, 52525 + CLR CH%WBF(H) + MOV #-1,CH%WBF(H) ;TO HOST -1, WHICH IS NON-EXISTENT +CHSBK7: TST CH%XMT(H) ;INITIATE TRANSMISSION, DON'T ENABLE INTERRUPT +CHSBK5: BIC #%CATEN,(H) ;GO IDLE, CLEAR TRANSMIT INTERRUPT ENABLE +;HERE TO EXIT FROM CHAOS INTERRUPT. RESTORE REGS AND RETURN FROM INT +CHSBKX: POP + RTI + +.IIF NZ CH%WBF-CH%MYN, .ERR FOO CODE ASSUMES CH%WBF = CH%MYN + +;BROADCAST A PACKET FULL OF ROUTING INFO, SINCE WE ARE MORE OR LESS A GATEWAY +CHORUT: MASK 6 ;INHIBIT CLOCK INTERRUPTS SO COSTS DON'T CHANGE + ADD #CH%WBF,H ;ADDRESS WRITE BUFFER + MOV #%CORUT*400,(H) ;OPCODE + MOV #2*,A ;COUNT SUBNETS WHICH WE KNOW ANYTHING ABOUT (REASONABLE COST) + CLR B +5$: CMP SBNCST(A),#1000 + BHIS 6$ + ADD #4,B ;THIS ONE WILL GENERATE 2 WORDS +6$: SUB #2,A + BPL 5$ + MOV B,(H) ;BYTE COUNT + CLR (H) ;DESTINATION + CLR (H) ;.. + MOV (H),(H) ;SOURCE = CH%MYN + CLR (H) ;SOURCE INDEX + CLR (H) ;PACKET NUMBER + CLR (H) ;ACK NUMBER + MOV #2*,A ;GO THROUGH SUBNET TABLES + MOVB 1(H),C ;GET SUBNET THIS IS GOING OUT ON + ASL C + MOV SBNCST(C),C ;GET COST OF GETTING TO US FROM GUY WHO RECEIVES THIS +10$: CMP SBNCST(A),#1000 ;WAS THIS ONE INCLUDED IN BYTE COUNT? + BHIS 11$ ;NO, DON'T PUT IT IN PACKET + MOV A,B ;FIRST WORD IS SUBNET NUMBER + ASR B + MOV B,(H) + MOV SBNCST(A),B ;SECOND WORD IS COST + ADD C,B ;WHICH MUST INCLUDE COST OF GETTING TO US + MOV B,(H) +11$: SUB #2,A ;NEXT SUBNET + BPL 10$ + CLR (H) ;BROADCAST THIS PACKET + SUB #CH%WBF,H ;RESTORE H + CLR CHXRTF(I) ;CLEAR REQUEST FOR ROUTING PACKET + UNMASK + BR CHSBK7 ;FIRE IT OFF, DON'T ENABLE TRANSMIT-DONE INTERRUPT + +;INITIATE TRANSMISSION ON CHAOS INTERFACE +;CALL WITH SINK NUMBER IN I, AT PI LEVEL OR MASKED. BASHES ALL REGS. +CHSXMT: INC CHOSTS(I) ;SET CHOSTS TO 1, TRANSMIT STARTING +CHSXM0: MOV CHOHWR(I),H ;GET HARDWARE ADDRESS + MOV CHOINX(I),B ;GET SOURCE SUPPLYING THE PACKET + MOV CHIBFP(B),D ;GET PACKET ADDRESS + ADD #CH%WBF,H ;ADDRESS THE WRITE BUFFER + MOV CHILNG(B),C ;GET WORD COUNT + CALL MOVDH ;COPY INTO HARDWARE + MOV CHICBA(B),(H) ;STORE CABLE DESTINATION + SUB #CH%WBF,H ;RESTORE H + TST CH%XMT(H) ;TRIGGER TRANSMISSION + BIS #%CATEN,(H) ;ENABLE DONE INTERRUPT + RET ;PI LEVEL WILL PICK UP OUTPUT + +.ENDC ;CHAOSP + +.IFNZ ETHERP + .SBTTL ETHERNET SUPPORT + +;ENABLE NEXT ETHERNET PACKET TO COME IN. +;SINCE WE ONLY HAVE ONE BUFFER, THIS SETS UP THE TRANSFER RATHER +;THAN JUST ENABLING THE INTERRUPT AS THE CHAOSNET DOES. +;THAT WOULDN'T WORK ANYWAY, BECAUSE THE HARDWARE IS SO TOTALLY BRAIN-DAMAGED. +ETHRFL: MOV CHIHWR(I),H + ADD #10,H + MOV #-,(H)+ ;- WORD COUNT, +1 FOR HARDWARE BUG + MOV #ETHIBF+,(H)+ ;BUFFER ADDRESS + MOV #101,(H) ;START, INTERRUPT-ENABLE + RET + +;INCOMING PUP TOO BIG. WE DON'T HAVE FRAGMENTATION, SO SEND A PUP ERROR REPORT +ETHBIG: MOV #ETHIBF+PKDAT,A ;COPY PUP HEADER INTO DATA FIELD + MOV A,C + MOV #ETHIBF+PKDAT+20.,B + .IREPT 10.,< MOV (A)+,(B)+ > + MOV #517.,(B)+ ;PACKET TOO LARGE ERROR + MOV #DATMAX,(B)+ ;MAX NUMBER OF BYTES ALLOWED + MOV #50$,A +5$: MOVB (A)+,(B)+ ;ASCII MESSAGE + BNE 5$ + INC B ;MESSAGE LENGTH IS EVEN. INCLUDE CHECKSUM IN COUNT. + SUB #ETHIBF+PKDAT,B ;GET PUP LENGTH + MOV B,(C)+ ;BUILD PUP HEADER NOW + MOV #4,(C)+ ;PUP TYPE = ERROR + CMP (C)+,(C)+ ;PUP ID SAME + .IREPT 3,< MOV 6(C),(C)+ > ;DESTINATION = ORIGINAL SOURCE + MOV #,(C)+ ;SOURCE = ME + .IREPT 2,< CLR (C)+ > ;SOURCE PORT ZERO + CALL ETHOUT ;TRANSMIT + JMP ETHINX ;DISMISS + +;The ascii message. This isn't as destroyed as it looks. +50$: .ASCIZ/UP Pot oalgr eotf tii n ahCoanstep caek.t/ + .EVEN + +;INPUT INTERRUPT +ETHIBK: PUSH + MOV #CHXETH,I + MOV CHIHWR(I),H + MOV 14(H),A ;PICK UP STATUS + CLR 14(H) ;CLEAR RECEIVE INTERRUPT ENABLE + CMP ETHIBF+PKDAT-2,#1000 ;TYPE = PUP? + BNE ETHIIX ;NO, IGNORE PACKET + TST 10(H) ;CHECK RESIDUAL WORD COUNT + BEQ ETHBIG ;PACKET TOO BIG, RESPOND WITH PUP ERROR + TST A ;CHECK COMBINED INPUT ERRORS BIT + BMI 70$ ;ERROR, IGNORE PACKET + MOV ETHIBF+PKDAT+10,A ;GET DESTINATION HOST + BEQ 5$ ;AND SEE IF BROADCAST OR SELF + CMP A,# + BNE 11$ ;NO, ROUTE AS REGULAR MESSAGE +5$: CMPB ETHIBF+PKDAT+2,#1 ;PUP TYPE = ECHO-ME? + BEQ ETHECO ;YES, ECHO IT (MAYBE TAKE THIS OUT AFTER 11 DEBUGGED) + CMPB ETHIBF+PKDAT+2,#200 ;GATEWAY INFORMATION REQUEST? + BNE 10$ + TST ETHIBF+PKDAT+12 ;NOT REALLY UNLESS DESTINATION SOCKET IS 2 + BNE 10$ + CMP ETHIBF+PKDAT+14,#2 + BNE 10$ + TST CHISTS+CHXEGT ;PSEUDO DEVICE AVAILABLE? + BNE ETHIIX + MOV #ETHIBF+PKDAT+4,A ;YES, SEND HIM SOME INFO + MOV #EGTPID,B + .IREPT 2,< MOV (A)+,(B)+ > ;COPY PUP ID + ADD #6,A ;COPY SOURCE HOST AND SOCKET INTO DESTINATION + .IREPT 3,< MOV (A)+,(B)+ > + CALL ETHRT1 + MOV #CHXETH,I ;I CLOBBERED BY ETHRT1 + BR ETHIIX + +10$: TST A ;DON'T HARASS REST OF NET WITH BROADCASTS + BEQ ETHIIX +11$: MOV #ETHIBF+PKDAT,A ;CHECK THE CHECKSUM + CALL PUPCKT + BNE 60$ ;BAD, COUNT AS RAM ERROR +.IF DF NDVRBF + CMP ETHIBF+PKDAT+10,DVRHST ;SEE IF ADDRESSED TO DOVER USER + BNE 12$ + CMP ETHIBF+PKDAT+14,DVRIDX + BNE 12$ + CALL DVRPUP ;YES, PROCESS + MOV #CHXETH,I + BR ETHIIX + +.ENDC ;NDVRBF +;TRANSLATE PUP AND SEND TO CHAOSNET +12$: MOV #ETHIBF,A ;FILL IN CHAOSNET HEADER + MOV #<%COUNC*400>,(A)+ ;PKOP + MOV ETHIBF+PKDAT+0,B ;PKNBYT (TOTAL PUP LENGTH = CHAOS DATA LENGTH) + INC B ;ROUND UP TO AN EVEN NUMBER + ASR B + ASL B + MOV B,(A)+ + MOV ETHIBF+PKDAT+10,(A)+ ;PKDHST + MOV ETHIBF+PKDAT+14,(A)+ ;PKDIND (LOW HALF OF PUP PORT) + MOV ETHIBF+PKDAT+16,(A)+ ;PKSHST + MOV ETHIBF+PKDAT+22,(A)+ ;PKDIND (LOW HALF OF PUP PORT) + MOV ETHIBF+PKDAT+6,(A)+ ;PKPKN (LOW HALF OF PUP ID) + MOV #100001,(A)+ ;PKACN = PROTOCOL NUMBER + CALL CHSIHD ;PROCESS THIS HEADER, GET LENGTH, DEST + BVS ETHIIX ;IGNORE IF NO GOOD + CALL SWAB10 ;SWAB IF NOT GOING TO 10-COMPATIBLE DEST + INC CHISTS(I) ;INDICATE BUFFER READY TO SEND + CALL CHSOUT ;SEND IT OUT + BR ETHINX ;ETHRFL WILL BE CALLED WHEN NECESSARY + +60$: ADD #1,NPKSRL-CHXCHS(I) ;COUNT ERRORS (SOFTWARE CHECKSUM) + ADC HPKSRL-CHXCHS(I) + BR ETHIIX + +70$: ADD #1,NPKSGB-CHXCHS(I) ;COUNT ERRORS (HARDWARE CHECKSUM) + ADC HPKSGB-CHXCHS(I) +ETHIIX: CALL ETHRFL ;AND READ ANOTHER PACKET +ETHINX: POP + RTI + +;ETHERNET PUP ECHO PROTOCOL +ETHECO: MOV #ETHIBF+PKDAT+10,A ;INTERCHANGE SOURCE AND DESTINATION + MOV A,B ;I DON'T BOTHER CHECKING CHECKSUM, BUT I DO GENERATE IT + .IREPT 3, PUSH (A)+ + .IREPT 3,< MOV (A)+,(B)+ > + .IREPT 3, POP -(A) + MOV #,(A) ;FIX SOURCE TO BE ME + INCB ETHIBF+PKDAT+2 ;SET PUP TYPE = 2 (I AM AN ECHO) + CALL ETHOUT ;SEND BACK OUT ON THE ETHERNET + BR ETHINX + +;GENERAL PURPOSE ROUTINE FOR TRANSMITTING INTERNALLY-GENERATED PUPS TO +;THE ETHERNET. FIXES THE DESTINATION ADDRESS (THIS IS HOW OTHER +;HOSTS FIGURE OUT WHAT SUBNET THEY ARE ON!), COMPUTES THE PUP CHECKSUM, +;AND INTERFACES TO THE PACKET SWITCH. CALLED WITH SOURCE INDEX IN I. +;CALL THIS WITH A PACKET THAT ALREADY HAS ITS BYTES IN ETHERNET ORDER. +;BASHES ALL REGISTERS. +ETHOUT: MOV CHIBFP(I),A + ADD #PKDAT,A ;ADDRESS OF PUP + TST 10(A) ;ONLY IF NOT BROADCASTING, + BEQ 10$ + TSTB 11(A) ;DESTINATION ADDRESS HAVE NETWORK NUMBER? + BNE 10$ + MOVB #ETHSBN,11(A) ;NO, PUT IT IN +10$: CALL PUPCKS ;INSERT CHECKSUM + MOV #CHXETH,B + MOV B,CHIOUX(I) + INC CHISTS(I) + JMP CHSOUT + +;INITIATE TRANSMISSION ON ETHER INTERFACE +;CALL WITH SINK NUMBER IN I, AT PI LEVEL OR MASKED. BASHES ALL REGS. +;PACKET IS ALREADY SWABBED INTO ETHERNET BYTE ORDER (REVERSE OF CHAOSNET). +ETHXMT: INC CHOSTS(I) ;SET CHOSTS TO 1, TRANSMIT STARTING + CLR A ;NO OUTPUT START DELAY +ETHXM0: MOV CHOHWR(I),H ;GET HARDWARE ADDRESS + MOV CHOINX(I),B ;GET SOURCE SUPPLYING THE PACKET + MOV CHIBFP(B),D ;GET PACKET ADDRESS + ADD #PKDAT,D ;GET PUP ADDRESS + MOV #1000,-(D) ;SMASH LAST 2 WORDS OF CHAOS HEADER. TYPE=PUP + MOV #ETHHSN,-(D) ;STORE SOURCE ADDRESS + MOVB 14(D),1(D) ;STORE DESTINATION ADDRESS + MOV 4(D),B ;GET PUP SIZE IN BYTES + ADD #5,B ;CONVERT TO WORDS, ALLOW FOR ETHERNET HEADER + ASR B + NEG B ;HARDWARE WANTS IT NEGATIVE + MOV B,(H)+ ;OUTPUT WORD COUNT + MOV D,(H)+ ;OUTPUT BUFFER ADDRESS + MOV A,2(H) ;OUTPUT START DELAY + MOV #101,(H) ;START OUTPUT, ENABLE INTERRUPT + RET ;PI LEVEL WILL FINISH + +;OUTPUT DONE/ABORTED INTERRUPT +ETHOBK: PUSH + MOV #CHXETH,I + MOV CHOHWR(I),H + MOV 4(H),A ;PICK UP STATUS BEFORE WRITING IT + CLR 4(H) ;CLEAR INTERRUPT ENABLE + TST A ;CHECK FOR ERROR + BPL 10$ + ADD #1,NPKSAB-CHXCHS(I) + ADC HPKSAB-CHXCHS(I) + NEG CHOSTS(I) ;ERROR, ENTER RETRANSMIT MODE + BPL 10$ ;ALREADY RETRANSMITTED ONCE, PUNT + MOV #25.,A ;WAIT 1 MS (DON'T BOTHER BEING RANDOM) + CALL ETHXM0 ;START TRANSMISSION AGAIN + BR ETHINX ;AND EXIT + +10$: CALL CHSODN ;TRANSMISSION FINISHED + CALL CHSRUN ;FIND MORE WORK TO DO + BR ETHINX ;DISMISS + +;CHECKSUM PUP ADDRESSED BY A. BASHES A,B,C. +PUPCKS: CALL PUPCK1 ;COMPUTE CHECKSUM + MOV B,(A) ;STORE CHECKSUM + RET + +;RETURN 'EQ' IF CHECKSUM MATCHES +PUPCKT: CALL PUPCK1 ;COMPUTE CHECKSUM + CMP (A),#-1 ;PACKET CHECKSUMMED? + BEQ 5$ ;NO, ALWAYS MATCH + CMP B,(A) ;RETURN WITH CC SET FROM NEW AND OLD CKSMS +5$: RET + +;A POINTS AT PACKET, RETURN WITH A -> CHECKSUM AND CHECKSUM IN B. BASH C. +PUPCK1: MOV (A),C ;GET LENGTH + DEC C ;IN WORDS NOT COUNTING CHECKSUM + ASR C + CLR B ;BUILD CHECKSUM IN B +10$: ADD (A)+,B ;ONE'S COMPLEMENT ADD + ADC B + BPL 11$ ;TRANSFER SIGN BIT INTO CARRY + SEC +11$: ROL B ;AND LEFT CYCLE + SOB C,10$ + INC B ;GRONK MINUS ZERO + BEQ 15$ + DEC B +15$: RET + +;BROADCAST ETHERNET GATEWAY INFO +ETHRUT: MASK 5 ;ENTER SUITABLE LEVEL FOR HACKING NET + TST CHISTS+CHXEGT ;IS THE PSEUDO SOURCE THAT EMITS THE + BNE 99$ ; PACKET AVAILABLE? IF NOT, PUNT. + CLR CHXRTF+CHXETH ;CLEAR REQUEST FLAG + MOV #EGTPID,A + CLR (A)+ ;PUP ID ZERO + CLR (A)+ + CLR (A)+ ;BROADCAST DESTINATION + CLR (A)+ ;TO SOCKET 2 + MOV #2,(A)+ + CALL ETHRT1 ;BUILD AND SEND GATEWAY INFO +99$: UNMASK + RET + +BADSBP: .WORD BADSUB ;POINTER INTO BAD SUBNETS +BADSUB: ;SUBNETS THAT SHOULD NOT HAVE INFORMATION SENT + ;ABOUT. THIS LIST MUST BE IN INCREASING ORDER + ;AND MUST END IN 377. + .BYTE 004 ;AI CHAOS 11 pseudo subnet (only AI PDP-10 (RIP) is on this) + .BYTE 010 ;Tech Square LCSnet (unused) + .BYTE 011 ;Tech Square LCS asynchronous line net (IP) + .BYTE 012 ;Tech Square VII LCSnet (IP) + .BYTE 014 ;Symbolics: Los Angeles-Chatsworth land line + .BYTE 020 ;CHAOS MIT IN subnet (ask JNC) + .BYTE 027 ;Experimental asynchronous line net + .BYTE 030 ;Experimental radio broadcast net + .BYTE 040 ;Symbolics: Tech Square-Vassar St. microwave link + .BYTE 041 ;Symbolics: Cambridge-Palo Alto land line + .BYTE 042 ;Symbolics: Palo Alto-Chatsworth land line + .BYTE 047 ;Symbolics: Cambridge-Chatsworth land line + .BYTE 054 ;S-1: 10Mb Ethernet + .BYTE 055 ;S-1: Pronet ring + .BYTE 056 ;S-1: serial line subnet + .BYTE 057 ;S-1: serial line subnet + .BYTE 061 ;Symbolics: Cambridge-Cambridge land line + .BYTE 062 ;Symbolics: Cambridge-Washington land line + .BYTE 064 ;Symbolics: Cambridge-Houston land line + .BYTE 070 ;Symbolics: Chatsworth-Westwood land line + .BYTE 072 ;Atari: Cambridge-MIT land line + .BYTE 073 ;Atari: Cambridge-Sunnyvale land line + .REPT 8 + .BYTE 377 ;SPARES + .ENDR + .BYTE 377 +.EVEN + +ETHRT1: MOV #BADSUB,BADSBP ;INITIAL BAD SUBNET POINTER + MOV #EGTSBN,A ;FILL IN GATEWAY INFORMATION IN THE PUP + CLR I ;I SUBNET*2, A EGTSBN POINTER +10$: ;; FOR EACH SUBNET, .BYTE GATE-NET, TARGET-NET, HOP-COUNT, GATE-HOST + CLR B ;FOR NON-GATEWAY, USE 0 AS GATEWAY ADDRESS + TST SBNTYP(I) ;HARDWARE CONNECTION? + BGT 11$ + MOV SBNADR(I),B ;NO, GET GATEWAY ADDRESS +11$: cmpb i,#60 + bhi 20$ ;dover, as of 1-Dec-83 can't handle more than 60 + ;; FILTER OUT KNOWN BAD SUBNETS + CMPB I,@BADSBP ;MAYBE UPDATE POINTER + BHI 115$ ; NO UPDATE NEEDED + INC BADSBP +115$: CMPB I,@BADSBP ;THIS TIME, CHECK FOR EQUALITY + BEQ 20$ ;PUNT + ;; END FILTER + MOV SBNCST(I),C ;GET COST + CMP C,#1000 ;IF NOT REACHABLE, DON'T PUT IN PACKET + BHIS 20$ + .IREPT 3, ASR C ;DIVIDE BY 8 TO GET APPROXIMATE HOP COUNT + CMP C,#ETHMXH ;DON'T PUT MORE THAN MAXHOPS + BLOS 12$ + MOV #ETHMXH,C +12$: MOV I,D ;GET TARGET-NET + ASR D + SWAB B + MOVB B,(A)+ ;STORE IN WIERD XEROX BYTE ORDER + MOVB D,(A)+ + MOV B,(A)+ + MOVB C,-2(A) +20$: TST (I)+ ;NEXT SUBNET + CMP I,#NSUBNT*2 + BLO 10$ + SUB #EGTSBN,A ;NUMBER OF DATA BYTES IN PUP + ADD #22.,A ;FOR HEADER AND CHECKSUM + MOV A,EGTPLN ;SET PUP LENGTH + MOV #CHXEGT,I ;SET UP TO TRANSMIT TO ETHERNET + JMP ETHOUT +.ENDC ;ETHERP + +.IF DF NDVRBF + .SBTTL DOVER PROTOCOL TRANSLATOR + +;RFC PACKET IN A. MUST PRESERVE I, AND RETURN 'EQ'. +DVROPN: MOV PKPKN(A),C + MOV PKSIND(A),B + MOV PKSHST(A),A + PUSH I + CALL 5$ + POP I + SEZ + RET + +;SET UP DOVER TO TALK TO HOST IN A, INDEX IN B, PKT# IN C, SENDING BACK AN OPN +;OR SENDING A LOS IF BUSY. MUST WATCH FOR DUPLICATE RFC'S +;MUST BE CALLED WITH CHAOS AND ETHER INTERRUPTS MASKED +5$: TST DVRHST ;BUSY? + BEQ 10$ ;NO + CMP A,DVRHST + BNE DVRBSY ;YES, TALKING TO ANOTHER HOST + CMP B,DVRIDX + BNE DVRBSY ;YES, TALKING TO ANOTHER GUY SAME HOST + BR 11$ ;DUPLICATE RFC + +10$: CLR DVRTIM ;FLUSH TIMEOUT + MOV A,DVRHST + MOV B,DVRIDX + INC DVRLIX ;ESTABLISH UNIQUE LOCAL INDEX + BNE 11$ + INC DVRLIX ;DON'T USE 0 +11$: CLR DVRMSK ;CLEAR THE BUFFER RING + CLR DVRID ;FIRST PACKET TO SEND TO DOVER IS PACKET 0 + INC C ;C := FIRST PACKET ID THAT WILL COME IN FROM CHAOS + MOV C,DVROFS + MOV #%COOPN*400,B ;SEND AN OPN + BR DVRST1 ;REST IS LIKE STS + +DVRBSY: TST DVRPKP ;SPECIAL BUFFER BUSY? + BNE CPOPJ0 ;YES, PUNT + MOV #DVRBF2,C ;SEND A CLS + MOV #%COCLS*400,(C)+ + MOV #4,(C)+ + MOV A,(C)+ + MOV B,(C)+ + MOV #CHADD,(C)+ + CLR (C)+ + CLR (C)+ + CLR (C)+ + MOV #"BU,(C)+ + MOV #"SY,(C)+ + MOV #DVRBF2,DVRPKP + BR DVRRFL + +;HERE TO SEND STS TO GUY CONNECTED TO DOVER +;MUST BE MASKED AGAINST CHAOS INTERRUPTS +DVRSTS: MOV #%COSTS*400,B +DVRST1: MOV #DVRBF2,A ;USE THIS BUFFER + MOV #4,D ;NUMBER OF BYTES +DVRST2: MOV A,C + MOV B,(A)+ ;OPCODE + MOV D,(A)+ ;NUMBER OF BYTES + MOV DVRHST,(A)+ ;DESTINATION HOST + MOV DVRIDX,(A)+ ;DESTINATION INDEX + MOV #CHADD,(A)+ ;SOURCE HOST + MOV DVRLIX,(A)+ ;SOURCE INDEX + CLR (A)+ ;NO PACKET NUMBER + CMP B,#%COLOS*400 ;IF SENDING LOS, PUNT THE REST + BEQ 20$ + MOV DVRID,B + DEC B ;LAST PACKET ACKNOWLEDGED BY DOVER + ADD DVROFS,B ;CONVERT TO CHAOSNET ID + MOV B,(A)+ ;ACKNOWLEDGE PACKET NUMBER + MOV B,(A)+ ;RECEIPT + MOV #NDVRBF,(A)+ ;WINDOW SIZE +20$: MOV C,DVRPKP ;CAUSE PACKET TO GET SENT + ;DROP INTO DVRRFL + +;HERE TO GET ANOTHER PACKET FROM THE DOVER. THIS CAN BE EITHER A CHAOSNET +;PACKET TO BE SENT BACK TO THE APPROPRIATE GUY, OR A PUP TO GO TO THE DOVER +DVRRFL: MOV #CHXDVR,I ;THIS MIGHT NOT BE SET UP WHEN CALLED + TST CHISTS(I) ;PACKET SOURCE ONLY EMANATES ONE AT A TIME + BNE CPOPJ0 + CMP CHIBFP(I),DVRPKP ;FINISHED SENDING SPECIAL PACKET? + BNE 10$ + CLR DVRPKP ;YES, MAKE READY FOR ANOTHER +10$: CLR CHIBFP(I) ;THIS PACKET NO LONGER BEING SENT + MOV DVRPKP,A ;GOT SPECIAL PACKET TO SEND? + BNE 30$ ;YES, SEND IT + TST DVRMSK ;GOT NEXT BUFFER TO SEND TO DOVER? + BPL CPOPJ0 ;NO + CMP DVRRTR,#60. ;1-SECOND RETRANSMISSION INTERVAL ELAPSED? + BLO CPOPJ0 ;NO, DON'T SEND YET + CLR DVRRTR ;SENDING, RESET RETRANSMISSION TIMER + MOV DVRBFP,A + BIC #PKFCMS,PKFC(A) ;CLEAR FORWARDING COUNT SINCE SENDING AGAIN +30$: MOV A,CHIBFP(I) ;SEND THIS PACKET + CALL CHSIHD ;ROUTE HIM + BVS DVRRFL ;BAD, IGNORE + CMP B,#CHXCHS ;SWAB IF SENDING TO 10, BUT NOT ETHERNET + BHIS 35$ + CALL CHSSWB +35$: INC CHISTS(I) ;INDICATE BUFFER READY TO SEND + RET + +;CALLED WITH A PUP IN ETHIBF WHICH IS FROM THE DOVER AND ADDRESSED +;TO THE GUY WHO'S TRYING TO PRINT ON IT. MUST BE MASKED AGAINST ETHER & CHAOS INTERRUPTS. +DVRPUP: MOVB ETHIBF+PKDAT+2,B + CMP B,#31 ;EFTP ACKNOWLEDGE? + BNE DVRPP1 + CMP ETHIBF+PKDAT+6,DVRID ;ACKNOWLEDGING EXPECTED PACKET? + BNE CPOPJ0 ;NO, IGNORE IT + INC DVRID ;YES, ADVANCE ID, POINTER, AND PACKET-PRESENCE MASK + MOV DVRBFP,A + ADD #DVRBFL,A + CMP A,#DVRBF2 + BLO 11$ + MOV #DVRBUF,A +11$: MOV A,DVRBFP + ASL DVRMSK + SETOM DVRRTR ;FAKE RETRANSMIT TIMER TO SEND NEXT PUP RIGHT AWAY + TST CHISTS+CHXDVR ;PACKET SOURCE BUSY? + BEQ DVRSTS ;NO, SEND AN ACKNOWLEDGEMENT TO THE CHAOSNET +CPOPJ0: RET + +DVRPP1: MOV #22.,A ;RELATIVE ADDRESS OF ASCII STRING + CMP B,#33 ;EFTP ABORT? + BEQ DVRERR + MOV #44.,A ;RELATIVE ADDRESS OF ASCII STRING + CMP B,#4 ;PUP ERROR? + BNE CPOPJ0 ;IGNORE ANYTHING ELSE +DVRERR: CLR DVRMSK ;DON'T SEND ANYTHING MORE TO THE DOVER + MOV ETHIBF+PKDAT,C ;PUP LENGTH + SUB A,C + SUB #2,C ;GET LENGTH OF ASCII STRING + ADD #ETHIBF+PKDAT,A ;GET ADDRESS OF ASCII STRING + MOV #DVRBUF+PKDAT,B ;BUILD A LOS PACKET TO SEND BACK + MOV C,D ;SAVE BYTE LENGTH + INC C + ASR C ;WORD COUNT + BEQ 11$ +10$: MOV (A)+,(B) + SWAB (B)+ ;ALTO HAS BYTES IN THE WRONG ORDER + SOB C,10$ +11$: MOV #%COLOS*400,B ;SEND A LOS + MOV #DVRBUF,A + CALL DVRST2 + CLR DVRHST ;KILL CONNECTION + RET + +;HERE IS A PACKET DIRECTED TO THE DOVER. DO GOOD THINGS WITH IT. +;NOTE, IT HAS ALREADY BEEN SWABBED INTO ETHERNET BYTE ORDER. +DVRPKT: MOV CHOINX(I),B ;GET SOURCE SUPPLYING THE PACKET + MOV CHIBFP(B),A ;GET ADDRESS OF PACKET + CLR DVRTIM ;FOREIGN HOST IS NOT IDLE + MOVB PKOP(A),B ;DATA PACKET? + BMI 50$ ;YES + CMP B,#%COSNS + BNE 11$ + TST CHISTS+CHXDVR + BNE 90$ + CALL DVRSTS ;SNS => STS + BR 90$ + +11$: CMP B,#%COCLS + BEQ 12$ ;CLS OR LOS PUNTS THE CONNECTION + CMP B,#%COLOS + BNE 13$ +12$: CLR DVRHST + BR 90$ + +13$: CMP B,#%COEOF ;NOTE THAT EOF IS TREATED VERY MUCH LIKE DATA! + BNE 90$ ;IGNORE ANYTHING RANDOM +50$: MOV PKPKN(A),B ;GET ID OF DATA PACKET + SUB DVROFS,B + MOV DVRBFP,D ;FIND WHERE IN THE BUFFER IT GOES + MOV #100000,C ;AND GET MASK BIT FOR IT + SUB DVRID,B ;B := ID RELATIVE TO NEXT EXPECTED + BEQ 53$ + CMP B,#NDVRBF + BHIS 90$ ;IGNORE DUPLICATE OR NOT IN WINDOW +51$: ADD #DVRBFL,D + CMP D,#DVRBF2 + BLO 52$ + MOV #DVRBUF,D +52$: CLC + ROR C + SOB B,51$ +53$: BIT C,DVRMSK ;ALREADY HAVE PACKET? + BNE 90$ ;YES, IGNORE + BIS C,DVRMSK ;NO, STORE IT AWAY + MOV D,C + ADD #PKDAT,D ;BUILD PUP + MOV PKNBYT(A),B + BIC #PKNBMS,B + MOV B,(D) + ADD #22.,(D)+ ;PUP LENGTH + MOV #30,(D)+ ;PUP TYPE + TST (A) ;WAS THIS DATA OR EOF? + BMI 54$ ;DATA + SUB (PC),-2(D) ;EOF, SET PUP TYPE TO 32 +54$: CLR (D)+ ;PUP ID HIGH + MOV PKPKN(A),(D) ;PUP ID LOW + SUB DVROFS,(D)+ ; CORRECTED + MOV #DVRADR,(D)+ ;DESTINATION HOST + CLR (D)+ ;DESTINATION SOCKET HIGH + MOV #20,(D)+ ;DESTINATION SOCKET LOW + MOV DVRHST,(D)+ ;SOURCE HOST + CLR (D)+ ;SOURCE SOCKET HIGH + MOV DVRIDX,(D)+ ;SOURCE SOCKET LOW + ADD #PKDAT,A + INC B + ASR B ;NUMBER OF DATA WORDS +;*** TEMPORARY KLUDGE *** + PUSH ;PUSH B LAST!! +;*** END TEMPORARY KLUDGE *** + BEQ 56$ +55$: MOV (A)+,(D)+ ;MOVE THE DATA + SOB B,55$ +56$: MOV C,A + ADD #PKDAT,A + MOV #<%COUNC*400>,(C) ;PKOP + MOV 10(A),PKDHST(C) + MOV (A),PKNBYT(C) ;SHOULD BE ENOUGH TO GET IT ROUTED TO ETHERNET + CALL PUPCKS ;STORE APPROPRIATE CHECKSUM +;*** TEMPORARY KLUDGE *** + POP ;LOOK FOR SOME KIND OF MACHINE FAILURE + TST B + BEQ 79$ +70$: CMP (D)+,(A)+ + BNE 75$ + SOB B,70$ + BR 79$ + +75$: DVRFKT=. + NOP ;PUT A BPT HERE IF YOU LIKE + INC NDVRFK + CLR DVRMSK ;DO IT ALL OVER AGAIN +79$: +;*** END TEMPORARY KLUDGE *** + CALL DVRRFL ;SEND THIS PACKET MAYBE +90$: MOV #CHXDVR,I + JMP CHSODN ;THIS PACKET HANDLED +.ENDC ;NDVRBF + .IFNZ DL10P + .SBTTL TRAP HANDLING + +TRAP14: HALT ;BPT WITH NO RUG IN CORE + +TRAP10: BPT ;ILLEGAL INSTRUCTION + +TRAP4: NOP ;PATCH BPT HERE IF YOU WANT + CMP (SP),#MAIN ;IF TRAP4 IN MAIN LOOP... + BLO CRASH + CMP (SP),#MAINE + BHIS CRASH + BIT #DLXPRT,DLXCSR ;AND DL10 PORT TURNED OFF + BNE CRASH + TST DLXOFF ;AND WE THOUGHT IT WAS ON + BNE CRASH +RESTRT: MOV #STKBAS,SP ;THEN RESTART MAIN LOOP + CLR -(SP) ;WHICH WILL WAIT FOR DL10 PORT TO TURN ON + MOV #MAIN,-(SP) + RTI + +CRASH: BPT ;OTHERWISE, CRASH + +PWRFAL: RESET ;POWER FAIL OR UP - IF FAIL, HALT DURING RESET + MOV #20,B ;WAIT 2 SECONDS TO +1$: CLR A ; MAKE SURE POWER IS REALLY ON + SOB A,. + SOB B,1$ + JMP INIT ;POWER SEEMS UP, RESTART PROGRAM +.ENDC ;DL10P + +.IFNZ NODDT ;IF NO DDT OR OTHER "OPERATING SYSTEM", SET UP TRAP HANDLERS +TRAP4: + .=4 + .WORD TRAP4,340,TRAP10,340,TRAP14,340,TRAP10,340,PWRFAL,340,TRAP10,340,TRAP10,340 + .=TRAP4 + +;ILLEGAL ADDRESS, UNIBUS NXM, STACK OVERFLOW +TRAP4: BPT + 0 + +;ILLEGAL INSTRUCTION, IOT, EMT +TRAP10: BPT + 0 + +;POWER FAILURE OR RESTORE +PWRFAL: HALT + 0 + +;BPT (OR TRACE) +TRAP14: .REPT 7 ;SAVE REGISTERS WHERE CARPET CAN FIND THEM + MOV %0+.RPCNT,BPTACS+<.RPCNT*2> + .ENDR + CLR BPTGO + SETOM BPTFLG +5$: TST BPTGO + BEQ 5$ + CLR BPTFLG + .REPT 7 + MOV BPTACS+<.RPCNT*2>,%0+.RPCNT + .ENDR + RTI + +BPTFLG: 0 ;NON-ZERO IF GOT A BPT +BPTGO: 0 ;NON-ZERO TO PROCEED +BPTACS: .BLKW 7 ;REGS EXCEPT PC + +.ENDC ;NODDT + + .SBTTL INITIALIZATION +GO:: +INIT: CLR PS +.IFNZ DL10P + RESET + MOV #STKBAS,SP + TST 14 + BNE 1$ ;BPT ALREADY SET UP BY RUG + MOV #TRAP14,14 + MOV #340,16 +1$: +.ENDC ;DL10P +.IFNZ NODDT ;NO OPERATING SYSTEM + RESET + MOV #STKBAS,SP +.ENDC ;NODDT + SETOM DLXOFF ;REINITIALIZE VARIOUS VARIABLES + SETOM NO.ITS +.REPT CHAOSP ;IDLE CHAOS NET INTERFACES + CLR CHISTS+CHXCHS+<2*.RPCNT> + CLR CHOSTS+CHXCHS+<2*.RPCNT> +.ENDR +.IIF NZ T300P, CLR RQBACT +.IFNZ NCT + MOV #NFTTY,I +76$: MOV NRMIPC(I),TTYIPC(I) + ADD #2,I + CMP I,#LASTTY + BLE 76$ + MOV #TYORNG,B ;CLEAR THE TYPOUT-DONE RING + CALL CLRING + MOV #,A ;GIVE OUTPUT DONE ON ALL LINES +78$: CALL PUT + INC A + CMP A,#+NCT + BLO 78$ +.ENDC ;NCT +.IFNZ NDMS +;;; Turn on DM11-BBs + CLR B ;iterated over DM11 units + MOV #NDMS,H +5$: MOV #DMCLR+DMCSN,@DMCSR(B) ;CLEAR SCANNER MEMORY +2$: BIT #DMBSY,@DMCSR(B) + BNE 2$ + CLR I ;iterated over modem channels + ;; turn on connected modem channels for one DM11 + CLR A ;counter for channels per unit +3$: TST M2LMAP(I) + BEQ 4$ + MOV A,@DMCSR(B) + MOV #LINENB,@DMLSR(B) +4$: TST (I)+ + INC A + CMP A,#16. + BLT 3$ + TST (B)+ + SOB H,5$ ;next DM11 + ;; treat first-time interrupts differently + SETOM DMINI + CLR B + MOV #NDMS,A +6$: MOV #DMSCN+DMIEN,@DMCSR(B) ;enable scanner interrupts + TST (B)+ + SOB A,6$ ;on all DMs + MOV #20000.,A + SOB A,. ;DELAY 50 MILLISECONDS + CLR DMINI ;WHILE P.I. LEVEL GETS INITIAL STATUS +.ENDC ;NDMS + +.IFG NDHS +;TURN ON DH11'S + MOV #NLDHHX,H +DHINIL: MOV DHSCR(H),A ;DEVICE ADDRESS + MOV #100000,16(A) ;TURN ON SILO MAINTENANCE MODE, SUSPECTED OF + ;LOSING + MOV #4000,(A) ;RESET DH11 + MOV 16(A),B ;CHECK SILO STATUS + BIC #300,B ;THESE BITS ARE IN RAM & DON'T CLEAR + BEQ DHSWIN ;SHOULD HAVE CLEARED MAINTENANCE MODE AND OTHER CRUD +DHSLUZ: BPT ;LOSE +DHSWIN: MOV #DHRENB+DHTENB,(A) ;NOW ENABLE INTERRUPTS ON DH11 + SUB #2,H + BGE DHINIL +.ENDC ;NDHS + +;TURN ON DL11S +.IFG NDLS + MOV #NLDLHX,H + MOV #NDLS-1,A +21$: +.IIF NZ DTE20P, BEQ 22$ ;NO KBD INT ON KL10 CTY DUE TO KLDCP LOSSAGE + MOV #103,@DLKS(H) ;ACTIVATE KEYBOARD INTERRUPT, D.T.R., READER +22$: MOV #100,@DLPS(H) ;ACTIVATE PRINTER INTERRUPT + SUB #2,H + DEC A + BPL 21$ +.ENDC ;NDLS + +;SET LINE PARAMETERS AND ALLOCATE BUFFERS +.IFNZ NCT + MOV #NFTTY,I +10$: MOV LPRVAL(I),A + MOV BUFSIZ(I),B + CALL SPARAM + ADD #2,I + CMP I,#LASTTY + BLE 10$ +.ENDC ;NCT + +;TURN ON CLOCK +.IIF Z DTE20P, MOV #100,@#LKS ;NO CLOCK INTERRUPTS IF KLDCP IS HACKING CLOCK TOO + +.IFNZ DTE20P +;INITIALIZE DTE20 + MOV #37774,DLYCNT ;DMA TO BANK 0, 2 USEC DELAY + MOV #%D3BYT,DIAG3 ;DO TO10 TRANSFERS IN BYTE MODE + MOV #MAIN,SADR ;ONLY DO INIT ONCE +.ENDC ;DTE20P +.IIF NZ TEN11P, SETOM T11I10 ;CAUSE 10 TO REINITIALIZE TEN-11 CHAOS +.REPT CHAOSP + MOV CHIHWR+CHXCHS+<2*.RPCNT>,H ;ADDRESS THE INTERFACE + CONC ,\.RPCNT ;CHECK THE HOST NUMBER SWITCHES AGAINST THE PROGRAM + BEQ .+4 + BPT + BIS #%CAREN,(H) ;ENABLE CHAOS NET INPUT INT +.ENDR ;CHAOSP +.IFNZ ETHERP + MOV CHIHWR+CHXETH,H ;ADDRESS THE INTERFACE + MOV 16(H),A ;GET HOST NUMBER SWITCHES + COMB A ;FIX XEROX MISTAKE + CMPB A,#ETHHSN ;CHECK HOST NUMBER SWITCHES + BEQ .+4 + BPT + MOV #CHXETH,I ;ENABLE TO RECEIVE FIRST ETHERNET PACKET + CALL ETHRFL +.ENDC ;ETHERP +;GO + JMP MAIN + +.IFNZ GOULDP +.SBTTL GOULD PRINTER BUFFERS + +GLPOIP: GLPBFF ;NEXT BUFFER IN AT M.P. LEVEL +GLPOOP: GLPBFF ;NEXT BUFFER OUT AT P.I. LEVEL + + .REPT NGLPBF ;ASSEMBLE THE BUFFERS + 0 .SEE GB.STA + GLPBFF ;DUE TO PALX BUG, LEAVE .SEE ON NEXT LINE + .SEE GB.NXT +GLPBFF==.-4 + 0 .SEE GB.FF + 0 .SEE GB.NL + 0 .SEE GB.PNT + .BLKB GLPBSZ + .ENDR +.ENDC ;GOULDP + + .SBTTL "TTYTYP" PARAMETER FILE + +T LPRVAL: + .BLKW NCT ;DH11 PARAMETER REG + +BUFFRS: ;BEGIN ALLOCATING BUFFERS HERE + +.IIF NZ NCT, INFORM ,\BUFFRS +ZZ===+3777>/4000 ;NUMBER OF K USED +.IRP ZZZZ,<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16> +.LIF EQ ZZ-.IRPCNT ;THIS IS A CRETINOUS CROCK TO GET IT COME OUT IN DECIMAL +INFORM ,\BUFFRS+,< (>,ZZZZ, +.ENDR + +.IFNZ NCT ;TTYTYP FILE ONLY IF WE HAVE TTYS +.IF P2 ;SPEED UP THE ASSEMBLY +OFF==69105 ;KLUDGES SO I DON'T HAVE TO PUT KEYWORD PARAMETERS INTO PALX +40K==40000 +80K==80000 + +.MACRO SPEED BAUD +ZZ==-1 +.IIF EQ BAUD-OFF, ZZ==0 +.IIF EQ BAUD-50, ZZ==1 +.IIF EQ BAUD-75, ZZ==2 +.IIF EQ BAUD-110, ZZ==3 +.IIF EQ BAUD-134, ZZ==4 +.IIF EQ BAUD-150, ZZ==5 +.IIF EQ BAUD-200, ZZ==6 +.IIF EQ BAUD-300, ZZ==7 +.IIF EQ BAUD-600, ZZ==10 +.IIF EQ BAUD-1200, ZZ==11 +.IIF EQ BAUD-1800, ZZ==12 +.IIF EQ BAUD-2400, ZZ==13 +.IIF EQ BAUD-4800, ZZ==14 +.IIF EQ BAUD-9600, ZZ==15 +.IIF EQ BAUD-80K, ZZ==16 +.IIF EQ BAUD-40K, ZZ==17 +.IIF LT ZZ, .ERROR UNRECOGNIZED SPEED "BAUD" +.ENDM SPEED + +.MACRO IPARM N,ODFLT,IDFLT,MUMLST +.IF GE <2*N>-NFTTY +.IF LE <2*N>-LASTTY +%%.ISPEED==-1 +%%.SPEED==-1 +.IRP MUM, +.IF NB + ZZ==0 + .IRPC MUMB, + .IIF GE .IRPCNT-2, .MEXIT + .IIF IDN MUMB,S, .IIF EQ .IRPCNT, ZZ==1 + .IIF IDN MUMB,P, .IIF EQ .IRPCNT-1, ZZ==ZZ+1 + .IIF IDN MUMB,I, .IIF EQ .IRPCNT, ZZ==1 + .IIF IDN MUMB,S, .IIF EQ .IRPCNT-1, ZZ==ZZ+1 + .ENDM + .IIF EQ ZZ-2, %%.'MUM + .ENDC +.ENDM +.IF LT %%.ISPEED + .IIF LT %%.SPEED, %%.ISPEED==IDFLT + .IELSE %%.ISPEED==%%.SPEED +.ENDC +.IIF LT %%.SPEED, %%.SPEED==ODFLT +SPEED %%.ISPEED +IZZ==ZZ +SPEED %%.SPEED +; BUFFER SIZE IS 1/2 SECOND'S TYPING +; BUT WILL BE SUBJECT TO LIMIT OF MAXBSZ +.IIF LT ZZ-7, BZZ==5. +.IIF EQ ZZ-7, BZZ==15. +.IIF EQ ZZ-10, BZZ==30. +.IIF EQ ZZ-11, BZZ==60. +.IIF EQ ZZ-12, BZZ==90. +.IIF EQ ZZ-13, BZZ==120. +.IIF EQ ZZ-14, BZZ==240. +.IIF EQ ZZ-15, BZZ==480. +.IIF GT ZZ-15, BZZ==1000. +.=LPRVAL+<2*N> ;ASSEMBLE LINE PARAMETER WORD +.IIF NE ZZ-3, ++3 ;ISPEED, OSPEED, NO PARITY, 8 BITS, FULL DUPLEX +.IELSE ++3+4 ;110 BAUD EXTRA STOP BIT +.=BUFSIZ+<2*N> +BZZ ;ASSEMBLE BUFFER SIZE +.ENDC +.ENDC +.ENDM IPARM + +;MACROS USED IN THE TTYTYP FILE: + +.MACRO TTDPRT TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,300,300, +.ENDM TTDPRT + +.MACRO TTDMRX TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,600,600, +.ENDM TTDMRX + +.MACRO TTDTRM TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,1200,1200, +.ENDM TTDTRM + +.MACRO TTDLPT TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,9600,9600, +.ENDM TTDLPT + +.MACRO TTDLA36 TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,300,300, +.ENDM TTDLA36 + +.MACRO TTDIML TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,50K,25K, +.ENDM TTDIML + +.MACRO TTDVT TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,9600,9600, +.ENDM TTDVT + +.MACRO TTDTEK TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,1200,1200, +.ENDM TTDTEK + +.MACRO TTDLSR TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,2400,2400, +.ENDM TTDLSR + +.MACRO TTDDPT TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,2400,2400, +.ENDM TTDDPT + +.MACRO TTDGT40 TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,4800,4800, +.ENDM TTDGT40 + +.MACRO TTDRAY TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,9600,9600, +.ENDM TTDRAY + +.MACRO TTDH19 TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,9600,9600, +.ENDM TTDRAY + +.MACRO TTD11 TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,4800,4800, +.ENDM TTD11 + +.MACRO TTDRAN TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,FOO,FOO, +.ENDM TTDRAN + +.MACRO TTDTV TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,FOO,FOO, +.ENDM TTDTV + +.MACRO TTDGRN TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,9600,9600, +.ENDM TTDGRN + +.MACRO TTDSTY TN,A,B,C,D,E,F,G,H,I,J +IPARM TN,FOO,FOO, +.ENDM TTDSTY + +.MACRO REPEAT N,FOO +FAKOUT: .REPT N +FAKOUT===0 +.ENDM + +NSTTYS==0 ;WE'RE NOT INTERESTED IN PSEUDO-TTYS +N11TYS==0 ;NOR IN PDP11 TVS + +.INSRT SYSTEM;TTYTYP > + +.EXPUNGE ZZ,IZZ,IZZZ,BZZ,OFF,40K,80K,%%.ISPEED,%%.SPEED +.EXPUNGE TT,TY,TO,TP,TCT,HOR,VER,ROL,SPEED,ISPEED + +.ENDC ;P2 + +.ENDC ;NCT + +.END INIT + \ No newline at end of file diff --git a/src/system/its.1644 b/src/system/its.1644 new file mode 100755 index 00000000..a9a0c458 --- /dev/null +++ b/src/system/its.1644 @@ -0,0 +1,21930 @@ +;-*-MIDAS-*- + +.SYMTAB 12003.,5500. +TITLE ITS + +SUBTTL DEFINITIONS + +.NSTGWD .SEE PATB ;NO STORAGE WORDS ALLOWED UNTIL PATB + +IF1 [ PRINTX \MACHINE NAME = \ +;WELL-KNOWN MACHINE NAMES ARE: +; AIKA AI LAB KA10 (R.I.P.) +; MLKA MATHLAB KA10 (R.I.P.) +; DM DYNAMIC MODELING KA10 (R.I.P.) +; MC Mail Computer KS10 +; AI AI Lab KS10 +; MX The ex-MC KL10 +; ML Math Lab KS10 +; MD Mostly Development KS10 +; SI Stacken ITS KS10 +; FU Australian KS10 +; PM PandaMonium KS10 +; DX DigeX KS10 +;THE FILE "CONFIG" HAS ASSEMBLY SWITCHES AS A FUNCTION OF MACHINE. + +.TTYMAC A +IFN ASCII/A/&ASCII/ /,.FATAL USE UPPER CASE! +DEFINE MCOND X ;0 IFF THIS IS MACHINE X. +,TERMIN +DEFINE MNAME X ;USED TO SUBSTITUTE IN THIS MACHINE'S NAME. +X!!A!!TERMIN +FOO==.TTYFLG ;MAKE ERR FILE LOOK NICE +.TTYFLG==1 +PRINTX/A +/ +.TTYFLG==FOO +TERMIN ];IF1 + +IFNDEF PCLSW,PCLSW==1 ;1 => ASSEMBLE PCLSR TEST FEATURE +IFNDEF TT11BY,TT11BY==8 ;PDP11-TV OUTPUT BUFFER BYTE SIZE. +.MLLIT==1 ;MULTI-LINE LITERAL MODE +ASTIME==.OP .OPER+@,0,.RTIME ;GET ASSEMBLY TIME AND DATE IN SIXBIT. +ASDATE==.OP .OPER+@,0,.RDATE ;RH OF INSN MUST BE 0, SO MIDAS WILL PUT IN PROPER AC FLD. + +;AC DEFS + +A=1 +B=2 +C=3 +D=4 +E=5 +TT=6 +I=7 +Q=10 +J=11 +R=12 +W=13 +H=14 +P=15 ;DO NOT CHANGE! ;PDL POINTER +T=16 ;" +U=17 ;" ;USER INDEX + +.XCREF A,B,C,D,E,TT,I,Q,J,R,W,H,P,T,U + +IF1 EXPUNGE APR,OCT,DEC ;FOR NEW CALENDAR HACK + +NULBLK==4 ;NUMBER OF LOCKED SWITCH BLKS IN USR VARIABLES + ;USES 2 WDS OF USER VAR PER + +NPVSEC==30. ;NUMBER OF SECONDS A USER IS ALLOWED TO BE IN THE PRIVILEDGED SWAPPING CLASS +IF2 LIOBLK==_-10. ;LOWEST BLOCK NEVER TO BE SHUFFLED + ;ALSO MAX # OF BLOCKS SYS JOB MAY HAVE +IF2 MAXJ==/LUBLK ;ROUND UP TO ACTUAL MAX #JOBS + +DIRMAP==1 ;ENABLE DIRECT MAPPING OF HIGH HALF + ;I DON'T THINK IT WORKS TO TURN THIS OFF. +NIOCHN==20 ;NUMBER OF I/O CHANNELS PER USER + +DEFINE $INSRT $%$%$% ;PRINTX MESSAGE WHEN FILE GETS INSERTED + .INSRT $%$%$% > + PRINTX \ ==> INSERTED: \ + .TYO6 .IFNM1 + .TYO 40 + .TYO6 .IFNM2 +PRINTX \ +\ +TERMIN + +;;; CONFIG uses this macro... +DEFINE CONC A,B +A!B!TERMIN + +$INSRT CONFIG ;CONFIGURATION SWITCHES FOR ALL KNOWN MACHINES + +$INSRT BITS ;DEFINITIONS OF MANY BIT NAMES + +;IN BADBTS => CLASS 2 OR 1 INTERRUPT ;IN VBDBTS=> CLASS 1 INTERRUPT +VBDBTS==%PIB42\%PIVAL\%PIBRK\%PIC.Z\%PI1PR\%PITRP\%PIDCL +BADBTS==VBDBTS\%PIMPV\%PIIOC\%PIILO\%PIMAR\%PIDIS\%PIOOB\%PILOS\%PIFET\%PIWRO\%PIPAR\%PITTY\%PIPDL\%PINXI + +UUOMIN==40000,, ;SMALLEST NUM THAT COULD BE A SYSTEM CALL +UUOMAX==50000,, ;ONE GREATER THAN LARGEST NUM " +UIOT=UUOMAX ;USE FOR USER I/O INST TRAP + + ;MAX DYN ALLOC ALLOC IO BUFFERS +MXIOB==100 ;MAX POSSIBLE + +SIOMT==50 ;MAX SIZE TRANSLATION TABLE + +LUPDL==50 ;LENGTH USER PDL MUST BE >= 40 FOR 2311 GC +LUIOP==20 ;LENGTH OF USER IO PDL +CPDLL==40 ;LENGTH CLOCK CHANNEL PDL +LUTCP==40 ;LENGTH UTC PDL (NETWORKS AND DISKS) +LSYSP==100 ;SYSTEM JOB PDL +LTTYP==40 ;LENGTH OF TTY (INTERRUPT LEVEL) PDL + +DMNSZ==20 ;# ENTRIES IN DEMON BUFFER (DMNBF) + +MXCZS==5 ;MAX NUMBER ^Z'S PER CLOCK BREAK + +SCLKI==30. ;60'THS PER SLOW CLOCK +VSCLKI==2*60.*60. ;60'THS PER VERY SLOW CLOCK TICK +MXOPT==8. ;SLOW CLOCK MAX UT OP CAN TAKE +NINFP==8. .SEE UFIN ;MAX # OF DIRECT INFERIORS A PROCEDURE MAY HAVE + +SSCHDB==100 ;LENGTH OF SCHEDULER HISTORY BUFFER + +SPD==60.*60.*24. ;# SECS IN A DAY (FITS IN A HALFWORD) + PDUPS==60. ;# PDCLK INCREMENTS/SEC + +OPNCOM==410300 ;COMMAND FIELD IN LH OF FIRST OPEN WORD + +IFN 340P,N340PB==10. ;# EXEC PGS USED FOR 340 DATA MUST BE EVEN +IFN N11TYS,[ + NTTPG==6 ;# EXEC PGS FOR PDP11 TV TTYS. + NTVBP==11 ;THESE PAGES ADDRESS THE WHOLE VIDEO BUFFER MEMORY ADDRESS + ;SPACE OF THE TV 11. THE LAST OF THESE ADDRESSES THE + ;TV CONSOLE REGISTER +] +NUVPG==256. ;NUMBER OF VIRTUAL PAGES PER USER. SIZE OF PAGE TABLE VARS. + ;DON'T TRY TO CHANGE THIS. +;CIRCULAR PAGE LINK FORM +;2.9=0 +;1.1-1.8 PAGE # +;2.8-1.9 USER # +;2.9=1 +;2.8=0 2.7-1.1 LINK TO MMP TABLE +;2.8=1 2.7-1.1 LINK TO MEM PNT TABLE +;EXCEPT 2.9-1.1=777777 => ABSOLUTE PAGE, NOT LINKED + +SUBTTL GOBBLE TTYTYP FILE + +IFN XGP\N11TYS,[IFE TEN11P,[ + .ERR XGP OR N11TYS WITHOUT TEN11P + N11TYS==0 + XGP==0 +] +] +IFNDEF UNSPLP,UNSPLP==*DEMON*<1-TPLP> + ;1 IF THE "UNSPOO" PROGRAM DOES LPT SPOOLING. + +IFNDEF TSYSM,[ +MNAME PRINTX \NO PARAMS KNOWN FOR , MACHINE. +\ +.INSRT TTY: +] + +IF2,[ +;TTY LINES DEFINITIONS + +;MACRO WHICH RETURNS THE %TY BIT FOR THE CONTROLLER ACCORDING TO THE LINE NUMBER + +DEFINE CNTRLR +IRPS F,,[0 NFKSTY NFETY NFNTY NFNVTY NFDZTY NFDPTY NFMTY NFDLTY NFSTTY NF11TY + ]NT,,[NOTYS NKSTYS NETYS NNTYS NNVTTS NDZTYS NDPTYS NMTYS NDLTYS NSTTYS N11TYS + ]FG,,[%TYOTY %TYKST %TYETY %TYNTY %TYNVA %TYDZT %TYDPK %TYMTY %TYDL %TYSTY %TY11T] + IFGE -F,[IFL -,[FG]]TERMIN TERMIN + +;MACRO WHICH RETURNS $TTISP, $TTOSP BITS GIVEN BAUD RATES + +DEFINE SPEEDC +*%TTISP+*%TTOSP!TERMIN + +DEFINE SPEED1 +IRPS BD,,[0 600 110 150 300 1200 1800 2400 4800 9600 25K 40K 50K 80K + ]CD,,[0 1 2 3 4 5 6 7 10 11 12 13 14 15 ] +IFSE BAUD,BD,[CD] TERMIN TERMIN + +;KEYWORD PARAMETERS TO TTY DEFINITION MACROS +; FOR OVER-RIDING DEFAULTS +;SPEED NUMBER OF BAUDS OUTPUT +;ISPEED NUMBER OF BAUDS INPUT IF DIFFERENT +;TT LH(TTTYP) IN ADDITION TO SPEED CODE +;TY RH(TTYTYP) IN ADDITION TO CONTROLLER BIT +;TO LH(TTYOPT) IN ADDITION TO USUAL CODES FOR TERMINAL TYPE +;TP RH(TTYOPT) IN ADDITION TO PAD CODES +;TCT TCTYP +;HOR SCREEN WIDTH +;VER SCREEN HEIGHT +;ROL LINES PER GLITCH WHEN SCROLLING + +;DEFINE TTY AS PRINTING. +;IF SPEED IS 110, ASSUME TTY IS TELETYPE, +;MEANING CAN'T BS, STANDARDIZE ALTMODES. +;IF KA10 CONSOLE TTY OR TK10 TTY, NEED PARITY +DEFINE TTDPRT N,+SPEED=300,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,TCT=%TNPRT,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==80.-IFE 110-SPEED,8 +T!N!$VER==MOVE +T!N!$OPT==TO+%TOOVR+%TOALT+IFN 110-SPEED,[%TOMVB+%TOLWR-%TOALT],,<1+IFE 300-SPEED,[IFE TY&<%TYDIL\%TYRLM>,[3]]>*%TPPCR+TP +T!N!$TYP==TT+\\,[%TTPAR]]>,,TY+ +T!N!$TCT==TCT +T!N!$ROL==1 +TERMIN + +;DEFINE TTY AS MEMOREX +DEFINE TTDMRX N,+SPEED=600,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,HOR=120.,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==MOVE +T!N!$OPT==TO+%TOOVR+%TOMVB+%TOLWR,,4*%TPPLF+6*%TPPCR+TP +T!N!$TYP==TT+,,TY+ +T!N!$TCT==%TNMEM +T!N!$ROL==1 +TERMIN + +;DEFINE TTY AS TERMINET. +DEFINE TTDTRM N,+SPEED=1200,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,HOR=120.,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==MOVE +T!N!$OPT==TO+%TOOVR+%TOMVB+%TOLWR,,5*%TPPLF+TP +T!N!$TYP==TT+,,TY+ +T!N!$TCT==%TNTRM +T!N!$ROL==1 +TERMIN + +;DEFINE TTY AS A LPT. +DEFINE TTDLPT N,+SPEED=9600,ISPEED=,TT=0,TY=0,TO=0,TP=0,HOR=200.,TCT=%TNPRT,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==MOVE +T!N!$OPT==TO+%TOMVB+%TOOVR,,TP +T!N!$TYP==%TTDDI+TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==1 +TERMIN + +;DEFINE TTY AS AN LA36 DECWRITER. +DEFINE TTDLA36 N,+SPEED=300,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,HOR=132.,TCT=%TNPRT,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==MOVE +T!N!$OPT==TO+%TOMVB+%TOOVR+%TOLWR,,TP +T!N!$TYP==TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==1 +TERMIN + +;DEFINE TTY AS IMLAC. (RUNNING SOFTWARE-TTY PROGRAM) +DEFINE TTDIML N,+SPEED=50K,ISPEED=25K,TT=0,TY=0,TO=0,TP=0,HOR=90.,VER=44.,TCT=%TNSFW,ROL=10.,SMARTS=%TQIM1 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOOVR+%TOLWR+%TOMVB+%TOMVU+%TOERS+%TOLID+%TOCID,,TP +T!N!$TYP==%TTDDI+TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==ROL +TERMIN + +;DEFINE TTY AS VT52 +DEFINE TTDVT N,+SPEED=9600,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,HOR=80.,VER=24.,TCT=%TNESC,ROL=1,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOMVU+%TOMVB+%TOLWR+%TOERS,,TP+%TPPTB* + ;DIRECT POSITIONING LOSES AT 9600 +T!N!$TYP==TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==ROL +TERMIN + +;DEFINE TTY AS H19 +DEFINE TTDH19 N,+SPEED=9600,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,HOR=80.,VER=24.,TCT=%TNH19,ROL=1,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOMVU+%TOMVB+%TOLWR+%TOERS+%TOLID+%TOCID,,TP+%TPPTB*3 +T!N!$TYP==TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==ROL +TERMIN + +;DEFINE TTY AS AAA +DEFINE TTDAAA N,+SPEED=9600,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS+%TPMTA,HOR=80.,VER=48.,TCT=%TNAAA,ROL=1,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOMVU+%TOMVB+%TOLWR+%TOERS+%TOLID+%TOCID,,TP+%TPPTB*2 +T!N!$TYP==TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==ROL +TERMIN + +;DEFINE TTY AS C100 +DEFINE TTDC100 N,+SPEED=9600,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,HOR=79.,VER=24.,TCT=%TNHDS,ROL=1,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOMVU+%TOMVB+%TOLWR+%TOERS+%TOLID+%TOCID,,TP+%TPPTB*3+ +T!N!$TYP==TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==ROL +TERMIN + +;DEFINE TTY AS TEKTRONIX. +DEFINE TTDTEK N,+SPEED=1200,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,TCT=%TNTEK,HOR=73.,VER=35.,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOMVU+%TOOVR+%TOMVB+%TOLWR+%TOMOR,,TP +T!N!$TYP==TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==0 +TERMIN + +;DEFINE TTY AS A LOSING DATAPOINT +DEFINE TTDLSR N,+SPEED=2400,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$TCT==%TNODP +T!N!$HOR==71.-IFN MCOND AIKA,1 ;OTHER DATAPOINTS HAVE SHORTER SCREENS. +T!N!$VER==25. +T!N!$OPT==TO+%TOMVB+%TOMVU+%TOERS,,4*%TPPCR+TP +T!N!$TYP==TT+,,TY+ +T!N!$ROL==1 +TERMIN + +;DEFINE TTY AS DATAPOINT. +DEFINE TTDDPT N,+SPEED=2400,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,HOR=[72.-IFN MCOND AIKA,[1]],SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$TCT==%TNDP +T!N!$HOR==HOR ;OTHER DATAPOINTS HAVE SHORTER SCREENS. +T!N!$VER==25. +T!N!$OPT==TO+%TOMVB+%TOMVU+%TOERS,,4*%TPPCR+TP +T!N!$TYP==TT+,,TY+ +T!N!$ROL==1 +TERMIN + +;DEFINE TTY AS A TELERAY 1061 +DEFINE TTDRAY N,+SPEED=9600,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,HOR=80.,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$TCT==%TNRAY +T!N!$HOR==HOR +T!N!$VER==24. +T!N!$OPT==TO+%TOMVU+%TOMVB+%TOERS+%TOLWR+%TOLID+%TOCID,,3*%TPPTB+TP +T!N!$TYP==TT+,,TY+ +T!N!$ROL==1 +TERMIN + +;DEFINE A TTY THAT IS A GT40. +DEFINE TTDGT40 N,+SPEED=4800,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS,TCT=%TNDP,HOR=72.,VER=32.,ROL=1,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOMVB+%TOERS+%TOMVU+%TOOVR+%TOLWR,,TP +T!N!$TYP==TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==ROL +TERMIN + +;DEFINE A TTY THAT IS A LINE TO A PDP11. +DEFINE TTD11 N,+SPEED=4800,ISPEED=,TT=0,TY=0,TO=0,TP=0,TCT=%TNPRT,HOR=72.,VER=MOVE,ROL=1,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOMVB+%TOOVR+%TOALT,,TP +T!N!$TYP==TT+%TTDDI+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==ROL +TERMIN + +;DEFINE A TTY THAT IS RANDOM. +DEFINE TTDRAN N,+SPEED=FOO.,ISPEED=,TT=0,TY=0,TO=FOO.,TP=FOO.,TCT=FOO.,HOR=FOO.,VER=FOO.,ROL=FOO.,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO,,TP +T!N!$TYP==TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==ROL +TERMIN + +;DATAMEDIA +DEFINE TTDDTM N,+SPEED=4800,ISPEED=,TT=0,TY=0,TO=0,TP=%TPORS+3*%TPPCR,HOR=80.,VER=24. +T!N!$SMT==0 +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOMVB+%TOERS+%TOMVU+%TOLWR+%TOLID+%TOCID,,TP +T!N!$TYP==TT+,,TY+ +T!N!$TCT==%TNDTM +T!N!$ROL==1 +TERMIN + +;DEFINE A PDP11 TV COMMUNICATING VIA TEN-11 INTERFACE. NO OPTIONS. +DEFINE TTDTV N +T!N!$SMT==%TQGRF+%TQVIR+%TQREC+%TQXOR+<.DPB 14,<.BP %TQHGT>>+<.DPB 6,<.BP %TQWID>>,,%TRSCN +T!N!$HOR==96. +T!N!$VER==45 +T!N!$OPT==%TOMVB+%TOMVU+%TOERS+%TOSAI+%TOLWR+%TOOVR+%TOFCI+%TOLID+%TOCID,,%TP11T+%TPRSC +T!N!$TYP==%TTLCL+,,%TY11T +T!N!$TCT==%TNTV +T!N!$ROL==4 +TERMIN + +;DEFINE A PDP11 TV COMMUNICATING AS A SOFTWARE TTY. TYPICALLY A GRINNELL (512x512). +DEFINE TTDGRN N,+SPEED=9600,ISPEED=,TT=0,TY=0,TO=0,TP=%TPCBS+%TPORS,HOR=86.,VER=50.,TCT=%TNSFW,ROL=0,SMARTS=0 +T!N!$SMT==SMARTS,, +T!N!$HOR==HOR +T!N!$VER==VER +T!N!$OPT==TO+%TOMVB+%TOMVU+%TOERS+%TOSAI+%TOLWR+%TOOVR+%TOFCI,,TP +T!N!$TYP==TT+,,TY+ +T!N!$TCT==TCT +T!N!$ROL==ROL +TERMIN + +;DEFINE AN STY LINE. NO OPTIONS. +DEFINE TTDSTY N +T!N!$SMT==0,, +T!N!$HOR==81. +T!N!$VER==MOVE +T!N!$OPT==%TOMVB+%TOOVR+%TOLWR+%TORAW,,%TPORS +T!N!$TYP==%TYSTY +T!N!$TCT==%TNPRT +T!N!$ROL==1 +TERMIN + +DEFINE MCONDX MCHN +IFE MCOND MCHN,TERMIN + +;;; THE NEXT TWO MACROS CAUSE TTYTYP FILE TO BE INSERTABLE BY BOTH +;;; PDP-10 AND PDP-11 PROGRAMS. + +DEFINE .ENDC +TERMIN + +DEFINE .ENDR +TERMIN + + .CRFOFF +$INSRT TTYTYP + .CRFON +EXPUNGE TTDPRT,TTDTRM,TTDDPT,TTDMRX,TTDGT40,TTD11,TTDRAN,TTDGRN,TTDVT,TTDTEK +EXPUNGE TTDTV,TTD2741,TTDSTY,TTDLPT,TTDIML,TTDLA36,TTDLSR +EXPUNGE SPEEDC,SPEED1,CNTRLR,MCONDX,.ENDC,.ENDR +] ;END OF IF2 + +SUBTTL BUG MACROLOGY + +;Macro for reporting a bug or other interesting condition +;Use this in place of JRST 4, especially when condition is automatically +;recoverable or wants explanation typed out for benefit of loser. +; +;First argument is one of the following symbols: +; INFO - just print on the system console +; CHECK - same as INFO unless SYSDBG non-zero or buffer full, then same as PAUSE +; PAUSE - print message, go to DDT, allow alt-P +; HALT - print message, go to DDT, do not allow alt-P +; DDT - PAUSE but not because of a bug (shorter message), allow alt-P +; AWFUL - same as HALT but usable when there is no pdl in P +; Should there be a combination of AWFUL and PAUSE? +; That would require restoring P upon attempt to continue +;Arguments after the first are either strings to be printed +;(enclose in brackets), or format,value pairs. Value is any +;address; indexing and indirection are allowed, however registers +;P and TT may not be referenced. +;A format is one of the following symbols: +; OCT - octal number, with ,, if bits on in the left halt +; DEC - decimal number +; THOU - decimal number with commas every three digits +; CR - print a carriage return (unfortunately swallows and ignores an arg) +; SIXBIT - sixbit word +; ASCIZ - asciz string +;Undefined formats will be taken as strings to be printed. +;The maximum number of value arguments is 6 +;A space is printed after each formatted value. A space is also +;printed after the last string and before any additional formatted values. +; +;With no arguments, BUG may be used in place of JRST 4,. +;It uses the same amount of storage but has the advantage of going +;straight to DDT. In this case there won't be a specific message +;about what the bug was, of course. +; +;Note that the BUG macro always generates one word of code, and hence +;may be skipped over. +;All registers are preserved. +;P must point at a valid PDL. +; +;Due to Midas inadequacy, the BUG macro may not be used from inside +;a literal. You will get an error (label inside brackets) if you try it. +; +;Example: +; BUG PAUSE,[DSK: DRIVE NUMBER ],OCT,Q,[IS OFF-LINE.] +; +DEFINE BUG FLAVOR,ARGS/ +IFNB [FLAVOR][ + ;Make sure we are not in a literal, since cannot get value of "." +BUGBUG: EXPUNGE BUGBUG + ;Generate call to appropriate flavour of subroutine + ZZ==0 + IRPS FLA,,[INFO,CHECK,PAUSE,HALT,DDT]SUB,,[BUGINF,BUGCHK,BUGPSE,BUGHLT,BUGDDT] + IFSE [FLAVOR]FLA,[ + PUSHJ P,SUB + ZZ==1 ] + TERMIN + IFSE [FLAVOR]AWFUL, JSR BUGAWF + .ELSE IFE ZZ, .ERR "FLAVOR" UNKNOWN FLAVOUR OF BUG + + BUGB==0 ;Initialize formatting bits + + ;Initialize remote macros +DEFINE BUGMC1 *ZZ001*ZZ002*ZZ003* +ZZ001!ZZ002!ZZ003!TERMIN + +DEFINE BUGMC4 ZZ001 +ZZ001 +TERMIN + + BUGN==0 ;number of accumulated arguments + BUGNN==0 ;total number of arguments + BUGF==0 ;next thing not argument + IRP ARG,,[ARGS] + ;; Processing "ARG" + IFN BUGF,[ ;Address of word to print + BUGN==BUGN+1 + BUGNN==BUGNN+1 + BUGMC5 [ARG] + BUGF==0 + ] + .ELSE [ ;Name of format in which to print? + IRPS FMT,,OCT DEC THOU CR UNUSED5 SIXBIT ASCIZ + IFSE [ARG]FMT,[ + BUGF==1 + BUGB==BUGB+<<.IRPCNT+1>_<<5-BUGNN>*3>> + ] + TERMIN + IFE BUGF,[ ;Just a string to be printed + IFN BUGN,[ ;Say to output some arguments before this string + BUGMC3 BUGN + BUGN==0 + ] + BUGMC2 [ARG] + ] ] + TERMIN + IFG BUGNN-6, .ERR MORE THAN 6 WORDS TO BE PRINTED IN BUG MACRO + ;Make bug table entry: length,,pc ? bits,,string ? args + IF1, BUGMC1 'ZZ==[ASCIZ|',,'|]' + IF2,[ + ZZ==. + LOC BUGTAB+LBUGTB + BUGNN+2,,ZZ + BUGMC1 'BUGB,,[ASCIZ|',,'|]' + BUGMC4 + LOC ZZ + ] + LBUGTB==LBUGTB+BUGNN+2 +];end IFNB +.ELSE PUSHJ P,BUGNIL +TERMIN + +LBUGTB==0 ;Initialize length of bug table + +;This support macro appends a string to the middle argument of BUGMC1 +DEFINE BUGMC2 STRING +BUGMC1 //,[DEFINE BUGMC1 *ZZ001*ZZ002*ZZ003* +ZZ001!ZZ002!]//,STRING!!ZZ003!TERMIN +TERMIN + +;This support macro appends a character, given by number, to the middle +;argument of BUGMC1 +;Only for characters 0 through 7 +DEFINE BUGMC3 #N +IRPC C,,.QUOTE// + IFE .IRPCNT-N,{ + BUGMC2 C + .ISTOP } +TERMIN +TERMIN + +;This one is a simple remote macro +DEFINE BUGMC5 STR +BUGMC4 [DEFINE BUGMC4 ZZ001 +ZZ001]STR +TERMIN +TERMIN + +SUBTTL DEFINE PI CHANNELS + +LPTP==OLPTP+NLPTP+GLPTP ;ANY KIND OF LPT EXCEPT A TTY LPT +IFE NMTCS,[ ;IF NO MAG TAPES AT ALL +TM10A==0 ; CAN'T HAVE ANY KIND! +TM10B==0 +TM03S==0 +] ;IFE NMTCS +TM10P==TM10A+TM10B ;SOME KIND OF A TM10 MAGTAPE PRESENT +IFN TABP,TABCLK==0 ;1=>PUT TABLET ON CLOCK CHNL + +;PRIORITY INTERRUPT CHANNEL ASSIGNMENTS + DCCHN==1 ;DC CHANNEL + DCLOC=40+2*DCCHN ;DC INTERRUPT LOCATION +IFN IMPP, IMPCHN==1 ;IMP STUFF +IFN NETP, NETCHN==2 ;SOFTWARE ACTIVATED... + UTCCHN==2 ;UTC CHANNEL + DSKCHN==UTCCHN ;2314 CHANNEL + MTCCHN==UTCCHN ;MAG TAPE CONTROL CHANNEL + LPTCHN==4 ;LINE PRINTER, PAPER TAPE, ETC. CHANNEL + TTYCHN==3 ;TTY CHANNEL +IFN PLTP, PLTCHN==4 ;PLOTTER CHANNEL +IFN PTRP, PCHCHN==4 ;PTP CHANNEL +IFN PTRP, PTRCHN==4 ;PAPER TAPE READER CHANNEL +IFN NTYP, NTYCHN==4 ;NTY 11 KLUDGE +IFN 340P, SDCHN==4 ;DISPLAY SPECIAL CHANNEL +IFN DSDP, DSDCHN==4 ;INTERRUPT FROM OTHER PROCESSOR +IFN ARMP, TIPBCH==5 ;ARM TIP BREAK CHNL +IFN OMXP, OMPCHN==5 ;OUTPUT MULTIPLEXOR +IFN VIDP, NVDCHN==5 ;NEW VIDI +IFN TABP, IFE TABCLK, TABCHN==5 ;TABLET +IFN 340P\E.SP, DISCHN==6 ;DISPLAY DATA CHNL +IFN CH10P, CHXCHN==5 ;CHAOSNET + ;WOULD BE 6 BUT PI 6 BROKEN IN ML-KA TTLIOB +IFN CH11P, CHXCHN==6 ;UNIBUS CHAOSNET PACKET COPYING +IFN TABP, IFN TABCLK, TABCHN==7 ;TABLET + APRCHN==7 ;DO NOT CHANGE + + PIOFF==400 ;TURN OFF PI SYSTEM + PION==200 ;TURN ON PI SYSTEM + PICOFF==1200 ;TURN OFF PI CHANNEL + PICON==2200 ;TURN ON PI CHANNEL + PICIRQ==4200 ;REQUEST INTERRUPT ON PI CHANNEL + CLKON==2201 ;ABSOLUTE + CLKOFF==1201 +IFN OMXP, OMXON==CLKON\<400_-OMPCHN-1> +IFN OMXP, OMXOFF==CLKOFF\<400_-OMPCHN-1> + LPTON==CLKON\<400_-LPTCHN-1> + LPTOFF==CLKOFF\<400_-LPTCHN-1> +IFN PTRP, PTPON==CLKON\<400_-PCHCHN-1> +IFN PTRP, PTROFF==CLKOFF\<400_-PCHCHN-1> +IFN PTRP, PTRON==CLKON\<400_-PTRCHN-1> +IFN PTRP, PTROFF==CLKOFF\<400_-PTRCHN-1> + TTYON==CLKON\<400_-TTYCHN-1> + TTYOFF==CLKOFF\<400_-TTYCHN-1> + UTCON==CLKON\<400_-UTCCHN-1> + UTCOFF==CLKOFF\<400_-UTCCHN-1> +IFN NETP, NETON==UTCON +IFN NETP, NETOFF==UTCOFF +IFN KL10P, DTEON==CLKON +IFN KL10P, DTEOFF==CLKOFF + + DSKRQ==PICIRQ\PICON\<200_-DSKCHN> ;RQ INT + TURN ON FOR SAKE OF KL + MTCRQ==PICIRQ\PICON\<200_-MTCCHN> + UTCRQ==PICIRQ\PICON\<200_-UTCCHN> + TTYRQ==PICIRQ\PICON\<200_-TTYCHN> + CLKRQ==PICIRQ\PICON\<200_-APRCHN> +IFN NETP,NETRQ==PICIRQ\PION\<200_-NETCHN> +IFN CH11P,CHXRQ==PICIRQ\PICON\<200_-CHXCHN> + +IFN TABP,[ +IFN TABCLK,[ +TABON==CLKON +TABOFF==CLKOFF +] +IFE TABCLK,[ +TABON==CLKON\<400_-TABCHN-1> +TABOFF==CLKOFF\<400_-TABCHN-1> +] +] + +IFN NUNITS, IFE NEWDTP, CUINT==5000+UTCCHN ;CONO TO UTC TO ACTIVATE UTAPE INTERRUPT + +PMLCAD==(.BP ) ;BYTE POINTER TO L.H. REAL CORE ADR +PMRCAD==(.BP PMRCM) ;BYTE POINTER TO R.H. REAL CORE ADR + +SUBTTL DEFINE DEVICE CODES, IOBFT CHNL NUMBERS + +IFN STKP, STK==70 ;STANFORD KEYBOARD +IFN OLPTP, OLPT==124 ;LINE PRINTER +IFN NLPTP, NLPT==464 +IFN TM10P, MTC==340 ;MAG TAPE CONTROL +IFN TM10P, MTS==344 ;MAG TAPE STATUS +IFN VIDP, NVDX==620 ;NEW VIDI X +IFN VIDP, NVDY==624 ;NEW VIDI Y +IFN VIDP, NVDT==630 ;NEW VIDI T (DEFLECTION DELAY) +IFN PLTP, PLT==654 ;CAL COMP PLOTTER +IFN HCLKP, CLK1==710 ;HOLLOWAY CLOCK +IFN HCLKP, CLK2==714 ; " +IFN IMXP, MPX==574 ;INPUT MULTIPLEXOR +IFN OMXP, OMPX==570 ;OUTPUT MULTIPLEXOR +IFN TK10P\NTYP, NTY==600 ;KNIGHT TTY KLUDGE +IFN MTYP, MTY==400 +IFN DL10P, DLB==60 ;DL10 BASE +.ALSO DLC==64 ;DL10 CONTROL +IFN PDCLKP, PDCLK==500 ;DE-CORIOLIS CLOCK (FOR ML-KA AND DM, CALENDAR CLOCK) +IFN DSDP, DSDEV==20 ;DE SELECTION AND INTER COM DEVICE +IFN DSDP, DSDEVN==24 ;DE SELECTION DEV (FOR DEVICES YOU DATAO DEV CODE TO DSDEVN) +IFN ARMP, TIPDEV==504 ;TIP BREAK DEVICE +IFN RBTCP, RBTCON==514 ;ROBOT CONSOLE +IFN DPKPP, DPK==604 ;DATA POINT KLUDGE +IFN DC10P, DC0==610 ;2314 DISK CONTROL +IFN DC10P, DC1==614 ;2314 DISK CONTROL +IFN RP10P, DPC==250 ;RP10 DISK CONTROL +IFN RH10P, DSK==270 ;RH10 DISK CONTROL +IFN KAIMP, IMP==460 ; AI-KA/ML-KA/MC-KL IMP interface +IFN DMIMP, FI==424 ; DM IMP hardware +IFN NUNITS,[ +IFN NEWDTP,[ + DTC==320 + DTS==324 +] ;END OF IFN NEWDTP +] ;END OF IFN NUNITS + + +;IOBFT CHANNEL NUMBERS - 77 MEANS "FREE" + +IFN NUNITS, NUTIC==8 ;NUMBER UT IN CHNLS +.ELSE NUTIC==0 +IFN NUNITS, NUTOC==8 ;NUMBER UT OUT CHNLS +.ELSE NUTOC==0 + NFCLC==NUTIC+NUTOC+1 ;# OF FIRST CORE LINK CHNL + NCLCH==14 ;NUMBER CORE LINK CHNLS + NFNETC==NFCLC+NCLCH ;# OF FIRST NCP NET CHNL (if any) + ;NNETCH DEFINED IN CONFIG +IFG NFNETC+NNETCH-77, .ERR TOO MANY IOBFT CHANNELS + +SUBTTL RANDOM DEFINITIONS FOR I/O DEVICES + +IFN DSDP, IFN VIDP, DSNVID==200000,, ;DEASSIGN BIT FOR NVD +IFN DSDP, IFN 340P, DSNDIS==4000,, ;DEASSIGN BIT FOR DIS +IFN DSDP, IFN NMTCS, DSMTC==1,, ;DEASSIGN BIT FOR MAG TAPE + +IFN RBTCP, RLTSWC==17 ;ROBOT CONSOLE SELECT FOR LIGHTS AND SWITCHES +IFN RBTCP, IFN TABP, RTABC==16 ;ROBOT CONSOLE SELECT FOR TABLET + +IFN IMXP, LCHN==177 ;MULTIPLEXOR LIMIT ON READ IN + + NUDCH==14 ;NUMBER DIRECTORY CHNLS +IFN IMXP, NPOTCH==20. ;NUMBER POT CHANNELS +IFG NQCHN+1+NQS-77, .ERR MORE THAN 6 BITS OF DISK CHANNEL NUMBER + +IFN CODP, CODBFL==5 ;CODE BUFFER +IFN PTRP, PUNSIZ==20 ;PTP BUF SIZ +IFN PTRP, REDSIZ==200 ;PTR BUF SIZ +IFN PLTP, LPLBUF==200 ;PLT BUF SIZ +IFN LPTP, LPTBSZ==1000 ;LPT BUF SIZ +IFN VIDP, NVDLNG==340 ;NVD BUF SIZE +IFN TPLP, TPLBSZ==100 ;TPL BUFFER SIZE IN SYS JOB +IFN TABP, LTABBF==100 ;TABLET BUFFER +IFN N11TYS, TT11CR==764044 ;UNIBUS ADR OF TV11 CONSOLE REG + +EOFCH==3 ;SYSTEM END OF FILE CHR +EOFWRD=REPEAT 5,[EOFCH_<.RPCNT*7+1>\]0 ;WORD OF EOFCH'S + +IFN 340P, DVEF==4000 ;DISPLAY VERTICAL EDGE FLAG +IFN 340P, DHEF==1000 ;DISPLAY HOR EDGE FLAG + +IFN 340P, EWRT==400./12. ;EQIV "COST" IN DISPLAY WRDS FOR TRIP THRU RECYC +IFN 340P, MDISWD=70000 ;MAX # WDS SENT TO SCOPE IN 1/2 SEC + +NSWPV==E.SP\340P+VIDP+IMXP ;# OF DEVICES THAT CAN SWAPIN PAGES + +IFN C1MXP,[ +IFN NMTCS, MAGLOC==76 ;INTERRUPT LOCS FOR MAGTAPE +IFN NUNITS, DCMLOC==74 ;" " FOR DC +IFN IMXP, IMXLC==66 ;" " IMX +IFN IMPP,[ + IMPILC==70 ;INPUT FROM IMP + IMPOLC==72 ;OUTPUT TO IMP +] +] + +IFE C1MXP,[ +IFN NMTCS, MAGLOC==42 +IFN NUNITS, DCMLOC==42 +] +IFN PLTP,[ +;PLOTTER CONTROL BITS +SD==4000 +PD==10000 +PUP==200 +PDN==400 +SDC==20000 +PDC==40000 +SDS==1000 +PDS==2000 +] + IFN KA10P,[ + +SUBTTL STUFF PECULIAR TO KA-10 PROCESSOR + +;;;PAGING BOX INSTRUCTIONS + +LPM=102000,, ;LOAD PG MEM STATE VECTOR DONT CLR ASSOC MEM +LPMR= LPM 2, ;CLEAR ASSOC MEM AND LOAD +SPM= LPM 1, ;STORE PG MEM STATE VECTOR +LPMRI=LPM 6, ;LOAD PM, CLEAR ASSOC REG, AND CAUSE INTERRUPT +EXPGNG==4 .SEE UPQUAN ;4 TO TURN ON EXEC PAGING +XCTR=103000,, ;EXECUTE INSTRUCTION WITH MAPPING CONTROLLED BY AC FIELD + ;VIOLATION CAUSES USER MEM PROTECT INTERRUPT UNLESS INHIBITED + ;VIOLATION ALSO SKIPS BUT THIS IS OF NO CONSEQUENCE UNLESS + ;INTERRUPT IS INHIBITED SINCE PC WILL BE RESET FROM OPC +XCTRI= XCTR 4, ;XCTR WITH PAGE FAULT INHIBITED (SKIPS ON FAULT) + ; AC FIELD VALUES FOR XCTR AND XCTRI + XR==1 ;MAP READ MAIN OPERAND OF SIMPLE INSTRUCTION (MOVE, SKIPL, HLL) + XW==2 ;MAP WRITE MAIN OPERAND OF SIMPLE INSTRUCTION (MOVEM) + XRW==3 ;MAP READ/WRITE OPERAND OF SIMPLE INSTRUCTION (E.G. IORM) + XBYTE==3;MAP BYTE DATA AND BYTE POINTER (ILDB, IDPB) + XBR==1 ;MAP BLT READ + XBW==2 ;MAP BLT WRITE + XBRW==3 ;MAP BOTH OPERANDS OF BLT + ;KA10 PAGING BOX GOES BY WHETHER IT'S A READ OR WRITE (OR RW) CYCLE + ;KL10 PAGING BOX WORKS DIFFERENTLY (SEE BELOW) + ;DO NOT USE MULTI-OPERAND INSTRUCTIONS (DMOVE, PUSH, ETC.) WITH XCTR + +DEFINE CLRPGM U ;CLEAR PAGER ASSOCIATIVE MEMORY. ARG IS USUALLY "(U)". + SPM UPGML!U ;STORE SO DON'T LOSE QUANTUM TIMER + LPMR UPGML!U +TERMIN + +;;; MISCELLANEOUS BUILTIN I/O DEVICES + +PI==4 ;INTERRUPT SYSTEM +LIGHTS==PI ;DEVICE CODE FOR DATAO THAT SETS CONSOLE LIGHTS. +CLK==0 ;DEVICE CODE FOR 60 HZ CLOCK INTERRUPT (APR) +CLKINT==1000 ;CONI CLK, BIT FOR INTERRUPT. ALSO CONO BIT TO CLEAR. +PTR==104 ;PAPER TAPE READER +PTP==100 ;PAPER TAPE PUNCH +TTY==120 ;CONSOLE TTY +DTC==320 ;DECTAPE CONTROL +IFN 340P, DIS==130 ;340 DISPLAY + +PI0LOC==40 ;INTERRUPT VECTOR BASE + +OIPBIT==%PC1PR ;PC BITS FOR 1-PROCEED. +BADPC==%PCUIO+%PCSPC+37 ;BITS IN PC USER NOT ALLOWED TO TURN ON + +DEFINE UUOH ;UUO HANDLER LOCATIONMS ARE REFERENCED THROUGH THESE MACROS +XUUOH!TERMIN + +DEFINE FORTY +40!TERMIN + +DEFINE SYSCTX ;SET UUO LEVEL AC BLOCKS +TERMIN + +DEFINE USRCTX ;SET USER-MODE AC BLOCKS +TERMIN + +DEFINE OVHMTR NAME ;OVERHEAD METERING DOESN'T WORK ON KA'S +TERMIN +] ;END OF IFN KA10P + IFN KL10P,[ + +SUBTTL STUFF PECULIAR TO KL-10 PROCESSOR + +;;;PAGING BOX INSTRUCTIONS + +XCTR=074000,, ;EXECUTE INSTRUCTION WITH MAPPING, PAGE FAILS ENABLED +XCTRI=075000,, ;SAME BUT SKIPS IF THERE IS PAGE FAIL (DONE SNEAKILY BY SOFTWARE) +LPMR=076000,, ;LOAD PAGER MEMORY (JPC, DBRS) AND CLEAR PT DIR +SPM=077000,, ;STORE PAGER MEMORY + ;AC FIELD VALUES FOR XCTR AND XCTRI + XR==4 ;MAP MAIN OPERAND OF SIMPLE INSTRUCTION (FOR READING) + XW==4 ;MAP MAIN OPERAND OF SIMPLE INSTRUCTION (FOR WRITING) + XRW==4 ;MAP MAIN OPERAND OF SIMPLE INSTRUCTION (FOR READING AND WRITING) + XBYTE==5;MAP BYTE DATA AND BYTE POINTER + XBR==1 ;MAP BLT SOURCE + XBW==4 ;MAP BLT DESTINATION + XBRW==5 ;MAP BOTH BLT OPERANDS + XEA==16 ;MAP EFFECTIVE ADDRESS COMPUTATION + ;IN KL10 BITS ARE: 14 INDIRECT WORDS + ; 10 XR UNDER SOME RANDOM WIERD CONDITIONS (?) + ; 4 MAIN OPERAND " " " ALSO BYTE WRITE + ; 2 INDEX REGISTER, @ AND XR IN BYTE PTRS + ; 1 2ND OPND - BLT SOURCE, BYTE READ, STACK DATA + +DEFINE CLRPGM U ;CLEAR PT DIR WITHOUT SWITCHING USERS. ARG IS USUALLY "(U)". + CONO PAG,660000+ +TERMIN + +;;; INTERNAL "I/O" DEVICES + +PI==4 ;INTERRUPT SYSTEM +PAG==10 ;CONO, DATAO PAG SET UP PAGING + ..D010==0 ;FOR DDT +CCA==14 ;CACHE OPERATIONS +TIM==20 ;TIMER DEVICE +MTR==24 ;METERS DEVICE + +IFN PDCLKP,[ ;IF THIS KL-10 HAS FREEMAN KL-UDGE BOARD, +LIGHTS==500 ;DATAO LIGHTS, SETS CONSOLE LIGHTS. +CLK==500 ;60 HZ CLOCK INTERRUPT (ON KL-UDGE BOARD) +CLKINT==10 ;CONI CLK, BIT FOR INTERRUPT. ALSO CONO BIT TO CLEAR. + ;ALSO DATAI 500, IS THE DECORIOLIS CLOCK. + ;AND CONO 500,400000 TURNS CLOCK BACK ON AFTER POWER FAIL. +] + +OIPBIT==%PS1PR ;1-PROCEED BITS IN THE PC. +BADPC==%PSUIO+37 ;%PSPUB IS OK? + +;;; SPECIAL INSTRUCTIONS + +SWPIA=DATAI CCA, ;INVALIDATE WHOLE CACHE +SWPIO=CONI CCA, ;INVALIDATE ONE PAGE OF CACHE +SWPUO=CONSO CCA, ;UNLOAD ONE PAGE OF CACHE +SWPUA=DATAO CCA, ;UNLOAD WHOLE CACHE +WRPAE=702100,, ;WRITE PERFORMANCE-COUNTER ENABLES +APRID==BLKI ;READ CPU SERIAL NUMBER AND OPTIONS +RDERA=BLKI PI, ;READ ERROR ADDRESS +RCCL=DATAI TIM, ;READ CALENDAR CLOCK (DOUBLE WORD) +RPERFC=BLKI TIM, ;READ PERFORMANCE COUNTER (DOUBLE WORD) +REBOXC=DATAI MTR, ;READ EBOX CYCLE COUNTER (DOUBLE WORD) +RMBOXC=BLKI MTR, ;READ MBOX CYCLE COUNTER (DOUBLE WORD) + +;;;EPT LOCATIONS + +$INSRT EPT + +;;;PAGE FAIL WORD - UPFW(U) + + %PF==1,,405000 + %PFUSR==400000 ;USER PAGE + %PFCOD==370000 ;FAILURE CODE: + %PFPRO==210000 ;PROPRIETARY VIOLATION + %PFMAR==230000 ;MAR BREAK + %PFILW==240000 ;ILLEGAL WRITE IN READ ONLY + %PFPNA==330000 ;PAGE NO ACCESS + %PFPTP==250000 ;PAGE TABLE PARITY + %PFPAR==360000 ;PARITY ERROR, DATA IN AR + %PFPRX==370000 ;PARITY ERROR, DATA IN ARX + %PFPUB==4000 ;PUBLIC PAGE + %PFCCH==2000 ;CACHED + %PFPAG==1000 ;PAGED + $PFPNO==121000 ;VIRTUAL PAGE NUMBER + ;1.1-3.5 VIRTUAL ADDRESS + +DEFINE UUOH ;UUO HANDLER LOCATIONS REFERENCED THROUGH THESE MACROS +XUUOH(U)TERMIN + +DEFINE FORTY +MUUODP(U)TERMIN + +;SET SPECIAL CONTEXT: CURRENT AC BLOCK CURACS, PREVIOUS BLOCK (FOR XCTR) OLDACS, +; UPT AS SPECIFIED. IF NO ACS SPECIFIED, THEY DON'T CHANGE; SAME FOR UPT. +; DISABLE, IF NONBLANK, CAUSES ACCOUNTING UPDATING NOT TO BE DONE EVEN THOUGH +; UPT IS BEING SET. +DEFINE SPCCTX CURACS,OLDACS,UPT,DISABLE +DATAO PAG,[IFNB CURACS OLDACS,[SETZ]+IFNB UPT,[1^13]+2^13+CURACS_33+OLDACS_30+UPT/1000+400000-IFNB UPT,[IFB DISABLE,[400000]]] +TERMIN + +SYSCTX=SPCCTX 0,1 ;UUO LEVEL CONTEXT: CURRENT AC BLOCK 0, PREVIOUS = 1. +USRCTX=SPCCTX 1,1 ;USERS RUN IN BLOCK 1. +IRPC N,,[234567] + AC!N!CTX=SPCCTX 0,N ;CUR AC 0, PREV N. USE XCTR TO ACCESS SPECIAL ACS +TERMIN + +;AC BLOCK USAGE: +; 0 ACCUMULATORS FOR SYSTEM (AT UUO LEVEL) +; 1 ACCUMULATORS FOR USER +; 2 USED TEMPORARILY BY TTY INPUT INTERRUPTS +; 3-5 NOT USED +; BLOCKS 2 & 3 ARE USED BY THE UNFINISHED MUSIC MICROCODE +; BLOCKS 4 & 5 ARE USED BY THE UNFINISHED JPC RING FEATURE +; 6-7 USED BY MICROCODE +] ;END OF IFN KL10P + IFN KS10P,[ + +SUBTTL STUFF PECULIAR TO THE KS-10 PROCESSOR + +EPT==:0 ; This MUST agree with the Salvager! +HSB==:500 +$INSRT KSDEFS + +DEFINE CLRPGM U ;CLEAR PT DIR WITHOUT SWITCHING USERS. ARG IS USUALLY "(U)". + WREBR 20000+ +TERMIN + +OIPBIT==1000 ;BIT 8 (SYMBOLIC NAME %PSINH) +BADPC==%PSUIO+37 ;BITS IN PC THAT USER CANNOT TURN ON + +DEFINE UUOH ;UUO HANDLER LOCATIONS REFERENCED THROUGH THESE MACROS +XUUOH(U)TERMIN + +DEFINE FORTY +MUUODP(U)TERMIN + +;SET SPECIAL CONTEXT: CURRENT AC BLOCK CURACS, PREVIOUS BLOCK (FOR XCTR) +; OLDACS, UPT AS SPECIFIED. IF NO ACS SPECIFIED, THEY DON'T CHANGE; SAME +; FOR UPT. +DEFINE SPCCTX CURACS,OLDACS,UPT +WRUBR [IFNB CURACS OLDACS,[SETZ]+IFNB UPT,[1^13]+CURACS_33+OLDACS_30+UPT] +TERMIN + +SYSCTX=SPCCTX 0,1 ;UUO LEVEL CONTEXT: CURRENT AC BLOCK 0, PREVIOUS = 1. +USRCTX=SPCCTX 1,1 ;USERS RUN IN BLOCK 1. +IRPC N,,[234567] + AC!N!CTX=SPCCTX 0,N ;CUR AC 0, PREV N. USE XCTR TO ACCESS SPECIAL ACS +TERMIN + +;AC BLOCK USAGE: +; 0 ACCUMULATORS FOR SYSTEM (AT UUO LEVEL) +; 1 ACCUMULATORS FOR USER +; 2 USED TEMPORARILY BY TTY INPUT INTERRUPTS +; 3-6 NOT USED +; 7 USED BY MICROCODE (AC0 GETS BAD DATA WHEN MEMORY ERROR OCCURS, THIS +; COULD BE FIXED IF ANYONE THINKS IT IS WORTH IT...) +] ;END OF IFN KS10P + +IFE KS10P,[ ; For the benefit of processors without UMOVE and UMOVEM. + +DEFINE UMOVE (AC,ADDR) +XCTR XR,[MOVE AC,ADDR] +TERMIN + +DEFINE UMOVEM (AC,ADDR) +XCTR XW,[MOVEM AC,ADDR] +TERMIN + +] ;IFE KS10P + +SUBTTL SYS IOC STATUS WORD FORMAT + +;RIGHT HALF WORD DEVICE STATUS +;1.1-1.6 SYS PHYSICAL DEVICE CODE +;1.7-1.9 OPEN MODE +;2.1 SYS BUFF CAP FULL +;2.2 " " " EMPTY +;2.9-2.3 DEVICE DEPENDANT + +;LEFT HALF WORD CHANNEL STATUS +;3.6-3.1 SET BY OPENS THAT DONT SKIP +;4.5-3.7 SET BY IOC ERRORS (INTERRUPTS) AT IOT OR OPER TIME + ;3.9-3.7 ARE FOR 340 OR E&S ERRORS + ;4.5-4.1 ARE FOR OTHER DEVICES +;A LIST OF ERROR CODES FOR OPEN FAILURES ARE IN THE FILE BITS. + +NDOPL==7 ;NUM OF DIS OPNL + +;4.5-3.7 SET BY IOC ERRORS AT IOT OR OPER TIME + +;3.9-3.7 SET BY 340 ROUTINES +;1 ILLEGAL SCOPE MODE +;2 SCOPE HUNG +;3 MORE THAN 1K SYS SCOPE BUF +;4 MEMORY PROTECT +;5 ILLEGAL SCOPE OP +;6 MEMORY PROTECT ON PDL POINTER +;7 ILLEGAL PARAMETER SET + +;4.5-4.1 +;DECIMAL CODE +;13 DIRECTORY'S ALLOCATION EXHAUSTED +;12 DIRECTORY FULL +;11 ILLEGAL CHR AFTER ^P ON TTY DISPLAY +;10 CHNL IN ILLEGAL MODE WHEN .IOT ATTEMPTED +;9 DEVICE FULL +;8 CHANNEL NOT OPEN +;7 USR OP CHNL DOES NOT HAVE USR OPEN +;6 ATTEMPT TO OVER IOPUSH +;5 ATTEMPT TO OVER IOPOP +;4 NON-EXISTANT SUB DEVICE +;3 NON-RECOVERABLE DATA ERROR ;NON-EX-MEM ON PDP6 REF +;2 END OF FILE +;1 DEVICE HUNG OR REPORTING NON-DATA ERROR + +MIOTER==1 ;LOWEST IOCERR CODE USED +NIOTER==13. ;NUMBER " " + +;4.9-4.5 ALWAYS ZERO (USED BY IOPUSH FOR CHNL NUM) + +;SYS PERIPHERAL DEVICE CODES + +;1.6 INDICATES DIRECTORY DEVICE +;1.5 INDICATES NON PHYSICAL DEVICE + +SNTTY==1 +SNTDS==2 ;TERMINAL DISPLAY +SNLPD==3 ;DATA PRODUCTS LPT +SNVID==4 +SNBAT==5 +SNPLT==6 +SNPTP==7 +SNIMPX==10 +SNOMPX==11 +SNPTR==12 +SN340==13 ;340 AS ASCII DEVICE +;SN340I==14 ;INTERPRETED DISPLAY ON 340 +SNMTC==15 ;MAGTAPE +SNCOD==16 ;CODE DEVICE +SNTAB==17 +SNNUL==21 +SNJOB==22 +SNBOJ==23 +SNSPY==24 +SNSTY==25 +SNNET==26 ; Arpanet NCP +SNLPV==27 ;VOGUE LPT +SNSTK==30 ;STANFORD KEYBOARD +SNMSP==31 ;CROCK "IPC" FOR NOW +IFN CHAOSP,SNCHA==32 ;CHAOS NET +IFN TCPP,SNTCP==33 ; Internet TCP/IP network device +SNTRAP==34 ;TRAP "DEVICE" +IFN INETP,SNIPQ==35 ; Internet Queue +IFN KS10P,SNUBI==36 ; Unibus interrupt +SNUTC==41 +SN2311==43 +SNFUSR==60 +SNUSR==61 +SNCLK==62 ;CLO, CLU, & CLI +SNDIR==63 +SNPDP==64 ;PDP6 +SNDIRH==65 ;DIRHNG "DEVICE" +SNLCK==66 ;LOCK "DEVICE" + +SUBTTL SYSTEM VERSION NUMBER & MISC MACROS + +ITSMCH==: ; Define SIXBIT machine name symbol +ITSVRS==:.FNAM2 ; Preserve SIXBIT symbol value of ITS version # +FNM==ITSVRS ;SRI GETS VERSION NUMBER + ;WORKS FOR DECIMAL IGNORES LOW ORDER NON-NUMERIC CHRS +DEFINE VNAM +.TAG FOO + ZZZQ==FNM&77 + IFGE ZZZQ-'0,IFLE ZZZQ-'9,.GO BAR + FNM==FNM_-6 + .GO FOO +.TAG BAR + ZZZQ==1 + SRI==0 +.TAG MUM + IFE FNM,.GO END + ZCHR==FNM&77-'0 + IFL ZCHR,.GO END + IFG ZCHR-9,.GO END + SRI==SRI+ZZZQ*ZCHR + ZZZQ==ZZZQ*10. + FNM==FNM_-6 + .GO MUM +.TAG END + TERMIN + +IF1 VNAM + +DEFINE SRITYP A +ZZZ==10 ;SAVE OLD RADIX +RADIX 10. + MOVEI I,[MNAME [.ASCII ? +] ITS !SRI A?] +RADIX ZZZ + TERMIN + + ;"MONTHS OF THE YEAR" MACRO + +DEFINE MNIRP A +IRPS M,,[JAN:FEB:MAR:APR: +MAY:JUN:JUL:AUG: +SEP:OCT:NOV:DEC:]L,,[31. 29. 31. 30. +31. 30. 31. 31. +30. 31. 30. 31.] +A +TERMIN +TERMIN + +FOO==-1 ;ACCUMULATED VALUE FOR FOLLOWING DEFINITION: + +MNIRP [M==FOO +FOO==FOO+L] ;JAN=-1, FEB=30., MAR=59., ETC. + +DEFINE INFORM A,B +IF1,[PRINTX \A = B +\]TERMIN + +ZZZ==10 +RADIX 10. +INFORM VERSION,\SRI +RADIX ZZZ + +SSYS==0 ;LENGTH OF SYS CODE + +DEFINE EBLK +IFN CKPAR,.ERR LOSS AT EBLK +CKPAR==1 +IFE .-CKZZ,.STOP ;NO WORDS BETWEEN BBLK AND EBLK +CONC CK,\CKNUM,==CKZZ-.,,CKZZ +CKNUM==CKNUM+1 +SSYS==SSYS+.-CKZZ +TERMIN + +DEFINE BBLK +CKZZ==. +IFE CKPAR,.ERR LOSS AT BBLK +CKPAR==0 +TERMIN + +CKPAR==1 +CKNUM==0 + + +;INSERT CALL TO THIS MACRO AT ANY PLACE IT IS POSSIBLE TO PCLSR +;(IF IT IS DESIRED FOR PCLSR TEST FEATURE TO TEST THAT SECTION) + +DEFINE PCLT +IFN PCLSW,[ + SKIPE PCLDBM + PUSHJ P,PCLTST +] +TERMIN + +DEFINE PCLTH A +IFN PCLSW,[ + SKIPN PCLDBM + JRST .+3 + PUSHJ P,PCLTSH + A +] +TERMIN + +DEFINE PI2SAF + CONSO PI,20000 + CONSO PI,40 + CAIA + JRST 4,. ;PI 2 NOT OFF AND NOT IN PROGRESS +TERMIN + +SUBTTL DEFINE EXEC PAGES + +EXPGN==0 + +DEFINE EXECPG X +X==EXPGN +EXPGN==EXPGN+1 +ZZQ==&1 +ZZQQ==X_-1 +.!X==220000*ZZQ+2200,,ZZQQ +TERMIN + +;EXEC MAP ASSIGNMENTS +IFN 340P,[ +EXECPG 340P1, ;USED TO FETCH + TRACE 340 PNTRS +EXECPG 340P2, +REPEAT N340PB,CONC [EXECPG DPG]\.RPCNT,; ;DATA AREA PNTRS FOR 340 DATA +] +EXECPG CORJF, ;CORE JOB FROM PAGE +EXECPG CORJT, ;CORE JOB TO PAGE +IFN VIDP,[ +EXECPG VSB1, ;.VSCAN B1 +EXECPG VSB2, ;.VSCAN B2 +] +IFN TEN11P,[ +EXECPG T11CP, ;TEN11 CONTROL PAGE +] +EXECPG PAREP, ;USED BY SYSTEM IN ITS DILIGENT EFFORTS TO FIX PARITY ERRORS + +IFN ECCMEM, EXECPG ECCPG, ;PAGE USED TO ACCESS ECC HISTORY + +IFN XGP,[ +EXECPG XGPC, ;LOW 2K OF XGP PDP-11 (USED TO TRACE BUFF POINTERS) +EXECPG XGPB, ;2K BUFFER IN PDP-11 (CHANGES LOCATION) +EXECPG XGPUB, ;XGP USER CORE EXEC PG SETUP TO POINT TO USER CORE DURING XGPIM SYSTEM CALL +] +IFN N11TYS,[ +REPEAT NTTPG,[CONC [EXECPG TTPG]\.RPCNT, +] +REPEAT NTVBP,[CONC [EXECPG TTR]\.RPCNT, +]] +IFN CHAOSP,[ IFN T11CHP,[ +EXECPG CHSPG ;CHAOS NET 10-11 COMMUNICATION PAGE +T11CHS=400000+CHSPG*2000 +]] ;CHAOSP, T11CHP +;^ INSERT NEW EXEC PAGES HERE +;EXEC PAGES BELOW THIS POINT WILL BE COPYABLE BY USERS +REPEAT NMMP,CONC [EXECPG MMP]\.RPCNT,; ;MMP TABLE + MMP=MMP0*2000+400000 ;VIRTUAL ADDRESS OF MMP +EXPUNGE EXECPG +NEXPGS==EXPGN ;# EXEC PGS USED + +SUBTTL LOW CORE + +.YSTGWD ;STORAGE WORDS OKAY NOW + +IFN KL10P, LOC EPT+1000 ;KL needs a full DEC page for EPT +IFN KS10P,[ + IFE KSIMP, LOC EPT+1000 ;KS needs a full DEC page, too, + IFN KSIMP, LOC EPT+2000 ; unless you are losing even worse. +] + +PATB=. +LOC 20 + BBLK + +IFN KS10P,[ +LOC 30 ; 8080 communications area + EBLK +] ;IFN KS10P + +IFN TM10B,[ + LOC 30 + EBLK +MICWA: MIOWD + 0 +IFE RP10P+RH10P,BBLK +] +IFN RP10P+RH10P,[ + LOC 32 +IFE TM10B,EBLK +QICWA: QIOWD + 0 +IFN QRDCMP,[ +RCICWA: 0 + 0 +];QRDCMP + BBLK +] +IFN E.SP,[ + LOC 34 + E.SPM ;POINTER , NEVER CHANGES +] + +IFE KS10P,[ +LOC 37 + EBLK +] ;IFE KS10P + +LOC 41 +IFN KA10P, JSR UUOH ;UUO TRAP +IFE KA10P, JSR LUUOEX ;USER UUO IN EXEC MODE (ERROR) + +LOC PI0LOC+2 + REPEAT 2, JSR RINT1 + REPEAT 6*2, JSR RINT ;INITIALIZE ANY UNUSED PI LOCNS + +LOC 61 +IFN KA10P, JSR 60H ;60 TRAP +IFN C1MXP, REPEAT 2*7., JSR RINT1 ;INITIALIZE C1MPX LOCNS + +LOC PI0LOC+2*APRCHN + JSR CLKBRK ;PROCESSOR OR CLOCK INTERRUPT + JRST 4,. + +LOC PI0LOC+2*LPTCHN + JSR LPTBRK ;LPT,DISPLAY,PTP,PTR,OTHER PROCESSOR +IFN 340P, JSR DRECYC ;HACK HACK + +LOC PI0LOC+2*TTYCHN + JSR TTYBRK ;TTY,DATAPOINT KLUDGE + JRST 4,. + +LOC PI0LOC+2*UTCCHN + JSR UTCBRK ;MICRO TAPE OR DISK (S) + JRST 4,. + +IFN E.SP,[ +LOC PI0LOC+2*DISCHN + JSR ESBRK + JRST 4,. +] +IFN 340P,[ +LOC PI0LOC+2*DISCHN + JSR DIGNOR ;340 DISPLAY BLKO GETS PATCHED IN HERE + CONO PI,4000+200_<-SDCHN> ;HACK HACK +] +IFN CH10P+CH11P,[ +LOC PI0LOC+2*CHXCHN + JSR CHXBRK + JRST 4,. +];CH10P + +IFN VIDP,[ +LOC PI0LOC+2*OMPCHN + JSR OMPXBK ;OUTPUT MPXR, NVID, ETC. + JRST 4,. +] +IFN KAIMP,[ +LOC PI0LOC+2*IMPCHN + JSR IMPBRK +LOC IMPILC + JSR IMPIBK + 0 +LOC IMPOLC + JSR IMPOBK + 0 +] ; IFN KAIMP + +IFN KL10P,[ +LOC PFOPC +PFOPC: 0 ;PAGE FAIL OLD PC STORED HERE +PFNPC: PFAIL ;WHERE TO GO FOR PAGE FAIL + +LOC EPTDIA +EPTDIA: JRST SALV ;STD COMMAND START ADDRESS ("DIAGNOSTIC") +EPTDDT: JRST DDT ;DDT COMMAND START ADDRESS +EPTSTL: JRST DSKDMP ;STL COMMAND START ADDRESS ("LOADER") +EPTITS: JRST BEG ;STM COMMAND START ADDRESS ("MONITOR") + ;SALV THEN GO +LOC EPTTR1 +EPTTR1: CAI ;ARITH OVERFLOW EXEC MODE IGNORED +EPTTR2: JSR ILLTRP ;PDL OVERFLOW EXEC MODE IS AN ERROR +EPTTR3: JSR ILLTRP ;ONE PROC CODE? + +LOC DTEBPO +DTEBPO: 0 ;BYTE TRANSFER NOT USED +DTEBPI: 0 ;BYTE TRANSFER NOT USED +DTELOC: ;INTERRUPT FROM CONSOLE 11 +IFE PDCLKP, JSR DTEBRK ;IF USING 11 FOR CLOCK, FIRST CHECK FOR CLOCK INTR +.ELSE JSR TTYBRK ;OTHERWISE JUST USING 11 FOR TTYS. + 0 ;UNUSED WORD +DTEPRO: 0 ;NO PROTECTED EXAMINES +DTERLO: 0 ;.. +DTEPRI: 0 ;NOR PROTECTED DEPOSITS +DTERLI: 0 ;.. + +LOC EPT+430 +REPEAT 8,MUUOEX ;HALT IF UUO IN PROCESSOR BREAK ROUTINES + +LOC EPTEBC +EPTEBC: 0 ? 0 ;EBOX COUNT FOR PROC BRK ROUTINES AND NULL JOB +EPTMBC: 0 ? 0 ;MBOX DITTO + +LOC TIMLOC + JSR OVHBRK ;INTERVAL TIMER INTERRUPT, EVERY 39 MILLISEC ON CHANNEL 1 + +;OVHMTR MACRO IS USED TO CONSTRUCT TABLE OF AREAS OF EXEC CORE TO BE METERED +;ON KL10 OVHBRK CHECKS WHERE THE PC IS IF IT IS IN EXEC MODE. + +DEFINE OVHMTR NAME ;NAME IS 3 CHARACTERS NAMING THE REGION THAT BEGINS HERE +OVHMT1 NAME,\. ;EVALUATE "." AT THIS POINT IN TIME +TERMIN + +;KLUDGE MACRO +DEFINE OVHMT1 NAME,POINT +OVHTAB [DEFINE OVHTAB FOO +FOO] <(SIXBIT/NAME/)>,,POINT ? 0 +TERMIN +TERMIN + +;THIS IS THE CORRESPONDING REMOTE MACRO +DEFINE OVHTAB FOO +FOO +TERMIN +] ;END OF IFN KL10P + +IFN KS10P,[ + +LOC EPTUIT+UBAQ + UBAQIB ; Pointer to interrupt table for Unibus Q (dsk) + +LOC EPTUIT+UBAI + UBAIIB ; Pointer to interrupt table for Unibus I (other) + +LOC EPTPFW +EPTPFW: 0 ; Page fail word +EPTPFO: 0 ; Page fail old PC +EPTPFN: PFAIL ; Page fail new PC + +IRP I,,[1,2,3,4,5,6,7] +LOC EPTP!I!W +EPTP!I!W: 0 ; Page fail word +EPTP!I!O: 0 ; Page fail old PC +EPTP!I!N: PF!I!AIL ; Page fail new PC at PI level I +TERMIN + +LOC EPTTR1 +EPTTR1: CAI ;ARITH OVERFLOW EXEC MODE IGNORED +EPTTR2: JSR ILLTRP ;PDL OVERFLOW EXEC MODE IS AN ERROR +EPTTR3: JSR ILLTRP ;TRAP 3 SHOULD NOT HAPPEN + +LOC EPT1PO +EPT1PO: 0 ;ONE-PROCEED OLD-PC +EPT1PN: MUUOEX ;ONE-PROCEED SHOULD NOT HAPPEN IN UPT=EPT MODE + +LOC EPTUEN +EPTUEN: MUUOEX ;HALT IF UUO IN PROCESSOR BREAK ROUTINES +EPTUET: MUUOEX +LOC EPTUUN +EPTUUN: MUUOEX +EPTUUT: MUUOEX + +IFN KSIMP,[ +;Here because with EPT at 0, this is the second half of physical +; page 0, which is uncached, which we want, and otherwise unused. +; +LOC EPT+1000 ; IMP data reformatting buffers +IMPIBF: BLOCK 400 +IMPBFS==.-IMPIBF +IMPOBF: BLOCK 400 +] + +;OVHMTR MACRO IS USED TO CONSTRUCT TABLE OF AREAS OF EXEC CORE TO BE METERED +;ON KS10 PC SAMPLING FACILITY IS USED, 60-CYCLE CLOCK COLLECTS THAT DATA +;NOTE THAT THE TABLE FORMAT IS NOT THE SAME AS ON KL10, FOR SPEED REASONS + +DEFINE OVHMTR NAME ;NAME IS 3 CHARACTERS NAMING THE REGION THAT BEGINS HERE +OVHMT1 NAME,\. ;EVALUATE "." AT THIS POINT IN TIME +TERMIN + +;KLUDGE MACRO +DEFINE OVHMT1 NAME,POINT +OVHTAB [DEFINE OVHTAB FOO +FOO] POINT,,<(SIXBIT/NAME/)> +TERMIN +TERMIN + +;THIS IS THE CORRESPONDING REMOTE MACRO +DEFINE OVHTAB FOO +FOO +TERMIN +] ;END OF IFN KS10P + +IFN DL10P,[ ;DL10 COMMUNICATIONS AREA IN NON-ENCACHED LOW CORE +IFN KL10P, LOC 500 ;500-777 RESERVED FOR DL10 AREA AND BUFFERS +IFN KA10P, LOC 100 ;IF KA10, PUT DL10 AREA JUST BELOW START OF SYSTEM +IFN KS10P, .ERR DL10 on KS10 system? + +DL10AR: JSR TTYBRK ;INTERRUPT INSTRUCTION (NOT ACTUALLY USED) + +;FOLLOWING LOCATIONS MUST AGREE WITH IOELEVEN PROGRAM + +DL10VR: NDLTYS_8+NFDLTY ;"I/O VERSION NUMBER" +DL10UP: 0 ;INCREMENTED BY -11 EVERY 1/60 SECOND. + ;SETOM'ED BY 10 EVERY 1/2 SECOND. DETECTS UP/DOWNNESS. + +DL10SO: 0 ;LINE # TO SET OUTPUT DONE FOR, SET BY -10, CLEARED BY -11. + +DL10IL: 0 ;LINE # WITH INPUT AVAILABLE. CLEARED BY -10 AFTER CHAR READ. +DL10IC: 0 ;CHARACTER RECEIVED FROM THAT LINE. + +DL10OD: 0 ;LINE # WITH OUTPUT DONE. CLEARED BY -10 WHEN PROCESSED. +DL10BS: 0 ;BUFFER SIZE FOR THAT LINE. + +DL10BP: 0 ;WIERD DL10 BYTE POINTER TO TTY OUTPUT BUFFER. +DL10CC: 0 ;NUMBER OF CHARACTERS BEING OUTPUT TO TTY. +DL10LN: 0 ;LINE # OUTPUT BEING SENT TO. CLEARED BY -11 WHEN GOBBLED. + +DL10CL: 0 ;DIALUP LINE CONNECT OR DISCONNECT INFO. SET BY 11, 0'D BY 10. + ;0000NN => LINE # NN DISCONNECTED. + ;01RTNN => LINE # NN CONNECTED, %TTISP=R, %TTOSP=T. + +DL10PL: 0 ;LINE # TO SET PARAMETERS OF. CLEARED BY -11 WHEN PROCESSED. +DL10PR: 0 ;VALUE OF DH11 LPR REGISTER. +DL10PS: 0 ;NUMBER OF BYTES OF OUTPUT BUFFERING DESIRED. + +DL10XD: 0 ;1=EXAMINE -11 CORE, 2=DEPOSIT. CLEARED BY -11 WHEN DONE. +DL10XA: 0 ;EXAMINE/DEPOSIT ADDRESS +DL10XW: 0 ;EXAMINE/DEPOSIT WORD + +GLPTBP: 0 ;BYTE POINTER TO BUFFER FOR GOULD LPT +GLPTBC: 0 ;BYTE COUNT " " - IF NONZERO BUFFER IS ACTIVE BY PDP11. +GLPTER: 0 ;NONZERO => PDP11 CLAIMS PRINTER IS BROKEN. +GLPGRF: 0 ;NONZERO => GRAPHICS MODE (SET BY 10). + +;CHAOS NET SHARED VARIABLES +DLCINI: 1 ;THE COMMENTS ARE IN THE CHAOS FILE +DLCSP1: 0 +DLCSP2: 0 +DLCSS1: 0 +DLCSS2: 0 +DLCRP1: 0 +DLCRP2: 0 +DLCRS1: 0 +DLCRS2: 0 + +;^ ADD MORE HERE + +DLXEND:: ;END OF ASSIGNED DL10 AREA + +IFG .-DL10AR-100, .ERR DL-10 AREA TOO BIG, CHANGE CONO IN TSS INITIALIZATION +LOC DL10AR+100 ;SKIP OVER 11-ACCESSIBLE AREA + +DL10BF: BLOCK <261.+3>/4 ;OUTPUT BUFFER, 8-BIT BYTES. HAS TO BE NON-ENCACHED. + +IFN GLPTP,[ +GLPBSZ==255. ;BUFFER SIZE IN WORDS. MAXIMUM POSSIBLE WITHOUT MODIFYING (ELIMINATING) + ;"WORD COUNT" HARDWARE IN DL-10. +GLPMPP: 0 ;MAIN PROGRAM POINTER - IF NONZERO BUFFER IS ACTIVE BY M.P. LEVEL (PDP10) +GLPMPC: 0 ;MAIN PROGRAM COUNTER +GLPTBF: BLOCK GLPBSZ ;ONE BUFFER FOR NOW +] ;END IFN GLPTP + +IFN KL10P, IFG .-1000,.ERR DL10 STORAGE TOO BIG, DOESN'T FIT IN UNENCACHED PAGE +IFN KA10P, PATB=. ;MOVE ORIGIN OF SYSTEM UP +] ;END IFN DL10P + +IFN NETYS,[ ;ASSEMBLE DTE20 CONTROL AREA +IFE KL10P, .ERR DTE20 WITHOUT KL10? +LOC 400 + +DTEVER: NETYS_8+NFETY ;400 I/O VERSION NUMBER, SET BY 10, CHECKED BY 11 + +DTECHK: 0 ;401 INCREMENTED BY 11 60 TIMES PER SECOND + ;SETOMED BY 10 EVERY HALF SECOND. + ;USED TO TELL 11 THAT 10 IS UP. + +DTEINP: -1 ;402 -1 IF IDLE, ELSE INPUT REQUEST FROM 10 TO 11 + ;SETUP DTEBPI IN EPT AND DO DATAO DTE, BEFORE SETTING THIS. + ;SEE COMMENTS BELOW DTEOUT FOR WHAT GOES HERE +DTEOUT: -1 ;403 -1 IF IDLE, ELSE OUTPUT REQUEST FROM 10 TO 11 + ;SETUP DTEBPO IN EPT BEFORE SETTING THIS. + ;CONTENTS OF DTEINP AND DTEOUT ARE DESCRIBED BELOW. + ;THESE ARE SET BY THE 10, SETOMED BY 11 WHEN TRANSFER STARTS. + ;RH # BYTES EXPECTED. LH COMMAND+LINE#. COMMANDS ARE: + %DCTYO==1000 ;TELETYPE OUTPUT (NOTE 4.1=0 INPUT, =1 OUTPUT) + %DCETI==2000 ;ETHERNET INPUT (N.Y.I.) + %DCETO==3000 ;ETHERNET OUTPUT (N.Y.I.) + +DTELSP: -1 ;404 LINE # WHOSE SPEED IS TO BE SET, SET BY 10, SETOMED BY 11 +DTELPR: -1 ;405 CORRESPONDING DH11 LINE PARAMETER REGISTER,,BUFFER SIZE + +DTEOST: -1 ;406 LINE# TO START OUTPUT ON (SET OUTPUT DONE). + ;SET BY 10, SETOMED BY 11 + + BLOCK 1 ;407 NOT USED + +DTETYI: -1 ;410 TELETYPE INPUT. SET BY 11, SETOMED BY 10. + ;LH LINE#,,RH CHAR RCVED. + +DTEODN: -1 ;411 TELETYPE OUTPUT DONE. SET BY 11, SETOMED BY 10. + ;LH LINE#,,RH BUFFER SIZE. + +DTEHNG: -1 ;412 HANGUP/DIALIN WORD. SET BY 11, SETOMED BY 10. + ;0000NN LINE # NN HUNG UP. + ;01RTNN LINE # NN HAS SPEED RCV=R, XMT=T (CODES AS IN TTYTYP) + +;^ ADD MORE LOCATIONS HERE, NOT TO EXCEED 437 + +;LOCATIONS 440-457 ARE KNOWN ABOUT BY BOTH IOELEV AND KLDCP, +;USED MOSTLY FOR NON-TIMESHARING PROGRAMS. +];NETYS + +LOC PATB + + ;FOR VARIABLES (MONITORABLE WITH KEYS) +NSKED: 0 ;# TIMES NON-NULL JOB IS RUN +NNSKED: 0 ;# TIMES NULL JOB IS RUN +NRSKED: 0 ;# OF FULL SCHEDULES (MUST SCAN ALL JOBS) +NSSKED: 0 ;# OF SCHEDULES SAVED BY SCHBLN FEATURE. +NRESKED:0 ;# TIMES A JOB SCHEDULED JUST AFTER IT RAN. +NSCHDU: 0 ;TOTAL NUMBER OF JOBS FOUND RUNNABLE IN FULL SCHEDULES +NNULBK: 0 ;# OF CONSECUTIVE BLOCKS OF NULLTIME. +NUINT: 0 ;# TIMES USER GIVEN INTERRUPT +NAUINT: 0 ;# ATTEMPTED USER INT (POSSIBLY UNSUCCESSFUL DUE TO PG FAULT) +NPCLSR: 0 ;# ATT TO PCLSR +NEPCLS: 0 ;# PCLSRS WHERE JOB WAS IN EXEC MODE +NFPCLS: 0 ;# OF PCLSRS THAT FAILED (JOB WAS IN EXEC MODE AND NOT BLOCKED) +NSOUSR: 0 ;# ATT TO SWAP OUT USR +NSOPGS: 0 ;# TIMES THRU LOOP LOOKING FOR PG TO SWAP OUT +NPGSO: 0 ;# TIMES AT SWOPG +NAGEAB: 0 ;# TIMES SWAP OUT ABORTED BY AGE BITS +NSHRAB: 0 ;# TIMES SWAP OUT ABORTED BY SHARING +NPGFLT: 0 ;# PAGE FAULT (ALL CAUSES) +NCLKI: 0 ;# CHNL 7 INTS (ALL CAUSES) +NPGLD: 0 ;# TIMES AT PGLDU +NUFLS: 0 ;# TIMES AT UFLS +NTUSB: 0 ;# TIMES USER SWAP BLOCKED +NTSBUP: 0 ;# TIMES SWAP BLOCKED USER TOOK PAGE FAULT AND LET IN +NTSBUB: 0 ;# TIMES SWAP BLOCKED USER TOOK PAGE FAULT AND BLOCKED +NTSBUU: 0 ;# TIMES SWAP BLOCKED USER UNBLOCKED BEFORE TIME (MEM APPARENTLY AVAIL) +NAGES: 0 ;# TIMES AROUND PAGE-AGEING LOOP + +;THE FOLLOWING FOUR MUST BE CONSECUTIVE +NRPI: 0 ;# REFS TO PAGE IN (BUT MAP WAS NOT SET UP, ETC) +NRPCI: 0 ;# PAGE FAULTS REFS TO PAGE COMMING IN +NRPO: 0 ;# REFS TO PAGE OUT +NRPGO: 0 ;# TO PAGES GOING OUT +CLKBRS: 0 ;CLKBRK COPIED INTO HERE (SINCE CLKBRK GETS CHANGED) + +PAT: IFG .-PATB-40,.ERR PAT TOO HIGH + +LOC PATB+40 + +BBLK + +PATCH: BLOCK 140 ;PATCH SPACE CODE AND CONSTANTS + +EBLK + +VPATCH: +VPAT: +BLOCK 40 ;PATCH SPACE VARIABLES + +SUBTTL PROCESSOR BREAK ROUTINES + +DEFINE CLKSAV BRK=CLKBRK +IFE KA10P, XCT CLCXSV ;DATAI PAG,CLCX(U) + XCT CLUSAV ;STORE U IN AC17S FOR CURRENT USER (UNLESS NULL JOB) + MOVE U,BRK ;SAVE AWAY BRK + MOVEM U,CLKBRS +IFSN BRK,CLKBRK, MOVEM U,CLKBRK ;SAVE IN CLKBRK IF NOT CLKBRK +TERMIN + +IFE KA10P,[ +DEFINE CLKLEV ;ENTER CLOCK-LEVEL CONTEXT + SPCCTX 0,1,EPT ;UPT = EPT; CLOCK LEVEL CONTEXT. + MOVE U,USER + JRST 2,@.+1 ;MAKE XCTR WORK RIGHT + %PSPCU,,.+1 + MOVE P,CPDLP +TERMIN +] ;IFE KA10P +IFN KA10P,[ +DEFINE CLKLEV + MOVE U,USER + MOVE P,CPDLP +TERMIN +] ;IFN KA10P + +IFN KL10P,[ ;CODE USED IF GETTING 60-CYCLE CLOCK FROM PDP11 (IN CASE MAIN CLOCK DOWN) + +;HACKING THE DTE: + +;THE TTY CODE ASSUMES, SINCE THE DTE20 IS USED BY ITS SOLELY AS +;THE INTERFACE TO THE CONSOLE TTY AND THE LINE-FREQUENCY CLOCK, +;THAT IT MAY FREELY GIVE THE "MONITOR TTY OUTPUT" COMMAND WHEN +;THE "MONITOR TTY OUTPUT DONE" INTERRUPT IS RECEIVED. ANY CODE +;WHICH HACKS THE DTE OTHER THAN AT PI LEVEL OR IN ITS INITIALIZATION +;MUST THEREFORE OBSERVE THE FOLLOWING PROTOCOL: +; CONO PI,DTEOFF +; SKIPN DTEFLG ;WAIT FOR MONITOR TTY OUTPUT TO GO THROUGH +; JRST .-1 +; SETZM DTEFLG +; ;HERE SET DTECMD +; CONO DTE,%DBL11 +; SKIPN DTEFLG ;WAIT FOR THIS COMMAND TO GO THROUGH +; JRST .-1 +; CONO PI,DTEON +; + +DTEBRK: 0 +BBLK + CONSO PI,1_<7-APRCHN> ;TEMPORARY (I HOPE) HARDWARE BUG IN KL10 PI HARDWARE + JRST 4,. ;ALLEGEDLY FIXED + CONO PI,TTYRQ ;REALLY WANTED TO INTERRUPT ON TTY CHANNEL, + JFCL ; BUT HAVE TO DO IT THIS WAY DUE TO + JFCL ; MISFEATURES IN THE PI HARDWARE + SKIPN DTECLK ;DON'T TAKE OUT THE JFCLS!! + JRST 12,@DTEBRK + CLKSAV DTEBRK ;TAKE CLOCK INTERRUPT + JRST CLKB2A +EBLK +];KL10P + +CLKBRK: 0 ;PC SAVED HERE BY JSR FOR CLOCK INT. + +BBLK +IFN KL10P,[ + CONSO PI,1_<7-APRCHN> ;HARDWARE BUG IN KL10 PI SYSTEM + JRST 4,. ;ALLEGEDLY FIXED +] +IFE KA10P, CONO PI,020000+200_<-APRCHN> ;BAG-BITING DEC LOSERS CHANGED + ;FUNCTIONAL SPECIFICATION OF + ;PROGRAMMED REQUESTS +CLKBR2: CLKSAV ;SAVE AC BLK STATUS AND U. +CLKB2A: AOS NCLKI + SKIPGE U,USER ;PICK UP INDEX OF CURRENT USER, SKIP UNLESS NULL JOB + JRST [ SPM UPGML ;JUMP IF NULL JOB WAS RUNNING + JRST CLKBKR ] + SPM UPGML(U) ;STORE PAGE MAP AWAY + AOSN UFLSF ;SKIP UNLESS GOT HERE FROM UFL6 + JRST CLUFLS + MOVEM T,AC16S(U) ;STORE AWAY T + MOVEI T,AC0S(U) + BLT T,AC15S(U) ;STORE REST OF ACS +CLKBKR: CLKLEV ;SET UP CROCK-LEVEL CONTEXT HARDWARE + +;;; CHECK FOR THINGS OTHER THAN CLOCK TICKS (PAR ERR, PG FAULT, NXM, PDLOV, +;;; AROV AND ARFOV ARE POSSIBLE ON ONE MACHINE OR THE OTHER). + +IFN KA10P,[ + CONSZ 270220 ;CHECK PDL OV, MEM PROTECT, NXM, FOV, AR OV + JRST CLKB1 ;JUMP ON LOSSAGE +CLKB1D: CONSZ PI,200000 + JRST CLKB1E ;PARITY +] ;KA10P + +IFN KL10P,[ + AOSG PFAILF + JRST PFA6 ;PAGE FAULT + CONSZ 7740 ;This is all but the cache sweep done bit (=20). + JRST CLKB2 ;APR ERROR INTERRUPT +] ;KL10P + +IFN KS10P,[ + AOSG PFAILF + JRST PFLU2 + CONSZ 7620 ;This is all but the interval timer's bit (=40). + JRST CLKBKS ; (Memory ECC (=100) doesn't interrupt) + CONSO 40 + JRST CLK1F +] ;KS10P + +IFN PDCLKP\KA10P,[ ;IF 60 HZ CLOCK IS IN HARDWARE + CONSO CLK,CLKINT + JRST CLK1F ;INTERRUPT NOT FROM CLOCK, MUST BE SPURIOUS (OR + ;PREEMPT) +] ;PDCLKP\KA10P + +;DROP THROUGH FOR PLAIN CLOCK-TICK. + ; +; 60-CYCLE CLOCK INTERRUPT +; +CLKTIC: +;IFN 340P, DATAI CLK1,LQTIM + SOSG @CLROOT ;COUNT DOWN, SKIP IF NOT YET TO NEXT REQUEST + JRST CLQBRK ;SERVICE CLOCK QUEUE REQUEST +CLQBRT: +IFN KS10P, CONO 020040+APRCHN ;Clear interval flag +IFN PDCLKP\KA10P, CONO CLK,CLKINT+APRCHN ;Clear hardware clock flag +IFE PDCLKP\KA10P\KS10P, SETZM DTECLK ;Clear software clock flag +IFN KA10P,[ + DATAI CLKBSW + SKIPGE CLKBSW +] ;KA10P +IFN KL10P, SKIPGE DTESWR +IFN KS10P, SKIPE 8SWIT0 + BUG DDT,[SWITCH 0 IS UP] +IFN KS10P, SETZM 8SWIT0 ; Allow hacker to P +IFN CHAOSP, IFN T11CHP, PUSHJ P,T11WAK ;RUN TEN-11 CHAOS NET INTERFACE +IFN XGP,[ + SKIPL XGPUSR + PUSHJ P,XGPCLK +] +IFN 340P,[ + AOSGE T,DTIME + JRST DSTPD ;WAIT IF DTIME CLOBERED DUE TO RATE EXCEEDED + CAILE T,2 + MOVEI T,2 + MOVEM T,DTIME + SKIPL CDISOF + SKIPGE DISOFF + JRST DSTPD + AOSG DISON + CONO DIS,1100\SDCHN_3\DISCHN ;RESTART DISPLAY +DSTPD: +] +IFN E.SP,[ + SKIPN T,E.SPGW ; E&S WAITING FOR PAGE + JRST E.SOK + HRRZM T,DISSPG ; SAVE FOR SWPPIN + SKIPL T,DISUSR ; -1 IMPLIES NO USER + MOVEM T,DISSWI ; USER INDEX FOR SWPPIN +E.SOK: +] +IFN N11TYS,[ + SKIPE @TT11HD ;ANY INPUT FROM PDP11? + PUSHJ P,TT11IN ;YES, DO INPUT INT LVL STUFF FOR IT,. +] +IFN DZ11P,[ + PUSHJ P,DZSCAN ;SCAN DZ'S FOR INPUT +] + MOVS T,TTERQS + CAIE T,(MOVE) + PUSHJ P,TTECH ;CHARACTERS TO BE ECHO ED +IFN NETP,[ + SKIPE STYNTA ;IF THERE ARE STY'S CONNECTED TO NETWORK I/O, + PUSHJ P,STYNTC ;XFER BETWEEN THEM. +] +IFN KS10P, PUSHJ P,OVHCLK + SETCMM CLKFL1 + SKIPL CLKFL1 + AOS TIME ;GET HERE EVERY THIRTIETH OF A SECOND +IFN PAGPRE,[ + SKIPE PREEMP ;CHECK FOR PRE-EMPTION INTERRUPT + JRST PRESCD +];PAGPRE + AOSG SCHFLG + JRST CLKB5 ;TIME NOT UP + AOS NLPCLK + JRST SCHED ;SCHEDULE + +CLK1F: +IFN PAGPRE,[ + SKIPE PREEMP ;CHECK FOR PRE-EMPTION INTERRUPT. THIS IS HERE + JRST PRESCD ; BECAUSE OF SCREW CASE WHEREBY DLSRCH PREVENTS + ; PREEMP FROM DOING ANYTHING, AND PREEMP WOULD + ; PREVENT CLOCK FLAG FROM GETTING CLEARED IF IT WAS + ; TESTED BEFORE CLOCK. +];PAGPRE +; MOVEI J,APRCHN ;DO NOT TAKE THESE OUT WITHOUT SEEING RG!!!! +; JSP E,SPUR +; JRST SCHED + AOS CHSPUR+APRCHN ;COUNT SPURIOUS INT + JRST SCHED ;(MIGHT HAVE BEEN RUNNING NULL JOB) + +IFN PAGPRE,[ +PRESCD: AOS NLPPRE + JRST SCHED +];PAGPRE + +IFN KL10P,[ +CLKB2: CONSZ 2000 ;NXM + PUSHJ P,MEMHNG + CONSZ 1040 ;POWER FAIL OR I/O PAGE FAIL + BUG HALT,[KL: POWER FAIL OR I/O PAGE FAIL] + CONSZ 300 ;CACHE DIR OR PT DIR PAR ERR. + BUG HALT,[KL: CACHE OR MAP DIR PAR ERR] + CONSO 4400 ;SBUS ERR OR MB PAR ERR + JRST SCHED ;CALLED MEMHNG, AND NOTHING ELSE => SCHEDULE. + SETOM PARRSN ;TEL PAR ERR SCANNER THIS IS AN INTERRUPT, NOT A PG FAIL. + RDERA PARERA ;STORE ADDR OF PAR ERR. + JRST CLKB1E +] ;IFN KL10P + +IFN KS10P,[ +CLKBKS: CONSZ 7600 ; Any bad guys? (8080 -> KS is 20, Interval is 40, + JRST CLKKS1 ; Memory ECC is 100.) + CONO 020020+APRCHN ; 8080 wants service. Clear the bit. + MOVEI I,NFKSTY ; TTY # (fancy name for 0) + CONO PI,TTYOFF ; Pretend this is TTY interrupt level. + SKIPN A,8CTYIN ; Any input from 8080? + JRST CLKKS2 + SETZM 8CTYIN ; Yes: Make room for more. + PUSHJ P,NTYI1 ; Stuff it into the tty. + MOVEI I,NFKSTY ; Just in case... +CLKKS2: SKIPN 8CTYOT ; Room for output yet? + PUSHJ P,TYPSC ; Yes: Get some now. + CONO PI,TTYON ; No: 8080 will wake us up later. + JRST SCHED ; Null job might have been running. + +CLKKS1: CONSZ 1000 ;Power failure + BUG HALT,[KS: POWER FAIL] + CONSZ 6000 ;KS -> 8080 or Flag 24 + BUG HALT,[KS: KS->8080 FLAG OR FLAG 24 SET] + CONSZ 400 ;NXM + PUSHJ P,MEMHNG + CONSO 200 ;Bad memory data + JRST SCHED + IORD B,[KSECCS] + MOVEM B,PARERA + JRST CLKB1E + +] ;IFN KS10P + +CLUFLS: CONO PI,CLKON ;FROM UFLS + CLKLEV + MOVE T,UPC(U) + MOVEM T,CLKBRK + AOS NUFLS + AOS NLPUFL + JRST SCHED2 + + ;CLOCK QUEUE SERVICE +CLQBRK: SKIPG U,CLROOT ;GET POINTER TO CURRENT BLOCK + BUG ;CLK QUEUE SCREWED + SKIPG T,1(U) ;GET POINTER TO NEXT BLOCK + BUG ;CLK QUEUE SCREWED + MOVEM T,CLROOT ;SET UP POINTER FOR NEXT BLOCK + SETOM 1(U) ;INDICATE CURRENT BLOCK IDLE + XCT 2(U) ;EXECUTE REQUEST (PROBABLY A JRST) + ;FALL THROUGH IF SINGLE INST RQ +CLQRET: ;RETURN FROM REQUEST + SKIPN @CLROOT ;SKIP IF TIME TILL NEXT RQ NONZERO + JRST CLQBRK ;ZERO TIME DELTA, DO NEXT RQ + JRST CLQBRT ;RETURN TO CLOCK ROUTINE + +CLQTTR: JUMPE TT,CLQRET ;COMMON RETURN FOR TT IDLE FLAG +CLQREE: MOVEI E,CLQRET ;RE ENTER RQ + +;CLOCK OFF OR IN PROGRESS LEVEL ADD TO CLOCK QUEUE, CALL BY JSP E, + ; T HAS TIME TILL RQ IN 60'THS + ; C POINTS TO THREE WORD BLOCK, RQ'ED INST IS IN THIRD +CLQPUT: MOVEI B,CLROOT-1 +CLQPU2: MOVE A,B ;REPLACE POINTER TO PREV BLOCK WITH CURRENT + SKIPG B,1(B) ;GET LINK TO NEXT BLOCK + BUG ;CLK QUEUE SCREWED + SUB T,(B) ;SUBTRACT TIME DELTA FOR NEXT BLOCK + JUMPG T,CLQPU2 ;JUMP IF RQ LATER THAN CURRENT BLOCK + JUMPE T,CLQPU6 ;JUMP IF RQ SAME AS " " (COULD USE PU2 BUT THIS FASTER) + ADD T,(B) ;RQ EARLIER, ADD BACK + MOVEM T,(C) ;SET DELTA OF BLOCK BEING ADDED + SUB T,(B) ;COMPUTE NEG OF DELTA FOR NEXT BLOCK + MOVNM T,(B) ;SET TIME DELTA FOR NEXT BLOCK + MOVEM B,1(C) ;SET LINK OF NEW BLOCK TO NEXT + MOVEM C,1(A) ;SET LINK OF PREV BLOCK TO NEW + JRST (E) + +CLQPU6: SETZM (C) ;SET TIME DELTA OF NEW BLOCK TO ZERO + MOVE A,1(B) ;GET POINTER TO NEXT BLOCK + MOVEM A,1(C) ;SET POINTER OF NEW TO NEXT BLOCK + MOVEM C,1(B) ;SET POINT OF CURRENT TO NEW BLOCK + JRST (E) + +;MAIN PROG LEVEL ADD TO CLOCK QUEUE +;CALL BY PUSHJ P,CLQADD +;WITH POINTER TO BLOCK IN NEXT WORD AND TIME TILL RQ IN T IN 60'THS +;POINTER TO BLOCK SHOULD NOT BE INDEXED BY C + +CLQAD1: MOVEI T,1 ;RQ IN ONE TICK +CLQADD: PUSH P,C + MOVE C,@-1(P) ;GET BLOCK POINTER + MOVEI C,@C + SKIPL 1(C) ;SKIP IF IDLE + JRST POPCJ1 ;IGNORE THIS RQ, BLOCK ALREADY ACTIVE + PUSH P,A + PUSH P,B + PUSH P,E + SKIPN (C) ;DELTA WORD OF IDLE BLOCK SHOULD BE ZERO + SKIPG T ;TIME SHOULD BE NON-ZERO + BUG ;CLK QUEUE SCREWED + CONO PI,CLKOFF + JSP E,CLQPUT ;ADD RQ +CLQDE4: CONO PI,CLKON + POP P,E + POP P,B + POP P,A + JRST POPCJ1 + +;DELETE CLOCK QUEUE ENTRY +;CALL BY PUSHJ P,CLQDEL WITH POINTER TO BLOCK IN NEXT WORD +CLQDEL: PUSH P,C + MOVE C,@-1(P) ;GET BLOCK POINTER + MOVEI C,@C + CONO PI,CLKOFF + SKIPGE 1(C) ;IGNORE RQ TO DELETE IF IDLE + JRST CKOCJ1 + PUSH P,A + PUSH P,B + PUSH P,E + JSP E,CLQCLR + JRST CLQDE4 + +CLQCLR: MOVEI B,CLROOT-1 ;CLOCK OFF OR IN PROGRESS VERSION +CLQDE2: MOVE A,B + SKIPG B,1(B) ;GET POINTER TO NEXT BLOCK + BUG ;CLK QUEUE SCREWED + CAME B,C ;SKIP IF FOUND BLOCK TO DELETE + JRST CLQDE2 + SKIPG B,1(B) ;GET POINTER TO BLOCK AFTER ONE TO DELETE + BUG ;CLK QUEUE SCREWED + MOVEM B,1(A) ;PATCH AROUND DELETED BLOCK + MOVE A,(C) + ADDM A,(B) ;ADD DELTA OF DELETED BLOCK TO NEXT + SETZM (C) ;CLEAR DEL + SETOM 1(C) ;MARK IDLE + JRST (E) + +OVHMTR PGF ;PAGE FAULT + +IFN KL10P,[ +EBLK +PFAILU: 0 ;SAVED U AS OF A PAGE FAILURE +PFINST: 0 ;PF INSTRUCTION IF XCT +PFOPC1: 0 ;SAVE PFOPC WHILE SWITCHING TO CLK LEVEL (PROTECT AGAINST XCTRI) +BBLK + +;PAGE FAULTS COME HERE, WITH PC IN PFOPC, AND PI SYSTEM TURNED OFF. + +PFAIL: MOVEM U,PFAILU + HLRZ U,EPTPFW + ANDI U,%PFCOD ;GET THE PFAIL CODE FROM THE PFW + CAIE U,%PFPAR + CAIN U,%PFPRX + JRST PFA2 ;IT'S A PAR ERR; BYPASS XCTR HACKS + MOVE U,PFOPC + TLNE U,%PCUSR + JRST PFA2 + LDB U,[331100,,(U)] ;GET OPCODE OF LOSING INSTRUCTION. + ;ASSUME THAT IN EXEC MODE VIRTUAL + ; AND PHYSICAL ADDRESSES ARE IDENTICAL + ; FOR INSTRUCTION FETCHES. ALSO ASSUME + ; THAT NOBODY DOES XCT OF XCT OF XCTR. +PFA4: CAIE U,XCTRI_-33 ;SKIP IF "XCTR WITH INHIBIT" + JRST PFA1 +REPEAT 2, AOS PFOPC ;ONCE COMPENSATING FOR INSTR ABORT, AND ONCE TO SKIP + MOVE U,PFAILU + JRST 17,@PFOPC ;KL-10 CROCK: JRST 17, TURNS ON PI SYSTEM + +PFA1: CAIE U,XCTR_-33 ;SKIP IF "XCTR WITH NO INHIBIT" + JRST PFA3 +PFA2: CONSO PI,77400 ;PI IN PROGRESS? + CONSO PI,1 ;CHANNEL 7 ENABLED? + BUG AWFUL,[PAGE FAULT WITH PI IN PROGRESS OR CLKOFF] + SKIPGE USER + BUG AWFUL,[PAGE FAULT IN NULL JOB] + MOVE U,PFOPC + MOVEM U,PFOPC1 + MOVE U,PFAILU ;RESTORE U SO CLKSAV CAN RE-SAVE IT +TPFLT1: SETOM PFAILF + CONO PI,CLKRQ ;CAUSE CLK BREAK AND PI SYSTEM ON + JRST . ;TAKES A WHILE TO GO OFF + +;COME BACK HERE PI IN PROGRESS ON CLK CHANNEL +PFA6: MOVE T,PFOPC1 + MOVEM T,CLKBRK ;SAVE PC AS OF PAGE FAULT AS PLACE INTERRUPTED FROM + AOSN PFAILF ;IF INTERRUPTED FROM INTPFL, + JRST PFA9 ; PC DOESN'T POINT TO FAULTING INSTRUCTION + TLNE T,%PSUSR ;MAYBE SPURIOUS MPV ON IOT IN USER MODE? + TLNE T,%PSUIO + JRST PFA9 ;CAN'T BE, I/O IS LEGAL + HLRZ TT,UPFW(U) + ANDI TT,%PFCOD + CAIE TT,%PFPNA ;CAN'T BE IF PAGE FAULT IS REALLY SOME OTHER RANDOM BREAK + CAIN TT,%PFILW ;SUCH AS A PARITY ERROR + JRST PFA11 +PFA9: +; MOVE T,PFOPC +; MOVEM T,UPOPC(U) ;SOLELY FOR THE .OPC USER VARIABLE + LDB E,[$PFPNO,,UPFW(U)] ;FAILING PAGE NO + HLRZ D,UPFW(U) + ANDI D,%PFCOD ;GET THE PAGE-FAULT CODE. + MOVEI A,0 ;INIT USER INT BITS + CAIE D,%PFPNA + CAIN D,%PFILW + JRST PFA5 ;REAL PAGE FAULT OR RWF + CAIN D,%PFMAR + JRST PFA7A + CAIN D,%PFPRO + JRST PFA7 ;OTHER RANDOM BREAKS + CAIE D,%PFPAR + CAIN D,%PFPRX + JRST PFA14 ;PARITY ERROR + MOVSI D,SCLBPF ;UNKNOWN PFW, GET SYSTEM JOB TO BARF ABOUT IT + TDNE D,SUPCOR + BUG PAUSE,[BAD PAGE FAIL WORD ],OCT,BPFPFW ;LOSING IN REAL TIME + IORM D,SUPCOR + AOS BPFERR + MOVEM U,BPFUSR + MOVE D,UPFW(U) + MOVEM D,BPFPFW + MOVE D,CLKBRK + MOVEM D,BPFPC + JRST SCHED ;IGNORE THE FAULT (BUT DO A FULL SCHEDULE SO SYS JOB WAKES) + +PFA14: SETZM PARRSN ;SAY THIS IS PAR ERR TRAP, NOT PAR ERR INTERRUPT. + MOVE D,UPFW(U) + MOVEM D,PARPFW ;SAVE PFW OF PAR ERR FOR ERROR MESSAGE + AC7CTX ;SELECT AC BLOCK 7, USED BY UCODE. + UMOVE D,0 ;SAVE THE AC THAT HOLDS THE BAD WORD + MOVEM D,PARWRD + SYSCTX ;AND RESET THE DATAO PAG TO NORMAL VALUE + JRST CLKB1E ;GO SCAN FOR THE ERROR. + +PFA3: CAIE U,XCT_-33 + BUG HALT,[PAGE FAULT IN SYSTEM AT ],OCT,PFOPC ;BARF! + MOVE U,@PFOPC ;QUUX! LET ONE LEVEL OF XCT WIN + MOVEM U,PFINST + MOVE U,PFAILU + LDB U,[331100,,@PFINST] + JRST PFA4 + +PFA11: XCTRI XR,[MOVE T,(T)] ;GET INSTRUCTION IN WHICH PAGE FAIL OCCURRED + TLCA T,700000 ;AND CHECK HIGH THREE BITS OF OPCODE + JRST PFA9 ;JUMP IF FAULT WAS ON INSTRUCTION FETCH + TLCE T,700000 + JRST PFA12 ;JUMP IF INSTRUCTION NOT AN IOT +PFA13: MOVSI TT,(HRRI T,) + DPB T,[2700,,TT] + XCTRI XEA,TT ;COMPUTE ITS EFFECTIVE ADDRESS + TLZA T,37 ;CLEAR @+XR, BUT LEAVE OPCODE AND AC + JRST PFA9 ;JUMP IF FAULT ON INDIRECT WORD + MOVEM T,MUUODP(U) ;IT WAS A SPURIOUS MPV, SO + MOVE T,CLKBRK ; SIMULATE TRAPPING AS A UUO + HRRI T,1(T) + MOVEM T,XUUOH(U) ;STORE OLD PC + MOVE T,CLCX(U) + MOVEM T,MUUOCX(U) ;AND OLD CONTEXT + MOVE T,MUUOCN(U) + MOVEM T,CLKBRK ;GET NEW PC + JRST CLKB5 ;AND RESTART USER AT UUOH0 + +PFA12: TLNN T,700000 ;MAYBE AN INSTRUCTION OVERLAYED ON AN MUUO, E.G. LPMR + TLNN T,040000 ;OPCODES 040-077 QUALIFY. + TLCA T,(XCT) + JRST PFA13 ;YUP. + TLNE T,777000 ;SKIP IF OPCODE WAS XCT + JRST PFA9 +; TLZ T,777740 +; TLO T,(MOVEI T,) +;Following instruction is suspected of not working (sometimes using wrong AC block) +; XCTRI XEA,T ;COMP EFFECTIVE ADDRESS OF XCT IN USER CONTEXT +;; JRST PFA11 ;AND GO PROCESS INSTRUCTION AT THAT ADDRESS +; JRST [ MOVEM T,TRMNAM(U) ;TEMPORARY FOR DEBUGGING +; JRST PFA11 ] +; JRST PFA9 ;HERE IF FAULT WAS IN INDIRECT CYCLE +;Replacement code: +PFA15: DATAI PAG,TT ;HMM, SEE IF WRONG AC BLOCK SELECTED + TLNN TT,100 + BUG + LDB TT,[220400,,T] ;CHECK FOR NEED TO SIMULATE INDEXING + JUMPE TT,PFA16 + UMOVE TT,(TT) + ADD TT,T + HRR T,TT +PFA16: TLNN T,(@) ;CHECK FOR NEED TO SIMULATE INDIRECT + JRST PFA11 + XCTRI XR,[MOVE T,(T)] + JRST PFA15 ;PROCESS INDIRECT WORD + JRST PFA9 ;TAKE FAULT ON INDIRECT WORD +;End replacement code. +];KL10P + +IFN KS10P,[ + +EBLK + +IRP I,,[1,2,3,4,5,6,7] +PF!I!SVU: 0 ;Saved U at PI level I page fail +PF!I!SVT: 0 ;Saved T at PI level I page fail +PF!I!INS: 0 ;Instruction at PI level I page fail +TERMIN +IFN .-PF1SVU-21., .ERR Wrong length PFXSVU block. + +BBLK + +IRP I,,[1,2,3,4,5,6,7] +PF!I!AIL: ;;PI level I page fail comes here. + MOVEM T,PF!I!SVT ;Save T + MOVEM U,PF!I!SVU ;Save U + JSP U,PIFAIL ;Set up U and join common code +TERMIN +IFN .-PF1AIL-21., .ERR Wrong length PFXAIL block. +PFXSVT==:0,,> +PFXINS==:0,,> +PFXWRD==:0,,> +PFXOPC==:0,,> + +PIFAIL: MOVE T,PFXWRD(U) ;Check page fail word + TLNE T,%PFNXI + BUG AWFUL,[NON-EX IO REG WITH PI IN PROGRESS ],OCT,PFXWRD(U),[PC=],OCT,PFXOPC(U) + TLNE T,%PFNXM\%PFPAR + BUG AWFUL,[NXM OR PARITY ERROR WITH PI IN PROGRESS] + MOVE T,PFXOPC(U) ;Check for user mode. + TLNE T,%PSUSR + BUG AWFUL,[PAGE FAULT IN USER MODE WITH PI IN PROGRESS] + SKIPA T,(T) ;We assume that it wasn't the instruction + ;fetch itself that caused the fault. +PIFL2: MOVEI U,PF7AIL-PF7XCT(U) ;Correct U on return from PFXXCT + MOVEM T,PFXINS(U) ;Save instruction that caused fault + LSH T,-33 ;Look at opcode + CAIE T,XCTRI_-33 ;XCTRI gets special treatment: + JRST PIFL1 +REPEAT 2, AOS PFXOPC(U) ;Arrange for it to skip. + JRST PFXRET(U) ;And return. + +IRP I,,[1,2,3,4,5,6,7] +PF!I!RET: + MOVE T,PF!I!SVT ;Restore T + MOVE U,PF!I!SVU ;Restore U + JRST 2,@EPTP!I!O ;Return +TERMIN +IFN .-PF1RET-21., .ERR Wrong length PFXRET block. +PFXRET==:0,,> + +;;;Let XCT chains that end in XCTRI win. We assume that none of the +;;;fetches along the way to the XCTRI itself caused the fault. +PIFL1: CAIE T,XCT_-33 + BUG AWFUL,[PAGE FAULT WITH PI IN PROGRESS] + MOVE T,PFXSVT(U) ;Restore T + JRST PFXXCT(U) ;Go pick up word XCT'ed + +IRP I,,[1,2,3,4,5,6,7] +PF!I!XCT: + MOVE U,PF!I!SVU ;Restore U + MOVE T,@PF!I!INS ;Pick up XCTed instruction + JSP U,PIFL2 ;Set up U again and rejoin common code +TERMIN +IFN .-PF1XCT-21., .ERR Wrong length PFXXCT block. +PFXXCT==:0,,> + +EBLK + +PFLCLK: 0 ; Did page fault happen with CLKOFF? +PFLSVU: 0 ; Saved U during page fail +PFLSVT: 0 ; Saved T during page fail +PFLINS: 0 ; Faulting instruction + +BBLK + +;;; Note! +;;; If we are swapped out while running with Exec mode PC between PFAIL and +;;; PFAILE inclusive, EPTPFO is saved as our PC. (There are actually only +;;; a few PC's for which this is possible given that we mostly run CLKOFF.) + +PFAIL: SETZM PFLCLK + CONSO PI,1 + SETOM PFLCLK + CONO PI,CLKOFF ; Don't bother me + MOVEM U,PFLSVU ; Save U + MOVEM T,PFLSVT ; Save T + SKIPGE U,USER + BUG AWFUL,[PAGE FAULT IN NULL JOB] + MOVE T,EPTPFW ; Get the explanation + MOVEM T,UPFW(U) ; Save it for others + MOVE U,PFLSVU ; Restore U, only needed it for a moment. + TLNE T,%PFNXM\%PFPAR ; Bad stuff should interrupt us, right? + BUG AWFUL,[NXM OR PARITY ERROR DIDN'T INTERRUPT] + MOVE T,EPTPFO + TLNE T,%PSUSR ; In Exec mode? + JRST PFLUSR + MOVE T,(T) ; We assume that it wasn't the instruction + ; fetch itself that caused the fault. +PFLOOP: MOVEM T,PFLINS ; Save instruction that caused fault. + LSH T,-33 ; Check opcode for XCTRI + CAIN T,XCTRI_-33 ; Should we skip? + JRST PFLSKP + CAIN T,XCTR_-33 ; Touching user address? + JRST PFLUSR + CAIE T,UMOVE_-33 ; These guys are just like XCTR + CAIN T,UMOVEM_-33 + JRST PFLUSR + ;; Let XCT chains win. We assume that none of the fetches along + ;; the way caused the fault. + CAIE T,XCT_-33 + BUG HALT,[PAGE FAULT IN SYSTEM AT],OCT,EPTPFO + MOVE T,PFLSVT ; Restore T for a moment + MOVE T,@PFLINS ; Pick up XCTed instruction + JRST PFLOOP + +;;; Come here to cause faulting instruction to skip. +PFLSKP: MOVE T,PFLSVT ; Restore T +REPEAT 2, AOS EPTPFO + SKIPL PFLCLK ; Unless clock was already off + CONO PI,CLKON ; turn it back on +PFAILE: JRST 2,@EPTPFO + +;;; Come here on NXI error. +PFLNXI: + +;;; We come here when the page fault is "soft" and it happened in user mode +;;; or while using XCTR, UMOVE, or UMOVEM. +PFLUSR: MOVE T,EPTPFW + TLNN T,%PFNXI ; Non-existent IO Register? + JRST PFLU1 ; Nope + MOVE T,EPTPFO + TLNE T,%PSUSR ; NXI in User IOT mode is not fatal. + TLNN T,%PSUIO + BUG AWFUL,[NON-EX IO REG ],OCT,EPTPFW,[PC=],OCT,EPTPFO +PFLU1: MOVE T,PFLSVT ; Restore T + SKIPGE PFLCLK ; Check for lossage + BUG AWFUL,[PAGE FAULT WITH CLKOFF AT],OCT,EPTPFO +TPFLT1: SETOM PFAILF ; Cause CLK level to go to PFLU2 +CCLKRQ: CONO PI,CLKRQ + JRST . ; Takes a while to go off... + +;;;CLKBRK comes back here at CLK level. +PFLU2: MOVE T,EPTPFO + MOVEM T,CLKBRK ;Save PC of page fault as place interrupted + ;from. + LDB E,[$PFPNO,,UPFW(U)] ;E: Virtual page number + HLRZ D,UPFW(U) + ANDI D,%PFNXI\%PFWRT\%PF2.9\%PF2.8 ;D: Page fault code + MOVEI A,0 ;A: User interrupt bits + TRNE D,%PFNXI ;NXI in User IOT mode. + JRST PFA7A + +;Drops through into PFA5 + +] ;KS10P + +IFN KA10P,[ +CLKB1: MOVE T,CLKBRK + CONSZ 200 + JRST CLKFO1 ;FLOATING OVERFLOW ENABLED +CLKFO2: CONSZ 20 ;SKIP IF AR OV INT NOT ENABLED + CONSO 10 ;OV ENABLED, SKIP IF OV + CONSZ 270000 ;NOT OV, CHECK PDL OV, MEM PROTECT, NXM + JRST CLKB1C ;PDL OV, NXM, ETC + JRST CLKB1D ;ONLY CLOCK BREAK, AR OV JUST ENABLED + +CLKFO1: CONSO 100 ;SKIP ON FLOATING OVERFLOW + JRST CLKFO2 ;NOT REALLY FLOATING OVERFLOW +CLKB1C: JUMPL U,CNLJL ;NULL JOB LOST + MOVEI A,0 ;SET UP INTERRUPT BITS FOR USER + CONSZ 20 ;SKIP IF OV NOT ENABLED + CONSO 10 ;OV ENABLED, SKIP ON OV + JRST CLB1A ;NOT AROV + PUSHJ P,AROV +CLB1A: CONSZ 200 ;SKIP IF FL OV NOT ENABLED + CONSO 100 ;FL OV ENABLED, SKIP ON FL OV + JRST CLB1B ;NOT FLOATING OVERFLOW + PUSHJ P,ARFOV +CLB1B: CONSO 270000 ;SKIP IF PDL OV, NXM, OR MEM PROTECT + JRST CLB1X + CONSZ 10000 ;NON EX MEM + PUSHJ P,MEMHNG + CONSO 200000 + JRST CLKB1H + TRO A,%PIPDL ;PDL OVFLO + TLNN T,%PCUSR ;SKIP IF IN USER MODE + BUG HALT,[PDL OVERFLOW IN EXEC MODE] +CLKB1H: CONSO 20000 ;MEM PROTECT + JRST CLKB1G + HLLZ D,UPQUAN(U) ;PICK UP FAULT BITS + TLNE D,1000 + TLNN D,770 ;ALL CONDITIONS WHICH ABORT INSTRUCTION + JRST CLKB1J ;(PLUS PAGE NXM FOR RANDOMNESS) + TRZ A,%PIPDL ;INSTRUCTION ABORTED, DON'T SET PDL OV + HLLZ T,UPOPC(U) + LSH T,5 + HRR T,UPOPC(U) ;FIX UP OPC + MOVEM T,CLKBRK ;RESET PC FROM OPC + AOS NPGFLT + HLRZ E,UPJPC(U) ;GET VIRTUAL PAGE # (LH OF JPC) + TRNN E,400 + JRST CFHFPF + ANDI E,377 ;FLUSH AGE ETC +] ;KA10P + ;DROP THROUGH INTO PFA5 + +IFE KA10P,[ +PFA5: AOS NPGFLT +] ;IFE KA10P + MOVE TT,LUMPS + HRRZ W,USER +IFN KA10P,[ + TLNE D,320 ;SKIP IF REALLY PAGE FAULT + JRST CFH4 ;OTHERWISE WRITE IN READ ONLY OR EXECUTING IMPURE PAGE +] ;KA10P + +;COME HERE WITH +; A BITS FOR USER'S PIRQC +; D PAGE FAULT BITS OR CODE +; E VIRTUAL PAGE NUMBER OF PAGE FAILURE +; TT THE UMAPS SETTING +;THE MYSTERIES OF W: +; RH IS A USER INDEX +; LH 0 => NORMAL PAGE FAULT +; NON0 => SWAP IN REQUEST FOR OTHER REASON. D,TT SHOULD BE 0. +; SPECIFICALLY, +; 4.9 => DMA DEVICE SWAP-IN, SEE SWIRQB, SWPPIN +; 4.8 => FROM SCHEDULER, TO GIVE INTERRUPT (?) THIS IS NO LONGER USED, +; PROBABLY. +; 4.7 => FROM CFHAHD, TO PAGE AHEAD. THIS IS ONE LEVEL OF RECURSIVE +; USE OF CFHSW1. +; FOR A NORMAL PAGE FAULT, THE USER PC IS IN CLKBRK. + +CFHSW1: HRRZM E,CFHUVP ;USER'S VIRTUAL PAGE NUMBER + TRZN E,200 + JRST CFH1 + MOVEI C,UPGCPH(W) ;VIRTUAL ADDRESS IN USER'S HIGH SEG + TLNN TT,%UMMPU ;IS MY UPPER NORMAL? + JRST CFH2 ;YES, USE MY UPPER CPB + MOVEI C,UPGCPH(TT) ;NO, TRY HIS UPPER. + TLNE TT,%UMUTL ;IS MY UPPER GOING TO HIS LOWER? + MOVEI C,UPGCP(TT) ;YES, TRY HIS LOWER. + JRST CFH2 + +CFH1: MOVEI C,UPGCP(W) ;VIRT ADDRESS IN USER'S LOW SEG + TLNN TT,%UMMPL + JRST CFH2 ;MY LOWER DBR NOT HACKED + MOVEI C,UPGCP(TT) + TLNE TT,%UMLTU ;WAS MY LOWER HACKED TO POINT TO UPPER? + MOVEI C,UPGCPH(TT) ;YES. +CFH2: ROT E,-1 + ADD C,E + HRLI C,222200 + SKIPGE E + HRLI C,2200 + MOVE T,C ;CALCULATE MAP ENTRY B.P. FROM CIRC PTR B.P. + ADD T,[(200000-2000)UPGMP-UPGCP] + LDB E,C ;CIRC MEM USE POINTER FOR PAGE FAULT + JUMPE E,CFH4 ;ADDRESS IS IN REAL ILM + CAIN E,-1 + JRST CFH4 ;ON REFERENCE TO ABS PAGE ALSO ILM +IFN KL10P,[ CAIE D,%PFILW + JRST CFHW1 + LDB I,T + JRST .+1(I) + BUG ;? + JRST CFH4 ;WRITE IN READ ONLY? + JRST CFHRWF ;READ WRITE FIRST + BUG ;? +] ;KL10P +IFN KS10P,[ CAIN D,%PFWRT\%PF2.8 ;WRITE IN READ ONLY + JRST CFH4 + CAIN D,%PFWRT\%PF2.9 ;READ WRITE FIRST + JRST CFHRWF + TRNE D,%PF2.8\%PF2.9 ;PAGE NOT IN MAP + BUG HALT,[BOGUS PAGE FAIL CODE] +] ;KS10P +IFN KA10P,[ + TLNE D,40 + JRST CFHRWF +] ;KA10P +;REFERENCE TO PAGE WITH NO ACCESS IN MAP. +CFHW1: SKIPGE RPCL(W) + JUMPGE W,CFF1 ;BEING RPCLSRED? + MOVEM A,CFHAS + AOSE CIRPSW + JRST CFH5 ;CIRPSW NOT AVAILABLE + TRZE E,400000 + TRNE E,200000 + JRST CFHSW3 + CAML E,MMPMX + BUG ;MMP OUT OF RANGE + MOVE C,E ;CIRC PNTR ALREADY POINTS TO MMP + ADD C,MMPEAD + JRST CFHSW4 + +CFHSW3: PUSHJ P,UCPRL ;FIND MMP + 200000,,.+2 + BUG ;NONE? + SUB P,[4,,4] +CFHSW4: LDB D,[410200,,(C)] ;TWO BITS OF MMP ENTRY GIVES DISPOSITION OF PAGE + AOS NRPI(D) + JRST @CFHDT(D) + +CFHDT: CFHPI ;IN + CFHPCI ;COMING IN + CFHPO ;OUT + CFHPGO ;GOING OUT + +;PAGE FAULT IN JOB BEING PCLSR'D. +CFF1: MOVE C,CLKBRK + TLNE C,%PCUSR + BUG ;BEING RPCLSRED IN USER MODE +IFN KA10P,[ + MOVSI D,1770 + ANDCAM D,UPQUAN(W) ;CLR PG FLT + LPMR UPGML(W) + CONO 470000+APRCHN ;CLR PDL OV + QT OV + MPV + NXM +] ;KA10P + MOVE T,[BADBTS] + IOR T,MSKST(W) + AND T,A + IORM T,PIRQC(W) +IFE KA10P,[ + MOVE T,CLCX(W) ;RESTORE UPT BUT NOT ACS + HRLI T,300000 + DATAO PAG,T +] ;IFE KA10P + CONO PI,CLKOFF ;GO ALLOW SELF TO GET RPCLSRED + JRST 10,UFL1 ;GO INTO UFLS WITH CLK OFF RATHER THAN + ;IN PROGRESS + +CFHRWF: ;HANDLE "WRITE IN READ-WRITE-FIRST PAGE" PAGE FAULT. +IFN KA10P,[ + TLNE D,10 + JRST CFHW1 ;SOMETIMES NO ACCESS SEEMS TO BE ON TOO + LDB I,T + CAIE I,2 + BUG ;GOT "WRITE IN R-W-F PAGE" BUT PAGE ISN'T R-W-F. +] ;KA10P + MOVEI I,3 + DPB I,T + MOVEM A,CFHAS + JRST CFHX1 + +;; EXIT FROM PAGE FAULT HANDLING FOR NON-ERROR FAULT. +;; C SHOULD CONTAIN 0 IF CAN CONTINUE NOW, OR A FLSINS TO WAIT WITH. +;; A SHOULD CONTAIN -1 IF FAULT HANDLED SUCCESFULLY (PAGE IN OR ON ITS WAY), ELSE 0. +CFHX: SETOM CIRPSW + TLNN W,200000 + JUMPL W,CPOPJ +CFH5A: JUMPE C,CFHX1 ;IF NOT GOING TO WAIT, SKIP NPGWTU CODE + MOVSI D,%SWPGW + IORM D,USWST(W) ;WAITING FOR PAGE + AOS NPGWTU ;KEEP COUNT OF USERS WAITING FOR A PAGE + SKIPN FLSINS(W) + MOVEM C,FLSINS(W) + SKIPE FLSINS(W) + CLEARM DLSRCH +CFHX1: MOVE A,CFHAS +IFN KA10P, MOVSI D,1770 ;CLEAR FAULT STATUS BITS + MOVE U,USER + JRST CFH6 + +;; WAIT FOR CIRPSW TO BE AVAILABLE. +CFH5: SETZ A, + JUMPL W,CPOPJ + MOVE C,[SKIPL CIRPSW] + AOS NLPPGC + JRST CFH5A + +;PAGE FAULT ON PAGE THAT'S REALLY IN CORE. +CFHPI: PUSHJ P,CFHAHC ;SEE IF WE WANT PAGE-AHEAD OR PAGE-BEHIND. + MOVSI D,MMPPGA + TDNE D,(C) + AOS NPGAHR ;COUNT NUMBER OF PAGED-AHEAD PAGES ACTUALLY USED. + ANDCAB D,(C) + MOVSI D,MMPPGB + TDNE D,(C) + AOS NPGBHR ;COUNT NUMBER OF PAGES AGED BY PAGE-BEHIND WHICH WERE USED AGAIN. + ANDCAB D,(C) + HRLI C,2200 + PUSH P,C ;SAVE MMP ENTRY ADDRESS FOR PPIUM. + PUSHJ P,UCPRL + 100000,,.+2 ;RETURN ON MEMPNT + BUG ;NO MEMORY LINKED IN? + SUB P,[4,,4] ;FIND MEMBLT INDEX + POP P,C + TLNE D,MMPBAD ;WAS THIS PAGE RECENTLY A PAR ERR VICTIM? + JRST CFHPB ;YES; READ IT BACK OFF THE DISK IF POSSIBLE. +IFN E.SP,[ + JUMPGE W,E.SBAR ;IF NOT CALLED FROM SWPPIN + HRRZ H,DISUSR ;CHECK TO SEE IF SERVICING E&S + CAIN H,(W) ;NOT DISPLAY, THEN SKIP + PUSHJ P,E.SPGI ;ELSE TIE DOWN PAGE +E.SBAR: +] + MOVE A,T + HLLZS MMSWP(A) ;CLEAR LENGTH OF CIRC LIST (BUT NOT EXEC PGS COUNT) + MOVE D,C + HRLI D,(TDNE T,) + PUSHJ P,PPIUM ;PUT PAGE INTO USERS' MAPS +IFN E.SP,SETZM E.SPGH ; CLEAR QSWI1 FLAG + MOVEI C,0 + MOVNI A,1 + JRST CFHX + +;COME HERE FOR PAGE WHICH SEEMS TO BE IN CORE, BUT HAD A PAR ERR RECENTLY. +;"SWAP IT OUT", SO IF IT'S PURE IT WILL JUST BE READ BACK FROM DISK. +CFHPB: PUSH P,W + MOVE A,T + SETOM CIRPSW ;UNLOCK, SO SWPOPG CAN RE-LOCK. + MOVE C,USER ;TELL SWPOPG WHICH JOB SHOULDN'T BE PCLSR'ED. + PUSHJ P,SWPOPL ;"SWAP OUT" THE PAGE (EVEN IF LOCKED DOWN) + JRST [ POP P,W ;FAILED TO GO OUT. COULD BE EXEC PAGE POINTING TO IT, + SETZ A, ;OR A JOB THAT CAN'T BE PCLSRED RIGHT NOW. + MOVSI C,(CAIA) ;WAIT A LITTLE AND TRY AGAIN (HOPE FOR THE BEST) + JRST CFHX ] + POP P,W + AOSE CIRPSW ;SWPOPG UNLOCKS; RE-LOCK. + JRST CFH5 ;OR ELSE GO INTO PAGE-WAIT TILL CIRPSW FREE. + MOVE C,SWOMMP + JRST CFHSW4 ;TRY AGAIN TO REFERENCE PAGE, SWAPPING IT BACK IN. + +;ON A RANDOM PAGE FAULT, SEE IF WE WANT PAGE-AHEAD OR PAGE-BEHIND. +;ASSUMES W SET UP AS FOR CFHSW1, AND TT +CFHAHC: MOVE D,CFHUVP ;GET USER'S VIRTUAL PAGE NUMBER. + TLNN W,-1 ;PAGE AHEAD ONLY FOR NORMAL PAGE FAULT (SO PC IS IN CLKBRK). + SKIPN PAGAHD(W) ;IS PAGE-AHEAD WANTED FOR THIS JOB? + POPJ P, + MOVSI T,%UMMPU + TRNN D,200 + MOVSI T,%UMMPL + TDNE TT,T ;NO PAGE-AHEAD ON PAGE NOT MAPPED NORMALLY. + POPJ P, + HLRZ H,PAGRAN(W) + HRRZ T,PAGRAN(W) + CAML D,H ;IS PAGE IN RANGE FOR AUTOMATIC PAGE-AHEAD? + CAML D,T ;IF SO, GO DO IT. + POPJ P, + PUSH P,C + PUSHJ P,CFHAHD + POP P,C + POPJ P, + +;AUTOMATIC PAGE-AHEAD AND PAGE-BEHIND. +;WHEN PAGE N IS PUT INTO THE MAP, PAGE N+1 IS SWAPPED IN +;AND PAGE N-1 IS SWAPPED OUT. +;(ACTUALLY, 1 IS A PARAMETER, IN THE PAGAHD VARIABLE) +CFHAHD: PUSH P,CFHUVP +;LOOP, REQUESTING SWAP-IN FOR THE NEXT N PAGES. E HAS PAGE NUMBER TO SWAP IN. +CFHAH1: MOVE E,CFHUVP + HLRE A,PAGAHD(W) + MOVE T,A + ADD A,(P) + CAMN A,E ;DETECT END OF LOOP. + JRST CFHAH2 + SKIPL T ;ELSE INCREMENT OR DECREMENT PAGE NUMBER. + AOSA E + SOS E + PUSHJ P,CFHRNG ;IS PAGE NUMBER IN RANGE FOR PAGE-AHEAD? + JRST CFHAH2 + PUSH P,W + HRLI W,500000 ;PAGE AHEAD THE PAGE. 100000 MEANS PAGE-AHEAD. + SETZB D,TT + SETOM CIRPSW ;ALLOW CFHSW1 TO LOCK CIRPSW. + PUSH P,CFHAS + PUSHJ P,CFHSW1 + POP P,CFHAS + SETZM CIRPSW ;BUT REALLY IT'S ALREADY LOCKED SO KEEP IT SO. + POP P,W + SKIPN A + AOS NPGAH1 ;COUNT NUMBER OF TIMES AN ATTEMPT FAILS. + JRST CFHAH1 + +;NOW IT'S TIME FOR PAGE-BEHIND. E HAS PAGE NUMBER TO SWAP OUT. +CFHAH2: MOVE E,(P) +;???? IS THERE ANY NEED TO PRESERVE U, EVER, INSIDE CFHSW1? + PUSH P,U + HRRE A,PAGAHD(W) ;GET PAGE-BEHIND DISTANCE. + JUMPE A,CFHAH4 + ADDB A,E ;COMPUTE WHICH PAGE TO PAGE OUT. + PUSHJ P,CFHRNG ;SKIP IF PAGE IS IN RANGE FOR PAGE-BEHIND. + JRST CFHAH4 + MOVE U,W + PUSHJ P,UPLC ;LOOK UP THE PAGE IN THE MAP. + LDB D,Q ;D GETS CIRC PNTR + JUMPE D,CFHAH4 ;NO PAGE THERE + CAIN D,-1 + JRST CFHAH4 ;ABSOLUTE PAGE, DO NOTHING. + LDB D,T + TRO D,PMAGEM ;AGE THE PAGE, IF THE PAGE IS REALLY IN THE MAP, + TRNE D,600000 + DPB D,T + AOS NPGBHA ;COUNT PAGES AHED FOR PAGE-BEHIND. + MOVE D,T ;SAVE B.P. TO PAGE MAP HALFWORD, FOR CFHAH6. + MOVE C,Q ;STARTING FROM CIRC PTR, FIND MMP + PUSHJ P,UCPRL + 200000,,.+2 + BUG ;IF NONE FOUND + SUB P,[4,,4] ;FOUND MMP, C POINTS TO IT + MOVE E,C ;SAVE ADDRESS OF MMP ENTRY + MOVSI T,MMPTMP\MMPOUT ;IF PAGE IS IN TRANSIT OR OUT, DO NOTHING TO IT. + TDNE T,(C) + JRST CFHAH6 + MOVE T,CLKBRK + TLNN T,%PCUSR ;IF JOB IN EXEC MODE, CAN'T SWAP OUT PAGE, SO JUST LEAVE AGED. + JRST CFHAH6 + MOVE T,MEMFR + SUB T,NCBCOM ;IF LOTS OF FREE MEM, DON'T SWAP OUT. + SUB T,SILNG + CAML T,CFHAHS + JRST CFHAH6 + PUSHJ P,UCPRL ;GET CORE PAGE NUMBER IN T. + 100000,,.+2 + BUG + SUB P,[4,,4] + HLRZ A,MMSWP(T) + JUMPN A,CFHAH6 ;POINTED TO BY AN EXEC PAGE, E.G. 340, CAN'T SWAP OUT. + PUSH P,E + PUSH P,D + PUSH P,W + MOVE A,T ;PHYSICAL PAGE # TO SWAP OUT + HRRZ C,W ;DON'T PCLSR ME + SETOM CIRPSW ;SWPOPG WILL WANT TO RE-LOCK CIRPSW. + PUSHJ P,SWPOPG ;SWAP OUT + JRST CFHAH5 ;CAN'T SWAP OUT => LEAVE JUST AGED. + AOS NPGBHD ;COUNT PAGES SWAPPED OUT BY PAGE-BEHIND. +CFHAH5: POP P,W + POP P,D + POP P,E + POP P,U + POP P,CFHUVP + AOS CIRPSW ;SWPOPG UNLOCKS; RE-LOCK. + POPJ P, ;CAN'T GET LOCKED BY SOMEONE ELSE, WE ARE AT CLOCK LEVEL + +;HERE FOR PAGE-BEHIND PAGE WHICH WE CAN'T OR DON'T WANT TO SWAP OUT. +CFHAH6: MOVSI T,MMPPGB ;IT HAS ALREADY BEEN AGED. MARK IT FOR METERING PURPOSES. + IORM T,(E) ;E POINTS TO MMP ENTRY. +CFHAH4: POP P,U + POP P,CFHUVP + POPJ P, + +;SKIP IF PAGE NUMBER IN E IS IN RANGE FOR PAGE-AHEAD OR PAGE-BEHIND. +;ASSUMES USER INDEX IN W. CLOBBERS T. +CFHRNG: CAIL E,400 + POPJ P, + HLRZ T,PAGRAN(W) + CAIGE E,(T) + POPJ P, + HRRZ T,PAGRAN(W) + CAIL E,(T) + POPJ P, + JRST POPJ1 + +EBLK + +CFHAHS: 20 ;IF LESS THAN THIS MUCH FREE MEM, PAGE-BEHIND SHOULD SWAP OUT. + +NPGAHD: 0 ;NUMBER OF PAGES WE ACTUALLY SWAPPED IN FOR PAGE-AHEAD. +NPGAH1: 0 ;NUMBER OF TIMES WE WERE UNABLE TO PAGE AHEAD. +NPGBHD: 0 ;NUMBER OF PAGES WE ACTUALLY SWAPPED OUT FOR PAGE-BEHIND. +NPGBHA: 0 ;NUMBER OF PAGES WE DID PAGE-BEHIND. +NPGAHR: 0 ;NUMBER OF PAGED-AHEAD PAGES ACTUALLY USED. +NPGBHR: 0 ;NUMBER OF PAGES AGED FOR PAGE BEHIND AND USED AGAIN. + +BBLK + +;REFERENCE TO SWAPPED OUT PAGE, MMP ADDRESS IN C. SWAP IN THE PAGE. +;W HAS THE USER INDEX AND FLAGS. +CFHPO: PUSHJ P,CFHPOA + JRST [ SETZ A, ;FAILED. RETURN CODE FOR FAILURE, IF THIS IS FOR DEVICE (W<0). + JRST CFHX] + TLNN W,100000 ;IF THIS IS A PAGE-AHEAD REQUEST, + JRST CFHPOB + MOVSI A,MMPPGA ;MARK THE MMP ENTRY SO, + IORM A,(C) + AOS NPGAHD ;AND COUNT IT AS A SUCCESSFUL ATTEMPT TO PAGE AHEAD. +CFHPOB: TLNN W,200000 + JUMPL W,CFHPO2 + PUSHJ P,CFHAHC ;ORDINARY PG FAULT => MAYBE PAGE AHEAD. + MOVSI D,%SWBEM +IFN SWPWSP,[ ;SWAPPING IN A PAGE FOR THIS GUY + ANDCAM D,USWST(W) ;SO CLEAR BEST EFFORT MADE TO SWAP OUT BIT +];SWPWSP +IFE SWPWSP,[ + TDNN D,USWST(W) ;IF JOB IS BRINGING IN FIRST PAGE + JRST CFHPO2 ; SINCE BEING SWAPPED OUT, + ANDCAM D,USWST(W) ;CLEAR BEST EFFOR MADE TO SWAP OUT BIT + EXCH U,W ;AND MAKE SWAP HISTORY TABLE ENTRY + MOVSI T,0 ;FOR "BEGIN LOADING" + PUSHJ P,SWPKHT + EXCH U,W +];SWPWSP +CFHPCI: +CFHPGO: +CFHPO2: MOVNI A,1 ;SIGNAL "SUCCESS" + TLNN W,200000 + JUMPL W,CFHX + MOVSI D,MMPTMP ;BIT ON IF PAGE "IN TRANSIT" + SKIPN FLSINS(W) + MOVEM D,EPDL2(W) ;HANG USER UNTIL PAGE GETS WHERE IT'S GOING + HRLI C,(TDNE T,) ;COMBINE WITH ADDRESS OF MMP + AOS NLPPAG + JRST CFHX + +;SWAP IN PAGE. W HAS USER INDEX AND FLAGS. C HAS MMP ADDRESS. +;SKIPS IF SUCCESSFUL. OTHERWISE RETURNS FLSINS IN C. +;SIGN BIT IN W IS SET FOR SWAP IN FOR DEVICE OR FOR PAGE-AHEAD +;(THAT IS, NOT ONE WHICH A JOB MUST WAIT FOR) +;SO DON'T INCREMENT SOME COUNTERS AND DON'T BOTHER WITH FLSINS IN C. +CFHPOA: +IFE SWPWSP,[ + SKIPGE USWSCD(W) ;IF SWAP BLOCKED, EITHER UNBLOCK OR GIVE UP. + JRST CFBO1 +CFBO2: +];SWPWSP +IFN SWPWSP,[ + MOVE E,USWST(W) ;IF SWAPPED OUT, WE ARE EITHER GOING TO ENTER + TLNE E,%SWOUT ;THE LOADING STATE OR THE SWAP BLOCKED STATE + JRST CFSB +CFSB1: +];SWPWSP + MOVSI E,MMPISW + AND E,(C) + CONO PI,UTCOFF-1 + JUMPN E,CFHPO5 ;INITIAL SWAPIN; GIVE UP AND WAIT NOW IF TUT IS LOCKED. +CFHPO7: PUSHJ P,HMRQC ;GET PHYS MEM BLOCK, NUMBER IN A. + JRST CFHPO1 ;MEM NOT AVAILABLE + MOVEI B,1 + DPB B,[410200,,(C)] ;INDICATE COMING IN + HRRZ B,(C) ;OLD CP OF MMP + MOVEM B,MEMPNT(A) ;BECOMES LINK OUT OF CORE BLOCK + HLRZ B,1(C) ;B := DISK ADDRESS + LDB I,[$MMPUN,,(C)] ;I := DISK NUMBER + CAIL I,NQS + BUG + HRLM B,MEMPNT(A) ;SET DISK ADDRESS CORE BLOCK COMING FROM +IFN SWPWSP,[ + MOVE D,USWST(W) + TLNN D,%SWLOD + AOSA NPLBNL + AOS NPLBLJ +];SWPWSP + SKIPE E ;IF INITIAL SWAP IN PAGE, SOS THE TUT NOW + PUSHJ P,CFHPO8 ;SINCE WE ARE DISSOCIATING THE PAGE FROM THE DISK BLOCK. + CAIGE A,TSYSM + CAIGE A,SYSB + BUG ;SHOULDN'T HAVE TO SWAP IN THE SYSTEM + CONO PI,UTCON-1 ;LEAVE CLKCHN OFF. + SOS NPGSWO + AOS SWIPRQ ;TOTAL SWAP IN REQUESTS +;; MARK THE PHYSICAL MEMORY BLOCK AS BEING SWAPPED INTO BY THIS PAGE. + MOVEI B,MUSWPG + DPB B,[MUR,,MEMBLT(A)] + MOVEI B,600000(A) + HRRM B,(C) ;MAKE CP OF MMP POINT TO MEMPNT + MOVE TT,C + SUB TT,MMPEAD + DPB TT,[MMMPX,,MEMBLT(A)] ;STORE MMP INDEX IN MEMBLT + MOVEI TT,.BM MLO + ANDCAM TT,MEMBLT(A) ;SET END OF LIST IN THIS BLOCK +;; PUT THE TRANSFER ON THE SWAP IN LIST. + CONO PI,UTCOFF-1 + HLRZ TT,SINLST(I) ;GET PREV BLOCK + SKIPE TT + DPB A,[MLO,,MEMBLT(TT)] ;CHAIN TO PREV BLOCK + SKIPN TT + MOVEM A,SINLST(I) ;OR TO HEADER IF FIRST + HRLM A,SINLST(I) ;AND SET NEW LAST BLOCK + AOS SILNG ;AOS NUMBER OF PENDING SWAP IN RQS. + PUSHJ P,QSTRT1 ;WAKE UP DISK INTERRUPT LEVEL. + CONO PI,UTCON-1 +;; UPDATE SWAP HISTORY TABLE. + HRLZ TT,W + IDIVI TT,LUBLK ;TT 3.1-3.8 GETS USER NUMBER, BASHES I +IFN SWPWSP,[ + MOVSI T,%SWLOD + TDNE T,USWST(W) + TLO TT,(SETZ) +];SWPWSP + MOVE T,CFHUVP + DPB T,[321000,,TT] + HRR TT,TIME + MOVEM TT,@PGIHTP + AOS T,PGIHTP + MOVE TT,UTRNTM(W) + MOVEM TT,PGIHTL-1(T) + MOVEI TT,PGIHTB + CAIL T,PGIHTB+PGIHTL + MOVEM TT,PGIHTP + TLNN W,200000 + JUMPL W,POPJ1 + AOS USIPRQ(W) + JRST POPJ1 ;HANG USER UNTIL PAGE IN + +;IF SWAPPNG IN "INITIAL SWAP IN" PAGE, CHECK TO SEE WHETHER TUT IS AVAILABLE. +;WE CAN'T SWAP THE PAGE IN IF NOT. +CFHPO5: LDB I,[$MMPUN,,(C)] ;GET DSK # + CAIL I,NQS + BUG + SKIPL QTUTO(I) + JRST CFHPO7 ;DISK TUT AVAIL + CONO PI,UTCON-1 + TLNN W,200000 + JUMPL W,CPOPJ ;NO COUNTER AOS IF SWAPIN FOR DEVICE OR PAGE AHEAD. + MOVE C,[SKIPGE QTUTO] ;ALSO MUSTN'T SMASH C + ADD C,I + AOS NLPPGT + POPJ P, + +;LATER ON, COME HERE TO SOS THE TUT, AFTER GETTING THE MEM, WHEN WE CAN NO LONGER BLOCK. +CFHPO8: ANDCAM E,(C) ;CLEAR INITIAL SWAPIN BIT + MOVE D,B ;GET TRK # + PUSHJ P,TUTPNT + CAIGE B,TUTMNY + SOJL B,[JRST 4,.] + DPB B,D + HRRZS 1(C) ;CLEAR ASSIGNED TRACK NUMBER SO NEW SPACE ASSIGNED ON SWAPOUT + POPJ P, + +;HERE IF NO MEMORY TO SWAP PAGE INTO. +CFHPO1: CONO PI,UTCON-1 + TLNN W,200000 + JUMPL W,CPOPJ + SKIPGE MEMFRZ ;IF BECAUSE MEMFRZ LOCKED, MAKE JOB WAIT FOR MEMFRZ. + JRST CFHPO4 + MOVE C,[SKIPL MEMFRZ] + AOS NLPPGM + POPJ P, + +CFHPO4: MOVE C,[PUSHJ P,CFHPO3] + MOVN D,SOLNG + SUB D,SWPOPR ;- # PGS GOING OUT + ADDI D,10. ;MAKE SURE AT LEAST 10. GOING OUT + JUMPLE D,.+2 + ADDM D,SWPOPR + MOVEI D,1 + SKIPN FLSINS(W) + MOVEM D,EPDL2(W) + AOS NLPPG3 + POPJ P, + +CFHPO3: PUSH P,A ;FLSINS ROUTINE (NEEDED MEM) + MOVE A,MEMFR + SUB A,NCBCOM + CAIL A,5(T) + JRST POPAJ1 ;NEEDED MEM AVAILABLE + ADD A,SOLNG + ADD A,SWPOPR + SUBI A,10.(T) + JUMPGE A,POPAJ ;WILL EVENTUALLY WIN + MOVNS A + ADDM A,SWPOPR ;LOSING - SWAP SOME MORE STUFF OUT + JRST POPAJ + +IFE SWPWSP,[ +;HERE IF TRYING TO SWAP IN A PAGE BUT SWAP BLOCKED +CFBO1: MOVE E,MEMFR ;GUY SWAPPED BLOCKED + SUB E,NCBCOM + SUB E,AUSOPG + SUB E,SILNG + ADD E,SOLNG + JUMPGE E,CFBO3 ;SEEMS TO BE ROOM SO LET IT COME IN + TLNN W,200000 + JUMPL W,CPOPJ ;HANG GUY UNTIL SWAP BLOCK GOES AWAY + MOVE C,[SKIPGE USWSCD] + ADDI C,(W) + AOS NTSBUB + AOS NLPPGB + POPJ P, + +CFBO3: AOS NTSBUP + JRST CFBO2 +];SWPWSP + +OVHMTR WS ;WORKING-SET COMPUTATIONS + +IFN SWPWSP,[ +;HERE WHEN A SWAPPED OUT OR SWAP BLOCKED JOB TRIES TO SWAP IN A PAGE. +;JOB IN W, C -> MMP, USWST(W) IN E. RETURN TO CFSB1. +;WE DECIDE WHETHER ENOUGH CORE CAN BE GARNERED TO LET HIM IN, AND PUT +;HIM INTO THE LOADING STATE, OR ELSE PUT HIM INTO THE SWAP BLOCKED STATE. + +CFSB: PUSH P,C + TLNN E,%SWSB ;ALREADY SWAP BLOCKED? + PUSHJ P,WSRCM ;NO, RECOMPUTE WORKING SET + POP P,C + MOVE B,USWPRI(W) ;FIND SUM OF WS'S OF SWAPPED IN GUY'S WITH BIGGER USWPRI + PUSHJ P,WSAVL + MOVE D,USVWRK(W) ;COMPUTE AMT OF WS NOT ALREADY IN CORE + SUB D,UWRKST(W) +IFL TSYSM-356.,[ + CAML D,[TSYSM-100.,,] + JRST .+3 ;WS > PHYSICAL MEM, ALLOW IN ANYWAY, FOO! +];TSYSM + CAMGE A,D ;WILL IT FIT IN AVAILABLE MEM? + JRST CFSB2 ;NO, SWAP BLOCK + PUSHJ P,CFELD ;YES, ENTER 'LOADING' STATE + JRST CFSB1 ;AND GO AHEAD AND BRING IN THE PAGE + +CFSB2: TLNN W,200000 ;IF PAGE-AHEAD, JUST RETURN. + JUMPL W,CPOPJ + MOVE T,TIME + MOVSI A,%SWSB ;ALREADY SWAP BLOCKED? + TDNE A,USWST(W) + JRST CFSB3 + IORM A,USWST(W) ;NO, ENTER SWAP BLOCKED STATE + AOS NUSWB + MOVEM T,USWTIM(W) +CFSB3: MOVE U,W + MOVSI T,3_16. ;MAKE SWAP HISTORY TABLE ENTRY FOR SWP BLK + PUSHJ P,SWPKHT + MOVE T,TIME + SUB T,USWTIM(W) ;HOW LONG SWAP BLOCKED + CAIGE T,20.*30. ;IF LESS THAN 20 SECONDS, + SKIPA T,[15.] ; SLEEP FOR 1/2 SECOND, + MOVEI T,5*30. ; OTHERWISE SLEEP FOR 5 SECONDS + ADD T,TIME + SKIPN FLSINS(W) + MOVEM T,EPDL2(W) + MOVEI A,0 ;WILL THEN TAKE FAULT AGAIN AND + MOVE C,[CAMLE T,TIME] ;CHECK AVAILABLE MEMORY AGAIN + AOS NLPPGB + POPJ P, + +;ROUTINE TO FIND MEMORY AVAILABLE TO A JOB WHOSE USWPRI IS IN B +;RETURNS IN LH(A) SUITABLE FOR COMPARING TO UWRKST. SMASHES T,TT,J + +WSAVL: MOVEI J,2*LUBLK ;DON'T LOOK AT SYS NOR CORE JOB + MOVSI T,%SWOUT+%SWLOD ;IF THESE BITS CLEAR, JOB IS SWAPPED IN + MOVE A,MEMFR ;FREE CORE + SUB A,NCBCOM ;FUDGE FOR THINGS IN PROCESS + SUB A,SILNG ;.. + ADD A,SOLNG ;.. + ADD A,NLOOSP ;LOOSE PAGES ARE EVICTABLE + SUB A,SWPOPR ;DON'T COUNT PAGES ALREADY COMMITTED TO EVICT + HRLZI A,-4(A) ;ALIGN AS UWRKST AND ALLOW 4 PAGES OF SLOP + SKIPA TT,TIME ;TO SEE IF PROTECTED AGAINST MEMORY PREEMPTION +WSAVL1: ADDI J,LUBLK + CAML J,USRHI + POPJ P, + SKIPE UNAME(J) + TDNE T,USWST(J) + JRST WSAVL1 ;DOESN'T EXIST, OR NOT SWAPPED IN, OR LOADING + CAMGE B,USWPRI(J) + CAMGE TT,USWTIM(J) + JRST WSAVL1 ;HIGHER PRIORITY OR PROTECTED + ADD A,UWRKST(J) ;THIS GUY'S WORKING SET IS PREEMPTABLE + JRST WSAVL1 + +;Routine to re-compute working set, also re sets up map +;to point to any pages which are swapped in but not mapped in. +;This is necessary in order to get the proper estimate of +;how much core is going to have to be swapped out to make +;this job fit. Called when a job leaves the swapped-out state, +;to enter either Loading or Swap-blocked. +;Job is in W, smashes A,B,C,D,E,T,TT,H,I,U. +;Call with CIRPSW locked and clk in progress. +WSRCM: SETZM UWRKST(W) + MOVEI E,UPGMP(W) ;SET UP SCAN OF USER'S MAP + HRLI E,442200 + MOVEI C,UPGCP(W) ;AND OF CIRCULAR POINTERS + HRLI C,442200 + LDB D,[121100,,HUSRAD(W)] ;# OF USER PAGES +WSRCM1: ILDB A,E ;GET PAGE MAP ENTRY + ILDB B,C ;AND CIRCULAR POINTER + JUMPE A,WSRCM2 ;JUMP IF PAGE DOESN'T EXIST + CAIN B,-1 + JRST WSRCM2 ;ABS PAGE, DON'T COUNT + TRNN A,600000 ;ALREADY SWAPPED IN? + JRST WSRCM3 ;NO, GO PONDER + ANDI A,PMRCM ;GET PAGE MAPPED TO + HRRZ B,MMSWP(A) ;GET # SHARERS + MOVSI A,1 ;COMPUTE WS ADJUSTMENT + IDIV A,B + ADDM A,UWRKST(W) +WSRCM2: SOJG D,WSRCM1 ;LOOP + POPJ P, + +WSRCM3: PUSH P,C ;PAGE NOT MAPPED, SEE IF IT'S IN + PUSHJ P,UCPRL + 100000,,WSRCM4 ;RETURN WITH 4 PUSHES IF MEMORY IN LOOP + POP P,C ;NO MEMORY, LEAVE ALONE + SOJG D,WSRCM1 + POPJ P, + +WSRCM4: SUB P,[4,,4] ;FOUND MEMORY, IN T + TRNE A,2 + MOVEI A,2 ;USE READ/WRITE/FIRST RATHER THAN READ/WRITE + LSH A,20 + IORI A,PMCSHM(T) ;SET UP MAP + DPB A,E + AOS C,MMSWP(T) ;ONE MORE USER POINTING TO PAGE + MOVSI A,1 + MOVEI B,-1(C) + IDIVM A,B ;ADJUST WS AS IF WAS ALREADY POINTING TO PAGE + ADDM B,UWRKST(W) ;ADDM DOES NOTHING IF THERE WAS DIVIDE BY ZERO + IMULI C,-1(C) ;COMPUTE WS DECREASE DUE TO ADDITIONAL SHARING + MOVNI C,(C) + IDIV A,C ;IF DIVIDE BY ZERO, A GETS RIGHT THING! + MOVE C,(P) ;ADJUST ALL SHARER'S WS'S + PUSHJ P,UCPRL + SETZ WSRCM5 + POP P,C + SOJG D,WSRCM1 + POPJ P, + +WSRCM5: ADDM A,UWRKST(U) + POPJ P, + +;LEAVE LOADING STATE IF IN IT. JOB IN U, SMASH C,TT,T,I +LVLOAD: MOVE C,USWST(U) + TLZN C,%SWLOD + POPJ P, ;NOT IN LOADING STATE +LVLOA0: MOVEM C,USWST(U) ;TURN OFF LOADING STATE + MOVE T,TIME + SUB T,USWTIM(U) ;TIME IT TOOK TO LOAD + IMUL T,LODFCT ;COMPUTE PROTECT TIME + HLRZS T + ADD T,TIME + MOVEM T,USWTIM(U) + MOVSI T,1_16. ;MAKE SWAP HISTORY TABLE ENTRY + JRST SWPKHT + +;PUT JOB IN W INTO THE 'LOADING' STATE. CALL WITH D CONTAINING USVWRK-UWRKST. +;WSRCM MUST HAVE BEEN CALLED ALREADY ON THIS JOB. SMASHES A,D,T,TT,I + +CFELD: MOVE T,USWST(W) + TLNE T,%SWSB + SOS NUSWB ;CEASES TO BE SWAP-BLOCKED + TLZ T,%SWOUT+%SWSB+%SWDSO+%SWBEM + TLO T,%SWLOD + MOVEM T,USWST(W) + MOVE T,TIME ;SAVE TIME STARTED TO LOAD + MOVEM T,USWTIM(W) + MOVE U,W + MOVSI T,0 ;MAKE SWAP HISTORY TABLE ENTRY + PUSHJ P,SWPKHT + JUMPLE D,CPOPJ + HLRZ D,D ;NUMBER OF PAGES GOING TO NEED, PROBABLY + MOVE A,MEMFR ;FREE CORE + SUB A,NCBCOM ;FUDGE FOR THINGS IN PROCESS + SUB A,SILNG ;.. + ADD A,SOLNG + SUB D,A ;NUMBER OF PAGES GOING TO HAVE TO SWAP OUT + SKIPLE D + ADDM D,SWPOPR ;START THEM GOING OUT NOW + POPJ P, +];SWPWSP + +OVHMTR FLT ;MISC FAULTS + +CFH4: TLNE W,100000 ;PAGE-AHEAD OF NON-EX PAGE: DO NOTHING. + POPJ P, + JUMPL W,SWIILM ;IF FROM DMA DEVICE, GIVE ERROR +;HERE FOR FAULTS WHICH ABORT THE INSTRUCTION. +PFA7: MOVE T,OPTION(U) ;IF USER WANTS IT, + TLNN T,%OPOPC ;GIVE HIM THE OPC RATHER THAN + AOSA T,CLKBRK ;THE INCREMENTD PC. +PFA7A: MOVE T,CLKBRK ;HERE FOR KL10 MAR BREAK AND KS10 NXI + ;ERROR, ALWAYS GIVE ORIGINAL PC, INST + ;ABORTED + TLNE T,%PCUSR + JRST CLKB1J + MOVEI C,IOADCR ;FROM EXEC MODE SO RESET PC TO IOADCR + EXCH C,CLKBRK + HRRM C,LEXFDR(U) ;AND SAVE FAULT EXEC ADR FOR DEBUGGING + CLEARM DLSRCH ;IN CASE IT WAS SET + CLEARM UMAPS(U) ;RESTORE NORMAL MAP IN CASE RANDOM ONE WAS + ;IN USE + +CLKB1J: HRLM D,LEXFDR(U) ;SAVE PF BITS FOR DEBUGGING PURPOSES + +IFN KS10P,[ TRNE D,%PFNXI ;Non-existent IO register in KS10 Unibus. + TLO A,(%PINXI) +] ;KS10P + +IFN KS10P, TRNN D,%PFNXI\%PF2.9\%PF2.8 +IFN KA10P, TLZE D,210 ;NO ACCESS OR DBL +IFN KL10P, CAIN D,%PFPNA + TRO A,%PIMPV ;ILM + +IFE KS10P,[ +IFN KA10P, TLZE D,20 ;PURE +IFN KL10P, CAIN D,%PFPRO + TLO A,(%PIFET) +] ;IFE KS10P + +IFN KS10P, CAIN D,%PFWRT\%PF2.8 +IFN KA10P, TLZE D,100 ;W IN RD ONLY +IFN KL10P, CAIN D,%PFILW + TLO A,(%PIWRO) + + TDNE A,[%PIMPV\%PIWRO\%PINXI] + PUSHJ P,MPVMAS ;SAVE FAULT PAGE # FOR DEBUGGING + +;;; NO ABORT-TYPE FAULTS, CHECK OTHERS: + +IFE KS10P,[ +IFN KL10P, CAIN D,%PFMAR +IFN KA10P, TLZE D,2 + PUSHJ P,PCMARB +] ;IFE KS10P + +IFN KA10P,[ TLZE D,2000 + PUSHJ P,CPROC1 ;ONE PROCEED + ANDCA D,UPQUAN(U) ;GET BITS FLUSHED BY TLZE'S +] ;KA10P + +CFH6: +IFN KA10P,[ + ANDCMI D,-1 ;DON'T CLOBBER USER'S RUNTIME. + TLZ D,4 ;DON'T CLOBBER EXEC PAGING FLAG. + TLO D,1 ;IGNORE QUANTUM-TIMEOUT INT. + ANDCAM D,UPQUAN(U) +] ;KA10P +CLKB1K: LPMR UPGML(U) +CLKB1G: IFN KA10P, CONO 470000+APRCHN ;RESET +CLB1X: MOVE T,CLKBRK ;PUT USER'S PC WHERE IT BELONGS + MOVEM T,UPC(U) + MOVE B,[BADBTS] + IOR B,MSKST(U) ;GET OR OF ENABLED AND BAD BITS + AND B,A ;GET AND WITH BITS ACTUALLY ON + JUMPE B,CLB1XA ;NOT BAD OR ENABLED, FORGET ABOUT IT + IORM B,PIRQC(U) ;GIVE INTERRUPT + CAIN T,IOADCR ;READY TO BE INTERRUPTED? + JRST CLKB5 ;NOT QUITE, RUN MOMENTARILY AND WILL UFLS +IFN SCHBLN,SETZM SCHMNY ;DO FULL SCHEDULE TO DELIVER THE INTERRUPT + JRST SCHED2 + +CLB1XA: MOVSI T,%SWINT .SEE INTPFL ;IF PAGE FAULT DUE TO USER TRYING TO + TDNN T,USWST(U) ;INTERRUPT, BETTER SCHED SO HE GETS THE INT. + SKIPE FLSINS(U) ;ELSE PROCEED THE USER IF HE HAS GOT WHAT HE WANTED. + JRST SCHED2 ;OR IF HE'S WAITING, GO SCHEDULE. + JRST CLKB5 + +IFN KA10P,[ ;NULL JOB LOST +CNLJL: CONSZ 230220 ;SKIP ON JUST "ADDR BREAK" (QUANTUM OVERFLOW) + BUG PAUSE,[KA: APR ERROR IN NULL JOB] + CONO 470000+APRCHN + JRST SCHED + +CFHFPF: BUG PAUSE,[PAGE FAULT IN SYSTEM, PC=],OCT,CLKBRK,[PAGE=],OCT,E + MOVSI D,1770 ;FALSE PAGE FAULT + MOVEI A,0 + JRST CFH6 +] ;KA10P + +EBLK +RINT: 0 +BBLK + CONI RINTAP ;SAVE STATUS IN CASE SOMEONE DUMPS IT + CONI PI,RINTPI + BUG AWFUL,[RANDOM INTERRUPT, APR ],OCT,RINTAP,[PI ],OCT,RINTPI + JRST 12,@RINT ;YOU CAN TRY PROCEEDING + +EBLK +RINTAP: 0 ;APR STATUS AT RINT +RINTPI: 0 ;PI STATUS AT RINT + +IFN KS10P,[ ; On KS, all random interrupts are created equal. +BBLK +RINT1==:RINT +] ;IFN KS10P + +IFE KS10P,[ +R1NTAC: BLOCK 20 +RINT1: 0 +BBLK + MOVEM 17,R1NTAC+17 + MOVEI 17,R1NTAC + BLT 17,R1NTAC+16 + MOVEI J,1 + JSP E,SPUR + MOVSI 17,R1NTAC + BLT 17,17 + JRST 12,@RINT1 +] ;IFE KS10P + +IFE KS10P,[ ;KS10 HAS NO MAR + +PCMARB: +IFN KA10P,[ + HLLZ B,UPOPC(U) ;FLAGS + LSH B,5 + HRR B,UPOPC(U) ;PC + MOVE T,B + XOR T,CLKBRK ;DID PC CHANGE FROM START OF INST TO PLACE TRAPPED? + TDNE T,[#<%PCFPD,,>] + TLO B,(@) ;YES, INSTRUCTION COMPLETED, FLAG FOR USER +] ;KA10P ;LOSES FOR JSR .-1 WITH MAR AT .-1, BUT OTHERWISE OK +IFN KL10P,[ + MOVE B,CLKBRK ;PC OF FAULTING INST IF USER, OR IOADCR IF EXEC +; MOVEM B,UPOPC(U) ;SOLELY FOR .OPC USER VAR +;NOTE- ON KL10 THE INSTRUCTION IS NEVER COMPLETED, DON'T SET 3.5 +] ;KL10P + TLNE B,%PCUSR + JRST PCMAR1 ;USR MODE, USE PC FROM PAGER + MOVE B,UUOH ;EXEC MODE, USE USER PC (UUO) + HRRI B,-1(B) +IFN KL10P,[ ;ON KL10 AVOID DOING AOS UUOH AT IOADCR + MOVEM U,AC0S+U(U) + MOVEI T,UUOER2 + MOVEM T,CLKBRK +];KL10P +PCMAR1: MOVEM B,UMARPC(U) + TRO A,%PIMAR + MOVEI B,0 +IFN KA10P, DPB B,[220300,,UPMAR(U)] ;DISABLE MAR +IFN KL10P, DPB B,[270400,,UPMAR(U)] ;DISABLE MAR + POPJ P, + +] ;IFE KS10P + +IFN KA10P,[ +CPROC1: MOVE T,CLKBRK + TLNN T,%PCUSR ;SKIP IF FROM USER MODE + JRST CPRUUO + TRO A,%PI1PR ;GIVE USER INTERRUPT + POPJ P, + +CPRUUO: MOVE T,[JRST ONEPROC] ;ONE PROCEED INT. FROM EXEC. MODE + MOVEM T,UEXIT ;CLOBBER EXIT TO RUN SYS CALL TO COMPLETION + POPJ P, + +AROV: TLZE T,400000 + TLNN T,%PCUSR + JRST AROV2 ;NOT REALLY SET OR SET BY SYS + MOVEM T,CLKBRK + SKIPE PICLR(U) ;SKIP IF INTERRUPTS TO USER NOT ENABLED + TRO A,%PIARO ;GIVE USER INTERRUPT + POPJ P, + +AROV2: MOVEM T,CLKBRK + POPJ P, + +ARFOV: TLZE T,40000 + TLNN T,%PCUSR + JRST AROV2 + MOVEM T,CLKBRK + SKIPE PICLR(U) + TLO A,(%PIFOV) + POPJ P, +] ;KA10P + +;;; HANDLE PARITY ERRORS. + +CLKB1E: SETZM PARDIE ;AT FIRST ASSUME THE PAR ERR ISN'T FATAL. + CONO PI,PIOFF ;TURN OFF WORLD +IFN KA10P, CONO PI,240000 ;RESET +IFN KL10P,[ ;CLEAR THE CACHE + SWPUA + CONSZ 200000 + JRST .-1 +] ;KL10P +IFN KS10P,[ + CLRCSH ;Clear the cache +] ;KS10P + MOVSI B,SCLPAR + TDNE B,SUPCOR ;IF PREV ERROR NOT PRINTED, PRINT IT NOW AND PAUSE + BUG PAUSE,[TOO MANY PARITY ERRORS. PREV STATUS=],DEC,PARCNT,OCT,PARAAN,OCT,PARAOR,OCT,PARAND,OCT,PARIOR + IORM B,SUPCOR ;TELL SYS JOB TO PRINT OUR DATA WHEN WE FINISH. + AOS PARERR ;COUNT # OF PAR ERRS SINCE SYSTEM STARTED. + SETOM PARAND ;INIT LOGAND AND LOGOR OF ALL BAD DATA WORDS + SETZM PARIOR + SETOM PARAAN ;AND SIMILAR FOR ADDRESSES OF PAR ERRS. + SETZM PARAOR + MOVE T,CLKBRK + MOVEM T,PARPC + MOVE T,USER + MOVEM T,PARUSR ;REMEMBER WHICH JOB GOT THE PAR ERR. + JUMPL T,PARSCJ ;PAR ERR IN NULL JOB? OR WHAT? +IFN KL10P,[ + SKIPE PARRSN ;PAR ERR IN WORD NOT REFERENCED + JRST PARSCJ ; SHOULDN'T SCREW THE RUNNING JOB +] ;KL10P + CAIG T,LUBLK + SETOM PARDIE ;PAR ERR IN A SUPERVISOR-MODE JOB IS HOPELESS. + MOVSI TT,(%PIPAR) + IORM TT,PIRQC(T) ;GIVE RUNNING USER A PARITY ERROR (CLASS 1 INT) +PARSCJ: SPM PARPG +IFN KL10P,[ + PUSH P,PFNPC ;MAKE SURE THE PAR ERRS WE DETECT WHILE SCANNING DON'T + MOVEI D,PARFX4 ;CALL US RECURSIVELY (ON KA, THAT'S DONE BY HAVING + MOVEM D,PFNPC ;CLKCHN OFF) +] ;KL10P +IFN KS10P,[ + PUSH P,EPTP7N ;Same hack for the KS except page fails trap + MOVEI D,PARFX4 ;as a function of current PI level. + MOVEM D,EPTP7N +] ;KS10P + MOVEI D,0 ;POINTER TO ERROR BUFFER + MOVSI TT,-TSYSM + PUSHJ P,PARSCN ;SCAN MAIN MEM BLOCKS +IFN PDP6P,[ + MOVE TT,[-LPDP6M,,PDP6BM_-10.] ;SCAN PDP6 MEM FOR PARITY ERRORS + SKIPGE PDP6UP ;BUT NOT IF PDP6 IS DOWN. + PUSHJ P,PARSCN +] +IFN KL10P,[ + POP P,PFNPC + CONO 024400+APRCHN ;CLEAR PAR ERR FLAGS. +] ;KL10P +IFN KS10P,[ + POP P,EPTP7N + CONO 020200+APRCHN ;CLEAR FLAG + MOVSI A,%KEHLD+%KEREF ;CLEAR STATUS AND ERROR ADDR + IOWR A,[KSECCS] +] ;KS10P + MOVEI A,0 + DPB A,[.PAREP+EXEUMP] + LPMR PARPG ;SET UP MAP WITH PARPG SET TO MPV. + MOVEM D,PARCNT ;SAVE AWAY COUNT OF ERRORS IN BUFFER + SKIPE PARDIE + BUG HALT,[PARITY ERROR IN SYSTEM MEMORY. CNT=],DEC,PARCNT,[ADR AND ],OCT,PARAAN,CR,0,[ ADR IOR ],OCT,PARAOR,[DATA AND ],OCT,PARAND,[DATA IOR ],OCT,PARIOR + ;FATAL ERROR (DONT ALLOW CONTINUE SINCE ERR IS + ;KNOWN TO BE A LOSER) + CONO PI,PION ;TURN WORLD BACK ON + JRST SCHED + +PARSCN: +PARFX3: HRRZ T,TT ;SCAN AOBJN POINTER IN TT + CAIL T,TSYSM + JRST PARFX7 + LDB T,[MUR,,MEMBLT(TT)] + CAIN T,MUHOLE + JRST PARFX8 ;HOLE THERE +PARFX7: MOVEI T,600000(TT) ;NOTE THAT WE ARE NOT ENABLING THE CACHE. + DPB T,[.PAREP+EXEUMP] ;ON KL10 THIS WILL CAUSE A 1-WORD READ. + LPMR PARPG ;SET UP TO CHECK PAGE # IN TT + MOVEI B,0 ;ADDRESS WITHIN PAGE +PARFX1: +IFN KA10P, CONO PI,200000 ;CLEAR PAR ERR +PARFX5: MOVE C,400000+PAREP*2000(B) ;REFERENCE EVERY MEMORY LOCATION +IFN KA10P,[ + ;;ON KA, MUST CHECK EXPLICITLY. + ;;ON KL AND KS, PAR ERR WILL TRAP RIGHT TO PARFX4. + CONSZ PI,200000 ;PARITY ERR? + JRST PARFX4 ;YES. +] ;KA10P + CAIGE B,1777 ;SKIP ON FINISHED WITH BLOCK + AOJA B,PARFX5 +PARFX8: AOBJN TT,PARFX3 ;CHECK NEXT PAGE + POPJ P, ;DONE + +PARFX4: ;HERE WHEN THE SCAN FINDS A WORD WITH BAD PARITY +IFN KL10P, HRRZ T,PFOPC +IFN KS10P, HRRZ T,EPTP7O +IFE KA10P,[ + ;;DID THIS TRAP COME FROM SCAN LOOP WHERE WE EXPECT THEM? + CAIE T,PARFX5 + JRST 4,. + AC7CTX + UMOVE C,0 ;GET CONTENTS OF LOCATION WITH BAD PARITY + SYSCTX +] ;IFE KA10P + SETO T, ;MAKE SURE T ISN'T ACCIDENTALLY 0 AT PARFX6. + HRRZ E,TT + LSH E,10. + IOR E,B ;MAKE MEM ADR + CAIGE E,20 ;PAR ERR IN SHADOW ACS ISN'T SERIOUS. + JRST PARFX6 + ANDM E,PARAAN ;UPDATE ANDS AND ORS OF DATA AND ADRS + IORM E,PARAOR + ANDM C,PARAND + IORM C,PARIOR + MOVE A,USRHI + CAIGE E,USRSTG(A) + SETOM PARDIE ;PARITY ERROR IN EXEC CORE + HRRZ T,TT + CAIL T,TSYSM + JRST PARFX6 + LDB T,[MUR,,MEMBLT(TT)] + CAIE T,MUFR + CAIN T,MUINP + JRST PARFX6 + CAIE T,MUDISB + CAIN T,MUFRT + JRST PARFX6 + CAIN T,MUDDT + JRST PARFX6 + SOJE T,PARFX6 ;USER + SETOM PARDIE ;ERR IN CRITICAL MEMORY (DISK DIR, ETC) +PARFX6: MOVEM C,400000+PAREP*2000(B) ;FIX UP MEMORY AS BEST WE CAN + MOVEM C,PARCON(D) ;SAVE LOSING CONTENTS + MOVEM E,PARADR(D) ;SAVE LOSING ADDRESS + CAIL D,MXPARS-1 ;OVERFLOWING BUFFER? + SOS D ;JUST DON'T CLOBBER STUFF. AT LEAST PARAND, ETC. WILL BE VALID. + JUMPN T,PARFX9 + PUSH P,D ;PAR. ERR IN USER MEMORY, + HRRZ D,TT + CAIL D,TSYSM + JRST PARFXA + PUSHJ P,UCPRL4 ;HAS ANY JOB WRITTEN IN THIS PAGE? + 400000,,PARFU1 + JUMPL D,PARFXB ;SOMEONE HAS; JUST GIVE EVERYONE AN INTERRUPT. + PUSHJ P,UCPRL4 ;DOES MMP SAY PAGE WAS WRITTEN? IF SO, SET SIGN(D); + 200000,,PARFU2 ;OTHERWISE, SET MMPBAD, CAUSING PAGE TO BE RELOADED FROM DISK. + JUMPGE D,PARFXA +PARFXB: PUSHJ P,UCPRL4 ;PAGE HAS BEEN WRITTEN SINCE LAST ON DISK, SO WE CAN'T ESCAPE + 400000,,PARFU3 ;GIVING EVERY JOB AN INTERRUPT. +PARFXA: POP P,D +PARFX9: AOS B ;INCREMENT B HERE SO YOU DON'T HACK THE SAME + ; WORD AGAIN. IF THAT WORD WAS SOLIDLY BAD, + ; THIS CODE WOULD LOOP + CAIG B,1777 ;MIGHT BE DONE WITH PAGE + AOJA D,PARFX1 + AOJA D,PARFX8 + +PARFU1: CAIG U,LUBLK + SETOM PARDIE ;SYS JOB OR CORE JOB HAS PAGE + PUSH P,Q + MOVE A,I ;FIND PAGE-MAP HALFWORD FOR THIS PAGE + PUSHJ P,UPLC + POP P,Q + LDB A,T + LSH A,-20 + CAIE A,1 ;MAP SET UP TO A PAGE, AND IN READ-ONLY MODE? + JRST PARFU5 + DPB A,T ;YES, UNMAP IT SO THAT NEXT ACCESS WILL TRAP AND GO TO CFHPB + SOS MMSWP(D) ; IN CASE WE WILL SET MMPBAD. + ;NOTE, THIS MAY CRASH THE SYSTEM IF THE JOB WAS RUNNING IN A UUO, + ;HAD CHECKED ACCESS TO THE PAGE, AND WAS ASSUMING IT COULD ACCESS + ;IT AGAIN SAFELY. USUALLY THIS ONLY HAPPENS WHEN WRITING, HOWEVER. +IFN SWPWSP, ;DON'T BOTHER ADJUSTING WORKING SET. WILL BE FIXED ON NEXT SWAPIN. +PARFU5: CAIL A,3 +PARFU4: TLO D,400000 ;IF THIS JOB HAS WRITTEN THE PAGE, SET SIGN (D) + POPJ P, ;TO SIGNAL THAT SETTING MMPBAD IS NO USE. + +PARFU2: MOVE T,(C) ;C HAS ADDR OF MMP ENTRY; HAS PAGE BEEN WRITTEN BY A JOB + TLNN T,MMPWRT ;THAT NO LONGER HAS IT IN MAP? + TLNN T,MMPWOD ;OR HAS IT NEVER BEEN ON DISK? + JRST PARFU4 ;IF SO, AVOID SETTING MMPBAD, AND INTERRUPT EVERYONE. + HLRZ T,1(C) + JUMPE T,PARFU4 ;DITTO IF THERE IS NO DISK SPACE ASSIGNED. + MOVSI T,MMPBAD + IORM T,(C) + POPJ P, + +PARFU3: MOVSI T,(%PIPAR) + IORM T,PIRQC(U) + POPJ P, + +MEMHNG: +IFN PDP6P,[ + LDB B,[221100,,UPJPC(U)] ;FAULT ADDR + TRZN B,400 ;SKIP IF REFERENCE WAS VIA USER MAP + JRST MEMHN1 + MOVEI C,UPGMP(U) + ROT B,-1 + ADDI C,(B) + HRLI C,PMLCAD ;POINTER TO CORE ADR FIELD OF LH PAGE IN MAP WD + SKIPGE B + HRLI C,PMRCAD ;RH MAP WD + LDB C,B ;C GETS PAGE # + CAIGE C,+LPDP6M + CAIGE C,PDP6BM_-10. + JRST MEMHN1 + MOVE B,CLKBRK + TLNE B,%PCUSR + JRST MEMHN3 ;USER MODE PDP6 NXM + MOVEI B,IOCER3 ;PDP6 MEM + HRRM B,CLKBRK + JRST MEMHN2 +] + +MEMHN1: ;NXM + ; JRST 4,.+1 ;COMMENTED OUT SINCE NXM STOP SHOULD ALWAYS BE SET. +MEMHN2: +IFN KA10P,CONO 10000+APRCHN ;CLEAR NON EX MEM AFTER HALT TO RESET MEMORY +IFN KL10P,CONO 22000+APRCHN +IFN KS10P,[ + CONO 20400+APRCHN ;Clear APR flag + MOVSI B,%KEHLD+%KEREF ;Clear saved error address + IOWR B,[KSECCS] +] ;KS10P + MOVSI B,SCLNXM + TDNE B,SUPCOR ;Haven't printed previous error? + BUG PAUSE,[TOO MANY NXM ERRORS.] + IORM B,SUPCOR + MOVE T,CLKBRK + MOVEM T,NXMPC + MOVE T,USER + MOVEM T,NXMUSR + AOS NXMERR + POPJ P, + +IFN PDP6P,[ +MEMHN3: MOVSI B,%PIMPV ;PDP6 NXM GIVE MPV INTERRUPT + IORM B,PIRQC(U) + JRST MEMHN2 +] + SUBTTL SLOW CLOCK SERVICE ROUTINE + +OVHMTR SLW ;SLOW CLOCK + +SSLCK: SKIPGE SHUTDN ;SYSTEM "DEAD" => + PUSHJ P,COFFIN ;GO TO DDT AFTER RIGOR MORTIS SETS IN. + SETCMB A,SCKPHS ;CHECK SYSTEM CHECKSUMS EVERY OTHER SLOW CLOCK TICK + MOVE T,SUPCOP ;WHICH IS ONCE PER SECOND. + SKIPE A + IORM T,SUPCOR +IFN KS10P,[ + CONSO 100 ; Check for memory ECC corrected errors + JRST SSLCK0 + IORD A,[KSECCS] ; A: status and error addr + MOVEM A,ECCERA ; Remember most recent one + AOS ECCERR ; Also count 'em + CONO 20100+APRCHN ; Clear memory ECC APR flag + MOVSI T,%KEHLD+%KEREF ; Clear status and error addr + IOWR T,[KSECCS] + MOVE T,A + AND A,ECCAND ; A: AND of previous errors + IOR T,ECCIOR ; T: IOR of previous errors + CAMN A,ECCAND ; If either changes, this is news. + CAME T,ECCIOR + BUG INFO,[MEMORY: ECC CORRECTED ERROR],OCT,ECCERA + MOVEM A,ECCAND + MOVEM T,ECCIOR +SSLCK0: ] ;IFN KS10P +IFN NETP,PUSHJ P,NETCLK ; Run 1/2 sec clock routines for various net stuff +IFN NETYS, SETOM DTECHK ;TELL 11 WE'RE ALIVE +IFN DPKPP,[ + CONSO DPK,7 + CONO DPK,TTYCHN ;CROCK - IF DPK LOSES ITS PIA, GIVE IT BACK. +] + MOVE A,UTTBF + CAIGE A,30 + JRST SSLCK2 + SETOM UTBFLF ;SIGNAL CORE JOB TO FLUSH UTAPE BUFFERS + AOS NCORRQ +SSLCK2: SKIPE UTTYCT ;SKIP IF NO NEW USERS + SKIPL TREESW ;SKIP UNLESS SOMEBODY'S MUNGING THE TREE STRUCTURE. + CAIA + PUSHJ P,USTART ;NEW USER TO START +IFN 340P,[ + SKIPL T,DWDS + MOVEI T,0 + ADDI T,MDISWD + MOVEM T,DWDS ;RESET DISPLAY RATE COUNTER +] + CONO PI,UTCOFF ;UTC OFF WHILE HACKING UTAPE, MTAPE, DISK, ETC. +IFN RH10P+RH11P,[ + SKIPLE USFHLT + SOS USFHLT +];RH10P+RH11P +IFN NUNITS,[ +IFE NEWDTP,[ + MOVE T,TIME + AOSN UIDLE ;SKIP IF DEC TAPE NOT IDLE + JRST [MOVEM T,LUTOTM ? JRST SSLCK1] ;DEC TAPE IDLE + SUB T,LUTOTM ;SUBTRACT LAST UTC OPERATION TIME + CONSO UTC,4000 + CAIGE T,MXOPT*SCLKI ;SKIP IF DEC TAPE HUNG TOO LONG ON ONE OPERATION + JRST SSLCK3 ;OK + SETOM UTHERR ;SET UTC HUNG ERR FLAG +SSLCK1: CONO UTC,CUINT ;CAUSE DEC TAPE INTERRUPT ROUTINE TO RUN +SSLCK3: +] +IFN NEWDTP,[ + MOVE T,TIME + AOSN UIDLE + JRST [MOVEM T,LUTOTM ? JRST SSLCK1] + SUB T,LUTOTM + CAIGE T,MXOPT*SCLKI + JRST SSLCK3 + SETOM UTHERR +SSLCK1: SETOM CUINT + CONO PI,UTCRQ +SSLCK3: +]] ;END IFN NUNITS + SKIPL QSDU ;IF DISK TRANSFER IN PROGRESS + JRST [ MOVE T,LQTM ;SEE IF IT'S TAKING UNREASONABLY LONG TIME + ADDI T,5*30. + CAMGE T,TIME + PUSHJ P,QHUNG ;YES, UNHANG THE DISK + JRST .+1 ] +IFN T300P,[ + SKIPL QSDU1 ;IF TRANSFER IN PROGRESS ON OTHER CONTROLLER + JRST [ MOVE T,LQTM1 ;SEE IF IT'S TAKING UNREASONABLY LONG TIME + ADDI T,5*30. + CAMGE T,TIME + PUSHJ P,QHUNG1 ;YES, UNHANG THE DISK + JRST .+1 ] +];T300P +IFN DC10P, PUSHJ P,QRCTMO ;RECALIBRATE TIMEOUT + CONO PI,UTCON + PUSHJ P,QSTRTR ;WAKE UP DISK ROUTINES +IFN NMTCS, PUSHJ P,MSTRTR ;WAKE UP MAG TAPE ROUTINES (MUST BE SEPARATE INTR) +;DROPS THROUGH + +;DROPS IN +IFG NMTYS,[ ;TRY TO UNHANG MORTON TTY CARDS + MOVE I,[-NMTYS,,NFMTY] + MOVE T,TIME + SUBI T,60. ;IF HAVEN'T TYPED FOR 2 SECONDS +SSLCM1: SKIPL TTYOAC(I) ;YET SUPPOSED TO BE TYPING + CAMGE T,TTLTM(I) + JRST SSLCM2 + CONO PI,TTYOFF-1 + CONO MTY,@TTYLT(I) ;SELECT THE LINE + DATAO MTY,[0] ;AND BANG ON IT + CONO PI,TTYON-1 ;MAYBE IF WE'RE LUCKY ITS DONE FLAG WILL COME ON +SSLCM2: AOBJN I,SSLCM1 +] ;END IFG NMTYS +IFN IMPP,[ +IFN KAIMP, CONI IMP,IMPCNI ;KEEPS HOST READY ON +IFE KSIMP,[ + ;KS doesn't drop interrupts, I hope + PUSHJ P,IMPOST ;START UP OUTPUT +] +IFN NCPP,[ + SKIPLE IMNCS + PUSHJ P,IMPCCL ;CLOSE NETWORK CHANNELS + SKIPLE IMNAS + PUSHJ P,IMPAAA ;WAKE UP STYS THAT NEED IT +];NCPP + SKIPGE IMPTCU ;IF IMP IS TRYING TO COME UP + AOSE IMPUCT ;AND UP-COMING TIMEOUT EXHAUSTED + JRST SSLCK8 + BUG INFO,[NET: TIMED OUT TRYING TO COME UP] + MOVEI A,1 ;THEN MAKE IT STAY DOWN + MOVEM A,IMPUP ;IF THIS IS ML-KA THE IMP CABLE PROBABLY BROKE AGAIN +SSLCK8: +];IMPP +IFN PDP6P,[ + SKIPL PDPISR + CONO DSDEV,DSDCHN ;ENABLE INTERRUPTS FROM 6 +];PDP6P +IFN NETYS,[ + SKIPE DTEBBY + SOSL DTEBBT + JRST .+3 + BUG CHECK,[TTY: TIMEOUT ON OUTPUT XFER TO DTE, DTEBBY],OCT,DTEBBY + SETZM DTEBBY +];NETYS +IFN N11TYS,[ +;SEE IF THE TV PDP11 WANTS TO GO DOWN. + SKIPN TEN11F ;PROVIDED THE PDP11 IS THERE, + SKIPN TT11P ;AND WE'RE TRYING TO USE IT, + JRST SSLCK5 + LDB A,[061600,,TT11HA] ;DOES 11 WANT WHO LINES UPDATED? + CAIL A,2000*NTTPG ;RANGE CHECK SO CLOBBERED 11 MEMORY DOESN'T CAUSE ILL MEM REF + BUG HALT,[GARBAGE POINTER IN TV-11 MEMORY] + SKIPGE 1+400000+TTPG0*2000(A) + JRST [ MOVEI T,SCRWHO ;YES + IORM T,SUPCOR + CLEARM 1+400000+TTPG0*2000(A) + JRST .+1] + SKIPE TT11DN ;IF IT IS REQUESTING TO GO DOWN, + JRST SSLCK5 + SETZM TT11P ;DON'T USE IT & WAIT FOR IT TO RE-INIT, + MOVSI T,1 + MOVEM T,TT11DN ;GIVE IT OUR PERMISSION TO GO DOWN. + MOVEI T,SCR11D ;CAUSE "11 DOWN" MESSAGE + IORM T,SUPCOR +SSLCK5: SKIPN TEN11F + SKIPG TT11P ;WAITING FOR 11 TO BE UP? + JRST SSLCK6 + SKIPN TT11UP ;SKIP ON 11 UP + JRST SSLCK6 + MOVEI T,SCR11U + IORM T,SUPCOR ;INIT THE TTYS +SSLCK6: +] + SKIPLE T,AGERTE ;IF IT'S ENABLED, AGE SOME PAGES + PUSHJ P,AGE +;DROPS THROUGH + +;DROPS IN +IFN DL10P,[ + SKIPN DL10F + JRST SSLCKA + SETOM DL10UP ;COULD ALSO CHECK WHETHER PDP11 IS INCREMENTING THIS. + DATAI DLC,A + TRNE A,20 ;SEE IF PDP11 HALTED. + JRST SSLCKA + BUG INFO,[I/O PDP11 WENT DOWN] + SETZM DL10F + MOVEI T,%TYDL + MOVSI A,-NCT + TDNE T,TTYTYP(A) + SETOM TTYOAC(A) + AOBJN A,.-2 +SSLCKA: ] + AOS QACTTM ;Bump this for benefit of QSK dir writers. + SKIPN SWPOPR ;If there is a request to swap out pages + SKIPE SOLNG ; or if there are pages now going out + JRST SSKQ2 ; do not bother with LMEMFR, warnings. + MOVN A,LMEMFR ;See how many free low-memory pages. + ADD A,MINCOR + JUMPLE A,SSRCK ;Okay + AOS NCORRQ ;Wake up core job to do some shuffling + SUB A,MEMFR + ADD A,LMEMFR ;Core wanted minus high free + SKIPLE A + ADDM A,SWPOPR ;Swap out to make room. +;Check to see if we are running out of various resources. +;RSWTIM is a timestamp of last warning, initialized by DATIM6 and PDDCHK. +SSRCK: MOVE A,RSWTIM ;Get time we last checked. + ADDI A,2*30. + CAML A,TIMOFF ;If we checked less then 30 secs ago + JRST SSKQ2 ; don't deluge the console. + MOVE A,TIMOFF ;Else remember that we are cheking now. + MOVEM A,RSWTIM + MOVEI A,5 ;There should be at least 5 free low pages. + CAMLE A,LMEMFR ;If there are not, print warning. + BUG INFO,[Warning: Just ],DEC,LMEMFR,[ free pages in low core.] + SKIPN QFCHN ;Check disk channels. + BUG INFO,[Warning: No free qsk channels.] + MOVN A,USRHI ;Check job slots. + IDIVI A,LUBLK + ADDI A,MAXJ + SKIPN A + BUG INFO,[Warning: System full - no job slots.] +SSKQ2: +IFN 340P,[ + SKIPL DISUSR + PUSHJ P,DISCHK ;CHECK FOR 340 DEATH +] + PUSHJ P,PDCCHK ;CHECK ON REAL-TIME HACKS +IFN PTRP,[ + PUSHJ P,PTRCHK ;CHECK ON PAPER TAPE READER + PUSHJ P,PTPCHK ;CHECK ON PAPER TAPE PUNCH +] ;PTRP +IFE KS10P,[ ; Silly KS10 doesn't have devices... + SKIPN CCSDEV + JRST SCDCK3 + SETZM CCSDEV + MOVSI I,-128. +SCDCK1: SKIPGE A,DCHNTC(I) + TLNE A,300000 + JRST SCDCK2 + AOS CCSDEV + SUB A,[1,,] + TLNN A,777 + TLZ A,400000 + MOVEM A,DCHNTC(I) +SCDCK2: AOBJN I,SCDCK1 +SCDCK3:; JSP E,CHECK ;CHECK FOR CLOBBERED DEVICES +] ;IFE KS10P +IFN NLPTP,[ + CONO PI,LPTOFF + MOVE A,NLPTBR ;IF LPT OUTPUT BUFFER NOT EMPTY + CAIN A,LPTBSZ + JRST [ CONSZ NLPT,100 ;AND LPT IS READY + CONSZ NLPT,7 ;BUT HAS NO PIA + JRST .+1 + CONO NLPT,LPTCHN ;THEN IT LOST AGAIN + AOS NTNLPL ;COUNT NUMBER OF TIMES NEW LPT LOST + JRST .+1 ] + CONO PI,LPTON +] +IFN ECCMEM,[ +;THIS ASSUMES THAT THE PDP-10/XBUS ADDRESS OFFSET IS ZERO +ECCLOG: MOVE B,400000+ECCPG*2000+1760 + LSH B,-32. + CAMN B,ECCIDX ;DID ECC HISTORY POINTER ADVANCE? + JRST ECCLG9 + AOS A,ECCIDX ;YES, GET NEXT WORD FROM ECC HISTORY + MOVE B,400000+ECCPG*2000+1760-1(A) + ANDI A,17 ;ADVANCE OUR COPY OF POINTER + MOVEM A,ECCIDX + LDB A,[240700,,B] ;SYNDROME BITS + TLZ B,777774 ;REDUCE B TO ADDRESS BITS + BUG INFO,[MEM: ECC ERROR, ADDRESS ],OCT,B,[SYNDROME],OCT,A + JRST ECCLOG ;LOOK FOR MORE HISTORY + +ECCLG9: +];ECCMEM + PUSHJ P,GPDTIM ;WHAT CALENDAR TIME IS IT? + SETOB A,LPDTIM + EXCH A,LPDTIM ;REMEMBER IT FOR NEXT CLOCK TICK. + JUMPL A,ALCR0 ;TIME NOT KNOWN THIS AND/OR LAST TICK => DO NOTHING + SUB A,LPDTIM ;ELSE HOW LONG HAS IT BEEN SINCE PREVIOUS TICK? + CAML A,[-5*PDUPS] ;MORE THAN 5 SECONDS? SHOULD ONLY BE 1/60 + JRST ALCR0 ;ONLY EXPLANATION IS ITS WAS STOPPED AND CONTINUED. + SKIPL SYSDBG ;SO UNLESS THAT'S NORMALLY EXPECTED + PUSHJ P,DEATHM ;TELL THE WORLD "ITS REVIVED" + MOVE T,TIME ;REMEMBER WHEN THIS LAST HAPPENED + MOVEM T,RVVTIM + +;DROPS THROUGH + +;DROPS IN +;DECAY VARIOUS EXPONENTIAL AVERAGES. ON KA10, RUN IN ACS SINCE IT'S FASTER. +;ON KL10, DON'T, SINCE IT'S SLOWER. ON KS10, DON'T, BECAUSE IT IS +;JUST AS FAST TO RUN IN THE ACS BUT IT WASTES TIME TO MOVE THE CODE +;INTO THEM. +ALCR0: MOVSI U,-NCT + SETZM SLOADU +IFN KA10P,[ + MOVE I,[ALCR1,,A] + BLT I,I + JRST A +] ;KA10P + +ALCR1: MOVN T,USRRCE(U) ;A ;DECAY USRRCE AVERAGES + ASH T,-4 ;B + ADDB T,USRRCE(U) ;C + CAMLE T,SLOADU ;D ;AND SET SLOADU TO HIGHEST USRRCE + MOVEM T,SLOADU ;E +IFN KA10P,[ + AOBJN U,A ;TT + JRST .+1 ;I +] ;KA10P +IFE KA10P, AOBJN U,ALCR1 + + MOVN T,USRRCE+NCT + ASH T,-4-2 ;DISOWNED JOBS (DECAY SLOWER) + ADDB T,USRRCE+NCT + IMULI T,1999. ;MAKE COMMENSURATE WITH REGULAR USRRCE'S + ASH T,-13. ; (You might think that you could just + ; divide by 4, but in fact the ratio + ; between the two decay rates is + ; ln(64/63)/ln(16/15) = .24401474) + ADDM T,SLOADU ;DISOWNED TIME COULD HAVE BEEN USED BY REAL + ; USERS + MOVN T,USRRCE+NCT+1 + ASH T,-4+1 ;SYS, CORE, AND SOME DAEMON JOBS (DECAY FASTER) + ADDM T,USRRCE+NCT+1 + IRPS RCE,,LOSRCE IDLRCE + MOVN T,RCE ;LOST TIME AND IDLE TIME + ASH T,-4 + ADDB T,RCE + TERMIN + ADDM T,SLOADU ;IDLE TIME COULD HAVE BEEN USED BY USERS + +IFE KS10P, MOVE A,[193682794.] ; = 100. * 250000. * .5 / ln(16/15) + ; (100% of 250000. four usec ticks per second, + ; decaying by 16/15 every .5 second.) +IFN KS10P, MOVE A,[198524864.] ; = 100. * 256250. * .5 / ln(16/15) + ; (256250. 3.9 usec ticks per second.) +; Used to be: +; MOVE A,[100.*15.*125000.] ;100% DIVIDED BY MAXIMUM SINGLE TREE % + ADD A,LOSRCE ;WITH FUDGE FACTOR FOR LOST TIME + IDIVM A,SLOADU ;GIVES EFFECTIVE # OF COMPETITORS FOR MACHINE. +; It is possible for SLOADU to drop below 100. (giving a fair share greater +; than 100%). This happens because the decay rate for disowned jobs is +; less than the decay rate for consoles. If the load switches abruptly +; from the disowned jobs to some console, the resource word for the console +; fills up quicker than the disowned resource word decays, causing their +; sum to briefly exceed the maximum. This would be hard to fix without +; introducing additional resource words just for better maintaining SLOADU. +; +; An additional odd effect: If only disowned jobs are running, and a +; network server starts up, the fair share drops almost to zero. This is +; because when such jobs are created, their resource word is zeroed to +; given them an initial priority boost. + + MOVEI T,0 +IFN KA10P,[ + MOVE W,[ALCR4,,A] + BLT W,W + JRST A +] ;KA10P + +ALCR4: MOVN H,JTMU(T) ;A + ASH H,-4 + ADDM H,JTMU(T) + MOVE H,MSKST(T) + ANDI H,%PICLK ;E + SKIPE UNAME(T) ;TT + IORM H,PIRQC(T);I + ADDI T,LUBLK ;Q + CAMGE T,USRHI ;J +IFN KA10P,[ + JRST A ;R + JRST .+1 ;W +] ;KA10P +IFE KA10P, JRST ALCR4 +;DROPS THROUGH + ;DROPS IN +IFN SWPWSP,[ + MOVE U,USRHI + SUBI U,LUBLK ;ACCOUNT FOR I/O WAIT TIME IN USWPRI + MOVSI T,%SWOUT+%SWPGW +IFN KA10P,[ + MOVE J,[ALCR5,,A] + BLT J,J + JRST A +] ;KA10P +ALCR5: SKIPE UNAME(U) ;A ;IGNORE JOBS WHICH DON'T EXIST OR + TDNE T,USWST(U) ;B ;ARE SWAPPED-OUT OR IN PAGE-WAIT +IFN KA10P, JRST I ;C +IFE KA10P, JRST ALCR6 + SKIPN USTP(U) ;D ;CHARGE JOBS WHICH ARE STOPPED + SKIPE FLSINS(U) ;E ;OR BLOCKED + JRST ALCR7 ;TT +ALCR6: SUBI U,LUBLK ;I ;NEXT JOB +IFN KA10P,[ + JUMPG U,A ;Q + JRST .+1 ;J +] ;KA10P +IFE KA10P, JUMPG U,ALCR5 +];SWPWSP + SKIPGE 37 ;CHECK FOR PLANNED SYSTEM DEATH + PUSHJ P,DEATH ;ABOUT TO START DYING + JFCL + IRPS 4US,,[IDLTM1 LOSTM1 USRTM1 NULTM1]SEC,,[IDLTIM LOSTIM USRTIM NULTM3] + MOVE A,4US ;KEEP SYSTEM WIDE USAGES AS TWO WORDS + IDIVI A,250000. ;ONE IN 4.069 USEC UNITS + ADDM A,SEC ;AND ONE IN SECONDS + MOVEM B,4US ;SO NO OVERFLOW + TERMIN + IMULI A,60. ;CONVERT TO 60THS + ADDM A,NULTIM ;ADD TO 60THS USED (OBSOLETE) + MOVEI T,SCLKI + MOVEI C,SSLCKB + JRST CLQREE ;RE-ENTER RQ FOR SLOW CLOCK BREAK + +IFN SWPWSP,[ ;JOB IN U NEEDS TO BE CHARGED FOR MEMORY USED WHILE BLOCKED OR STOPPED +ALCR7: HLLO W,UWRKST(U) + JFFO W,.+1 ;H GETS 19 - LOG(WORKING SET SIZE + 1/2) + SUBI H,19. + IMUL H,[-125000.] ;CHARGE FOR 1/2 SECOND OF MEMORY USAGE + ADDM H,USWPRI(U) +IFN KA10P, JRST I +IFE KA10P, JRST ALCR6 +];SWPWSP + +;SYSTEM IN FINAL THROES OF COMING DOWN, SEE IF IT'S OVER YET + +COFFIN: MOVE T,NLOOSP ;MUST SWAP OUT ALL LOOSE PAGES + ADDB T,SWPOPR + JUMPN T,CPOPJ ;SWAPPAGE OUT STILL GOING ON + MOVEI T,NQCHN+1+NQS-1 + SKIPGE QSGL(T) + SOJG T,.-1 + SKIPL QSGL(T) ;NOT OVER IF ANY DISK CHANNELS ARE ACTIVE + POPJ P, + MOVSI T,040000 + MOVE TT,QACTB ;SEE IF DISK STUFF NOT OUT YET + TDNE TT,QMDRO + POPJ P, ;MFD NOT OUT + MOVSI A,-NQS +COFFI8: TDNE T,QTUTO(A) + JRST COFFI9 ;TUT NEVER CAME IN + TDNE TT,QTUTO(A) + POPJ P, ;TUT NOT OUT +COFFI9: AOBJN A,COFFI8 + MOVSI A,-QNUD +COFFI1: SKIPN QSNUD(A) + JRST COFFI2 + TDNE TT,QSNLCN(A) + POPJ P, ;UFD NOT WRITTEN +COFFI2: AOBJN A,COFFI1 + +IFN NUNITS,[ + MOVSI A,-NUNITS + SKIPGE UFLAPF(A) + POPJ P, ;TAPE STILL FLAPPING + AOBJN A,.-2 +] + MOVE A,DTHTIM + ADDI A,15.*30. ;DON'T WAIT FOR CONSOLES MORE THAN 15 SECONDS + CAMGE A,TIME ;BECAUSE %TCHNG ISN'T NECESSARILY SET + JRST COFFI3 + MOVEI A,NFSTTY-1 ;CHECK FOR REAL CONSOLES STILL TYPING OUT + MOVSI T,%TCHNG ;AND NOT HUNG (NEVER GOING TO FINISH TYPING OUT) + TDNN T,TTYCOM(A) + SKIPGE TTYOAC(A) + SOJGE A,.-2 + JUMPGE A,CPOPJ ;A CONSOLE IS STILL TYPING, DON'T GO DOWN YET +COFFI3: SKIPL A,SYSCN + SKIPGE TTYOAC(A) + CAIA + POPJ P, ;SYSTEM CONSOLE HAS A LOT OF TYPING TO DO + MOVEI A,2*LUBLK +COFFI7: CAML A,USRHI + JRST COFFI4 + SKIPE UNAME(A) + POPJ P, ;JOBS STILL EXIST + ADDI A,LUBLK + JRST COFFI7 + +;SYSTEM FULLY DOWN; GO TO DDT. +COFFI4: BUG DDT,[SHUTDOWN COMPLETE] + SETZM SHUTDN ;IF USER PROCEEDS, BRING SYSTEM BACK UP + SETZM DEDTIM ;ARRANGE TO RELOAD ATSIGN DRAGON + SETZM FLSINS ;BY RESTARTING SYS JOB WHERE IT DOES THAT + MOVEI A,ISYS + MOVEM A,UPC + POPJ P, + +;ROUTINE TO AGE SOME PAGES. THIS ROUTINE SLOWLY CIRCULATES THROUGH +;CORE. IF IT TOUCHES A PAGE TWICE, AND NO USER HAS TOUCHED IT, +;THE PAGE GETS SWAPPED OUT. ALSO FLUSHES PAGES NOT IN ANY USER'S MAP. +;ENTER WITH VALUE OF AGERTE IN T. + +AGE: MOVE TT,MEMFR + CAIL TT,100 + POPJ P, ;NO MEMORY COMPETITION, DON'T BOTHER + ADD T,AGEREQ ;INCREASE NUMBER OF PAGES NEEDING TO BE AGED + CAIGE T,100 ; BUT DON'T LET IT GET INFINITELY HUGE + MOVEM T,AGEREQ ; IF CIRPSW IS LOCKED FOR A LONG TIME + SKIPN DLSRCH ;IF MUSTN'T PCLSR ANYONE, OR + SKIPL CIRPSW ; IF CIRPSW LOCKED, HAVE TO WAIT UNTIL NEXT SLOW CLOCK + POPJ P, + LDB W,[121000,,HUSRAD] ;DON'T AGE SYSTEM JOB (CIRC PNTRS NOT CONNECTED) + MOVE A,AGEPOS ;CONTINUE AGEING FROM WHERE LEFT OFF LAST TIME + SKIPGE U,USER ;CHECK FOR NULJOB + JRST AGE0 + MOVE T,CLKBRK ;PC FOR USER WHO MAY GET PCLSR'D + MOVEM T,UPC(U) .SEE SWOP2 + LPMR UPGML(U) ;DON'T LEAVE SWAPPED OUT PAGES IN ASSOC MEM +AGE0: CAIGE A,TSYSM + CAMGE A,W + MOVE A,W + SOSGE AGEREQ + JRST [ MOVEM A,AGEPOS ? SETZM AGEREQ ? POPJ P, ] + AOS NAGES + LDB T,[MUR,,MEMBLT(A)] + CAIE T,MURUSR + AOJA A,AGE0 + MOVE D,A + PUSHJ P,UCPRL4 + SETZ AGE1 + MOVNI C,1 ;NO USERS ACTIVELY USING THIS PAGE, SWAP IT OUT + PUSHJ P,SWPOPG + JFCL + AOJA A,AGE0 + +AGE1: MOVEI C,UPGMP(U) + MOVE T,I ;DON'T CLOBBER I + ROT T,-1 + ADD C,T + HRLI C,222200 + SKIPGE T + HRLI C,2200 + LDB T,C ;GET PAGE MAP WORD + TRNN T,600000 + POPJ P, ;USER NOT CONNECTED TO THIS PAGE + TROE T,PMAGEM + POPJ P, ;HASN'T TOUCHED THIS PAGE SINCE AGE BITS LAST SET + DPB T,C ;HAS TOUCHED PAGE, TURN AGE BITS BACK ON + SUB P,[4,,4] ;AND BACK OUT OF UCPRL + AOJA A,AGE0 + +IFN 340P,[ + +DISCHK: SKIPGE DISOFF + POPJ P, + AOSLE DISDIE + SKIPGE CDISOFF + POPJ P, + MOVEI T,1 + MOVEM T,DTIME +DISZAP: MOVE T,[JSR DBLKPB] + MOVEM T,40+2*DISCHN + MOVEI T,DIS300-1 ;CAUSE 340 TO STOP AND INTERRUPT SOON + MOVEM T,DBLKOP + CLEARM DISOFF + CONO DIS,5100+SDCHN_3+DISCHN + POPJ P, +] + +DEATH: SKIPL SHUTLK + POPJ P, + SETZM 37 ;CLEAR START DYING FLAG + MOVEI T,60.*5.*60. ;5 MIN + MOVEM T,DEDTIM + LSH T,-1 + ADD T,TIME + MOVEM T,SHUTDN + PUSHJ P,CLQDEL + DEDBLK +DEATHX: SKIPN T,DEDTIM + POPJ P, + AOS (P) + MOVEI TT,0 + CAIGE T,40.*60. + JRST DEATHY + MOVE TT,T + LSH TT,-2 +DEATHY: MOVEM TT,DEDTIM + SUB T,TT + PUSHJ P,CLQADD + DEDBLK +DEATHM: MOVEI A,%PIDWN + PUSHJ P,INTALL ;TELL THE WORLD + MOVSI T,SCLSHD ;CAUSE TYPE OUT ON UNLOGGED-IN CONSOLES +SUPSET: IORM T,SUPCOR + POPJ P, + +VSSLCK: MOVSI T,SCLVSK + IORM T,SUPCOR ;CAUSE VERY SLOW CLOCK TO RUN + MOVEI T,VSCLKI + MOVEI C,VSLCKB + JRST CLQREE + +IFN CCLKP,[ +RCCLK: DATAI 374,T ;HACK CHESS CLOCK + TRNE T,4000 + AOSA CCLK1 + AOS CCLK2 + MOVEI T,6 + MOVEI C,CCLKB + JRST CLQREE +] + +IFN N11TYS,[ +WHOSET: MOVEI T,SCRWHO ;CAUSE SYS TO UPDATE WHO LINES + IORM T,SUPCOR + MOVEI T,5.*60.-5 ;5 SECONDS MINUS A LITTLE SO DOESN'T SYNC WITH OTHER CLOCKS + MOVEI C,WHOCLB + JRST CLQREE +] + +SUBTTL SWAP SCHEDULER + +OVHMTR SWS ;SWAP SCHEDULER + +;15 SECOND CLOCK +15SCLK: +IFN IMPP, PUSHJ P,IMRSTO ;RESET CONTROL LINK RFNM WAIT FOR LOSING IMP. + +;RECOMPUTE SWAP BLOCK DATA. +;DECAY SWAP PRIORITIES (USWPRI AND SWRCE) +;RESET BEST-EFFORT-HAS-BEEN-MADE TO SWAP OUT BITS + + MOVSI B,%SWBEM ;SET UP TO CLEAR "BEST EFFORT TO SWAP OUT BIT" + SETOM SBEFLG ;NOT YET DESPERATE ENOUGH TO TRY USERS WHOSE BEST EFFORT BITS ARE SET +IFE SWPWSP,[ + CLEARB T,NUSWB ;# USERS LOCKED OUT + SETOM BUSR ;SMALLEST SWAPPED BLOCKED USER + MOVE D,[37777,,777777] + MOVEM D,BUSIZ ;SIZE OF SMALLEST SWAP-BLOCKED USER. + CLEARM ASBUM ;REAL MEM OCC BY ACTIVE SWAPPED BLOCKED LOSERS + MOVSI D,400000 ;TO CLEAR SWAPPED BLOCKED BIT +];SWPWSP +.ELSE MOVEI T,LUBLK*2 +15S1: CAML T,USRHI + JRST 15S2 + SKIPN UNAME(T) + JRST 15S3 + MOVN C,USWPRI(T) + ASH C,-2 + ADDM C,USWPRI(T) ;DECAY JOB SWAP PRI'S + MOVE C,NMPGS(T) +IFE SWPWSP,[ + SKIPE ENPZRO + SUBI C,1 ;COMPENSATE FOR PAGE ZERO ALWAYS IN +];SWPWSP + CAMLE C,NSWPGS(T) ;SKIP ON NOT COMPLETELY OUT + ANDCAM B,USWST(T) .SEE %SWBEM +IFE SWPWSP,[ + SKIPGE USWSCD(T) + JRST 15S4 ;CLEAR SWAPPED BLOCK BIT AND MAYBE ADD TO AUSOPG AND TRUMM (IF HE WAS HUNG ON IT) +];SWPWSP +15S3: ADDI T,LUBLK + JRST 15S1 + +15S2: +IFE SWPWSP,[ + SKIPE ENSWSC + PUSHJ P,SWSCD ;SWAP BLOCK LOSERS IF NECESSARY +];SWPWSP + MOVSI T,-NCT-2 +15S5: MOVN C,SWRCE(T) ;DECAY TREE SWAP PRI'S + ASH C,-2 + ADDM C,SWRCE(T) + AOBJN T,15S5 + MOVEI T,15.*60. + MOVEI C,15SCLB + JRST CLQREE + +IFE SWPWSP,[ +15S4: ANDCAM D,USWSCD(T) ;CLEAR SWAP BLOCK BIT + SKIPN TT,FLSINS(T) ;WAS HE HUNG TESTING IT + JRST 15S3 + SUBI TT,(T) + CAME TT,[SKIPGE USWSCD] + JRST 15S3 ;HE WASN'T HUNG ON THIS + CLEARM FLSINS(T) ;HE WAS SO NOW HES ACTIVE + MOVE TT,USWST(T) + TLZE TT,%SWPGW + SOS NPGWTU ;FLSINS WAS SET BY PAGE FAULT, SO CONSIDERED + TLZ TT,%SWBEM ;TO BE WAITING FOR A PAGE + MOVEM TT,USWST(T) + MOVE TT,NMPGS(T) + ADDM TT,TRUMM ;GUY IS NOW RUNNABLE + SUB TT,NSWPGS(T) ;ANY PAGES HE MAY HAVE IN MEM NO LONGER BELONG TO A BLOCKED USER + MOVNS TT + ADDB TT,BUMPGS + SKIPGE TT + CLEARB TT,BUMPGS + MOVE TT,NSWPGS(T) ;ANY SWAPPED OUT PAGES BELONG TO AN ACTIVE USER + ADDM TT,AUSOPG + JRST 15S3 +];SWPWSP + +IFE SWPWSP,[ + +PRVCLK: SKIPN ENPVCL + JRST PRVCK4 + MOVSI B,%SWPRV + SKIPL U,PRVUSR + ANDCAM B,USWST(U) + SETOM PRVUSR ;TURN OFF CURRENT PRIVILEDGED USER + MOVEI J,2*LUBLK +PRVCK1: CAML J,USRHI + JRST PRVCK2 + SKIPN UNAME(J) + JRST PRVCK3 + MOVE B,UTRNTM(J) ;GET USER RUN TIME + SUB B,LTRNTM(J) + MOVE A,USIPRQ(J) + SUB A,LSIPRQ(J) + IMUL A,[NPVSEC*125000.] ;1/2 NUMBER OF 4 MICROSECOND INTERVALS IN THE PRIV INTERVAL + SKIPE B + IDIV A,B + MOVE B,UPGSEC(J) + LSH B,-1 ;DIVIDE LAST VALUE BY TWO + ADD A,B + MOVEM A,UPGSEC(J) ; LAST/2 + CURRENT + MOVE A,UTRNTM(J) + MOVEM A,LTRNTM(J) + MOVE A,USIPRQ(J) + MOVEM A,LSIPRQ(J) ;SAVE OLD VARIABLES +PRVCK3: ADDI J,LUBLK + JRST PRVCK1 + +PRVCK2: PUSHJ P,NPRVUS ;GET NEXT PRIV USR +PRVCK4: MOVEI T,NPVSEC*60. + MOVEI C,PRVCLB + JRST CLQREE + +NPRVUS: MOVEI J,2*LUBLK + SETOM U + MOVNI T,30.*2 ;DON'T LET A BLOCKED OR STOPPED PERSON BE PRIVILEDGED + ADD T,TIME + MOVE B,PRVCUT + HRLOI E,377777 +NPVUS1: CAML J,USRHI + JRST NPVUS2 + CAMGE T,LUBTM(J) ;BLOCKED TOO LONG? + SKIPN UNAME(J) + JRST NPVUS3 + CAMG B,UPGSEC(J) + CAMG E,LPRVTM(J) + JRST NPVUS3 + MOVE U,J + MOVE E,LPRVTM(J) +NPVUS3: ADDI J,LUBLK + JRST NPVUS1 + +NPVUS2: MOVEM U,PRVUSR + SKIPG U + POPJ P, + MOVSI B,%SWPRV + IORM B,USWST(U) + MOVE T,TIME + MOVEM T,LPRVTM(U) + POPJ P, +];SWPWSP + +IFE SWPWSP,[ +IFNDEF MEMSYS,MEMSYS==50 ;GUESS AT AMOUNT OF MEM SYSTEM NEEDS +IFNDEF MEMSY1,MEMSY1==50 ;AMOUNT OF MEM ANY ONE USER MUST LEAVE TO "FIT". + +SWSCD: MOVE E,TRUMM ;SEE IF NECESSARY TO SWAP BLOCK SOMEONE + CAIGE E,TSYSM-SYSB-MEMSYS + POPJ P, ;NO SHOULD FIT + MOVE E,MEMFR + SUB E,NCBCOM + ADD E,SOLNG + SUB E,SILNG + SUB E,AUSOPG + ADD E,BUMPGS ;WILL SWAP OUT BLOCKED USERS FIRST + ADD E,ASBUM + SUBI E,20 ;SLOP + JUMPGE E,CPOPJ ;SHOULD HAVE ROOM FOR EVERYBODY + MOVMM E,SWSCT1 ;SAVE # PGS REQ + MOVNI E,1 ;NEED TO GRONK USER (MAYBE) + CLEARB T,TT ;TT SWP PRI OF PROCESS + MOVEI R,0 ;R SWP PRI OF TREE +SWSCP1: CAML T,USRHI + JRST SWSCP2 + SKIPE UNAME(T) + SKIPE USTP(T) + JRST SWSCP7 + SKIPGE USWSCD(T) + JRST SWSCP7 ;GUY ALREADY LOCKED OUT + SKIPE FLSINS(T) + JRST SWSCP4 ;SEE IF REALLY BLOCKED OR JUST PAGE WAIT +SWSCP5: MOVE B,UTMPTR(T) + CAML R,SWRCE-USRRCE(B) + CAMG TT,USWPRI(T) + JRST SWSCP6 ;THIS GUY A BIGGER LOSER THAT PREV BIGGEST +SWSCP7: ADDI T,LUBLK + JRST SWSCP1 + +SWSCP6: MOVE E,T + MOVE R,SWRCE-USRRCE(B) + MOVE TT,USWPRI(T) + JRST SWSCP7 ;GUY REALLY BLOCKED + +SWSCP4: MOVE B,USWST(T) + TLNE B,%SWPGW + JRST SWSCP5 + JRST SWSCP7 + + +SWSCP2: JUMPL E,CPOPJ ;NO VICTIM + MOVE B,NMPGS(E) + CAIGE B,TSYSM-SYSB-MEMSY1 + JRST SWSCP9 ;"SMALL LOSER" + SUB B,NSWPGS(E) + CAMLE B,SWSCT1 ;SKIP ON WILL STILL NEED TO BLOCK MORE LOSERS + POPJ P, +SWSCP9: MOVSI B,400000 + IORM B,USWSCD(E) ;SWAP BLOCK LOSER + AOS NUSWB + AOS NTUSB + MOVE TT,NMPGS(E) + CAMLE TT,BUSIZ + JRST SWSCP8 + MOVEM TT,BUSIZ + MOVEM E,BUSR +SWSCP8: SUB TT,NSWPGS(E) + SOSGE TT + MOVEI TT,0 + ADDM TT,ASBUM ;THIS GUY SWAPPED BLOCKED + MOVN TT,NMPGS(E) + ADDM TT,TRUMM ;DOESNT COUNT ANY MORE + SKIPGE TRUMM + CLEARM TRUMM + MOVN TT,NSWPGS(E) + ADDM TT,AUSOPG ;NOT REALLY ACTIVE ANY MORE + JRST SWSCD ;SEE IF THATS ENUF +];SWPWSP + +OVHMTR PPI ;PPIUM + +;PUT PAGE INTO USERS' MAPS (OF ALL USERS THAT ARE CONNECTED VIA CIRCULAR POINTERS) +;ALSO UPDATES THE WORKING SETS. +;CALL WITH PAGE NUMBER IN A, STARTING BYTE POINTER IN C, AND TDNE T,MMP IN D. +;SMASHES T,H,I,U,E,TT,C +PPIUM: AOS NPPIUM +IFN SWPWSP,[ + MOVEI E,0 ;COUNT USERS OF THE PAGE + PUSHJ P,UCPRL + 400000,,[AOJA E,CPOPJ] + HRRM E,MMSWP(A) ;ALL THESE SHARERS WILL BE CONNECTED TO THE PAGE + MOVSI T,1 ;COMPUTE WORKING SET ADJUSTMENT + IDIVM T,E ;I.E. 1 OVER NUMBER OF SHARERS +];SWPWSP + PUSHJ P,UCPRL ;GIVE PAGE TO ALL USERS WAITING FOR IT + 400000,,PPIUM1 + POPJ P, + +;SET UP MAP TO MEMBLT INDEX IN A +PPIUM1: AOS NPPIU1 + CAIG U,LUBLK + BUG ;SYS JOB OR CORE JOB + PUSH P,I + MOVEI C,UPGMP(U) + ROT I,-1 + ADDI C,(I) + HRLI C,222200 + SKIPGE I + HRLI C,2200 + LDB I,C + JUMPE I,[JRST 4,.] ;DOESN'T REALLY EXIST? + MOVSI T,MMPPGA ;DON'T REALLY PUT IN MAP IF PAGE-AHEAD PAGE. + TDNE T,(D) ;JUST PRE-EMPT. + JRST QSWI2A + TRNE I,600000 ;DO NOTHING IF ALREADY IN MAP. +IFE E.SP,[ + JRST QSWI2 ;ALREADY IN MAP, POSSIBLE AS A RESULT OF RIDICULOUS TIMING ERROR +] +IFN E.SP,[ + JRST E.SPGJ ; CHECK E&S WANTS READ/WRITE FIRST FIX +] + SOS NSWPGS(U) ; NUMBER OF SWAPPED-OUT PAGES + SOS SNSWPG ;DECR CNT OF SWAPPED OUT FOR SYS + SKIPN (P) ;DON'T SET UP PG 0 AS R-W-F. + JRST QSWI3 + TRNE I,2 + MOVEI I,2 ;SET READ/WRITE TO READ/WRITE/FIRST +QSWI3: LSH I,16. + IORI I,PMCSHM(A);BRING IN ADDRESS AND CACHE BITS + DPB I,C +QSWI2: +IFE SWPWSP,[ + AOS MMSWP(A) ;INCREMENT COUNT OF USERS IN RING +];SWPWSP +IFN SWPWSP,[ + ADDM E,UWRKST(U) ;ADJUST WORKING SET +];SWPWSP +QSWI2A: +IFN PAGPRE,[ +;IF THIS USER IS WAITING FOR THIS PAGE, MAKE HIM RUNNABLE BY PUTTING +;HIM ON THE SCHMNY LIST, AND PRE-EMPT THE CURRENTLY-RUNNING USER. +;THE IDEAS ARE TO START THIS USER'S NEXT PAGE READ AS SOON AS POSSIBLE, +;AND TO ELIMINATE THE SCHEDULING THAT WOULD OTHERWISE BE NECESSARY TO RUN THIS GUY. + AOS NPREE1 + CONSZ PI,200_-APRCHN ;CAN'T PREEMPT IF CLKOFF + CONSZ PI,100000_-APRCHN ;OR IN PROGRESS, BECAUSE + JRST POPIJ ;MIGHT ZERO FLSINS WHILE SCHEDULER + ;IS EXECUTING IT & SIMILAR NASTIES + AOS NPREE2 + CAME D,FLSINS(U) ;IF JOB THAT JUST GOT PAGE IS WAITING FOR IT + JRST POPIJ + AOS NPREE3 + SETZM FLSINS(U) ;THEN THAT JOB PREEMPTS CURRENT ONE + MOVSI T,%SWPGW + TDNE T,USWST(U) + SOS NPGWTU ;FLSINS WAS DUE TO PAGE FAULT (MIGHT BE IN .CALL CORBLK) + ANDCAM T,USWST(U) + HRRZ I,U + PUSHJ P,SCHSB + SETOM PREEMP + CONO PI,CLKRQ ;REQUEST INT TO SCHEDULER +];PAGPRE +IFE PAGPRE,[ + SKIPE ENPREE + CAME D,FLSINS(U) + JRST POPIJ + MOVE TT,PRVCUT + CAME U,PRVUSR + CAMLE TT,UPGSEC(U) + SETZM SCHFLG +];PAGPRE +POPIJ: POP P,I + POPJ P, + +IFN E.SP,[ +E.SPGJ: SKIPE E.SPGH ; FLAG FROM E.SPGI + CAME U,DISUSR + JRST QSWI2 ; LEAVE AS IS + TRNN I,400000 + JRST QSWI2 + MOVEI I,3 + JRST QSWI3 ; GO MAKE READ/WRITE + ; DON'T SOS NSWPGS, SINCE PAGE IS ALREADY HERE +];E.SP + +SUBTTL USER SCHEDULER + +OVHMTR SC1 ;SCHEDULER 1 - ENTRY + +IFN KL10P, IFNDEF SCCOST, SCCOST==250. ;CHARGE 1 MILLISEC FOR SCHEDULING +IFN KA10P, IFNDEF SCCOST, SCCOST==1000. ;CHARGE 4 MILLISEC FOR SCHEDULING +IFN KS10P, IFNDEF SCCOST, SCCOST==1000. ;CHARGE 4 MILLISEC FOR SCHEDULING + +SCHED: SKIPGE U,USER + JRST SCHED9 + MOVE T,CLKBRK +IFN KS10P,[ + ;; If user is swapped out while running in the page fail code, then + ;; EPTPFO is used as the PC. Either he is on his way in, in which + ;; case he will come back when restarted, or he is on his way out, + ;; in which case this just pushes him on his way. + TLNE T,%PSUSR + JRST SCHED0 + HRRZ T,T + CAIL T,PFAIL ; First instruction inclusive + CAILE T,PFAILE ; Last instruction inclusive + SKIPA T,CLKBRK + MOVE T,EPTPFO +SCHED0: ] ;IFN KS10P + MOVEM T,UPC(U) +IFN SCHBLN,SETZM SCHMNY ;ENTERED FROM QUANTUM RUNOUT, TIME TO CHECK ALL USERS +SCHED2: ;ENTERED FROM UFLS OR PAGE FAULT, CHECK FOR AUXIL PERSON TO RUN + ;IF SCHMNY IS STILL -1 + AOS NSKED + MOVSI T,UEXIT ;GET HERE FROM CLUFLS + HRRI T,UUO(U) + BLT T,SUEXND-1(U) +IFN KL10P,[ + AC7CTX + XCTR XR,[HRRZ A,13] ;GCSTBR + XCTR XR,[HRL A,14] ;STBR + SYSCTX + MOVEM A,ULSPBR(U) + SKIPL MTRUSR ;SKIP IF PERF COUNTER AVAILABLE + JRST [ DMOVE A,MBOXCT(U) ;COMPUTE EQV CPU TIME FROM MBOX+EBOX ACCT + DSUB A,STMBOX ;AS INCREMENTAL RUNTIME + DMUL A,KLMBCC + DADD B,EBOXCT(U) + DSUB B,STEBOX + DMUL B,KLEBCC + MOVE A,D + JRST SCHD2A ] + RPERFC A + DSUB A,STPERF ;USER RUN TIME IN 80 NS UNITS LEFT 12 + DIVI A,50.*4096. ;CONVERT TO 4 MICROSECOND UNITS IN A +SCHD2A: +] ;KL10P +IFN KS10P, LDB A,[044000,,UPQUAN(U)] ;GET TIME USED IN 3.9 USEC UNITS +IFN KA10P, LDB A,[022100,,UPQUAN(U)] ;GET TIME USED IN 4.069 USEC UNITS + ADDM A,USRTM1 ;SYSTEM TOTAL USER RUN TIME + ADDM A,UTRNTM(U) ;INCREASE RUN TIME + ADDM A,JTMU(U) ;DECREASE PROCEDURE PRIORITY + MOVEI B,SCCOST(A) ;ACCOUNT FOR OVERHEAD IN STARTING UP + ADDM B,@UTMPTR(U) ;DECREASE PROCEDURE TREE PRIORITY +IFE SWPWSP,[ + MOVE T,NMPGS(U) ;USWPRI IS PAGES IN CORE X CPU TIME + SUB T,NSWPGS(U) +];SWPWSP +IFN SWPWSP,[ + HLLO B,UWRKST(U) ;USWPRI IS LOG(WORKING SET SIZE) X (CPU TIME + IO WAIT TIME) + JFFO B,.+1 ;C GETS 19 - LOG(WORKING SET SIZE + 1/2) + MOVEI T,19. + SUB T,C +];SWPWSP + IMUL T,A + MOVE Q,UTMPTR(U) + ADDM T,USWPRI(U) ;CHARGE AGAINST SWAPPINNG PRI + ADDM T,SWRCE-USRRCE(Q) ;AND FOR TREE + MOVE B,A + LSH B,-7 ;GET RUNTIME IN 512 USEC UNITS + CAILE B,777 + MOVEI B,777 ;TO FIT IN SCHEDULER HISTORY TBL + MOVE C,USWST(U) + SKIPE FLSINS(U) + TLNN C,%SWPGW + JRST SCHED8 + TRO B,1000 ;BLOCKAGE DUE TO PAGE FAULT +IFN SWPWSP,[ + CAML A,LODQNT ;CHECK FOR LEAVING LOADING STATE +SCHED8: TLZN C,%SWLOD ;DUE TO RUNNING FOR MORE THAN LODQNT BETWEEN PAGE FAULTS + JRST .+2 ;OR DUE TO BLOCKAGE FOR REASON OTHER THAN A PAGE FAULT + PUSHJ P,LVLOA0 ;LEAVE LOADING STATE +];SWPWSP +.ELSE SCHED8: + DPB B,[311200,,@SCHHP] ;COMPLETE SCHEDULER HISTORY TBL ENTRY + SKIPL Q,RTIMER(U) ;SKIP UNLESS RUNTIME INT ACTIVE + JRST SEARRT +SCHED3: SKIPGE DLSRCH + JRST SEAREP ;DELETE SEARCH, EXIT +IFN PAGPRE,[ + SKIPE PREEMP ;PRE-EMPT? + JRST SCHEDP ;YES, AVOID DOING FULL SCHEDULE +];PAGPRE +IFN SCHBLN,[ + SKIPN SCHMNY ;IF NOT YET TIME TO DO A FULL SCHEDULE, + JRST SEARL0 +SCHED4: HLRZ U,UREALT ;THEN CHECK LIST OF JOBS SCHEDULED BEFORE + JUMPE U,SEARL0 ;ALWAYS SCHEDULE IF HIGH PRIORITY REAL TIME USER ACTIVE + PUSHJ P,SCHGB ;POP NEXT JOB OFF LIST + JUMPL U,SEARL0 ;EMPTY + PUSHJ P,SCHACK + JRST SCHED4 ;JOB CEASED TO BE RUNNABLE + AOS NSSKED ;OK, RUN THIS ONE + JRST SCHED6 +];SCHBLN + +SEARRT: SUB Q,A + MOVEM Q,RTIMER(U) + JUMPGE Q,SCHED3 + MOVSI T,(%PIRUN) ;GIVE RUNTIME INTERRUPT + IORM T,PIRQC(U) + JRST SCHED3 + ; +; HERE TO DO A FULL SCHEDULE (LOOK AT ALL JOBS) +; + +OVHMTR SC2 ;SCHEDULER 2 - SEARCH + +SEARL0: AOS NRSKED ;1 MORE REAL SCHED (ACTUALLY SEARCHES JOBS) + CLEARM TRUMM ;TOTAL RUNNABLE USER MEM + CLEARM AUSOPG ;ACTIVE USER SWAPPED OUT PAGES + CLEARM BUMPGS ;PAGES IN REAL CORE BELONGING TO BLOCKED USERS +IFE SWPWSP, CLEARM ASBUM ;PGS IN REAL MEM OCC BY SWAPPED BLOCKED LOSERS + SKIPN SWPOPB + SKIPE SWPOPR + PUSHJ P,SWPON ;SWAP OUT STUFF +IFN NSWPV,[ + SKIPGE CIRPSW + PUSHJ P,SWPPIN ;SERVICE SWAPPING REQUESTS FROM OTHER PROCESSORS (DISPLAY) +] + SETZB U,J ;JOB BEING SCHEDULED + SETZM RNABLU ;NUM RUNABLE USERS +IFN SCHBLN,[ + SETZM SCHBNJ ;GOT NO RUNNABLE JOBS YET + SETOM SCHMNY ;ALLOW ALL THE RUNNABLES WE FIND TO RUN +];SCHBLN +.ELSE SETOM I ;BEST USER SO FAR + MOVNI T,7 + MOVEM T,SCHFLG ;DONT SCHED AGAIN FOR 1/7.5 SEC + JRST SEARL1 + +;HERE IF NULL JOB HAD BEEN RUNNING + +SCHED9: AOS NNSKED ;1 MORE TIME NULL JOB WAS RUN +IFN KA10P, LDB C,[022100,,UPQUAN] ;GET TIME NULL JOB RAN IN 4.069 USEC UNITS +IFN KS10P, LDB C,[044000,,UPQUAN] ;GET TIME NULL JOB RAN IN 3.9 USEC UNITS +IFN KL10P,[ + CAMN U,MTRJOB ;IF METERING ONLY NULL JOB, STOP METERS NOW + WRPAE PAEOFF + CAMN U,MTRJOB + CONO MTR,4001 ;TIME-BASE OFF, INTERVAL PIA=1 + REBOXC A ;COMPUTE NULL JOB'S EQUIVALENT RUNTIME IN 4 USEC UNITS + DSUB A,NULEBC + RMBOXC C + DSUB C,NULMBC + DMUL C,KLMBCC ;CONVERT MBOX COUNT TO EBOX COUNTER UNITS, + DADD A,D ;ADD TO EBOX COUNT + DMUL A,KLEBCC ;CONVERT TO 4 USEC UNITS. + SKIPGE MTRUSR + JRST [ RPERFC C ;PERFORMANCE METER AVAILABLE, USE IT INSTEAD + DSUB C,NULPRF + DIVI C,50.*4096. ;CONVERT TO 4 MICROSECOND UNITS + JRST .+1 ] +];KL10P + ADDM C,NULTM1 ;ACCUMULATE TOTAL NULL TIME IN 4 USEC UNITS + SKIPE NPGWTU ;IF SOMEONE WOULD HAVE BEEN RUNNING IF THEY + ADDM C,LOSTM1 ; WEREN'T WAITING FOR A PAGE, THIS WAS LOST TIME + SKIPN NPGWTU ;BUT OTHERWISE + ADDM C,IDLTM1 ;IT WAS COMPLETE IDLE TIME + SKIPE NPGWTU ;NOW COMPUTE % TIME IDLE AND LOST + ADDM C,LOSRCE + SKIPN NPGWTU + ADDM C,IDLRCE +IFN PAGPRE,SKIPN PREEMP ;CHECK FOR PRE-EMPT + JRST SEARL0 ;NOW GO DO A FULL SCHEDULE +IFN PAGPRE,[ +SCHEDP: SETZM PREEMP + AOS NPREEL + PUSHJ P,SCHGB ;U GETS USER TO PRE-EMPT THIS ONE (LAST INTO SCHMNY LIST) + JUMPL U,SCHDP1 ;NO ONE TO PRE-EMPT, RUN SAME USER AGAIN + PUSHJ P,SCHACK ;MAKE SURE PRE-EMPTING JOB IS RUNNABLE + JRST SCHEDP ;AFRAID NOT + AOS NPREEM ;OK, RUN THIS ONE + SKIPL I,USER + PUSHJ P,SCHSB ;PRE-EMPTED JOB IS STILL A CANDIDATE FOR RUNNING + JRST SCHED6 + +SCHDP1: SKIPGE U,USER ;TRY TO RUN SAME USER AGAIN + JRST SCHED1 ;RUN NULL JOB AGAIN + PUSHJ P,SCHACK ;MAKE SURE THIS JOB IS STILL RUNNABLE (COULD HAVE UFLSED) + JRST SEARL0 ;FOO, BETTER DO A FULL SCHEDULE + JRST SCHED6 ;OK, RUN THIS GUY +];PAGPRE + +;MAIN SEARCH LOOP, RETURN HERE TO EXAMINE NEXT PROCEDURE +SEARL: MOVEI U,LUBLK ;LENGTH OF USER VAR BLOCK + ADDB U,J ;STEP TO NEXT USER + CAML U,USRHI ;SKIP IF EXISTS + JRST SEAREN ;ALL PROCEDURES HAVE BEEN EXAMINED +SEARL1: SKIPE T,USTP(U) + JRST SEARS1 ;EMPTY OR STOPPED JOB SLOT + SKIPE A,PIRQC(U) + JRST SEAR2A ;FIRST WORD INTERRUPT PENDING +SEARL2: SKIPE B,IFPIR(U) + JRST INTWD2 ;SECOND WORD INTERRUPT PENDING +SEARL3: SKIPN FLSINS(U) + JRST SEARC ;NOT BLOCKED +SEARL4: MOVE T,EPDL2(U) + XCT FLSINS(U) ;TEST BLOCKING CONDITION (MAY SKIP ONCE OR TWICE) + JRST SEARLB ;UNRUNABLE + JRST SEARC ;LOW PRIORITY UNBLOCK + SKIPA Q,[-1] ;HIGH PRIORITY UNBLOCK + MOVEI Q,3 ;EXTRA LOW PRIORITY + JRST SEARC2 + +SEARC: SETZM Q ;SET TO NORMAL PRIORITY + PUSHJ P,UPRIVL ;COMPUTE PRIVELEGE LEVEL (MAY SKIP ONCE OR TWICE) + SOJA Q,SEARC2 ;HIGH-PRIORITY + JRST SEARC2 + SKIPGE APRC(U) + ADDI Q,2 ;DISOWNED JOB IN USER MODE +SEARC2: AOS RNABLU ;ANOTHER RUNABLE USER + MOVE T,TIME + MOVEM T,LUBTM(U) ;RECORD LAST TIME UNBLOCKED +IFE SWPWSP,[ + SKIPGE USWSCD(U) + JRST SEARC7 ;HE'S SWAPPED BLOCKED SO HE DOESNT COUNT +];SWPWSP + JUMPE U,SEARC4 ;DON'T FIGURE SYSTEM JOB. + MOVSI T,%SWDSO + ANDCAM T,USWST(U) ;RUNNABLE SO NOT DESIRED OUT + MOVE T,NMPGS(U) + ADDM T,TRUMM ;TOTAL RUNNABLE USER MEM + MOVE T,NSWPGS(U) + ADDM T,AUSOPG ;TOTAL PAGES OF RUNNABLE USERS SWAPPED OUT +SEARC4: CAMN U,UREALT ;IF THIS IS REAL TIME USER IN HIGH PRIORITY + JRST [ MOVEI A,0 ; PHASE, SCHEDULE WITH INFINITE PRIORITY + JRST SEARP2 ] + SKIPLE T,URTIME(U) ;NON SKIP IF POSSIBLE REAL TIME BLOCK + TLNN T,1 ;SKIP IF REAL TIME BLOCK UNLESS PI IN PROGRESS + JRST SEARC6 + SKIPGE PICLR(U) ;SKIP IF PI IN PROGRESS + JRST SEARL ;REAL TIME BLOCKED +SEARC6: MOVE A,@UTMPTR(U) ;GET AMOUNT OF MACHINE TIME USED RECENTLY BY TREE PROCEDURE IS IN + LSH A,3 ;COMBINE WITH TIME FOR JUST THIS PROCEDURE + ADD A,JTMU(U) ;TO GET PRIORITY FIGURE (SMALLER NUMBER IS HIGHER PRI) + LSH A,(Q) ;ADJUST PRIORITY BY MULTIPLICATIVE FACTOR IN Q +;THE EFFECT OF THIS PRIORITY COMPUTATION IS THAT JOBS IN THE SAME TREE +;ARE COMPARED BY JTMU, WHILE JOBS IN DIFFERENT TREES ARE COMPARED MAINLY +;BY USRRCE, ALTHOUGH A MUCH SMALLER JTMU CAN OVERRIDE A SOMEWHAT LARGER +;USRRCE. THIS IS SOMEWHAT DIFFERENT THAN THE COMPUTATION THAT WAS HERE +;BEFORE MAY 1980, BUT THAT COMPUTATION'S RESULTS EVEN DEPENDED ON THE +;ORDER THAT JOBS HAPPENED TO BE INSPECTED, AND ALLOWED A TREE WITH +;A LARGE NUMBER OF RUNNING JOBS TO GET AN UNFAIR SHARE OF THE MACHINE. +SEARP2: +IFN SCHBLN, PUSHJ P,SCHSJB ;INSERT JOB INTO PRIORITY-SORTED LIST +.ELSE [ JUMPL I,SEARP5 + CAML A,U0P ;SKIP IF IS BETTER THAN BEST SO FAR + JRST SEARL +SEARP5: MOVEM U,I ;I GETS NEW BEST USER SO FAR + MOVEM A,U0P ;U0P GETS PRIORITY OF THAT USER +];SCHBLN + JRST SEARL ;TRY NEXT + +IFE SWPWSP,[ +SEARC7: MOVE T,NMPGS(U) ;RUNNABLE AND SWAPPED BLOCKED + SUB T,NSWPGS(U) + SOSL T + ADDM T,ASBUM + JRST SEARC4 +];SWPWSP + +;JOB IS NOT RUNNABLE +SEARLB: JUMPE U,SEARL ;DON'T FIGURE SYSTEM JOB + MOVE T,USWST(U) +IFE SWPWSP, SKIPL USWSCD(U) ;IF LOCKED OUT, DONT COUNT +IFN SWPWSP, TLNN T,%SWSB + TLNN T,%SWPGW + JRST SEARB1 ;NOT WAITING FOR PAGE + MOVE T,NMPGS(U) ;USER IS WAITING FOR PAGE SO COUNT FOR ACTIVE + ADDM T,TRUMM + MOVE T,NSWPGS(U) + ADDM T,AUSOPG + JRST SEARL + +SEARB1: TLNE T,%SWBEM + JRST SEARL ;HAVE MADE BEST SWAPOUT EFFORT + MOVE T,NMPGS(U) + SUB T,NSWPGS(U) + SOSL T + ADDM T,BUMPGS ;REAL MEM PGS BELONGING TO BLOCKED USERS + JRST SEARL + +SEARS1: SKIPN UNAME(U) + JRST SEARL + MOVE T,USWST(U) ;GUY STOPPED, DOES HE HAVE PAGES IN REAL MEM? + TLNE T,%SWBEM + JRST SEARL ;HAVE TRIED BEST EFFORT TO SWAP OUT + MOVE T,NMPGS(U) + SUB T,NSWPGS(U) + ADDM T,BUMPGS + JRST SEARL + +IFN SCHBLN,[ +;TEST ALL THINGS THAT MAKE A PERSON UNRUNNABLE, OR AT LEAST +;REQUIRE THE ATTENTION OF THE SCHEDULER +;SKIP-RETURN IF JOB IS RUNNABLE, BASHES T, A +SCHACK: CAMGE U,USRHI ;NON-EXISTENT + SKIPE USTP(U) ;STOPPED + POPJ P, + SKIPE T,PIRQC(U) + JRST [ TDNE T,[BADBTS] + JRST SCHACI ;NON-DEFERRABLE + SKIPN PICLR(U) + JRST .+3 ;ALL INTERRUPTS DEFERRED + ANDCM T,IDF1(U) + TDNE T,MSKST(U) + JRST SCHACI + JRST .+1 ] + SKIPE T,IFPIR(U) + JRST [ SKIPN PICLR(U) + JRST .+1 ;ALL INTERRUPTS DEFERRED + ANDCM T,IDF2(U) + TDNE T,MSKST2(U) + JRST SCHACI + JRST .+1 ] + SKIPE FLSINS(U) ;FLUSH INSTRUCTION NOT SATISFIED + JRST [ MOVE T,EPDL2(U) + XCT FLSINS(U) ;IT MAY BE SATISFIED BUT NOT CLEARED YET + POPJ P, ;STILL BLOCKED + JRST .+1 ;CAN SKIP VARIOUS RANDOM NUMBERS OF TIMES + JRST .+1 + JRST .+1 ] +SCHAC1: SKIPLE T,URTIME(U) ;REAL-TIME BLOCKED + TLNN T,1 + SKIPA + SKIPLE PICLR(U) + AOS (P) + POPJ P, + +SCHACI: MOVE T,UPC(U) ;TRYING TO INTERRUPT, NEEDS SCHEDULER + TLNN T,%PCUSR ;ATTENTION UNLESS RUNNING IN EXEC MODE + SKIPE FLSINS(U) ;IN WHICH CASE NEED TO LET IT FINISH + POPJ P, ;SO IT CAN BE PCLSRED + JRST SCHAC1 + +;PUT JOB IN U, PRIORITY IN A, INTO STACK IN PRIORITY ORDER. BASH T,TT,B. +SCHSJB: SKIPG T,SCHBNJ ;FIRST SEARCH FOR SLOT IN WHICH TO INSERT + JRST SCHSJ1 ;BUFFER NOW EMPTY, SKIP SEARCH + MOVE TT,T + CAML A,SCHBPR-1(T) + SOJG T,.-1 ;LOOP TERMINATES WITH T SLOT WHERE IT BELONGS + CAIL TT,SCHBLN + SOJA T,SCHSJ3 ;BUFFER FULL, WORK DIFFERENTLY +SCHSJ0: MOVE B,SCHBTB-1(TT) ;MOVE STUFF UP TO ADD ANOTHER ENTRY + MOVEM B,SCHBTB(TT) + MOVE B,SCHBPR-1(TT) + MOVEM B,SCHBPR(TT) + CAILE TT,1(T) + SOJA TT,SCHSJ0 +SCHSJ1: AOS SCHBNJ +SCHSJ5: MOVEM U,SCHBTB(T) + MOVEM A,SCHBPR(T) + POPJ P, + +SCHSJ3: AOS NSCHOV ;BUFFER NOT BIG ENOUGH FOR ALL RUNNABLE JOBS + JUMPL T,CPOPJ ;THIS JOB IS LOWEST PRIORITY, FORGET IT + JUMPE T,SCHSJ5 ;THIS JOB IS SECOND-LOWEST PRIORITY, FORGET LOWEST + MOVE TT,[SCHBTB+1,,SCHBTB] + BLT TT,SCHBTB-1(T) ;MOVE LOWER PRIORITY JOBS DOWN, FORGET LOWEST + MOVE TT,[SCHBPR+1,,SCHBPR] + BLT TT,SCHBPR-1(T) + JRST SCHSJ5 + +;PUSH JOB IN I ONTO STACK OF RUNNABLE JOBS +SCHSB: AOS T,SCHBNJ + CAILE T,SCHBLN + JRST [ SOS SCHBNJ ;BUFFER OVERFLOW + AOS NSCHOV ;MOVE LOWER PRIORITY JOBS DOWN, FORGET LOWEST + MOVE T,[SCHBTB+1,,SCHBTB] + BLT T,SCHBTB+SCHBLN-2 + MOVEM I,SCHBTB+SCHBLN-1 + POPJ P, ] + MOVEM I,SCHBTB-1(T) + POPJ P, + +;POP STACK OF RUNNABLE JOBS INTO U (RETURNS -1 IF STACK EMPTY) +SCHGB: SOSL U,SCHBNJ + SKIPA U,SCHBTB(U) + SETZM SCHBNJ ;BUFFER EMPTY, U HAS -1 + POPJ P, +];SCHBLN + +.ALSKF==0 +DEFINE ALTSKP A +IFE .ALSKF,[ + DEFINE .ALSKS +A TERMIN +] +IFN .ALSKF,[ + CAME U,.ALSKS + CAMN U,A + POPJ P, +] +.ALSKF==.ALSKF#1 +TERMIN + +;DETERMINES USER PRIVILEGE LEVEL FOR SCHEDULING AND SWAPPING +UPRIVL: SKIPN RPCL(U) ;BEING RPCLSR'ED? + CAMN U,UMASTER ;MASTER? + POPJ P, ;HIGHLY PRIVILEGED + AOS (P) ;SKIP AT LEAST ONCE +IFN 340P\E.SP, ALTSKP DISUSR +IFN VIDP, ALTSKP NVDUSR +IFN TABP, ALTSKP TABUSR +IFN ARMP, ALTSKP ARMUSR +IFN LPTP, ALTSKP LPTUSR +IFG LPTP-1, ALTSKP OLPUSR +IFN PLTP, ALTSKP PLTUSR +IFN .ALSKF,[ + CAMN U,.ALSKS + POPJ P, ;DON'T FIGURE DISOWNED IF USING ABOVE DEVICES +] + MOVE T,UPC(U) + TLNE T,%PCUSR + AOS (P) ;SKIP TWICE + POPJ P, + +OVHMTR SC3 ;SCHEDULER 3 - EXIT + +;SEARCH END (EXIT) +SEAREN: +IFE SWPWSP,[ + SKIPE NUSWB + PUSHJ P,SSWC1 ;SEE IF ENUF CORE TO UNBLOCK A SWAPPED BLOCKED LOSER +];SWPWSP +IFE SCHBLN,[ + SKIPGE U,I ;SKIP IF NON-NULL JOB BEST + JRST SCHED1 + AOS NSCHDU +];SCHBLN +IFN SCHBLN,[ + MOVE T,SCHBNJ + ADDM T,NSCHDU + PUSHJ P,SCHGB ;GET HIGHEST-PRIORITY JOB + JUMPL U,SCHED1 ;NONE, RUN NULL JOB +];SCHBLN +SCHED6: SKIPE FLSINS(U) + JRST SCHED5 +SCHED1: EXCH U,USER + JUMPL U,SCHDN ;JUMP IF SWITCHING FROM NULL JOB + CAMN U,USER ;SKIP UNLESS RUNNING SAME JOB AGAIN + JRST SEAREP ;JUMP ON SAME JOB +IFN KL10P,[ + CAMN U,MTRJOB ;IF LEAVING JOB BEING METERED, STOP METER AND + WRPAE PAEOFF + CAMN U,MTRJOB + CONO MTR,4001 ;TIME-BASE OFF, INTERVAL PIA=1 +] +;SWAP OUT THE OLD JOB'S CONSOLE REGISTER, AND CLEAR ITS BLINKER. +IFN N11TYS,[ + SKIPGE TT11P + SKIPE TEN11F + JRST SSTVR1 ;DONT HACK 11 + SKIPL TVCREG(U) ;DO WE WANT TO SAVE TV CONSOLE REG FOR THIS GUY? + SKIPN T,400000+TTR10*2000 ;0 IS NOT A (VERY) LEGITIMATE CONSOLE REG FCN + JRST SSTVR2 ;SO ASSUME 11 STOPPED, DONT CLOBBER PREV THING + MOVEM T,TVCREG(U) +SSTVR2: SKIPGE T,TVVBN(U) ;DID WE SET RUNNING BLINKER FOR THIS GUY? + JRST SSTVR1 ;NO + MOVEM T,400000+TTR10*2000 ;SET TO VIDEO BUFFER WE SET IT IN + MOVE A,TVBLAD ;ADDR IN VIDEO BUFFER WE FLASHED + CLEARM 400000+TTR0*2000(A) ;CLEAR IT +SSTVR1:] +IFN KA10P,[ + MOVE T,40 + MOVEM T,SV40(U) ;SAVE LAST UUO EXECUTED FOR THIS USER + MOVE T,UPC(U) ;IF USER HAS JUST TRAPPED TO 60, + TLNE T,%PCUSR + JRST SCHDN + ANDI T,-1 + CAIL T,60H0 + CAILE T,60HE + JRST SCHDN + MOVNI T,60H0-UUOH0 + ADDM T,UPC(U) ;THEN MOVE HIM INTO UUOH INSTEAD + MOVE T,60 ;AND MOVE 60H'S VARIABLES INTO UUOH'S VARS + MOVEM T,SV40(U) ;(THAT'S ALL 60H DOES ANYWAY). + MOVE T,60H + MOVEM T,SUUOH(U) +] ;KA10P +;DROPS THROUGH. + ;DROPS IN +;COME HERE TO SET UP A JOB THAT WASN'T ALREADY RUNNING. + +SCHDN: MOVE A,U + SKIPGE U,USER + JRST SCHDN2 ;JUMP IF SWITCHING TO NULL JOB +IFN KA10P,[ + MOVE T,SV40(U) ;LOAD NEW KRUFT + MOVEM T,40 +] ;KA10P +IFN N11TYS,[ + SKIPGE TT11P ;DONT HACK 11 IF ITS DOWN (MOSTLY IN CASE ITS BEING HACKED + ;HARDWARILY + SKIPE TEN11F + JRST SLTVR1 ;DONT HACK 11 + SKIPGE T,TVVBN(U) ;BLINK RUNNING FROB? + JRST SLTVR2 + MOVEM T,400000+TTR10*2000 + MOVE A,TVBLAD + MOVNI T,20 + MOVEM T,400000+TTR0*2000(A) + SKIPA T,TVVBN(U) +SLTVR2: MOVSI T,12_<8+4+16.-18.> ;ALU NOP + SKIPL TVCREG(U) + MOVE T,TVCREG(U) + MOVEM T,400000+TTR10*2000 +SLTVR1:] +IFN KL10P,[ + CAMN U,MTRJOB ;IF THIS JOB'S BEING METERED, TURN ON METER AND TIME BASE. + WRPAE PAEON + CAMN U,MTRJOB + CONO MTR,2001 ;TIME-BASE ON, INTERVAL PIA=1 +];KL10P + SOS NRESKED ;COMPENSATE FOR EXTRA AOS ON NEXT PAGE + +;DROPS THROUGH + ;DROPS IN +;COME HERE TO START UP A JOB EVEN IF IT WAS ALREADY RUNNING BEFORE THIS SCHEDULE. + +SEAREP: AOS NRESKED +IFN KA10P,[ + HRLOI T,1 + ANDCAM T,UPQUAN(U) ;RESET QUANTUM TIMER +] ;KA10P +IFN KL10P,[ + RPERFC STPERF ;SAVE PERF METERS FOR LATER USE + DMOVE A,EBOXCT(U) ;COMPUTING RUN TIME EFFECTIVELY RESETS + DMOVEM A,STEBOX ;QUANTUM TIMER + DMOVE A,MBOXCT(U) + DMOVEM A,STMBOX +] ;KL10P +IFN KS10P, SETZM UPQUAN(U) ;RESET QUANTUM TIMER + PUSHJ P,PGLDU + MOVN A,U + IDIVI A,LUBLK + SKIPE B + BUG +IFE KS10P,[ ; KS has no lights. + MOVSI B,400000 + LSH B,(A) + SKIPN MIPGDS + DATAO LIGHTS,B ;LIGHTS HAVE ONE BIT, SHOWING WHICH JOB IS RUNNING. +] ;IFE KS10P + MOVN B,A ;GET JOB'S NUMBER IN B + MOVE T,UPC(U) ;USER'S PC WORD + MOVEM T,CLKBRK + AOS A,SCHHP ;SET UP SCHEDULER HISTORY TBL + CAIL A,SCHHB+SSCHDB + MOVEI A,SCHHB + MOVEM A,SCHHP + HRRM T,(A) ;STORE PC + TLNN T,%PCUSR + TRO B,400000 + HRLM B,(A) ;STORE USER INDEX AND USER BIT + MOVSI T,UUO(U) + HRRI T,UEXIT + BLT T,UEXND-1 ;BLT IN UEXIT BLOCK +IFN KL10P,[ + MOVE T,ULSPBR(U) + AC7CTX + XCTR XW,[HRRZM T,13] ;GCSTBR + XCTR XW,[HLRZM T,14] ;STBR +] ;KL10P ;CONTEXT WILL BE RESTORED AT CLKB5 BELOW +IFN KA10P, CONO @APRC(U) + +; +; THIS IS THE ONE PLACE WHERE CLOCK LEVEL RETURNS TO THE USER JOB +; +CLKB5: +IFE KA10P, DATAO PAG,@CLCXSV ;RESTORE CONTEXT + MOVE U,USER + MOVSI U,AC0S(U) ;RESTORE AC BLOCK 0 + BLT U,U + JRST 12,@CLKBRK ;RESTORE PC, FLAGS, AND PI + +;HERE WHEN STARTING A USER WHO HAD BEEN FLSING + +SCHED5: MOVE T,USWST(U) +IFN SWPWSP,[ + TLNN T,%SWPGW ;PAGE WAITS DON'T COUNT AS BLOCKING + TLNN T,%SWOUT ;IF SWAPPED-OUT, UNBLOCKING BUMPS SWAP-IN PRIORITY + JRST SCHD5A + MOVE TT,USWPRI(U) ; (A SOMEWHAT QUESTIONABLE FEATURE) + LSH TT,-1 + MOVEM TT,USWPRI(U) +SCHD5A: +];SWPWSP + TLNE T,%SWPCL + JRST SCHED7 ;JUMP IF PAGES SWAPPED OUT WHILE BLOCKED IN EXEC MODE + TLNE T,%SWPGW + SOS NPGWTU ;NOT WAITING FOR A PAGE ANY MORE + MOVSI T,%SWPGW+%SWRUN+%SWINT ;NOT WAITING FOR PAGE,NOT UNBLOCKED SWAPOUT, + ANDCAM T,USWST(U) ;NOT WAITING FOR INTERRUPT PAGE + SETZM FLSINS(U) ;NOT WAITING FOR ANYTHING + JRST SCHED1 + +SCHED7: PUSHJ P,PCLSR ;PAGES WERE SWAPPED OUT WHILE BLOCKED IN EXEC MODE + BUG ;SO PCLSR JOB SINCE IT MIGHT BE COUNTING ON THOSE PAGES + JRST SCHED1 ;PCLSR MUST SUCCEED. JOB WAS BLOCKED WITH EMPTY LSWPR. + + +;COME HERE TO RUN THE NULL JOB. + +SCHDN2: SKIPL A ;WERE RUNNING IT ALREADY? + AOS NNULBK ;NO, INCREMENT # CONSECUTIVE BLOCKS OF NULLTIME. + MOVSI T,(JFCL) + MOVEM T,CLUSAV ;AVOID LOSSAGE AT CLKBRK+1 NEXT CLOCK INT +IFE KA10P, MOVEM T,CLCXSV +IFE KS10P,[ ; KS has no lights. + SKIPN MIPGDS + DATAO LIGHTS,[0] ;LOAD LIGHTS WITH JOB RUNNING (NONE) +] ;IFE KS10P +IFN KA10P,[ + HRLOI T,1 + ANDCAM T,UPQUAN +] ;KA10P +IFN KL10P,[ + CAMN U,MTRJOB + WRPAE PAEON + CAMN U,MTRJOB + CONO MTR,2001 ;TIME-BASE ON, INTERVAL PIA=1 + REBOXC NULEBC + RMBOXC NULMBC + RPERFC NULPRF +] ;KL10P +IFN KS10P, SETZM UPQUAN + CLEARM SCHFLG ;RESCHEDULE ON NEXT CLK INT + LPMR UPGML + JRST 12,@[%PSPCU,,NULJOB] ;DISMISS INT AND GO TO NULL JOB + +NULJOB: MOVSI (JRST 4,) + MOVEI 17,1 ;SET ACS 0 TO 16 TO JRST 4,0 + BLT 17,16 ;TO CATCH SPURIOUS TRANFERS TO ACS + MOVE 17,[AOJA 17] ;RUNS IN ACS TO FREE MEMORY FOR OTHER PROCESSORS + JRST 2,@[%PCUSR,,17] ;RUNS IN USER MODE FOR SAKE OF RANDOMNESS + +IFE SWPWSP,[ +OVHMTR SC4 ;SCHEDULER 4 - UNSWAPBLOCKER + +;SEE IF THERE IS ENOUGH CORE TO UNBLOCK A SWAP-BLOCKED JOB. +SSWC1: SKIPGE U,BUSR + POPJ P, + MOVN T,NSWPGS(U) + ADD T,MEMFR + SUB T,NCBCOM + ADD T,SOLNG + SUB T,SILNG + SUB T,AUSOPG + ADD T,ASBUM + ADD T,BUMPGS + CAIGE T,20 + POPJ P, ;THERE ISN'T ENOUGH ROOM. + MOVSI T,400000 + ANDCAM T,USWSCD(U) ;CLEAR SWAP BLOCKED + SETOM BUSR + MOVE T,[-1_-1] + MOVEM D,BUSIZ ;SIZE OF SMALLEST SWAP-BLOCKED USER. + AOS NTSBUU + SOSN NUSWB + JRST SSWSC3 + MOVEI U,0 + MOVNI R,1 + MOVSI T,200000 +SSWSC4: CAML U,USRHI + JRST SSWSC6 + SKIPGE USWSCD(U) + SKIPN UNAME(U) + JRST SSWSC5 + CAMGE T,NMPGS(U) + JRST SSWSC5 + MOVE R,U + MOVE T,NMPGS(U) +SSWSC5: ADDI U,LUBLK + JRST SSWSC4 + +SSWSC6: MOVEM R,BUSR ;STORE NEW SMALLEST SWAPPED BLOCKED LOSER + SKIPGE R + MOVEI T,0 + MOVEM T,BUSIZ +SSWSC3: JUMPL I,SEARL0 ;MAYBE CAN RUN THIS GUY NOW + POPJ P, +];SWPWSP + +OVHMTR SWU ;SWAP USER + +;SWAP OUT N PAGES (N IS IN SWPOPR) +SWPON: MOVE C,SOLNG + SKIPGE CIRPSW ;CAN'T DO ANYTHING WITHOUT CIRPSW + CAILE C,2*NQS + POPJ P, ;ALREADY STUFF ON WAY OUT + SKIPL U,PSWOUS ;SEE IF CONTINUING TO SWAP OUT A USER + CAML U,USRHI + JRST SWPON1 + MOVE C,PSWCLS + SKIPE LSWPR(U) ;PREFER NOT TO SWAP OUT + JRST SWPON1 ;USER WHO HAS SWITCHES LOCKED + SKIPE UNAME(U) ;SKIP ON USER KILLED + SKIPL USWST(U) .SEE %SWDSO ;OR NOT DESIRED OUT ANY MORE +SWPON1: PUSHJ P,SWPON2 ;FIND NEW USER TO FLUSH + JUMPL U,SWUP8 +SWPON6: MOVSI A,%SWDSO ;THIS USER NOW DESIRED OUT + IORM A,USWST(U) + MOVEM C,PSWCLS + MOVEM U,PSWOUS + MOVE T,UPC(U) + TLNE T,%PCUSR + JRST SWPU1 ;OK TO SWAP USER + SKIPN LSWPR(U) ;PCLSR IF HAS LOCKS, OR AT JBFLS, + SKIPN FLSINS(U) ;OR IF NOT BLOCKED + JRST SWPON8 + MOVSI T,%SWPCL ;OTHERWISE, DON'T PCLSR NOW, BUT + IORM T,USWST(U) ;WHEN IT UNBLOCKS + JRST SWPU1 ;AND START SWAPPING OUT ITS PAGES + +SWPON8: PUSHJ P,PCLSR ;GET OUT OF SYS BEFORE SWAPPING OUT + POPJ P, + JRST SWPU1 + +;FOUND NO USER TO SWAP OUT +SWUP8: SKIPE NLOOSP + JRST SWOL1 ;SWAP OUT SOME LOOSE PAGES + AOSE SBEFLG ;HAVE WE COME HERE TWICE? + JRST SWUP6 ;YES, GIVE UP + MOVSI B,%SWBEM ;NO, TURN OFF EVERYONE'S BEST EFFORT BIT + MOVEI J,2*LUBLK ;AND LOOK AT EVERYONE AGAIN SINCE WE'RE DESPERATE +SWUP9: CAML J,USRHI ;TO FIND A PAGE TO SWAP OUT + JRST SWUP7 + ANDCAM B,USWST(J) + ADDI J,LUBLK + JRST SWUP9 + +SWUP7: PUSHJ P,SWPON2 ;HAVING TURNED OFF %SWBEM, FIND A USER TO SWAP OUT + JUMPG U,SWPON6 ;GO SOMEONE, GO DO +SWUP6: SETZM SWPOPR ;CAN'T FIND ANYONE TO SWAP OUT, GIVE UP + SETOM PSWOUS + POPJ P, + +SWOL1: SKIPN A,FLOOSP ;SWAP OUT SOME LOOSE PAGES + BUG ;NLOOSP WAS TOO HIGH? + MOVNI C,1 + PUSHJ P,SWPOPG + BUG ;CIRPSW, EXEC PAGE COUNT ALREADY CHECKED + SETOM SBEFLG ;WE FOUND A PAGE TO SWAP OUT, NOT DESPERATE + MOVE C,SOLNG + SOSLE SWPOPR ;ENOUGH + CAIL C,20. ;ENOUGH FOR NOW + POPJ P, + SKIPE NLOOSP ;SWAP OUT MORE PAGES + JRST SWOL1 + JRST SWPON + ;START SWAPPING OUT THIS USER'S PAGES +SWPU1: AOS NSOUSR + MOVSI A,%SWRUN + CAILE C,1 ;CLASS + IORM A,USWST(U) ;INDICATE USER WAS RUNNABLE AT TIME OF SWAP OUT +IFE SWPWSP,[ + SETZM SWUPC + SKIPN ENUPC + JRST SWPU1B + MOVE T,UPC(U) ;CALCULATE WHAT PAGE HIS PC IS ON + LDB C,[121000,,UPC(U)] + ROT C,-1 + ADDI C,UPGMP(U) + MOVE A,[222200,,(C)] + SKIPGE C + IBP A + LDB A,A + TRNN A,600000 + SETZM A + ANDI A,PMRCM ;MASK TO REAL CORE ADR BITS + SKIPN USTP(U) ;ONLY IF RUNNING + TLNN T,%PCUSR ;AND IN USR MODE + CAIA + MOVEM A,SWUPC ;THEN DON'T ALLOW UPC PAGE TO BE SWAPPED OUT +SWPU1B: +];SWPWSP + MOVE B,PSWLC + AOSE PSWSFL + JRST SWPU3A ;PICK UP FROM WHERE LEFT OFF +IFE SWPWSP,[ + SKIPE ENPZRO + SETOM SWPP0F +];SWPWSP + MOVEI C,UPGMP(U) ;ADDRESS OF PAGE MAP (START FROM PG 0) + MOVEI J,UPGCP(U) + HRLI C,442200 ;CNVRT TO BYTE PNTR TO MAP + HRLI J,442200 + MOVEM C,SWPMBP + MOVEM J,SWPCBP + LDB B,[121100,,HUSRAD(U)] ;DO ALL PAGES THAT MIGHT EXIST +SWPU2: ILDB D,SWPCBP ;CIRC PNTR ENTRY + ILDB A,SWPMBP ;PAGE MAP ENTRY + AOS NSOPGS + JUMPE D,SWPU3A ;DOESN'T HAVE PAGE +IFE SWPWSP,[ + AOSN SWPP0F + SKIPE USTP(U) ;DON'T SWAP OUT PAGE 0 IF NOT STOPPED + CAIN D,-1 ;PAGE IS ABSOLUTE + JRST SWPU3A + TRNN A,600000 ;NO ACCESS + JRST SWPU3A + SKIPN ENAGE + JRST SWPU2A + TRON A,PMAGEM ;HAS PAGE BEEN REFERENCED? (AGE MASK) + JRST [ DPB A,SWPMBP + AOS NAGEAB + JRST SWPU3A ] +SWPU2A: ANDI A,PMRCM ;MASK TO REAL CORE PAGE # + CAMN A,SWUPC ;DON'T SWAP OUT PAGE WHERE PC IS IF RUNNING + JRST SWPU3A +];SWPWSP +IFN SWPWSP,[ ;I DOUBT THAT MOST OF THAT NONSENSE DOES ANYTHING + TRNE A,600000 ;NO ACCESS + CAIN D,-1 ;OR PAGE IS ABSOLUTE + JRST SWPU3A ;MEANS DON'T SWAP OUT + ANDI A,PMRCM ;MASK TO REAL CORE PAGE # +];SWPWSP + HRRZ D,MMSWP(A) ;NUMBER OF USERS WHO HAVE THIS PAGE MAPPED + SOJN D,SWPU4 ;PAGE IS SHARED +SWPU6: MOVEM B,PSWLC ;SAVE HOW FAR SWAP-OUT SCAN GOT + MOVE C,PSWOUS + PUSHJ P,SWPOPG ;SWAP OUT THIS PAGE + JRST SWPU3 + SETOM SBEFLG ;FOUND A PAGE TO SWAP OUT, NOT DESPERATE + MOVE C,SOLNG + SOSLE SWPOPR ;ENOUGH + CAIL C,20. ;ENOUGH FOR NOW + POPJ P, +SWPU3: MOVE B,PSWLC + MOVE U,PSWOUS +SWPU3A: SOJG B,SWPU2 + SETOM PSWOUS + MOVSI B,%SWBEM + IORM B,USWST(U) ;SET BEST EFFORT BIT +IFN SWPWSP,[ + SKIPL APRC(U) ;IF DISOWNED, + JRST SWPON + MOVE B,USWPRI(U) ;DECREASE PRIORITY TO COME BACK IN + LSH B,2 + MOVEM B,USWPRI(U) +];SWPWSP + JRST SWPON + ;TRYING TO SWAP OUT A SHARED PAGE +SWPU4: MOVEM B,PSWLC ;SAVE HOW FAR SWAP-OUT SCAN GOT + AOSE CIRPSW + BUG ;CIRPSW LOCKED IN SWAP OUT CODE + MOVE C,[2200,,MEMPNT(A)] + MOVEM A,SWOBK + PUSHJ P,UCPRL + 400000,,SWPU5 ;CONSULT THE OTHER USERS OF THE PAGE + SETOM CIRPSW + MOVE A,SWOBK + JRST SWPU6 ;OK TO SWAP IT OUT + +SWPU5: SKIPGE TT,USWST(U) .SEE %SWDSO + POPJ P, ;USER DESIRED OUT, CAN'T HOLD PAGE IN +IFN SWPWSP, TLNN TT,%SWLOD ;IF USER IS LOADING, HOLDS PAGE IN + SKIPN AGERTE + JRST SWPU5A + MOVE TT,I + LSH TT,-1 + ADDI TT,UPGMP(U) + HRLI TT,2200 + TRNN I,1 + HRLI TT,222200 + LDB TT,TT + TRNE TT,600000 ;SKIP IF NO ACCESS, IGNORE AGE + TRNE TT,PMAGEM ;HAS SHE USED THIS PAGE? + POPJ P, ;NO, CAN'T HOLD PAGE IN +SWPU5A: SUB P,[4,,4] + SETOM CIRPSW ;SHARED W/USER WHO IS WANTED IN CORE + AOS NSHRAB ;SO DON'T SWAP IT OUT + JRST SWPU3 + +;COME HERE WITH BEST USER TO SWAP OUT IN U, CLASS IN C +SWPONX: JUMPL U,CPOPJ ;NO SWAP OUTTABLE LOSER +IFN SWPWSP,[ + CAILE C,1 + SKIPN NLOOSP + JRST SWPNX2 + SETO U, ;WOULD RATHER SWAP OUT LOOSE PAGES + POPJ P, + +SWPNX2: MOVSI T,%SWOUT ;MAKE USER SWAPPED OUT + TDNE T,USWST(U) + JRST SWPNX3 ;ALREADY IS? + IORM T,USWST(U) + MOVE T,UWRKST(U) + MOVEM T,USVWRK(U) + MOVE T,TIME + MOVEM T,USWTIM(U) ;DROPS INTO SWPNX3 +];SWPWSP +IFE SWPWSP,[ + CAILE C,1 + SKIPN NLOOSP + SKIPA B,USWST(U) + JRST [ SETO U, ? POPJ P, ] ;WOULD RATHER SWAP OUT LOOSE PAGES + SKIPGE USWSCD(U) + JRST SWPNX3 ;HE'S ALREADY SWAP BLOCKED + TLNN B,%SWPGW ;IS HE RUNNABLE? + SKIPN FLSINS(U) + SKIPE USTP(U) + JRST SWPNX3 + MOVE B,NMPGS(U) ;HE'S RUNNABLE + CAIGE B,TSYSM-SYSB-MEMSY1 + JRST SWPNX1 ;SMALL, NO THRASH + SUB B,NSWPGS(U) + ADD B,MEMFR + SUB B,NCBCOM + ADD B,SOLNG + SUB B,SILNG + SUB B,AUSOPG + JUMPG B,SWPNX3 ;LET THIS GUY THRASH +SWPNX1: SKIPN ENSWBK + JRST SWPNX3 + MOVSI B,(SETZ) ;SWAP BLOCK THIS LOSER + IORM B,USWSCD(U) + AOS NTUSB + AOS NUSWB + MOVE B,NMPGS(U) ;SMALLEST SWAP BLOCKED LOSER? + CAML B,BUSIZ + JRST SWPNX3 + MOVEM U,BUSR ;YES + MOVEM B,BUSIZ ;DROP INTO SWPNX3 +];SWPWSP +;HAVING DECIDED TO SWAP OUT JOB IN U, MAKE SWAP HISTORY TABLE ENTRY +SWPNX3: MOVSI T,2_16. +;GENERAL SWAP HISTORY TABLE KEEPER. ENTER WITH JOB IN U, EVENT IN T, BASHES TT,I,T +SWPKHT: HRLZ TT,U + IDIVI TT,LUBLK ;TT 3.1-3.8 GETS JOB NUMBER, BASHES I + IOR TT,T + HRR TT,TIME +IFN SWPWSP, HLRZ T,UWRKST(U) +IFE SWPWSP,[ + MOVE T,NMPGS(U) + SUB T,NSWPGS(U) +];SWPWSP + SOSL T + DPB T,[321000,,TT] + MOVEM TT,@SWPHTP + AOS T,SWPHTP + MOVE TT,UTRNTM(U) + MOVEM TT,SWPHTL-1(T) + MOVEI TT,SWPHTB + CAIL T,SWPHTB+SWPHTL + MOVEM TT,SWPHTP + POPJ P, + +OVHMTR SWF ;SWAP FIND USER + +;FIND A USER TO SWAP OUT, RETURN IN U, -1 IF NONE +SWPON2: SETOM PSWSFL ;START FROM BEG OF USER +IFE SWPWSP,[ + SKIPL U,PRVUSR + PUSHJ P,CKPRUS ;MAKE SURE PRIV USER EXISTS AND HAS NOT BEEN BLOCKED FOR A LONG TIME +];SWPWSP + MOVNI T,30.*60. + ADD T,TIME ;A MINUTE AGO + MOVNI U,1 + MOVEI J,2*LUBLK + MOVEI C,NSSCDC ;# SWAP OUT CLASSES +SWPON4: CAML J,USRHI ;C HAS INDEX OF MAX CLASS INTERESTED IN + JRST SWPONX ;LOOKED AT ALL USERS, GO PONDER RESULTS + SKIPE UNAME(J) ;SEE IF FOR REAL + SKIPN NMPGS(J) ;DON'T BOTHER IF HAS NO MEMORY + JRST SWPON3 +IFN SWPWSP,[ + MOVE B,USWST(J) + TLNE B,%SWBEM+%SWLOD ;DON'T SWAP OUT IF BEST EFFORT ALREADY MADE, + JRST SWPON3 ; OR STILL LOADING IN + MOVEI I,7 + MOVE TT,USWTIM(J) + CAMLE TT,TIME ;IF PROTECT TIME HASN'T ELAPSED YET, GETS HIGHER PRIORITY + JRST SWPTK ;TO PREVENT THRASHING +];SWPWSP +IFE SWPWSP,[ + MOVE B,USWST(J) + TLNE B,%SWBEM + JRST SWPON3 ;BEST EFFORT ALREADY MADE +];SWPWSP + SKIPE LSWPR(J) + JRST SWPON7 ;PREFER NOT TO SWAP OUT LOSER WITH SWITCHES LOCKED + MOVEI I,1 + TLNE B,%SWPGW + JRST SWPON5 ;FLSINS IS WAITING FOR A PAGE (NOT REALLY BLOCKED) + CAML T,LUBTM(J) + SOJA I,SWPTK ;BLOCKED FOR A LONG TIME (CLASS 0) + SKIPN FLSINS(J) +SWPON5: SKIPE USTP(J) + JRST SWPTK ;CLASS 1 (BLOCKED) +IFE SWPWSP,[ + TLNE B,%SWPRV + JRST [ MOVEI I,7 ;CLASS 7 (PRIV USER) + JRST SWPTK ] +];SWPWSP + JUMPL B,[AOJA I,SWPTK] .SEE %SWDSO ;DESIRED OUT (CLASS 2) + MOVEI I,4 + SKIPGE APRC(J) + SOJA I,SWPTK ;DISOWNED (CLASS 3) +IFE SWPWSP,[ + SKIPGE USWSCD(J) + JRST SWPTK ;SWAP BLOCKED (CLASS 4) +];SWPWSP + SKIPGE TTYTBL(J) + AOJA I,SWPTK ;DOESNT HAVE TTY (CLASS 5) +SWPON7: MOVEI I,6 ;OTHERWISE.... + +SWPTK: CAMGE C,I + JRST SWPON3 ;THIS GUY IN MORE WINNING CLASS +IFE SWPWSP,[ + MOVE A,NMPGS(J) + SUB A,NSWPGS(J) +];SWPWSP +.ELSE MOVE A,UWRKST(J) + CAME C,I + JRST SWPTK2 + XCT SWPTT(C) ;IN SAME CLASS, COMPARE CLASS-DEPENDENT PRIORITY MEASURES + JRST SWPON3 +SWPTK2: MOVE E,@SWPTT(I) ;MAKE THIS GUY BEST VICTIM + MOVE C,I + MOVE U,J +SWPON3: ADDI J,LUBLK + JRST SWPON4 + +;SKIP IF THIS GUY (J) IS BETTER LOSER TO FLUSH THAN PREV BEST (IN E) +SWPTT: CAMG E,LUBTM(J) ;BLOCKED FOR A LONG TIME (0) - LATER LUBTM WINS + CAMG E,LUBTM(J) ;BLOCKED (1) - LATER LUBTM WINS + CAML E,A ;DESIRED OUT (2) - SMALLER WORKING SET WINS + CAML E,A ;DISOWNED (3) - SMALLER WORKING SET WINS + CAML E,A ;RUNNABLE, SWAP BLOCK SET (4) - SMALLER WORKING SET WINS + CAML E,USWPRI(J) ;RUNNABLE, W/O TTY (5) - GO BY PRIORITY + CAML E,USWPRI(J) ;OTHERWISE (6) - GO BY PRIORITY +IFE SWPWSP, BUG ;PRIVELEGED USER (7) - SHOULD ONLY BE ONE +IFN SWPWSP, CAMG E,USWTIM(J);PROTECTED (7) - LATER UNPROTECT TIME WINS +NSSCDC==.-SWPTT + +IFE SWPWSP,[ +CKPRUS: MOVSI B,%SWPRV + CAMGE U,USRHI + ANDCAM B,USWST(U) ;TURN OFF PRIV USER BIT + MOVNI TT,30.*2 + ADD TT,TIME ;TWO SECONDS AGO + SKIPE UNAME(U) + CAML TT,LUBTM(U) + PUSHJ P,NPRVUSR + SKIPG U,PRVUSR + POPJ P, + MOVSI B,%SWPRV + IORM B,USWST(U) + POPJ P, +];SWPWSP + +OVHMTR UUO ;RANDOM UUOS + +;AC: A.9 =>1 SWAP OUT USER +;4.8 => 1 ALL PAGES +;4.7=1 => LOOP FOR A WHILE +;3.9-3.1 USER # SELF IF 0 +;RH => USER VIRTUAL PG # +;OR 4.9=0, 4.8=0, 4.7=0 SWAP OUT RH # OF PAGES +;IF 4.9=0, 4.8=1 AND 4.7=0, HACK PCLSR TEST FEATURE ON CURRENT USER +;RH =0 LEAVE PCLSR TEST MODE =1 ENTER IN ADVANCE MODE =-1 ENTER IN HOLD MODE +; =2 ENTER IN ADVANCE BUT DON'T ^Z + +ASWAP: SKIPN SYSDBG + JRST ILUUO + UMOVE A,(J) + TLNE A,100000 + JRST ASWAP3 + JUMPL A,ASWAP1 + TLNE A,200000 + JRST ASWPCL ;PC LSR TEST MODE. + HRRZM A,SWPOPR ;CLOBBER CLOBBER + POPJ P, + +ASWAP1: HLRZ B,A + ANDI B,777 .SEE MAXJ ;FIELD SHOULD BE BIG ENOUGH + IMULI B,LUBLK + SKIPE B + MOVE U,B + TLNN A,200000 + JRST ASWAP2 + MOVE D,NMPGS(U) + SUB D,NSWPGS(U) + JUMPL D,[JRST 4,.] + JUMPE D,CPOPJ + CONO PI,CLKOFF + MOVEM U,PSWOUS + SETOM PSWSFL + ADDM D,SWPOPR + MOVSI D,%SWDSO + IORM D,USWST(U) + CONO PI,CLKON + POPJ P, + +ASWAP2: PUSHJ P,CWAIT ;RETURNS WITH CLKOFF AND CIRPSW AVAILABLE + SKIPL CIRPSW + HRRZS A ;A HAS VIRTUAL PAGE # + PUSHJ P,UPLC ;RETURN POINTERS IN T AND Q + LDB A,T ;GET MAP ENTRY + LDB C,Q ;GET CIRC PNTR + CAIE C,-1 ;DON'T SWAP OUT ABS PAGE + TRNN A,600000 + POPJ P, ;ALREADY OUT OR DOESN'T HAVE PAGE + ANDI A,PMRCM ;MASK TO REAL CORE PAGE # + MOVNI C,1 + PUSHJ P,SWPOPG + JFCL + JRST CLKONJ + +ASWAP3: MOVE B,[1250000.] + SOJG B,. + UMOVE A,2000 + JRST ASWAP3 + +ASWPCL: MOVEM U,PCLUSR + CLEARM PCLL + CLEARM PCLHSH + SETOM PCLNXT + HRRES A + MOVEM A,PCLDBM + POPJ P, + +;.CALL PGWRIT +; ARG 1 - A +; ARG 2 - PAGE NUMBER IN 'S ADDRESS SPACE +;IF ONLY ONE ARGUMENT IS GIVEN, IT IS ARG 2, AND ARG 1 DEFAULTS TO CURRENT USER + +;THE PAGE IS SWAPPED OUT. THE CALL DOESN'T RETURN UNTIL THE SWAP IS COMPLETED. +; THIS ALLOWS USER TO BE SURE THAT THE COPY ON DISK IS UP TO DATE. +;CONTROL BIT 1.1 => RETURN IMMEDIATELY, NO WAITING. TO WAIT LATER, JUST DO +; ANOTHER PGWRIT WITHOUT SETTING 1.1. +;CONTROL BIT 1.2 => UNLOCK PAGE. IF YOU CALL THIS ON A LOCKED PAGE, +; WITHOUT SETTING BIT 1.2, THE PAGE WILL BE SWAPPED OUT, BUT THE NEXT +; TIME IT IS SWAPPED IN IT WILL BE LOCKED AGAIN. THIS IS USEFUL FOR +; CONTROLLING EXACTLY WHEN A DATA BASE PAGE GETS WRITTEN TO DISK. + +NPGWRT: CAIGE W,2 + JRST [ MOVE J,U ? JRST NPGWR1 ] + MOVE J,A + JSP T,NCORUI ;DECODE THE JOB SPEC + JRST NPGWR0 + JSP T,NCORWR ;WHICH MUST BE WRITABLE + JRST OPNL31 +NPGWR0: +IFN PDP6P,[ + CAIN J,-1 + JRST OPNL34 ;CAN'T HACK PDP6 +];PDP6P + MOVE A,B ;NOTE: SWPOPG TAKES CARE OF THE PCLSR'ING + PUSHJ P,NPGWR1 ;CALL MAIN ROUTINE + POPJ P, ;LOST, OPNL CLEARED LSWPR + JRST LSWPJ1 ;WON, UNLOCK DIELOK + +;USER INDEX IN J, PAGE NUMBER IN A +NPGWR1: TDNE A,[-1,,-400] + JRST OPNL32 ;PAGE NUMBER NOT VALID + PUSHJ P,CWAIT ;DON'T ALLOW PAGE MAPS TO CHANGE, AND TURN CLK OFF + SKIPL CIRPSW ;DON'T NEED UTCOFF BECAUSE UTC LEVEL CAN ONLY PUT PAGES INTO MAPS + EXCH U,J + PUSHJ P,UPLC + EXCH U,J + LDB D,Q ;D GETS CIRC PNTR + JUMPE D,OPNL32 ;NO PAGE THERE + CAIN D,-1 + JRST OPNL12 ;ABSOLUTE PAGE + PUSH P,U + MOVE C,Q ;STARTING FROM UPGCP, FIND MMP + PUSHJ P,UCPRL + 200000,,.+2 + BUG ;IF NONE FOUND + SUB P,[4,,4] ;FOUND MMP, C POINTS TO IT + MOVSI T,MMPTMP ;IF PAGE IS IN TRANSIT + TDNE T,(C) + JRST [ POP P,U + TDNE T,(C) ;AWAIT COMPLETION + PUSHJ P,UFLS + JRST NPGWR1 ] ;THEN TRY AGAIN + MOVE E,C ;SAVE ADDRESS OF MMP ENTRY + PUSHJ P,UCPRL ;SEE IF PAGE IS IN MEMORY + 100000,,NPGWR3 + POP P,U ;NOT SWAPPED IN, BYPASS SWAP-OUT CODE + JRST NPGWR2 + +NPGWR3: SUB P,[4,,4] ;IT'S SWAPPED-IN TO CORE PAGE IN T + POP P,U + HLRZ D,MMSWP(T) + JUMPN D,OPNL12 ;POINTED TO BY AN EXEC PAGE, E.G. 340, SHOULDN'T MESS. + PUSH P,A ;SAVE USER'S VIRTUAL PAGE # + PUSH P,J ;SAVE WHAT JOB THAT IS + PUSH P,E ;SAVE ADDRESS OF MMP ENTRY + MOVE A,T ;PHYSICAL PAGE # TO SWAP OUT + MOVE C,USER ;DON'T PCLSR ME + PUSHJ P,SWPOPL ;SWAP OUT, EVEN IF LOCKED + JRST NPGWR4 ;NO DISK SPACE, OR SOME JOB NOT PCLSRABLE + POP P,E + POP P,J + POP P,A +NPGWR2: MOVE T,CTLBTS(U) + MOVSI D,MMPLOK + TRNE T,2 ;CONTROL BIT 1.2 UNLOCKS + ANDCAM D,(E) + TRNE T,1 ;CONTROL BIT 1.1 INHIBITS WAITING FOR SWAP TO FINISH. + JRST CLKOJ1 + MOVSI T,MMPTMP ;PAGE IN TRANSIT BIT + TDNE T,(E) ;WAIT FOR BIT TO TURN OFF + PUSHJ P,UFLS + JRST CLKOJ1 + +;COULDN'T SWAP OUT, WAIT A WHILE AND TRY AGAIN +NPGWR4: PUSHJ P,UDELAY ;UDELAY TURNS CLKON + POP P,E + POP P,J + POP P,A + JRST NPGWR1 + +EBLK + +;SWAP IN RQ BLOCKS +SWIRQB: +IFN 340P\E.SP, DISSWI: -1 ;USER +IFN VIDP, VIDSWI: -1 +IFN IMXP, POTSWI: -1 +IFN NSWPV-.+SWIRQB,.ERR NSWPV ERR + +SWIVPN: +IFN 340P\E.SP, DISSPG: 0 ;VIRTUAL PAGE NUMBER +IFN VIDP, VIDSPG: 0 +IFN IMXP, POTSPG: 0 + +SWPNTB: ;SIGNAL BITS IN LH OF W TO CFHSW1 +IFN 340P\E.SP, 400000 ;DISPLAY +IFN VIDP, 400000 ;VID +IFN IMXP, 400000 ;POTS + +SWILMT: ;PIRQC BIT TO SET ON ILM +IFN 340P\E.SP, %PIDIS +IFN VIDP, %PIMPV +IFN IMXP, %PIMPV + +PSWOUS: -1 ;INDEX OF PARTIALLY SWAPPED OUT USER +PSWCLS: 0 ;CLASS OF PARTIALLY SWAPPED OUT USER +PSWSFL: 0 ;-1 START FROM BEG OF USER, ELSE PICK UP WHERE LEFT OFF +SWPMBP: 0 ;PNTR TO MAP +SWPCBP: 0 ;PNTR TO CIRC DESC SPACE +PSWLC: 0 ;LOOP COUNT +SBEFLG: -1 ;0 => ALREADY ONCE WANTED TO CLEAR ALL "BEST EFFORT" BITS. +SWPOPR: 0 ;NUMBER OF PAGES DESIRED TO BE SWAPPED OUT +SWPOPB: 0 ;SWAP OUT REQUEST BUT ONLY SWAP OUT NON-RUNNING USERS TO MEET (UNUSED?) +SILNG: 0 ;TOTAL LENGTH OF SWAP IN LISTS +SOLNG: 0 ;TOTAL LENGTH OF SWAP OUT LISTS + ;SINLST AND SOUTLS ARE IN DISK CODE. VARIATION ON QBFP. +SWODSK: NQS-1 ;UNIT TO SWAP OUT ON NEXT +SWOBK: 0 ;MEMBLT BEING SWAPPED OUT +SWOMMP: 0 ;MMP ADDRESS (NOT INDEX) +SPGNMF: 0 ;-1 => PAGE NOT MODIFIED +CFHAS: 0 ;TEMP FOR A AT CFH +SWPIQS: 0 ;SAVE Q AT SWPPIN +CFHUVP: 0 ;USER'S VIRTUAL PAGE NUMBER TOOK FAULT ON +LUMPS: 0 ;UMAPS USED FOR CURRENT USER, MAY DIFFER FROM + ;UMAPS(U) IF TOOK FAULT TRYING TO CAUSE INTERRUPT +TRUMM: 0 ;TOTAL USER MEM ACTIVE USERS +NPGSWO: 0 ;NUMBER OF CURRENTLY SWAPPED OUT PAGES +AUSOPG: 0 ;ACTIVE USER SWAPPED OUT PAGES +BUMPGS: 0 ;REAL CORE PAGES OCC BY BLOCKED + STOPPED LOSERS +NUSWB: 0 ;# LOSERS SWAP BLOCKED +SWPOPU: 0 ;USER PG "BELONGS" TO (IE NOT NECC TO PCLSR THIS GUY, + ;BUT PCLSR ANYONE ELSE LINKED TO PG.) +AGEREQ: 0 ;NUMBER OF PAGES BEING AGED AT SLOW CLOCK +AGEPOS: 0 ;LAST PAGE # AGED + +IFE SWPWSP,[ +PRVUSR: -1 ;PRIV USR +PRVCUT: 1500 ;CUT OFF FOR PRIV USR +SWUPC: 0 ;ABSOLUTE PAGE NUMBER OF USER MODE PC DURNING SWAP OUT +SWPP0F: -1 ;-1 IF CONSIDERING PAGE 0 +ASBUM: 0 ;REAL MEM OCC BY ACTIVE "SWAPPED BLOCKED" LOSERS +SWSCT1: 0 ;TEM AT SWSCD +BUSR: 0 ;INDEX OF SMALLEST SWAP BLOCKED LOSER +BUSIZ: 0 ;SIZE OF BUSR +];SWPWSP + +IFN PAGPRE,[ +PREEMP: 0 ;IF NON-ZERO, A PRE-EMPT IS IN PROGRESS (WHEN WE NEXT GET TO CLK LVL) +NPREEL: 0 ;NUMBER OF LOOPS AT SCHEDP (ATTEMPTED PREEMPTS) +NPREEM: 0 ;NUMBER OF SUCCESSFULL PREEMPTS +NPREE1: 0 ;NUMBER OF TIMES A PAGE CAME IN AND WE STARTED TO THINK ABOUT PREEMPTION +NPREE2: 0 ;NUMBER OF TIMES WE DIDN'T PUNT BECAUSE OF CLKOFF OR IN PROGRESS +NPREE3: 0 ;NUMBER OF TIMES WE DIDN'T PUNT BECAUSE FLSINS WAS WRONG +];PAGPRE + +;COUNTS OF REASONS FOR ENTRY TO SCHED +;THESE METERS MAY BE TEMPORARY - SOME OF THEM ARE REDUNDANT +;REASONS NOT COUNTED - VARIOUS PARITY, NXM, AND OTHER ERROR CASES +NLPPRE: 0 ;NUMBER OF TIMES LOST PROCESSOR DUE TO PREEMPT +NLPCLK: 0 ;NUMBER OF TIMES LOST PROCESSOR DUE TO CLOCK +NLPUFL: 0 ;NUMBER OF TIMES LOST PROCESSOR DUE TO UFLS +NLPPAG: 0 ;NUMBER OF TIMES LOST PROCESSOR DUE TO PAGE-IN +NLPPGT: 0 ;NUMBER OF TIMES LOST PROCESSOR DUE TO PAGE FAULT AND TUT LOCKED +NLPPGC: 0 ;NUMBER OF TIMES LOST PROCESSOR DUE TO PAGE FAULT AND CIRPSW LOCKED +NLPPGM: 0 ;NUMBER OF TIMES LOST PROCESSOR DUE TO PAGE FAULT AND MEMFRZ LOCKED +NLPPG3: 0 ;NUMBER OF TIMES LOST PROCESSOR DUE TO PAGE FAULT AND CALLED CFHPO3 (NO MEM) +NLPPGB: 0 ;NUMBER OF TIMES LOST PROCESSOR DUE TO PAGE FAULT AND SWAP-BLOCKED +NPPIUM: 0 ;NUMBER OF TIMES PAGE PUT INTO BUNCHA USERS' MAPS +NPPIU1: 0 ;NUMBER OF USERS PAGES PUT INTO MAPS OF (RATIO OF THESE 2 IS SHARING) + +IFN SWPWSP,[ +LODQNT: ;RUN TIME IN 4-USEC UNITS BETWEEN PG FAULTS TO LEAVE + ;LOADING STATE + IFN KL10P, 3000. ;12 MS + IFN KA10P, 9000. ;36 MS + IFN KS10P, 3000. .ERR Guessed LODQNT on KS10? +LODFCT: 3,,0 ;MULTIPLY LOADING TIME BY THIS TO GET PROTECT TIME (INT,,FRAC) +NUPTAW: 0 .SEE SWOP6 ;NUMBER OF USERS PAGE TAKEN AWAY FROM + +;METERS + +NPLBLJ: 0 ;NUMBER OF PAGE LOADS BY LOADING JOBS +NPLBNL: 0 ;NUMBER OF PAGE LOADS BY NON-LOADING JOBS + +;Still to be done +; 1-, 5-, 15- minute average population of each state, +; also avg of NPGWTU and RNABLU (for load avg) +; avg of core occupied by jobs in each state, +; i.e. UWRKST for load, pro, sw in. +; Relationship of sum of UWRKST's of loading and swapped in +; versus total core occupied by user pages. +; Average time spent in each state before moving on, +; versus size of job. Maybe cpu time as well as +; real time? + +];SWPWSP +BBLK + + +OVHMTR SWP ;SWAP PAGE + +;SWAP OUT PAGE WHOSE MEMBLT INDEX IS IN A +;SKIP IF SUCCESSFUL +;C IS USER WHO DOESN'T NEED TO BE PCLSRED BEFORE HIS PAGES CAN BE SWAPPED. +SWPOPL: TDZA B,B ;THIS ENTRY IGNORES LOCK BIT +SWPOPG: MOVSI B,MMPLOK ;THIS ENTRY RESPECTS LOCK BIT + MOVEM C,SWPOPU + MOVEM A,SWOBK + CAIGE A,TSYSM + CAIGE A,SYSB + BUG ;DON'T SWAP OUT PART OF SYSTEM + AOSE CIRPSW + POPJ P, + LDB C,[MMMPX,,MEMBLT(A)] + ADDI C,MMP + HRRZM C,SWOMMP ;STORE ADDRESS OF FIRST WORD OF MMP ENTRY + TDNE B,(C) .SEE MMPLOK ;LOCKED IN CORE? + JRST [ CAIGE A,256. ;IF SO, DON'T SWAP OUT UNLESS IN "LOW" MEMORY + CAIGE A,LIOBLK ;IN WHICH CASE MUST GO OUT TO AVOID SYSTEM DEADLOCK + JRST SCRPSJ ;SEE CODE AT CIMEMR + CAIGE A,128. + JRST .+1 + CAIL A,128.+NEXPGS ;SHADOWS OF EXEC PAGES + SKIPN USEMDM + JRST SCRPSJ + JRST .+1 ] + SOS CIRPSW ;RELEASE SWITCH + HLRZ B,1(C) + JUMPN B,SWOP1 ;JUMP IF DISK SPACE ALREADY ASSIGNED +SWODF3: MOVSI B,-NQS +SWODF6: AOS I,SWODSK + CAIL I,NQS + SUBI I,NQS ;WRAP AROUND + MOVEM I,SWODSK ;CURRENT SWAPPING DSK + CONO PI,UTCOFF-1 ;DON'T CHANGE STATE OF CLOCK CHNL. + SKIPGE QTUTO(I) ;TUT LOCKED + JRST SWODF7 + SKIPL QACT(I) + SKIPG QSFTS(I) ;DSK FULL IN SWAPPING AREA + JRST SWODF7 + MOVSI A,(SETZ) + IORM A,QTUTO(I) + CONO PI,UTCON-1 ;DON'T TURN ON CLOCK CHNL. + MOVEI A,NQCHN+1(I) ;QMFTP(A) CONTAINS TRACK TO START FROM + PUSHJ P,QGTK4 ; RETURNS TRACK IN D + SOS QSFTS(I) +SWODF5: MOVSI A,(SETZ) + ANDCAM A,QTUTO(I) + MOVE A,SWOMMP + HRLM D,1(A) ;STORE DISK ADDRESS IN MMP ENTRY + DPB I,[$MMPUN,,(A)] + JRST SWOP1 + +SWODF7: AOBJN B,SWODF6 ;TRY NEXT DSK FOR SWAPPING AREA + CONO PI,UTCON-1 ;NON FOUND FIND FILE SPACE + MOVNI D,1 + MOVNI I,1 + MOVSI E,-NQS +SWODF2: SKIPL QTUTO(E) ;FIND WHICH DISK HAS MOST FREE SPACE + SKIPGE QACT(E) + JRST SWODF4 + CAMGE D,QSFT(E) + HRRZ I,E + CAMGE D,QSFT(E) + MOVE D,QSFT(E) +SWODF4: AOBJN E,SWODF2 + JUMPL I,CPOPJ ;NO DSK SPACE AVAIL + HRRZM I,SWODSK ;LAST DSK HACKED + JUMPLE D,CPOPJ ; NO ROOM ANYWHERE + CONO PI,UTCOFF-1 + SKIPGE QTUTO(I) + JRST UTCNJ ;TUT LOCKED + MOVSI A,(SETZ) + IORM A,QTUTO(I) + CONO PI,UTCON-1 + MOVEI D,NBLKS/2 ;STARTING POINT + MOVEI A,NQCHN+1(I) ;DISK CHANNEL + MOVEM D,QMFTP(A) + PUSHJ P,QGTK4 ;RETURNS TRACK IN D + MOVEI E,NUDSL + MOVEM E,QMFTP(A);DON'T LEAVE SWAPPING CHNL POINTING INTO FILE SPACE + SOS QSFT(I) + JRST SWODF5 + +SCRPSJ: SETOM CIRPSW + POPJ P, + +SWOP1: AOSE CIRPSW + POPJ P, + AOS NPGSO + +;COME HERE FROM SWPOPG AND MMPRTN TO SWAP OUT A PAGE. +;CLOCK OFF OR IN PROGRESS AND ARGUMENTS IN SWOBK AND SWOMMP. +;PUTS BLOCK ON SWAPOUT LIST IF DISK COPY NEEDS TO BE UPDATED, ELSE +;JUST DELETES MEMORY. IF NO USERS ARE USING THE PAGE, +;RETURNS THE MMP ENTRY OR ARRANGES FOR THE DISK ROUTINES TO. + +SWOP1A: CONO PI,UTCOFF-1 ;DON'T CHANGE STATE OF CLOCK CHNL. + MOVE A,SWOBK ;CORE BLOCK # CONTAINING PAGE TO BE SWAPPED OUT + HLRZ C,MMSWP(A) ;NUMBER OF EXEC PAGES POINTING TO THIS PAGE + JUMPN C,SWOP5 ;POINTED TO BY EXEC PAGE, CAN'T SWAP OUT +IFN 340P,[ + MOVSI C,-N340PB-2 +SWOPT2: LDB I,DPEP(C) + TRZN I,600000 + JRST SWOPT1 + ANDI I,PMRCM ;MASK TO REAL CORE PAGE # + CAIN I,(A) + BUG ;DISPLAY STILL SET UP TO PAGE BEING SWAPPED OUT +SWOPT1: AOBJN C,SWOPT2 +] + MOVSI C,MMPPGA + ANDCAM C,@SWOMMP + MOVSI C,(SETZ) + IORM C,MEMBLT(A) ;PREVENT NEW EXEC PAGES FROM BEING SET UP POINTING HERE + CONO PI,UTCON-1 + MOVE C,[2200,,MEMPNT] + ADD C,SWOBK + SETOB B,SPGNMF ;INITIALIZE PAGE NOT MODIFIED FLAG, AND COUNT USERS IN B +IFN SWPWSP,[ + LDB I,C + PUSH P,I + SETZM NUPTAW + MOVSI D,-1 ;COMPUTE WORKING SET CONTRIBUTION TO BE TAKEN AWAY + IDIV D,MMSWP(A) ;LH(MMSWP) KNOWN TO BE ZERO! + PUSHJ P,UCPRL ;CHECK ALL USERS, TAKE PAGE AWAY FROM SOME + 400000,,SWOP6 ;ALSO COUNTS USERS IN B + POP P,I + AOJE B,SWOP7 ;JUMP IF NO USERS USING PAGE, RETURN MMP ENTRY + CAMN B,NUPTAW ;ANY USERS STILL MAPPED TO PAGE? + JRST SWOP8 ;NO, GO SWAP IT OUT + MOVSI D,1 ;YES, COMPUTE WORKING SET ADJUSTMENT + IDIV D,MMSWP(A) ;TO BE ADDED BACK IN TO THEM + PUSHJ P,UCPRL ;GO BACK AND FIX WORKING SETS + 400000,,SWOP6B + JRST SWOP6E ;ABORT SWAP OUT +];SWPWSP +IFE SWPWSP,[ + LDB I,C + PUSH P,I ;NOTE: CAN BACK OUT OF THIS PUSH AT SWOP2B + PUSHJ P,UCPRL + 400000,,SWOP2 ;RETURN ON USERS (CAN BACK OUT AT SWOP2B) + POP P,I + JUMPGE B,SWOP8 +];SWPWSP +SWOP7: MOVSI B,MMPGON ;NO USERS USING PAGE, SO MMP ENTRY WILL BE RETURNED + IORM B,@SWOMMP ;FLAG THAT MMP ENTRY WILL SOON GO AWAY + MOVEI A,0 ;REMOVE FROM LOOSE PAGE LIST + MOVE T,FLOOSP +SWOP7A: MOVE B,A ;B PREDECESSOR + SKIPN A,T ;T SUCCESSOR + BUG ;NOT IN LIST? + LDB T,[MLO,,MEMBLT(A)] + CAME A,SWOBK + JRST SWOP7A + SKIPE B ;FOUND, PATCH OUT OF LIST + DPB T,[MLO,,MEMBLT(B)] + SKIPN B + MOVEM T,FLOOSP + SKIPN T + MOVEM B,LLOOSP + SOSL NLOOSP + JRST SWOP8 + BUG ;NLOOSP TOO LOW. + +IFN SWPWSP,[ + +;THIS UCPRL ROUTINE SCANS ALL USERS, COUNTS THEM IN B, +;USES D TO ADJUST WORKING SETS OF USERS WHICH ARE MAPPED TO +;THE PAGE, AND TAKES THE PAGE AWAY FROM ANY USERS IT CAN, +;COUNTING THEM IN NUPTAW. +SWOP6: AOS B ;COUNT USERS OF THIS PAGE + CAIG U,LUBLK + BUG ;SYS JOB OR CORE JOB? + PUSH P,I + MOVEI C,UPGMP(U) ;MAKE C POINT TO UPGMP ENTRY (PTW) + ROT I,-1 + ADDI C,(I) + HRLI C,222200 + SKIPGE I + HRLI C,2200 + LDB I,C + SKIPN I + BUG ;NO ACCESS? + TRNE I,600000 + ADDM D,UWRKST(U) ;IS MAPPED TO PAGE, ADJUST WORKING SET + CAMN U,SWPOPU + JRST SWOP6A ;DON'T CONSIDER PCLSRING SWPOPU + MOVE T,UPC(U) + TLNE T,%PCUSR + JRST SWOP6A + SKIPN LSWPR(U) ;PCLSR IF HAS SWITCHES LOCKED + SKIPN FLSINS(U) + JRST SWOP6D + MOVSI T,%SWPCL ;DONT PCLSR NOW, BUT WHEN UNBLOCKS + IORM T,USWST(U) + JRST SWOP6A + +SWOP6D: PUSH P,D + PUSH P,C + PUSH P,I + PUSHJ P,PCLSR ;BETTER NOT CLOBBER U OR H OR A + JRST [ SUB P,[2,,2] + POP P,D + JRST SWOP6C ] + POP P,I + POP P,C + POP P,D +;WHEN WE GET HERE, THIS JOB CAN'T HOLD THIS PAGE IN +SWOP6A: TRNN I,600000 + JRST SWOP6C ;NOT SET UP SINCE PREV SWAPPED OUT + AOS NUPTAW ;TAKE IT AWAY + LSH I,-16. ;SAVE ACCESS MODE IN LOW ADR BITS + CAILE I,2 ;SKIP ON READ ONLY OR READ/WRITE/FIRST + CLEARM SPGNMF ;PAGE HAS BEEN MODIFIED + CAIN I,2 ;FLUSH R.W.F. + MOVEI I,3 + DPB I,C ;STORE PROTECTION BITS BACK IN LOWER TWO BITS OF ENTRY + AOS NSWPGS(U) ;INCR COUNT OF SWAPPED OUT PGS OF USER + AOS SNSWPG ;INCR CNT OF SWAPPED OUT FOR SYS + SOS MMSWP(A) ;DECR COUNT OF PAGE SHARERS +IFN E.SP,[ + CAMN U,DISUSR ;IF USER OF E&S + PUSHJ P,E.SLPM ;LOAD ITS MAP +] +SWOP6C: POP P,I + POPJ P, + +SWOP6F: CAMN U,-4(P) ;DON'T LOOK AT USER TAKING PAGE AWAY FROM + POPJ P, ;ELSE DROP INTO SWOP6B +;THIS UCPRL ROUTINE ADJUSTS WORKING SETS OF JOBS THAT +;ARE MAPPED TO THE PAGE USING D. +SWOP6B: PUSH P,I + MOVEI C,UPGMP(U) ;MAKE C POINT TO UPGMP ENTRY (PTW) + ROT I,-1 + ADDI C,(I) + HRLI C,222200 + SKIPGE I + HRLI C,2200 + LDB I,C + SKIPN I + BUG ;NO ACCESS? + TRNE I,600000 + ADDM D,UWRKST(U) ;IS MAPPED TO PAGE, ADJUST WORKING SET + POP P,I + POPJ P, +];SWPWSP + +IFE SWPWSP,[ +;COME HERE VIA UCPRL FOR ALL USERS OF PAGE BEING SWAPPED OUT + +SWOP2: AOS B ;COUNT USERS OF THIS PAGE + CAIG U,LUBLK + BUG ;SYS JOB OR CORE JOB? + PUSH P,I + CAMN U,SWPOPU + JRST SWOP2A + MOVE T,UPC(U) + TLNE T,%PCUSR + JRST SWOP2A + SKIPN LSWPR(U) ;PCLSR IF HAS SWITCHES LOCKED + SKIPN FLSINS(U) + JRST SWOP2D + MOVSI T,%SWPCL ;DONT PCLSR NOW, BUT WHEN UNBLOCKS + IORM T,USWST(U) + JRST SWOP2A + +SWOP2D: PUSHJ P,PCLSR + JRST SWOP2B +SWOP2A: MOVEI C,UPGMP(U) + ROT I,-1 + ADDI C,(I) + HRLI C,222200 + SKIPGE I + HRLI C,2200 + LDB I,C + SKIPN I + BUG ;NO ACCESS? + TRNN I,600000 + JRST SWOP2C ;NOT SET UP SINCE PREV SWAPPED OUT + LSH I,-16. ;SAVE ACCESS MODE IN LOW ADR BITS + CAILE I,2 ;SKIP ON READ ONLY OR READ/WRITE/FIRST + CLEARM SPGNMF ;PAGE HAS BEEN MODIFIED + CAIN I,2 ;FLUSH R.W.F. + MOVEI I,3 + DPB I,C ;STORE PROTECTION BITS BACK IN LOWER TWO BITS OF ENTRY + AOS NSWPGS(U) ;INCR COUNT OF SWAPPED OUT PGS OF USER + AOS SNSWPG ;INCR CNT OF SWAPPED OUT FOR SYS + MOVE I,SWOBK + SOS MMSWP(I) ;KEEP ACCURATE COUNT OF UPGMP'S POINTING AT THIS PAGE +IFN E.SP,[ + CAMN U,DISUSR ;IF USER OF E&S + PUSHJ P,E.SLPM ;LOAD ITS MAP +] +SWOP2C: POP P,I + POPJ P, + +SWOP2B: SUB P,[6,,6] ;2 PUSHES OF I AND 4 FOR UCPRL +];SWPWSP +SWOP6E: MOVE A,SWOBK ;ABORT SWAP-OUT + MOVSI I,(SETZ) + ANDCAM I,MEMBLT(A) + SOS CIRPSW + POPJ P, + +SWOP8: DPB I,C ;DELINK MEMPNT + MOVEI I,3 .SEE MMPOUT .SEE MMPTMP + DPB I,[410200,,@SWOMMP] ;INDICATE ON THE WAY OUT + MOVSI I,MMPBAD + ANDCAM I,@SWOMMP + MOVE A,SWOBK + MOVSI B,(SETZ) + CONO PI,UTCOFF-1 + ANDCAM B,MEMBLT(A) + MOVE C,@SWOMMP + TLNN C,MMPGON ;UNLESS PAGE WILL BE FORGOTTEN AFTER SWAP OUT, + AOS NPGSWO ; KEEP COUNT OF PAGES CURRENTLY SWAPPED OUT + TLNE C,MMPWRT ;IF WAS WRITTEN BY USER WHO LATER DELETED IT, + JRST SWOP3 + SKIPGE SPGNMF ;OR IF PAGE MODIFIED, + TLNN C,MMPWOD + JRST SWOP3 ;OR IF HASN'T BEEN WRITTEN TO DISK, MUST WRITE OUT. + MOVEI I,2 ;NO NEED TO WRITE OUT. INDICATE OUT. + DPB I,[410200,,@SWOMMP] + PUSHJ P,IMEMR ;RETURN THE MEMORY + MOVE A,SWOMMP + TLNE C,MMPGON + PUSHJ P,RETMMP ;ALSO RETURN THE MMP ENTRY IF NECESSARY + JRST SWOP4 + +SWOP5: SOS CIRPSW +UTCNJ: CONO PI,UTCON-1 ;DON'T TURN ON CLOCK CHNL + POPJ P, + +SWOP3: CAIGE A,TSYSM ;HAVE TO WRITE THIS PAGE OUT + CAIGE A,SYSB + BUG + HRRZ B,SWOMMP + LDB I,[$MMPUN,,(B)] + CAIL I,NQS + BUG ;DISK NUMBER NOT LEGITIMATE + MOVEI C,.BM MLO + ANDCAM C,MEMBLT(A) ;SET END OF LIST IN THIS BLOCK + HLRZ C,SOUTLS(I) ;GET PREV BLOCK + SKIPE C + DPB A,[MLO,,MEMBLT(C)] ;CHAIN TO PREV BLOCK + SKIPN C + MOVEM A,SOUTLS(I) ;OR TO HEADER IF FIRST + HRLM A,SOUTLS(I) ;AND SET NEW LAST BLOCK + AOS SOLNG + HLRZ C,1(B) + HRLM C,MEMPNT(A) ;STORE DISK ADDRESS + MOVEI B,MUSWPG + DPB B,[MUR,,MEMBLT(A)] + PUSHJ P,QSTRT1 +SWOP4: SOS CIRPSW +UTCNJ1: CONO PI,UTCON-1 + JRST POPJ1 + +IFN NSWPV,[ +SWPPIN: MOVSI Q,-NSWPV ;# OF DEVICES THAT CAN SWAP IN PAGES +SWPPI4: SKIPGE W,SWIRQB(Q) ;USER INDEX + JRST SWPPI6 + MOVE E,SWIVPN(Q) ;VIRTUAL PAGE NUMBER + HRL W,SWPNTB(Q) + CLEARB TT,D + MOVEM Q,SWPIQS + PUSHJ P,CFHSW1 + MOVE Q,SWPIQS + SETOM SWIRQB(Q) +SWPPI6: AOBJN Q,SWPPI4 + POPJ P, +] + +SWIILM: +IFN E.SP,[ + TRNN Q,-1 ; IS DEVICE DIS? (E&S IS INDEX 0 IN SWIRQB) + SETZM E.SPGW ; IF SO, CLEAR PAGE WAIT. +] + SKIPGE E,SWILMT(Q) + BUG + IORM E,PIRQC(W) + MOVEI A,0 + POPJ P, + +SUBTTL LOAD USER PAGE MAP + +OVHMTR UUO ;RANDOM UUOS (WELL, SOME MINOR SCHED STUFF, TOO) + +;SET PAGE MAP AT M.P. LEVEL, ASSUMING UMAPS HAS BEEN ALTERED. +;UMAPS EXISTS SO SCHEDULER CAN RESTORE THE MAP AFTER OTHER JOBS RUN. +;FORMAT OF A MAP SPECIFICATION IS: +%UM==1,,525252 +%UMMPL==200000 ;1 => MAP LOWER HALF TO SPEC'D JOB'S; 0 => USE LOWER OF JOB IN U. +%UMMPU==100000 ;1 => MAP UPPER HALF TO SPEC'D JOB'S; 0 => USE UPPER OF JOB IN U. +%UMALL==300000 ;SET => SELECT WHOLE MAP OF SPEC'D JOB. +%UMUTL==40000 ;IGNORED IF %UMMPU=0. IF %UMMPU=1, MEANS USE SPEC'D JOB'S LOWER + ;INSTEAD OF ITS UPPER, AS OUR UPPER HALF. READ "%UM UPPER-TO-LOWER". +%UMLTU==20000 ;"%UM-LOWER-TO-UPPER". WITH %UMMPL, MAKES LOWER -> SPEC'D JOB'S UPPER. +%UMSOA==4000 ;1 => USE AC0S AS THE USER'S ACS, INSTEAD OF UUOACS. + ;NOTE IF %UMLTU=1, OR IF LOWER -> PDP6, THE GARBAGS ACS ARE USED. + ;ELSE, THE ACS COME FROM THE JOB WHICH OUR LOWER HALF COMES FROM. +;RH ;JOB INDEX OF THE "SPECIFIED JOB". -1 => PDP6. + ;NOT NEEDED IF %UMMPL=%UMMPU=0. + +PGLDU: MOVE R,UMAPS(U) +;SET PAGE MAP AT INT. LEVEL, NOT CLOBBERING JOB'S UMAPS. ARG IN R. +PGLD: MOVEM R,LUMPS ;LAST UMAPS ACTUALLY USED + AOS NPGLD ;COUNT # CALLS TO PGLD + PUSH P,A ;R HAS UMAPS CODE + PUSH P,B + PUSH P,C + HRRZ C,U +IFN KA10P, MOVSI B,NUVPG/2 ;SET UP NORMAL DBL, MIGHT BE CHANGED IF PDP6 +IFE KA10P, MOVSI B,0 ;ONLY KA10 HAS DBL + TLNN R,%UMMPL + JRST PGLD3A ;USE NORMAL LOW SEG +IFN PDP6P,[ + TRNE R,400000 + JRST PGLD3B ;USE PNTR TO PDP6 +] + HRRZ C,R + TLNE R,%UMLTU ;SKIP ON USE HIS LOWER + JRST PGLD3D ;USE HIS UPPER +PGLD3A: HRRI B,UDBR1A(C) + TLNE R,%UMSOA + JRST PGLD3G ;MAKE AC'S POINT AT SWAP OUT AC'S + MOVEI A,UUOACS(C) +PGLD3F: MOVEM B,UPDBR1(U) +IFN KA10P, DPB A,[2300,,UPACP(U)] ;STORE AC PNTR +IFE KA10P,[ + CAMN A,AC1PTR ;IF CHANGING AC BLOCK 1 + JRST PGLD3H + EXCH A,AC1PTR ;STORE OLD BLOCK 1 + MOVE B,A + XCTR XBR,[BLT B,17(A)] + MOVS A,AC1PTR ;AND LOAD NEW BLOCK 1 + XCTR XBW,[BLT A,17] +PGLD3H: ] ;IFE KA10P +IFN KA10P, MOVSI B,NUVPG/2 ;SET UP DBL FOR DBR2 +IFE KA10P, MOVSI B,0 + HRRI B,UDBR2A(U) + TLNN R,%UMMPU + JRST PGLD6 ;USE NORMAL UPPER SEG + HRRI B,UDBR2A(R) + TLNE R,%UMUTL + HRRI B,UDBR1A(R) +IFN PDP6P,[ + TRNE R,400000 + MOVE B,PDP6MP +] +PGLD6: MOVEM B,UPDBR2(U) +PGLDR1: LPMR UPGML(U) + POP P,C + POP P,B + POP P,A + POPJ P, + +IFN PDP6P, PGLD3B: SKIPA B,PDP6MP +PGLD3D: HRRI B,UDBR2A(R) + MOVEI A,GACS + JRST PGLD3F + +PGLD3G: MOVEI A,AC0S(C) + JRST PGLD3F + +GACS: BLOCK 20 ;GARBAGE AC'S POINTED TO BY ACPNTR WHEN ITS REALLY POINTING + ;AT UPPER PAGES OR PDP6 SHOULD HOPEFULLY NEVER GET REFERENCED + +;MAIN PROGRAM MAP-SETTING ROUTINES. +IFN PDP6P,[ +MP6LD: SKIPA J,[%UMMPU,,-1] ;LOAD UPPER DBR TO PNT TO 6 +];PDP6P +MPLDZ: MOVEI J,0 ;SET NORMAL MAP - OUR OWN CORE. +MPLD1: CAMN J,UMAPS(U) ;SET UMAPS AS SPEC'D + JRST CLKONJ + MOVEM J,UMAPS(U) +MPLD: CONO PI,CLKOFF + PUSHJ P,PLD + JRST CLKONJ + +;SET MAP TO JOB # IN J; MIGHT OR MIGHT NOT BE THE CURRENT JOB. SAVES RH(J) +MPLDJ: CAME J,USER + TLOA J,%UMSOA+%UMALL ;OTHER JOB'S ACS ARE IN ITS AC0S. + TLO J,%UMALL ;THIS JOB => WANT UUOACS. + JRST MPLD1 + +;SIMILAR ROUTINES, BUT FOR USE WHEN CLKCHN IS OFF AND SHOULD STAY OFF. +IFN PDP6P,[ +PLD6: SKIPA J,[%UMMPU,,-1] ;MAKE UPPER DBR POINT TO PDP6. +];PDP6P +PLDZ: MOVEI J,0 ;NORMAL MAP +PLD1: MOVEM J,UMAPS(U) +PLD: SPM UPGML(U) ;IF ANY INHIBITED FAULT PRESENT, CAUSE IT TO GET STORED AWAY + PUSH P,R + PUSHJ P,PGLDU ;CAUSE ACTUAL PG LOAD TO HAPPEN + POP P,R + POPJ P, + +SUBTTL GIVING THE USER INTERRUPTS + +SEAR2E: MOVE A,PIRQC(U) + +;ROUTINE TO HANDLE FIRST WORD (PIRQC) INTS +SEAR2A: JUMPL A,SEAR2B ;REQUEST TO PCLSR + SKIPN PICLR(U) + JRST SEAR2C ;PI IN PROG, ONLY LOOK FOR FATAL INTS. + SETCM Q,IDF1(U) + AND Q,MSKST(U) ;ENABLED UNDEFERRED INTS. + TDNN A,Q ;ANY OF THOSE PENDING, + TDNE A,[BADBTS] ;OR ANY CLASS 1 OR 2 => INTERRUPT. + CAIA + JRST SEARL2 + ANDCA Q,A ;GET DISABLED OR DEFERRED PENDING INTS. + TDNN Q,[BADBTS] ;ANY CLASS 1 OR 2 DISABLED OR DEFERRED + JRST INTWD1 ;NO, INT. THIS JOB. + JRST SEAR2D ;YES, INT. SUPERIOR. + +SEAR2C: TDNN A,[BADBTS] ;PI IN PROG: ANY CLASS 1 OR 2 ? + JRST SEARL2 ;NO, NOTHING TO DO. +SEAR2D: PUSHJ P,PCLSR ;INT. THE SUPERIOR: PCLSR FIRST. + JRST SEARC ;CAN'T STOP THIS JOB IN EXEC MODE. + SETZ B, ;OK, HANDLE FATAL 1ST WORD INTS IN A, AND NO 2ND WORD INTS. + +;HANDLE A FATAL INTERRUPT BY INTERRUPTING THE SUPERIOR. +;FATAL 1ST WORD INTERRUPTS IN A, FATAL 2ND WORD INTS IN B. +INTSUP: MOVEM A,SRN4(U) ;.FTL1 + MOVEM B,SRN5(U) ;.FTL2 ;PUT THE FATAL INTERRUPTS WHERE SUPERIOR CAN READ THEM. + MOVSI T,BUSRC + IORM T,USTP(U) ;STOP INFERIOR +IFN SWPWSP, PUSHJ P,LVLOAD + MOVSI T,BULGOS ;IF LOST TRYING TO LOG OUT, ABORT LOGOUT + ANDCAM T,APRC(U) + MOVE Q,U ;SAVE USER INTERRUPTING + SKIPGE U,SUPPRO(U) ;SKIP UNLESS TOP LEVEL + JRST INTTOP ;REALLY TOP LEVEL + HLLZ T,U ;GET INT BIT + IORM T,IFPIR(U) ;TURN ON INTERRUPT BIT IN SUPERIOR + HRRZS U ;CLEAR LEFT HALF OF U + CAIL J,(U) ;SKIP IF SUPERIOR HAS NOT YET BEEN SCHEDULED + JRST SEARL1 ;RESCHEDULE SUPERIOR + JRST SEARL ;HAVEN'T GOT TO HIM YET SO CONTINUE + +INTTOP: MOVEI T,SCRDET + SKIPL APRC(Q) ;IF JOB ISN'T ALREADY DISOWNED + IORM T,SUPCOR ;SAY SOMEONE WANTS TO BE DETACHED. + JRST SEARL ;LEAVE STOPPED, SYS JOB WILL DETACH SOMEDAY. + +SEAR2B: PUSHJ P,PCLSR ;PCLSR THE JOB, E.G. SO IT CAN GET AN IOC ERROR + JRST SEARC ;RUNNING IN EXEC MODE, GO RUN IT + MOVSI A,(SETZ) ;CLEAR REQUEST + ANDCAM A,PIRQC(U) + JRST SEARL1 ;INSPECT THIS JOB AGAIN + +;IFPIR IS NONZERO BUT PIRQC IS ZERO. +INTWD2: SKIPN PICLR(U) + JRST SEARL3 ;IGNORE 2ND WD INTS IF PI IN PROG. + AND B,MSKST2(U) + ANDCM B,IDF2(U) ;GET ENABLED UNDEFERRED INTS. + JUMPE B,SEARL3 ;ALL DISABLED OR DEFERRED. + JSP T,INTPAG ;MAKE SURE NOT WAITING FOR PAGE NEEDED FOR INT. + PUSHJ P,PCLSR ;DON'T INT. EXCEPT IN USER MODE. + JRST SEARC + SETZ A, ;1ST WD INTS TO GIVE = 0. + JRST INTSRC ;2ND WD INTS TO GIVE ALREADY IN B. + +;PIRQC WAS NONZERO BUT NO FATAL INTS. +INTWD1: JSP T,INTPAG ;IF TRIED BEFORE & WENT TO INTPFL, WAIT FOR PAGE. + PUSHJ P,PCLSR ;CAN INT. ONLY IN USER MODE. + JRST SEARC + MOVE B,IFPIR(U) + AND B,MSKST2(U) ;GET PENDING ENABLED UNDEFERRED 2ND WD INTS IN B. + ANDCM B,IDF2(U) + AND A,MSKST(U) + ANDCM A,IDF1(U) ;PENDING ENABLED UNDEFERRED 1ST WD INTS IN A. +INTSRC: AOS NAUINT ;ELSE 1 MORE ATTEMPT TO INTERRUPT. + MOVSI R,%UMSOA ;LOAD ORDINARY MAP FOR THIS USER. + PUSHJ P,PGLD ;BUT ACS -> SWAP OUT ACS. + HRRZ T,40ADDR(U) ;GET ADDR OF USER'S LOCATION "40" + XCTRI XR,[MOVE T,2(T)] ;TRY TO GET CONTENTS OF "42" (..I SO STOP ON EXEC PG FAULT DOESNT) + SKIPA R,T + JRST INTPFL ;PAGE FAULT IN XCTR, GIVE UP & WAIT FOR PAGE. + ANDI R,-1 + JUMPE R,INTBAD ;42 POINTS TO 0 => BADPI ERROR. + MOVE TT,OPTION(U) + TLNN TT,%OPINT ;NEW STYLE INTERRUPTS? + JRST INTOLD ;NO, OLD STYLE. + XCTRI XR,[MOVE R,(R)] ;GET ADDR OF HIS INT PDL PTR. + CAIA + JRST INTPFL + JUMPGE T,INTBAD + CAMGE T,[-72.*5-1,,] + JRST INTBAD + XCTRI XR,[MOVE H,(R)] ;GET CONTENTS OF INT PDL PTR. + JRST INTSR2 ;ADVANCE T PAST INT PDL PTR ADDR. + JRST INTPFL + +INTSR0: XCTRI XR,[MOVE C,(T)] ;GET THE INTS NEXT INT TABLE ENTRY + SKIPA D,B + JRST INTPFL ;APPLIES TO. + XCTRI XR,[AND D,1(T)] + CAIA + JRST INTPFL + AND C,A ;WHICH OF THEM ARE WE TRYING TO GIVE? + JUMPN C,.+2 + JUMPE D,INTSR1 ;NOT GIVING ANY OF THEM, TRY NEXT ENTRY. + MOVE Q,IDF1(U) ;GET CURRENT SETTINGS OF DEFER WORDS. + XCTRI XW,[MOVEM Q,3(H)] + SKIPA Q,IDF2(U) ;AND PUT INTO NEXT INT PDL FRAME. + JRST INTPFL + XCTRI XW,[MOVEM Q,4(H)] + SKIPA Q,UPC(U) ;ALSO PUT CURRENT PC IN FRAME. + JRST INTPFL + XCTRI XW,[MOVEM Q,5(H)] + CAIA + JRST INTPFL + XCTRI XR,[MOVE E,2(T)] ;NOW SEE WHICH DEFER BITS TO TURN ON NOW. + CAIA + JRST INTPFL + XCTRI XR,[MOVE TT,3(T)] + CAIA + JRST INTPFL + XCTRI XR,[MOVE Q,4(T)] ;AND THE NEW PC. + TLOA Q,%PCUSR + JRST INTPFL + TLZ Q,BADPC + SKIPGE IOTLSR(U) + TLO Q,%PCUIO ;DON'T CHANGE HIS IOTLSR STATUS. + XCTRI XW,[MOVEM C,1(H)] + CAIA ;PUT INTS BEING GIVEN IN + JRST INTPFL ;INT. PDL FRAME. + XCTRI XW,[MOVEM D,2(H)] + TDZA B,D + JRST INTPFL + MOVE W,H ;REMEMBER PDL PTR BEFORE INCREMENT, FOR PDL OV TESTING + ADD H,[5,,5] + LDB J,[220500,,R] ;HOW MANY ACS SHOULD WE SAVE? + JUMPE J,INTSR5 ;NONE? + HRLS J + ADD H,J ;ADVANCE THE PDL PTR OVER WHERE THEY'LL GO. + SUBM H,J ;GET BACK THE OLD UN-ADVANCED PDL PTR IN J. + ROT R,14 + HRLI J,(R) ;PUT 3.7-4.1 OF R INTO LH(J) CIRCUITOUSLY + TLZ J,777760 + ROT R,-14 + AOS J ;MAKE J POINT AT 1ST UNUSED PDL WORD. + XCTRI XBRW,[BLT J,(H)] + CAIA + JRST INTPFL +INTSR5: JUMPGE R,INTSR4 ;SAVE DEBUGGING INFO ON INT PDL IF USER WISHES + HRRZ J,UPJPC(U) + XCTRI XW,[MOVEM J,1(H)] + SKIPA J,SUUOH(U) + JRST INTPFL + XCTRI XW,[MOVEM J,2(H)] + SKIPA J,LSPCL(U) + JRST INTPFL + XCTRI XW,[MOVEM J,3(H)] + CAIA + JRST INTPFL + ADD H,[3,,3] +INTSR4: MOVE J,U ;MAYBE? SCHED LOOP WANTS USER IDX IN J? + XCTRI XW,[MOVEM H,(R)] ;STORE BACK THE PDL POINTER, THUS FINALIZING ALL + TDZA A,C ;INTS HAVE BEEN GIVEN; NOW WE CAN CHANGE THE USER VARS. + JRST INTPFL + ANDCAM C,PIRQC(U) + ANDCAM D,IFPIR(U) + IORM E,IDF1(U) ;SET THE DEFER BITS SPEC'D IN TABLE ENTRY. + IORM TT,IDF2(U) + MOVEM Q,UPC(U) ;START USER AT INT HANDLER. + JUMPL H,INTSR3 ;NOW CHECK FOR INT PDL OVFLO. + JUMPGE W,INTSR3 + MOVEI TT,%PIPDL ;THERE WAS OVFLO, SET PDL OV INT + TDNN TT,MSKST(U) ;IF ENABLED. + JRST INTSR3 + IORM TT,PIRQC(U) + JRST SEAR2E ;RE-TRY THE INTERRUPT. + +INTSR3: JUMPN A,SEAR2E ;MORE INTS TO GIVE => RETRY. + JUMPN B,SEAR2E +INTSRX: AOS NUINT ;1 MORE INT GIVEN SUCESSFULLY. + SPM UPGML(U) + JRST SEARC ;SCHEDULE. + +INTSR1: ADD T,[4,,4] ;NO INTS GIVEN, TRY NEXT ENTRY. +INTSR2: AOBJN T,INTSR0 + JRST INTSUP ;ENABLED INTS BUT NO ENTRIES FOR THEM. + +;GIVE INTS THE OLD WAY. +INTOLD: SKIPN C,A ;GIVE INTS OF 1 WD AT A TIME. + SKIPA C,B ;(NO 1ST WD, GIVE ALL 2ND WD) + TDZA B,B ;(SOME 1ST WD INTS, GIVE NO 2ND WD INTS) + TLO C,4^5 ;(GIVING 2ND WD, SET SIGN TO SAY SO) + XCTRI XW,[MOVEM C,(T)] + SKIPA Q,UPC(U) ;STORE INTS BEING GIVEN, + JRST INTPFL + MOVEI T,2(T) ;ADVANCE -> PLACE TO START USER. + XCTRI XW,[MOVEM Q,-1(T)] + TLOA T,%PCUSR ;OLD PC STORED, SET UP NEW. + JRST INTPFL + ANDCAM A,PIRQC(U) ;SAY THESE INTS NOW GIVEN. + ANDCAM B,IFPIR(U) + SKIPGE IOTLSR(U) + TLO T,%PCUIO + MOVEM T,UPC(U) ;SET HIS PC -> TSINT+2 + SETZM PICLR(U) + JRST INTSRX + +;IF WE ARE WAITING FOR A PAGE NEEDED FOR TAKING AN INTERRUPT, +;GIVE UP ON TRYING TO TAKE TE INT. UNLESS PAGE HAS COME IN SINCE LAST TRY. +INTPAG: MOVSI E,%SWPGW + SKIPE FLSINS(U) + TDNN E,USWST(U) + JRST (T) ;JOB NOT WAITING FOR PAGE + MOVSI E,%SWINT + TDNN E,USWST(U) + JRST (T) ;NOT WAITING FOR INTERRUPT PAGE + MOVE E,T + MOVE T,EPDL2(U) + XCT FLSINS(U) + JRST SEARL ;PAGE NOT IN + MOVSI T,%SWPGW+%SWINT ;PAGE IN + ANDCAM T,USWST(U) + SETZM FLSINS(U) + SOS NPGWTU + JRST (E) + +;COME HERE WHEN AN XCTRI TAKES FAULT WHILE TRYING TO STORE AN INTERRUPT. +INTPFL: MOVE J,U ;MAYBE? SCHED MAIN LOOP WANTS USR IDX IN J. + SPM UPGML(U) ;STORE MAP IN INTERRUPTING STATE +IFN KA10P, LDB T,[221000,,UPJPC(U)] ;FAULT ADDRESS +IFN KL10P, LDB T,[$PFPNO,,UPFW(U)] +IFN KS10P, LDB T,[$PFPNO,,EPTP7W] ; Fault happened at PI level 7. + ROT T,-1 + ADDI T,UPGCP(U) + SKIPL T + TLOA T,222200 + HRLI T,2200 + LDB E,T + JUMPE E,INTBAD ;DON'T HAVE PAGE +IFN KA10P,[ + HLLZ T,UPQUAN(U) + TLNE T,100 + JRST INTBAB ;WRITE IN RD ONLY +INTBAC: HLLZ T,UPC(U) ;SIMULATE SETUP OF OPC + LSH T,-5 + HRR T,UPC(U) + MOVEM T,UPOPC(U) ;FAULT STATUS + MOVSI T,1000 + IORM T,UPQUAN(U) ;BIT NOT SET BY XCTRI + MOVSI T,%SWINT + IORM T,USWST(U) ;PAGE FAULT RESULT OF INTERRUPT ATT + LPMRI UPGML(U) ;SET MPV FLAG, WILL CAUSE INT. LATER LPMR'S WON'T + ; CLEAR IT. + JRST SCHED6 ;"RUN" USER, TAKING PAGE FAULT IMMEDIATELY + +INTBAB: TLNE T,50 ;NO ACCESS OR W IN RWF + JRST INTBAC ;PAGING BOX BUG? IGNORE RD ONLY + JRST INTBAD ;REALLY IS READ-ONLY. +] ;KA10P +IFN KL10P,[ + SUBI T,UPGCP-UPGMP + LDB E,T + TRNE E,600000 + LSH E,-20 + CAIN E,2 ;RWF + JRST INTBAB + MOVS T,UPFW(U) + ANDI T,%PFCOD + CAIE T,%PFPNA + JRST INTBAD ;REAL VIOLATION +;DROPS THROUGH + ;DROPS IN +;KL10P ;PF OR RWF, TAKE THE FAULT, READ IN THE PAGE, THEN TRY TO INTERRUPT AGAIN + +INTBAB: MOVSI T,%SWINT + IORM T,USWST(U) ;PAGE FAULT RESULT OF INTERRUPT ATTEMPT + SETOM DLSRCH ;DON'T INTERRUPT AT INTBA1, SCHEDULE, TRY TO PCLSR + ; WITH WRONG PC + MOVEI T,INTBA1 + EXCH T,UPC(U) ;HACK USER'S PC + MOVEM T,EPDL3(U) + JRST SCHED6 ;RUN USER, RETURNING IMMEDIATELY TO INTBA1 + +INTBA1: CONO PI,PIOFF + SETZM DLSRCH + MOVEM U,PFAILU ;SIMULATE A PAGE FAULT ON THE INTERRUPT WORD + MOVE U,USER + MOVE U,EPDL3(U) + MOVEM U,PFOPC1 ;RESTORE USER'S PC + MOVNI U,2 + MOVEM U,PFAILF ;FLAG FAULT FROM INTPFL + MOVE U,PFAILU ;RESTORE U SO CLKSAV CAN RE-SAVE IT + CONO PI,CLKRQ ;TURN PI SYSTEM ON AND CAUSE CLOCK BREAK + JRST . ;TAKES A WHILE TO GO OFF +] ;KL10P +IFN KS10P,[ + MOVE T,EPTP7W + TLNE T,%PF2.8 ; Write in read only? + JRST INTBAD ; Yes: %PIB42 + MOVEM T,UPFW(U) ; No: Set up for a simulated fault + MOVSI T,%SWINT + IORM T,USWST(U) ; Signal fault as result of interrupt attempt + SETOM PFAILF ; Cause CLK level to go to PFLU2 at + ; first opportunity. + MOVEI T,CCLKRQ ; Make sure that happens real fast + EXCH T,UPC(U) ; by setting his PC thusly. + MOVEM T,EPTPFO ; Save old PC as location of fault. + JRST SCHED6 ; Go run this user. +] ;KS10P + +INTBAD: MOVEI A,%PIB42 ;TURN ON BAD PI LOC INT BIT + IORB A,PIRQC(U) ;GIVE USER INTERRUPT(MUST IORM TO AVOID TIMING ERR) + JRST SEAR2A ;RE-PERFORM ACTIONS FOR NON-ZERO PIRQC + ;WILL CAUSE AN INTERRUPT TO SUPERIOR + +;INTERRUPT ALL USERS THAT WANT IT +; C(A) IS BIT IN PIRQC TO TURN ON +DBGINT: MOVSI A,(%PIDBG) ;"SYS BEING DEBUGGED" INT +INTALL: MOVEI U,0 ;ENTRY INITIALIZE +INTA2: ADDI U,LUBLK ;ADVANCE TO NEXT BLOCK OF USER VARIABLES + CAML U,USRHI ;SKIP UNLESS AT END + POPJ P, ;THROUGH, RETURN + SKIPN UNAME(U) ;SKIP IF BLOCK IN USE + JRST INTA2 ;IDLE, IGNORE + LDB T,[410100,,USTP(U)] ;GET BUCSTP OF USERS STOP WORD + JUMPN T,INTA2 ;IF USER CONTROL STOPPED, JUMP TO IGNORE + MOVE B,MSKST(U) ;PICK UP INTERRUPT MASK + AND B,A ;MASK C(B) TO APPROPRIATE BIT + IORM B,PIRQC(U) ;GIVE INT TO USER + JRST INTA2 ;LOOP + +SUBTTL PCLSR ROUTINES + +; PUT PC OF USER WHOSE INDEX IS IN U IN USER MODE +; (CALL ONLY WITH CLOCK OFF OR CLOCK BREAK IN PROGRESS) +;SKIPS IF SUCCESSFUL, FAILS IF USER RUNNING IN EXEC CODE OR HAS TO BE FINALIZED +; +PCLSR: AOS NPCLSR + CAIG U,L + BUG ;PCLSR'ING NULL, SYS OR CORE JOB? + MOVEI T,L + IDIVM U,T + IMULI T,L + CAMN T,U ;IS U REALLY A MULTIPLE OF LUBLK? + SKIPN UNAME(U) ;SHOULD NOT HAPPEN TO NONEXTANT JOB + BUG + SKIPE USTP(U) + JRST POPJ1 ;USER STOPPED (MUST ALREADY BE IN USER MODE) + AOS NEPCLS + SKIPLE T,RPCL(U) + JRST PCLSR2 ;LOSER IS RPCLSR'ING SOMEONE +PCLSR3: MOVE T,SUEXIT(U) +IFE KA10P,SUB T,U + CAME T,[JRST 2,@XUUOH] + JRST PCLSR5 ;EXIT ALREADY CLOBBERED + MOVE T,UPC(U) ;PICK UP PROGRAM COUNTER (FLAGS IN L.H.) + TLNN T,%PCUSR ;SKIP IF USER MODE ON + JRST PCLSR8 ;JOB CURRENTLY IN EXEC MODE + SOS NEPCLS ;WAS WRONGLY AOS'ED + CLEARM FLSINS(U) ;IN CASE HE WAS WAITING FOR A PAGE OR CIRPSW + MOVE T,USWST(U) + TLNE T,%SWPGW + SOS NPGWTU + MOVSI T,%SWPGW+%SWRUN+%SWINT + ANDCAM T,USWST(U) + AOS (P) + POPJ P, + +PCLSR8: SKIPE FLSINS(U) ;SKIP IF UNBLOCKED + JRST PCLSR1 ;HUNG, TRY TO BACK UP TO UUO +PCLSR4: MOVE T,[JRST ONEFLS] + MOVEM T,SUEXIT(U) ;MUNG EXIT OF UUO, COME BACK LATER +PCLSRF: AOS NFPCLS + POPJ P, + +PCLSR2: SETZM RPCL(U) ;CLEAR OUT POINTERS IN BOTH DIRECTIONS + SETZM RPCL(T) + JRST PCLSR3 + +PCLSR5: SKIPN FLSINS(U) + JRST PCLSRF ;NOT HUNG, LET RUN TO COMPLETION +IFN KA10P,[ ;HUNG, UNCLOBBER EXIT AND BACK UP TO UUO + CAME T,[JRST ONEPROC] ;SKIP IF ONE PROCEEDING A SYS CALL + JRST PCLSR6 + MOVSI T,%PC1PR + IORM T,SUUOH(U) ;RESET SINGLE INSTRUCTION PROCEED +PCLSR6:] ;KA10P +IFN KS10P,[ ;HUNG, UNCLOBBER EXIT AND BACK UP TO UUO + CAME T,[JRST ONEPR4] ;SKIP IF ONE PROCEEDING A SYS CALL + JRST PCLSR6 + MOVSI T,OIPBIT + IORM T,XUUOH(U) ;RESET SINGLE INSTRUCTION PROCEED +PCLSR6:] ;KS10P + MOVE T,UPC(U) + TLNE T,%PCUSR + BUG +IFN KA10P, MOVE T,[JRST 2,@UUOH] +IFE KA10P,[ + MOVSI T,(JRST 2,@) + HRRI T,UUOH +] ;IFE KA10P + MOVEM T,SUEXIT(U) ;UNCLOBBER EXIT +PCLSR1: HLRZ T,LSPCL(U) ;SAVE LAST TWO DISTINCT LOCS PCLSR'ED FROM + CAIN T,@UPC(U) + JRST PCLSR9 + HRL T,UPC(U) + MOVEM T,LSPCL(U) +PCLSR9: SOS T,SUUOH(U) ;GET USER LOCATION OF HIS CURRENT UUO +UFL5: +IFN KL10P,[ + TLC T,%PS1PR-%PSINH + TLCN T,%PS1PR-%PSINH + TLO T,%PSINH ;ONE PROCEEDING AND INSTR NOT COMPLETE +] ;KL10P + MOVEM T,UPC(U) ;SET USERS PROGRAM COUNTER +IFE KA10P,[ + MOVSI T,701100 ;RESTORE PAGE-CONTEXT TO USER MODE + HLLM T,CLCX(U) +] ;IFE KA10P + CLEARM UMAPS(U) ;RESTORE TO NORMAL MAP + SETZM FLSINS(U) ;CLEAR OUT ANY BLOCKING CONDITION + MOVE T,USWST(U) + TLNE T,%SWPGW + SOS NPGWTU + MOVSI T,%SWPGW+%SWRUN+%SWPCL+%SWINT ;NOT BLOCKED ON PAGE, NOT UNBLOCKED SWAPOUT, + ANDCAM T,USWST(U) ; NOT INTERRUPT PAGE, NOT SWAPPED OUT WHILE BLOCKED + SKIPE T,LSWPR(U) + JRST LSWZAP ;REQUIRED TO UNLOCK SWITCHES +PCLSR7: +IFE KA10P,[ + MOVEI T,UUOACS(U) ;IF JOB U'S ACS ARE IN HARDWARE AC BLOCK 1, + CAMN T,AC1PTR ;COPY THEM INTO UUOACS WHERE THEY BELONG. + XCTR XBR,[BLT T,UUOACS+17(U)] +] ;IFE KA10P + MOVEI T,AC0S(U) + HRLI T,UUOACS(U) + BLT T,AC17S(U) + JRST POPJ1 ;EXIT AFTER BACKING UP TO UUO + ; +; AOS USTP OF USER IN A +; +NJRPCL: CAIE A,-1 ;ENTRY TO IGNORE IF NULL JOB +RPCLSR: CAMN A,USER ;NORMAL ENTRY + POPJ P, ;TRYING TO RPCLSR SELF OR NULL JOB + PCLT + PUSH P,U ;SAVE U + MOVE U,A ;GET INDEX OF RPCLSRED JOB IN U + MOVE A,USER ;GET RPCLSRING USER INDEX IN A + CONO PI,CLKOFF ;TURN OFF CLOCK BREAKS + PUSHJ P,PCLSR ;PUT USER IN USER MODE + JRST RPCLOS ;JUMP IF CAN'T DO IT RIGHT NOW + AOS USTP(U) ;WIN,STOP USER + CONO PI,CLKON ;RE-ENABLE CLOCK BREAKS +RPCLS1: MOVE A,U ;RESTORE A + POP P,U ;RESTORE U + POPJ P, +; +RPCLOS: SKIPE RPCL(U) ;SKIP IF ZERO RPCL FOR USER BEING RPCLSRED + JRST RPCLS2 ;SOMEONE GOT THERE FIRST + SKIPE RPCL(A) ;SKIP IF ZERO RPCL FOR RPCSRING USER + JRST UDELAY ;YOU ARE BEING RPCLSR'ED, SURRENDER + HRROM A,RPCL(U) ;SET UP RPCL IN VARS OF RPCLSRED USER + HRRM U,RPCL(A) ;" OF RPCLSRING USER + PCLT + SKIPE RPCL(A) ;WILL NOT SKIP AT FIRST + PUSHJ P,UFLS ;WAIT FOR PERSON BEING RPCLSRED TO GET TO ONEFL2 + JRST RPCLS1 +; +RPCLS2: MOVE A,U ;RESTORE A AND U + POP P,U + PCLT + SKIPE RPCL(A) ;WAIT FOR OTHER GUY TO WIN + PUSHJ P,UFLS + JRST RPCLSR ;THEN TRY AGAIN + +; +; UNDO AN RPCLSR +; +NJUPCL: CAIE A,-1 ;ENTRY TO IGNORE IF NULL JOB +UPCLSR: CAMN A,USER ;REGULAR ENTRY + POPJ P, ;TRYING TO UPCLSR SELF OR NULL JOB + SOSGE USTP(A) + BUG + POPJ P, + +IFN KA10P,[ +; +; RETURN FROM SYSTEM CALL IN ONE PROCEED MODE +; +ONEPROC:CONO PI,CLKOFF ;TURN OFF CLOCK BREAKS + MOVE U,USER ;BE SURE U HAS RUNNING USER INDEX IN IT + MOVEI T,%PI1PR + IORM T,PIRQC(U) ;GIVE USER INTERRUPT + JRST ONEPR2 +] + +SUBTTL KS-10 ONE-PROCEED + +IFN KS10P,[ +ONEPRO: SYSCTX ;SWITCH TO SYSTEM AC BLOCK + SKIPGE U,USER + BUG AWFUL,[ONE-PROCEED IN NULL JOB] + MOVE T,1PROPC(U) ;PC OF NEXT INSTRUCTION TO EXECUTE + TLNE T,%PSUSR ;NORMALLY USER MODE IS EXPECTED + JRST ONEPR3 + HRRZ T,T ;SEE IF IT'S FIRST INSTRUCTION OF EXEC ENTRY + CAIE T,UUOH0 + CAIN T,MUUOTR + SKIPA TT,[JRST ONEPR4] + BUG AWFUL,[ONE-PROCEED IN EXEC MODE],OCT,1PROPC(U) + MOVEM TT,UEXIT ;CLOBBER EXIT TO RUN SYS CALL TO COMPLETION + CAIE T,UUOH0 ;AND RESUME PROCESSING UUO + JRST [ USRCTX + JRST MUUOTR ] + USRCTX + JRST UUOH0 + +ONEPR3: MOVEM T,UUOH ;PUT USER PC WHERE ONEFLS WANTS IT +ONEPR4: SYSCTX ;COME HERE WHEN ONE-PROC'D UUO FINISHES + MOVE U,USER ;BE SURE U HAS RUNNING USER INDEX IN IT + MOVEI T,%PI1PR + IORM T,PIRQC(U) ;GIVE USER INTERRUPT + JRST ONEFLS +];KS10P + +SUBTTL USER START ROUTINES +; +; CALLED EVERY SLOW CLOCK TICK WHEN TTY WANTING TOP PROCEDURE LOADED +; +USTART: PUSH P,U +USTRT1: SKIPL T,@UTTYO ;GET TTY TO BE STARTED + JRST [ MOVE U,MMPFR ;WHEN STARTING A HACTRN, MAKE SURE CORE IS AVAILABLE + CAIGE U,100 + JRST USTRTL ;IT'S NOT, SAY SYSTEM FULL + JRST .+2 ] ;T HAS INITIAL TTYTBL + MOVSI T,%TBNOT+%TBDTY+%TBNVR ;NOT A REAL TTY, INITIALIZE TTYTBL TO NO TTY + PUSHJ P,USTRA ;CREATE NEW USER SLOT ENTRY + JRST USTSC1 ;LOSE, HAVE TO WAIT + SKIPGE T,@UTTYO ;SKIP IF REALLY A TTY + JRST USTRTS ;DONT LOAD A HACTRN + MOVE T,[SIXBIT /HACTRN/] ;LOAD HACKTRN +USTRT2: MOVEM T,JNAME(U) ;SET JOB NAME + MOVEM T,XJNAME(U) + HRLZI T,%PCUSR + HRRI T,1 + MOVEM T,UPC(U) + MOVEI T,AC0S(U) + HRLI T,NUSTCD + BLT T,AC17S(U) + MOVE T,JNAME(U) + MOVEM T,AC0S+11(U) + SETZM @UTMPTR(U) ;GIVE TEMPORARY HIGH PRIORITY + SETZM USTP(U) ;START UP +USTSC2: AOS T,UTTYO ;AOS RING BUFF + CAIL T,UTTYS+MXCZS + MOVEI T,UTTYS + MOVEM T,UTTYO + SOSE UTTYCT + JRST USTRT1 ;MORE JOBS TO SET UP + JRST POPUJ + +USTRTS: MOVEM U,1(T) ;STORE USER'S INDEX IN SECOND WORD + MOVE T,(T) ;GET JNAME FROM FIRST WORD (POINTED TO BY RH OF @UTTYO) +IFN DEMON,[ + CAME T,[SIXBIT /LDRDEM/] + CAMN T,[SIXBIT /UNSPOO/] + AOS UTMPTR(U) ;LOADER, UNSPOOLER -> SYSTEM TREE +] + JRST USTRT2 + +USTSC1: MOVE U,USRHI ;IF A USER IS ^Z'ING AND THERE IS NO POSSIBILITY + SKIPL T,@UTTYO ;OF GETTING MORE JOB SLOTS, + CAIGE U,LUBLK*MAXJ + JRST POPUJ +USTRTL: MOVSI U,%TANJS ;THEN MARK THE TTY AS IN NEED OF A "SYSTEM FULL" MESSAGE + IORM U,TTYSTA(T) + MOVEI U,SCRCFM ;AND WAKE UP THE SYS JOB. + IORM U,SUPCOR + JRST USTSC2 ;REMOVE THIS TTY FROM LIST OF THOSE NEEDING A ^Z. + +;GOBBLE NEW USER SLOT, RESET VARIABLES (SKIPS IF IT WINS) +;RETURNS INDEX IN U. IF FAILS, CLOBBERS U! +USTRA: MOVEI U,0 +USTR3: CAML U,USRHI + JRST USTR1 ;ASSIGN MORE CORE TO USER STORAGE + SKIPN UNAME(U) + JRST USTR2 ;HAVE FOUND FREE USER SLOT (IN U) + ADDI U,LUBLK + JRST USTR3 + +USTR1: SKIPGE SJCFF + POPJ P, ;SYSTEM JOB FLUSHING CORE, WAIT UNTIL IT STABILIZES + MOVEI U,LUBLK ;MOVE UP USRHI IF SYS HAS ENOUGH CORE + ADD U,USRHI + PUSH P,T + MOVE T,HUSRAD ;LENGTH OF SYS + CAIGE T,USRSTG(U) + JRST MORCOR ;SYS NEEDS MORE CORE FOR USER VARIABLES + POP P,T +USSINI: SETOM USTP-LUBLK(U) ;SYS INITIALIZATION ENTRY + EXCH U,USRHI +USTR2: PUSHJ P,USTR4 ;RESET USER VARIABLES + MOVEI T,SIOCHN-1(U) + MOVEM T,SIOCP(U) + CLEARM IOCHNM(U) + HRLI T,IOCHNM(U) + HRRI T,IOCHNM+1(U) + BLT T,IOCHNM+17(U) ;CLEAR ALL I/O CHANNELS +USRST4: HRLI T,AC0S(U) + HRRI T,AC0S+1(U) + SETZM AC0S(U) + BLT T,AC17S(U) ;CLEAR AC'S & RETURN HAPPY + JRST POPJ1 + +MORCOR: SUB P,[1,,1] + MOVSI T,SCLDEC + ANDCAM T,SUPCOR ;CLEAR ANY SYS CORE DECREASE REQ + MOVSI T,SCLEX + JRST SUPSET ;REQUEST MORE CORE FROM SYS JOB + ; +; INITIALIZE A SET OF USER VARIABLES +; T HAS INITIAL TTYTBL, POSITIVE IT IS TTY # ELSE NO TTY +USTR4: MOVEM T,TTYTBL(U) + JUMPL T,USTR4B + PUSH P,U + HRRM U,TTYSTS(T) ;TELL TTY IT NOW BELONGS TO NEW JOB, + MOVSI U,%TSCNS ;AND IS NOW A CONSOLE. + IORM U,TTYSTS(T) + MOVSI U,%TSFRE + ANDCAM U,TTYSTS(T) ;AND IS NO LONGER FREE + MOVSI U,%TACFM+%TACTZ + ANDCAM U,TTYSTA(T) ;AND WILL NEED CONSOLE FREE MESSAGE + POP P,U + ADDI T,USRRCE +USTR4A: MOVEM T,UTMPTR(U) + HRROI T,'000 + MOVEM T,UNAME(U) + PUSH P,U + MOVE T,U + IDIVI T,LUBLK + POP P,U + DPB T,[000300,,UNAME(U)] + LSH T,-3 + DPB T,[060300,,UNAME(U)] + LSH T,-3 + DPB T,[140300,,UNAME(U)] + MOVE T,UNAME(U) + MOVEM T,XUNAME(U) + MOVEM T,HSNAME(U) + MOVE T,JNAME(U) + MOVEM T,XJNAME(U) + MOVEI T,(U) + HRLI T,%TSCNS + MOVEM T,TTSTSV+2(U) + SETZM USWST(U) +IFN SWPWSP,[ + SETZM UWRKST(U) + SETZM USVWRK(U) + MOVE T,TIME + ADDI T,2*30. ;PROTECT FROM SWAPOUT FOR 2 SECONDS (RANDOMLY) + MOVEM T,USWTIM(U) +];SWPWSP + SETZM NSWPGS(U) + SETZM NMPGS(U) + SETOM JBI(U) ;NOT JOB DEVICE HANDLER (NOT YET, ANYWAY) + SETZM OPTION(U) + SETZM STTYOP(U) + SETOM TRNLST(U) ;INIT TRANSL LISTS TO NIL + SETOM TRNLS1(U) + SETZM HUSRAD(U) + JUMPE U,.+5 ;SYSTEM JOB DOESN'T HAVE A MAP + CLEARM UPGMP(U) + MOVSI T,UPGMP(U) + HRRI T,UPGMP+1(U) + BLT T,UPGCP+NUVPG/2-1(U) + MOVSI T,(MOVEM U,) + HRRI T,AC17S(U) + MOVEM T,SCLUSV(U) +IFE KA10P,[ + MOVSI T,(DATAI PAG,) + HRRI T,CLCX(U) + MOVEM T,SCLCXS(U) + MOVEI T,USRSTG(U) +IFN KL10P, LSH T,-9 + HRLI T,701100 + MOVEM T,CLCX(U) + MOVSI T,(JRST 2,@) + HRRI T,XUUOH(U) + MOVEM T,SUEXIT(U) + MOVSI T,(CAI) ;INITIALLY IGNORE TRAPS 1 AND 2 + MOVEM T,TR1INS(U) + MOVEM T,TR2INS(U) +IFE KS10P,MOVEI T,%PI1PR ;TRAP 3 IS IGNORED TOO ON KS + MOVEM T,TR3INS(U) ;TRAP 3 GIVES ONE-PROCEED INTERRUPT ON KL +] ;IFE KA10P +IFN KL10P,[ + SETZM ULSPBR(U) + MOVSI T,MUUOKN ;UUO NEW PC'S ARE SAME AS SYS JOB'S, + HRRI T,MUUOKN(U) ; EXCEPT THAT UUO IN EXEC MODE IS AN ERROR + BLT T,MUUOPT(U) + MOVEI T,MUUOEX + HRRM T,MUUOKN(U) +] ;KL10P +IFN KS10P,[ + MOVE T,[%PSPCU,,MUUOEX] + MOVEM T,MUUOKN(U) ; UUO in Exec mode is an error + MOVEM T,MUUOKT(U) ; (either case) + HRRI T,UUOH0 + MOVEM T,MUUOCN(U) ; Normal UUO + HRRI T,MUUOTR + MOVEM T,MUUOCT(U) ; UUO as trap instruction + HRRI T,ONEPRO + MOVEM T,1PRNPC(U) ; One-proceed jumps to ONEPRO +] ;KS10P +IFN KA10P,[ + MOVE T,[JRST 2,@UUOH] + MOVEM T,SUEXIT(U) +] ;KA10P + MOVSI T,BUSRC + MOVEM T,USTP(U) + SETOM SUPPRO(U) + SETZM UCLBLK(U) + SETOM UCLBLK+1(U) + MOVE T,[JRST UREALB] + MOVEM T,UCLBLK+2(U) + CLEARM UPGML(U) ;CLEAR USER PG MAP VARIABS + MOVEI T,UPGML+1(U) + HRLI T,-1(T) + BLT T,UPGMLE(U) +IFN KA10P,[ + MOVSI T,1+EXPGNG ;DONT ENABLE QUAN COUNTER FOR NOW (BUT SET + ; EXEC PAGING) + MOVEM T,UPQUAN(U) + MOVE T,EXECMP + MOVEM T,UPDBR3(U) ;SET UP EXEC DBR + MOVSI T,IFN MCOND DM,[1040] .ELSE [0] ;ON DM, B+C MEMORIES DON'T WORK + MOVEM T,UPACP(U) ;SET UP B+C MEMORY PTRS +] ;KA10P +IFN KS10P, SETZM UPQUAN(U) ; Clear quantum counter. + +;DROPS THROUGH + +;DROPS THROUGH, AND .RESET OF USR DEVICE COMES HERE. +USRST2: MOVE T,UNAME(U) + MOVEM T,USYSNM(U) ;CLOCK MUST BE OFF OR PI IN PROG ON 7 + MOVE T,TIME ;DON'T SWAP JOB OUT RIGHT AWAY + MOVEM T,LUBTM(U) + PUSH P,A + PUSH P,B + PUSH P,C + PUSH P,E + MOVEI C,UCLBLK(U) + SKIPL 1(C) + JSP E,CLQCLR + SETOM SERVER(U) + SETZM PAGAHD(U) + SETZM PAGRAN(U) + SETZM UWHO1(U) + SETZM UWHO2(U) + SETZM UWHO3(U) +IFN N11TYS,[ + SETZM NVDBA(U) ;0 VIDEO BUFFERS ASSIGNED BY JOB. + SETOM TVCREG(U) + SKIPL T,TTYTBL(U) + PUSHJ P,USTTV0 + SETOM TVVBN(U) +USTTV1: ];N11TYS + POP P,E + POP P,C + POP P,B + POP P,A + SETZM URTIME(U) + SETZM UTIME(U) + SETOM RTIMER(U) + MOVSI T,%PCUSR + MOVEM T,UPC(U) + HRLI T,-LUPDL + HRRI T,UPDL-1(U) + MOVEM T,USRPDL(U) + SETZM MSKST(U) + SETZM MSKST2(U) + MOVE T,[20,,40] + MOVEM T,40ADDR(U) + MOVEI T,APRCHN+440 + MOVEM T,APRC(U) + SETZM USTYN(U) + SETZM PIRQC(U) + SETZM IFPIR(U) + SETZM IDF1(U) + SETZM IDF2(U) + SETOM PICLR(U) + SETZM FLSINS(U) + SETZM UTRNTM(U) +IFN KL10P,[ + SETZM EBOXCT(U) + SETZM EBOXCT+1(U) + SETZM MBOXCT(U) + SETZM MBOXCT+1(U) +] + SETZM USIPRQ(U) + SETZM TRUNTM(U) + SETZM TSIPRQ(U) +IFE SWPWSP,[ + SETZM LTRNTM(U) + SETZM LSIPRQ(U) + SETZM UPGSEC(U) +];SWPWSP + SETZM IOTLSR(U) + MOVSI T,%OPOJB ;USR RESET DOESN'T CLEAR OJB OPTION BIT + ANDM T,OPTION(U) + SETOM CORRQ(U) + POPJ P, + +USTR4B: MOVEI T,USRRCE+NCT + JRST USTR4A + +IFN N11TYS,[ +;SET UP THE BLINKER FOR THE JOB IN U. +USTTV0: SKIPN TEN11F + SKIPL TT11P + POPJ P, + HRL T,TTYTYP(T) + TLNN T,%TY11T + POPJ P, ;NOT A TV + MOVE A,TT11HD ;11 HEADER ADR + ADDI A,-NF11TY(T) + LDB B,[141000,,1(A)] ;VIDEO BUFFER # + TRO B,17_8 ;CSET ALU FCTN + LSH B,4+16. ;INTO POSITION FOR MOVEMING INTO CONSOLE REG + MOVEM B,TVVBN(U) + JRST POPJ1 +] ;END IFN N11TYS + +; USER START CODE + +NUSTCD: JFCL ;0 + .OPEN 1,7 + .LOGOUT ;2 + .CALL 12 + .LOGOUT + .IOT 1,2 + JRST (2) + .UII,,(SIXBIT/SYS/) ;7 + SIXBIT /ATSIGN/ + SIXBIT /HACTRN/ + SETZ ;12 + SIXBIT /LOAD/ + 16 + SETZ 17 + -1 ;16 + 1 ;17 + +USTCDR: SYSCTX ;GOT HERE FROM ULEAVE WHICH SELECTED THE USER ACS, + MOVE U,USER ; SELECT SYSTEM ACS INSTEAD. + MOVEI A,USTCDR+1 ;COME BACK HERE IN CASE OF PCLSR + MOVEM A,UUOH + MOVE P,USRPDL(U) + PUSHJ P,UBLAM + MOVE U,USER + MOVSI T,NUSTCD + XCTR XBW,[BLT T,17] + MOVE T,JNAME(U) + UMOVEM T,11 + MOVE T,[%PCUSR,,1] + MOVEM T,UUOH + JRST URET + +SUBTTL USER KILL ROUTINES + +; +; CLOSE ALL DEVICES AND INFERIOR PROCEDURES OF A JOB (INDEX IN U) +; +IODCL: MOVNI I,1 ;SET TO STOP + PUSHJ P,IODCL3 ;STOP ALL INFERIOR JOBS (RECURSIVE) + MOVEI I,0 ;THEN KILL. +IODCLA: PUSH P,I + MOVE A,OPTION(U) + TLNE A,%OPLOK ;IF USER HAS ENABLED THE SWITCH-UNLOCK FEATURE, + PUSHJ P,IODCSW ;UNLOCK HIS LOCKED SWITCHES. +IFN 340P\E.SP, PUSHJ P,ADCLOSE ;FLUSH DISPLAY +IFN IMXP, PUSHJ P,POTCLS ;DISCONNECT HIS POTS +IFN VIDP,[ + CAMN U,SCNUSR + PUSHJ P,SCNSTP ;KILL SCANNER IF HIS +] +IFN ARMP, PUSHJ P,AARMOFF ;FLUSH ARM +IFN DEMON, PUSHJ P,DEMOUT ;FLUSH EXISTANCE (CURRENT OR FORMER) AS DAEMON. +IFN N11TYS,[ + SKIPE NVDBA(U) + PUSHJ P,VBDFLS ;DEASSIGN ALL VIDEO BUFFERS. +] +IFN KL10P,[ + CAMN U,MTRUSR ;DEASSIGN THE PERFORMANCE COUNTER + PUSHJ P,PRFOFF +];KL10P + PUSHJ P,CLQDEL ;RELEASE AND STOP CLOCK QUEUE BLOCK + UCLBLK(U) + HRRZ A,UREALT + CAMN A,U + SETOM UREALT ;UN REAL TIME + CAMN U,UMASTER ;UNMASTER + SETOM UMASTER + PUSHJ P,AIOPDL ;POP UP ALL OF IO PDL (CLOSING CHNLS POPPED INTO) + MOVEI R,IOCHNM(U) +IODCL1: PUSHJ P,CCLOSE ;CLOSE ALL CHANNELS + CAIGE R,IOCHNM+NIOCHN-1(U) + AOJA R,IODCL1 + PUSH P,U + SKIPGE T,JBI(U) ;IF THIS JOB IS A JOB-DEVICE, + JRST IODCL2 + HRROS JBCJUI(T) ;TELL THE JOB CHANNEL THAT THE HANDLER IS GONE. + CONO PI,CLKOFF + SKIPGE JBCG(T) ;IF OUR CREATOR STILL HAS A JOB CHANNEL, + JRST IODCL6 + MOVE A,JBCUI(T) ;FLUSH THE CREATOR'S JOB CHANNELS, + CONO PI,CLKON + PUSHJ P,RPCLSR ;STOPPING THE CREATOR IN CASE HE'S USING THEM NOW. + MOVE T,JBI(U) ;RPCLSR CLOBBERS T. + MOVSI C,%CLSJ + PUSHJ P,CHSCAA + PUSHJ P,[HRRZ B,(R) + TDNN C,CLSTB(B) + POPJ P, + HLRZ B,(R) + CAMN B,T + SETZM (R) + POPJ P,] + PUSHJ P,UPCLSR ;ALLOW THE CREATOR TO CONTINUE AND GET IOC ERROR OR RETRY OPEN +IODCL6: CONO PI,CLKON + SETOM JBCUI(T) ;FLUSH THE JOB-DEVICE SLOT. + SETOM JBI(U) ;SAY THIS JOB NO LONGER A JOB-DEVICE. + JRST IODCL2 + +IODCL3: PUSH P,I ;I=0 KILL I=-1 STOP I=1 JUST CLOSE CHANNELS. + PUSH P,U +IODCL2: MOVEI A,0 +IODCL4: HRRZ E,SUPPRO(A) + SKIPE UNAME(A) ;SKIP IF VARIABLES BLOCK IDLE + CAIE E,(U) ;SKIP ONLY IF IT IS A DIRECT INF. + JRST IODCL5 ;TRY NEXT SET OF VARS + PUSH P,A + MOVE U,A + PUSHJ P,1USTOP ;STOP (WITH BUSRC BIT) + MOVE R,P + MOVE P,USRPDL(U) + PUSH P,R + SKIPGE I,-2(R) + JRST IODCL8 ;STOP + PUSHJ P,IODCLA ;KILL OR CLOSE CHNLS, RECURSE +IODCL9: MOVE P,(P) + SKIPE -2(P) ;KILLING? + JRST IODCL7 ;JUST CLOSING CHNLS. + MOVE A,U ;KILLING; WAIT TILL NO OTHER JOB + PUSHJ P,AUCL3 ;IS LOOKING AT THE ONE THAT WE'RE KILLING. + PUSHJ P,UBLST2 ;FLUSH CORE + SETZ R, + PUSHJ P,ZUSLOG ;ACCOUNT FOR USAGE THEN FLUSH LAST VESTIGES + CONO PI,CLKON +IODCL7: POP P,A + HRRZ U,(P) +IODCL5: ADDI A,LUBLK + CAMGE A,USRHI + JRST IODCL4 ;LOOP FOR ALL SETS OF USER VARIABLES + POP P,U + SUB P,[1,,1] + POPJ P, + +IODCL8: PUSHJ P,IODCL3 + JRST IODCL9 + +;SYSTEM CALL UNLOCK. 1 ARG, A JOB SPEC. +;THAT JOB'S LOCKS ARE ALL UNLOCKED. +NUNLOCK: + MOVE J,A + JSP T,NCORUI ;DECODE THE JOB SPEC. + JRST NUNLO1 ;WE'RE CERTAINLY ALLOWED TO WRITE THIS JOB. + JUMPE U,NUNLO1 ;SYSTEM JOB CAN DO IT TO ANYBODY + JSP T,NCORWR ;NOT SURE, SO CHECK. + JRST OPNL31 ;NO, NOT ALLOWED. +NUNLO1: +IFN PDP6P,[ + CAIN J,-1 + JRST OPNL34 +];PDP6P + ;THE CALL IS ALLOWED, SO UNLOCK THAT JOB'S LOCKS + CAMN J,USER + JRST NUNLO2 + MOVE A,J ; If not self, + PUSHJ P,RPCLSR ; assure a User mode PC + PUSHJ P,SOSSET + USTP(A) + JRST NUNLO3 + +NUNLO2: MOVE A,UUOH ; If we are asked to unlock + SUBI A,1 ; our own locks, put our PC in + MOVEM A,SRN3(U) ; SRN3 where IODCSW will look for it +NUNLO3: MOVE U,J + MOVE A,OPTION(U) + TLNE A,%OPLOK ; Provided it is using locks at all... + PUSHJ P,IODCSW + CAME U,USER + PUSHJ P,LSWPOP ; USTP + JRST LSWPJ1 ; DIELOK + ; Returns with U clobbered, which seems to be OK for .CALL's? + + +;CALL HERE TO UNLOCK THE SWITCHES A JOB HAS LOCKED (USER IDX IN U). +;LOCATION 43 (ACTUALLY, 3+C(40ADDR)) HAS THE LIST POINTER. 0 IS NIL. +;ANYTHING ELSE POINTS TO 2-WORD BLOCK; THE 1ST WORD IS THE SWITCH OR THE +;ADDRESS OF THE SWITCH. THE RH OF THE SECOND IS THE CDR OF THE LIST. +;THE LH OF THE SECOND IS THE UNLOCK INTRUCTION. THE INDEX FIELD IS IGNORED, +;ONE LEVEL OF INDIRECTION IS PERMITTED, AND THE INSN MUST BE EITHER +;AOS OR SOS WITH 0 IN AC FLD, A LOGICAL INSTRUCTION (TOP 3 BITS = 4), +;A HALFWORD INSTRUCTION, OR A MOVE,MOVN,MOVS,MOVN,ADD OR SUB SERIES INSN, +;OR 0 WHICH MEANS SETOM. ONLY INSNS THAT MODIFY MEMORY ARE USEFUL. +;44 IS AN AOBJN POINTER TO THE CRITICAL RTNS TABLE, OF 2-WORDS ENTRIES. +;THE 1ST WORD EACH IS ,,+1. +;THE SECOND IS THE UNLOCK INSTRUCTION, WITH THE ADDRESS OF THE SWITCH +;IN THE RH (AGAIN, 1 LEVEL OF INDIRECTION IS PERMITTED). +;IF THE PC IS IN THAT RANGE, THE UNLOCK INSN IS EXECUTED. +;43 AND 44 ARE UPDATED DURING PROCESSING TO PREVENT PCLSR LOSSAGE. +;SEE .INFO.;ITS LOCKS + + +;MACRO TO DO XCTR, OR POPJ IF THAT WOULD CAUSE INTERRUPT. +DEFINE XCTRIJ + JSP TT,IODCXC + XCTR!TERMIN + +; IODCSW: Unlock locks for user in U +; User should be stopped so that he is in user mode. +; The only exception is if we are unlocking the locks of the running job, +; in which case the contents of SRN3 will be used as our PC. +; Clobbers just about everything except U. +IODCSW: PUSH P,U + PUSHJ P,IODCS0 ; Do actual work, if any... + MOVE U,USER ; But be sure to always + PUSHJ P,MPLDZ ; restore normal page map of running user. + JRST POPUJ ; And U + +IODCS0: HRRZ J,U + MOVE U,USER ;SET UP MAP TO USER BEING HACKED (IDX IN J). + PUSHJ P,MPLDJ ;LH(J) CLOBBERED, RH SAVED. + HRRZ U,J ;U HAS WHAT IT HAD AT CALL (USR BEING HACKED). + MOVEI C,1000 ;COUNT LENGTH OF LIST SO CIRCULAR LISTS DON'T HANG US UP. + HRRZ E,40ADDR(U) + XCTRIJ XRW,[MOVES B,3(E)] ;GET HIS "43" (AND MAKE SURE IT'S WRITABLE) +IODCS1: JUMPE B,IODCS2 ;REACHED END OF LOCKED SWITCH LIST, MAYBE? + XCTRIJ XR,[HLL B,1(B)] ;MERGE LOCK INSN WITH ADDR OF SWITCH. + PUSHJ P,IODCDO ;EXECUTE THE UNLOCK INSN + POPJ P, ;IODCDO DETECTED MPV OR PUR INTERRUPT. + XCTR XR,[HRRZ B,1(B)] ;REPLACE LIST BY ITS CDR. + UMOVEM B,3(E) + SOJG C,IODCS1 + +IODCS2: XCTRIJ XRW,[MOVES E,4(E)] ;GET JOB'S "44", AND MAKE SURE IT'S WRITEABLE. + HRRZ C,UPC(U) ;GET ITS PC, FOR COMPARISON. + CAMN U,USER ; Except if this is us, + HRRZ C,SRN3(U) ; then unlock PC is in SRN3 + JUMPGE E,CPOPJ ;THERE ARE NO PROTECTED RANGES => DONE. +IODCS3: XCTRIJ XR,[MOVS B,(E)] ;GET BOUNDS OF NEXT PROTECTED RANGE. + CAIGE C,(B) ;IS PC ABOVE LOWER BOUND? + JRST IODCS4 + MOVSS B + CAIL C,(B) ;IS IT BELOW UPPER? + JRST IODCS4 + XCTRIJ XR,[MOVE B,1(E)] ;PC IS IN THIS RANGE; GET UNLOCK INSN + PUSHJ P,IODCDO ;EXECUTE IT + POPJ P, ;NO SKIP => MPV OR PUR INTERRUPT DETECTED. +IODCS4: ADD E,[2,,2] ;CHECK ALL ENTRIES IN CRITICAL RTN TABLE, 1 BY 1. + HRRZ B,40ADDR(U) ;UPDATE 44 SO ENTRIES ALREADY PROCESSED ARE + UMOVEM E,4(B) ;ACTUALLY IN THE TABLE. THIS IS IN CASE PCLSR. + JUMPL E,IODCS3 + POPJ P, + +;PRECEDE AN XCTR WITH JSP TT,IODCXC TO POPJ IF THE XCTR WOULD +;CAUSE AN INTERRUPT (MPV OR PUR). CLOBBERS A,T,Q. +IODCXC: MOVEI A,@(TT) ;GET EFFECTIVE ADDR OF XCTR. + MOVEI A,@(A) ;GET EFFECTIVE ADDR OF XCTR'ED INSN. + LSH A,-10. ;GET PAGE # BEING REFERENCED. + PUSHJ P,UPLC ;SET T = B.P. TO PAGE MAP HALFWORD. CLOBBERS Q. + LDB T,T + TRNE T,600000 ;IF PAGE IS SWAPPED IN, PUT ACCESS BITS IN + LSH T,-20 ;SAME PLACE THEY ARE WHEN SWAPPED OUT (LOW 2 BITS). +;FOLLOWING CODE COMMENTED OUT BECAUSE IT DOESN'T WORK ON THE KL10 XCTR +; TRNE T,2 ;CHANGE CODE 2 (READ-WRITE, NOT WRITTEN) TO 3 (READ-WRITE). +; IORI T,1 +; LSH T,27 ;PUT ACCESS CODE IN AC FIELD, AND TEST +; ANDCA T,(TT) ;AGAINST WHAT THE XCTR WILL TRY TO DO. +; TLNN T,(0 3,) ;ALL DESIRED ACCESS AVAILABLE => +; JRST (TT) ;WE WIN. +; POPJ P, ;ELSE QUIT OUT OF CALLING ROUTINE. +; +;FOLLOWING CODE INSERTED INSTEAD. THIS RELIES ON THE FACT +;THAT ONLY THE FOLLOWING INSTRUCTIONS ARE XCTRIJ'ED: +; BOOLE,HWT,MOVXX,ADDX,SUBX,AOSX,SOSX + MOVE A,@(TT) ;GET INSTRUCTION XCTR'ED + TLC A,300000 + TLCE A,300000 ;SKIP IF AOS OR SOS + TLNE A,002000 ;SKIP IF DOESN'T WRITE IN MEMORY + TRNE T,2 ;INSTRUCTION WRITES, SKIP IF RW OR RWF ACCESS NOT PRESENT + TRNN T,3 ;INSTRUCTION READS, SKIP IF ANY ACCESS PRESENT + POPJ P, ;INSUFFICIENT ACCESS, QUIT OUT OF CALLING ROUTINE + JRST (TT) ;WINNING, GO DO THE XCTR + +;PUSHJ P,IODCDO WITH INSN IN B TO XCTRIJ IT, CHECKING FOR LEGALITY +;AND PERFORMING ONE LEVEL OF INDIRECTION IF THE @ BIT IS SET. +;(WE CAN'T AFFORD AN INFINITE LOOP WHILE KILLING A JOB EVEN IF IT IS +;INTERRUPTABLE) +;INDEX FIELD IS IGNORED. IF THE OPCODE IS 0, SETOM IS USED INSTEAD. +;SKIPS IF INSN IS LEGAL AND DOESN'T CAUSE MPV OR PUR INTERRUPT. +;CLOBBERS A,D,J,T,TT,Q +IODCDO: MOVE J,B ;B IS NOT CLOBBERED. + TLZN J,(@) + JRST IODCD1 + XCTRIJ XR,[HRR J,(J)] ;INDIRECTION IS WANTED; DO IT. +IODCD1: TLNN J,-1 ;IF LH IS 0, REPLACE BY (SETOM) + HRLI J,(SETOM) + LDB A,[271500,,J] + CAIE A,AOS_-27 ;AOS AND SOS ARE LEGAL WITH 0 IN AC FIELD. + CAIN A,SOS_-27 + JRST IODCD2 + LDB A,[410300,,J] + CAIE A,4 ;ALL INSNS WITH 4 IN TOP 3 BITS (LOGICAL INSNS) ARE OK. + CAIN A,5 ;HALFWORD INSTRUCTIONS ALSO OK. + JRST IODCD3 + LDB A,[360600,,J] + CAIE A,MOVE_-36 ;ALL FORMS OF MOVE, MOVS, MOVN AND MOVM OK + CAIN A,MOVN_-36 + JRST IODCD3 + CAIE A,ADD_-36 ;ADD & SUB OK. (OF COURSE, ONLY TO-MEMORY INSNS MAKE SENSE) + POPJ P, +IODCD3: LDB A,[270400,,J] ;AC FIELD NEED NOT BE 0, SO GET CONTENTS OF SPEC'D AC, + UMOVE D,(A) + MOVEI A,D + DPB A,[270400,,J] ;AND MAKE THE INSN USE AC D, WHERE THE VALUE IS. +IODCD2: TLZ J,17 + XCTRIJ XRW,J ;EXECUTE INSN, CHECKING FOR INTERRUPTS. + AOS (P) + POPJ P, + +; FLUSH LAST VESTIGES OF USER +; ELIMINATES ALL POINTERS TO USER & FREES USER VARIABLES (CLOBBERS U TO "USER") +; R, IF NON-ZERO, IS ADDRESS OF CHANNEL NOT TO BE CLOSED UNTIL LAST MINUTE +; (IN CASE PCLSR OUT OF .UCLOSE) + +ZUSER: MOVEI A,(U) ;CLEAR BOTH TRANSLATION LISTS + HRLI A,300000 ;FOR THIS JOB. + PUSHJ P,NTRNC + JFCL + MOVEI A,0 ;AND GET RID OF EXISTING FOREIGN-USER CHANNELS. +ZUSER2: SKIPE UNAME(A) + PUSHJ P,ZUSES ;SEE IF THIS USER HAS ANY POINTERS TO BE FLUSHED + CAMN U,SERVER(A) ; If we were a server for this guy, + SETOM SERVER(A) ; clear it out. + ADDI A,LUBLK + CAMGE A,USRHI + JRST ZUSER2 ;LOOP FOR ALL SETS OF USER VARIABLES + SKIPE R + SETZM (R) + CONO PI,CLKOFF + SKIPE NMPGS(U) ;USER SHOULD HAVE NO MEMORY BY NOW + BUG + SETZM UNAME(U) ;ONLY PLACE THAT UNAME IS ZEROED + SETOM USTP(U) ;SET USTP TO SPEED SEARCH + MOVE A,U ;USER FLUSHED + MOVE U,USER + MOVSI T,SCLDEC + IORM T,SUPCOR ;CAUSE USER VARIABLE BLOCKS DECREASE PROGRAM TO RUN + POPJ P, ;RETURN WITH CLOCK OFF + + +;CALLED BY ADISOWN, NATTACH, NDETACH, ETC. +ZUSES: MOVEI D,%CLSU\%CLSFU\%CLSJI\%CLSJO ;CLSTB BITS FOR CHANNELS TO CLOSE +ZUSES1: PUSH P,B + PUSH P,R + PUSH P,C + MOVE C,R + SETZM B ;CLEAR STOPPED PROC FLAG + PUSHJ P,CHSCAA ;EXECUTE FOLLOWING INST FOR EACH CHANNEL AND I/O PDL SLOT + PUSHJ P,ZACHEK + POP P,C + POP P,R + SKIPE B ;SKIP UNLESSS YOU STOPPED THE PROC + PUSHJ P,UPCLSR ;RESTART USER + JRST POPBJ + +ZACHEK: HLRZ T,(R) ;CHECK FOR CHANNEL TO ZAP + CAME T,U + POPJ P, +ZACHK4: HRRZ T,(R) + HLRZ T,CLSTB(T) + TRNN T,(D) + POPJ P, ;IS IT EITHER TYPE OF USER CHANNEL? OR JOB CHNL? + TRON B,-1 ;SET FLAG + PUSHJ P,RPCLSR ;STOP USER + HRRZ T,(R) + HLRZ T,CLSTB(T) + TRNN T,%CLSFU ;IS IT A FOREIGN USR CHNL? + JRST ZACHK2 ;NO, SUPERIOR OR JOB CHNL. + JUMPG R,ZACHK1 ;IOPDL CHANNEL + MOVEI T,LUBLK ;SEE IF A HAS BEEN CLOBBERED + IDIVM A,T ;(AT LEAST MAKE SURE IT'S A VALID USER INDEX) + IMULI T,LUBLK + CAMN T,A + CAML A,USRHI + BUG + HRRZ T,R ;NORMAL CHANNEL, INTERRUPT ON IT. + SUBI T,IOCHNM(A) + MOVE T,CHNBIT(T) + AND T,MSKST2(A) + IORM T,IFPIR(A) +ZACHK2: CAIE C,(R) ;UNLESS THE ONE NOT TO BE CLOSED UNTIL LAST MINUTE, + SETZM (R) ;FOR ANY KIND OF CHANNEL, CLEAR IT OUT. + POPJ P, + +ZACHK1: MOVEI T,IIOPOP ;FOREIGN USR IN IOPDL SLOT: INTERRUPT WHEN IOPOPPED. + MOVEM T,(R) + POPJ P, + +ZUSLOG: PUSH P,[ZUSER] ;DO LOGUSE THEN ZUSER + +;LOG RUNTIME AND SWAPIN REQUESTS USED BY JOB IN U +;JOB CALLED FOR SHOULD NOT BE CURRENT OR ABLE TO RUN DURING CALL +;JOB SHOULD NOT BE TOP LEVEL EXCEPT WHEN DMNPLO CALLS +; HERE JUST BEFORE SENDING THE USAGE TO THE DEMON +;CLOBBERS T,TT,I + +LOGUSE: MOVN TT,UTRNTM(U) + MOVN T,USIPRQ(U) + EXCH TT,TRUNTM(U) ;AVOID CHARGING FOR THIS USAGE TWICE + EXCH T,TSIPRQ(U) + SUB TT,TRUNTM(U) ;COMPUTE TOTAL USAGE NOT YET CHARGED + SUB T,TSIPRQ(U) + SKIPGE I,SUPPRO(U) ;FIND HIGHEST JOB IN TREE + POPJ P, ;BUT IF TOP LEVEL RETURN WITH USAGE IN TT, T +;THIS IS TO FIND A BUG. -- CStacy, 4/30/82 + CAME I,U ;IS THIS JOB ITS OWN SUPERIOR? + JRST LOGUS1 + BUG PAUSE,[SOME JOB IS ITS OWN SUPERIOR, U AND I=],OCT,U +LOGUS1: SKIPL SUPPRO(I) + JRST [ MOVE I,SUPPRO(I) ? JRST .-1 ] + ADDM TT,TRUNTM(I) ;ADD CHARGES TO TREE'S ACCOUNT + ADDM T,TSIPRQ(I) + POPJ P, + +;DO LOGOUT FOR TREE HEADED BY JOB IN U +;CALLER SHOULD THEN PUSHJ P,DMNPLI TO LOG JOB BACK IN +;THIS IS USED TO KEEP ACCOUNTING STRAIGHT WHEN DETACH, CHUNAME, RELOAD (SIGH) +;IF JOB IS CURRENTLY RUNNING, TIME USED IN CURRENT QUANTUM +;WON'T GET CHARGED THIS TIME AROUND. TOO BAD. +;CLOBBERS T,TT,I,J,D. CALL WITH CLKOFF OR IN PROGRESS. + +LOGUPD: PUSH P,U + MOVE J,UTMPTR(U) + MOVEI U,LUBLK +LOGUP1: ADDI U,LUBLK + CAML U,USRHI + JRST LOGUP2 + CAMN J,UTMPTR(U) ;SKIP JOBS IN OTHER TREES (FOR SPEED) + SKIPGE SUPPRO(U) ;AND SKIP TOP LEVEL JOBS + JRST LOGUP1 + SKIPE UNAME(U) ;DON'T GET CONFUSED BY EMPTY SLOTS + PUSHJ P,LOGUSE ;PROBABLY AN INFERIOR IN TREE LOGGING OUT, UPDATE ACCT + JRST LOGUP1 + +LOGUP2: POP P,U + JRST DMNPLO ;TELL DEMON ABOUT TREE'S USAGE + +SUBTTL USER UUO WAIT (HANG UP) ROUTINE +; DOES NOT WORK FOR XCT T OR FOR X (T) +; THE INSTRUCTION BEFORE THE PUSHJ P,UFLS GETS EXECUTED WITH AN +; ARGUMENT PASSED IN T AND ITS USER INDEX IN U. I BELIEVE IT +; IS ONLY ALLOWED TO BASH T AND A. +; +UFLS: CONSZ PI,77400 + BUG HALT,[UFLS WITH PI IN PROGRESS] + CONO PI,CLKOFF ;DOES NOT ALLOW CLOCK INTS + XCT CLUSAV + SKIPGE U,USER ;GET INDEX OF USER BEING BLOCKED + JRST 4,. ;NULL JOB SHOULD NOT GET BLOCKED + MOVEM T,EPDL2(U) ;SAVE C(T) FOR FLSINS AT PCLSR + MOVEM T,AC16S(U) ;SAVE IN SWAP OUT AC ALSO + POP P,UPC(U) ;WORK FOR INST INDEX OF P + MOVEI T,AC0S(U) + BLT T,AC15S(U) ;STORE REST OF ACS + MOVE T,UPC(U) ;GET PC AT CALL (=CALL+1 ; =SKIP +2) + SKIPA T,-2(T) ;GET POINTER TO SKIP +UFL3: MOVE T,(T) ;GET CONTENTS OF E (WAS AN XCT) + MOVE U,AC17S(U) ;WIN FOR INSNS INDEX OF U. + HRRI T,@T ;CALCULATE E + TLZ T,37 ;CLEAR OUT @ AND INDEX BITS + MOVE U,USER + MOVEM T,FLSINS(U) ;STORE AS BLOCKING CONDITION + TLC T,(XCT) + TLNN T,777740 + JRST UFL3 ;JUMP IF INSTRUCTION WAS XCT + CONO PI,UTCON-1 ;TURN ON ALL PIS EXCEPT CLOCK + MOVSI T,%SWPGW+%SWINT + ANDCAM T,USWST(U) ;CLEAR WAITING FOR PAGE TYPE FLSINS + SKIPGE RPCL(U) ;SKIP IF NOT BEING RPCLSRED + JRST UFL1 ;LOSER IS BEING RPCLSRED +UFL6: MOVE U,AC17S(U) ;FOR CLUSAV TO STORE + SETOM UFLSF + CONO PI,CLKRQ ;CAUSE INTERRUPT TRANSFERING TO CLOCK ROUTINE PI IN + ; PROGRESS +IFE KA10P, JRST . ;ON KL AND KS SEEMS TO TAKE A WHILE TO GO OFF ("I + ; CAN WAIT FOREVER, YOU KNOW") +IFN KA10P, JRST 4,. ;ON KA SHOULD GO OFF RIGHT AWAY + +UFL1: MOVE P,CPDLP ;MUST NOT USE USR PDL SINCE THAT CAN + ;GET CLOBBERED BY LSWDIS VIA UFL5 + ;CLOCK IS OFF, SO CPDLP IS OK +IFN KA10P,[ + MOVE T,UEXIT ;PICK UP EXIT INSTR + CAME T,[JRST ONEPROC] ;SKIP IF WAS TRYING TO ONE PROCEED THE UUO + ; THAT HUNG + JRST UFL1A ;NOT ONE PROCEEDING + MOVSI T,%PC1PR ;GET ONE PROCEED BIT + IORM T,UUOH ;TURN IT ON IN PC +UFL1A:] ;KA10P +IFN KS10P,[ + MOVE T,UEXIT ;PICK UP EXIT INSTR + CAME T,[JRST ONEPR4] ;SKIP IF WAS TRYING TO ONE PROCEED THE UUO + ; THAT HUNG + JRST UFL1A ;NOT ONE PROCEEDING + MOVSI T,OIPBIT ;GET ONE PROCEED BIT + IORM T,UUOH ;TURN IT ON IN PC +UFL1A:] ;KS10P + SOS T,UUOH ;UUOH HAS REAL PC IF UFL5 SKIPS. WILL GET SET BY ONEPR1 + PUSHJ P,UFL5 ;BACK UP TO UUO + JRST UFL6 ;FINALIZATION REQUIRED + MOVE T,RPCL(U) + JRST ONEFL2 ;WIN + +SUBTTL VARIOUS WAIT & LOCK-SWITCH ROUTINES +; +;WAIT FOR INSTRUCTION AFTER CALL TO SKIP WITH UTCCHN OFF +; +LWAIT1: CONO PI,UTCON ;TURN INTERRUPTS ON +LWAIT: PCLT + XCT @(P) ;ENTRY, EXECUTE INSTRUCTION + PUSHJ P,UFLS ;HANG TILL INSTRUCTION SKIPS + CONO PI,UTCOFF ;TURN INTERRUPTS OFF + XCT @(P) ;TRY AGAIN + JRST LWAIT1 ;LOSE + JRST POPJ1 ;WIN, RETURN SKIPPING OVER ARG +; +;WAIT FOR LOCK VAR (@ NEXT LOC) TO BE -1 AND SEIZE IT +; +SWTL: PCLT + MOVEI T,(@) ;ENTRY + HRLM T,(P) ;MAKE PC STORED ON PDL INDIRECT + SKIPGE @(P) ;SKIP IF ALREADY LOCKED + JRST SWTL1 ;NOT LOCKED SO TRY TO GRAB IT + MOVEI T,@(P) ;ADDRESS OF SWITCH + HLRZ T,1(T) ;USER THAT HAS SWITCH + ANDI T,777 + IMULI T,LUBLK + CAMN T,USER ;SKIP IF THIS USER DOESN'T HAVE IT + BUG ;THIS USER ALREADY HAS THAT SWITCH +SWTL1: SKIPL @(P) ;(DO NOT CHANGE TO AOSE) + PUSHJ P,UFLS ;HANG TILL NEGATIVE + CONO PI,CLKOFF + AOSE @(P) + JRST SWTL1 +SWTL2: MOVEI T,@(P) +SWTL3: PUSH P,U + PUSH P,T + MOVE T,USER + IDIVI T,LUBLK + ADDI T,600000 + MOVE U,USER + HRL T,LSWPR(U) + POP P,U + MOVSM T,1(U) + MOVE T,USER + HRRZM U,LSWPR(T) + POP P,U + JRST CLKOJ1 +; +;IF LOCK ALREADY SEIZED, JUST SET UP POINTERS +SWTLZ: MOVEI T,(@) + HRLM T,(P) + JRST SWTL2 + +SWTAD: PCLT ;TRY TO LOCK SWITCH (@NEXT LOCN). IF SUCEED, SKIP EXTRA TIME. + MOVE T,@(P) ;IF FAIL, DO N LSWPOPS (AS SPEC IN 4.6-4.1 OF NEXT WORD) + SKIPGE (T) ;AND WAIT FOR SWITCH TO SEEM TO BE AVAILABLE. + JRST SWTAD1 ;THEN RETURN (NOTE: NOT LOCKING IT). +SWTAD2: TLNN T,77000 + JRST SWTAD3 + PUSH P,T + PUSHJ P,LSWPOP + POP P,T + SUB T,[1000,,] + JRST SWTAD2 + +SWTAD3: SKIPL (T) + PUSHJ P,UFLS + JRST POPJ1 + +SWTAD1: CONO PI,CLKOFF + AOSE (T) + JRST [ CONO PI,CLKON + JRST SWTAD2 ] + AOS (P) ;SKIP OVER FAILURE RETURN + JRST SWTL3 + +; +;WAIT FOR INSTRUCTION AFTER CALL TO SKIP WITH CLKCHN OFF +CWAIT1: CONO PI,CLKON ;TURN CLOCK ON +CWAIT: PCLT + XCT @(P) ;ENTRY, EXECUTE INSTRUCTION + PUSHJ P,UFLS ;HANG TILL INSTRUCTION SKIPS + CONO PI,CLKOFF ;TURN CLOCK OFF + XCT @(P) ;TRY AGAIN + JRST CWAIT1 ;LOSE + JRST POPJ1 ;WIN, RETURN SKIPPING OVER ARG + +; +;WAIT FOR LOCK VAR (@ NEXT LOC) TO BE NON-NEGATIVE AND SEIZE IT +LSWTL: PCLT + MOVEI T,(@) ;IF 4.9 OF NEXT LOCN =1, RETURN WITH UTCOFF + HRLM T,(P) + MOVSI T,400000 + PUSHJ P,LWAIT + SKIPGE @-1(P) + IORM T,@(P) + MOVE T,(P) + SKIPL (T) + CONO PI,UTCON + MOVEI T,@(P) +LSWTL2: PUSH P,TT + MOVEI TT,601000 + PUSHJ P,LSWSET + POP P,TT + JRST POPJ1 + +;SWITCH LIST LOCK, DOES NOT WORK FOR SWITCHES POINTED TO INDEX OF A, B, OR D +;FOLLOW BY LIST OF SWITCHES +;4.9-4.4=0 4.3-4.1 0 AOSE SWITCH 1 SIGN SWITCH +SLUGH: PCLT + PUSH P,A + PUSH P,B + PUSH P,D + MOVEI T,AC0S(U) + BLT T,AC0S+17(U) ;FOR SLWAIT FIRST TIME +SLUGH1: HRRZ T,-3(P) ;POINTER TO SWITCH LIST + PUSHJ P,SLWAIT + PUSHJ P,UFLS + HRRZ T,-3(P) +SLUGH2: MOVE A,(T) ;TRY TO LOCK LIST + TLNE A,770000 + JRST SLUWIN ;REACHED END OF LIST + LDB B,[220400,,A] ;INDEX + LDB D,[330300,,A] + SKIPE B + ADD A,(B) + HRRZS A + CAIL D,2 + BUG + XCT SLLOCK(D) + JRST SLULOS + AOBJP T,SLUGH2 ;LH COUNTS SWITCHES SUCCESSFULLY SEIZED + ;SHOULD NVERE FALL THROUGH +SLWAIT: MOVE A,(T) + TLNE A,770000 + JRST POPJ1 ;WIN + LDB B,[220400,,A] ;INDEX + LDB D,[330300,,A] ;TYPE CODE + JUMPE B,SLWT1 + ADD B,U + ADD A,AC0S(B) +SLWT1: CAIL D,2 + BUG + XCT SLWATT(D) + POPJ P, ;LOSE + AOJA T,SLWAIT ;THAT SWITCH OK, TRY OTHERS + +SLWATT: SKIPL (A) ;WAIT FOR NEG (AOSE SW) + SKIPGE (A) ;WAIT FOR POS (SIGN SW) + +SLUWIN: POP P,D + POP P,B + POP P,A + SUB P,[1,,1] ;"RETURN" BUT NOT INCREMENTED + JRST (T) + +SLLOCK: PUSHJ P,SWTLX + PUSHJ P,LSWTLX + +SLULOS: HLRZ A,T +SLULO2: JUMPE A,SLUGH1 ;NONE SEIZED TRY AGAIN + PUSHJ P,LSWPOP ;RELEASE THOSE SEIZED + SOJA A,SLULO2 + +SWTLX: CONO PI,CLKOFF ;DON'T GO OFF HALF-LOCKED + AOSE (A) + JRST CLKONJ + EXCH A,T + PUSHJ P,SWTL3 + BUG +SWTLX1: EXCH A,T + JRST POPJ1 + +LSWTLX: CONO PI,UTCOFF + SKIPGE (A) + JRST UTCONJ + MOVSI B,400000 + IORM B,(A) + CONO PI,UTCON + EXCH A,T + PUSH P,TT + MOVEI TT,601000 + PUSHJ P,LSWSET + POP P,TT + JRST SWTLX1 + +;SET UP ROUTINE TO SETOM VARIABLE UPON UNLOCKING SWITCH +STMSET: PUSH P,TT + MOVEI TT,606000 + JRST COMSET + +IFN 0,[ +;SET UP ROUTINE TO BE CALLED ON PCLSR'ING OUT +FINSET: MOVE T,@(P) + HRLI T,-1(P) + PUSH P,TT + MOVEI TT,402000 + PUSHJ P,LSWSET + POP P,TT + JRST POPJ1 +] + +;SET UP ROUTINE TO AOS VARIABLE UPON UNLOCKING SWITCH +AOSSET: PUSH P,TT + MOVEI TT,605000 + JRST COMSET + +;SET UP ROUTINE TO SOS VARIABLE UPON UNLOCKING SWITCH +SOSSET: PUSH P,TT + MOVEI TT,603000 + JRST COMSET + +;SET UP ROUTINE TO SOS LH UPON UNLOCKING SWITCH +;HALT IF SWITCH'S LH EVER BECOMES NEGATIVE +SOLSET: PUSH P,TT + MOVEI TT,607000 + JRST COMSET + +;SET UP ROUTINE TO BE CALLED UPON UNLOCKING SWITCH +;THAT ROUTINE MAY ONLY CLOBBER A AND T!! IT GETS CALLED +;WITH USER IN U, AND THE JOB'S ACS IN AC0S(U)-AC17S(U) +LOSSET: MOVE T,@(P) + HRLI T,-1(P) + PUSH P,TT + MOVEI TT,602000 + PUSHJ P,LSWSET + POP P,TT + JRST POPJ1 + +;SET UP ROUTINE TO CLEAR SIGN BIT OF VARIABLE UPON UNLOCKING SWITCH +SGNSET: PUSH P,TT + MOVEI TT,601000 + JRST COMSET + +;SET UP ROUTINE TO DO NOTHING UPON UNLOCKING SWITCH +NULSET: PUSH P,TT + MOVEI TT,0 + PUSHJ P,LSWSET + POP P,TT + POPJ P, + +;ROUTINE TO ADD THIS PROCEDURE TO A LIST POINTED TO +;BY THE WORD AFTER THE CALL. UNLOCKING REMOVES IT FROM THE LIST +LSTSET: PUSH P,TT ;LEAVES CLKON + MOVEI TT,604000 + PUSHJ P,LSTST3 + POP P,TT + JRST POPJ1 + +LSTST3: PUSH P,U + PUSH P,Q + MOVEI Q,LSWB0(U) +REPEAT NULBLK,[ +IFN .RPCNT,ADDI Q,2 + SKIPN 1(Q) + JRST LSTST2 +] + BUG ;NOT ENOUGH BLOCKS +LSTST2: MOVE T,@-4(P) ;ADDRESS OF HEAD OF LIST + CONO PI,CLKOFF + PUSH P,(T) ;PUSH HEAD OF LIST + POP P,(Q) ;POP INTO LSWB BLOCK + MOVEM Q,(T) + HRLM T,(Q) + MOVE T,(Q) + TRNE T,-1 + HRLM Q,(T) + CONO PI,CLKON + JRST LSWSE3 + +IFN 0,[ +;SET UP ROUTINE TO SETOM VARIABLE UPON UNLOCKING OF SWITCH +;BY OTHER THAN PCLSRING OUT +STMNPS: PUSH P,TT + MOVEI TT,206000 + JRST COMSET + +;SET UP ROUTINE TO BE CALLED UPON UNLOCKING OF SWITCH +;BY OTHER THAN PCLSRING OUT +LNPSET: PUSH P,TT + MOVEI TT,202000 + JRST COMSET +];END IFN 0 + +COMSET: EXCH TT,(P) + MOVE T,@-1(P) + MOVEI T,@T + EXCH TT,(P) + PUSHJ P,LSWSET + POP P,TT + JRST POPJ1 + +;SET USER LOCK SWITCH BLOCK, WD1 IN T, MODE IN TT +LSWSET: PUSH P,U + MOVE U,USER + PUSH P,Q + MOVEI Q,LSWB0(U) +REPEAT NULBLK,[IFN .RPCNT,ADDI Q,2 + SKIPN 1(Q) + JRST LSWSE2 +] + BUG ;NOT ENOUGH BLOCKS + +LSWSE2: MOVEM T,(Q) +LSWSE3: MOVE T,U + IDIVI T,LUBLK + MOVE U,USER + HRL T,LSWPR(U) + IOR T,TT ;GET TYPE + MOVSM T,1(Q) + HRRZM Q,LSWPR(U) + JRST POPQUJ + +LSWCJ1: AOS (P) ;EXIT TO DO LSWCLR AND SKIP-RETURN. + +;UNLOCK ALL SWITCHES, CALLED BY OPENL, ADISOWN, IOADCR +LSWCLR: PUSH P,T +LSWCL1: +;TEMPORARY CODE ADDED 1/22/80 TO SEE IF THERE ARE ANY MORE OF +;THIS CLASS OF BUGS + CAME U,USER + BUG +;END TEMPORARY CODE + SKIPN T,LSWPR(U) ;MUST HAVE USER IN U + JRST POPTJ + PUSHJ P,LSWPOP + JRST LSWCL1 + +LSWPJ1: AOS (P) +LSWPOP: PUSH P,U + MOVE U,USER + TLO U,400000 ;SIGNAL NOT PCLSR + SKIPN T,LSWPR(U) + BUG + PUSHJ P,LSWPPP + JRST POPUJ + +LSWPPP: PUSH P,A + PUSH P,T + MOVE A,1(T) + HRRZM A,LSWPR(U) + CAIL T,USRSTG + SETZM 1(T) + PUSHJ P,LSWDIS + POP P,T + POP P,A + POPJ P, + +LSWZAP: PUSH P,U ;FROM PCLSR + PUSH P,A +LSWZP1: PUSH P,T + MOVE A,1(T) + HRRZM A,LSWPR(U) + CAIL T,USRSTG + SETZM 1(T) + PUSHJ P,LSWDIS + POP P,T + HRR U,-1(P) + SKIPE T,LSWPR(U) + JRST LSWZP1 + POP P,A + SUB P,[1,,1] + TLZN U,200000 ;HAS PC BEEN CLOBBERED? ;THIS IS ONLY FOR FINSET R.I.P. + JRST PCLSR7 ;NO + SKIPLE PCLDBM + SETZM LSUUO(U) ;INDICATE OCCURRENCE OF FINSET (WILL MEAN WE HAVEN'T MISSED MARK) + JRST PCLSR4 ;REQUIRED TO START UP ROUTINE + +;-1(P) HAS POINTER TO SWITCH BLOCK TO UNDO. +;A HAS SECOND WORD OF THAT BLOCK. +; 4.9=1 => PERFORM FUNCTION ON PCLSR +; 4.8=1 => PERFORM FUNCTION ON ANY LSWPOP OTHER THAN PCLSR +; 4.1-4.3 => FUNCTION +; 3.1-3.9 USER # LAST LOCKED BY +; 1.1-2.9 LSWPR THREAD + +LSWDIS: LDB T,[330300,,A] ;FUNCTION + TLNE A,400000 ;SKIP IF NOT FOR PCLSR + JUMPGE U,LSWDS1 ;PCLSRED AND 4.9=1 + TLNN A,200000 ;NOT FOR PCLSR OR FOR PCLSR BUT NOT PCLSRED + POPJ P, ;NOT FOR EITHER LSWPOP + JUMPGE U,CPOPJ ;FOR OTHER LSWPOP BUT PCLSRED +LSWDS1: JRST LSWTAB(T) + +LSWTAB: JRST UNSWTL ;0 (AOSE) ALSO USED FOR QUSR + JRST UNLSWT ;1 (SIGN) + JRST ULROUT ;2 (GO TO ROUTINE) + JRST ULAOS ;3 (AOS, SOS) + JRST UNLST ;4 (UNLOCK FROM LIST) + JRST ULSOS ;5 (SOS, AOS) + JRST ULSTM ;6 (SETOM) + JRST ULAOSL ;7 (AOS,SOS LEFT HALF) + +UNSWTL: MOVE T,-1(P) + SETOM (T) + POPJ P, + +ULSTM: MOVE T,@-1(P) + SETOM (T) + POPJ P, + +UNLSWT: MOVE T,@-1(P) + MOVSI A,400000 + ANDCAM A,(T) + POPJ P, + +ULAOSL: MOVE T,@-1(P) + MOVSI A,-1 + ADDB A,(T) + JUMPGE A,CPOPJ + BUG ;OVER-SOS'ED + +ULAOS: MOVE T,@-1(P) + SOS (T) + POPJ P, + +UNLST: SETOM DLSRCH + MOVS T,@-1(P) + HLRM T,(T) + MOVSS T + TRNE T,-1 + HLLM T,(T) + SETZM DLSRCH + POPJ P, + +ULSOS: MOVE T,@-1(P) + AOS (T) + POPJ P, + +ULROUT: MOVE T,@-1(P) + TLNE A,200000 + JRST ULROU1 ;A LOSSET - MAY CLOBBER A OR T; USR INDEX IN U + HRRZM T,UPC(U) ;IT'S A FINSET, EXPECTS THE OLD METHOD OF CALL. + TLNE T,-1 + HLRM T,AC15S(U) +IFE KA10P,[ + MOVSI T,%PSPCU ;IT MIGHT TRY AN XCTR + HLLM T,UPC(U) +] ;IFE KA10P + TLOE U,200000 ;SIGNAL PC CLOBBERED + BUG ;PC TRIED TO BE CLOBBERED TWICE + POPJ P, + +ULROU1: JUMPGE U,(T) ;IF LOSSET, AND LSWPOPPING, + MOVE A,[B,,AC0S+B] + ADDI A,(U) ;PUT THE ACS IN THE AC0S, SINCE + BLT A,AC0S+H(U) ;THAT'S WHERE THEY'LL BE IF CALL LOSSET ROUTINE WHILE PCLSRING. + JRST (T) + +;FIND SWITCH POINTED TO BY WORD AFTER +;PUSHJ P,LSWREM AND UNLOCK IT +LSWREM: PUSH P,T + PUSH P,U + PUSH P,Q + MOVE U,USER + SKIPN U,LSWPR(U) + BUG + HRRZ Q,@-3(P) + MOVEI T,1 +LSWRM1: CAMN U,Q + JRST LSWRM2 + HRRZ U,1(U) + SKIPN U + BUG + AOJA T,LSWRM1 +LSWRM2: POP P,Q + POP P,U + PUSHJ P,LSWPON + AOS -1(P) + JRST POPTJ + +LSWDEL: PUSH P,U ;REMOVE SWITCH FROM HEAD OF LIST + MOVE U,USER ;DO NOT ATTEMPT TO UNLOCK IT + PUSH P,T + SKIPN T,LSWPR(U) + BUG + PUSHJ P,LSWDDD + JRST POPTUJ + +LSWDDD: PUSH P,Q + HRRZ Q,1(T) + HRRZM Q,LSWPR(U) + CAILE T,USRSTG + SETZM 1(T) + POP P,Q + POPJ P, + +;POP C(T)'TH FROB BACK +LSWPON: PUSHJ P,LSWBAK + PUSHJ P,LSWPPP + POPJ P, + +;DELETE C(T)'TH FROB BACK +LSWDLN: PUSHJ P,LSWBAK + PUSHJ P,LSWDDD + POPJ P, + +LSWBAK: PUSH P,U + MOVE U,USER + TLO U,400000 ;SIGNAL NOT PCLSR IN CASE OF LSWPPP + PUSH P,Q + MOVE Q,T + MOVEI T,LSWPR-1(U) + SOJE Q,LSWBA3 ;UNLOCKING FIRST FROB + MOVE T,1(T) + SOJG Q,.-1 +LSWBA2: MOVE Q,T + HRRZ T,1(T) + PUSH P,LSWPR(U) ;DON'T WORRY, YOU CAN'T GET PCLSR'ED JUST BELOW + XCT @-3(P) + HRRZ T,LSWPR(U) + HRRM T,1(Q) + POP P,LSWPR(U) + JRST POPQU1 + +LSWBA3: MOVE T,LSWPR(U) + XCT @-2(P) + JRST POPQU1 + +SUBTTL VARIOUS RETURNS + +PPBAJ1: POP P,B +POPAJ1: AOSA -1(P) +POPBAJ: POP P,B +POPAJ: POP P,A +CPOPJ: POPJ P, + +POPQJ: POP P,Q + POPJ P, + +POPBJ1: AOSA -1(P) +POPCBJ: POP P,C +POPBJ: POP P,B + POPJ P, + +POPJ3: AOS (P) +POPJ2: AOSA (P) +POPCJ1: POP P,C +POPJ1: AOSA (P) +POPCJ: POP P,C + POPJ P, + +POPJJ1: AOS -1(P) +POPJJ: POP P,J + POPJ P, + +POPUJ1: AOSA -1(P) +POPTUJ: POP P,T +POPUJ: POP P,U + POPJ P, + +POPTJ: POP P,T + POPJ P, + +POPTTJ: POP P,TT + POPJ P, + +POPWJ2: AOS -1(P) +POPWJ1: AOS -1(P) +POPWJ: POP P,W + POPJ P, + +PIONJ: CONO PI,PION + POPJ P, + +CKOCJ1: CONO PI,CLKON + JRST POPCJ1 + +CLKOJ1: AOS (P) +CLKONJ: CONO PI,CLKON + POPJ P, + +CKOPJ1: AOS (P) +CLKOPJ: CONO PI,CLKON + JRST LSWPOP + +IFN OMXP,[ +OMXONJ: CONO PI,OMXON + POPJ P, +] + +TTYOJ1: AOS (P) +TTYONJ: CONO PI,TTYON + POPJ P, + +IFN PTRP, PTRONJ:: PTPONJ:: +LPTONJ: CONO PI,LPTON + POPJ P, + +IFN NETP,NETOJ1: +UTCOJ1: AOSA (P) +UTCOAJ: POP P,A +IFN NETP,NETONJ: +UTCONJ: CONO PI,UTCON + POPJ P, + +POPQU1: AOS -2(P) +POPQUJ: POP P,Q + POP P,U + POPJ P, + +POP1J1: AOS -1(P) +POP1J: SUB P,[1,,1] + POPJ P, + +POP2J: SUB P,[2,,2] + POPJ P, + +POP3J1: AOS -3(P) +POP3J: SUB P,[3,,3] + POPJ P, + +POP4J: SUB P,[4,,4] + POPJ P, + +POP7J: SUB P,[2,,2] +POP5J: SUB P,[5,,5] + POPJ P, + +SUBTTL UUO PROCESSOR + +.IOT=UUOMIN +.OPEN=UUOMIN+1_27. +.OPER=UUOMIN+2_27. +.CALL=UUOMIN+3_27. +.USET=UUOMIN+4_27. +.BREAK=UUOMIN+5_27. +.STATUS=UUOMIN+6_27. +.ACCESS=UUOMIN+7_27. + +DEFINE GLOSYM X + IRP Y,,[X] + SQUOZE 4,.!Y + .!Y + TERMIN + TERMIN + +;REPEAT OVER USET NAMES FROM 0 TO 77. + DEFINE USTIRP A + IRPS X,,[UPC VAL TTY FLS UNAME JNAME MASK USTP +PIRQC INTB MEMT SV40 IPIRQ APIRQ SNAME PICLR +MARA MARPC UUOH UIND RUNT MSK2 IFPIR APRC +CNSL UTRP IIFPI AIFPI IMASK AMASK IMSK2 AMSK2 +JPC OPC RTMR HSNAME BCHN MPVA IDF1 ADF1 +IDF2 ADF2 DF1 DF2 OPTION 40ADDR TVCREG +TTST TTS1 TTS2 WHO1 WHO2 WHO3 SUPPRO TR1INS +TR2INS MBOX MBO1 EBOX EBO1 XUNAME XJNAME FTL1 FTL2] +A +TERMIN +TERMIN + +;REPEAT OVER USET NAMES 600 AND UP. + DEFINE USTIR1 A + IRPS X,,[PAGRAN PAGAHD SERVER] + A + TERMIN TERMIN + +;NOTE: OPER'S BELOW ARE 8 PER LINE +; USE UP ILUUO'S BEFORE ADDING TO END +; THE FOLLOWING SHOULD GO AWAY EVENTUALLY +; ITYI (=ITYIC) +; SETMSK (=SUSET) +; WSNAME (=SUSET) +; UPISET (=SUSET) +; RDSW (=DATAI) +; EOFC (OBSOLETE) +DEFINE OPRIRP A + IRPS X,,[ITYI LISTEN SLEEP SETMSK SETM2 DEMON CLOSE +UCLOSE ATTY DTTY IOPUSH IOPOP DCLOSE DSTOP RDTIME +RDSW GUN UDISMT GETSYS IPDP GETLOC SETLOC DISOWN +DWORD DSTEP GENSYM LOGOUT REALT WSNAME UPISET RESET +ARMOVE DCONTIN CBLK ASSIGN DESIGN RTIME RDATE HANG +EOFC IOTLSR RSYSI SUPSET PDTIME ARMRS UBLAT IOPDL +ITYIC MASTER VSTST NETAC NETS REVIVE DIETIM SHUTDN +ARMOFF NDIS FEED EVAL REDEF IFSET UTNAM UINIT +RYEAR RLPDTM RDATIM RCHST RBTC DMPCH SWAP MTAPE +GENNUM NETINT] + A +TERMIN +TERMIN + +DEFINE CALIRP A +IRPS X,,[DISMIS LOSE TRANAD VALUE UTRAN CORE TRAND +DSTART FDELE DSTRTL SUSET LTPEN VSCAN POTSET] +A TERMIN TERMIN + +;THESE ARE THE SYMBOLS USED BY MIDAS AND DDT. THEY ALSO +;EXIST IN SYS:ITS DEFS. +;SYMBOLS SHOULD BE LEFT IN CURRENT ORDER OR DDT WILL LOSE +SYSYMB: USTIRP [SQUOZE 44,.R!X + .IRPCNT] + SQUOZE 44,.RIOC + 100 + SQUOZE 44,.RIOS + 120 + SQUOZE 44,.RIOP + 140 + SQUOZE 44,.RPMAP + 200 + USTIR1 [SQUOZE 44,.R!X + 600+.IRPCNT] + USTIRP [SQUOZE 44,.S!X + 400000+.IRPCNT] + USTIR1 [SQUOZE 44,.S!X + 400600+.IRPCNT] + + GLOSYM [IOT,OPEN,OPER] + +DEFINE DEFSYM X/ +IRPS Z,,[X] +SQUOZE 44,Z +Z +.ISTOP +TERMIN TERMIN + +.INSRT BITS > + +EXPUNG DEFSYM + + ZZ=1 + OPRIRP [IFSN X,ILUUO,[.!X=.OPER ZZ + SQUOZE 4,.!X + .!X] + ZZ==ZZ+1] + +MXOPR==ZZ + + SQUOZE 4,.CALL + .CALL + +CALIRP [ +IFSN X,UNUSD,[ + .!X=.CALL .IRPCNT+1, + SQUOZE 4,.!X + .!X +]] + + GLOSYM [USET,BREAK,STATUS,ACCESS] +SYSYME==.-1 + +;THESE SYMBOLS ARE USED BY DDT, SO THE USER CAN OPEN .PIRQC, ETC. + ;BEGINNING FOR .GETSYS (USYMS) +SYSUSB: +USTIRP [ + SQUOZE 4,.!X + .IRPCNT +] + SQUOZE 4,.IOC + 100 + SQUOZE 4,.IOS + 120 + SQUOZE 4,.IOP + 140 + SQUOZE 4,.PMAP + 200 +USTIR1 [ + SQUOZE 4,.!X + 600+.IRPCNT +] +SYSUSE==.-1 ;END FOR .GETSYS (USYMS) + +;SIXBIT NAME TABLES FOR WHO LINE GENERATION. +;ALSO USED BY PEEK FOR PRINTING OUT JOBS' STATUS. + +OPRSXB: SIXBIT/OPER/ +OPRIRP [ +.1STWD SIXBIT/X/ +] + +CALSXB: SIXBIT/CALL/ +CALIRP [ +.1STWD SIXBIT/X/ +] + SIXBIT/UNUSD/ + +UUOSXB: +IRPS X,,IOT OPEN OPER CALL USET BREAK STATUS ACCESS +.1STWD SIXBIT/X/ +TERMIN +NUUOSX==.-UUOSXB + +;MACRO TO SAVE ACS AS APPROPRIATE FOR OUR CPU, LOAD UP U, +;CHECK VARIOUS ERROR CONDITIONS. + +DEFINE UUOSAV + CONSZ PI,77400 + BUG AWFUL,[UUO WITH PI IN PROGRESS] +IFN KA10P,[ + UMOVEM U,17 ;SAVE 17 + SKIPGE U,USER ;LOAD CURRENT USERS INDEX, + BUG AWFUL,[UUO IN NULL JOB] + UMOVEM T,16 ;SAVE LOC 16 FOR USER + MOVEI T,0 ;HA HA + XCTR XBW,[BLT T,15] ;SAVE REST OF ACS IN USERS SHADOW 0-15 +] ;KA10P +IFE KA10P,[ + SYSCTX + SKIPGE U,USER + BUG AWFUL,[UUO IN NULL JOB] + LDB T,[330300,,MUUOCX(U)] + CAIE T,1 + BUG AWFUL,[UUO WHILE IN AC BLK ],DEC,T +] ;IFE KA10P +TERMIN + +; UUO AND ILLOP TRAP HANDLER +; +;EITHER DISPATCHES TO APPROPRIATE UUO ROUTINE, +; RETURNS CONTROL TO USERS UUO ROUTINE, GOES TO ILLOP, USRTRP, OR USRIOT. +;CODE ON THIS PAGE IS INTERRUPTABLE AT ANY POINT + +;COME HERE TO RETURN A UUO TO THE USER. RESTORES USER ACS W THROUGH U ONLY. +USRUUO: CAIG U,LUBLK + BUG AWFUL,[RETURNABLE UUO FROM SYS OR CORE JOB,PC=],OCT,UUOH + MOVE W,UUOH + TLNN W,%PCUSR + BUG AWFUL,[RETURNABLE UUO FROM EXEC MODE,PC=],OCT,UUOH + HRRZ W,40ADDR(U) + MOVE P,USRPDL(U) ;IN CASE AN XCTR FAULTS. + XCTR XR,[HLRZ H,1(W)] + CAIE H,(JSR) ;ELSE OK ONLY IF OPCODE IN 41 IS 0 OR JSR. + JUMPN H,ILUUO ;THIS IS IN CASE USER IS HANDLING USER-UUO'S WITH PUSHJ + ;AND HIS UUOH ISN'T ABLE TO BE JSR'D TO. + XCTR XR,[HRRZ H,1(W)] + JUMPE H,ILUUO ;0 ISN'T ACCEPTABLE AS UUOH ADDRESS. + MOVE T,FORTY + UMOVEM T,(W) ;ALL IS LEGAL; PLANT UUO INTO USERS "40". + MOVE T,UUOH ;SIMULATE A JSR AT USER'S "41" + UMOVEM T,(H) + AOS H + HRRM H,UUOH ;SET TO RETURN TO USER AT FIRST INSTRUCTION OF UUO HANDLER +IFN KA10P,[ + MOVE U,[W,,W] + XCTR XBR,[BLT U,U] +] ;KA10P +ULEAVE: USRCTX ;SELECT USER MODE AC BLOCK IF NEC. + +EBLK + +;THE FOLLOWING BLOCK OF LOCATIONS IS SWITCHED WITH SOME USER VARS + +UEXIT: JRST 2,@XUUOH ;EXIT FROM UUO (FOR KL-10, POINTS TO APPROPRIATE + ;UPT LOC) + +CLUSAV: MOVEM U,AC17S ;CLOCK SAVE OF U + +IFE KA10P,[ +CLCXSV: DATAI PAG,CLCX ;CLOCK LEVEL CONTEXT SAVE +] ;IFE KA10P + +IFN KA10P,[ +XUUOH: 0 ;UUO AND ILLOP TRAP GETS HERE - UUOH0 MUST BE . + 1. +] ;KA10P + +UEXND:: ;END OF SWAPPED UEXIT BLOCK. + +BBLK + +UUOH0: UUOSAV +MUUOT1: SKIPGE UTRAPM(U) ;IF SUPERIOR WANTS TO CATCH UUOS, THIS IS FATAL INT. + JRST USRTRP + SKIPGE T,FORTY ;PICK UP THE UUO OR ILLOP + JRST USRIOT + CAML T,[UUOMIN] + CAML T,[UUOMAX] + JRST USRUUO ;NOT A SYSTEM CALL, GIVE TO USER +;DROPS THROUGH + ;DROPS IN +;HERE WITH UUO TO BE HANDLED BY SYSTEM IN T +ILLOP1: JUMPN U,UUOH1 + MOVEI Q,0 ;SAVE SYS JOB EXEC MODE LSWPR PNTR + EXCH Q,LSWPR + MOVEM Q,SLSWPR +UUOH1: SKIPE LSWPR(U) + JRST 4,. + MOVEM T,LSUUO(U) ;SAVE UUO FOR DEBUGGING PURPOSES + LSH T,-27. ;RIGHT JUSTIFY OP CODE + SKIPL UUODSP-UUOMIN_-27.(T) + JRST UUOTR3 + MOVE H,OPTION(U) + TLNE H,%OPDEC + JRST USRUUO +UUOTR3: SETZM SYSCVL(U) ;DIDN'T GET INTO SYSTEM VIA .CALL + MOVE P,USRPDL(U) ;SET UP USER PDL + HRRZ C,FORTY ;PICK UP EFFECTIVE ADDRESS OF UUO + LDB R,[270400,,FORTY] ;PICK UP AC FIELD OF UUO + MOVEM R,UUAC(U) ;SAVE AC FLD + PUSHJ P,@UUODSP-UUOMIN_-27.(T) ;DISPATCH ON UUO TYPE + JRST URET ;NORMAL RETURN (NON SKIP) +URETJ1: +IFE KA10P, MOVE U,USER ;(SINCE UUOH IS IN THE USER VARIABLES) + AOS UUOH ;UUO ROUTINE SKIPPED, AOS USER RETURN POINT +URET: MOVE U,USER + MOVE A,PIRQC(U) ;CHECK FOR RETURNING TO USER WITH PCLSR'ING FATAL + ; INT SET. + TDNE A,[BADBTS&#<%PIC.Z\%PIDIS>] ;A FEW BITS ARE FATAL BUT SET + ; ASYNCHRONOUSLY. + JRST [ HRRZ A,UEXIT ;INT SET, MAKE SURE UEXIT IS CLOBBERED + IFN KA10P, CAIE A,ONEPRO ;TO A LOCATION WHICH WILL CHECK PIRQC. + IFN KS10P, CAIE A,ONEPR4 + CAIE A,ONEFLS + BUG + JRST .+1] + SKIPE UMAPS(U) + PUSHJ P,MPLDZ + CAMN U,PCLUSR + SKIPG PCLDBM + JRST URET2 + SKIPL PCLNXT + JRST URPCL1 +URET2: SKIPE LSWPR(U) + BUG + JUMPN U,URETC + MOVEI T,0 ;RESTORE SYS JOB EXEC LSWPR + EXCH T,SLSWPR + MOVEM T,LSWPR +URET1: CONSO PI,1 + BUG ;RETURNING TO USER MODE WITH CLOCK OFF +IFN KA10P,[ + MOVEI U,0 + XCTR XBR,[BLT U,U] ;RESTORE USERS ACS FROM USERS SHADOW 0-17 +] ;KA10P + JRST ULEAVE + +URETC: REPEAT NULBLK/2,[ + SKIPN CONC LSWB,\<2*.RPCNT>,+1(U) + SKIPE CONC LSWB,\<2*.RPCNT+1>,+1(U) + BUG +] + REPEAT NULBLK&1,[ + SKIPE CONC LSWB,\,+1(U) + BUG +] + JRST URET1 + +URPCL1: SKIPN LSUUO(U) + JRST URET2 ;DIDN'T REALLY MISS MARK (DUE TO FINSET) + SETOM PCLNXT ;MISSED MARK, REINITIALIZE + SETZM PCLL + SETZM PCLHSH + JRST URET2 + +UUOTRO: MOVE T,FORTY + JRST UUOH1 + +USRIOT: MOVSI T,(UIOT) ;I/O INST TURNS INTO PSEUDO UUO TO DISPATCH ON + JRST ILLOP1 + +IFE KA10P,[ + +;HANDLE UUOS EXECUTED FOR TRAPS (PDL OV, ARITH OV, ONE PROCEED). +;MOST ARE AS USUAL, BUT OPCODE 0 IORM'S ADDRESS INTO PIRQC. +;NOTE: LOSER IS NOT PERMITTED TO USE OPCODE 0 - SEE USTR1I, ETC. + +MUUOTR: UUOSAV + MOVE T,FORTY + TLNE T,-1 + JRST MUUOT1 ;IF OPCODE ISN'T 0, TREAT UUO NORMALLY (STARTING A + ; ONE PROCEED) + MOVSI A,%PSTR1+%PSTR2 + ANDCAB A,UUOH ;TURN OFF TRAP FLAGS, GET PC + TRNN T,%PIARO + JRST MUUOT2 + TLNE A,%PCFOV ;DISTINGUISH FIXED AND FLOATING OVERFLOW. + TLO T,(%PIFOV) +MUUOT2: MOVE A,MSKST(U) + IOR A,[BADBTS] + AND T,A ;INTS SETTING WHICH AREN'T DISABLED + IORM T,PIRQC(U) + SKIPN PICLR(U) + TDZA A,A + SETCM A,IDF1(U) + IOR A,[BADBTS] ;MASK FOR INTS WHICH AREN'T DEFERRED + TDNE T,A + JRST ONEPR1 ;TAKE INT + JRST URET ;IGNORE INT + +MUUOEX: BUG AWFUL,[MUUO IN EXEC MODE, PC=],OCT,EPT+425 + ;UUO IN EXEC MODE NOT IN SYS JOB + +LUUOEX: 0 + BUG AWFUL,[LUUO IN EXEC MODE,PC=],OCT,LUUOEX + +ILLTRP: 0 + BUG AWFUL,[TRAP IN EXEC MODE,PC=],OCT,ILLTRP +] ;IFE KA10P + +IFN KA10P,[ +EBLK +60H: 0 ;TRAPS FROM 60 +BBLK +60H0: UUOSAV ;IF WE LOSE PROCESSOR HERE, 60 GETS COPIED INTO 40, + ; 60H IS COPIED INTO UUOH, AND UPC GETS MOVED INTO + ; UUOH0. +60HE: CONO PI,CLKOFF + MOVE T,60H + MOVEM T,UUOH + MOVE T,60 + MOVEM T,FORTY + CONO PI,CLKON + JRST MUUOT1 +] ;KA10P + +;COME HERE FROM UEXIT WHEN USER IS BEING PCLSR'ED +; KA10 - ALL USER ACS ARE IN MACHINE ACS AND IN UUOACS +; KL10 & KS10 - ALL USERS ACS ARE IN AC BLOCK 1 + +ONEFLS: CONO PI,CLKOFF ;TURN OFF CLOCK BREAKS + SYSCTX + MOVE U,USER ;GET INDEX OF CURRENT USER +ONEPR2: SKIPE T,RPCL(U) ;SKIP IF NO RPCLSRING OCCURING + JRST ONEFL2 ;RPCLSRING GOING ON +ONEPR1: MOVE U,USER ;GET INDEX OF CURRENT USER + CONO PI,CLKOFF ;TURN OFF CLOCK BREAKS + SKIPE LSWPR(U) + JRST 4,. + MOVEI T,AC0S(U) ;PUT USER ACS INTO SWAP OUT ACS + XCTR XBR,[BLT T,AC17S(U)] + MOVE T,UUOH + MOVEM T,UPC(U) ;SIMULATE JRST 2,@UUOH +IFN KA10P, MOVE T,[JRST 2,@UUOH] +IFE KA10P,[ + MOVSI T,(JRST 2,@) + HRRI T,UUOH +] ;IFE KA10P + MOVEM T,UEXIT ;RESTORE UEXIT + USRCTX + MOVE U,USER ;AS IF HAD RETURNED TO USER THEN CLKBRK + ;EXCEPT THAT AC'S ARE ALREADY STORED IN AC0S + JRST UFL6 ;RESCHEDULE, ETC + +ONEFL2: JUMPG T,[JRST 4,.] ;LOSEY LOSEY (SHOULD NOT TRY TO EXIT WHILE TRYING TO RPCLSR SOMEONE) + MOVE A,FLSINS(T) ;GET FLSINS OF USER SUPPOSEDLY RPCLSRING YOU + SUBI A,RPCL(T) ;HIS FLSINS SHOULD BE A SKIPE OF HIS RPCL + CAME A,[SKIPE] ;SKIP IF HE HAS THE RIGHT FLSINS + JRST 4,. ;LOSEY LOSEY + CLEARM FLSINS(T) ;ASSURE NO INTERRUPT + SETZM RPCL(U) ;ACS IN UUO ACS CLOCK OFF + AOS USTP(U) ;STOP SELF + SETZM RPCL(T) ;UNHANG LOSER RPCLSR'ING YOU + JRST ONEPR1 + +;ROUTINES TO GIVE THE RUNNING JOB AN INTERRUPT AND ABORT THE CURRENT INSTRUCTION + +TTYLOS: SKIPA T,[%PITTY] ;JOB WHOSE %TBINT IS SET TRIED TO USE ITS TTY WHEN DIDN'T OWN IT +IOADC: MOVEI T,%PIMPV ;I/O UUO MEMORY PROTECT VIOLATION + JRST UUOERR + +ABREAK: MOVEI T,%PIBRK ;.BREAK - INTERRUPT TO SUPERIOR +ILLOP4: IORM T,PIRQC(U) + JRST ONEPR1 + + RADIX 10. +IOCERF: ;ADDRESS OF FIRST IO CHANNEL ERROR +ZZ==NIOTER +IFG ZZ-9,ZZ==9 +REPEAT ZZ,CONC IOCER,\.RPCNT+MIOTER,: JSP T,IOCERX +IFG NIOTER-9,[REPEAT NIOTER-9,CONC IOCR,\.RPCNT+MIOTER+9,: JSP T,IOCERX +] +IFN 0, IOCER1: IOCER2: IOCER3: IOCER4: IOCER5: IOCER6: IOCER7: ;FOR @ +.ALSO IOCER8: IOCER9: IOCR10: IOCR11: IOCR12: IOCR13: IOCR14: + + RADIX 8 +IOCERX: CONSZ PI,77400 + JRST 4,. ;ERR WITH PI IN PROGRESS + SUBI T,IOCER9-9+1 + MOVE U,USER + HRRZ TT,UUAC(U) + DPB TT,[BCHPTR] ;STORE LAST CHNL IN ERROR + ADD TT,U + DPB T,[330600,,IOCHST(TT)] +IOCERR: MOVEI T,%PIIOC + JRST UUOERR + +AILUUO:: +ILUUO: SKIPA T,[%PIILO] ;ILLEGAL SYSTEM UUO +TRPDEV: ;ATTEMPTED USE OF TRAP DEVICE +USRTRP: MOVSI T,(%PITRP) ;SYSTEM UUO IN TRAP MODE + +UUOERR: MOVE U,USER + IORM T,PIRQC(U) ;GIVE USER INT BIT +IOADCR: MOVE U,USER + MOVE T,OPTION(U);PC CLOBBERED TO HERE IF MPV IN EXEC MODE - INTR OUT OF UUO + TLNN T,%OPOPC ;UNLESS USER HAS SAID NOT TO, + AOS UUOH ;UNDO SOS THAT PCLSR'ING WILL DO; PC SHOULD END UP -> AFTER UUO. +UUOER2: CONO PI,CLKON ;THERE HAD BETTER BE A CLASS 1 OR 2 INT. PENDING. + MOVE P,USRPDL(U) + SETZM SCHMNY ;CAUSE FULL SCHEDULE SO INTERRUPT WILL BE SEEN + JFCL ; (IT'S A CROCK TO HAVE TO DO THIS, BUT HARD TO FIX) + PUSHJ P,UFLS ;LET THE INTERRUPT PCLSR US. + JRST 4,. + +UUOER1: MOVE U,USER ;UUOERR ASSUMING %OPOPC + IORM T,PIRQC(U) + JRST UUOER2 + +IFN KA10P,[ +ILEXPF: CONO PI,CLKOFF ;GET HERE AFTER EXEC PAGE FAULT TAKEN ON XCTRI + SPM UPGML(U) + MOVSI A,1770 ;CLEAR FAULT REASON BITS + ANDCAM A,UPQUAN(U) + LPMR UPGML(U) + JRST ILUUO +] ;KA10P +IFE KA10P, ILEXPF==ILUUO ;NO CLEANUP NECESSARY + +;UUO DISPATCH + +;AT DISPATCH TIME, P HAS UPDL, C HAS RH OF 40 +;R HAS AC FIELD OF UUO, U HAS USER INDEX + +UUODSP: SETZ AIOT ;SETZ FLAGS UUO'S TO REFLECT TO USER WHEN %OPDEC OPTIONS + SETZ AOPEN ;IN EFFECT. THEY ARE THE UUOS WHICH OVERLAP DEC + AOPER + ACALL + AUSET + ABREAK + ASTATUS + SETZ AACCESS + SETZ AUIOT +IF2,IFN _-27.+UUODSP-.+1,.ERR LOSE AT UUODSP + +;.CALL IOT +NIOT: CAIL W,3 ;SET IOTBTS TO USER'S 3RD ARG, OR TO 0. + SETZ C, + MOVEM C,IOTBTS(U) + HRRZ C,B ;ADDRESS OF 2ND ARG + SKIPGE SYSCVL(U) + SKIPA C,[SETZ] ;USING OUTPUT ARG INSTEAD OF INPUT, FOR UNIT INPUT MODE + CAIL W,2 + AOSA (P) ;GOING TO SUCCEED NOW + JRST OPNL30 ;NOT ENOUGH ARGS + JRST AIOT1 + +;.IOT +AIOT: SETZM CTLBTS(U) + SETZM IOTBTS(U) + ADDI R,IOCHNM(U) ;GET IOCHNM WD ADDR IN R. +AIOT1: MOVE A,U + IDIVI A,LUBLK + SKIPE B + BUG + HLRZ A,(R) ;PICK UP LEFT HALF (DEVICE DEPENDENT) + HRRZ B,(R) ;PICK UP RIGHT HALF (INDEX INTO IOTTB, ETC.) + MOVE D,IOTTB(B) ;GO TO ROUTINE FOR PARTICULAR DEV AND MODE + TLNE D,%IOTOT+%IOTBK+%IOTSP ;BUT FOR "NORMAL" UNIT MODE INPUT, SPECIAL: + JRST (D) + XCTR XRW,[MOVES (C)] ;MAKE SURE XCTR XW, BELOW WON'T PCLSR. + PUSH P,C + PUSHJ P,(D) ;CALL IOT ROUTINE, EXPECTING VALUE IN W. +AIOT3: JRST AIOT2 ;NOTE AIOT3 MAY BE CHECKED FOR ON PDL. + JRST AIOT2 + +AIOT2: POP P,C + SKIPGE C + SKIPA A,W ;RETURNING IN NEW SYSTEM-CALL STYLE + UMOVEM W,(C) + POPJ P, + +;RANDOM ACCESS + +AACCES: HRRZ A,UUAC(U) + UMOVE B,(C) + MOVE T,['ACCESS] + MOVEM T,LSCALL(U) ;IN CASE PASSED TO JOB DEVICE + MOVEI W,2 + PUSHJ P,NACCES + JRST IOCER8 ;FOR .ACCESS, SIGNAL FAILURE WITH IOC ERROR. + POPJ P, ;ONLY POSSIBLE FAILURE IS CHANNEL NOT OPEN. + +NACCES: MOVEI T,AIOCAL ;GET ,, IN R + MOVSI J,NACCE1 + JRST CHNDCD + +NACCE1: TLNN R,%CLSQ\%CLSU\%CLSFU + JRST OPNL34 + HRRM B,IOCHST-IOCHNM(R) ;STORE USR .ACCESS POINTER + TLNN R,%CLSQ + JRST POPJ1 ;NOT DISK + HLRZ I,(R) + MOVEM B,QRADAD(I) ;STORE ACCESS POINTER FOR DSK + MOVSI D,%QAACC + IORM D,QSRAC(I) ;SET ADR HAS BEEN HACKED FLAG + JRST POPJ1 + +;SIOT SYMBOLIC SYSTEM CALL - IOT A STRING. +; 1ST ARG CHANNEL NUMBER. +; 2ND ARG BYTE POINTER +; 3RD ARG STRING LENGTH +; 4TH (OPTIONAL) ARG DEVICE-INDEPENDENT CONTROL BITS +; CTLBTS DEVICE DEPENDENT CONTROL BITS + +NSIOT: TLNN B,1000 ;OBJECT IF B.P. OR COUNT IS IMMEDIATE. + TLNE C,1000 + JRST OPNL33 + CAIGE W,4 + SETZ D, + MOVEM D,IOTBTS(U) + MOVE D,IOTTB(H) + TLNE D,%IOTBK+%IOTSP ;SIOT ALLOWED ONLY ON UNIT MODE CHANNELS. + JRST OPNL12 ;"MODE NOT AVAILABLE". + XCTR XRW,[MOVES A,(B)] ;ENSURE BYTE POINTER WRITABLE + TLNE A,(@) ;CAN'T HACK BYTE POINTER WITH INDIRECT ADDRESSING + JRST OPNL33 ;MEANINGLESS ARGS + TLNE A,17 + PUSHJ P,NSIOT9 ;HACK INDEXING + XCTR XRW,[MOVES A,(C)] ;ENSURE BYTE COUNT WRITABLE + JUMPLE A,POPAJ1 ;0 BYTES TO BE XFERED => SUCCEED IMMEDIATELY. + HLRZ A,(R) + MOVE TT,B ;IN CASE SPECIAL ROUTINE WANTS TO CALL SIOKT + TLNE D,%IOTBP ;IF THERE'S A SPECIAL DEVICE ROUTINE FOR SIOT, + JRST -1(D) ;GO TO IT. +;THIS CALL IS LEGAL AND ORDINARY. LOOP, CALLING THE UNIT MODE ROUTINE. +NSIOT1: PUSH P,A + PUSH P,B + PUSH P,C + PUSH P,D ;PUT ALL IMPORTANT INFO ON STACK FOR MAIN LOOP + HRRZS (P) ;TO LOOK AT. + PUSH P,R + TLNN D,%IOTOT + JRST NSIOIL ;INPUT AND OUTPUT PART HERE +NSIOOL: UMOVE A,@-3(P) + IBP A ;THIS HAIR IS TO AVOID INCREMENTING THE USER'S COPY + UMOVE D,(A) ;OF THE BYTE POINTER BEFORE THE BYTE HAS BEEN + HRRI A,D ;FINALLY TAKEN WITH NO POSSIBILITY OF PCLSR'ING OUT. + LDB D,A ;CAN'T USE XCTR XR,[LDB D,A] BECAUSE ON THE KA10 + MOVE C,[SETZ D] ;THAT WOULD USE THE LOSER'S AC A. + MOVE R,(P) + MOVE A,-4(P) ;SET UP ARGS FOR IOT ROUTINE; C HAS ADDR OF VALUE. + PUSHJ P,@-1(P) ;CALL THE IOT ROUTINE. + XCTR XRW,[IBP @-3(P)] ;NOW STEP THE B.P. AND COUNT. + XCTR XRW,[SOS A,@-2(P)] + JUMPG A,NSIOOL + JRST NSIOTX + +NSIOIL: UMOVE A,@-3(P) + IBP A ;MAKE SURE NO FAULT IDPB'ING THE BYTE + XCTR XRW,[MOVES (A)] + MOVE R,(P) ;NOW GET THE ARGS FOR THE IOT ROUTINE, + MOVE A,-4(P) + PUSHJ P,@-1(P) ;AND CALL IT, WITH VALUE COMING IN W. + JRST NSIOI3 ;NO SKIP => WE WIN. + JRST NSIOTX ;1 SKIP => THERE'S NO INPUT; RETURN WITHOUT STEPPING B.P. + ;2 SKIPS => THIS BYTE IS THE LAST ONE AVAILABLE. + XCTR XBYTE,[IDPB W,@-3(P)] + XCTR XRW,[SOS @-2(P)] + JRST NSIOTX + +NSIOI3: XCTR XBYTE,[IDPB W,@-3(P)] + XCTR XRW,[SOS A,@-2(P)] + JUMPG A,NSIOIL +NSIOTX: SUB P,[5,,5] + JRST POPJ1 + +NSIOT9: EXCH A,R ;INDEXED BYTE POINTER, EVAL INDEX ONCE AND WRITE BACK + PUSHJ P,ASCIND + EXCH A,R + UMOVEM A,(B) + POPJ P, + ; +; ROUTINES TO SIMULATE SOME I/O INSTRUCTIONS WHEN EXECUTED BY USER + +IFE KS10P,[ ; KS10 will never have any devices so we might as well punt + ; this sham right from the start. + +AUIOT: MOVE I,FORTY ;GET I/O INST + ANDI R,7 ;GET IOT TYPE FIELD + LDB J,[320700,,FORTY] + LDB D,[420200,,IOTTYP(R)] + JRST @IOTTYP(R) ;DISPATCH ON TYPE + +IOTTYP: 000000,,IOTTY3 ;BLKI + 000000,,IOTTY2 ;DATAI + 200000,,IOTTY3 ;BLKO + 200000,,IOTTY2 ;DATAO + 600000,,IOTTY2 ;CONO + 400000,,IOTTY2 ;CONI + 400000,,IOTTY1 ;CONSZ + 400000,,IOTTY1 ;CONSO + +IOTTY1: CAIN J,177 ;IF EQ INST WAS 7777XX,,XXXXXX + JRST ILUUO ;USER HAS EXECUTED A SMALL NEGATIVE NUMBER + JRST IOTTY2 + +IOTTY3: +IFN KL10P,[ + MOVE C,DCHNTB(J) + TRNE C,10000 + JRST IOTTY2 ;SPECIAL BLKI THAT IS TREATED LIKE DATAI +] + TLO I,40 ;BLOCK TYPE, TURN ON BIT TO CONVERT TO UNIT + UMOVE C,(I) ;GET BLOCK POINTER + ADD C,[1,,1] ;ADVANCE + TLNE C,-1 ;SKIP IF OVERFLOW + AOS (P) ;CAUSE RETURN TO SKIP + UMOVEM C,(I) ;STORE BACK + HRR I,C ;MODIFY INST ADR TO RH OF BLOCK POINTER +IOTTY2: SKIPL C,DCHNTB(J) + JRST IOTTYA + LSH C,19.(D) + SKIPL C + JRST ILUUO +IOTTYB: XCTR XRW,I ;DO IOT + POPJ P, ;NORMAL RETURN + JRST POPJ1 ;IOT SKIPPED RETURN + +IOTTYA: SKIPGE DCHNTC(J) + JRST ILUUO ;SUSPICIOUS DEVICE + JRST IOTTYB + +] ;IFE KS10P + +IFN KS10P, AUIOT==:ILUUO ; For now. + +IFN 0,[ ; Simple IO instruction simulating for the KS should look + ; like this. Unfortunately XCTR XRW,[APRID 100] clobbers + ; exec location 100. Further investigation is needed + ; before figuring out how to deal with this. + +AUIOT: LDB R,[271500,,FORTY] ; Get opcode and AC. + CAIE R,APRID_-27 ; For now this is the only instruction we + ; simulate on the KS + JRST ILUUO + XCTR XRW,FORTY ; Do it + POPJ P, ; Return normally + JRST POPJ1 ; It skipped (well APRID can't, but perhaps + ; someday something else will) +] ;IFN 0 + +SUBTTL .SUSET, .USET, .CALL USRVAR + +;COMMON CODE FOR USRVAR, TTYVAR, ETC. SYMBOLIC SYSTEM CALLS +;PUSHJ P,VARCAL WITH FIRST ARG DECODED INTO H,I,J,R; B,C,W,U SET UP AS IN .CALL +;NOTE B IS A POINTER TO THE SECOND ARG (IN BLOCK MODE IS WRITTEN BACK) +;POPJS (OR PUSHJS IN THE CASE OF BLOCK MODE) BACK WITH E CONTAINING +;VARIABLE SPEC, D INPUT DATA, W INSTRUCTION TO HACK IT (0 TO READ INTO A, +;OTHERWISE OP D, WITH RH CLEAR WHERE OP IS MOVEM, ANDCAM, ADDM, ETC.) + +VARCAL: HRRZ E,B ;USE 2ND ARG AND NUM OF ARGS TO DETERMINE TYPE OF OPERATION + TLNE B,1000 + JRST VARCA1 ;IMMEDIATE 2ND ARG + UMOVE E,(B) ;GET VALUE OF 2ND ARG + TLC E,777000 + TLCN E,777000 + JRST VARCBL ;BLOCK MODE (2ND ARG LOOKS LIKE AOBJN POINTER) +VARCA1: EXCH D,C ;D GETS 3RD ARG, INPUT DATA + CAIL W,4 + JRST VARCA2 ;JUMP IF IMMEDIATE INSTRUCTION MODE + CAIGE W,3 ;SKIP IF WRITING + TDZA W,W ;W 0 FOR READING + MOVSI W,(MOVEM D,) ;SIMPLE CASE OF WRITING (SEE VARCBL FOR HAIR) + POPJ P, ;CALLER WILL DO OPERATION AND POPJ1 OR OPEN-LOSS + +VARCA2: ADD P,[2,,2] ;IMMEDIATE INSTRUCTION MODE. MAKE STACK SAME AS AT VARCAL. + TLNN C,-1 ;E HAS VARIABLE SPEC + MOVSS C ;C GETS INSTRUCTION + PUSHJ P,VARCA3 ;PERFORM THE INSTRUCTION + JRST POP3J1 ;TAKE GOOD RETURN FROM THE CALL + +VARCBL: PUSH P,J ;BLOCK MODE. SAVE J WHICH SOME SUSETS CLOBBER + PUSH P,B ;SAVE POINTER TO AOBJN POINTER TO SPEC,INSN PAIR LIST + XCTR XRW,[MOVES B,@(P)] ;GET AOBJN POINTER, TEST WRITEABILITY +VARCB1: UMOVE E,(B) ;GET VARIABLE SPEC + UMOVE C,1(B) ;GET "INSTRUCTION" + MOVE J,-1(P) ;GET DECODED FIRST ARG OR WHATEVER (SOME USRVAR ROUTINES CLOBBER J) + PUSHJ P,VARCA3 ;PERFORM THE INSTRUCTION + MOVE B,[2,,2] + XCTR XRW,[ADDB B,@(P)] ;ADVANCE AOBJN POINTER + JUMPL B,VARCB1 ;MORE STUFF TO DO + JRST POP3J1 ;POINTER COUNTED OUT, POP B, J, PUSHJ TO VARCAL + +VARCA3: EXCH C,R ;HERE TO PERFORM INSTRUCTION IN C + TLNE R,37 + PUSHJ P,ASCIND ;EVALUATE INSTRUCTION'S EFFECTIVE ADDRESS + EXCH C,R + LDB B,[410300,,C] ;GET MAJOR PDP10 OPCODE CLASS + JRST @.+1(B) + VARCBE ;0 UUO ILLEGAL + VARCBE ;1 FP/BYTE ILLEGAL + VARCB2 ;2 MOVE/ADD/SUB + VARCBE ;3 CAM ETC. RESERVED FOR .HANGING IN THE FUTURE + VARCB4 ;4 BOOLE + VARCBE ;5 HWT ILLEGAL + VARCB6 ;6 TEST + VARCBE ;7 IOT ILLEGAL + +VARCBE: SUB P,[4,,4] ;POP PUSHJ TO VARCA3, B, J, PUSHJ TO VARCAL + JRST OPNL33 ;BAD ARG + +VARCB6: TLNE C,006000 ;TEST INSTRUCTION - SKIP IF NO SKIP + JRST VARCBE ;SKIPPING TESTS RESERVED FOR FUTURE .HANGS + TLNE C,010000 ;SKIP IF IMMEDIATE + XCTR XR,[SKIPA D,(C)] + HRRZ D,C + TLNE C,001000 ;SKIP IF TDX OR TRX + MOVSS D ;TSX OR TLX + LDB C,[370200,,C] ;GET MODIFICATION TYPE + XCT (C)[JRST VARCBE ;NO MODIFICATION OBVIOUSLY AN ERROR + MOVSI W,(ANDCAM D,) ;TXZ + MOVSI W,(XORM D,) ;TXC + MOVSI W,(IORM D,)] ;TXO + JRST VARCBA + +VARCB4: TLNE C,002000 ;BOOLEAN INSTRUCTION - OK IF RESULT TO AC + JRST VARCBE + TLNN C,001000 ;SKIP IF IMMEDIATE + XCTR XR,[SKIPA D,(C)] + HRRZ D,C + HLLZ W,C ;SET UP OPCODE TO HAVE A+M EXCHANGED + TLZ W,003777 ;AND RESULT TO BE SENT TO MEMORY + TLCE W,030000 + TLCE W,030000 + TLC W,030000 + TLO W,(<002000,,> D,) + JRST VARCBA + +VARCB2: SETZB W,D ;MOVE/ADD/SUB GROUP + HLRZ B,C + CAIN B,(MOVEM) + JRST VARCBB ;SIMPLY READING + TLNE C,002000 + JRST VARCBE ;RESULT MUST BE TO AC + TLZ C,(0 17,) ;CHANGE AC FIELD TO D + TLO C,(0 D,) + TLNE C,060000 ;SKIP IF MOVE GROUP + JRST VARCB5 + XCTR XR,C ;FETCH OPERAND, DO MODIFICATION IF CALLED FOR (MOVN) + MOVSI W,(MOVEM D,) ;OPERATION WILL BE SIMPLE STORE + JRST VARCBA + +VARCB5: TLC C,070000 + TLCE C,070000 + JRST VARCBE ;NOT ADD/SUB + XCTR XR,C ;ADD TO/SUBTRACT FROM ZERO IN D + MOVSI W,(ADDM D,) ;DROP INTO VARCBA + +;HERE WITH E, W, D ALL SET UP FOR WRITING. +VARCBA: PUSHJ P,@-3(P) ;CALL BACK TO CALLER OF VARCAL + JRST POP4J ;LOST, POP PUSHJ TO VARCA3, B, J, VARCAL, TAKE ERR RETURN + POPJ P, ;WON, RETURN FROM VARCA3 + +;HERE WITH E AND W SET UP FOR READING. +VARCBB: PUSH P,C ;SAVE ADDRESS TO BE READ INTO + XCTR XRW,[MOVES (C)] ;NO FAULT. INSURANCE OF WRITEABILITY. + PUSHJ P,@-4(P) ;GET VALUE OF VARIABLE INTO A + JRST POP5J ;LOST POP C, VARCA3, B, J, VARCAL, TAKE ERR RETURN TO USER + POP P,C ;WON, STORE RESULT INTO USER + UMOVEM A,(C) + POPJ P, ;AND RETURN FROM VARCA3 + +USETBT: 420200,,USETL(E) ;BYTE POINTER TO UENTRY FIELD A + 400200,,USETL(E) ; " B + 200200,,USETL(E) ; " C + 160200,,USETL(E) ; " D + +USETRL: 221600,,USETL(E) ;BYTE POINTER TO UENTRY FIELD E + 001600,,USETL(E) ; " F + +;IN EACH UENTRY ENTRY: A IS THE METHOD FOR USET READ +; B IS THE METHOD FOR SUSET READ +; C IS THE METHOD FOR USET SET +; D IS THE METHOD FOR SUSET SET +; E & F ARE USED BY THE METHODS AS LISTED BELOW +;METHOD 0 = ILLEGAL MODE +;METHOD 1 = USE F AS RELATIVE LOC OF VAR +;METHOD 2 = USE E AS ROUTINE TO TRANSFER TO +;METHOD 3 = USE F AS ROUTINE TO TRANSFER TO + +DEFINE UENTRY A,B,C,D,E,F + ZZ==.SUCCESS + A_20+B_16+E,,C_20+D_16+F + IF2 [ + IFN 777774&,[PRINTX /UENTRY A,B,C,D TOO BIG +/] IFN 740000&,[PRINTX /UENTRY E,F TOO BIG +/] IFSE [E!F],[PRINTX /UENTRY E,F NULL +/] ] + .SUCCESS==ZZ + TERMIN + +USETL: UENTRY 1,1,2,0,UPCSET,UPC-USRSTG ;.UPC + UENTRY 1,1,1,1,,VALUE-USRSTG ;.VAL + UENTRY 3,3,2,2,USTTY,URTTY ;.TTY + UENTRY 1,1,0,0,,FLSINS-USRSTG ;.FLS + UENTRY 1,1,0,2,UUNAME,UNAME-USRSTG ;.UNAME + UENTRY 1,1,2,2,UJNAME,JNAME-USRSTG ;.JNAME + UENTRY 1,1,2,2,USMASK,MSKST-USRSTG ;.MASK + UENTRY 1,1,2,0,USTOP,USTP-USRSTG ;.USTP + + UENTRY 1,1,2,2,USPIRQ,PIRQC-USRSTG ;.PIRQC + UENTRY 2,2,0,0,UGSUPR, ;.INTB + UENTRY 1,1,2,2,USMEMT,HUSRAD-USRSTG ;.MEMT + UENTRY 1,1,0,0,,SV40-USRSTG ;.SV40 +REPEAT 2,UENTRY 1,1,2,2,IAPIRQ,PIRQC-USRSTG ;.IPIRQ/.APIRQ + UENTRY 1,1,2,2,USYNST,USYSNM-USRSTG ;.SNAME + UENTRY 1,1,2,2,UPISET,PICLR-USRSTG ;.PICLR + + UENTRY 2,2,3,3,URMAR,USMAR ;.MARA + UENTRY 1,1,1,1,,UMARPC-USRSTG ;.MARPC + UENTRY 1,1,0,0,,SUUOH-USRSTG ;.UUOH + UENTRY 2,2,0,0,UINDEX, ;.UIND + UENTRY 1,2,0,0,UTRNTR,UTRNTM-USRSTG ;.RUNT + UENTRY 1,1,2,2,USMSK2,MSKST2-USRSTG ;.MSK2 + UENTRY 1,1,2,2,USIFPI,IFPIR-USRSTG ;.IFPIR + UENTRY 1,1,0,0,,APRC-USRSTG ;.APRC + + UENTRY 3,3,0,0,,URCNSL ;.CNSL + UENTRY 2,0,3,0,RUTRAP,SUTRAP ;.UTRP +REPEAT 2,UENTRY 1,1,2,2,IAIFPI,IFPIR-USRSTG ;.IIFPI/.AIFPI +REPEAT 2,UENTRY 1,1,2,2,IAMASK,MSKST-USRSTG ;.IMASK/.AMASK +REPEAT 2,UENTRY 1,1,2,2,IAMSK2,MSKST2-USRSTG ;.IMSK2/.AMSK2 + + UENTRY 3,3,2,2,UJPCS,UJPCR, ;.JPC + UENTRY 2,2,0,0,UROPC, ;.OPC + UENTRY 1,1,1,1,,RTIMER-USRSTG ;.RTMR + UENTRY 1,1,1,1,,HSNAME-USRSTG ;.HSNAME +;IFN KL10P,UENTRY 1,1,1,1,,ULSPBR-USRSTG ;.LSPBR +;.ELSE UENTRY 1,1,1,1,,SRN3-USRSTG + UENTRY 2,2,3,3,RUBCHN,SUBCHN, ;.BCHN + UENTRY 2,2,0,0,MPVARD ;.MPVA +REPEAT 2,UENTRY 1,1,2,2,IADF1,IDF1-USRSTG ;.IDF1, .ADF1 + +REPEAT 2,UENTRY 1,1,2,2,IADF2,IDF2-USRSTG ;.IDF2, .ADF2 + UENTRY 1,1,2,2,USDF1,IDF1-USRSTG ;.DF1 + UENTRY 1,1,2,2,USDF2,IDF2-USRSTG ;.DF2 + UENTRY 1,1,1,1,,OPTION-USRSTG ;.OPTION + UENTRY 1,1,1,1,,40ADDR-USRSTG ;.40ADDR +IFE N11TYS, UENTRY 1,1,1,1,,SRN3-USRSTG ;.TVCREG - JOB'S CONSOLE REGISTER CONTENTS +IFN N11TYS, UENTRY 1,1,1,2,STVCRG,TVCREG-USRSTG + UENTRY 1,1,1,1,,TTSTSV+2-USRSTG ;.TTST + + UENTRY 1,1,1,1,,TTSTSV-USRSTG ;.TTS1 + UENTRY 1,1,1,1,,TTSTSV+1-USRSTG ;.TTS2 + UENTRY 1,1,1,1,,UWHO1-USRSTG ;.WHO1 + UENTRY 1,1,1,1,,UWHO2-USRSTG ;.WHO2 + UENTRY 1,1,1,1,,UWHO3-USRSTG ;.WHO3 + UENTRY 3,3,0,0,,RUSUPP ;.SUPPRO +IFN KA10P, UENTRY 2,2,0,0,URTR1I ;.TR1INS +IFE KA10P, UENTRY 1,1,1,1,,TR1INS-USRSTG +IFN KA10P, UENTRY 2,2,0,0,URTR2I ;.TR2INS +IFE KA10P, UENTRY 1,1,1,1,,TR2INS-USRSTG + +IFE KL10P,[ +REPEAT 4,UENTRY 1,1,0,0,,SRN3-USRSTG +] ;IFE KL10P +IFN KL10P,[ + UENTRY 1,0,0,0,,MBOXCT-USRSTG ;.MBOX + UENTRY 1,0,0,0,,MBOXCT+1-USRSTG ;.MBO1 + UENTRY 1,0,0,0,,EBOXCT-USRSTG ;.EBOX + UENTRY 1,0,0,0,,EBOXCT+1-USRSTG ;.EBO1 +] ;KL10P + UENTRY 1,1,1,1,,XUNAME-USRSTG ;.XUNAME (USER'S REAL NAME) + UENTRY 1,1,1,1,,XJNAME-USRSTG ;.XJNAME + UENTRY 1,1,1,1,,SRN4-USRSTG ;.FTL1 + UENTRY 1,1,1,1,,SRN5-USRSTG ;.FTL2 + UENTRY 1,1,1,1,,PAGRAN-USRSTG ;.PAGRANGE + UENTRY 1,1,1,1,,PAGAHD-USRSTG ;.PAGAHEAD + UENTRY 2,2,3,3,URSERV,USSERV ;.SERVER +MXVAL==.-USETL +EXPUNGE UENTRY ;NO MORE UENTRY'S + +MXVAL2==.RADIX 2,CONC [.LENGTH/]\MXVAL-1,/ ;BASE 2 LOG OF TABLE SIZE + +;SIXBIT TABLE OF USER VARIABLE NAMES. MUST BE IN CORRECT ORDER, +;SAME AS SYSCTB. + +USETTB: SIXBIT/ADF1/ + SIXBIT/ADF2/ + SIXBIT/AIFPIR/ + SIXBIT/AMASK/ + SIXBIT/AMSK2/ + SIXBIT/APIRQC/ + SIXBIT/APRC/ + SIXBIT/BCHN/ + SIXBIT/CNSL/ + SIXBIT/DF1/ + SIXBIT/DF2/ + SIXBIT/EBO1/ + SIXBIT/EBOX/ + SIXBIT/FLS/ + SIXBIT/FTL1/ + SIXBIT/FTL2/ + SIXBIT/HSNAME/ + SIXBIT/IDF1/ + SIXBIT/IDF2/ + SIXBIT/IFPIR/ + SIXBIT/IIFPIR/ + SIXBIT/IMASK/ + SIXBIT/IMSK2/ + SIXBIT/INTB/ + SIXBIT/IPIRQC/ + SIXBIT/JNAME/ + SIXBIT/JPC/ + SIXBIT/MARA/ + SIXBIT/MARPC/ + SIXBIT/MASK/ + SIXBIT/MBO1/ + SIXBIT/MBOX/ + SIXBIT/MEMT/ + SIXBIT/MPVA/ + SIXBIT/MSK2/ + SIXBIT/OPC/ + SIXBIT/OPTION/ + SIXBIT/PAGAHE/ + SIXBIT/PAGRAN/ + SIXBIT/PICLR/ + SIXBIT/PIRQC/ + SIXBIT/RTMR/ + SIXBIT/RUNT/ + SIXBIT/SERVER/ + SIXBIT/SNAME/ + SIXBIT/SUPPRO/ + SIXBIT/SV40/ + SIXBIT/TR1INS/ + SIXBIT/TR2INS/ + SIXBIT/TTS1/ + SIXBIT/TTS2/ + SIXBIT/TTST/ + SIXBIT/TTY/ + SIXBIT/TVCREG/ + SIXBIT/UIND/ + SIXBIT/UNAME/ + SIXBIT/UPC/ + SIXBIT/USTP/ + SIXBIT/UTRP/ + SIXBIT/UUOH/ + SIXBIT/VAL/ + SIXBIT/WHO1/ + SIXBIT/WHO2/ + SIXBIT/WHO3/ + SIXBIT/XJNAME/ + SIXBIT/XUNAME/ + SIXBIT/40ADDR/ +IFN .-USETTB-MXVAL, .ERR USETTB INCONSISTENT WITH USETL +REPEAT 1_--1, -1 ;PAD TO POWER OF 2 WITH PLUS INFINITY + +;THE FOLLOWING TABLE IS PARALLEL TO USETTB AND GIVES THE NUMERIC USET CODE +;WHICH SHOULD BE IN THE RANGE 0 - 77 OR 600 AND UP. +USETBN: 47 ;.ADF1 + 51 ;.ADF2 + 33 ;.AIFPI + 35 ;.AMASK + 37 ;.AMSK2 + 15 ;.APIRQ + 27 ;.APRC + 44 ;.BCHN + 30 ;.CNSL + 52 ;.DF1 + 53 ;.DF2 + 73 ;.EBO1 + 72 ;.EBOX + 3 ;.FLS + 76 ;.FTL1 + 77 ;.FTL2 + 43 ;.HSNAME + 46 ;.IDF1 + 50 ;.IDF2 + 26 ;.IFPIR + 32 ;.IIFPI + 34 ;.IMASK + 36 ;.IMSK2 + 11 ;.INTB + 14 ;.IPIRQ + 5 ;.JNAME + 40 ;.JPC + 20 ;.MARA + 21 ;.MARPC + 6 ;.MASK + 71 ;.MBO1 + 70 ;.MBOX + 12 ;.MEMT + 45 ;.MPVA + 25 ;.MSK2 + 41 ;.OPC + 54 ;.OPTION + 601 ;.PAGAHE + 600 ;.PAGRAN + 17 ;.PICLR + 10 ;.PIRQC + 42 ;.RTMR + 24 ;.RUNT + 602 ;.SERVER + 16 ;.SNAME + 65 ;.SUPPRO + 13 ;.SV40 + 66 ;.TR1INS + 67 ;.TR2INS + 60 ;.TTS1 + 61 ;.TTS2 + 57 ;.TTST + 2 ;.TTY + 56 ;.TVCREG + 23 ;.UIND + 4 ;.UNAME + 0 ;.UPC + 7 ;.USTP + 31 ;.UTRP + 22 ;.UUOH + 1 ;.VAL + 62 ;.WHO1 + 63 ;.WHO2 + 64 ;.WHO3 + 75 ;.XJNAME + 74 ;.XUNAME + 55 ;.40ADDR +IFN .-USETBN-MXVAL, .ERR USETBN INCONSISTENT WITH USETL + +;.CALL USRVAR HACK USER VARIABLES. +;ARG 1 - SPEC +;ARG 2 - AOBJN PNTR FOR BLOCK MODE OR 0,,USER-VAR-NUMBER OR SIXBIT/USER-VAR-NAME/ +;ARG 3 - DATA IF WRITING AND NOT IN BLOCK MODE. (OPTIONAL) +;ARG 4 - IMMEDIATE INSTRUCTION, OVERRIDES ARG 3. (OPTIONAL) +;VAL 1 - DATA IF READING AND NOT IN BLOCK MODE + +NUSRVA: MOVE J,A ;DECODE FIRST ARG + JSP T,NCORUI ;GET JOB AND LOCK ITS DIELOK + JRST NUSRV0 ;DEFINITELY WRITEABLE + JSP T,NCORWR ;NOT SURE, CHECK FURTHER + TLO J,(SETZ) ;SET WRITE PROTECT BIT +NUSRV0: +IFN PDP6P,[ + TRNE J,400000 + PUSHJ P,NULSET +] + PUSHJ P,NUSRV5 ;DO IT + POPJ P, ;LOST + JRST LSWPJ1 ;WON, UNLOCK DIELOK AND TAKE SUCCESS RETURN + +NUSRV5: PUSHJ P,VARCAL ;DECODE ARGS, HACK BLOCK MODE, SET E, W, D. +NUSRV3: SETZB B,I ;ENTER HERE FROM .USET AND .SUSET + TLNN E,-1 ;NOW DECODE USER VARIABLE SPEC + JRST NUSRV1 ;JUMP IF OLD STYLE NUMERIC SPEC +REPEAT MXVAL2,[ ;SIXBIT SPEC LOOK UP IN TABLE + CAML E,USETTB+1_(B) + ADDI B,1_ +] + CAMN E,USETTB(B) + CAIL B,MXVAL + JRST OPNL11 ;ILLEGAL USER VARIABLE NAME + MOVE E,USETBN(B) ;TRANSLATE TO NUMERIC SPEC +NUSRV1: JUMPE W,NUSRV2 ;READING + JUMPL J,OPNL31 ;WRITING AND WRITE PROTECTED + MOVEI I,2 ;MAGIC INDEX 1.2=R/W 1.1=OTHER/SELF +NUSRV2: CAIN U,(J) + IORI I,1 +IFN PDP6P,[ + HRRE B,J + AOJE B,PDPPMT ;USER IS PDP6 +] + CAIL E,600 + JRST [ SUBI E,500 + JRST NUSRV4] + CAIL E,100 + JRST AUSET2 ;100 TO 577 ARE .IOC, .IOS, .IOP, .PMAP VARS. +NUSRV4: CAIL E,MXVAL ;DETECT USET CODE BEYOND 6XX MAXIMUM. + JRST OPNL11 + LDB B,USETBT(I) ;GET METHOD BITS + SOJL B,OPNL12 ;VARIABLE NOT AVAILABLE THIS MODE (WRITE PROTECT?) + SOJL B,AUSVAR ;SIMPLE VARIABLE + LDB B,USETRL(B) ;GET ADDRESS OF ROUTINE TO CALL + HRRZ A,J ;SOME ROUTINES WANT USER INDEX IN A + JUMPE W,(B) + CAMN W,[MOVEM D,] + JRST (B) + PUSH P,D ;READ/ALTER/REWRITE + PUSH P,E + PUSH P,I + PUSH P,W + PUSH P,J + TRZ I,2 ;FIRST READ IT + MOVEI W,0 + PUSHJ P,NUSRV4 + JRST POP5J ;READ LOST + POP P,J + POP P,W + POP P,I + POP P,E + POP P,D + HRRI W,A + XCT W ;MODIFY THE VALUE IN A + MOVE D,A + MOVSI W,(MOVEM D,) + JRST NUSRV4 ;THEN WRITE IT BACK + +; +; .SUSET [N,,LOC] ;SAME AS .USET (SEE BELOW) BUT REFERS TO SELF +; +ASUSET: HRRZ J,U ;JOB TO BE HACKED IS SELF + SETZM UUAC(U) ;IF ERROR, RETURN LOSS IN .IOS+0 + JRST AUSET0 + +; ;IF N&200000=1, BLOCK MODE +; .USET CH,[N,,LOC] ;IF N&400000=0, READS USER VAR SPECIFIED BY REST OF N + ; FOR INFERIOR OR FOREIGN USER OPEN ON CHANNEL CH + ; INTO USER LOCATION LOC + ;IF N&400000.NE.0, SETS USER VAR SPECIFIED BY REST OF N + ; FOR DIRECTLY INFERIOR USER OPEN ON CHANNEL CH + ; FROM USER LOCATION LOC +AUSET: MOVE J,R ;DECODE AC FIELD AS CHANNEL NUMBER + PUSHJ P,AUSETJ + JRST IOCER7 ;USR OP CHNL DOES NOT HAVE USR OPEN +AUSET0: XCTR XR,[HRRZ B,(C)] ;GET ADDRESS READING INTO OR WRITING FROM + XCTR XR,[HLRZ E,(C)] ;GET VARIABLE AND DIRECTION + TRNE E,200000 + JRST ABUSET ;BLOCK MODE + TRZN E,400000 + JRST AUSET1 ;JUMP IF READING + JUMPL J,IOCER7 ;WRITE PROTECT VIOLATION + MOVSI W,(MOVEM D,) ;FLAG WRITING + UMOVE D,(B) ;GET DATA TO WRITE + PUSHJ P,NUSRV3 ;DO THE WRITE + JRST ILUUO ;LOST + POPJ P, + +;BLOCK-MODE .USET +ABUSET: TRNE E,400000 + TLOE J,(MOVE) ;SET BLOCK BIT + JRST ILUUO ;BLOCK IN BLOCK LOSES + UMOVE Q,(C) ;GET AOBJN PTR AGAIN +ABUST2: UMOVEM Q,(C) ;STORE AWAY UPDATED POINTER + PUSH P,C + PUSH P,J + MOVE C,Q + PUSHJ P,AUSET0 + POP P,J + POP P,C + UMOVE Q,(C) + AOBJN Q,ABUST2 + POPJ P, + +AUSET1: MOVEI W,0 ;FLAG READING + XCTR XRW,[MOVES (B)] ;ENSURE WRITEABILITY + PUSH P,B + PUSHJ P,NUSRV3 ;GET VALUE OF VARIABLE INTO A + JRST ILUUO ;LOST + POP P,J +APTUAJ: UMOVEM A,(J) + POPJ P, + +;DECODE ARG FOR USET +AUSETJ: JSP T,NCRUI2 + JRST POPJ1 + JSP T,NCORWR + TLO J,(SETZ) + JRST POPJ1 + +AUSVAR: LDB C,USETRL+1 ;GET ADDRESS OF VARIABLE + ADDI C,USRSTG(J) + JUMPE W,[MOVE A,(C) + JRST POPJ1] + HRR W,C + XCT W + JRST POPJ1 + +IFN PDP6P,[ +PDPPMT: MOVEI A,%JSSIX#%JSNUM ;PDP6 HAS ONLY A FEW VARIABLES, WHICH ARE READ-ONLY + CAIN E,.RUIND + JRST POPJ1 + MOVEI A,LPDP6M*2000 ;FIXED MEM BOUND FOR PDP-6 + CAIN E,.RMEMT + JRST POPJ1 + JRST POPJ1 ;IGNORE OTHER VARIABLES +] + +;VARIABLES 100 - 577 (.IOC, .IOS, .IOP, .PMAP) +AUSET2: JUMPN W,OPNL31 ;JUMP IF TRYING TO WRITE + SUBI E,100 + CAIL E,40 + JRST AUSET4 ;>140=>.RIOP+M + TRZE E,20 + JRST AUSET3 ;117.RIOS+M + ADDI E,IOCHNM(J) ;77.RIOC+M +AUSETX: MOVE A,(E) ;GET VAR + JRST POPJ1 + +AUSET3: MOVE R,J ;INFERIOR USER INDEX + ADDI R,IOCHNM(E) ;GET CHANNEL POINTER + MOVE H,(R) + JRST NSTATUS ;DO A .CALL STATUS + +AUSET4: CAIL E,40+LUIOP ;COMPARE AGAINST LAST IO PDL LOC + JRST AUSET5 ;READ MAP ENTRY + ADDI E,SIOCHN-40(J) ;MAKE UP POINTER TO VAR + JRST AUSETX + +;USET VARIABLE 200+N -- READ MAP VARIABLE FOR PAGE N. +; (0 <= N < 400) E CONTAINS N+100. + +;VALUE OF MAP WORD READ: + +;4.9 - PAGE WRITEABLE. +;4.8 - PAGE EXISTS (IF THIS OFF, WHOLE WORD IS 0) +;4.7 - PAGE IS IN CORE. +;4.6 - PAGE IS PUBLIC (ANYONE CAN WRITE IT) + +;3.1 - 3.9 - # TIMES PAGE SHARED (LIKE CORTYP'S 4TH VALUE'S RH) +;2.1 - 2.9 - ABS PAGE # OR PAGE # IN NEXT SHARER +; (LIKE CORTYP'S 3RD VALUE) +;1.1 - 1.9 - 0 => ABS PAGE (OR NO PAGE, OF COURSE) +; -1 => UNSHARED PAGE, +; ELSE USR NUM. OF NEXT SHARER. + +AUSET5: CAIGE E,100 + JRST OPNL11 + PUSHJ P,SWTL + CIRPSW ;DON'T LET PAGE TABLES CHANGE. + MOVEI A,-100(E) ;PAGE NUMBER IN JOB. + PUSH P,J + PUSHJ P,NCORT0 ;PUT CORTYP'S VALUES IN A THRU D. + POP P,J + PUSHJ P,LSWPOP ;FREE CIRPSW. + ANDI B,777 ;CORTYP'S 2ND VALUE IN 1.1 - 1.9 + DPB C,[111100,,B] ;3RD VALUE IN 2.1 - 2.9 + TLO B,(D) ;4TH VALUE RH INTO 3.1-3.9 + LSH D,-20. + TLO B,(D) ;4TH VAL BITS 4.8-4.9 INTO 4.6-4.7 + IOR A,B ;TOGETHER WITH 1ST VALUE'S 4.8, 4.9. + JRST POPJ1 + +USTOP: AOS (P) ;GOING TO WIN + JUMPN D,1USTOP ;NONZERO VALUE => STOP THE JOB. + MOVE B,APRC(A) ;ZERO => START. + TLNE B,BULGOS ;BUT DON'T EVER START A JOB THAT'S BEING KILLED. + POPJ P, + JRST 1USTRT + +1USTOP: MOVNI D,1 ;SET TO STOP +1USTRT: PUSHJ P,RPCLSR ;STOP USER IN A + DPB D,[.BP BUSRC_22,USTP(A)] ;BUSRC +IFN SWPWSP,[ + EXCH U,A + PUSHJ P,LVLOAD + EXCH U,A +];SWPWSP + JRST UPCLSR + +;SET INFERIOR'S PC +UPCSET: PUSHJ P,RPCLSR ;STOP USER IN USER MODE + TLO D,%PCUSR ;BE SURE USER MODE IS ON IN NEW PC + TLZ D,BADPC ;BE SURE PRIVILEGED BITS ARE OFF + SKIPGE IOTLSR(A) ;SKIP UNLESS USER IS SUPPOSED TO BE IN IOT-USER MODE + TLO D,%PCUIO ;TURN ON IOT-USER MODE + MOVEM D,UPC(A) ;SET PC + PUSHJ P,UPCLSR ;RESTART + JRST POPJ1 + +UJPCS: CAIN U,(A) ;SET .JPC, WITH CARE IF SETTING OWN + SPM UPGML(U) + HRRM D,UPJPC(A) + CAIN U,(A) + LPMR UPGML(U) + JRST POPJ1 + +UJPCR: CAIN U,(A) ;READ .JPC: + SPM UPGML(U) ;IF READING ONE'S OWN, MAKE SURE IT'S UP TO DATE. + HRRZ A,UPJPC(A) + JRST POPJ1 + +IFN KA10P,[ +UROPC: HLLZ A,UPOPC(J) + LSH A,5 + HRR A,UPOPC(J) + JRST POPJ1 +] ;KA10P +IFE KA10P, UROPC: JRST OPNL12 ;.OPC NOT SUPPORTED ON KL AND KS ((CAN'T + ; USE == DUE TO FWD REF)) + +IFN N11TYS,[ ;SET OWN TV CONSOLE REGISTER +STVCRG: MOVEM D,TVCREG(U) ;ENABLE TVCREG TO BE SWAPPED IN AND OUT OF HARDWARE + JUMPL D,POPJ1 ;IF TURNING ON; OR, IF TURNING OFF, ALL DONE + SKIPGE TT11P ;ALLOWED TO TOUCH HARDWARE? + SKIPE TEN11F + CAIA + MOVEM D,400000+TTR10*2000 ;UPDATE REG IN HARDWARE + MOVEM D,TVCREG(U) ;AND UPDATE AGAIN IN SOFTWARE IN CASE CLOBBERED AT SSTVR2 + JRST POPJ1 +] + +IFE KS10P,[ ; KS10 doesn't have a MAR and it never will... + +;READ MAR +URMAR: MOVE A,UPMAR(J) +IFN KA10P, TLZ A,777770 +IFN KL10P, LDB B,[270400,,A] +IFN KL10P, HRL A,MARPTB(B) + JRST POPJ1 + +;SET MAR +USMAR: CONO PI,CLKOFF ;TURN OFF CLOCK INTERRUPTS + CAMN J,USER + SPM UPGML(J) ;STORE PG VARIABLES IF HACKING CURRENT USER +IFN KA10P,[ + TLZ D,777770 + TLO D,4 ;SET USER MODE +] ;KA10P +IFN KL10P,[ + LDB B,[220400,,D] + HLL D,MARPTB(B) +] ;KL10P + MOVEM D,UPMAR(J) + CAMN J,USER + LPMR UPGML(J) ;USE LPMR BECAUSE KL10 DOESN'T HAVE VANILLA LPM + JRST CLKOJ1 + +IFN KL10P,[ ;MAR PERMUTATION TABLE. MAYBE CAN DO BETTER???? ***** + +MARPTB: 0 1, 0 ;OFF ;NONE (EXEC) + 0 11, 0 ;FETCH ;NONE (USER) + 0 3, 2 ;WRITE ;WRITE(EXEC) + 0 17, 6 ;ANY ;WRITE (USER) + 0 1, 10 ;OFF ;READ (EXEC) + 0 11, 14 ;FETCH ;READ (USER) + 0 3, 12 ;WRITE ;NOT FETCH (EXEC) + 0 17, 16 ;ANY ;NOT FETCH (USER) + 0 5, 1 ;READ ;FETCH (EXEC) + 0 15, 5 ;READ+FETCH ;FETCH (USER) + 0 7, 13 ;NOT FETCH ;NOT READ (EXEC) + 0 13, 17 ;NOT READ ;NOT READ (USER) + 0 5, 11 ;READ ;READ+FETCH (EXEC) + 0 15, 15 ;READ+FETCH ;READ+FETCH (USER) + 0 7, 3 ;NOT FETCH ;ANY (EXEC) + 0 13, 7 ;NOT READ ;ANY (USER) +] ;KL10P +] ;IFE KS10P + +IFN KS10P,[ +URMAR: +USMAR: JRST OPNL12 +] ;KS10P + +RUSUPP: HRRE A,SUPPRO(J) ;READ SUPERIOR'S USER INDEX + JUMPL A,POPJ1 ;-1 => TOP LEVEL +UINDEX: IDIVI A,LUBLK ;GET INDEX NUMBER + JRST POPJ1 ;GIVE TO USER + +;READ OWN RUN TIME +UTRNTR: CONO PI,CLKOFF +IFN KA10P,[ + SPM UPGML(U) + LDB A,[2300,,UPQUAN(U)] + LSH A,-2 ;SIMULATE 4.069 USEC CLOCK +] ;KA10P +IFN KL10P,[ + SKIPL MTRUSR ;SKIP IF PERFORMANCE METER AVAILABLE + JRST [ RMBOXC A ;REQUIRES AC ORDER - A,B,C,D,E + DSUB A,STMBOX + DMUL A,KLMBCC ;BECAUSE DMUL PRODUCES FOUR WORD RESULT + REBOXC D + DSUB D,STEBOX + DADD B,D + DMUL B,KLEBCC + MOVE A,D + JRST UTRNT1 ] + RPERFC A + DSUB A,STPERF + DIVI A,50.*4096. +UTRNT1: +] ;KL10P +IFN KS10P,[ + SPM UPGML(U) + LDB A,[400400,,UPQUAN(U)] ; 3.9 USEC CLOCK +] ;KS10P + ADD A,UTRNTM(U) + JRST CLKOJ1 + +;SET JOB'S TTYTBL (.TTY VARIABLE). +USTTY: CONO PI,CLKOFF ;PREVENT TIMING ERROR. + HLLZ E,TTYTBL(J) ;GET CURRENT VALUE + XOR E,D ;GET WHICH BITS USER WANTS TO CHANGE + AND E,[%TBNVR+%TBINT+%TBWAT+%TBOUT+%TBINF+%TBIIN+%TBOIG,,] ;GET BITS USER IS ALLOWED TO CHANGE + TRNE I,1 + TLZ E,%TBWAT ;THESE BITS CAN BE ALTERED ONLY BY THE SUPERIOR + XORM E,TTYTBL(J) ;ALTER THE USER-CONTROLLED BITS WITHOUT WRITING THE OTHERS. + JRST CLKOJ1 + +;READ JOB'S TTYTBL (.TTY) VARIABLE +URTTY: CONO PI,CLKOFF + HRRZ A,TTYTBL(J) + SKIPGE TTYTBL(J) + IDIVI A,LUBLK + HLL A,TTYTBL(J) + JRST CLKOJ1 + +;READ JOB'S .CNSL VARIABLE - TTY# OF TREE'S CONSOLE +URCNSL: MOVE A,UTMPTR(J) + SUBI A,USRRCE + CAIL A,NCT + SUBI A,NCT+2 ;DISOWNED -1 SYS -2 + JRST POPJ1 + +UJNAME: JUMPE D,OPNL33 ;SET INFERIOR'S JNAME + CAME D,[SIXBIT/PDP6/] + CAMN D,[SIXBIT/PDP10/] + JRST OPNL33 ;CHANGING TO ILLEGAL NAME + CAIN I,3 ;.SUSET? + JRST UJNAMS ;YES... + PUSHJ P,RPCLSR + PUSHJ P,UJNAMU ;IS NEW JNAME UNIQUE? + JRST UJNAMG ;NO + MOVEM D,JNAME(A) ;YES + CONO PI,CLKON + PUSHJ P,UPCLSR + JRST POPJ1 + +UJNAMU: MOVE B,UNAME(A) + MOVEI E,0 + CONO PI,CLKOFF +UJNAM1: CAME B,UNAME(E) + JRST UJNAMF + CAMN D,JNAME(E) + POPJ P, +UJNAMF: ADDI E,LUBLK + CAMGE E,USRHI + JRST UJNAM1 + JRST POPJ1 + +UJNAMG: PUSHJ P,UPCLSR + CAME A,E + JRST OPNL13 ;DUPLICATE NAME + JRST CLKOJ1 ;WASN'T REALLY CHANGING THE NAME + +UUNAME: HLRE I,D ;SET OWN UNAME + AOJE I,OPNL33 ;CHECK FOR ILLEGAL ___nnn UNAME + SKIPA I,U +UJNAMS: SETO I, ;SET OWN JNAME + JUMPE D,OPNL33 ;CHECK FOR EVIL NAMES + CAME A,U ;SELF? + BUG ;SOMETHING SCREWED + SKIPL SUPPRO(U) + JRST OPNL40 ;MUST BE TOP LEVEL + CONO PI,CLKOFF ;TURN CLOCK OFF NOW SO WE DON'T GET REOWNED OR SOMETHING + SKIPL I + SKIPA C,JNAME(U) ;CHANGING UNAME, KEEPING JNAME + SKIPA C,UNAME(U) ;VICE VERSA + EXCH D,C ;NOW C=UNAME, D=JNAME + MOVEI E,0 ;CHECK FOR DUPLICATE NAMES +UUNAM0: SKIPE UNAME(E) + CAMN E,U ;ALLOW SETTING TO SAME NAME AS BEFORE + JRST UUNAM1 + HRRZ A,SUPPRO(E) + CAMN C,UNAME(E) + CAME D,JNAME(E) + CAMN A,I ;JOB CAN'T HAVE INFERIORS IF SETTING UNAME + JRST OPNL13 ;OR DUPLICATE U-JNAME IF SETTING EITHER +UUNAM1: ADDI E,LUBLK + CAMGE E,USRHI + JRST UUNAM0 + CAMN C,UNAME(U) + CAME D,JNAME(U) + SKIPA A,D ;D GETS CLOBBERED + JRST CLKOJ1 ;THE NAMES WEREN'T ACTUALLY CHANGED! (SYNCOM DOES IT). + CAME C,UNAME(U) ;IF NOT LOGGED IN, AND CHANGING UNAME, + SKIPGE TTYTBL(U) ; AND CONSOLE-CONTROLLED, + JRST UUNAM3 + HLLO J,UNAME(U) + AOJN J,UUNAM2 + AOS SUSRS ;DISGUST! SHOULD BE USING LOGIN +UUNAM2: HRRZ T,TTYTBL(U) + HRLI T,[ASCIZ / CHUNAM /] + PUSHJ P,SGWAIT ;REQUEST SYSTEM JOB TO PRINT OUR MSG + MOVEM C,SLGIV+2 ;INCLUDE NEW UNAME AS SECOND NAME +UUNAM3: PUSHJ P,LOGUPD ;CHARGE OLD NAME FOR USAGE SO FAR + MOVEM C,UNAME(U) ;THEN SWITCH NAMES + MOVEM A,JNAME(U) + PUSHJ P,DMNPLI ;LOG BACK IN UNDER NEW NAMES + JRST CLKOJ1 + +;WAIT FOR SLGIV VARIABLES TO BECOME FREE, AND REQUEST THE +;SYSTEM JOB TO PROCESS THEM. TAKES STRING,,TTY IN T, AND +;PLACES UNAME(U) IN SLGIV, AND T INTO SLGIV+1. THE CALLER +;IS RESPONSIBLE FOR FILLING IN SLGIV+2 + +SGWAIT: PUSH P,T + MOVSI T,SCLLGI ;SOMEBODY ELSE IS USING THOSE VARIABLES + PUSHJ P,CWAIT ;WAIT FOR THE SYSTEM JOB TO FINISH WITH + TDNE T,SUPCOR ;THEM. + IORM T,SUPCOR ;REQUEST THE SYSTEM JOB TO PRINT OUR MSG + POP P,SLGIV+1 ;STRING,,TTY # + MOVE T,UNAME(U) ;STORE AWAY THE UNAME + MOVEM T,SLGIV + POPJ P, + +RUTRAP: LDB A,[430100,,UTRAPM(J)] ;GET SPECIAL TRAP MODE INDICATOR + JRST POPJ1 + +SUTRAP: DPB D,[430100,,UTRAPM(J)] ;SET " " " " + JRST POPJ1 + +IFN KA10P,[ +URTR1I: SKIPA A,[0,,%PIARO] ;READ "TRAP 1 INSTRUCTION" FOR KA-10 +URTR2I: MOVEI A,%PIPDL ;TRAP 2 + JRST POPJ1 +] ;KA10P + +;SET MEMORY BOUND +USMEMT: CAMN U,A + JRST USMEM2 + PUSHJ P,RPCLSR + MOVSI B,BSSTP + IORM B,USTP(A) + PUSHJ P,UPCLSR +USMEM2: ADDI D,1777 + LSH D,-10. + MOVE B,D + MOVEM A,SRN5(U) ;ARGUMENT TO NCORFS + PUSHJ P,LOSSET + NCORFS ;CLEARS BSSTP IN USTP(A). + EXCH U,A + PUSHJ P,ACORE + JRST OPNL33 ;LOST + EXCH U,A + JRST LSWPJ1 + +;SET SYSTEM NAME (ZERO IGNORED) +USYNST: SKIPE D + MOVEM D,USYSNM(J) + JRST POPJ1 + +;SET INFERIOR'S INTERRUPT MASK +USMASK: SKIPA E,[2] ;MOVEM +IAMASK: ANDI E,1 ;ANDCAM OR IORM + ANDCM D,[VBDBTS] ;BITS FOR CLASS 1 INTS CAN'T BE CHANGED. + XCT (E)[ IORB D,MSKST(A) + ANDCAB D,MSKST(A) + MOVEM D,MSKST(A)] +IFN KA10P,[ + MOVEI B,440+APRCHN ;NOW UPDATE JOB'S APRC VARIABLE. + TRNE D,%PIARO + TRC B,60 + TLNE D,(%PIFOV) + TRC B,600 + HRRM B,APRC(A) + TRNE I,1 + CONO @APRC(A) +] ;KA10P +IFE KA10P, PUSHJ P,TRINST + JRST UPISE1 + +IFE KA10P,[ +;SET THE AROV AND PDLOV TRAP INSNS ACCORDING TO WHETHER THE +;INTERRUPTS ARE ENABLED; BUT DON'T OVERRIDE AN EXPLICIT SPECIFICATION +;BY THE USER, WHICH IS ANYTHING OTHER THAN 0 OR (CAI) IN THE LH. + +TRINST: MOVE D,MSKST(A) + MOVSI B,(CAI) ;CAI IS FASTER THAN JFCL - NO AC DECODE + TDNE D,[%PIFOV+%PIARO] ;AND OVERFLOW GOES OFF A LOT + MOVEI B,%PIARO + HLRZ C,TR1INS(A) + SKIPE C + CAIN C,(CAI) + MOVEM B,TR1INS(A) +; MOVSI B,(CAI) ;THESE LINES COMMENTED OUT TO MAKE +; TRNE D,%PIPDL ; PDL OVERFLOW CLASS 2 INSTEAD OF CLASS 3 + MOVEI B,%PIPDL + HLRZ C,TR2INS(A) + SKIPE C + CAIN C,(CAI) + MOVEM B,TR2INS(A) + POPJ P, +] ;IFE KA10P + +;SET INFERIOR'S PI IN PROGRESS FLAG +UPISET: ASH D,-35. ;SHIFT SIGN BIT TO BOTTOM BIT + MOVEM D,PICLR(A) ;SET VARIABLE +;COME HERE WHEN ANY INTERRUPT VARIABLE'S VALUE IS CHANGED +;BY A .USET OR .SUSET; TAKE ANY INTS THAT ARE NOW PENDING. +UPISE1: HRRZ A,J ;IAMASK, ETC. MODIFY A. RESTORE IT. + AOS (P) ;GOING TO WIN + TRNN I,1 ;SKIP IF A SUSET + JRST APISE6 + JRST APISE1 ;SEE IF SHOULD REINTERRUPT + +IAMSK2: ADDI A,MSKST2-IDF1 +IADF1: ADDI A,IDF1-IDF2 +IADF2: ADDI A,IDF2-PIRQC ;IORM OR ANDCAM INTO IDF2. +IAPIRQ: ADDI A,PIRQC-IFPIR +IAIFPI: ANDI E,1 ;GET USET PARITY (0=IORM, 1=ANDCAM) + XCT IAINS(E) ;DO APPRO OP + JRST UPISE1 + +IAINS: IORB D,IFPIR(A) ;SET BITS + ANDCAB D,IFPIR(A) ;FLUSH BITS + +USMSK2: ADDI A,MSKST2-IDF1 ;SET .MSK2, ETC. +USDF1: ADDI A,IDF1-IDF2 +USDF2: ADDI A,IDF2-PIRQC +USPIRQ: ADDI A,PIRQC-IFPIR +USIFPI: MOVEM D,IFPIR(A) + JRST UPISE1 + +;.RBCHN, .SBCHN READ/SET NUMBER OF LAST CHANNEL ON WHICH ERROR OCCURRED +RUBCHN: LDB A,[BCHPTR#(A#U)] + JRST POPJ1 + +SUBCHN: DPB D,[BCHPTR#(A#U)] + JRST POPJ1 + +;GET INT BIT +UGSUPR: HLLZ A,SUPPRO(J) + JRST POPJ1 + +;SAVE AWAY MA (HIGH BITS) ON LAST MPV OR WIRO +;CALLED FROM CLKBRK, DONT CLOBBER A OR D + +MPVMAS: +IFN KA10P,[ + HLRZ T,UPJPC(U) + LSH T,10. ;HIGH BITS ONLY ON KA +] ;KA10P +IFE KA10P, HRRZ T,UPFW(U) + HRRM T,IOTLSR(U) + POPJ P, + +;.RMPVA READ VIRTURAL PAGE # (8 BITS) OF LAST MPV OR WIRO + +MPVARD: HRRZ A,IOTLSR(J) + JRST POPJ1 + +;.RSERVER Read server user number, or -1 if none. +URSERV: SKIPL A,SERVER(J) + IDIVI A,LUBLK + JRST POPJ1 + +;.SSERVER Set server user number, or clear if negative. +; (To prevent timing screws, you should really use the SSERVE call to set +; this variable, but for debugging convenience...) +USSERV: IMULI D,LUBLK + SKIPGE D + SETOI D, + MOVEM D,SERVER(J) + JRST POPJ1 + +SUBTTL USER INSTRUCTION HANG ROUTINE (.HANG) + +; .HANG was rewritten by Alan Feb 87: +; +; The general theory is that .HANG should behave -exactly- like JRST .-1 as +; much as possible. Thus, it is considered to make sense to put any +; skipping or jumping instruction before a .HANG. We are always careful to +; return from the .HANG by jumping to the previous instruction, so any side +; effects (such as clearing bits or incrementing accumulators or memory) are +; always performed, and jumps will be correctly taken. +; +; There are two ways to leave a .HANG, either the job can get PCLSR'ed, or +; the awaited condition can become true. We arrange for -both- cases to +; return the job to the previous instruction by SOSing UUOH -once- before +; calling UFLS, and once more if UFLS returns. +; +; As an additional feature, .HANG with a non-zero accumulator behaves like +; the disjunction of ordinary .HANG and .SLEEP, allowing the user to do a +; timeout. The accumulator should initially contain an argument, as for +; .SLEEP, that indicates when .HANG should timeout. In that case only, +; .HANG returns to the following instruction and the designated accumulator +; will contain zero. If such a .HANG is interrupted, or if it returns +; because the awaited condition is now true, that accumulator will contain +; the correct negative number indicating the absolute time it would have +; timed out. +; +; Accepted instructions are: +; Any CAI, CAM, JUMP, SKIP, AOJ, AOS, SOJ, or SOS class instruction. +; Any test instruction. +; JFFO. +; JFCL with 0 in the AC field. +; Or an XCT that eventually fetches one of the above. +; +; As special cases SKIPA 0, and CAIA 0, are taken to request a schedule, +; and JFCL 0, and SKIP 0, set %SWDSO. +; +; As before, it is a limitation that changes to memory referenced by .HANG +; when computing effective addresses and fetching XCT'ed instructions will +; not cause the job to wake up. But how could it be otherwise? Changes to +; the accumulators will of course cause the job to be PCLSR'ed. + +AHANG: MOVE R,UUOH + UMOVE R,-2(R) ; Get user's flush instruction + HRLOI A,377777 ; A: most positive fixnum + JUMPE J,AHANG2 ; No AC => timeout when hell freezes over + XCTR XR,[MOVN A,(J)] ; A: argument as for .SLEEP + JUMPG A,AHANG2 ; 'twas already neg., so wait 'til then + SUB A,TIME ; else compute time + UMOVEM A,(J) ; store back negative for PCLSRing + MOVN A,A ; A: time to wait for +AHANG2: PUSHJ P,ASCIND ; Compute E for instruction + HLRZ C,R ; C: Opcode and AC + CAIE C,(JFCL) + CAIN C,(SKIP) + JRST AHANGI ; User might be waiting for a while + CAIE C,(SKIPA) + CAIN C,(CAIA) + JRST AHANGF ; User is just trying to cause a schedule + LSH C,-9 ; C: 9-bit opcode + CAIN C,XCT_-33 + JRST AHANG1 ; XCT - Go loop + CAIN C,JFFO_-33 + JRST AHANGO ; JFFO is like JUMPN + LSH C,-6 ; C: First 3 bits of opcode + CAIN C,CAI_-41 + JRST AHANGC ; CAI, CAM, JUMP, SKIP, AOJ, SOJ, AOS, SOS + CAIN C,TRN_-41 + JRST AHANGT ; Txxx +IFN KS10P, JRST ILUUO +IFE KS10P,[ +;CODE TO ALLOW CONSO, CONSZ AS .HANG INSTRUCTIONS + HLRZ C,R ;CHECK FOR CONSO, CONSZ + TRZ C,077477 + LDB B,[320700,,R] ;GET DEVICE CODE/4 + SKIPGE T,DCHNTB(B) + TRNE T,40000 + CAIE C,(CONSZ\CONSO) + JRST ILUUO ;UNRECOGNIZED INSTRUCTION, OR USER CONI NOT + ; ALLOWED + MOVEM R,EPDL(U) + MOVE T,A + SOS UUOH + PUSHJ P,AHANG9 + PUSHJ P,UFLS + JRST AHANGX + +AHANG9: XCT EPDL(U) + CAMGE T,TIME + AOS (P) + POPJ P, + +] ;IFE KS10P + +; XCT ? .HANG +AHANG1: PUSHJ P,OPBRK ; Don't let "XCT ." hang you up + UMOVE R,(R) ; Get new instruction + JRST AHANG2 ; And start over + +; CAI, CAM, JUMP, SKIP, AOJ, SOJ, AOS, SOS ? .HANG +AHANGC: TLNN R,040000 + JRST AHANG3 ; CAI, CAM, JUMP, SKIP + TLNN R,010000 + JRST AHANGJ ; AOJ, SOJ + TLNN R,020000 + SKIPA T,[-1] ; AOS: Compare with -1 + MOVEI T,1 ; SOS: Compare with 1 + TLZ R,770777 ; Clear all but last 3 bits of opcode + TLO R,(CAM T,) ; Build a CAM instruction + TLNE R,001000 ; With the opposite sense + TLC R,006000 + JRST AHANGM + +AHANG3: TLNN R,020000 + JRST AHANG4 ; CAI, CAM + TLNN R,010000 + JRST AHANGJ ; JUMP + TLZ R,(0 17,) ; SKIP + JRST AHANGM + +; JFFO ? .HANG +AHANGO: TLC R,(JFFO#JUMPN) +AHANGJ: HRRI R,AHANGX + JRST AHANGA + +; SKIPA ? .HANG -- just flush once (ignores timeout) +AHANGF: SOSA UUOH + SKIPA + PUSHJ P,UFLS + JRST AHANGX + +; JFCL ? .HANG -- hang infinitely (or until timeout) +AHANGI: MOVE B,TIME + ADDI B,60.*30. ; If sleeping for more than a minute + MOVSI C,%SWDSO ; Desire swap out + CAML A,B ; (just like .SLEEP) + IORM C,USWST(U) + SOS UUOH +AHANG5: MOVE T,A + CAML T,TIME + PUSHJ P,UFLS + JRST AHANGX + +; Txxx ? .HANG +AHANGT: TLZ R,060000 ; Make opcode be TRN or TDN series + TLNE R,010000 ; If TRN, only AC matters + JRST AHANGB ; TDN: Both AC and memory matter +; Wait for something that only references the user's accumulators. +; (Instruction in R might be some kind of jump to AHANGX.) +AHANGA: PUSHJ P,AHANGG ; Get contents of user's AC into T + SOS UUOH + XCT R ; Must try it once to prevent timing screw + JRST AHANG5 ; OK, wait forever for PCLSR + JRST AHANGX + +AHANG4: TLNN R,010000 ; If CAM, both AC and memory matter + JRST AHANGA ; CAI: Only AC matters +; Wait for something that references memory. +; (Instruction in R better not be a jump!) +AHANGB: PUSHJ P,AHANGG ; Get contents of user's AC into T +AHANGM: MOVEM R,EPDL(U) + SOS UUOH + TRNE R,-20 ; Memory reference really only AC? + JRST AHANG6 ; No, real memory, go wait + XCTR XRW,R ; Must try it once to prevent timing screw + JRST AHANG5 ; OK, wait forever for PCLSR + JRST AHANGX + + PUSHJ P,UHANG +AHANG6: PUSHJ P,UFLS +AHANGX: ;; Everyone exits here after SOSing UUOH once (before hanging). + ;; Thus we always exit to the previous instruction (just like being + ;; PCLSRed), unless we timeout instead. + CAMGE A,TIME ; Timeout? + JRST AHANGY ; Yes + SOS UUOH + POPJ P, + +AHANGY: XCTR XW,[SETZM (J)] ; Let user know we timed out + AOS UUOH ; And fall through instead of backing out + POPJ P, + +;.HANG flush instruction routine, called with PUSHJ only on clock level +UHANG: +IFE KS10P,[ + MOVEI TT,0 ; Save MAR word + EXCH TT,UPMAR(U) ; so will not MAR + LPMR UPGML(U) + MOVEM TT,UPMAR(U) ; Restore MAR +] ;IFE KS10P +IFN KS10P, LPMR UPGML(U) + MOVE TT,AC0S+A(U) + XCTRI XRW,EPDL(U) + CAMGE TT,TIME + AOS (P) ; Might be because location swapped out or + POPJ P, ; missing, but that's OK because we always + ; exit to the previous instruction! + +; Kind of like ASCIND for the accumulators... +AHANGG: LDB T,[270400,,R] + UMOVE T,(T) ; Get contents of AC from user + TLZ R,(0 17,) ; Clear out AC field in instruction + TLO R,(0 T,) ; Replace AC field with T + POPJ P, + +; Allow interrupt if being PCLSRed +OPBRK: PUSH P,T + MOVE T,UEXIT + CAMN T,[JRST ONEFLS] + PUSHJ P,UDELAY + POP P,T + POPJ P, + +SUBTTL .OPEN AND FRIENDS + +; +;.FDELE FILBLK ;DELETE OR RENAME FILE SPECIFIED AT FILBLK +; +AFDELE: SETZM UUAC(U) + UMOVE A,(C) ;GET DEVICE + MOVEI W,4 + DPB W,[OPNCOM,,A] ;SET OP TO SPECIFY AN .FDELE + JRST AFDEL1 +; +;OPEN SET UP AND DISPATCH +;3.1=0 => INPUT =1 OUTPUT +;3.2=0 => UNITS =1 BLOCK +;3.3=0 => ASCII =1 IMAGE +;4.9-4.7 OPERATION FIELD +; 0=> NORMAL READ OR WRITE +; 1=> WRITE OVER MODE +; 2=> MAKE LINK +; 4=> DELETE OR RENAME (INTERNAL) +; +;.OPEN CH,FILBLK ;OPEN FILE SPECIFIED AT FILBLK ON LOGICAL CHANNEL CH +; +AOPEN: ;C HAS EFF ADR OF UUO AND R ITS AC FIELD + ADDI R,IOCHNM(U) ;MAKE R POINT TO SPECIFIED I/O CHANNEL WORD + PUSH P,C + PUSHJ P,ACLOSE ;CLOSE PREV + POP P,C + UMOVE A,(C) ;GET DEV AND MODE BITS + LDB W,[OPNCOM,,A] + CAIN W,4 + JRST OPNL23 ;BARF IF TRY TO DELETE WITH .OPEN +AFDEL1: MOVEI TT,SRN3(U) ;MOVE 4TH-6HT ARGS + HRLI TT,3(C) ;TO SRN3 THRU SRN5 + MOVEI Q,3(TT) + XCTR XBR,[BLT TT,-1(Q)] + UMOVE B,1(C) ;GET 2ND, 3RG ARGS (FILENAMES) + UMOVE C,2(C) + MOVE D,USYSNM(U) ;USE DEFAULT SNAME. + HLRZ E,A ;GET MODE BITS. + HRLZI A,(A) ;LEFT-JUSTIFY DEVICE NAME. + SETZM EPDL(U) + SETZM EPDL3(U) +NOPNE: CAIN W,4 ;SKIP ON NOT .FDELE (ENTRY FOR NCALL TYPE OPEN, ETC COMMANDS) + SKIPN SRN3(U) ;SKIP ON RENAME + JRST AOPEN3 ;JUMP IF A .OPEN OR DELETING .FDELE + JUMPN B,AOPEN3 ;JUMP UNLESS RENAME WHILE OPEN. + MOVE TT,C ;GET CH ON WHICH FILE IS SUPPOSIDLY OPEN + TDNE TT,[-NIOCHN] ;SKIP IF CH LOGICALLY LESS THAN 20 + JRST OPNL14 ;BAD CHANNEL NUM + ADDI TT,IOCHNM(U) ;RELOCATE TO POINT TO CH WORD FOR USER + MOVE Q,(TT) ;GET CH WORD + JUMPE Q,OPNL44 ;CHNL NOT OPEN + HLRZ Q,CLSTB(Q) ;GET LEFT HALF OF CLOSE TABLE ENTRY FOR INDEX IN I/O CH WORD + TRNE Q,%CLSJI\%CLSJO + JRST JFDEL4 ;JOB DEVICE CHNL + TRNN Q,%CLSDO\%CLSQ ;SKIP IF A DIRECTORY DEVICE + JRST POPJ1 ;JUMP IF NOT DIRECTORY DEVICE + HLRZ J,(TT) ;PICK UP DEV CHNL NO + EXCH A,B ;PUT FN1, FN2 IN A, B. + EXCH B,C +IFN NUNITS,[ + TRNN Q,%CLSDO ;SKIP IF DEC TAPE + JRST NOPNE1 + MOVSI C,'UT0 ;GET DUMMY UT DEV NAME. + HRRZ I,UTTNO(J) ;GET POSSIBLE (?) TAPE NUM + TLO C,(I) ;STORE IN DEV NAME + MOVE TT,DVAUT ;WILL EXIT TO UTAPE OPEN RTN. + JRST OPEN2B +NOPNE1: +] + MOVSI C,'DSK ;NOT UT, MUST BE DSK. + MOVE TT,DVAQSK ;NOBODY ELSE HANDLES RENAME WHILE OPEN. + JRST OPEN2B + +AOPEN3: PUSHJ P,TRAN ;PERFORM I/O TRANSLATIONS + JRST OPNL3 ;TOO MANY TRANSLATIONS. + MOVEM D,USYSN1(U);SAVE TRAN'D SNAME FOR OPEN RTN. + PUSH P,A ;PUT NAMES ON STACK. + PUSH P,B + PUSH P,C + MOVSI B,-NDEVS ;LOAD LENGTH OF FIRST DEV NAME TABLE + CAME A,DEVTAB(B);SEARCH FIRST DEV NAME TABLE + AOBJN B,.-1 ;LOOP TILL FOUND OR COUNTED OUT + JUMPG B,OPEN1 ;JUMP IF NOT FOUND +OPEN2: MOVE TT,DEVADR(B) ;LOAD BITS,,OPEN-ROUTINE-ADDRESS +OPEN21: POP P,B ;UNSAVE SECOND FILE NAME + POP P,A ;UNSAVE FIRST FILE NAME + POP P,C ;UNSAVE DEVICE NAME + CAIN W,4 + JRST [ TLNN TT,%DVDEL + JRST OPNL34 ;DEVICE DOES NOT ALLOW DELETE + JRST OPEN2B ] + CAIN W,2 + JRST [ TLNN TT,%DVLNK + JRST OPNL34 ;DEVICE DOES NOT ALLOW LINK + JRST OPEN2B ] +OPEN2B: HRRZ D,E ;MODE BITS + EXCH E,C ;SAVE DEVICE IN E + HLL C,E ;SET UP OLD-STYLE C: MODE,,DEV + MOVSS C +; +;AT THIS POINT: A & B HAVE FILE NAMES, C HAS MAPPED DEV AND MODE BITS, D HAS MODE BITS, +;W HAS OPEN COMMAND, E HAS DEVICE NAME, TT HAS DEVADR WORD (BITS,,ROUTINE) +; + ROT D,-1 ;ROTATE IN/OUT BIT TO SIGN + CAIN W,4 ;SKIP IF NOT A .FDELE + TDZ D,[400000,,7] ;A .FDELE, MAKE LOOK LIKE OPEN FOR READ + PUSHJ P,FLDRCK + JRST OPEN2D ;NORMAL OPEN + JUMPL D,OPNL2 ;WRITING DIRECTORY? + JUMPN W,OPNL12 ;DELETING, RENAMING, LINKING, WRITING OVER DIRECTORY? + TLNE TT,%DVDIR + JRST (TT) ;OPEN DEVICE FOR DIRECTORY +;ASKING FOR DIR OF DEVICE SYSTEM DOESN'T HAVE DIR ROUTINE FOR. +;PASS IT OFF TO THE UNKNOWN-DEVICE HANDLER. + PUSH P,E ;PUSH DEVICE NAME + PUSH P,A ;PUSH FN1 + PUSH P,B ;PUSH FN2 + HLRZ E,C ;GET MODE BITS + JRST OPEN22 ;PASS TO UNKNOWN DEVICE JOB + +OPEN2D: TLNE TT,%DVIN + JUMPGE D,(TT) ;OPENING FOR INPUT AND DEVICE CAN DO INPUT + TLNE TT,%DVOUT + JUMPL D,(TT) ;OPENING FOR OUTPUT AND DEVICE CAN DO OUTPUT + JRST OPNL2 ;DEVICE DOESN'T GO THAT DIRECTION + +;CHECK FOR NUMBERED DEV +OPEN1: MOVE B,[-NDV1,,DVT1-DEVTAB] ;LOAD AOBJN POINTER WITH COUNT FOR 2ND DEV TABLE +OPEN1A: MOVEI I,0 ;INITIALIZE NUMBERED DEV NUM TO ZERO + MOVE D,[440600,,-2(P)] ;GET BYTE POINTER INTO DEV REQUESTED + MOVE C,[440600,,DEVTAB(B)] ;GET BYTE POINTER INTO CURRENT TABLE ENTRY +OPENA1: ILDB A,C ;GET CHAR FROM TABLE + ILDB J,D ;GET CHAR FROM DEV + JUMPE A,OPEN1B ;JUMP ON SPACE IN TABLE, "MATCHES" DIGIT IN DEV + CAIN A,(J) ;SKIP IF CHAR DIFFER + JRST OPEN1C ;SAME, TRY FOR NEXT CHAR +OPENZ1: AOBJN B,OPEN1A ;LOOP TO NEXT TABLE ENTRY OR COUNT OUT +;CHECK FOR NAMED SECONDARY PACK +;FIND THE ONE WITH THIS NAME AND THE BIGGEST QSFT. +;ASSUME THAT BY THE TIME WE GET HERE TUTS HAVE BEEN READ IN AND SO FORTH + SKIPE A,-2(P) ;GET DEVICE NAME AGAIN + CAMN A,[-1] ;0 OR -1 ARE NOT LEGAL PACK NAMES + JRST OPEN22 + MOVEI C,NQS-1 ;SEARCH NAMES OF SECONDARY PACKS + SETOB TT,I ;I BEST DRIVE SO FAR, TT BEST QSFT SO FAR +OPENZ2: CAMN A,QRESRV(C) + JRST [ CAML TT,QSFT(C) + JRST .+1 + MOVE TT,QSFT(C) + MOVE I,C + JRST .+1 ] + SOJGE C,OPENZ2 + MOVE TT,[%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK,,QSKOB] + JUMPGE I,OPEN21 +; +;"UNKNOWN DEVICE" HANDLER. FOO DEVICE IS LOADED BY +;SYS;ATSIGN DEVICE FROM FILE DEVICE;JOBDEV FOO +; +OPEN22: POP P,EPDLT2(U) ;WHEN WE USE SYS:ATSIGN DEVICE AS A JOB DEVICE, + POP P,EPDLT1(U) ;SET UP THE "NAMES BEFORE LAST TRANSLATION" TO BE + POP P,EPDLT4(U) ;THE NAMES BEING USED, INCLUDING "FOO" AS THE DEVICE. + MOVE A,USYSN1(U) + MOVEM A,EPDLT3(U) + MOVSI C,'JOB + MOVE TT,DVAJOB ;DEVADR ENTRY FOR JOB: + MOVSI A,'SYS + MOVEM A,USYSN1(U) + MOVE A,['ATSIGN] + MOVE B,['DEVICE] + JRST OPEN2B + +OPEN1B: JUMPE J,OPEN1C ;JUMP IF DEV ARG EXHAUSTED + SUBI J,'0 ;CONVERT SIXBIT DIGIT TO NUMBER + JUMPL J,OPENZ1 ;JUMP IF TOO SMALL, NOT A DIGIT + CAILE J,9 ;SKIP IF LESS THAN 10. + JRST OPENZ1 ;LOSE, TRY NEXT + ASH I,3 ;MULTIPLY NUM SO FAR BY 8 + ADD I,J ;ADD NEW DIGIT +OPEN1C: TLNE C,770000 ;SKIP IF ALL SIX CHAR POSITIONS COMPARED + JRST OPENA1 ;GO TO NEXT POSITION + JRST OPEN2 + +NSOPEN: HRRZ R,A ;Args: 1 mode (LH) chnl (RH), 2 BP or aobjn -> block of BPs. + CAIL R,NIOCHN + JRST OPNL14 + ADDI R,IOCHNM(U) + PUSH P,A ;Save channel number. + PUSH P,B ;Save BP or BP block ptr. + PUSHJ P,CCLOSE + POP P,R ;Get back the BP or aobjn pointer. + MOVEM R,EPDL(U) ;Save where job device can get it. + PUSHJ P,FNPRS ;Parse into DEV, FN1, FN2, SNM in A, B, C, D. + MOVEM D,SRN3(U) ;Make symbolic open of network win using 5th arg as foreign host. + POP P,R ;Pop back channel number argument. + MOVE E,CTLBTS(U) + TSC E,E + TRZ E,-1 + XOR R,E + LDB E,[OPNCOM,,R] + CAIE E,2 + CAIN E,4 + JRST OPNL12 ;COMMAND CANT BE LINK OR FDELE FOR "NEW" CALL + HLRZ E,R + JRST NDEL1 + +;Given in R a BP into user memory, or an aobjn -> of BPs block in user memory, +;parse filenames into A, B, C, D. Clobbers Q, T, R, H, I. +FNPRS: SETZ Q, ;Guess that it is a BP, not a block of them. + SETZ A, ;Clear out the old-fashioned filename words. + SETZ B, + SETZ C, + SETZ D, + SETCM T,R ;Is our "BP" realy an aobjn pointer to fewer than 64 things? + TLNE R,-1 ;If LH is 0, treat as BP and replace with 440700 later. + TLNE T,777700 + JRST FNPRS8 + MOVE Q,R ;Put the aobjn pointer in Q and get the first BP in R. + UMOVE R,(Q) +FNPRS8: PUSHJ P,ASCIND +FNPRS7: PUSHJ P,FNPRS4 ; Read a sixbit word + JUMPL I,FNPRS9 ; Nothing there at all! + CAIN H,"; ; Directory? + JRST FNPRS0 ; Go do special hack + MOVEI I,B ; assume FN1 + SKIPE B ; unless we already have a FN1 + MOVEI I,C ; in which case assume FN2 + CAIN H,": + MOVEI I,A ; unless it was a device + SKIPN (I) ;Put it there, unless already something there. + MOVEM T,(I) + JUMPN H,FNPRS7 ;H=0 means end of last arg string. +FNPRS9: ;; Supply default values for all components except FN1. + SKIPN A + MOVSI A,(SIXBIT /DSK/) + SKIPN D + MOVE D,USYSNM(U) + SKIPN C + MOVSI C,(SIXBIT />/) + POPJ P, + +FNPRS0: SKIPN I,D + JRST FNPRS2 + LSH T,-6 + TLO T,(SIXBIT /./) +FNPRS1: LSH T,-6 + LSH I,6 + JUMPN I,FNPRS1 +FNPRS2: IOR D,T + JRST FNPRS7 + +;;; Extract in T the next SIXBIT word from user memory off bp in R, +;;; clobbering I (test 4.9 to see if there was no word read at all). +;;; Terminating character returned in H (0 means we got to the end of the +;;; string). Q should be an aobjn pointer to a block in user memory of +;;; additional BPs. +FNPRS4: SETZ T, + MOVE I,[440600,,T] +FNPRS6: PUSHJ P,FNPRS3 + JUMPE H,CPOPJ ; that was the end of the string + CAIE H,": + CAIN H,"; + JRST FNPRS5 ; done? + CAIN H,40 + JRST FNPRS5 ; done? + CAIN H,^Q + PUSHJ P,FNPRS3 + CAIL H,140 + SUBI H,40 + SUBI H,40 + TLNE I,770000 + IDPB H,I + JRST FNPRS6 + +FNPRS5: JUMPL I,FNPRS6 ; keep looking if we haven't seen anything yet. + POPJ P, + +;Extract in H the next character from user memory off the byte pointer in R. +;Q should be an aobjn pointer to a block of further BPs +;(in user memory) to use after this one is exhausted. +FNPRS3: TLNN R,-1 + HRLI R,440700 + IBP R + UMOVE H,(R) ;Fetch the word the BP points to. + PUSH P,R + HRRI R,H ;Change the BP to point to H. + LDB H,R ;Extract the desired byte. + POP P,R + JUMPN H,CPOPJ + AOBJP Q,CPOPJ ;When one BP is exhausted, go to the next (if any). + UMOVE R,(Q) + PUSHJ P,ASCIND + JRST FNPRS3 + +NOPEN: HRRZ R,A ;ARGS 1 MODE (LH) CHNL (RH) 2-5 LIKE NOPEN1 1-4 + CAIL R,NIOCHN + JRST OPNL14 + ADDI R,IOCHNM(U) + PUSH P,A + PUSH P,B + PUSH P,C + PUSH P,D + PUSH P,E + PUSH P,W + PUSHJ P,CCLOSE + POP P,W + SOS W ;STRIP OF FIRST ARG + POP P,D ;B-E POPPED INTO A-D + POP P,C + POP P,B + POP P,A + POP P,R ;A POPPED INTO R + TLC R,@CTLBTS(U) + LDB E,[OPNCOM,,R] + CAIE E,2 + CAIN E,4 + JRST OPNL12 ;COMMAND CANT BE LINK OR FDELE FOR "NEW" CALL + JSP T,NOPEN1 + MOVEM D,SRN3(U) ;MAKE SYMBOLIC OPEN OF NETWORK WIN USING 5TH ARG AS FOREIGN HOST. +NDEL1: CLEARM SRN4(U) +NRN2: CLEARM SRN5(U) +NOPENX: TRNE R,-NIOCHN + BUG ;BAD CHANNEL # + HRRZM R,UUAC(U) ;CHNL # (MAYBE ONLY FOR ERRS) IN R + ADDI R,IOCHNM(U) + LDB W,[OPNCOM,,R] + JRST NOPNE + +;DEFAULT THE ARGS FOR .CALL OPEN, ETC,; PUT MODE IN E. +NOPEN1: SETZM EPDL(U) + SETZM EPDL3(U) + CAIGE W,2 + MOVSI B,(SIXBIT /@/) + CAIGE W,3 + MOVSI C,(SIXBIT /@/) + CAIGE W,4 + MOVE D,USYSNM(U) ;SYSTEM NAME + HLRZ E,R ;GET MODE BITS FOR TRAN. + JRST (T) + +;MAKE LINK 1-4 AS NOPEN1, 5 SNAME 2 6,7 FN1,2(2) +NMLINK: MOVSI R,200000 + CAIN W,2 ;Only 2 args are BPs. + JRST [ PUSHJ P,2FNPRS + JRST NOPENX] + CAIGE W,7 ;Otherwise, must be seven word of sixbit. + JRST OPNL33 + MOVEM E,SRN3(U) + MOVEM TT,SRN4(U) + MOVEM I,SRN5(U) + JSP T,NOPEN1 + JRST NOPENX + +NDEL: SETZM SRN3(U) + CAIN W,2 + JRST OPNL33 + CAIN W,1 ;If it's just a BP (or block of them), + JRST [ MOVE R,A ;Parse it into filenames in A-D. + MOVEM R,EPDL(U) + PUSHJ P,FNPRS + JRST .+2] + JSP T,NOPEN1 + MOVSI R,400000 ;DELETE, ARGS AS NOPEN1 + SETZ E, + JRST NDEL1 + +NRNAM: MOVSI R,400000 + CAIN W,2 ;Only 2 args are BPs. + JRST [ PUSHJ P,2FNPRS + JRST NRN2] + CAIGE W,6 ;Otherwise, must be six word of sixbit. + JRST OPNL33 + MOVEM E,SRN3(U) + MOVEM TT,SRN4(U) + MOVSI R,400000 ;RENAME 1-4 AS NOPEN1 5,6 NEW FN1,2 + JSP T,NOPEN1 + JRST NRN2 + +;Parse two BPs (or aobjn pointers to blocks of BPs) into user memory +;into filenames. The second bunch go in SRN3 - SRN5; the first in A - D. +;The two args are saved in EPDL and EPDL3. Clears E, preserves R. +2FNPRS: PUSH P,R + MOVEM A,EPDL(U) ;Save two BPs for job device. + MOVEM B,EPDL3(U) + PUSH P,A ;Decode the second BP first, to get the new names. + MOVE R,B + PUSHJ P,FNPRS + MOVEM B,SRN3(U) ;Stick them where RENAME looks. + MOVEM C,SRN4(U) + MOVEM D,SRN5(U) + POP P,R ;Parse the first BP, to get the old file filenames. + PUSHJ P,FNPRS + SETZ E, + POP P,R + POPJ P, + +;Takes either channel, FN1 (sixbit) and FN2 (sixbit) +;or channel and BP (or aobjn -> block of BPs). +NRNWO: SETZM EPDL(U) + SETZM EPDL3(U) + PUSH P,A + CAIN W,2 + PUSHJ P,[MOVE R,B ;If channel and BP, parse the BP into filenames. + MOVEM R,EPDL3(U) ;But also save it for job device. + JRST FNPRS] + MOVEM B,SRN3(U) ;PUT AWAY NEW NAMES. + MOVEM C,SRN4(U) + POP P,C + ANDI C,-1 ;We call "RENAME" with old fn2 = channel number. + SETZB A,B + MOVEI D,0 + MOVSI R,400000 ;OPNCOM IS .FDELE . + MOVEI E,400000 + JRST NRN2 + +SUBTTL HACKS FOR OPENS THAT LOSE + + +IFN 0,[ ;THESE "DEFNS" EXIST ONLY SO @ WILL CREF THEM + OPNL1: OPNL2: OPNL3: OPNL4: OPNL5: OPNL6: OPNL7: +OPNL10: OPNL11: OPNL12: OPNL13: OPNL14: OPNL15: OPNL16: OPNL17: +OPNL20: OPNL21: OPNL22: OPNL23: OPNL24: OPNL25: OPNL26: OPNL27: +OPNL30: OPNL31: OPNL32: OPNL33: OPNL34: OPNL35: OPNL36: OPNL37: +OPNL40: OPNL41: OPNL42: OPNL43: OPNL44: OPNL45: OPNL46: OPNL47: +OPNL50: OPNL51: OPNL52: OPNL53: OPNL54: OPNL55: OPNL56: OPNL57: +OPNL60: OPNL61: OPNL62: OPNL63: OPNL64: OPNL65: OPNL66: OPNL67: +OPNL70: OPNL71: OPNL72: OPNL73: OPNL74: OPNL75: OPNL76: OPNL77: +] ;END OF IFN 0 + +;HERE ARE THE REAL DEFNS +REPEAT NOPNLS,CONC OPNL,\.RPCNT+1,: JSP D,OPENL +; +OPENL: CONSZ PI,77400 + BUG ;ERROR WITH PI IN PROGRESS + MOVE U,USER ;BE SURE U=CURRENT USER'S INDEX + MOVEI D,-OPNL1(D) ;GET LOSSAGE NUMBER + MOVE R,SYSCVL(U);POSSIBLY RETURN IN ERROR-CODE ARG TO .CALL + TLNE R,%SCVER + UMOVEM D,(R) + HRRZ R,UUAC(U) ;GET CH NUM + CAILE R,NIOCHN-1 + BUG ;UUAC BAD + PUSHJ P,LSWCLR ;UNLOCK SWITCHES + DPB R,[BCHPTR] ;SAVE AS MOST RECENT CHANNEL IN ERR + ADD R,U ;RELOCATE TO POINT TO USER VARS + DPB D,[220600,,IOCHST(R)] ;STORE IN STATUS WORD + JRST CLKONJ + +SUBTTL RCHST, STATUS, RFNAME, RFPNTR, WHYINT CALLS + +;.CALL RFNAME +;1ST ARG IS A , WHOSE CHANNEL IS TO BE LOOKED AT. +;2ND ARG IS A CHANNEL NUMBER. +;3RD ARG IS BP TO STORE ASCIZ FILENAME STRING THROUGH. +;4TH ARG IS MAXIMUM NUMBER OF CHARACTERS TO STORE (DEFAULTS TO 1,,0). +;ONLY 1 ARG => IT IS CHANNEL #, AND JOB IS "SELF". +;FIRST 4 VALUES ARE THE DEVICE, FN1, FN2 AND SNAME +; AS LEFT-JUSTIFIED SIXBIT WHOLEWORDS. +;FIFTH VALUE IS THE MODE THE CHANNEL MIGHT BE RE-OPENED IN + +NRFNAM: MOVE J,A ;FIRST ARG IS JOB SPEC + CAIL W,2 + SKIPA A,B ;GET CHANNEL # INTO A IN EITHER CASE + MOVEI J,%JSELF ;IF ONLY ONE ARG, JOB SPEC IS SELF + MOVE Q,C ;SAVE BP FOR STORING ASCIZ FILENAME STRING - IF ANY. + CAIGE W,3 + SETZ Q, + CAIGE W,4 + MOVSI D,1 + JSP T,NCORUI ;DECODE JOB SPEC + JFCL +IFN PDP6P,[ + CAIN J,-1 + JRST OPNL34 ;PDP6 DOESN'T HAVE CHANNELS +] + PUSH P,D + PUSH P,Q + MOVE W,D + MOVE U,J ;LOOK IN THAT JOB'S CHANNELS + PUSHJ P,NRFNM1 ;GET THE CRUFT + JRST POP2J + PUSHJ P,LSWPOP ;UNSOS DIELOK. + MOVE T,Q + POP P,Q + POP P,I ;I GETS 4TH ARG: MAX NUMBER OF CHARS TO STORE IN STRING. + JUMPE T,POPJ1 ;IF DEVICE ROUTINE HAS CLEARED Q, IT HAS STORED THE STRING. + ;NOTE NETRCH PUTS AN EXTRA VALUE FOR .RCHST (GARBAGE, TO US) IN Q! + JUMPE Q,POPJ1 ;IF BP ARG WAS 0, CALLER DOESN'T WANT A STRING. + MOVE R,Q + PUSHJ P,ASCIND + MOVE Q,R + MOVE J,A ;IF SO, STORE ALL 4 FILENAMES DOWN IT, ONE BY ONE. + MOVEI T,": + PUSHJ P,NRFNS1 + MOVE J,D + MOVEI T,"; + PUSHJ P,NRFNS1 + MOVE J,B + MOVEI T,40 + PUSHJ P,NRFNS1 + MOVE J,C + MOVEI T,0 + PUSHJ P,NRFNS1 + JRST POPJ1 + +;STORE THE SIXBIT WORD IN J FOLLOWED BY THE ASCII CHAR IN T +;INTO USER ADDRESS SPACE DOWN THE BP IN Q. +NRFNS1: JUMPE J,CPOPJ ;OUTPUT NOTHING AT ALL IF THE SIXBIT WORD IS EMPTY. + CAIGE I,4 ;GIVE UP NOW IF TOO CLOSE TO END OF ALLOCATED SPACE. + POPJ P, + SETZ R, + ROTC J,6 ;ELSE GET NEXT CHAR IN R, AND CONVERT TO ASCII AND STORE. + ADDI R,40 + SETZ TT, + CAIE R,": ;PRECEDE ANY SPECIAL CHARACTERS WITH ^Q. + CAIN R,"; + MOVEI TT,^Q + CAIN R,40 + MOVEI TT,^Q + JUMPE TT,NRFNS2 + SOS I + PUSHJ P,NRFNSB +NRFNS2: SOS I + MOVE TT,R + PUSHJ P,NRFNSB + JUMPN J,NRFNS1 + SOS I + MOVE TT,T + PUSHJ P,NRFNSB ;IF NAME FINISHED BUT NOT EMPTY, FOLLOW BY TERMINATOR. + JUMPE T,CPOPJ + CAIN T,40 + POPJ P, + MOVEI TT,40 + PUSHJ P,NRFNSB ;IF TERMINATOR IS : OR ;, FOLLOW IT WITH A SPACE. + SOJA I,CPOPJ + +;STORE A BYTE IN TT DOWN BP IN Q TO USER SPACE, INCREMENTING FIRST. +;XCTR XBYTE LOSES BECUSE IT GETS THE BP FROM USER SPACE. +NRFNSB: IBP Q + PUSH P,T + PUSH P,Q + UMOVE T,(Q) + HRRI Q,T + DPB TT,Q + POP P,Q + UMOVEM T,(Q) + POP P,T + POPJ P, + +;GET THE FILENAMES FOR THE CHANNEL IN A OF JOB IN U INTO A THRU D. +;IF Q IS NONZERO, IT IS A BP TO STORE AN ASCIZ STRING, AND W IS THE +;MAX NUMBER OF CHARACTERS TO STORE. +;THE DEVICE DEPENDENT ROUTINE CAN STORE THE STRING ITSELF +;AND SET Q TO ZERO SO THAT IT WILL NOT BE STORED THE STANDARD WAY. +NRFNM1: MOVE T,[4,,NRFNM2] + JRST CHNDCD ;R GETS ADDR OF IOCHNM WD, H GETS CONTENTS. +NRFNM2: HLRZ A,H ;PUT LH(IOCHNM WD) WHERE DEVICE RTN LOOKS + HLLZ J,DCHSTB(H) + JUMPG J,[ ;IF 6-LETTER DEVICE NAME, LH IS POSITIVE ADDRESS + HLRZS J ;OF FULL NAME. NOTE THERE BETTER BE NO + MOVE J,(J) ;3-CHAR DEVICES WHOSE NAME DOES NOT START + JRST .+1 ] ;WITH A LETTER. + PUSH P,J ;SAVE THE PROBABLE VALUE OF DEVICE NAME + LDB J,[1400,,DCHSTB(H)] + HLRZ J,DRFNTB(J) ;GET RFNAME ROUTINE POINTER + SETZB B,C ;FN1, FN2 ARE 0 FOR NON-DIR-DEV + SETZ D, ;SNAME IS 0 FOR NON-MULTI-DIR-DEV + LDB E,[.BP (%IOTOM),IOTTB(H)] ;PROBABLE VALUE OF MODE + PUSHJ P,(J) ;CALL DEVICE-SPECIFIC ROUTINE + SKIPA A,(P) ;NO SKIP => USE DEVICE NAME FROM DCHSTB + MOVE A,J ;SKIP => USE DEVICE NAME RETURNED IN J + JRST POP1J1 + +;.CALL RFPNTR +;ARG 1 - CHANNEL NUMBER +;VAL 1 - ACCESS POINTER OF CHANNEL +;VAL 2 - BYTE SIZE OF CHANNEL. +;FAILS IF NOT A RANDOM-ACCESS DEVICE + +NRFPNT: HLRZ A,H ;CHANNEL ALREADY DECODED, SET UP LH(IOCHNM) FOR DEV RTN + LDB J,[1400,,DCHSTB(H)] + HRRZ J,DRFNTB(J) ;GET RFPNTR ROUTINE POINTER + JRST (J) ;IT SHOULD PUT POINTER IN A AND POPJ1, OR OPNL34 + +;SYMBOLIC CALL "RCHST" +;1ST ARG IS A CHANNEL NUMBER. +;6 OR MORE VALUES. THE FIRST 4 ARE THE DEVICE, FN1, FN2 AND SNAME +; AS LEFT-JUSTIFIED SIXBIT WHOLEWORDS. +;THE 5TH IS THE ACCESS POINTER, OR -1 IF NOT RANDOM ACCESS. +;THE 6TH IS THE MODE THE CHANNEL MIGHT BE RE-OPENED IN. +;MORE VALUES ARE RETURNED ONLY FOR NET:, AT THE MOMENT. +;THE DEV SUBROUTINE MAY PUT EXTRA RESULTS IN TT, I, AND Q, AND PUT # RESULTS INTO W + +NRCHST: SETO I, ;DEFAULT POSSIBLE EXTRA RESULTS + SETO TT, ;DEFAULT ACCESS POINTER TO -1 + MOVEI W,6 ;NORMAL NUMBER OF RESULTS IS 6 + SETZ Q, + PUSHJ P,NRFNM1 ;GET RESULTS 1 THROUGH 4 AND 6, AND SET UP R AND H + POPJ P, ;CHANNEL NUMBER MUST HAVE BEEN BAD + PUSH P,A + PUSH P,B ;SAVE THE AC THAT RFPNTR CLOBBERS. + HLRZ A,H ;GET ROUTINE TO GET ACCESS POINTER + LDB J,[1400,,DCHSTB(H)] + HRRZ J,DRFNTB(J) ;ROUTINE BETTER PRESERVE B,C,D,E,TT,I,Q + CAIL J,OPENL ;KLUDGILY SKIP IF WOULD OPEN-LOSS + PUSHJ P,(J) ;GET ACCESS POINTER IN A, ALWAYS SKIPS + MOVE A,TT ;NOT RANDOM ACESS, USE DEFAULT VALUE + MOVE TT,E ;OPEN MODE IS 6TH RESULT + MOVE E,A ;ACCESS POINTER IS 5TH RESULT + JRST PPBAJ1 + +;.RCHST AC, WITH AC/ CH,,ADDR +;RETURNS, IN THE 5 OR MORE WORDS STARTING AT ADDR, +;THE RESULTS OF A SYMBOLIC RCHST ON CHANNEL CH. +;EXCEPTION - THE DEVICE NAME IS RETURNED IN THE RH +;OF THE FIRST WORD , SO IT IS TRUNCATED TO 18 BITS. +;EXCEPTION - THE OPEN MODE VALUE IS NOT RETURNED. LATER VALUES +;ARE SHIFTED DOWN ONE WORD. +;NEVER SKIPS. + +ARCHST: UMOVE J,(J) ;GET CONTENTS OF AC + HLRZ A,J + CAIL A,NIOCHN + JRST ILUUO ;BAD CHANNEL NUMBER + PUSH P,J + PUSHJ P,NRCHST ;DO THE REAL WORK. + BUG ;ONLY ERROR RETURN SHOULD BE BAD CHANNEL NUMBER + HLRZS A ;PUT DEV NAME IN RH FOR HISTORY'S SAKE + POP P,J ;RH(J) HAS PLACE TO STORE DATA + MOVE TT,I + MOVE I,Q ;SHIFT DOWN LAST 2 VALS OVER THE OPEN MODE. + HRLI J,A + ADDI W,-2(J) ;W HAD 1+ # VALS, NOW HAS PLACE TO PUT LAST ONE + XCTR XBW,[BLT J,(W)] + POPJ P, + +;.STATUS CH,LOC ;STORE IN LOC THE STATUS OF CHANNEL CH + ;AND OF THE DEV OPEN ON IT IF ANY +;1.1-1.6 SYS PERIPHERAL DEVICE CODE +;1.7-2.9 DEVICE DEPENDENT +;3.1-4.9 LH(IOCHST) + +ASTATUS:ADDI R,IOCHNM(U) ;SET UP AC'S LIKE CHNDCD +ASTAT1: MOVE H,(R) ;ENTER HERE FROM .USET [.RIOS,,] + HLL R,CLSTB(H) + PUSHJ P,NSTATUS ;CALL NEW SYSTEM CALL VERSION + BUG + UMOVEM A,(C) ;GIVE TO USER + POPJ P, + +;.CALL STATUS +;ARG 1 - CHANNEL NUMBER +;VAL 1 - SAME AS .STATUS + +NSTATUS:HLRZ A,H ;SET UP LH(IOCHNM) + LDB D,[140600,,DCHSTB(H)] ;GET SYS PERIPHERAL DEVICE CODE + LDB J,[340300,,IOTTB(H)] ;GET I/O CHANNEL MODE FROM 4.5-4.2 + DPB J,[060300,,D] ;RETURN IN BITS 1.9-1.7 + LDB J,[1400,,DCHSTB(H)] + HLRZ J,DSTSTB(J) ;GET STATUS ROUTINE POINTER + PUSHJ P,(J) ;ROUTINE FILLS OUT STATUS WORD IN D + HLL D,IOCHST-IOCHNM(R) ;FILL IN LEFT HALF FROM IOCHST + TLZ D,740000 ;CLEAR BITS USED FOR CHANNEL NUM ON IO PDL + MOVE A,D ;RETURN VALUE IN A + JRST POPJ1 ;THIS CALL ALWAYS SUCCEEDS + +;.CALL WHYINT +;ARG 1 - CHANNEL NUMBER +;VAL 1 - %WY CODE FOR TYPE OF DEVICE +;ADDITIONAL VALUES DEVICE-DEPENDENT +;THIS IS THE USUAL CALL TO GIVE IN RESPONSE TO A SECOND WORD INTERRUPT + +NWHYINT:HLRZ A,H ;SET UP LH(IOCHNM) + LDB J,[1400,,DCHSTB(H)] + HRRZ J,DSTSTB(J) ;GET WHYINT ROUTINE POINTER + JRST (J) + +;DEVICE-SPECIFIC RFNAME/RCHST ROUTINES +;CALLED WITH STANDARD CHNDCD STUFF IN H AND R, LH(IOCHNM) IN A +;MUST PRESERVE H AND R; CAN CLOBBER W TO INDICATE EXTRA STUFF FOR RCHST + +RCHUSR: MOVE B,UNAME(A) ;GET UNAME + MOVE C,JNAME(A) ;GET JNAME + POPJ P, + +IFN NUNITS,[ ;UTAPE .RCHST +RCHUTP: HRRZ C,UTTNO(A) + MOVSI J,'UT0(C) ;GET REAL DEV NAME "UTN" IN J + AOS (P) ;SKIP TO RETURN CHANGED DEV NAME + MOVE D,UTASS(C) ;THE "SNAME" IS THE USER TAPE IS ASSIGNED TO. + CAIGE A,NUTIC + JRST RCHUTI ;INPUT + MOVE B,UTN1(A) ;OUTPUT, GET FN1 + MOVE C,UTN2(A) ;NOW FN2 + POPJ P, + + ;UTAPE INPUT .RCHST +RCHUTI: LDB T,[220500,,UTDBC(A)] ;GET FILE NUMBER + SUBI T,1 + LSH T,1 ;TURN INTO INDEX INTO DIRECTORY + CONO PI,CLKOFF + ADD T,UDIRO(C) ;GET POINTER TO FILE NAMES + MOVE B,(T) ;GET FN1 + MOVE C,(T) ;GET FN2 + JRST CLKONJ +] + +;RCHST ROUTINE FOR TTY +RCHTTY: MOVE J,A + ANDI J,#%TICNS#(.BM $TIIDX) + IOR E,J ;MERGE TTY OPEN MODE BITS WITH THE GENERAL ONES. + TRNE A,%TICNS + POPJ P, + ANDI A,7 + MOVEI J,'T00(A) + HLRZ A,(R) +RCHST1: ANDI A,70 + LSH A,3 + ADD J,A + HRLZS J ;J NOW HAS SIXBIT/TNM/, NM = TTY #. + JRST POPJ1 ;SKIP TO SAY DEV NAME IS IN J. + +;RCHST ROUTINE FOR STY +RCHSTY: MOVE J,TTYOPT(A) + TLNE J,%TOHDX + IORI E,4 ;STY BIT 1.3 => TTY IS HALF-DUPLEX. + MOVE J,STYSTS-NFSTTY(A) + TLNE J,%SSORS + IORI E,20 ;BIT 1.5 => WANT TO RECEIVE %TDORS ON .RESET OF TYOC, + TRNN E,1 ;FIND THE DON'T-HANG-BIT FOR THIS DIRECTION. + TLZA J,#%SSOHG ;AND FLUSH THE ONE FOR THE OTHER DIRECTION. + TLZ J,#%SSHNG + TLNE J,-1 ;THEN TESTING BOTH TESTS ONLY THE RELEVANT ONE. + IORI E,10 + SUBI A,NFSTTY + ANDI A,7 + MOVEI J,'S00(A) + HLRZ A,(R) + SUBI A,NFSTTY + JRST RCHST1 + +RCHDRH: HRRZ A,IOCHST-IOCHNM(R) ;TRACK NUMBER + IMULI A,LMNBLK ;DIRHNG DEVICE RFNAME + ADDI A,2000-LMNBLK*NUDSL + ADD A,QMDRO + MOVE D,MNUNAM(A) + POPJ P, + +;RCHST ROUTINE FOR DIRECTORY CHANNELS AND THE ERR DEVICE. +RCHDIR: MOVE T,DSKLST(A) ;GET THE TYPE OF DIRECTORY CODE. + SKIPE J,UDUSR(A) ;IF DEVICE # IS NONZERO, ADD IT TO DEV NAME + HRLZS J ;(ONLY HAPPENS FOR UTAPE) + ADD J,RCHDRD-1(T) ;DETERMINE DEV NAME FROM DIRECTORY TYPE + MOVE B,RCHDR1-1(T) ;SAME FOR FN1 + SKIPN C,RCHDR2-1(T) ;AND FN2, EXCEPT 0 FOR ERR DEVICES + MOVE C,UUDPP(A) ; SO WE WILL GET THE STATUS WORD BEING DECODED. + CAIN T,3 + MOVE D,UDSYSN(A) ;FOR DISK UFD'S, GET THE SNAME + JRST POPJ1 ;RETURN, SAYING WE HAVE SPEC'D THE DEVICE NAME. + +.SEE UDT ;THESE TABLES ARE IN PARALLEL WITH UDT +RCHDRD: 'UT0,, ? 'CLU,, ? 'DSK,, ? 'DSK,, + 'ERR,, ? 'TTY,, ? 'COR,, +IF2 IFN .-UDTLN-RCHDRD,.ERR RCHDRD WRONG LENGTH + +RCHDR1: '.FILE. ? '.FILE. ? '.FILE. ? 'M.F.D. + 3 ? '.FILE. ? '.FILE. +IF2 IFN .-UDTLN-RCHDR1,.ERR RCHDR1 WRONG LENGTH + +RCHDR2: SIXBIT /(DIR)/ ? SIXBIT /(DIR)/ ? SIXBIT /(DIR)/ ? SIXBIT /(FILE)/ + 0 ? SIXBIT /(DIR)/ ? SIXBIT /(DIR)/ +IF2 IFN .-UDTLN-RCHDR2,.ERR RCHDR2 WRONG LENGTH + + + +;CORE LINK .RCHST ROUTINE + +RCHCLO: CONO PI,CLKOFF + MOVE B,CLN1(A) ;GET FN1 + MOVE C,CLN2(A) ;GET FN2 + MOVE D,CLSYN(A) ;GET SYSTEM NAME + JRST CLKONJ + +;RFNAME ROUTINE FOR DSK + +RCHQSK: MOVE H,QUDPR(A) ;FILE STATUS FOR DISK PICKUP USER DIR POINTER + PUSHJ P,QUDLK ;LOCK DIRECTORY + MOVE C,QSNLCN(H) ;LOCATION OF DIRECTORY + MOVE D,UDNAME(C) + ADD C,QUDFPR(A) ;ADD LOCN OF FILE WITHIN DIRECTORY + MOVE B,(C) ;GET FIRST FILE NAME + MOVE C,1(C) ;GET SECOND FILE NAME + PUSHJ P,QUDULK + MOVE H,QSRAC(A) + TLNE H,%QALNK + TRO E,20 ;LINK MODE + MOVE H,(R) ;PRESERVE H + POPJ P, + +;RFNAME ROUTINE FOR BOJ: + +RCHBOJ: CONO PI,CLKOFF ;BOJ DEVICE .RCHST ROUTINE + MOVE T,JBCUI(A) ;RETURNS CREATOR'S NAME + MOVE B,UNAME(T) + MOVE C,JNAME(T) + SKIPGE JBCG(A) + SETZB B,C ;CREATOR GONE, RETURN BLANK NAMES + JRST CLKONJ + +;RFNAME ROUTINE FOR JOB: + +RFNJOB: SKIPE Q + PUSHJ P,RFNJ1 + CONO PI,CLKOFF + MOVE B,JBFN1(A) + MOVE C,JBFN2(A) + MOVE D,JBSYS(A) + MOVE E,JBOPNM(A) + MOVE J,JBDEV(A) + JRST CLKOJ1 + +;COPY THE BOJ JOB'S ASCIZ FILENAME STRING INTO OUR CALLER'S STRING. +;THE CALLER'S BP IS IN Q, AND HIS MAX CHARS TO STORE IS IN W. +RFNJ1: SKIPN B,JBFNP(A) + POPJ P, + PUSH P,TT + PUSH P,T + MOVE J,JBCJUI(A) + AOS DIELOK(J) ;PREVENT THE JOB FROM DIEING. + PUSHJ P,SOSSET + DIELOK(J) + TLZ B,37 + MOVE D,B + PUSHJ P,RFNJ3 + MOVEI TT,1 +;D HAS BP TO FETCH WITH, POINTING INTO C, WHICH CONTAINS WORD FETCHED FROM BOJ JOB. +;RH(B) HAS ADDR OF NEXT WORD TO FETCH FROM THE BOJ JOB. +;TT CONTAINS THE PREVIOUS CHARACTER TRANSFERRED, OR 1 +;IF THE PREVIOUS CHARACTER WAS QUOTED WITH A ^Q. +RFNJ2: ILDB E,D + TRNN D,#C ;IF THE BP IN D ADVANCES PAST C, + JRST RFNJ4 + PUSHJ P,RFNJ3 ;FETCH ANOTHER WORD INTO C, MAKE D POINT THERE AGAIN, + LDB E,D ;AND FETCH THE SAME BYTE OVER AGAIN. +RFNJ4: SOJL W,RFNJ5 + EXCH TT,E + PUSHJ P,NRFNSB ;STORE BYTE INTO CALLER, UNLESS HIS STRING IS FULL. + EXCH TT,E + CAIN TT,^Q ;A QUOTED CHAR DOES NOT TERMINATE AND DOES NOT QUOTE. + MOVEI E,1 + MOVE TT,E + JUMPN E,RFNJ2 ;STOP STORING AFTER A NULL WHICH ISN'T QUOTED. +RFNJ5: SETZ Q, + POP P,T + POP P,TT + JRST LSWPOP + +;READ THE NEXT WORD (ADDR IN B) FROM THE BOJ JOB. +RFNJ3: SETZ C, + PUSH P,U + PUSH P,A + PUSH P,Q + MOVE U,JBCJUI(A) + LDB A,[121000,,B] + PUSHJ P,UPLC ;LOOK UP THE BOJ JOB'S PAGE. + POP P,Q + POP P,A + POP P,U + LDB J,T ;IF IT DOESN'T EXIST, LOAD A ZERO, + JUMPE J,RFNJ6 ;AVOID GETTING MPV. + MOVE J,JBCJUI(A) + PUSHJ P,MPLDJ + UMOVE C,(B) +RFNJ6: HRRI D,C + AOJA B,MPLDZ + +;RFPNTR FOR USR: + +RFPUSR: HRRZ A,IOCHST-IOCHNM(R) ;GET THE ACCESS PTR + MOVEI B,36. ;BYTE SIZE IS ALWAYS FULL WORD. + JRST POPJ1 + +;RFPNTR FOR DISK + +RFPQSK: LDB B,[QSBSIZ(A)] ;GET FILE BYTE SIZE + MOVSI T,%QAACC + TDNN T,QSRAC(A) ;IF .ACCESS WAS DONE AND NOT HANDLED, + JRST RFPQS1 + MOVE A,QRADAD(A) ;GET WHAT THE .ACCESS SPECIFIED. + JRST POPJ1 + +RFPQS1: MOVE J,QFBLNO(A) ;GET BYTE # OF STRAT OF CURRENT BLOCK. + SKIPGE QSMDN(A) ;SKIP ON A BUFFER ACTIVE + JRST RFPQS2 ;NONE ACTIVE => QFBLNO POINTS TO NEXT BLOCK TO BE READ. + ADD J,QMPBSZ(A) ;ELSE CORRECT FOR THE NUMBER OF BYTES WE'VE PROCESSED + SUB J,QSMPRC(A) ;IN THE ACTIVE BLOCK (QFBLNO -> 1ST WD OF BLOCK). +RFPQS2: MOVE A,J + JRST POPJ1 + +SUBTTL RESET,IOPUSH,IOPOP,IOPDL,FORCE,FLUSH .CALLS + +;.RESET CH, ;RESET BUFFERED INFO ON CHANNEL CH + ;NOT IMPLEMENTED FOR MANY DEVICES + ;HAS SPECIAL EFFECTS ON "USR" DEVICE +;.CALL RESET +;ARG 1 - CHANNEL NUMBER + +NRESET: HRRZ A,H + AOSA (P) +ARESET: HRRZ A,(R) ;PICK UP INDEX FROM I/O CH WORD + SKIPA T,[HRRZ T,RSTB1(A)] ;.RESET USES RH OF TABLE +AIOPP1: MOVE T,[HLRZ T,RSTB1(A)] ;.IOPUSH, .IOPOP USE LH OF TABLE + IDIVI A,7 ;TABLE IS IN 5-BIT BYTES TO SAVE SPACE + ADD A,[440500,,RSTB] + IBP A + SOJGE B,.-1 + LDB A,A ;GET BYTE FROM TABLE + XCT T ;GET REAL TABLE ENTRY IN T + JRST (T) ;DISPATCH + +;IO CHANNEL PUSH DOWN LIST ROUTINES +;C(I) =0 AT DSP => IOPUSH =1 => IOPOP + +NIOPUS: AOS (P) +AIOPUSH:MOVE T,SIOCP(U) ;PICK UP PDL POINTER + CAML T,[LUIOP-1,,0] ;LUIOP-2,, is OK, leaves room for 1 more. + JRST IOCER6 ;OVER PUSH ERROR + PUSH T,(R) ;PUSH CURRENT IOCHNM + PUSH T,IOCHST-IOCHNM(R) ;&IOCHST + HRRZ A,(R) + HRRZ J,UUAC(U) + DPB J,[400400,,(T)] ;STORE CHANNEL NUM FOR POSSIBLE USE BY AIOPDL + MOVEM T,SIOCP(U) ;STORE BACK PDL POINTER + MOVEI I,0 ;INDICATE IOPUSH + PUSH P,R + PUSHJ P,AIOPP1 ;CALL DEVICE'S IOPDL HANDLER. SHOULD NOT HANG + POP P,R + SETZM (R) ;CLEAR OUT IOCHNM + SETZM IOCHST-IOCHNM(R) ;&IOCHST + POPJ P, + +NIOPOP: AOS (P) +AIOPOP: PUSHJ P,ACLOSE ;CLOSE WHATEVER MAY BE OPEN ON CHANNEL POPPING INTO + MOVE T,SIOCP(U) ;PICK UP PDL POINTER + TLNN T,-1 + JRST IOCER5 ;OVER POP ERROR + POP T,IOCHST-IOCHNM(R) ;POP BACK IOCHST + POP T,(R) ;&IOCHNM + HRRZ A,(R) + SETZM 1(T) ;CLEAR OUT PDL WORD TO AVOID CONFUSION IN + ;ROUTINES THAT GROVEL OVER I/O PDL + MOVEM T,SIOCP(U) ;STORE BACK PDL POINTER + MOVEI I,1 ;INDICATE IOPOP + JRST AIOPP1 ;CALL DEVICE'S IOPDL HANDLER + +AIOPDL: MOVE T,SIOCP(U) ;PICK UP PDL POINTER + TLNN T,-1 ;SKIP UNLESS IO PDL EMPTY + POPJ P, + LDB R,[400400,,(T)] ;FIND OUT WHAT CHNL TOP ENTRY WAS PUSHED FROM + ADDI R,IOCHNM(U) + PUSHJ P,AIOPOP ;POP BACK INTO CHNL PUSHED FROM + JRST AIOPDL + +IIOPPR: JUMPE I,[JRST 4,CPOPJ] ;IOPUSH + SETZM (R) ;CLOSE CHANNEL + SUBI R,IOCHNM(U) ;GET CHANNEL NUMBER + MOVE R,CHNBIT(R) ;SECOND WORD INTERRUPT BIT + IORM R,IFPIR(U) ;GIVE TO USER + POPJ P, + +;.CALL FORCE +;ARG 1 - CHANNEL NUMBER +;IF ANY OUTPUT IS BUFFERED UP, CAUSES IT TO BE SENT TO THE DEVICE +;(IF FORCE WAS NOT DONE, IT MIGHT NOT BE SENT UNTIL A COMPLETE +;BUFFERFULL HAD BEEN OUTPUT BY THE USER.) + +NFORCE: SKIPA T,[HLRZ T,DFRCTB(D)] ;FORCE USES LH OF TABLE +NFINI1: MOVE T,[HRRZ T,DFRCTB(D)] ;FINISH USES RH OF TABLE + HLRZ A,(R) ;PASS LH(IOCHNM) TO DEVICE ROUTINES + HRRZ D,(R) ;USE RH(IOCHNM) AS BYTE INDEX INTO RSTB + IDIVI D,7 ;TABLE IS IN 5-BIT BYTES TO SAVE SPACE + ADD D,[440500,,RSTB] + IBP D + SOJGE E,.-1 + LDB D,D ;GET BYTE FROM TABLE + XCT T ;GET REAL TABLE ENTRY IN T + JRST (T) ;DISPATCH + +;.CALL FINISH +;ARG 1 - CHANNEL NUMBER +;FIRST DOES A FORCE, THEN WAITS FOR ALL OUTPUT TO GET TO THE DEVICE + +NFINIS: PUSHJ P,NFORCE ;CALL DEV ROUTINE FOR FORCING + POPJ P, + JRST NFINI1 ;THEN CALL DEV ROUTINE FOR WAITING + +;.NETS CH, - UUO VERSION OF .CALL FORCE. +ANETS: PUSHJ P,NFORCE + JRST IOCER1 ;ILLEGAL HARDWARE OPERATION + POPJ P, + +SUBTTL I/O DEVICE DISPATCH TABLES + +COMMENT | + This page tries to document the ITS I/O device dispatch tables and +dispatch environment. It is not completed yet. + +The tables use several different indices, which are: + opnidx - result of device name lookup in DEVTAB + ioidx - result of OPEN; has symbolic values. This is the index + stored in RH of IOCHNM (per-job channel table) + sidx - secondary index from DCHSTB(ioidx) + ridx - secondary index from RSTB(ioidx) + +The following system calls are dispatched through these tables. +There are 11 dispatch routines that each device must specify. +The format is "CALL [table name(index-used) -> device-routine]" + +OPEN [DEVADR(opnidx) -> devO] + "opnidx" is looked up from DEVTAB which holds the device names. + The device's OPEN routine is in the RH of DEVADR. + It must set up the user's IOCHNM word for the channel, + by setting the RH to the right "ioidx" and the LH to whatever + the device wants. + + Context: + +CLOSE [CLSTB(ioidx) -> devCLS] + The device's CLOSE routine is in the RH of CLSTB. + It must zero the user's IOCHNM word for the channel. + + Context: + +IOT, SIOT [IOTTB(ioidx) -> devVarious] + These routines do I/O transfers. The main reason "ioidx" + has so many possible values (causing IOTTB to be large) is + because lots of devices specify different ioidx's for different + modes - input/output, block/unit, image/ascii, etc - in order + to speed up actual I/O transfers, which are probably the most + common device-related system calls. + + Context: + +STATUS [LH(DTSTB(sidx)) -> devSTA] + +WHYINT [RH(DTSTB(sidx)) -> devWHY] + +RCHST, RFNAME [LH(DRFNTB(sidx)) -> devRCH] + +RFPNTR [RH(DRFNTB(sidx)) -> devRFP] + +IOPUSH, IOPOP [LH(RSTBI(ridx)) -> devIOP] + +RESET [RH(RSTBI(ridx)) -> devRST] + +FORCE [LH(DFRCTB(ridx)) -> devFRC] + +FINISH [RH(DFRCTB(ridx)) -> devFIN] + +| + +;DISPATCH TABLE FOR .CLOSE UUO +;TRANSFERED THROUGH USING RIGHT HALF OF IOCHNM WORD AS AN INDEX +;R HAS THE ADDRESS OF THE IOCHNM WORD. +; +;VARIOUS ROUTINES USE THE BITS IN THE L.H. TO DECIDE WHETHER +;A CHANNEL IS ACCEPTABLE FOR SOME OPERATION. +%CLS==1,,525252 +%CLSU==400000 ;USR DEVICE (INFERIOR) +%CLSDO==200000 ;DECTAPE OUTPUT +%CLSJI==100000 ;JOB INPUT +%CLSDI==40000 ;DECTAPE INPUT +%CLSTI==20000 ;TTY INPUT +%CLSCL==10000 ;CORE-LINK DEVICE +%CLSBJ==4000 ;BOJ DEVICE +%CLSQO==2000 ;DISK OUTPUT +%CLSFU==1000 ;NON-INFERIOR USR +%CLSNRM==400 ;STANDARD CLOSE ROUTINE USED FOR THIS DEVICE. + ;RH SHOULD POINT, NOT AT THEROUTINE, BUT AT THE USR-USE PAIR +%CLSQ==200 ;DISK +%CLS6==100 ;PDP6 +%CLSJO==40 ;JOB OUTPUT +%CLSST==20 ;STY DEVICE +%CLST==10 ;TRAP DEVICE + +%CLSJ==%CLSJI\%CLSJO ;EITHER DIRECTION OF JOB DEVICE +%CL1QO==%CLSQO\%CLSQ ;BOTH BITS FOR DISK OUTPUT + +CLSTB: CPOPJ + OFFSET -CLSTB +TYIDN:: REPEAT 2, %CLSTI,,TYICLS ;TYI +TYODN:: REPEAT 2, TYOCLS ;TYO +NLIDN:: REPEAT 4, CPOPJ ;NULL +UWIDN:: REPEAT 4, %CLSU ,,CPOPJ ;USER +FUWIDN:: REPEAT 2, %CLSFU,,CPOPJ ;FOREIGN USER +DNDIRH:: DIRHCL ;DIRHNG +DNTRAP:: %CLST,,CPOPJ ;TRAP +DNLCK:: LCKCL ;LOCK +IFN KS10P,DNUBI:: UBICL ;UNIBUS INTERRUPT +IFN CHAOSP,CHAIDN:: REPEAT 2, CHACLS ;CHAOS NET +IFN NUNITS,[ +DNUACII:: REPEAT 3,[ + %CLSDI,,UTICL ;UTAPE. + %CLSDO,,UTOCL +]] +IFN OLPTP,LPTDN:: REPEAT 2, LPTCLS ;LPT +IFN NLPTP,[ +NLPTDN:: NLPDCL + NLPTCL +] +IFN GLPTP,GLPTDN:: REPEAT 2, GLPCLS +DIRCHN:: REPEAT 4, UTDCLS ;DIRECTORY DEVICE +IFN VIDP,NVIDOP:: REPEAT 2, NVDCLS ;NVIDI +IFN PLTP,PLTDN:: REPEAT 2, %CLSNR,,PLTUSR ;PLOTTER +IFN PTRP,[ +PTPI:: REPEAT 5, %CLSNR,,PTPUSR ;PAPER TAPE PUNCH +] +IFN IMXP,IMPXDN:: REPEAT 4, IMPXCL ;IMX +IFN OMXP,OMPXDN:: REPEAT 4, OMPXCL ;OMX +DCLUAI:: %CLSCL,,CLCLRA ;CORE LINK + %CLSCL,,CLCLWU + REPEAT 2,[ + %CLSCL,,CLCLRB + %CLSCL,,CLCLWB + ] +IFN PTRP,[ +REDUAI:: REPEAT 5, PTRCLS ;PAPER TAPE READER +] +IFN 340P,[ +DN340B:: REPEAT 4, ADCL1 ;340 +; ADCL1 ;IDS +] +IFN CODP,[ +CODDN:: REPEAT 2, CODCLS ;CODE DEV +] +DQUAI:: %CLSQ ,,QICL ;DISK + %CL1QO,,QOCLR + %CLSQ ,,QICL + %CL1QO,,QOCL + %CLSQ ,,QICL + %CL1QO,,QOCL +IFN VIDP,DNVDIU:: REPEAT 4, TVCCLS ;TVC +IFN PDP6P,PDPUIO:: REPEAT 4, %CLS6 ,,PDPCLS ;USR IN PDP10 MODE +IFN TABP,DTABUI:: REPEAT 2, %CLSNR,,TABUSR ;TABLET +IFN NMTCS,[ +MTUAIX:: REPEAT 3, MTICL ;MAG TAPE + REPEAT 3, MTOCL + ] +JDUAI:: REPEAT 3,[ + %CLSJI,,JOBCLS ;JOB DEVICE + %CLSJO,,JOBCLS + ] +BDUAI:: REPEAT 6, %CLSBJ,,CPOPJ ;BOJ +IIOPOP:: [JRST 4,CPOPJ] ;INTERRUPT ON IOPOP DEVICE +ISPY:: CPOPJ ;SPY +STYDUI:: REPEAT 2,[ ;PSEUDO TTY + %CLSST,,STYICL + %CLSST,,STYOCL + ] +IFN NCPP,NETDUI:: REPEAT 4, NETCLS ; Arpanet NCP +IFN TCPP,TCPDUI:: REPEAT 4, TCPCLS ; Internet TCP +IFN INETP,IPQDN:: IPQCLS ; Internet Queue +IFN MSPP,MSPIO:: MSCLOS ;MESS SWITCHER (DM) +IFN STKP,STKDP:: STKCLS ;STANFORD KEYBOARD +IFN NTYP,NTYIT:: REPEAT 4, NTYCLS ;A KLUDGE ON THE NTY + OFFSET 0 +IF2,IFN .-CLSTB-LIOTTB,.ERR BARF AT CLSTB + +;DISPATCH TABLE FOR .IOT UUO +;TRANSFERED THROUGH USING RIGHT HALF OF I/O CHANNEL WORD AS AN INDEX +%IOT==1,,525252 +%IOTBK==400000 ;4.9 = 1 => BLOCK = 0 => UNIT +%IOTOT==200000 ;4.8 = 1 => OUTPUT = 0 => INPUT " +%IOTBP==100000 ;4.7 = 1 => THERE IS A SPECIAL ROUTINE FOR SIOT, + ;AND ITS ADDRESS IS -1 + RH(IOTTB WORD). +%IOTSP==40000 ;4.6 => THIS DEVICE IS FUNNY. SIOT ISN'T ALLOWED, + ;AND IOT LETS THE DEVICE RTN DO ALL THE WORK. + ;PRESENT ONLY FOR UNIT INPUT MODES. +%IOT10==20000 ;4.5 => THIS CHANNEL WAS OPENED WITH BIT 1.4 SET IN MODE +%IOTIM==10000 ;4.4 => THIS CHANNEL WAS OPENED WITH BIT 1.3 (IMAGE MODE) SET IN MODE +; 4000 ;4.3 COPIES %IOTBK. THUS, BITS 4.5-4.2 REFLECT THE BOTTOM 4 BITS +; 2000 ;4.2 COPIES %IOTOT. OF THE OPEN-MODE. +%IOTOM==36000 ;BITS 4.5 - 4.2 + +%IOTBO==606000 ;BLOCK OUTPUT. +%IOTBI==404000 ;BLOCK INPUT. +%IOTUO==202000 ;UNIT OUTPUT. +%IOTUI==000000 ;UNIT INPUT. + +IOTTB: IOCER8 + OFFSET -IOTTB +TYIDN:: %IOTUI,,TYI ;TTY ENTRIES MUST BE COMPACT +TYIBN:: %IOTBI,,TTYBI +TYODN:: %IOTUO,,TYO (%IOTBP) +TYOBN:: %IOTBO,,TTYBO ;LAST TTY DEVICE +NLIDN:: %IOTUI,,NULI +NLBIDN:: %IOTBI,,NULBI +NLODN:: %IOTUO,,CPOPJ +NLBDN:: %IOTBO,,NULBOD +UWIDN:: %IOTUI,,UWI (%IOTIM) +UBIDN:: %IOTBI,,UBI +UWODN:: %IOTUO,,UWO (%IOTIM) +UBODN:: %IOTBO,,UBO +FUWIDN:: %IOTUI,,UWI (%IOT10) +FUBIDN:: %IOTBI,,UBI (%IOT10) +DNDIRH:: %IOTUI,,IOCR10 +DNTRAP:: TRPDEV +DNLCK:: %IOTUO,,IOCR10 +IFN KS10P,[ +DNUBI:: %IOTUI,,IOCR10 +];KS10P +IFN CHAOSP,[ +CHAIDN:: %IOTUI+%IOTBP,,CHAUI +CHAODN:: %IOTUO+%IOTBP,,CHAUO +];CHAOSP +IFN NUNITS,[ +DNUACII:: %IOTUI,,UASCII +DNUACCO:: %IOTUO,,UASCCO +DNUBKI:: %IOTBI,,UBLKI +DNUBKO:: %IOTBO,,UBLKO +DNUDTI:: %IOTUI,,UDATAI (%IOTIM) +DNUDTO:: %IOTUO,,UDATAO (%IOTIM) +] +IFN OLPTP,[ +LPTDN:: %IOTUO,,PILPT1 +LPTBN:: %IOTBO,,BLPTO +] +IFN NLPTP,[ +NLPTDN:: %IOTUO,,NLPT1 +NLPTBN:: %IOTBO,,BNLPTO +] +IFN GLPTP,[ +GLPTDN:: %IOTUO,,GLPTDO (%IOTBP) +GLPTBN:: %IOTBO,,GLPTBO +] +DIRCHN:: %IOTUI,,DIRCH +DIRBN:: %IOTBI,,DIRB +NDATAI:: %IOTUI,,DDATAI (%IOTIM+%IOTBP) +NBLKI:: %IOTBI,,DBLKI (%IOTIM) +IFN VIDP,[ +NVIDOP:: %IOTUI,,NVIDIT (%IOTSP) +BNVIDO:: %IOTBI,,BNVIDI +] +IFN PLTP,[ +PLTDN:: %IOTUO,,PLOT +PLTBN:: %IOTBO,,BPLOT +] +IFN PTRP,[ +PTPI:: %IOTUO,,PIPUN (%IOT10) +PTPA:: %IOTUO,,APIPUN +PTPB:: %IOTBO,,BPIPUN +PTPWA:: %IOTUO,,WAPIPN (%IOTIM) +PTPWB:: %IOTBO,,WBPIPN (%IOTIM) +] +IFN IMXP,[ +IMPXDN:: %IOTUI,,IMPXS (%IOTSP) +IMXDN:: %IOTUI,,IMPXS1 (%IOTSP) +BIMXDN:: %IOTBI,,BIMXS1 (%IOTSP) +BIMPXD:: %IOTBI,,BIMPXS (%IOTSP) +] +IFN OMXP,[ +OMPXDN:: %IOTUO,,OMPXS (%IOTSP) +OMXDN:: %IOTUO,,OMXDS (%IOTSP) +BOMXDN:: %IOTBO,,BOMXDS (%IOTSP) +BOMPXD:: %IOTBO,,BOMPXS (%IOTSP) +] +DCLUAI:: %IOTUI,,CLUAI +DCLUAO:: %IOTUO,,CLUAO +DCLBI:: %IOTBI,,CLBI +DCLBO:: %IOTBO,,CLBO +DCLUBI:: %IOTUI,,CLUBI (%IOTIM) +DCLUBO:: %IOTUO,,CLUBO (%IOTIM) +IFN PTRP,[ +REDUAI:: %IOTUI,,PTRUAI +REDBAI:: %IOTBI,,PTRBAI +REDUII:: %IOTUI,,PTRUII (%IOTIM) +REDBII:: %IOTBI,,PTRBII (%IOTIM) +REDUTI:: %IOTUI,,PTRUTI (%IOT10) +] +IFN 340P,[ +DN340B:: %IOTBO,,340B ;340 ENTRIES MUST BE COMPACT; BLOCK FIRST, THEN UNIT +DN340W:: %IOTUO,,340W (%IOTSP) +DN340C:: %IOTUO,,340C (%IOTSP) +DN340H:: %IOTUO,,340H (%IOTSP) +;DN340I:: %IOTUO,,340I (%IOTSP) +DN340L:: ;LAST 340 DEVICE ENTRY +] +IFN CODP,[ +CODDN:: %IOTUO,,SEND +CODBN:: %IOTBO,,BSEND +] +DQUAI:: %IOTUI,,QUAI (%IOTBP) +DQUAO:: %IOTUO,,QUAO (%IOTBP) +DQBI:: %IOTBI,,QBI +DQBO:: %IOTBO,,QBO +DQUII:: %IOTUI,,QUII (%IOTIM %IOTBP) +DQUIO:: %IOTUO,,QUIO (%IOTIM %IOTBP) +IFN VIDP,[ +DNVDIU:: %IOTUI,,RNVDIU (%IOTSP) +DNVDIB:: %IOTBI,,RNVDIB (%IOTSP) +DNVDOU:: %IOTUO,,RNVDOU (%IOTSP) +DNVDOB:: %IOTBO,,RNVDOB (%IOTSP) +] +IFN PDP6P,[ +PDPUIO:: %IOTUO,,UWO ;BUT JOB WILL BE -1 TO INDICATE PDP6 +PDPBIO:: %IOTBO,,UBO +PDPUII:: %IOTUI,,UWI +PDPBII:: %IOTBI,,UBI +] +IFN TABP,[ +DTABUI:: %IOTUI,,UTABI +DTABBI:: %IOTBI,,BTABI +] +IFN NMTCS,[ +MTUAIX:: %IOTUI,,MTUAI (%IOTBP) ;MAGTAPE +MTUIIX:: %IOTUI,,MTUII (%IOTIM %IOTBP) +MTBIX:: %IOTBI,,MTBI +MTUAOX:: %IOTUO,,MTUAO (%IOTBP) +MTUIOX:: %IOTUO,,MTUIO (%IOTIM %IOTBP) +MTBOX:: %IOTBO,,MTBO +] +JDUAI:: %IOTUI,,JBUI(%IOTBP) +JDUAO:: %IOTUO,,JBUI(%IOTBP) +JDBI:: %IOTBI,,JBBI +JDBO:: %IOTBO,,JBBI +JDUII:: %IOTUI,,JBUI (%IOTBP %IOTIM) +JDUIO:: %IOTUO,,JBUI (%IOTBP %IOTIM) +BDUAI:: %IOTUI,,BJUI +BDUAO:: %IOTUO,,BJUO +BDBI:: %IOTBI,,BJBI +BDBO:: %IOTBO,,BJBO +BDUII:: %IOTUI,,BJUI (%IOTIM) +BDUIO:: %IOTUO,,BJUO (%IOTIM) +IIOPOP:: [JRST 4,CPOPJ] ;INTERRUPT ON IOPOP DEVICE +ISPY:: %IOTUI,,SPYI +STYDUI:: %IOTUI,,STTYI ;PSEUDO TTY +STYDUO:: %IOTUO,,STTYW +STYDBI:: %IOTBI,,STTBI +STYDBO:: %IOTBO,,STTBO +IFN NCPP,[ +NETDUI:: %IOTUI,,NETI +NETDUO:: %IOTUO,,NETW (%IOTBP) +NETDBI:: %IOTBI,,NETBI +NETDBO:: %IOTBO,,NETBO +] +IFN TCPP,[ +TCPDUI:: %IOTUI,,TCPI (%IOTBP) +TCPDUO:: %IOTUO,,TCPW (%IOTBP) +TCPDBI:: %IOTBI,,TCPBI +TCPDBO:: %IOTBO,,TCPBO +] +IFN INETP,[ +IPQDN:: IPQIO ; No I/O calls used on this dev! +] +IFN MSPP,[ +MSPIO:: IOCR10 +] +IFN STKP,[ +STKDP:: STKI +] +IFN NTYP,[ +NTYIT:: %IOTUI,,NTYTI ;KLUDGE FOR FAST, LARGE BUFFER ON NTY +NTYOT:: %IOTUO,,NTYTO +NTYBIT:: %IOTBI,,NTYBI +NTYBOT:: %IOTBO,,NTYBO +] + OFFSET 0 +LIOTTB==.-IOTTB + +;TABLES FOR VARIOUS CHANNEL STATUS CALLS + +;DCHSTB - INDEXED BY IOTTB INDEX (RH OF IOCHNM) +;LH SIXBIT MAIN DEVICE NAME +;1.1-2.3 INDEX INTO THE NEXT TWO TABLES +;2.4-2.9 SYSTEM PERIPHERAL DEVICE CODE (FOR .STATUS) +.SEE DCHSTB ;ASSEMBLED SECOND TO GET VALUES OF THE TEMPORARY %%dev SYMBOLS. + +;DSTSTB - INDEX FROM DCHSTB +;LH STATUS ROUTINE, RH WHYINT ROUTINE (OPNL34 IF DEVICE DOESN'T GIVE 2ND WD INTS) + +DSTSTB: CPOPJ,,OPNL44 ;0 CHANNEL NOT OPEN + STDSTA,,OPNL34 ;1 RANDOM DEVICE + CPOPJ,,OPNL34 ;2 OTHER KIND OF RANDOM DEVICE + STATYI,,TYIWHY ;3 TTY INPUT + STATYO,,TYOWHY ;4 TTY OUTPUT + CPOPJ,,OPNL34 ;5 USR DEVICE + CPOPJ,,OPNL34 ;6 DIR "DEVICE" + CLISTA,,OPNL34 ;7 CORE LINK INPUT + STDSTA,,OPNL34 ;10 CORE LINK OUTPUT + CPOPJ,,OPNL34 ;11 DISK + JBSTAT,,OPNL22 ;12 JOB DEVICES (WHYINT SHOULDN'T GET HERE) + CPOPJ,,OPNL34 ;13 BOJ DEVICE + STASTI,,STIWHY ;14 STY INPUT + STASTO,,STOWHY ;15 STY OUTPUT + CPOPJ,,TRPDEV ;16 TRAP DEVICE + CPOPJ,,OPNL34 ;17 DIRHNG DEVICE + CPOPJ,,OPNL34 ;20 SPY DEVICE + CPOPJ,,OPNL34 ;21 LOCK DEVICE +OFFSET -DSTSTB ;BEGIN OPTIONAL DEVICES +IFN KS10P, %%UBI:: CPOPJ,,UBIWHY +IFN NMTCS, %%MT:: STAMTC,,OPNL34 +IFN NUNITS,%%UTP:: CPOPJ,,OPNL34 +IFN OLPTP, %%OLP:: STALPT,,OPNL34 +IFN NCPP, %%NET:: STANET,,NETWHY +IFN TCPP, %%TCP:: TCPSTA,,TCPWHY +IFN INETP, %%IPQ:: IPQSTA,,IPQWHY +IFN CHAOSP,%%CHA:: CPOPJ,,CHAWHY +OFFSET 0 + +;DRFNTB - INDEX FROM DCHSTB +;LH RFNAME ROUTINE, RH RFPNTR ROUTINE OR OPNL34 IF NOT RANDOM ACCESS + +DRFNTB: CPOPJ,,OPNL44 ;0 CHNL NOT OPEN + CPOPJ,,OPNL34 ;1 RANDOM DEVICE + CPOPJ,,OPNL34 ;2 OTHER KIND OF RANDOM DEVICE + RCHTTY,,OPNL34 ;3 TTY INPUT + RCHTTY,,OPNL34 ;4 TTY OUTPUT + RCHUSR,,RFPUSR ;5 USR DEVICE + RCHDIR,,OPNL34 ;6 DIR "DEVICE" + RCHCLO,,OPNL34 ;7 CORE LINK INPUT + RCHCLO,,OPNL34 ;10 CORE LINK OUTPUT + RCHQSK,,RFPQSK ;11 DISK + RFNJOB,,RFPJOB ;12 JOB DEVICES + RCHBOJ,,OPNL34 ;13 BOJ DEVICE + RCHSTY,,OPNL34 ;14 STY INPUT + RCHSTY,,OPNL34 ;15 STY OUTPUT + CPOPJ,,CPOPJ ;16 TRAP DEVICE + RCHDRH,,OPNL34 ;17 DIRHNG DEVICE + SPYRCH,,OPNL34 ;20 SPY DEVICE + LCKRCH,,OPNL34 ;21 LOCK DEVICE +OFFSET -DRFNTB ;BEGIN OPTIONAL DEVICES +IFN KS10P, %%UBI:: UBIRCH,,OPNL34 +IFN NMTCS, %%MT:: RCHMGT,,OPNL34 +IFN NUNITS,%%UTP:: RCHUTP,,OPNL34 +IFN OLPTP, %%OLP:: CPOPJ,,OPNL34 +IFN NCPP, %%NET:: NETRCH,,OPNL34 +IFN TCPP, %%TCP:: TCPRCH,,TCPRFP +IFN INETP, %%IPQ:: IPQRCH,,IPQRFP +IFN CHAOSP,%%CHA:: CHARCH,,OPNL34 +OFFSET 0 +IFN <.-DRFNTB>-, .ERR DRFNTB & DSTSTB NOT SAME LENGTH + +DEFINE XX NTIMES,DEVNAM,DN,SNXXX,IDX +IFNB DN, DN==:.-DCHSTB ;CHECK THAT DCHSTB IS IN SAME ORDER AS IOTTB +IFG SIXBIT/DEVNAM/, ZZ==[SIXBIT/DEVNAM/] ;DECIDE WHETHER FITS IN LH +.ELSE [ +IFE SIXBIT/DEVNAM/&777777, ZZ==(SIXBIT/DEVNAM/) +.ELSE ZZ==[SIXBIT/DEVNAM/] +] +REPEAT NTIMES, ZZ,,SNXXX_14+IDX +TERMIN + +DCHSTB: XX 1,,,,0 ;CHNL NOT OPEN + XX 2,TTY,TYIDN,,3 ;TTY INPUT + XX 2,TTY,TYODN,,4 ;TTY OUTPUT + XX 4,NUL,NLIDN,SNNUL,1 ;NUL DEVICE + XX 4,USR,UWIDN,SNUSR,5 ;USR DEVICE + XX 2,USR,FUWIDN,SNFUSR,5 ;FOREIGN USR + XX 1,DIRHNG,DNDIRH,SNDIRH,17 ;DIRHNG + XX 1,TRAP,DNTRAP,SNTRAP,16 ;TRAP + XX 1,LOCK,DNLCK,SNLCK,21 ;LOCK +IFN KS10P, XX 1,UBI,DNUBI,SNUBI,%%UBI ;UBIBUS INTERRUPT +IFN CHAOSP, XX 2,CHAOS,CHAIDN,SNCHA,%%CHA ;CHAOS NET +IFN NUNITS, XX 6,UT,DNUACII,SNUTC,%%UTP ;MICRO TAPE +IFG LPTP-1, XX 2,OLP,LPTDN,SNLPD,%%OLP ;DATA PRODUCTS LPT IN 2-LPT SYSTEM +.ELSE IFN OLPTP, XX 2,LPT,LPTDN,SNLPD,%%OLP ;DATA PRODUCTS LPT +IFN NLPTP, XX 2,LPT,NLPTDN,SNLPV,1 ;"VOGUE" LPT (ACTUALLY ODEC) +IFN GLPTP, XX 2,LPT,GLPTDN,SNLPV,1 ;GOULD LPT + XX 4,DIR,DIRCHN,SNDIR,6 ;DIR "DEVICE" +IFN VIDP, XX 2,NVD,NVIDOP,SNBAT,2 ;VIDISSECTOR +IFN PLTP, XX 2,PLT,PLTDN,SNPLT,1 ;PLOTTER +IFN PTRP, XX 5,PTP,PTPI,SNPTP,1 ;PAPER TAPE PUNCH +IFN IMXP, XX 4,IMX,IMPXDN,SNIMPX,1 ;INPUT A/D MULTIPLEXOR +IFN OMXP, XX 4,OMX,OMPXDN,SNOMPX,1 ;OUTPUT A/D MULTIPLEXOR + XX 3,CLO,DCLUAI,SNCLK,7 ;CORE LINK INPUT + XX 3,CLO,DCLBO,SNCLK,10 ;CORE LINK OUTPUT +IFN PTRP, XX 5,PTR,REDUAI,SNPTR,1 ;PAPER TAPE READER +IFN 340P, XX 4,DIS,DN340B,SN340,2 ;340 DISPLAY +;IFN 340P, XX 1,IDS,DN340I,SN340I,2 ;340 INTERPRETIVE DISPLAY +IFN CODP, XX 2,COD,CODDN,SNCOD,1 ;CODE + XX 6,DSK,DQUAI,SN2311,11 ;DISK +IFN VIDP, XX 4,TVC,DNVDIU,SNBAT,2 ;TV CAMERA +IFN PDP6P, XX 4,PDP,PDPUIO,SNPDP,5 ;PDP-6 DEVICE +IFN TABP, XX 2,TAB,DTABUI,SNTAB,2 ;TABLET +IFN NMTCS, XX 6,MT0,MTUAIX,SNMTC,%%MT ;MAGTAPE + XX 6,JOB,JDUAI,SNJOB,12 ;JOB DEVICES + XX 6,BOJ,BDUAI,SNBOJ,13 ;BOJ DEVICE + XX 1,IIP,IIOPOP,0,2 ;INTERRUPT-ON-IOPOP DEVICE + XX 1,SPY,ISPY,SNSPY,20 ;SPY +REPEAT 2,[ + XX 1,STY,,SNSTY,14 ;STY INPUT + XX 1,STY,,SNSTY,15 ;STY OUTPUT +] +IFN NCPP, XX 4,NET,NETDUI,SNNET,%%NET ; Arpanet NCP +IFN TCPP, XX 4,TCP,TCPDUI,SNTCP,%%TCP ; Internet TCP +IFN INETP, XX 1,IPQ,IPQDN,SNIPQ,%%IPQ ; Internet Queue +IFN MSPP, XX 1,MSP,MSPIO,SNMSP,2 ;MS SWITCH HACK +IFN STKP, XX 1,STK,STKDP,SNSTK,2 ;STANFORD KEYBOARD +IFN NTYP, XX 4,NTY,NTYIT,SNNUL,2 ;NTY 11 KLUDGE + +IFN .-DCHSTB-LIOTTB,.ERR BARF AT DCHSTB +EXPUNGE XX,%%UBI,%%MT,%%UTP,%%OLP,%%NET,%%TCP,%%CHA,%%IPQ + +DCHSTE==.-1 ;END FOR GETSYS (CHDEVS) + +;RSTB - INDEXED BY IOTTB INDEX FROM RH(IOCHNM) +;THIS TABLE IS IN 5-BIT BYTES; THE VALUES ARE THE INDICES +;INTO THE RSTB1 AND DFRCTB TABLES. +.SEE RSTB ;ASSEMBLED SECOND TO GET VALUES OF TEMPORARY %%dev SYMBOLS. + +;RSTB1 - INDEX FROM RSTB (BELOW) +;LH IOPUSH/POP ROUTINE, RH RESET ROUTINE +RSTB1: CPOPJ,,CPOPJ ;0 RANDOM DEVICE + TYIIOP,,TYIRS ;1 TTY INPUT + TYOIOP,,TYORS ;2 TTY OUTPUT + CPOPJ,,USRST ;3 USR DEVICE + CPOPJ,,JBIRS ;4 JOB INPUT + CPOPJ,,JBORS ;5 JOB OUTPUT + IIOPPR,,[JRST 4,CPOPJ] ;6 INTERRUPT ON IOPOP DEVICE + STYIIP,,STYIRS ;7 STY INPUT + STYOIP,,STYORS ;10 STY OUTPUT + CPOPJ,,CPOPJ ;11 DISK OUTPUT + DIRHIP,,CPOPJ ;12 DIRHNG + CPOPJ,,TRPDEV ;13 TRAP + OFFSET -RSTB1 ;OPTIONAL DEVICES BEGIN HERE +IFN KS10P, %%UBI:: UBIIOP,,CPOPJ +IFN OLPTP, %%LPT:: CPOPJ,,LPTRS +IFN NLPTP, %%NLP:: CPOPJ,,NLPTRS +IFN PLTP, %%PLT:: CPOPJ,,PLTRS +IFN PTRP, %%PTR:: CPOPJ,,PTRRS +IFN PTRP, %%PTP:: CPOPJ,,PUNCLR +IFN IMXP, %%IMX:: CPOPJ,,IMPXRS +IFN 340P, %%340:: CPOPJ,,DSIZAP +IFN CODP, %%COD:: CODIOP,,CODRS +IFN PDP6P, %%PDP:: PDPIOP,,PDPRST +IFN TABP, %%TAB:: CPOPJ,,TABCLR +IFN NCPP, %%NET:: NETIOP,,NETRS +IFN TCPP, %%TCP:: TCPIOP,,TCPRST +IFN INETP, %%IPQ:: IPQIOP,,IPQRST +IFN STKP, %%STK:: CPOPJ,,STKRS +IFN CHAOSP,%%CHA:: CHAIOP,,CPOPJ + OFFSET 0 + +;DFRCTB - INDEX FROM RSTB (BELOW) +;LH FORCE ROUTINE, RH FINISH ROUTINE +DFRCTB: OPNL34,,OPNL34 ;0 RANDOM DEVICE + OPNL2,,OPNL2 ;1 TTY INPUT (ILLEGAL) + POPJ1,,TTYFIN ;2 TTY OUTPUT + OPNL34,,OPNL34 ;3 USR + OPNL2,,OPNL2 ;4 JOB (SHOULDN'T GET HERE?) + OPNL22,,OPNL22 ;5 JOB (SHOULDN'T GET HERE?) + OPNL22,,OPNL22 ;6 IIP (SHOULDN'T GET HERE) + OPNL2,,OPNL2 ;7 STY INPUT (ILLEGAL) + POPJ1,,STYFIN ;10 STY OUTPUT + QSKFRC,,QSKFIN ;11 DISK OUTPUT + OPNL34,,OPNL34 ;12 DIRHNG + TRPDEV,,TRPDEV ;13 TRAP + OFFSET -DFRCTB ;OPTIONAL DEVICES BEGIN HERE +IFN KS10P, %%UBI:: OPNL34,,OPNL34 +IFN OLPTP, %%LPT:: POPJ1,,POPJ1 ;NEED TO WRITE THESE +IFN NLPTP, %%NLP:: POPJ1,,POPJ1 ;NEED TO WRITE THESE +IFN PLTP, %%PLT:: POPJ1,,POPJ1 ;NEED TO WRITE THESE +IFN PTRP, %%PTR:: OPNL34,,OPNL34 +IFN PTRP, %%PTP:: POPJ1,,PUNFIN +IFN IMXP, %%IMX:: OPNL34,,OPNL34 +IFN 340P, %%340:: OPNL34,,OPNL34 +IFN CODP, %%COD:: POPJ1,,CODFIN +IFN PDP6P, %%PDP:: OPNL34,,OPNL34 +IFN TABP, %%TAB:: OPNL34,,OPNL34 +IFN NCPP, %%NET:: NETFRC,,NETFIN +IFN TCPP, %%TCP:: TCPFRC,,TCPFIN +IFN INETP, %%IPQ:: IPQFRC,,IPQFIN +IFN STKP, %%STK:: OPNL34,,OPNL34 +IFN CHAOSP,%%CHA:: CHAFRC,,CHAFIN + OFFSET 0 + +;TABLE OF INDICES INTO THE RSTB1, DFRCTB TABLES ON THE PRECEDING PAGE +;THESE INDICES ARE UNRELATED TO THE INDICES IN DCHSTB A COUPLE PAGES BACK. +;NOTE THAT THE %% SYMBOLS ARE PURELY TEMPORARY AND EXPUNGED AT THE BOTTOM OF THIS PAGE. + +RSTB: .BYTE 5 + + 0 ;CHNL NOT OPEN + REPEAT 2,1 ;TTY INPUT + REPEAT 2,2 ;TTY OUTPUT + REPEAT 4,0 ;NUL DEVICE + REPEAT 4,3 ;USR DEVICE + REPEAT 2,0 ;FOREIGN USR + 12 ;DIRHNG + 13 ;TRAP + 0 ;LOCK +IFN KS10P, %%UBI ;UNIBUS INTERRUPT +IFN CHAOSP, REPEAT 2,%%CHA +IFN NUNITS, REPEAT 6,0 ;DEC TAPE +IFN OLPTP, REPEAT 2,%%LPT +IFN NLPTP, REPEAT 2,%%NLP +IFN GLPTP, REPEAT 2,0 + REPEAT 4,0 ;DIR "DEVICE" +IFN VIDP, REPEAT 2,0 +IFN PLTP, REPEAT 2,%%PLT +IFN PTRP, REPEAT 5,%%PTP +IFN IMXP, REPEAT 4,%%IMX +IFN OMXP, REPEAT 4,0 + REPEAT 6,0 ;CORE LINK. +IFN PTRP, REPEAT 5,%%PTR +IFN 340P, REPEAT 4,%%340 +;IFN 340P, 0 +IFN CODP, REPEAT 2,%%COD ;CODE + REPEAT 3, 0 ? 11 ;DISK IN, DISK OUT +IFN VIDP, REPEAT 4,0 +IFN PDP6P, REPEAT 4,%%PDP ;PDP-6 DEVICE +IFN TABP, REPEAT 2,%%TAB +IFN NMTCS, REPEAT 6,0 ;MAGTAPE + REPEAT 3,[4 + 5 + ] ;JOB + REPEAT 3,[0 ;BOJ INPUT + 0 ;BOJ OUTPUT + ] ;BOJ + 6 ;INTERRUPT ON IOPOP DEVICE + 0 ;SPY + 7 ? 10 ? 7 ? 10 ;PSEUDO-TTY +IFN NCPP, REPEAT 4,%%NET ;NET RESET INR/INS +IFN TCPP, REPEAT 4,%%TCP ; TCP RESET +IFN INETP, %%IPQ ; Internet Queue +IFN MSPP, 0 ;MS SWITCH HACK +IFN STKP, %%STK ;STANFORD KEYBOARD +IFN NTYP, REPEAT 4,0 ;NTY 11 KLUDGE + +IFN LIOTTB-.BYTC,.ERR BARF AT RSTB + .BYTE +EXPUNGE %%UBI,%%LPT,%%NLP,%%PLT,%%PTR,%%PTP,%%IMX,%%340,%%COD,%%PDP,%%TAB,%%NET,%%TCP,%%STK,%%CHA,%%IPQ + +DEFINE DVHR X,Y +X!Y!TERMIN + +DEFINE DV NAME,OPNRTE,BITS,TAG + SIXBIT/NAME/ +DVHR [DEFINE DVHR X,Y +X!][TAG BITS,,OPNRTE +Y!TERMIN] +TERMIN + +;DEVICE TABLES FOR AOPEN +; +;DEVTAB SIXBIT NAME +;DEVADR + %DVIN==400000 ;4.9 DEVICE CAN DO INPUT + %DVOUT==200000 ;4.8 DEVICE CAN DO OUTPUT + %DVDIR==100000 ;4.7 DEVICE CAN GIVE DIRECTORY + %DVDEL==40000 ;4.6 ALLOW DELETE/RENAME + %DVLNK==20000 ;4.5 ALLOW MLINK + ;RIGHT HALF, OPEN ROUTINE ADDRESS +%DV==1,,520000 ;BIT TYPEOUT MASK + +DEVTAB: +IFN NLPTP, DV LPT,NLPTO,%DVOUT +IFG OLPTP-NLPTP,DV LPT,LPTO,%DVOUT +IFG LPTP-1, DV OLP,LPTO,%DVOUT +IFN GLPTP, DV LPT,GLPTO,%DVOUT +IFN TTLPTP, DV LPT,LPTO,%DVOUT + + DV DSK,QSKO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK,DVAQSK: + DV COM,COMO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK + MNAME [ DV ],QSKO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK ;"AI:" ON + ; AI, ETC. + DV SYS,SYSO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK + DV DNRF,DNRFO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK ;DSK NO REF DATE + DV DNR,DNRFO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK ;DSK NO REF DATE + DV DIRHNG,DIRHO,%DVIN + DV TRAP,TRPDEV,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK + DV LOCK,LCKO,%DVOUT + DV UBI,UBIO,%DVIN + DV TTY,TTYO1,%DVIN+%DVOUT+%DVDIR + DV NUL,NULO,%DVIN+%DVOUT + DV USR,USRO,%DVIN+%DVOUT +IFN VIDP, DV NVD,NVIDI,%DVIN+%DVOUT +IFN CHAOSP, DV CHAOS,CHASO,%DVIN+%DVOUT +IFN NCPP, DV NET,NETO,%DVIN+%DVOUT +IFN TCPP, DV TCP,TCPO,%DVIN+%DVOUT +IFN INETP, DV IPQ,IPQO,%DVIN+%DVOUT +IFN MSPP, DV IPC,IPCO,%DVIN+%DVOUT + DV STY,STTYO,%DVIN+%DVOUT + DV JOB,JOBO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK,DVAJOB: + DV BOJ,BOJO,%DVIN+%DVOUT + DV OJB,JOBO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK +IFN STKP, DV STK,STKO,%DVIN +IFN PLTP, DV PLT,PLOTO,%DVOUT +IFN PLTP, DV IPL,IPLO,%DVOUT ;INTERPRETED PLOTTER +IFN XGP, DV XPL,XPLO,%DVOUT +IFN IMXP, DV IMX,IMPXO,%DVIN +IFN OMXP, DV OMX,OMPXO,%DVOUT +IFN PTRP, DV PTR,PTRO,%DVIN +IFN PTPP, DV PTP,PTPO,%DVOUT +IFN 340P, DV DIS,DISO,%DVOUT ;340 AS OUTPUT DEVICE +;IFN 340P, DV IDS,IDISO,%DVOUT ;340 AS INTERPRETED DISPLAY + DV CLU,CLUO,%DVIN+%DVOUT+%DVDIR+%DVDEL + DV CLO,CLOO,%DVIN+%DVOUT+%DVDIR+%DVDEL + DV CLI,CLIO,%DVOUT+%DVDIR+%DVDEL + DV CLA,CLAO,%DVIN+%DVDIR+%DVDEL +IFN CODP, DV COD,CODO,%DVOUT +IFN VIDP, DV TVC,TVCO,%DVIN+%DVOUT + DV ERR,ERRO,%DVIN +IFN TPLP+TTLPTP&DEMON, DV TPL,TPLO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK +IFN TABP, DV TAB,TABO,%DVIN + DV SPY,SPYO,%DVIN + DV COR,CORO,%DVDIR ;DIR=LAST LINE OF TTY^F +IFN NTYP, DV NTY,NTYOPN,%DVIN+%DVOUT ;NTY 11 KLUDGE + +NDEVS==.-DEVTAB + +DVT1: DV TTY,TTYO,%DVIN+%DVOUT+%DVDIR + DV TY,TTYO,%DVIN+%DVOUT+%DVDIR + DV T,TTYO,%DVIN+%DVOUT+%DVDIR +IFN NUNITS, DV UT,UTO,%DVIN+%DVOUT+%DVDIR+%DVDEL,DVAUT: + DV STY,STTYOA,%DVIN+%DVOUT + DV ST,STTYOA,%DVIN+%DVOUT + DV S,STTYOA,%DVIN+%DVOUT + DV DSK,QSKUO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK ;PARTICULAR UNIT + DV DK,QSKUO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK ;PARTICULAR UNIT + DV PK,QSKPO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK ;PARTICULAR PACK + DV P,QSKPO,%DVIN+%DVOUT+%DVDIR+%DVDEL+%DVLNK ;PARTICULAR PACK +IFN NMTCS, DV MT,MAGTO,%DVIN+%DVOUT ;MAGTAPE + +NDV1==.-DVT1 +EDEVS==.-1 ;END FOR GETSYS (DEVS) + +DEVADR: DVHR +IFN .-DEVADR-NDEVS-NDV1,.ERR DVHR LOST + +SUBTTL .OPER, .CALL DISPATCH + +AOPER: MOVE J,R ;AC FIELD OF UUO + ADDI R,IOCHNM(U) ;SET UP IO CHANNEL REFERENCE POINTER + CAIL C,MXOPR ;SKIP IF UUO E FIELD IS LESS THAN MAX OPR + JRST ILUUO ;ILLEGAL OPER + JRST @OPRDSP(C) ;LEGAL OPER-- DISPATCH ON E FIELD OF UUO + +OPRDSP: ILUUO + OPRIRP A!X ;AITYI,ALISTEN,ASLEEP,ETC. + +; +;CALL DISPATCH +; +ACALL: MOVE B,C ;SET UP COPY OF ERR ADR NOT TO BE RELOCATED + JRST @CALDIS(R) ;DISPATCH INDEX OF UUO'S AC FIELD + +CALDIS: ASYSC + ADISMIS + ALOSE + ATRANAD + AVALRET ;4 + AUTRAN + UACORE + ATRNDL + ADSTART ;10 + AFDELE + ADSTL + ASUSET + ALTPEN ;14 + AVSCAN + APOTSET +REPEAT 20-.+CALDIS,ILUUO + +SUBTTL MISCELLANEOUS UUO'S + +;SHUT DOWN SYSTEM + +ASHUTD: UMOVE C,(J) ;Arg is time to down in thirtieths. + JUMPL C,AREVIV ;Negative time means REVIVE. + CAMG C,[43200.*30.*60.] ;If time is longer than thirty days + CAIGE C,5*60.*30. ; or less than five minutes + POPJ P, ; Fail (prevent clock delta-T from losing). + ADD C,TIME ;Interval+now is when we will die. + PUSHJ P,SWTL ;Seize shutdown lock. + SHUTLK + SKIPGE SHUTDN ;Already down? + JRST LSWPOP ; Yes. + PUSHJ P,CLQDEL ;Flush obsolete clock queue entry, if any. + DEDBLK + MOVEM C,SHUTDN ;Remember time we will die. + SUB C,TIME ;Interval until death. + LSH C,1 ;Time till death after next clock-queue int. + MOVEM C,DEDTIM ;Remember time until death. + PUSHJ P,DEATHX ;Make DEATH entry on clock queue. + BUG ; DEDTIM says time to die already? + JRST LSWPJ1 ;Unlock shutdowns. + +;READ TIME TILL SYSTEM DOWN + +ADIETI: XCTR XW,[SETOM (J)] ;READ -1 IF NOT GOING DOWN + SKIPG A,SHUTDN + POPJ P, ;NOT DYING + SUB A,TIME + JRST APTUAJ ;GIVE TO USER + +;REVIVE SYS + +AREVIV: PUSHJ P,SWTL + SHUTLK + SKIPN SHUTDN + JRST LSWPOP ;NOT DYING + PUSHJ P,CLQDEL + DEDBLK + SETZM SHUTDN + SETZM DEDTIM + PUSHJ P,DEATHM + JRST LSWPOP + +;FROM CLOCK QUEUE BLOCK + +DEATHZ: PUSHJ P,DEATHX + SKIPA + JRST CLQRET + MOVSI T,SCLOUT + PUSHJ P,SUPSET ;DIE + SETOM DEDTIM + JRST CLQRET + +;GET VARIOUS SYS STATUS + +ASSTAT: CONO PI,CLKOFF + SKIPLE A,SHUTDN + SUB A,TIME + SKIPG SHUTDN + SUBI A,1 ;TIME TILL DOWN IF > 0, -1 IF UP, -2 IF DOWN + CONO PI,CLKON + MOVE B,SYSDBG + MOVE C,SUSRS + MOVE D,PARERR + ADD D,NXMERR + MOVE E,TIME + MOVE TT,[ITSMCH] ;SIXBIT NAME OF THIS MACHINE. + MOVE I,[ITSVRS] + MOVN Q,USRHI ;Q GETS NUMBER OF FREE JOB SLOTS + IDIVI Q,LUBLK + ADDI Q,MAXJ + MOVE J,USRHI +ASSTT1: SUBI J,LUBLK + SKIPN UNAME(J) + ADDI Q,1 + JUMPG J,ASSTT1 + JRST POPJ1 + +SUBTTL SYMBOLIC SYSTEM CALL HANDLER + +;IN ORDER @A...Z[\]^_ !".../0...9:;,=.? (THAT IS IN NUMERICAL ORDER) + +SYSCTB: SIXBIT /ACCESS/ ;IOCHNL, ADR + SIXBIT /ATTACH/ + SIXBIT /ATTY/ + SIXBIT /CALL/ ;SIXBIT // +IFN CHAOSP,[ + SIXBIT /CHAOSO/ + SIXBIT /CHAOSQ/ +];CHAOSP + SIXBIT /CLOSE/ ;IOCHNL + SIXBIT /CNSGET/ ;GET SEMIPERMANENT TTY INFO + SIXBIT /CNSSET/ ;SET SEMIPERMANENT INFO (TCMXH, TCTYP, TTYOPT, TTYCOM, ETC) + SIXBIT /CORBLK/ ;HACK PAGE MAP + SIXBIT /CORTYP/ ;READ STATUS OF PAGE. + SIXBIT /DELETE/ ;FILE DELETE + SIXBIT /DELEWO/ ;DELETE FILE OPEN ON SPEC'D CHANNEL +IFN DEMON,SIXBIT /DEMSIG/ ;SIGNAL DAEMON + SIXBIT /DETACH/ ;DISOWN ENTIRE TREE + SIXBIT /DIRSIZ/ + SIXBIT /DISMIS/ + SIXBIT /DISOWN/ ;DISOWN AN INFERIOR JOB +IFN DL10P, SIXBIT /DL10MP/ + SIXBIT /DSKUPD/ ;SIMULATE REFERENCE OF FILE + SIXBIT /ECHOIN/ ;ECHO-NEGOTIATE + SIXBIT /FILBLK/ ; READ NAME AREA OF FILE + SIXBIT /FILLEN/ ;READ FILE LENGTH + SIXBIT /FINISH/ + SIXBIT /FLAP/ ;TAPE # + SIXBIT /FLUSH/ ;OLD NAME FOR FINISH, EVENTUALLY " + SIXBIT /FORCE/ + SIXBIT /IOPOP/ + SIXBIT /IOPUSH/ + SIXBIT /IOT/ ;IOCHNL, QUAN OR BLK POINTER +IFN INETP,SIXBIT /IPKIOT/ + SIXBIT /ITYIC/ + SIXBIT /JOBCAL/ ;GENERAL JOBGET + SIXBIT /JOBGET/ ;JOB CHNL + SIXBIT /JOBINT/ ;JOB CHNL + SIXBIT /JOBIOC/ + SIXBIT /JOBRET/ ;JOB CHNL + SIXBIT /JOBREU/ + SIXBIT /JOBSTS/ ;SET JOB CHNL STATUS +IFN KL10P,SIXBIT /KLPERF/ ;ACTIVATE & CONTROL PERFORMANCE METER + SIXBIT /LISTEN/ ;IOCHNL, ADR + SIXBIT /LNKEDP/ ;DISK CH. RETURNS NONZERO IF LINKS WERE TRACED TO OPEN IT. + SIXBIT /LOAD/ ;USER CH, I/O CH, VARBLK + SIXBIT /LOGIN/ ;SIXBIT // + SIXBIT /LOGOUT/ ;. . . + SIXBIT /LOSE/ + SIXBIT /MLINK/ ;MAKE LINK +IFN NCPP, SIXBIT /NETAC/ + SIXBIT /NETBLK/ ;HANG ON NCP STATE +IFN IMPP,[ + SIXBIT /NETHST/ ;GETS STATUS OF HOST + SIXBIT /NETIMP/ ;GETS STATUS OF IMP +];IMPP +IFN NCPP, SIXBIT /NETINT/ +IFN INETP,[ ; A temporary cond, should become permanent. + SIXBIT /NETRFC/ ; Get pending request for connection +] + SIXBIT /OPEN/ ;FILE OPEN + SIXBIT /PDUMP/ ;USER CH, I/O CH, VARBLK + SIXBIT /PGDUMP/ ;OLD NAME FOR PGWRIT, EVENTUALLY DELETE + SIXBIT /PGWRIT/ ;DUMP PAGE OUT OF CORE +IFN CHAOSP, SIXBIT /PKTIOT/ +IFN QAUTHP, SIXBIT /RAUTH/ ;READ AUTHOR OF FILE + SIXBIT /RCHST/ ;READ OPENED FILENAMES & ACCESS POINTER + SIXBIT /RCPOS/ ;READ CURSOR POS +IFN DEMON,SIXBIT /RDDMST/ ;READ DEAMON STATUS + SIXBIT /RDMPBT/ ;READ FILE DUMPED BIT IOCHN, ADR + SIXBIT /RELOAD/ + SIXBIT /RENAME/ ;FILE RENAME + SIXBIT /RENMWO/ ;RENAME WHILE OPEN + SIXBIT /REOWN/ + SIXBIT /RESET/ + SIXBIT /RESRDT/ ;RESTORE REFERENCE DATE + SIXBIT /RFDATE/ ;READ TIME OF CREATION OF FILE IOCHN, ADR + SIXBIT /RFNAME/ ;READ FILE NAME AND MODE CHANNEL OPEN TO + SIXBIT /RFPNTR/ ;READ ACCESS POINTER + SIXBIT /RQDATE/ ;READ DSK DATE + SIXBIT /RSSIZE/ ;READ SCREEN SIZE +IFN QAUTHP, SIXBIT /SAUTH/ ;SET AUTHOR OF FILE + SIXBIT /SCML/ ;SET # COMMAND LINES + SIXBIT /SCPOS/ ;SET TTY CURSOR POSITION + SIXBIT /SDMPBT/ ;SET FILE DUMPED BIT IOCHN, ADR + SIXBIT /SETIOC/ ;CAUSE IO CHANNEL ERROR IN JOB/BOJ CHANNEL + SIXBIT /SFDATE/ ;SET TIME OF CREATION OF FILE IOCHN, ADR + SIXBIT /SIOT/ ;IOT A STRING GIVEN B.P. AND LENGTH + SIXBIT /SOPEN/ ;OPEN, TAKING MODE,,CHNL AND BP. + SIXBIT /SRDATE/ ;SET REFERENCE DATE + SIXBIT /SREAPB/ ;SET THE DO NOT REAP BIT + SIXBIT /SSERVE/ ;Set .SERVER without timing errors + SIXBIT /SSTATU/ ;READS VARIOUS SYSTEM STATUS + SIXBIT /STATUS/ +IFN DEMON,SIXBIT /STDMST/ ;SET DEAMON STATUS + SIXBIT /STLGET/ ;GET INFO ON SERVER TELNET CONTROLLING A STY + SIXBIT /STYGET/ ;GET INFO ABOUT SPECIFIED STY +IFN NETP,SIXBIT /STYNET/ ;CONNECT STY TO NETWORK SOCKETS, FOR TELNET SERVERS. + SIXBIT /T11MP/ ;TEMP ? TEN11 HACKER +IFN TCPP,SIXBIT /TCPOPN/ ; Open TCP Internet connection + SIXBIT /TRANAD/ ;CREATE TRANSLATION ENTRY + SIXBIT /TRANCL/ ;CLEAR TRANSL. LIST(S) FOR A JOB. + SIXBIT /TRANDL/ ;DELETE A TRANSL. ENTRY. + SIXBIT /TRANEX/ ;READ A JOB'S TRANSL. LIST. + SIXBIT /TRANS/ ;TRANSLATE A FILENAME. + SIXBIT /TRPOPN/ ;OPEN TRAP DEVICE FOR AN INFERIOR + SIXBIT /TTYESC/ ;SIMULATE TYPING OF ^_ + SIXBIT /TTYFLS/ ;FLUSH ITYIC'ED INPUT + SIXBIT /TTYGET/ ;SUPPLY TTY CH, RETURNS THREE WORDS OF TTY STATUS + SIXBIT /TTYSET/ ;SUPPLY TTY CH AND THREE WORDS OF TTY STATUS + SIXBIT /TTYVAR/ ;HACK TTY VARIABLES + SIXBIT /TVWHER/ + SIXBIT /UNLOCK/ ;UNLOCK A SPEC'D JOBS LOCKS. + SIXBIT /USRMEM/ ;READ OR WRITE A JOB'S MEMORY. + SIXBIT /USRVAR/ ;HACK USER VARIABLES + SIXBIT /VIDBUF/ ;ASSIGN/DEASSIGN VIDEO BUFFER. + SIXBIT /VIDSW/ ;SET VIDEO SWITCH. + SIXBIT /WHOLIN/ ;GET OR SET WHO-LINE MODE AND JOB. + SIXBIT /WHYINT/ ;FIND OUT WHY AN I/O CHANNEL INTERRUPTED + SIXBIT /XGPIM/ ;OUTPUT TO XGP IN IMAGE MODE +LSYSCT==:.-SYSCTB + +ZZ==.-SYSCTB-1 +RADIX 2 +ZZ2==CONC [.LENGTH /]\ZZ,/ +RADIX 8 +REPEAT 1_-ZZ-1,377777,,-1 +;4.X BIT IMPLIES SUPPLY ROUTINE WITH POINTER TO X'TH ARG, NOT ARG ITSELF +;3.9-3.7 = MINIMUM NUMBER OF ARGS +;3.1 => DECODE 1ST ARG AS IO CHNL, LEAVING IOCHNM WD ADDR IN RH(R), +; IOCHNM WD CONTENTS IN H, CLSTB ENTRY'S LH IN LH(R). +;3.2 => NEVER PASS TO SPECIAL CHECKER FOR JOB CHNL +;3.3 => DON'T BARF IF CHNL NOT OPEN, CALLED ROUTINE WILL HANDLE IT + +;# ARGS ACTUALLY SUPPLIED IN W WHEN DISPATCHING THRU SYSCTD, ARGS IN A...J +SYSCTD: 200,,NACCES + 100,,NATTAC + 100,,NATTY + 100,,NCALL +IFN CHAOSP,[ + 200,,CHAOSO + 100,,CHAOSQ +];CHAOSP + 100,,NCLOSE(7) + 100,,NCNSGET + 100,,NCNSSET + 24300,,NCORBL + 100,,NCORTY + 100,,NDEL + 100,,DELEWO(1) +IFN DEMON,100,,ADEMSIG + NDETAC + 100,,NDIRSIZ(1) + 1100,,NDISMIS + 100,,NDISOWN +IFN DL10P, 100,,DL10MP + 100,,ADSKUP(1) + 6500,,NECHOIN(1) + 100,,NFILBLK(1) + 100,,NFILLEN(1) + 100,,NFINIS(1) +IFN NUNITS, 100,,NFLAP +IFE NUNITS, 100,,OPNL1 + 100,,NFINIS(1) ;OLD NAME FOR FINISH, EVENTUALLY FLUSH + 100,,NFORCE(1) + 100,,NIOPOP(7) + 100,,NIOPUS(7) + 2100,,NIOT(7) ;(7) FOR CHNL NOT OPEN TO BE IOC ERROR, (3) TO BE OPEN LOSS +IFN INETP, 100,,IPKIOT(1) ; Requires at least 1 arg + 100,,NITYIC + 100,,NJBCL(1) + 100,,NJBGT(1) + 100,,NJBINT(1) + 100,,NSTIOC(1) + 100,,NJBRT(1) + 20500,,NJBREU + 100,,NJBSTS(1) +IFN KL10P,KLPERF + 100,,NLISTE + 100,,NLNKEDP(1) + 200,,NLOAD + 200,,NLOGIN + ALOGOU + 100,,NLOSE + 200,,NMLINK +IFN NCPP, 100,,ANETAC(1) +IFE INETP,[ +IFE CHAOSP, 4200,,ANETBLK(1) +IFN CHAOSP, 4200,,CHANBK(1) +] +IFN INETP, 4200,,NETBLK(1) ; Block (.hang) on net I/O channel +IFN IMPP,[ + 100,,ANETHST + ANETIMP +];IMPP +IFN NCPP, 100,,NNETINT(1) +IFN INETP, 100,,NETRFC + 200,,NOPEN + 4300,,PDUMP + 100,,NPGWRT ;OLD NAME FOR PGWRIT, EVENTUALLY DELETE + 100,,NPGWRT +IFN CHAOSP, 200,,PKTIOT(1) +IFN QAUTHP, 100,,ARAUTH(1) + 100,,NRCHST + 100,,ARCPOS +IFN DEMON,100,,ARDDMST + 100,,NRDMPBT(1) + 000,,NRELOAD + 200,,NRNAM + 200,,NRNWO + 100,,NREOWN(3) + 100,,NRESET(7) + 100,,NRESRDT(1) + 100,,NRFDATE(1) + 100,,NRFNAM + 100,,NRFPNT(3) + ARQDAT + 100,,ARSSIZ +IFN QAUTHP, 200,,ASAUTH(1) + 200,,ASCML + 100,,NSCPOS + 200,,NSDMPBT(1) + 200,,NSTIOC(1) + 200,,NSFDATE(1) + 6300,,NSIOT(7) ;(7) FOR IOC ERROR IF CHNL NOT OPEN, (3) FOR OPEN LOSS + 200,,NSOPEN + 200,,NSRDATE(1) + 100,,ASREAP(1) + 100,,NSSERV + ASSTAT + 100,,NSTATUS(7) +IFN DEMON,100,,ASTDMST + 100,,NSTLGT + 100,,NSTYGT +IFN NETP,200,,NSTYNT(3) + 200,,NT11M +IFN TCPP,500,,TCPOPN + 300,,NTRNAD + 100,,NTRNCL + 200,,NTRNDL + 200,,NTRNEX + 100,,NTRNS + 200,,TRPOPN + 100,,NTTYESC + 100,,NTTYFLS + 100,,ATTYGT + 300,,ATTYST + 2200,,NTTYVA + 100,,NTVWHERE + 100,,NUNLOCK + 2200,,NUSRME + 2200,,NUSRVA + 100,,NVDBF + 200,,NVIDSW + 100,,NWHOLI + 100,,NWHYINT(1) + 1100,,NXGPIM + +IFN .-SYSCTD-1-ZZ,.ERR NEW SYS CALL DISPATCH LOSES!!! + +REPEAT 1_-ZZ-1,ILUUO + +;.CALL ADR1 SKIPS UNLESS SOMETHING WRONG +;ADR1: SETZ +; SIXBIT // +; REPEAT #ARGS,BITS,,

+; BITS= 4.9 => LAST ARG +; 4.3 - 4.1 0 = NORMAL ARG +; 1 = IMMEDIATE +; 2 = OUTPUT ARG +; 3 = RETURN THE FAILURE CODE IF FAIL +; 4 = WORD OF CONTROL BITS +; 5 = IMMEDIATE CONTROL BITS + +ASYSC: PUSHJ P,ASCGRG ;B HAS E OF UUO + JRST OPNL43 ;CALL NAME UNKNOWN. + JRST OPNL15 ;MORE THAN 8 ARGS + JRST OPNL30 ;TOO FEW ARGS + PUSHJ P,ASYSC1 ;DISPATCH TO ROUTINE. + POPJ P, ;NO SKIP - OPENL HAS ALREADY BEEN CALLED. + AOS (P) ;SKIP - PROPAGATE THE SKIP UP THE PDL + MOVE U,USER ;!! + MOVE R,SYSCVL(U);SUCCESS RETURN, ZERO ERROR CODE ARG IF ANY + TLNE R,%SCVER + XCTR XW,[SETZM (R)] + JUMPGE R,CPOPJ ;JUMP IF NO OUTPUT VALUES WANTED +SYSCPT: HRRZ W,FORTY ;VALUES WANTED, PUT INTO USER MEMORY FROM ACS + ADDI W,2 + MOVSI T,-8 +SYSCP2: UMOVE R,(W) + TLNN R,1000 + TLNN R,2000 + JRST SYSCP3 + PUSHJ P,ASCIND + MOVE J,1(T) + UMOVEM J,(R) + AOBJP T,CPOPJ +SYSCP3: JUMPL R,CPOPJ + AOJA W,SYSCP2 + +ASYSC1: MOVE T,SYSCTD(H) + TLNN T,1 ;DECODE 1ST ARG AS IO CHNL? + JRST (T) ;NO, DISPATCH TO CALL. + TLNE T,2 ;OK TO GIVE TO JOB CHNL CHECKER? + JRST CHNDCD ;NO - GO DECODE CHANNEL + HRL J,T ;SAVE DISPATCH ADDR + HRRI T,AIOCAL ;MAKE DECODER RETURN TO CHECK FOR JOB DEVICE + JRST CHNDCD + +NCALL: MOVE T,A + MOVE R,[B,,A] + BLT R,A+6 + SETZM A+7 ;MAX 8 ARGS, 1 USED FOR NAME + SOS W + PUSHJ P,ASCRCH + JRST OPNL43 + MOVEI J,ASYSC+2 ;LOOK LIKE PUSHJ'ED FROM ASYSC + MOVEM J,(P) + LDB J,[331000,,SYSCTD(H)] + JUMPE J,NCALL2 + AOS B,FORTY + JRST NCALL3 ;HE WANTS POINTERS, WE HAVE JUST VALUES. + ;MUST GET ARGS AGAIN + +ASCRCH: MOVEI H,0 + REPEAT ZZ2,[CAML T,SYSCTB+1_(H) + ADDI H,1_ + ] + CAMN T,SYSCTB(H) + AOS (P) + POPJ P, + +;JSP T,HERE TO DECODE IO CHNL IN A, MODIFIERS IN 3.1-3.3 OF T. +;IF RH(T) = AIOCAL, LH(J) IS REAL RETURN ADDRESS. +;RETURNS IOCHNM ADDR IN RH(R), IOCHNM WD CONTENTS IN H, CLSTB BITS IN LH(R) +;CAN POPJ OUT FOR INVALID CHANNEL. + +CHNDCD: TRNE A,-NIOCHN ;IS 1ST ARG A LEGAL CHNL NUM? + JRST OPNL14 + CAMN U,USER + HRROM A,UUAC(U);REMEMBER CHNL # FOR IOC ERRORS, ETC. + MOVEI R,(A) + ADDI R,IOCHNM(U) ;YES, COMPUTE IOCHNM WD ADDR + MOVE H,(R) ;RETURN CONTENTS IN H. + HLL R,CLSTB(H) ;RETURN CLSTB BITS IN LH(R). + TLNE R,%CLST + JRST [ CAME U,USER ;TRAP DEVICE + JRST .+1 ;IF CHANNEL BELONGS TO THIS USER, TRAP + JRST TRPDEV ] ;OTHERWISE, IS PROBABLY RFNAME, LET IT THROUGH + TRNN H,-1 ;IF CHNL NOT OPEN + TLNE T,4 ;AND NOT SPECIALLY OK FOR THIS SYSTEM CALL + JRST (T) + JRST OPNL44 ;THEN BARF + +;JOB DEVICE CHECKER - PUT AIOCAL IN RH(T), JRST CHNDCD + +AIOCAL: HLRZ T,J ;GET DISPATCH ADR BACK + TLNN R,%CLSJ ;IS CHANNEL JOB DEVICE? + JRST (T) ;NO - DISPATCH + HLRZS H ;ISOLATE JOB DEVICE INDEX + DPB W,[230400,,JBSTS(H)] ;SAVE ARG COUNT + MOVNS W + HRLZS W + HRRI W,1 ;NOW HAVE AOBJN PNTR TO DATA + MOVE T,(W) ;COPY ARGS TO JOB AC TABLES + MOVEM T,@JBACTB-1(W) + AOBJN W,.-2 + MOVEI W,10 ;SET NON-STANDARD OP-CODE + HRRM W,JBSTS(H) + MOVE E,H ;PUT JOB INDEX IN E FOR JBWT + CONO PI,CLKOFF +AIOCA1: PUSHJ P,JBWT ;WAIT FOR JOB TO ANSWER + MOVE H,E ;GET JOB INDEX BACK IN H (FOR JBACTB) + MOVE W,[-8,,1] ;LOAD ANSWERS INTO ACS + MOVE T,@JBACTB-1(W) + MOVEM T,(W) + AOBJN W,.-2 + LDB T,[350400,,JBSTS(H)] ;GET SKIP COUNT + JUMPN T,POPJ1 ;SKIP COUNT NOT ZERO - SKIP + LDB C,[270600,,JBSTS(H)] ;GET OPEN LOSS CODE + SKIPE C ;MAKE SURE IN BOUNDS + CAILE C,NOPNLS + MOVEI C,22 + JRST OPNL1-1(C) ;GO REPORT LOSSAGE AND DON'T SKIP + +;SYSTEM CALL GET ARGS +ASCGRG: UMOVE T,(B) + CAME T,[SETZ] + JRST ILUUO + UMOVE T,1(B) + MOVEM T,LSCALL(U) + PUSHJ P,ASCRCH + POPJ P, ;CALL NAME UNRECOGNIZED. + AOS (P) + LDB J,[331000,,SYSCTD(H)] ;GET BITS CORRESP TO ARGS WHICH SAY SUPPLY PNTR TO NTH ONE +NCALL3: MOVEI W,2(B) + MOVE T,[-9,,A] + SETZM CTLBTS(U) +ASYSC2: UMOVE R,(W) + TLNE R,37 + PUSHJ P,ASCIND ;CALC EFFECTIVE ADDRESS + TLNE R,2000 + JRST ASYSC3 ;OUTPUT OR ERRORCODE ARG + TLNE R,4000 + JRST ASYSC5 ;CONTROL BITS + AOBJP T,CPOPJ + ROT J,-1 + JUMPL J,ASYSC7 ;J IF WANT ADDRESS, NOT VALUE + TLNE R,1000 + TLZA R,-1 ;IMMEDIATE, GET 0,,ADR + UMOVE R,(R) ;ELSE GET WORD POINTED TO +ASYSC7: MOVEM R,-1(T) ;PUT INTO AC + JRST ASYSC4 + +ASYSC5: TLNE R,1000 ;CTL BITS + TLZA R,-1 ;IMMEDIATE, GET 0,,ADR + XCTR XR,[HRRZ R,(R)] ;ELSE WORD ADDRESS + XORM R,CTLBTS(U) ;XOR ALL THESE ARGS TOGETHER +ASYSC4: XCTR XR,[SKIPL (W)] ;SKIP IF TERMINATE BIT ON + AOJA W,ASYSC2 + HLRE W,T + ADDI W,9 ;COMPUTE NUMBER OF ARGUMENTS SUPPLIED +NCALL2: LDB T,[300300,,SYSCTD(H)] + SUB T,W + JUMPG T,POPJ1 ;NOT ENOUGH ARGS + JRST POPJ2 ;OK + +ASYSC3: TLNE R,1000 + JRST ASYSC8 ;ERROR CODE ARG + XCTR XRW,[MOVES (R)] ;OUTPUT ARG, JUST MAKE SURE IT'S THERE + MOVSI R,%SCVOT ;AND FLAG PRESENCE +ASYSC9: IORM R,SYSCVL(U) + JRST ASYSC4 + +ASYSC8: HRLI R,%SCVER ;ERROR-CODE ARG + TDNE R,SYSCVL(U);CAN'T HAVE MORE THAN ONE ERRORCODE ARG + JRST CPOPJ ;SAY "TOO MANY ARGS" + XCTR XRW,[MOVES (R)] ;MAKE SURE IT'S THERE; MUSTN'T PCLSR OUT OF OPENL + JRST ASYSC9 + +;PERFORM INDEXING AND INDIRECTION ON ADDRESS WORD IN R. +;DON'T CLOBBER BITS 3.6 - 4.9. SET BITS 3.1 - 3.5 TO ZERO +;PUT ADDR IN RH. +ASCIND: TLNN R,37 + POPJ P, +ASCIN1: PUSH P,R + LDB R,[220400,,R] + CAIE R,0 + XCTR XR,[HRRZ R,(R)] + ADD R,(P) + HLL R,(P) ;GET ORIG @, MAY HAVE BEEN CARRIED INTO BY -1(17) + TLZ R,17 + TLZE R,(@) + UMOVE R,(R) + DPB R,[2700,,(P)] + POP P,R + TLNN R,37 + POPJ P, + PUSHJ P,OPBRK ;ALLOW PCLSR + JRST ASCIN1 + +TPFLT: CONO PI,CLKOFF ;PREVENT INTERRUPT AFTER IORM SPM ING BACK + ; ON TOP OF 1000 BIT +IFN KA10P,[ + SPM UPGML(U) + PUSH P,B + MOVSI B,1000 + IORM B,UPQUAN(U) + POP P,B + LPMRI UPGML(U) ;TAKE TRAP, MAYBE DONT COME BACK + JRST CLKONJ +] ;KA10P +IFN KL10P,[ + POP P,PFOPC1 ;IF RESTART FAULT, RETURN FROM TPFLT + JRST TPFLT1 ;JOIN REGULAR PAGE FAIL CODE +] ;KL10P +IFN KS10P,[ + POP P,EPTPFO ; If fault returns, just return from TPFLT + JRST TPFLT1 +] ;KS10P + +SUBTTL PURE DUMP + +;`PDUMP' SYMBOLIC SYSTEM CALL +; ARG 1 - JOB SPEC FOR JOB TO BE DUMPED +; ARG 2 - DISK CHANNEL TO DUMP ONTO +; ARG 3 - STATE WORD (MODIFIED) INITIALLY 0, THEN 4.9 + PAGE # ABOUT TO DUMP + +PDUMP: MOVE J,A + JSP T,NCRUI2 ;DECODE JOB SPEC (1ST ARG) + JFCL + MOVE A,J + JUMPL J,OPNL31 ;CAN'T PDUMP THE PDP6. + MOVE D,B + JSP T,PDUMDC ;DECODE 2ND ARG, B-> IOCHNM WORD. + TLNN J,%CLSQO + JRST OPNL34 ;NOT DISK WRITE CHANNEL. + HRRZM D,UUAC(U) ;SO SET IN CASE OF ERROR + HLRZ D,(B) + MOVEM D,SRN3(U) ;REMEMBER DISK CHANNEL NUMBER FOR LATER. + PCLT + XCTR XRW,[MOVES D,(C)] + MOVEM C,SRN4(U) ;REMEMBER STATE WORD ADDRESS FOR LATER + MOVEM A,EPDL(U) ;USER INDEX +PDUMA: CAIN A,(U) ;IF PDUMP'ING SELF, MUSTN'T PCLSR, + PUSHJ P,NULSET ;SO DO A NULSET INSTEAD OF THE SOSSET + CAIN A,(U) + JRST PDUMP9 ;SO THAT A LSWPOP CAN BE DEON AT THE END IN EITHER CASE. + PUSHJ P,RPCLSR ;HACKING ANOTHER JOB: STOP IT. + PUSHJ P,SOSSET + USTP(A) +PDUMP9: MOVE A,SRN3(U) ;GET DISK CHANNEL NUMBER + MOVE C,SRN4(U) + UMOVE D,(C) ;PICK UP STATE WORD + JUMPN D,PDUMP5 ;JUMP IF ALREADY WROTE MAP PAGE + PUSHJ P,PDBWG ;GET BUFFER AND COMMIT DISK TRACK FOR MAP PAGE + SETZM (E) ;CLEAR FIRST WORD OF MAP + ;AND DROP INTO PDUMP4 +;HANDLE THE NEXT PAGE. +PDUMP4: PUSHJ P,PUPLC ;GET BYTE POINTERS + LDB W,Q ;CIRC POINTER ENTRY + LDB R,T ;PAGE MAP ENTRY + ANDCMI R,PMAGEM ;CLEAR AGE BITS + CAIN W,-1 + TLO R,(SETZ) ;ABS PAGE + SKIPN W + MOVEI R,0 ;PAGE NON-EXISTANT + TRNN R,600000 + LSH R,16. ;SWAPPED OUT + MOVE W,D ;VIRTUAL PAGE NUMBER + ADDI W,1(E) ;ADDRESS OF ENTRY IN BLOCK + MOVEM R,(W) ;STORE ENTRY + CAIGE D,377 + AOJA D,PDUMP4 + HRLI W,1(W) + SETZM 1(W) + HRRI W,2(W) + BLT W,1777(E) + MOVE D,EPDL(U) + MOVEI W,1000(E) ;1000-1017 ACS + CAMN D,U + JRST [ XCTR XBR,.+2 + JRST .+3] + HRLI W,AC0S(D) + BLT W,1017(E) + PUSHJ P,QSBWW + SETZM QSMPRC(A) ;SO NEXT IOT GETS A NEW BUFFER + MOVSI D,(SETZ) ;SET STATE WORD TO `DUMPING PAGE 0' +;DROPS THROUGH + ;DROPS IN +;DUMP NEXT PAGE +PDUMP5: MOVE C,SRN4(U) ;STORE BACK STATE WORD + UMOVEM D,(C) +PDUMP8: PUSHJ P,PUPLC + LDB W,Q + CAIE W,-1 + SKIPN W + AOJA D,PDUMP6 ;PAGE ABSOLUTE OR NONEXISTANT +PDUMP3: PUSHJ P,PDBWG ;GET BUFFER AND COMMIT DISK TRACK TO DUMP THIS PAGE INTO + MOVE J,EPDL(U) ;SET UP MAP TO POINT TO USER BEING DUMPED + PUSHJ P,MPLDJ + HRLZ J,D ;GET VIRTUAL ADDRESS OF PAGE BEING DUMPED + LSH J,10. + HRR J,E ;BLT POINTER TO COPY THE PAGE + XCTR XBR,[BLT J,1777(E)] ;COPY PAGE INTO DISK BUFFER + PUSHJ P,MPLDZ ;RESTORE TO NORMAL MAP + PUSH P,D + PUSHJ P,QSBWW ;WRITE OUT THE COPIED PAGE + SETZM QSMPRC(A) ;SO NEXT IOT GETS NEW BUFFER + POP P,D + AOS D ;DONE WITH THIS PAGE +PDUMP6: TRNN D,400 ;SKIP IF FINISHED WHOLE ADDRESS SPACE + JRST PDUMP5 + JRST LSWPJ1 ;UNSTOP USER AND POPJ1 + +;ROUTINE TO GET DISK BUFFER AND COMMIT TRACK (FOR PDUMP) +;RETURNS BUFFER ADDRESS IN E. PRESERVES D. + +PDBWG: SKIPL E,QSMDN(A) ;GET CORE BLOCK # OF DISK BUFFER + JRST [ LSH E,10. ;CONVERT TO ADDRESS + POPJ P, ] + MOVE E,[444400,,1] ;NO BUFFER, GET ONE + MOVEI B,QBOV + PUSHJ P,QSBWG + PUSHJ P,UDELAY ;CAN'T GET MEMORY, WAIT A WHILE + JRST PDBWG + +;ROUTINE TO LOOK UP PAGE (FOR PDUMP AND PURE LOAD) +;PAGE# IN RH(D), USER# IN EPDL(U). RESULTS FROM UPLC IN Q AND T. + +PUPLC: PUSH P,A + PUSH P,U + MOVE U,EPDL(U) + MOVE A,D + ANDI A,377 + PUSHJ P,UPLC + POP P,U + JRST POPAJ + +;DECODE 2ND ARG TO PDUMP & LOAD. +;B GETS IOCHNM WORD ADDR, LH OF J GETS LH OF CLSTB ENTRY, RH GETS LH(IOCHNM). + +PDUMDC: TRNE B,-NIOCHN + JRST OPNL14 + ADDI B,IOCHNM(U) + HRRZ J,(B) + HLLZ J,CLSTB(J) + HLR J,(B) + JRST (T) + +SUBTTL PURE AND SBLK LOAD + +;`LOAD' SYMBOLIC SYSTEM CALL +; ARG 1 - JOB SPEC FOR JOB TO BE LOADED +; ARG 2 - DISK CHANNEL TO LOAD FROM +; ARG 3 - (OPTIONAL) FIRST ADDR,,LAST ADDR TO BE LOADED +; OR ZERO => LOAD ONLY PURE PAGES +; WHEN LOADING A PDUMPED FILE, FIRST,,LAST ROUNDED OFF TO PAGES +; DEFAULT 3RD ARG IS 0,,-1 NORMALLY, 20,,-1 LOADING SELF, 20,,37777 LOADING PDP6 + +;PAGE WORD +;4.9=1 ABSOLUTE, 1.1-2.9 = PTW +;4.8=1 SHARED WITH OTHER PAGES AT LEAST ONE OF WHICH IS WRITE +;4.7=1 LINK WITH VIRT PG IN RH 1.8-1.1 +;2.9-2.8 0 NXM, 1 RD ONLY, 2 OR 3 READ/WRITE +;2.7=1 WORD ALREADY PROCESSED + +NLOAD: MOVE J,A + JSP T,NCORUI ;DECODE THE JOB SPEC. + JRST NLOAD6 ;JOB GUARANTEED WRITEABLE. + JSP T,NCORWR ;ELSE CHECK IF WRITEABLE. + CAIN J,-1 ;BUT CAN WRITE PDP6. + CAIA + JRST OPNL31 ;NOT WRITEABLE. +NLOAD6: HRREI A,(J) ;MAKE SURE EXTEND SIGN IF PDP6. + JSP T,PDUMDC ;DECODE 2ND ARG. + TLNN J,%CLSQO + TLNN J,%CLSQ + JRST OPNL34 ;NOT DISK READ CHANNEL. + LDB J,[QSBSIZ(J)] + CAIE J,36. + JRST OPNL12 ;"MODE NOT AVAILABLE" IF CHANNEL NOT 36-BIT BYTES. + MOVE R,B ;IOCHNM ADDRESS IN CASE WE GET TO QICL + JUMPL A,NLOADE ;DONT STOP THE 6 + CAMN A,U + JRST NLOADA ;DONT STOP IF LOADING INTO SELF + PUSHJ P,RPCLSR + PUSHJ P,LSWPOP ;SOS JOB'S DIELOK - IT CAN'T DIE WHILE STOPPED. + MOVSI T,BSSTP ;STOPPING WITH BSSTP INSTEAD OF RH OF USTP + IORM T,USTP(A) ;AVOIDS DEADLY EMBRACE WITH CORE JOB (SEE CUSTOP) + SOS USTP(A) + PUSHJ P,LOSSET ;ARRANGE TO CLEAR BSSTP ON PCLSR. + NLUPCL + CAIGE W,3 + HRLOI C,0 ;DEFAULT 3RD ARG + JRST NLOADE + +NLOADA: PUSHJ P,LSWPOP ;DIELOK + CAIGE W,3 + HRLOI C,20 ;DEFAULT 3RD ARG +NLOADE: MOVEM A,SRN3(U) ;SAVE USER INDEX (-1 => PDP6) +IFN PDP6P,[ + JUMPL A,[HLRZ A,C ;PDP6, ENSURE LIMITS SMALL ENOUGH + CAIGE A,20 + HRLI C,20 ;ACS NOT ACCESSIBLE + MOVEI A,LPDP6M*2000-1 + CAIGE A,(C) + HRR C,A ;HAS ONLY 16K MEMORY + JRST .+1] +] + HLRZ A,(B) + MOVEM A,SRN4(U) ;SAVE # OF DISK CHANNEL + SETZM SRN5(U) ;START LOADING AT VIR PG #0 + MOVEM C,EPDLT1(U) ;SAVE LOAD LIMITS + HLRZ D,C + CAILE D,(C) + JRST OPNL33 ;FIRST > LAST + HLRZ C,QPCLSR(A) + JUMPE C,NLOADD + HRRZ Q,SRN3(U) + CAIN C,(Q) + JRST NLDSBB ;(COMING BACK AFTER PCLSR) + SETZM QPCLSR(A) +;DROPS THROUGH + ;DROPS IN +;GET FIRST BLOCK OF FILE BEING LOADED +NLOADD: CAMN U,PCLUSR + SETZM PCLIDX + SKIPL TT,QSMDN(A) + JRST NLOADB + PCLT + SKIPG QSBFS(A) + PUSHJ P,UFLS ;HANG UNTIL A BLOCK IS READ IN + MOVE Q,QSRAC(A) + TLNE Q,%QAACC+%QAMPU+%QAPAR + JRST OPNL7 ;LOST ONE WAY OR ANOTHER + MOVE E,[444400,,1] + MOVEI B,QBIV + PUSHJ P,QSBGB ;SET UP CHNL AREA. TT ADDR OF FIRST WORD OF BLOCK + BUG + JRST NLOADC ;QSBGB SKIPS FOR NORMAL RETURN + JRST OPNL46 ;SKIPPED TWICE => EOF + +NLOADB: MOVE J,QMPBSZ(A) + LSH TT,10. +NLOADC: SKIPE (TT) ;SKIP IF PURE DUMPED FILE + JRST NLDSB ;SBLK + SKIPGE SRN3(U) + JRST OPNL34 ;TRYING TO PURE LOAD PDP6 + MOVSI Q,%QAACC ;WILL GO RANDOM ACCESSING THROUGH FILE + IORM Q,QSRAC(A) ;THIS ALSO INHIBITS ACTIVATION AT PI LEVEL + HLRZ H,EPDLT1(U);LOW LOAD BOUNDARY + SKIPE EPDLT1(U) + CAIL H,20 + JRST NLOADH ;ACS NOT BE LOADED + MOVSI Q,1000(TT);ADDRESS OF DUMPED ACS + HRLS H + ADD Q,H + HRRZ H,EPDLT1(U);HIGH LOAD BOUNDARY + CAILE H,17 + MOVEI H,17 + HRRZ J,SRN3(U) ;JOB TO BE LOADED + PUSHJ P,MPLDJ + XCTR XBW,[BLT Q,(H)] ;LOAD UP HIS ACS + PUSHJ P,MPLDZ +NLOADH: MOVEI R,1(TT) ;ADDRESS OF FIRST WORD OF DUMPED MAP + MOVEM R,EPDL3(U) ;SAVE + MOVEI Q,2000 + PUSHJ P,QFNTR ;FIND DISK ADDRESS OF SECOND BLOCK + JRST OPNL46 ;OFF END OF FILE + SOS QSBI(A) ;UNDO QFNTR HACK + AOS QSLGL(A) + PUSHJ P,QUDULK ;UNLOCK USER DIRECTORY + PUSHJ P,SWTL ;LOCK CIRPSW + CIRPSW +;DROPS THROUGH + ;DROPS IN +;HERE TO DO NEXT PAGE (WHEN LOADING PDUMPED FILE) +NLOAD0: PUSHJ P,OPBRK + MOVE A,@EPDL3(U) + TRNE A,600000 ;SKIP IF NO ACCESS (IGNORE) + TRNE A,100000 + JRST NLD14 ;THIS PAGE ALREADY DONE OR NO ACCESS + MOVE Q,EPDLT1(U) + TRNE A,400000 ;SKIP IF READ ONLY + JUMPE Q,NLD14 ;IMPURE NOT BE LOADED + MOVE A,SRN5(U) ;VIRTUAL PAGE NUMBER + JUMPE Q,NLD16 + AND Q,[-2000,,-2000] + LSH Q,-10. ;FIRST PAGE,,LAST PAGE + HLRZ T,Q + CAIL A,(T) + CAILE A,(Q) + JRST NLD14 ;PAGE OUTSIDE OF RANGE TO BE LOADED +NLD16: MOVE U,SRN3(U) ;USER INDEX + PUSHJ P,UPLC + LDB R,Q ;LOOK IN CIRCULAR POINTER ENTRY FOR THIS PAGE + JUMPE R,NLOAD1 ;DOESN'T ALREADY HAVE THIS VIRTUAL PAGE + PUSH P,T ;SAVE BYTE POINTER TO PAGE MAP FOR THIS VIRTUAL PAGE + PUSH P,Q ;SAVE BYTE POINTER TO CIRCULAR POINTER ENTRY FOR THIS PAGE + PUSHJ P,PAGERT ;FLUSH THE ALREADY EXISTING VIRTUAL PAGE + POP P,Q + POP P,T +NLOAD1: MOVE U,USER + MOVE R,@EPDL3(U) ;PICK UP DUMPED PAGE MAP WORD + ANDCMI R,PMAGEM ;CLEAR AGE BITS (WOULD LOSE AT NLOAD4+4) + JUMPGE R,NLOAD3 ;NOT ABSOLUTE PAGE + ANDI R,PMRCM ;ABS PG # + CAIL R,TSYSM +IFE PDP6P, JRST OPNL32 +.ELSE [ + JRST [ CAIGE R, + CAIGE R, + JRST OPNL32 + HRRZ R,@EPDL3(U) ;ALLOW USER TO LOAD WRITABLE PDP6 PAGES. + ANDCMI R,PMAGEM\PMUNSD ;GIVE HIM WHATEVER ACCESS HE RQ'S. + JRST NLOAD5]] +;IFN TEN11P,[ ;NOT NECESSARY SINCE 10-11 PAGES ABOVE TSYSM NOW +; TRNN R,400 +; JRST .+3 +; MOVE E,T11MP-400(R) +; AOJN E,NLOAD2 ;DONT ALLOW PAGE TO POINT TO TEN11 +;] + + LDB E,[MUR,,MEMBLT(R)] + CAIN E,MUHOLE + TDZA R,R ;IF PAGE NXM TODAY, DON'T ACTUALLY GIVE ACCESS + +NLOAD5: TRO R,200000 ;RD ONLY + DPB R,T ;STORE ENTRY IN PAGE MAP + MOVEI R,-1 + DPB R,Q ;STORE -1 IN CIRCULAR POINTER +NLOAD2: MOVE E,SRN5(U) ;VIRTUAL PAGE NUMBER + MOVE U,SRN3(U) ;USER INDEX LOADING INTO + PUSHJ P,GHUSRA ;RECOMPUTE HUSRAD +NLD14: MOVE U,USER + MOVEI R,100000 + IORB R,@EPDL3(U) ;MARK DUMPED PAGE WORD AS ALREADY DONE + MOVE A,SRN4(U) ;DISK CHANNEL + TLNN R,500000 ;SKIP IF NO CORRESPONDING BLOCK IN FILE + TRNN R,600000 ;SKIP IF MUST ADVANCE ONE BLOCK + JRST .+3 ;DON'T ADVANCE FILE POINTER + PUSHJ P,QFNTN ;ADVANCE TO NEXT DISK ADDRESS + JRST OPNL46 ;PREMATURE EOF + AOS R,SRN5(U) ;NEXT VIRTUAL PAGE + CAMN U,PCLUSR + MOVEM R,PCLIDX + AOS EPDL3(U) ;NEXT MAP WORD + CAIGE R,400 + JRST NLOAD0 ;LOOP + PUSHJ P,LSWPOP ;RELEASE CIRPSW + MOVE B,SRN3(U) ;USER INDEX LOADING INTO + CAME B,U ;SKIP IF LOADING INTO SELF + PUSHJ P,LSWPOP ;UNSTOP USER + MOVE B,QFBLNO(A) + SETZM QFBLNO(A) + MOVEM B,QRADAD(A) + JRST POPJ1 + +NLOAD3: TLNN R,100000 ;SKIP IF LINK WITH PAGE IN RH OF R + JRST NLOAD4 + PUSH P,T ;SAVE BYTE POINTER TO MAP ENTRY FOR THIS VIRTUAL PAGE + PUSH P,Q ;SAVE POINTER TO CIRCULAR POINTER ENTRY FOR THIS PAGE + LDB A,[1700,,R] ;VIRTUAL PAGE NUMBER BEING LINKED TO + CAIL A,400 + JRST NLOAD8 ;BAD VIRT PAGE # + MOVE E,SRN5(U) ;VIRTUAL PAGE NUMBER OF PAGE BEING LINKED + MOVE U,SRN3(U) ;USER INDEX LOADING INTO + PUSHJ P,UPLC + LDB W,Q ;CIRCULAR POINTER OF OTHER ENTRY + JUMPE W,NLOAD8 ;DIDN'T EXIST + CAIN W,-1 + JRST NLOAD8 ;POINTS TO AN ABSOLUTE PAGE + MOVE C,U + IDIVI C,LUBLK + SKIPE D + BUG ;L DOESN'T DIVIDE U + LSH C,10 ;USER NUMBER _ 8 + TRZE C,400000 + BUG ;USER INDEX WAS TOO LARGE + IOR C,E ;NEW CIRCULAR POINTER + POP P,D ;NEW CIRCULAR POINTER BYTE POINTER + DPB W,D ;STORE OTHER ENTRY AS NEW CIRCULAR POINTER ENTRY + DPB C,Q ;MAKE OTHER CIRCULAR POINTER ENTRY POINT TO NEW ONE + LDB E,T ;OTHER MAP ENTRY + POP P,T ;POINTER TO NEW MAP ENTRY + ANDI R,600000 ;PROTECTION BITS + TRZN E,600000 + JRST NLD11 + IOR E,R + JRST NLD10 +NLD11: LSH R,-20 + DPB R,T +NLOAD9: AOS SNSWPG ;INCR CNT OF SWAPPED OUT FOR SYS + AOSA NSWPGS(U) ;USER LOADING INTO HAS ONE MORE SWAPPED OUT PAGE +NLD10: DPB E,T +NLD13: AOS NMPGS(U) ;USER HAS ONE MORE PAGE + AOS SNMPGS ;SYSTEM HAS 1 MORE PAGE +NLD15: MOVE U,USER + JRST NLOAD2 ;RECOMPUTE HUSRAD AND LOOP + +NLOAD4: MOVE A,SRN4(U) ;DISK CHANNEL + MOVEI TT,(R) ;PUT DESIRED ACCESS IN RH(TT), + ANDI TT,600000 + TDNE R,[200000,,400000] + IORI TT,%CBCPY ;ALONG WITH INITIAL-SWAPIN BIT IF NEC. + PUSHJ P,NCORQ7 ;FIND OR CREATE MMP ENTRY. + JRST OPNL37 ;MMP FULL + MOVE E,SRN5(U) ;GET PAGE # IN JOB BEING LOADED + MOVE U,SRN3(U) ;TARGET USER. + PUSHJ P,NCORR1 ;INSERT THE PAGE. + JRST NLD15 + +NLOAD8: SUB P,[2,,2] + JRST OPNL46 + +NLOADZ: PUSHJ P,LSWPOP ;FREE CIRPSW + MOVEI T,3 + CAMLE T,LMEMFR + PUSHJ P,UFLS + PUSHJ P,SWTL + CIRPSW +POPSM2: SOS (P) ;RETURN TO LOCN BEFORE PUSHJ + SOS (P) + POPJ P, + +;QTAOS: PUSHJ P,QTLOCK ;LOCK TUT +QTAOS1: MOVE D,QSLGL(A) ;DISK TRACK + PUSHJ P,TUTPNT + SKIPG B + BUG ;NOT PART OF ANY FILE + CAIGE B,TUTMNY + AOS B + DPB B,D ;ADD ONE TO TUT ENTRY FOR THIS TRACK + JRST QTULK + +NLUPCL: MOVSI T,BSSTP ;THIS IS THE LOSSET ROUTINE TO CLEAR BSSTP. + SKIPGE A,SRN3(U) + BUG + ANDCAM T,USTP(A) + POPJ P, + +NLDSBB: HRRZ J,SRN3(U) ; (COMING BACK AFTER PCLSRING OUT) A HAS DSK CHNL #) + PUSHJ P,MPLDJ ;LOAD MAP (ALSO CLOBBER UMAPS) + SKIPL C,SRN3(U) + CAIN U,(C) + JRST NLDSBH + PUSHJ P,LSWPOP + PUSHJ P,LOSSET + NLUPCL + MOVSI B,BSSTP + IORM B,USTP(C) +NLDSBH: HRRZ B,QPCLSR(A) + JRST (B) + +NLDSB: SKIPN EPDLT1(U) + JRST OPNL12 ;LOAD ONLY PURE FROM SBLK FILE LOSES + HRLZ B,SRN3(U) + HRRI B,NLDSBD + MOVEM B,QPCLSR(A) ;RESTART POINT IN CASE OF PCLSR + MOVEM J,QSMPRC(A) + MOVEM TT,QSMPRP(A) + HRRZ J,SRN3(U) + PUSHJ P,MPLDJ ;LOAD MAP (ALSO CLOBBER UMAPS) + +;DROPS THROUGH + +;DROPS IN +NLDSB1: HRROI I,EPDL3(U) + MOVEM I,SRN4(U) ;SET UP AOBJN PTR TO READ INTO EPDL3 +NLDSBD: MOVEI C,SRN4(U) ;SET C UP TO POINT TO AOBJN PTR + HRLI C,(TRN) ;INDICATE EXEC MODE ADR + PUSHJ P,QBI + SKIPGE SRN4(U) + JRST NLDSB9 ;PREMATURE EOF + MOVE I,EPDL3(U) + CAME I,[JRST 1] + JRST NLDSB1 ;IGNORE INITIAL STUFF UNTIL JRST 1 +NLDSBK: MOVEI B,NLDSBE + HRRM B,QPCLSR(A) +NLDSBE: HRROI I,QLDPTR(A) + MOVEM I,SRN4(U) + MOVEI C,SRN4(U) + HRLI C,(TRN) + PUSHJ P,QBI ;GET AN AOBJN POINTER + SKIPGE SRN4(U) + JRST NLDSB9 ;PREMATURE EOF + SKIPL B,QLDPTR(A) + JRST NLDSB6 ;NOT AN AOBJN POINTER + HLRZ C,EPDLT1(U);FIRST ADDRESS TO BE LOADED + SUBI C,(B) + JUMPLE C,NLDSB3 + HLROS B ;SKIP # WDS IN C + ADD B,C ;-# WDS REMAINING IN BLOCK + SKIPLE B + SUB C,B ;FLUSH WHOLE BLOCK + LDB D,[1200,,QSMPRP(A)] + SKIPGE QSMDN(A) + MOVEI D,0 + ADD D,QFBLNO(A) + ADD D,C ;ADVANCE ACC PTR TO SKIP PART OR ALL OF BLOCK + MOVEM D,QRADAD(A) + MOVSI D,%QAACC + IORM D,QSRAC(A) + JUMPGE B,[AOS QRADAD(A) ;SKIPPING WHOLE BLOCK, ALSO SKIP CHECKSUM + JRST NLDSBK] ;AND GO READ NEXT BLOCK + HRLS C + ADDM C,QLDPTR(A) ;UPDATE AOBJN POINTER +NLDSB3: MOVEI B,NLDSBF ;MAYBE FLUSH EXISTING MEMORY AND GET NEW + HRRM B,QPCLSR(A) +NLDSBF: HRRZ E,QLDPTR(A) ;START ADR OF BLOCK + HLRE C,QLDPTR(A) ;-LENGTH OF BLOCK + SUB E,C ;DON'T COMBINE THIS INSN WITH NEXT, MIGHT BE MOBY BLOCK + SUBI E,1 ;GET END ADR OF BLOCK + HRRZ T,EPDLT1(U);HIGH LOAD LIMIT + SUBM E,T ;NUMBER OF WORDS OF EXCESS IN BLOCK + MOVEM T,EPDLT2(U) ;SAVE FOR LATER USE + JUMPLE T,NLDSB7 ;JUMP IF BLOCK HAS NO EXCESS + SUB E,T ;ADJUST END ADDRESS + HRLZS T + ADDM T,QLDPTR(A);DECREASE COUNT IN AOBJN POINTER +NLDSB7: LSH E,-10. ;LAST PAGE NEEDED + PUSH P,A + PUSH P,R ;R HAS IOCHNM WD, NEEDED IF REACH QICL VIA QBI. + PUSH P,E ;PAGE NO. OF LAST PAGE NEEDED +NLDSB4: MOVE E,(P) + CAMGE E,SRN5(U) + JRST NLDSB5 ;ALREADY HAVE NEEDED PAGES + MOVE A,SRN5(U) + PUSH P,U + MOVE U,SRN3(U) ;LOOK UP THIS PAGE IN MAP OF USER WE'RE HACKING. + PUSHJ P,UPLC ;IF THERES A WRITABLE PAGE + POP P,U + LDB A,T ;IN THE SLOT ALREADY, KEEP IT. + TRNN A,600000 + TRNN A,2 + TRNE A,400000 + JRST NLDSBM + CAME U,SRN3(U) ;IF NOT HACKING SELF, NCORLL WILL LSWPOP + PUSHJ P,NULSET ;WHAT IT THINKS IS A LOSSET LIKE NLUPCL + PUSHJ P,SWTL + CIRPSW + MOVEI R,%JSNEW ;GET FRESH PAGE + MOVE TT,SRN3(U) ;INTO THE JOB WE'RE HACKING. + MOVE C,SRN5(U) ;PAGE # TO GIVE IT. + MOVSI A,%CBRED+%CBWRT+%CBNDW ;WANT WRITE ACCESS. + PUSHJ P,NCORL ;UNDOES NULSET AND SWTL. + JRST NLSBPL ;COULDNT GET PAGE (CALLED LSWCLR) +NLDSBM: AOS SRN5(U) + JRST NLDSB4 ;CHECK WHETHER WE NEED MORE PAGES. + +NLDSB5: SUB P,[1,,1] ;NOW WE HAVE ALL PAGES NEEDED TO LOAD THIS BLOCK. + POP P,R + POP P,A +NLDSBQ: MOVEI B,NLDSBC + HRRM B,QPCLSR(A) +NLDSBC: HRRZI C,QLDPTR(A) + HRLI C,(SETZ) + PUSHJ P,QBI ;DO A BLOCK IOT, USING THAT AOBJN POINTER. + AOSG B,EPDLT2(U);SKIP RESIDUE OF BLOCK AND CHECKSUM + MOVEI B,1 ;NO RESIDUE, JUST SKIP CHECKSUM + LDB D,[1200,,QSMPRP(A)] + SKIPGE QSMDN(A) + MOVEI D,0 + ADD D,QFBLNO(A) + ADD D,B + MOVEM D,QRADAD(A) + MOVSI D,%QAACC + IORM D,QSRAC(A) + JRST NLDSBK + +NLDSB6: LDB D,[1200,,QSMPRP(A)] + SKIPGE QSMDN(A) + MOVEI D,0 + ADD D,QFBLNO(A) + SUBI D,1 + MOVEM D,QRADAD(A) + MOVSI D,%QAACC + IORM D,QSRAC(A) +NLDSB8: CAME U,SRN3(U) ;UNLESS HACKING SELF OR PDP6, WE HAVE A SOSSET OF USTP TO POP. + SKIPGE SRN3(U) + CAIA + PUSHJ P,LSWPOP + AOSA (P) +NLDSB9: PUSHJ P,OPNL46 ;LOAD FILE NOT IN VALID SBLK FORMAT +NLSBP1: PUSHJ P,MPLDZ + SETZM QPCLSR(A) + POPJ P, + +NLSBPL: SUB P,[2,,2] ;FLUSH PUSHES OF E AND R. + POP P,A + JRST NLSBP1 + +SUBTTL .GUN, .LOGOUT + +;DESTROY PROCEDURE TREE WHOSE TOP INDEX SUPPLIED BY USER +AGUN: XCTR XR,[SKIPG A,(J)] + POPJ P, ;LOSE, NEG OR SYSTEM JOB + IMULI A,LUBLK + CONO PI,CLKOFF + CAMGE A,USRHI ;USER INDEX UNREASONABLE => LOSE. + CAIG A,LUBLK + JRST CLKONJ + JRST ALOGO6 + +ALOGOU: SKIPL SUPPRO(U) + JUMPN J,ABREAK ;.LOGOUT N, TURNS INTO .BREAK N,33 IF NOT TOP LEVEL + MOVE A,U ;.LOGOUT, AND STY CLOSE. + CONO PI,CLKOFF +;A HAS JOB BEING LOGGED OUT; U HAS JOB THAT'S DOING IT. +;.GUN AND .LOGOUT ACT BY PUTTING THE JOB IN SUCH A STATE THAT +;IT CAN DO NOTHING BUT TRY TO DISAPPEAR. IF THE JOB IS ALREADY +;IN THAT STATE, THIS ROUTINE DOES NOTHING. THAT PREVENTS +;RECURSION LOOPS WHEN KILLING CYCLIC STRUCTURES INVOLVING STY'S. +;EXCEPTION: IF THE JOB TO BE LOGGED OUT IS THE RUNNING JOB, +;WE DO THE REAL WORK BY GOING TO ALOGO1. +ALOGO6: SKIPE UNAME(A) ;JOB TO BE LOGGED OUT IS GONE. + SKIPL SUPPRO(A) ;CAN'T LOG OUT UNLESS TOP LEVEL. + JRST CLKONJ + CAME A,U + AOS (P) ;IF .GUN GETS THIS FAR, IT HAS "SUCCEEDED". + MOVSI T,BULGOS+BULGO + TDNE T,APRC(A) ;IF JOB IS ALREADY LOGGING OUT, + JRST ALOGO7 ; SEE IF IT IS THE RUNNING JOB + MOVSI B,%PCUSR + CAMN A,USER + AOJA B,ALOGO5 + PUSH P,U + MOVE U,USER + MOVEM A,SRN3(U) ;AUCL4 FINDS USR IDX TO HACK HERE. + PUSHJ P,LOSSET + AUCL4 ;CLEAR BULGOS IF AUCL3 PCLSR'S + PUSHJ P,AUCL3 ;SET BULGOS AND WAIT FOR DIELOK TO CLEAR. + POP P,U + CONO PI,CLKOFF + PUSHJ P,LSWDEL + EXCH B,UPC(A) ;SET HIM UP TO LOG OUT. +ALOGO4: MOVEM B,SRN3(A) ; Remember old PC for unlocking locks. + MOVE B,[.LOGOUT] ;PUT THE FOLLOWING ROUTINE IN JOB'S AC'S: + MOVEM B,AC0S(A) ; 0/ .LOGOUT + CAMN A,USER ; 1/ .VALUE + UMOVEM B,0 ; 2/ JRST 0 + MOVSI B,(.VALUE) + MOVEM B,AC0S+1(A) + CAMN A,USER + UMOVEM B,1 + MOVSI B,(JRST) + MOVEM B,AC0S+2(A) + CAMN A,USER + UMOVEM B,2 + MOVSI B,BULGOS + IORM B,APRC(A) ;SAY HE'S DIEING SO NO-ONE WILL HACK HIM. + MOVEM U,EPDL(A) ;RECORD WHO IS KILLING HIM. + MOVE B,UNAME(U) + MOVEM B,SRN4(A) + MOVE B,JNAME(U) + MOVEM B,SRN5(A) + SETZM PICLR(A) ;PREVENT INTERRUPTS. + SETZM MSKST(A) + SETZM PIRQC(A) + MOVSI B,BUSRC + ANDCAM B,USTP(A) ;MAKE SURE HE CAN RUN - ELSE HE WOULDN'T LOG OUT. +ALOGO7: CONO PI,CLKON + CAME A,USER + POPJ P, + JRST ALOGO1 ;IF JOB IS RUNNING JOB, MUST HACK AROUND + +ALOGO5: EXCH B,UUOH ;LOGGING OUT SELF - MAKE OUR PC LOOK + SOJA B,ALOGO4 ; AS IF WE HAD EXECUTED THE .LOGOUT IN AC 0 + +;COME HERE IF LOGGING OUT ONESELF (A=USER). +ALOGO1: MOVE U,A + PUSHJ P,AUCL3 ;WAIT TILL NO-ONE IS LOOKING AT ME, + PUSHJ P,UBLAM ;CLOSE MY CHANNELS AND KILL MY INFERIORS AND CORE. + MOVE A,USER + CONO PI,CLKOFF ;DON'T SCHEDULE WHILE GOING AWAY + MOVSI T,BULGO + IORM T,APRC(A) ;SYS JOB KILLS ANY TREES WITH BULGO SET. + MOVSI T,SCLGUN + IORM T,SUPCOR ;TELL SYS JOB TO LOOK AROUND FOR TREES TO KILL. + MOVSI T,BUSRC ;SUICIDE: MAKE SURE WE DON'T RUN ANY MORE. + IORM T,USTP(A) + JRST UDELAY ;CAUSE A SCHEDULE + +;COME WITH JOB INDEX IN A. INDICATE THAT JOB IS ABOUT TO DIE, +;THEN WAIT TILL IT'S SAFE TO KILL IT. +;TURNS CLOCK ON. +AUCL3: MOVSI T,BULGOS + IORM T,APRC(A) ;SAY THIS JOB STARTING TO GO AWAY. + CONO PI,CLKON ;NOONE CAN START HACKING US NOW; SAFE. + CAME A,USER ;IF NOT LOGGING OUT RUNNING USER, + PUSHJ P,1USTOP ;STOP THE JOB BEING KILLED. + SKIPE DIELOK(A) ;WAIT TILL NO-ONE IS LOOKING AT THAT JOB. + PUSHJ P,UFLS + HRLOI T,#BUSRC ;AND NO-ONE ELSE HAS HIM PCLSR'ED. + TDNE T,USTP(A) + PUSHJ P,UFLS + POPJ P, ;WE SUCCEEDED, BUT CALLER HAS WORK TO DO. + +SUBTTL REAL TIME USER FEATURE +; +;.REALT AC, SKIPS ONLY IF REAL TIME FACILITY REQUESTED AND SEIZED +;AC= 4.9=>TURN OFF OLD CLOCK RATE, FLUSHING REAL TIME FACILITY AND +; REMAINDER OF CURRENT TICK AND ZEROING TICK COUNT +; 4.8=>TURN ON NEW CLOCK RATE +; 4.7=>TRY TO SEIZE REAL TIME USER FACILITY +; 4.6=>DON'T SETTLE FOR PSEUDO-REAL TIME STATUS +; 4.5 =>ONLY WANT PSEUDO +; 4.4=>PROGRAM TO BE BLOCKED EXCEPT FOR HIGH PRIORITY PHASE OR INT. LEVEL +; 4.3=>READ INTO WD3+4 AS DESCRIBED BELOW (BEFORE ANY OTHER BITS INTERPRETED) +; 3.1-4.2=RESERVED FOR EXPANSION, SHOULD BE ZERO +; 1.1-2.9=RH=POINTER TO 4 WORD BLOCK +; WD1=FRAME TIME IN 60'THS (MUST BE <2**18.) +; WD2=PRIORITY TIME IN 60'THS (MUST BE <7 AND .CALL [SETZ ? SIXBIT/LOSE/ ? 401000,,X ] + +;.CALL LOSE +; USED TO REPORT LOSSAGE TO SUPERIOR PROCEDURE +;ARG 1 - LOSING INSTRUCTION ADDR,,LOSSAGE CODE (CODES DEFINED BY DDT) +;ARG 2 - NEW PC (DEFAULT = PC-2 SO CAN USE AS A NON-SKIP-RETURN HANDLER) +;CTL 1.1 - DEFAULT ARG 2 TO PC INSTEAD OF PC-2 +;CTL 1.2 - SETZM @.40ADDR +;CTL 1.3 - DON'T USE THE NEW PC AS THE LOSING INSTRUCTION ADDR + +ALOSE: HRRZ A,FORTY ;ARG 1 = EFF ADDR OF UUO + MOVEI W,1 + TDZA T,T +NLOSE: MOVE T,CTLBTS(U) + MOVE D,40ADDR(U) + TRNE T,2 + XCTR XRW,[MOVES (D)] + TLZ B,BADPC ;COMPUTE NEW PC FROM ARG 2 OR UUOH + SKIPGE IOTLSR(U) + TLO B,%PCUIO + TLO B,%PCUSR + MOVE C,UUOH + TRNN T,1 + HRRI C,-2(C) + CAIGE W,2 + MOVE B,C + TRNN T,4 + HRL A,B + HRRI B,1(B) ;PCLSR'ING WILL SOS + MOVEM A,VALUE(U) ;PASS TO SUPERIOR + MOVEM B,UUOH + TRNE T,2 + XCTR XW,[SETZM (D)] + MOVSI T,%PJLOS + JRST UUOERR + +AUCLOSE: +IFN PDP6P,[ + MOVE A,(R) ;OPER 10 + MOVE A,CLSTB(A) + TLNE A,%CLS6 + JRST PDPUCL +] + PUSHJ P,AUCL2 + POPJ P, + PUSHJ P,1USTOP + MOVEM A,SRN3(U) + PUSHJ P,LOSSET + AUCL4 + PUSHJ P,AUCL3 ;STOP JOB, AND WAIT TILL SAFE TO KILL IT + ;(TURNS CLOCK ON) + EXCH U,A + PUSH P,A + HLLZ T,SUPPRO(U) + PUSH P,T + PUSH P,R + PUSHJ P,UBLAST + POP P,R + PUSHJ P,ZUSLOG ;ACCOUNT FOR USAGE THEN FLUSH LAST VESTIGES + CONO PI,CLKON + POP P,T + POP P,U + ANDCAM T,IFPIR(U) + JRST LSWDEL + +AUCL4: HRRZ A,SRN3(U) + MOVSI T,BULGOS + ANDCAM T,APRC(A) + POPJ P, + +AUCL2: HLRZ A,(R) ;GUY BEING CLOSED + HRRZ B,(R) + LDB TT,[.BP (%CLSFU),CLSTB(B)] + JUMPN TT,OPNL31 ;FOREIGN JOB => .UCLOSE ISCAN'T MODIFY JOB + SKIPL CLSTB(B) .SEE %CLSU + JRST OPNL34 ;NOT A JOB AT ALL? + CONO PI,CLKOFF + MOVE TT,TTYTBL(U) + JUMPGE TT,AUCL1 ;HAVE TTY NOW + TLNN TT,%TBDTY ;NOT GIVING IT AWAY. + CAIE A,(TT) ;SKIP IF GAVE IT TO GUY WE'RE KILLING + JRST AUCL1 + PUSHJ P,SDTTY ;TAKE IT BACK FROM HIM. + JFCL +AUCL1: HLRZ A,(R) + JRST POPJ1 + +;DISMIS SYSTEM CALL. 1ST ARG INT PDL PTR (WILL BE DECREMENTED +;IF NOT AN IMMEDIATE ARG) +;2ND ARG OPTIONAL PC TO DISMIS TO (OVERRIDES THAT IN INT PDL) +;3RD ARG OPTIONAL NEW .DF1 VALUE " " " " +;4TH ARG OPTIONAL NEW .DF2 VALUE ... +;5TH ARG OPTIONAL ERROR CODE AS IN LOSE. IF PRESENT WILL LOSE RIGHT AFTER DISMISSING. +;IF 4 ARGS GIVEN, 1ST IGNORED EXCEPT FOR POSSIBLY DECREMENTING, OR POPPING OF ACS. +;CTL BITS (SAME FORMAT AS LH OF 1ST WORD OF INTERRUPT DISPATCH TABLE) +;SPECIFY POPPING OF SAME EXTRA INFO THAT INTERRUPTS CAN PUSH. + +NDISMIS:CAIL W,5 + MOVEM E,VALUE(U) + MOVE E,A ;GET IN E THE INT PDL PTR. + TLNN E,1000 ;IF 1ST ARG IMMEDIATE, IT IS PTR, + UMOVE E,(A) ;ELSE IT PTS TO PTR. + MOVE H,E ;SAVE UNPOPPED PDL POINTER FOR PDL OV CHECKING. + TLNE A,1000 ;IF PDL PTR ISN'T IMMEDIATE, POP IT ACC. TO CTL BITS. + JRST NDISM2 + MOVE T,CTLBTS(U) + TRNE T,400000 + SUB E,[3,,3] ;POP OFF DEBUGGING INFO IF IT WAS PUSHED. + LDB TT,[000500,,T] + JUMPE TT,NDISM2 ;IF ACS WERE PUSHED, POP THEM TOO. + HRLS TT + SUB E,TT ;DECREMENT THE PDL POINTER ENOUGH + LDB I,[060500,,T] + HRLI I,1(E) ;AND COPY FROM THE PDL TO THE ACS. + ADDI TT,-1(I) + XCTR XBRW,[BLT I,(TT)] +NDISM2: CAIGE W,2 ;IF NO 2ND ARG, GET PC FROM INT PDL + UMOVE B,(E) + CAIGE W,3 ;IF NO 3RD ARG, GET .DF1 FROM INT PDL + UMOVE C,-2(E) + CAIGE W,4 ;IF NO 4TH ARG GET .DF2 FROM INT PDL + UMOVE D,-1(E) + TLNE A,1000 ;IF 1ST ARG NOT IMMED, DECREMENT IT + JRST NDISM3 + SUB E,[5,,5] + UMOVEM E,(A) + JUMPGE E,NDISM3 ;AND CHECK FOR PDL OVFLO. + SKIPL H + PUSHJ P,NDISMP ;PDL OVFLO, SET INT BIT IF INT ENABLED. +NDISM3: MOVEM C,IDF1(U) ;RESTORE THE PC, .DF1, .DF2 + MOVEM D,IDF2(U) + MOVSI T,%PJLOS + CAIL W,5 + IORM T,PIRQC(U) + JRST NDISM1 + +NDISMP: MOVEI TT,%PIPDL ;PDL OV INT BIT. + TDNE TT,MSKST(U) + IORM TT,PIRQC(U) + POPJ P, + +;OLD-STYLE DISMISS JOINS HERE +ADISMIS:UMOVE B,(B) ;CALL 1, +NDISM1: TLO B,%PCUSR + TLZ B,BADPC + SKIPGE IOTLSR(U) + TLO B,%PCUIO +IFN KL10P,[ + SETCM A,UUOH ;IF ONE-PROCEEDING THE .DISMISS + TLNN A,%PS1PR-%PSINH + TLO B,%PS1PR-%PSINH ;TRAP IMMEDIATELY AT THE NEW PC +] + MOVEM B,UUOH + SETOM PICLR(U) + +;CHECK FOR PENDING INTERRUPTS AND TAKE THEM RIGHT AWAY +APISE1: +IFN PDP6P,[ + CAMN U,PDPISR + CONO DSDEV,DSDCHN ;ENABLE INTERRUPT FROM 6 +] + MOVE A,U + PUSHJ P,APISE6 ;SEE IF ANY DEVICES WANT TO RE-INTERRUPT. + MOVEI C,%PIARO + ANDCAB C,PIRQC(U) + SETCM D,MSKST(U) + IOR D,IDF1(U) ;FIND ALL DISABLED OR DEFERRED + SKIPN PICLR(U) ;(ALL ARE DEFERRED WHEN PI IS OFF). + SETO D, + AND D,[BADBTS] ;BAD + TDNE C,D ;PENDING INTERRUPTS + JRST ADISM7 ;IF THERE ARE ANY, LET THEM HAPPEN. + AND C,MSKST(U) + ANDCM C,IDF1(U) + JUMPN C,ADISM7 ;1ST WD INT. PENDING. + MOVE C,IFPIR(U) + AND C,MSKST2(U) + ANDCM C,IDF2(U) + JUMPE C,CPOPJ ;JUMP IF NO 2ND WORD INT PENDING. +ADISM7: MOVE C,[JRST ONEFLS] + MOVEM C,UEXIT + POPJ P, + +APISE6: MOVE D,MSKST(A) ;IF INTERRUPT FROM CONSOLE ENDBLED, + TRNN D,%PITYI + JRST APISE7 + SKIPL T,TTYTBL(A) ;IF THIS JOB HAS ITS CONSOLE + SKIPN TINTC(T) ;AND THE CONSOLE HAS INT. CHARS, + JRST APISE7 + MOVEI D,%PITYI ;GENERATE AN INTERRUPT. + IORM D,PIRQC(A) +APISE7: MOVE D,MSKST2(A) ;LOOK AT HIS ENABLED IO CHANNELS. + ANDI D,177777 +APISE0: JFFO D,APISE9 ;CHECK EACH ONE. + JRST APISE8 ;ALL CHECKED. + +APISE9: MOVNS E ;CHECK ONE IO CHNL THAT'S ENABLED TO INT. + ANDCM D,CHNBIT+35.(E) ;MARK THIS CHNL AS HANDLED. + ADDI E,35.+IOCHNM(A) ;GET ADDR OF IOCHNM WD FOR CHANNEL. + HRRZ T,(E) ;IS IT A TTY INPUT CHANNEL? + CAIL T,TYIDN + CAILE T,TYIBN + JRST APISE2 + LDB T,[$TIIDX,,(E)] ;YES, GET THE TTY NUMBER. + HRRZ C,TTYSTS(T) + CAIE T,%TINON ;IF IT ISN'T A DISOWNED TY CHANNEL, + CAIE C,(A) ;AND THE TTY BELONGS TO THIS JOB, + JRST APISE0 + SKIPN TINTC(T) ;AND IT HAS AN INT. CHAR WAITING, + JRST APISE0 + MOVE C,TYIMSK(T) +APISE4: AND C,MSKST2(A) ;GIVE AN INT. ON ONE OF THE CHANNELS IT'S OPEN ON. + MOVN T,C + AND C,T + IORM C,IFPIR(A) + JRST APISE0 + +APISE2: CAIN T,STYDUI ;NOT A TTY CHNL. IS IT A STY CHNL? + JRST APISE3 + CAIE T,STYDBI + JRST APISE0 +APISE3: LDB T,[$TIIDX,,(E)] ;YES, GET TTY #. + SKIPL C,STYSTS-NFSTTY(T) ;STY IN USE BY THIS JOB? + CAIE C,(A) + JRST APISE0 + SKIPGE TTYOAC(T) ;TTY OUTPUT PENDING? + JRST APISE0 + MOVE C,STYMSK-NFSTTY(T) ;YES, INT. ON ONE CHANNEL. + JRST APISE4 + +APISE8: +IFN STKP,[ + SKIPL C,STKUSR + CAIE C,(A) + POPJ P, + HRRZ C,STKMSK + AND C,MSKST2(A) + SKIPLE STKBC + IORM C,IFPIR(A) +] + POPJ P, + +;.SLEEP AC, ;IF C(AC) + OR ZERO: ;BECOME DORMANT FOR C(AC) 1/30'THS OF A SEC + ;IF C(AC) -: ;BECOME DORMANT TILL MAGNITUDE OF C(AC) > C(TIME) +ASLEEP: XCTR XR,[MOVN T,(J)] ;PICK UP NEGATIVE OF C(AC) + JUMPGE T,ASLP1 ;JUMP IF C(AC) WAS NEG + SUB T,TIME ;COMPUTE NEG OF TIME SLEEP SHOULD RUN OUT + UMOVEM T,(J) ;STORE BACK SO YOU WILL WIN IF PCLSR'ED OUT +ASLP1: MOVMS A,T ;MAKE POSITIVE + SUBI A,60.*30. ;IF SLEEPING FOR MORE THAN A MINUTE + MOVSI B,%SWDSO + CAMLE A,TIME + IORM B,USWST(U) ;PUT RIP VAN WINKLE ON ICE + PCLT + JRST ASLP2 ;ALWAYS GO TO UFLS AT LEAST ONCE + + CAMLE T,TIME ;HANG TILL C(T) LESS THAN C(TIME) +ASLP2: PUSHJ P,UFLS + XCTR XW,[SETZM (J)] ;CLEAR OUT ARG (FOR COMPATIBILITY WITH WHEN AC WAS COUNTED OUT) + JRST CLKONJ ;MAKE SURE CLKCHN ON IN CASE SLEEP WAS 0 & SKIPPED UFLS ENTIRELY + +;RELOAD CALL - IGNORE ARGS +;MUST BE FROM TOP LEVEL NON-DISOWNED JOB +;RELOADS AND STARTS SYS: ATSIGN WHATEVER + +NRELOAD:SKIPGE SUPPRO(U) + SKIPGE APRC(U) + JRST OPNL40 ;NOT TOP LEVEL + CONO PI,CLKOFF + PUSHJ P,LOGUPD ;LOG OUT + PUSHJ P,DMNPLI ;AND IN AGAIN + PUSHJ P,USRST2 ;RESET USER VARS + CONO PI,CLKON + SETZM @UTMPTR(U) ;TEMPORARY HIGH PRIORITY + JRST USTCDR ;LOAD FILE AND START IT + +AMASTER:UMOVE J,(J) + CONO PI,CLKOFF ;OPER 61 + SKIPL A,UMASTER + JRST AMAST2 + SKIPGE J +AMAST1: HRRZM U,UMASTER + JRST CLKOJ1 + +AMAST2: CAME U,A + JRST AMAST3 + SKIPL J + SETOM UMASTER + JRST CLKOJ1 + +AMAST3: JUMPGE J,CLKOJ1 + SKIPGE TTYTBL(U) + JRST CLKONJ ;LOSEY + PUSHJ P,RPCCK + CAME A,UMASTER + JRST AMASTER + JRST AMAST1 + +;.CALL SSERVE - Set .SERVER variable without timing screw. +; ARG1: , the client whose .SERVER variable is to be munged +; ARG2: , the server to be stored in the variable +; If one arg is given, it is the server and the client defaults to %JSELF +NSSERVER: + MOVE J,A + CAIL W,2 + SKIPA A,B + MOVEI J,%JSELF + JSP T,NCORUI ; Decode client and AOS his DIELOK + JRST NSSRV1 ; OK to write + JSP T,NCORWR ; Check further + JRST OPNL31 ; CAN'T MODIFY JOB +NSSRV1: +IFN PDP6P,[ + CAIN J,-1 ; PDP6? + JRST OPNL34 ; WRONG TYPE DEVICE +];PDP6P + EXCH J,A ; A: client J: server + JSP T,NCORUI ; Decode server and AOS his DIELOK + JFCL ; Don't give a damn about writability +IFN PDP6P,[ + CAIN J,-1 ; PDP6? + JRST OPNL34 ; WRONG TYPE DEVICE +];PDP6P + MOVEM J,SERVER(A) ; Safe to set it now + PUSHJ P,LSWPOP ; Server's DIELOK + JRST LSWPJ1 ; Client's DIELOK + + + SUBTTL LOGIN/ATTACH/DETACH/DISOWN CODE + +;SYMBOLIC CALL LOGIN: LOG A TREE IN. MUST BE GIVEN BY TOP-LEVEL NON-LOGGED-IN JOB +;WITH NO INFERIORS. +;ARG 1 - DESIRED UNAME +;ARG 2 - "TERMINAL NAME", PUT IN TRMNAM USER VARIABLE AND PRINTED AS SIXBIT ON SYSCON. +;ARG 3 - DESIRED XUNAME, FOR DEMON TO KNOW WHO TO ACCOUNT. + +NLOGIN: HLRE T,UNAME(U) + AOJN T,OPNL31 ;JUMP ON ALREADY LOGGED IN + SKIPL SUPPRO(U) + JRST OPNL40 ;CAN'T LOG IN IF NOT TOP LEVEL + JUMPE A,OPNL11 + HLRE T,A + AOJE T,OPNL11 ;BAD NAME + CAIGE W,3 + MOVE C,A ;IF XUNAME (ARG 3) MISSING, DEFAULT TO UNAME. + MOVEI D,0 + CONO PI,CLKOFF +ALOG2: SKIPN UNAME(D) + JRST ALOG4 + MOVE T,JNAME(D) + CAMN T,JNAME(U) + CAME A,UNAME(D) + JRST ALOG3 + JRST OPNL13 ;CONSOLE CONTROLLED TREE ALREADY LOGGED IN THAT NAME + +ALOG3: HRRZ T,SUPPRO(D) + CAMN T,U ;CAN'T LOGIN IF HAVE INFERIOR. RESTRICTION IMPOSED HERE + JRST OPNL12 ;SINCE WE NO CODE HERE TO SET INFERIOR'S UNAME. +ALOG4: ADDI D,LUBLK + CAMGE D,USRHI + JRST ALOG2 ;LOOP FOR ALL SETS OF PROCEDURE VARIABLES + HRRZ T,TTYTBL(U) + HRLI T,[ASCIZ / LOGIN /] + PUSHJ P,SGWAIT ;ASK THE SYSTEM JOB TO PRINT OUT THE RELEVANT INFO + SKIPL TTYTBL(U) ;SKIP IF NOT CONSOLE CONTROLLED + AOS SUSRS ;INCREMENT COUNT OF LOGGED IN CONSOLE CONTROLLED TREES + MOVEM A,UNAME(U) ;SET UNAME TO WHAT LOGGED IN AS + MOVEM A,SLGIV + MOVEM A,USYSNM(U) ;SET SNAME " + MOVEM A,HSNAME(U) ;SET HOME SNAME " + MOVEM C,XUNAME(U) ;SET XUNAME " " (USER MAY MUNG LATER) + MOVEM B,TRMNAM(U) + MOVEM B,SLGIV+2 ;INCLUDE TRMNAM AS SECOND NAME PRINTED + PUSHJ P,DMNPLI ;GIVE INFO TO DEMON + JRST CLKOJ1 ;TURN CLK ON AND SKIP RETURN + +ASETM2: UMOVE A,1(J) ;.OPER 5 + MOVEM A,MSKST2(U) +ASETMSK: UMOVE D,(J) ;OPER 4 + MOVE A,U + MOVEI I,1 + SOS (P) ;WILL SKIP RETURN + JRST USMASK ;ACT LIKE .SUSET. + +ARSYSI: SKIPA A,[ITSVRS] ;OPER 52 +ARDTIME:MOVE A,TIME ;OPER 17 + JRST APTUAJ + +IFE KS10P,[ ; On the KS10 they made DATAI 0, a UUO! +ARDSW: DATAI A ;OPER 20 + JRST APTUAJ +] ;IFE KS10P +IFN KS10P, ARDSW==:ILUUO + +ASUPSET:MOVEI C,003777 ;OPER 53 + XCTR XR,[AND C,(J)] + MOVE D,SUPCOR ;SAVE OLD CONTENTS + XORB C,SUPCOR + UMOVEM C,(J) + HRROI A,SUPCOR + JRST ASPST2 + +; .CALL DET +; ERROR RETURN +; NORMAL RETURN + +;DET: SETZ +; SIXBIT /DETACH/ +; SETZ [] ;SEE NCORUI + +;DISOWN JOB'S ENTIRE TREE AND FREE CONSOLE. IF TREE HAS NO +;CONSOLE, JUST MAKES IT DISOWNED. NO ARG => THIS JOB'S TREE +;ALWAYS SKIPS IF THE JOB SPEC IS REASONABLE. + +;CTL BIT 1.1 => DON'T SET SIGN OF APRC (DON'T MAKE TREE "DISOWNED"). +;CTL BIT 1.2 => USE SYSTEM TREE'S RESOURCE WORD +;CTL BIT 1.4 => KILL TREE AN HOUR FROM NOW IF IT ISN'T REOWNED +;CTL BIT 1.5 => SUPPRESS THE CONSOLE-FREE MESSAGE ON THE TTY + +NDETAC: HLRZ B,A ;XOR LH OF 1ST ARG INTO CTL BITS + XORM B,CTLBTS(U) + PUSHJ P,SWTL ;MAKE SURE NOBODY ELSE IS REARRANGING TREES. + TREESW + MOVEI J,(U) ;DEFAULT TO OUR TREE + JUMPE W,NDETA0 ;JUMP IF NO ARGS SUPPLIED + MOVE J,A ;JOB SPEC + JSP T,NCORUI ;DECODE ARG, GET USER INDEX IN J + JFCL ;IGNORE INFO ON WRITEABILITY + CAIG J,LUBLK ;DONT DETACH SYSJOB OR CORE JOB + JRST OPNL31 +NDETA0: SKIPL T,SUPPRO(J) ;FIND TOP LEVEL JOB OF TREE (IN J) + JRST [ MOVE J,T + JRST NDETA0 ] + HRRZ A,J ;TOP OF TREE + SKIPGE APRC(A) + JRST LSWCJ1 ;TREE IS ALREADY DISOWNED. + MOVEI Q,NDETA8 + PUSHJ P,IFPLUP ;STOP ALL BUT THIS JOB + PUSHJ P,NDETA7 ;DO THE WORK + JRST LSWCJ1 ;UNSTOP THE TREE + +NDETA7: PUSH P,U ;US + PUSH P,A ;TOP LEVEL + MOVEI U,(A) + CONO PI,CLKOFF + PUSHJ P,LOGUPD ;FOR ACCOUNTING PURPOSES, THIS IS LIKE A LOGOUT + CONO PI,CLKON +NDETA1: MOVEI U,(A) ;GET IN U USER INDEX OF OWNER OF TTY + MOVE A,TTYTBL(U) ;GET IN A TTY NUMBER + TLNE A,%TBDTY ;TREE HAS NO TTY => + JRST [ POP P,A ;JUST MAKE IT DISOWNED. + POP P,U + JRST NDETA5 ] + JUMPL A,NDETA1 ;GAVE TTY AWAY + MOVE T,(P) ;TOP-LEVEL JOB OF TREE SAVES USER TTY OPTIONS IN + MOVE B,TTYOPT(A) ;HIS STTYOP VARIABLE + AND B,[%TOUSR,,%TPUSR] + MOVEM B,STTYOP(T) + LDB B,[.BP (%TCRFS+%TCQRY),TTYCOM(A)] + IORI B,4 ;MAKE STTYOP NON-ZERO TO SHOW IT WAS STORED + DPB B,[170300,,STTYOP(T)] ;OVERLAPS PADLF FIELD + HRRZS A + PUSH P,TTYSTS(A) ;SAVE THIS TTY INFO + PUSH P,TTYST1(A) ;WILL PUT INTO TTY OWNER'S USER VARS + PUSH P,TTYST2(A) ;AFTER SUCCEED IN FREEING THE TTY + MOVE B,A + IMULI B,TPLEN*2 + MOVN B,TPVB+TPLEN(B) + ADD B,TCMXV(A) + PUSH P,B + MOVSI B,%TCDET ;IF TREE DETACHED DUE TO TOP LVL INT, + SKIPN USER ;THE CONSOLE FREE MESSAGE SHOULD SAY SO. + IORM B,TTYCOM(A) .SEE SYSCFM + ;THIS ALSO HAPPENS IF DIALUP LINE HUNG UP, OS'ERS BEWARE! +;DROPS THROUGH + ;DROPS IN +IFN N11TYS,[ + CONO PI,CLKOFF + PUSHJ P,TVBNCL ;CLEAR VIDEO BUFFER # + CONO PI,CLKON +];N11TYS + MOVE B,-5(P) ;GET BACK IDX OF RUNNING JOB + MOVE B,CTLBTS(B) + MOVSI T,%TACFM + TRNE B,20 ;CTL BIT 1.5 => MARK THE TTY AS NOT NEEDING CNSL FREE MSG. + IORM T,TTYSTA(A) + PUSHJ P,TTYLO1 ;NOW MAKE CONSOLE FREE. + POP P,B ;CAN'T PCLSR AFTER THIS POINT + DPB B,[$TBECL,,TTYTBL(U)] + POP P,TTSTSV+1(U) ;STORE INTO TTY'S OLD OWNER + POP P,TTSTSV(U) ;OLD TTY VARS FROM BEFORE FREEING IT + POP P,B + MOVEM B,TTSTSV+2(U) + SKIPA A,(P) ;TOP LEVEL JOB +NDETAA: HRRZ A,T + SKIPGE T,TTYTBL(A) ;SKIP IF HE HAS IT + JRST NDETAA ;NOW DO GUY HE GAVE IT TO + CAIE A,(U) + BUG ;BUT. BUT. BUT. + MOVSI B,%TBNOT+%TBDTY ;TAKEN FROM --ME-- AND DOESN'T HAVE IT + IORM B,TTYTBL(A) + HLLZS TTYTBL(A) + POP P,A ;TOP LEVEL + POP P,U ;US + HLRO B,UNAME(A) + AOSE B ;IF DETACHED TREE WAS LOGGED IN + SOS SUSRS ;ONE LESS CONSOLE CONTROLLED TREE +NDETA5: MOVSI B,BUMRTL ;IF REQUESTED, MARK TREE AS DUE TO DIE + MOVE D,CTLBTS(U) ;IN AN HOUR. + ANDCAM B,APRC(A) + TRNE D,10 + IORM B,APRC(A) + CONO PI,CLKOFF ;PERFORM ACCOUNTING FOR THIS USER AS IF HE WERE LOGGING OUT. + EXCH U,A + PUSHJ P,LOGUPD + EXCH U,A + MOVE D,JNAME(A) ;IF TOP LEVEL JOB ... + CAME D,[SIXBIT /HACTRN/] ;IS A HACTRN, + JRST NDETA3 +NDETA2: AOS D ;AOS ITS NAME LEVEL UNTIL ... + PUSHJ P,UJNAMU ;IT IS UNIQUE + JRST NDETA2 ;(UJNAMU TURNS OFF CLOCK) + MOVEM D,JNAME(A) +NDETA3: EXCH U,A + PUSHJ P,DMNPLI ;LOG BACK IN, NAME MAY HAVE CHANGED FROM HACTRN TO HACTRO + EXCH U,A + CONO PI,CLKON + MOVEI Q,NDETA9 ;NOW SAY ALL JOBS IN TREE + JRST IFPLUP ;ARE DISOWNED + +NDETA8: CAIE A,(U) ;IF JOB ISN'T SELF, STOP IT + JRST IFSTOP + POPJ P, + +;"ATTACH" SYSTEM CALL: +;1ST ARG - JOB SPEC -> OUR INFERIOR, OR TOP OF A DISOWNED TREE. +;2ND ARG - TTY SPEC (OF A TTY WHICH MUST BE FREE) + ;2ND ARG ABSENT => USE OUR CONSOLE, AND GUN OUR TREE +;CONTROL BIT 400000 => CHANGE JOB'S NAME TO HACTRN (IF 2 ARGS) +; 4 => START JOB AFTER ATTACHING (JUST LIKE DETACH) + +;CONNECTS THE SPECIFIED JOB TO THE SPECIFIED TTY, AS A CONSOLE CONTROLLED TREE. +;IF THE TTY IS OUR CONSOLE, WE ARE LOGGED OUT. +;IF THE JOB IS OUR INFERIOR, IT IS FIRST DISOWNED. + +NATTAC: PUSHJ P,SWTL + TREESW + SOJE W,NATTAN + EXCH A,B ;2ND ARG => IT IS TTY SPEC, SO DECODE IT. + JSP J,ATTYCI + MOVE A,B + MOVE B,I ;AND PUT IT IN B. + JRST NATTA6 + +NATTAN: SKIPL B,SUPPRO(U) ;NO 2ND ARG => WE MUST BE TOP LEVEL, SINCE WE'LL HAVE + JRST OPNL40 ;TO LOG OUT. B GETS NEGATIVE. +NATTA6: MOVE J,A + JSP T,NCRUI2 ;DECODE 1ST ARG, GET USR IDX IN J. + JFCL + SKIPGE A,SUPPRO(J) + JRST NATTA5 ;JOB SPEC'D MUST BE EITHER + CAIE U,(A) ;OUR INFERIOR, OR + JRST OPNL31 + JRST NATTA7 + +NATTA5: SKIPL APRC(J) ;THE TOP OF A DISOWNED TREE. + JRST OPNL31 +;NOW IF TTY IS OUR CONSOLE, B IS NEGATIVE; OTHERWISE, B HAS TTY #. +NATTA7: PUSH P,CTLBTS(U) + SETZM CTLBTS(U) ;DON'T GET FAKED OUT AT NATTA1, NATTA2, DSWNTY. + PUSH P,J + MOVE A,J + MOVEI Q,NDETA8 ;STOP SPEC'D JOB AND ITS INFERIORS. + PUSHJ P,IFPLUP + JUMPL B,NATTAG +NATTAM: CONO PI,TTYOFF + SKIPL T,TTYSTA(B) ;SEE IF TTY IS FREE + JRST NATTAL + MOVSI T,(SETZ) ;IT IS, GRAB IT + ANDCAM T,TTYSTA(B) .SEE %TACFM + ANDCAM T,TTYSTS(B) .SEE %TSFRE + CONO PI,TTYON + JRST NATTA8 ;SINCE NO PCLSR POSSIBLE, DON'T BOTHER WITH A LOSSET OF THESE + +NATTAL: HRRE Q,TTYSTS(B) + CONO PI,TTYON + SKIPG Q ;IF TTY IS IN USE + TLNE T,%TACTZ ;OR BEING ^Z'ED, DEVICE NOT AVAIL + JRST [ SUB P,[2,,2] ? JRST OPNL10 ] + MOVSI T,%TACFM+%TACTZ ;OTHERWISE JUST WAIT FOR CONSOLE FREE + TDNN T,TTYSTA(B) ;MESSAGE TO FINISH COMING OUT + PUSHJ P,UFLS + JRST NATTAM + +NATTAG: MOVE A,U ;IF HACKING OUR CONSOLE, MUST STOP OUR WHOLE TREE + MOVEI Q,NDETA8 ;(EXCEPT US, OF COURSE - NDETA8 CHECKS THAT). + PUSHJ P,IFPLUP + MOVEI B,(U) +NATTA4: MOVE B,TTYTBL(B) ;FIND THE TTY'S NUMBER. + TLNE B,%TBDTY + JRST NATTAL ;THIS TREE HAS NO TTY? + JUMPL B,NATTA4 .SEE %TBNOT + PUSHJ P,SDTTY ;GET TTY BACK TO TOP OF TREE FOR AGBLT3 LATER. + BUG + HRRO B,TTYTBL(U) +;I BELIEVE THAT NOTHING CAN PCLSR BEYOND THIS POINT. +;RH OF B HAS TTY #; SIGN IS SET IF TTY IS OUR CONSOLE. +NATTA8: AOS TTNTO(B) ;KEEP DSWNTZ FROM HALTING (WILL UNDO THIS LATER) + PUSH P,B ;PUSH ,, + HRRZ A,-1(P) ;LEGALITY OF CALL FULLY CHECKED; CAN START ALTERING. + SKIPGE APRC(A) ;IF SPEC'D JOB IS OUR INFERIOR, DISOWN IT. + JRST NATTA9 + MOVE B,TTYTBL(A) + TLNE B,%TBDTY ;IF THE INFERIOR HAS THE TTY, TAKE IT AWAY. + JRST NATTAF + PUSHJ P,SDTTY + BUG +NATTAF: HRRZ A,-1(P) + MOVEI Q,DSWNTY ;JUST LIKE .DISOWN, BUT KNOW JOBS ARE ALREADY STOPPED. + PUSHJ P,IFPLUP + PUSHJ P,NATTA1 +NATTA9: MOVEI Q,NATTA2 + MOVE A,U + SKIPGE (P) ;IF HACKING OUR CONSOLE, DISOWN OUR TREE SO IT IS FREE. + PUSHJ P,IFPLUP + ;OUR TTY NOW IN INCONSISTENT STATE SINCE WE ARE DISOWNED + ;BUT TTY STILL BELONGS TO US. AGBLT3 FIXES THAT. + MOVE B,(P) + SOSGE TTNTO(B) + BUG + MOVE TT,-1(P) ;NOW "RE-OWN" THE SPEC'D JOB + MOVE A,UNAME(TT);NOT CHANGING ITS UNAME + HRRZ J,B ;TO THE DESIRED TTY, WITH APPRO. RESOURCE WORD. + MOVEI D,USRRCE(B) + TLO D,400000 ;TELLS UFN2A THE TREE SHOULD BECOME UN-DISOWNED. + SETZ B, ;NO INTERRUPT BIT NEEDED. + SETOM DLSRCH ;INHIBIT SCHEDULING (UFN2A UNDOES THIS) + PUSH P,U + PUSHJ P,UFN2A + POP P,U + HRRZ A,-1(P) + SKIPA C,A +NATTAH: MOVE C,D ;FIND THE JOB IN THE TREE BEING ATTACHED + MOVE D,TTYTBL(C) + TLNN D,%TBDTY ;THAT IS SUPPOSED TO GET CONTROL OF THE TTY. + JRST NATTAH + SETOM SUPPRO(A) ;BUT DON'T LEAVE IT THINKING IT IS OUR INFERIOR. + SKIPGE I,(P) + JRST NATTAD + HLRE B,UNAME(A) ;ATTACHING JOB TO FREE TTY: + AOSE B + AOS SUSRS ;THIS MAY MEAN 1 MORE LOGGED IN CONSOLE-CTL'ED TREE. + CONO PI,TTYOFF + PUSHJ P,TTYINI ;INIT TTYOPT, ECHO AREA, TTYCOM, TTYSTA. + MOVSI B,%TSFRE ;NOW MAKE TTY'S TTYSTS HAPPY + ANDCAM B,TTYSTS(I) + MOVSI B,%TSCNS + IORM B,TTYSTS(I) + HRRM A,TTYSTS(I) + CONO PI,TTYON#1 ;TTYCHN ON, BUT NOT CLKCHN. + PUSH P,U + PUSH P,I ;IF THE JOB BEING ATTACHED IS LOGGED IN, + MOVE U,-3(P) ;PERFORM ACCOUNTING FOR IT. + HLRO T,UNAME(U) + AOSE T + PUSHJ P,LOGUPD + POP P,I + POP P,U +;DROPS THROUGH + ;DROPS IN + MOVE D,['HACTRN] + PUSHJ P,UJNAMU + JRST NATTAI + MOVE B,-2(P) ;SAVED CTLBTS(U) AT ENTRY + TRNE B,400000 + MOVEM D,JNAME(A) +NATTAI: MOVE B,-2(P) ;CTLBTS + MOVSI D,%USTSP ;BUSRC + TRNE B,4 + ANDCAM D,USTP(A) ;START JOB BEING ATTACHED, IF REQUESTED TO + PUSH P,U + HRRZ U,C ;GET USR IDX GIVING TTY TO IN U, +IFN N11TYS,[ + HRRZ T,I ;TTY # IN T FOR USTTV0 + PUSHJ P,USTTV0 ;GIVE THE JOB A BLINKER IF IT DESERVES ONE. + JFCL +] + POP P,A ;USR IDX TAKING TTY FROM (BUT NOT REALLY TAKING). I AND U STILL SET. + PUSHJ P,AGBLT4 ;MOVE HIS PER-JOB VARIABLES INTO THE TTY'S VARIABLES, ETC. + JRST NATTAE ;CLOCK IS NOW BACK ON. + +NATTAD: CONO PI,CLKOFF + MOVE J,JNAME(U) ;ATTACHING OUR TTY TO JOB: + MOVEM J,JNAME(A) ;GIVE JOB OUR JNAME ALONG WITH OUR TTY. + MOVE A,U + HRRZ U,C + PUSHJ P,AGBLT6 ;TRANSFER TTY TO HIM, SAVING OUR TTY STATE AND LOADING HIS. +NATTAE: MOVE U,A + POP P,B + EXCH U,(P) ;U := USER INDEX OF TOP OF TREE BEING ATTACHED + MOVSI T,BUMRTL ;SINCE TREE HAS BEEN ATTACHED, IT SHOULDN'T + ANDCAM T,APRC(U) ;DIE AN HOUR AFTER IT WAS DETACHED. + SKIPN STTYOP(U) ;RESTORE SAVED TTY OPTIONS, IF ANY + JRST NATTAP + LDB T,[170200,,STTYOP(U)] + DPB T,[.BP (%TCRFS+%TCQRY),TTYCOM(I)] + MOVE T,[%TOUSR,,%TPUSR] + ANDCAM T,TTYOPT(I) + AND T,STTYOP(U) + IORM T,TTYOPT(I) +NATTAP: HLRE T,UNAME(U) + CONO PI,CLKOFF + AOSE T + PUSHJ P,DMNPLI ;LOG HIM IN + CONO PI,CLKON + POP P,U + SUB P,[1,,1] ;FLUSH SAVED CTLBTS + PUSHJ P,LSWCLR ;UNSTOP THE JOBS AND FREE TREESW + JUMPGE B,POPJ1 ;RETURN IF WE DIDN'T GIVE AWAY OUR CONSOLE. + SETOM TTYTBL(U) ;DON'T WANT ALOGOU TO TYPE LOGOUT MESSAGE. + JRST ALOGOUT ;LOG THIS JOB OUT. + +;.CALL DISOWN +; RH OF ARG IS JOB SPEC, OF OUR INFERIOR. +; LH OF ARG XOR CONTROL BITS: +; 1.1 => RETAIN PRIORITY (DON'T SET APRC) +; 1.2 => USE SYSTEM RESOURCE +; 1.3 => CLEAR .USTP AFTER DISOWNING (THUS AVOIDING TIMING ERROR) +; 1.4 => SET BUMRTL SO THAT JOB WILL BE GUNNED IF IT IS STOPPED FOR A WHOLE HOUR +; AND NOT REOWNED OR ATTACHED. + +NDISOWN:HLRZ J,A + XORM J,CTLBTS(U) ;XOR LH OF 1ST ARG INTO CTL BITS. + HRRZ J,A + JSP T,NCRUI2 ;DECODE JOB SPEC; DON'T SET DIELOK. + JFCL + CAIN J,-1 + JRST OPNL31 ;PDP6 NO GOOD. + MOVEI R,IOCHNM(U) + ADD R,A ; R GETS ADDR OF IOCHNM WORD IF ARG WAS CHANNEL #, + TRNE A,400000 ;GET S0 IF ARG WAS OTHER SORT OF JOB SPEC. + SETZ R, + HRRZ A,J + HRRZ J,SUPPRO(A) + CAME J,U + JRST OPNL31 ;NO GOOD IF NOT OUR INFERIOR. + JRST NDISO1 ;JOIN OLD-STYLE DISOWN + +;.DISOWN CH, ;MAKES DIRECTLY INFERIOR PROCEDURE OPEN ON CHANNEL CH + ;THE TOP LEVEL JOB OF A DISOWNED JOB + +ADISOWN:HRRZ B,(R) ;PICK UP CH TYPE INDEX + SKIPL CLSTB(B) .SEE %CLSU ;SKIP IF AN INF. USER CHANNEL + JRST IOCER7 ;OTHER TYPE, GIVE IOC ERROR + HLRZ A,(R) ;PICK UP INF.'S INDEX + SETZM CTLBTS(U) +NDISO1: PUSHJ P,SWTL + TREESW + SETZM STTYOP(A) + MOVE B,TTYTBL(A) + TLNE B,%TBDTY ;SKIP IF TTY TAKEN AWAY + JRST ADISO1 + PUSH P,R + PUSH P,A ;JOB TO BE DISOWNED HAS THE TTY: TAKE IT AWAY. + PUSHJ P,SDTTY + BUG + POP P,A + POP P,R +ADISO1: MOVEI Q,DSWNTY + PUSHJ P,IFPHAK ;HACK INFERIORS + CAME U,USER + BUG + PUSHJ P,NATTA1 ;FLUSH OUR POINTERS TO INFERIOR, AND SET FLAGS + CAME U,USER + BUG + JRST LSWCJ1 ;UNSTOP HIS TREE AND FREE TREESW + +;FLUSH INFERIOR-JOB CHANNELS FROM JOB IN U TO JOB IN A +;CANNOT PCLSR BECAUSE JOB IS CURRENT OR STOPPED ALREADY +NATTA1: MOVEI R,0 ;NO PROTECTED CHANNEL + MOVEI D,%CLSU + EXCH U,A + PUSHJ P,ZUSES1 ;FLUSH POINTERS TO INFERIOR + EXCH U,A + SETOM SUPPRO(A) ;MARK AS TOP LEVEL + MOVE W,CTLBTS(U) + MOVSI TT,BUSRC ;CLEAR .USTP IF REQUESTED + TRNE W,4 + ANDCAM TT,USTP(A) + MOVSI TT,BUMRTL + TRNE W,10 + IORM TT,APRC(A) + POPJ P, + +DSWNTY: SKIPL TTYTBL(A) + BUG ;CHECKED AT HIGHER LEVEL, DATA INCONSISTENT +NATTA2: TDZA T,T ;DO SOS TTNTO OF CONSOLE TTY. +NDETA9: SETO T, ;DON'T. + PUSHJ P,CHSCAA ;LOOK AT ALL CNHLS + PUSHJ P,DSWNTZ ;BLESSING CONSOLE TTY CHNLS + MOVEI TT,SYSRCE ;SET RESOURCE POINTER TO SYSTEM OR DISOWNED + MOVE W,CTLBTS(U);DEPENDING ON CTLBTS + TRNN W,2 + MOVEI TT,USRRCE+NCT + MOVEM TT,UTMPTR(A) + MOVSI T,400000 + TRNN W,1 + IORM T,APRC(A) ;MARK AS DISOWNED + POPJ P, + +;BLESS CONSOLE TTY CHANNELS. IF T NONZERO, DON'T SOS TTNTO. +DSWNTZ: HLRZ B,(R) ;GET LH OF IOCHNM WORD + HRRZ J,(R) ;GET DEV TYPE INDEX + CAIL J,TYIDN ;SKIP IF LESS THAN LEAST TTY INDEX + CAILE J,TYOBN ;SKIP UNLESS .LTEQ. HIGHEST + POPJ P, ;NOT A TTY CHANNEL + TRZ B,#%TICNS#(.BM $TIIDX) + TRZE B,%TICNS ;SKIP IF NOT A CONSOLE TTY + CAIN B,%TINON ;DO NOTHING TO "DISOWNED" TTY CHNLS + POPJ P, + MOVEI J,%TINON ;CHANGE OTHER TTY CHNLS TO DISOWNED + DPB J,[$TIIDX,,(R)] ;CHNLS. + JUMPN T,CPOPJ ;IN NDETAC, TTNTO ALREADY SETZM'D. + SOSLE TTNTO(B) ;DECREMENT OPEN COUNT + POPJ P, + BUG ;SHOULD BE OPEN AT HIGHER LEVELS + +;ROUTINE TO SCAN ALL I/O CHANNEL AND I/O PDL SLOTS OF A PROCEDURE +;R 4.9=1 => REGULAR CHANNEL 4.9=0 => IOPUSHED CHANNEL +CHSCAA: MOVEI R,IOCHNM(A) +CHSCAN: HRLI R,-20 +CHSCA2: XCT @(P) + AOBJN R,CHSCA2 + HRLI R,-+400000 +CHSCA4: XCT @(P) + ADD R,[1,,2] + JUMPG R,CHSCA4 + JRST POPJ1 + ; +;IFPHAK AND IFPLUP TAKE A USER INDEX IN A AND THE ADDRESS OF A ROUTINE +; IN Q. THEY CALL THE ROUTINE FOR THE PROCEDURE AND ALL OF ITS +; INFERIORS BUT IFPHAK ALSO STOPS THE SPECIFIED PROCEDURE AND +; ALL ITS INFERIORS STRINGING THEIR USTP'S INTO THE CURRENT USER'S +; LSWPR. +; +IFPHAK: PUSH P,U + PUSH P,Q + MOVE U,USER ;MADE SURE YOU USE THE RIGHT LSWPR + MOVEI Q,IFSTOP ;SET UP TO STOP + PUSHJ P,IFPLUP + POP P,Q + POP P,U +IFPLUP: PUSH P,E ;SAVE E + PUSH P,H ; " H + SKIPA H,A +IFPLU5: MOVE A,E ;RECURSE + PUSH P,H + PUSH P,Q + PUSHJ P,(Q) ;CALL ROUTINE + POP P,Q + POP P,H + MOVEI E,LUBLK*2 ;INITIALIZE TO INDEX OF JOB AFTER CORE JOB +IFPLU2: SKIPN UNAME(E) + JRST IFPLU3 + HRRZ T,SUPPRO(E) + CAIN T,(A) + JRST IFPLU5 +IFPLU3: ADDI E,LUBLK ;STEP TO NEXT VAR BLOCK + CAMGE E,USRHI ;SKIP IF ALL EXAMINED + JRST IFPLU2 ;NOT ALL, CONTINUE + CAME H,A ;ALL, SKIP IF BACK TO TOP LEVEL + JRST IFPLU4 ;NOT AT TOP LEVEL, POP UP + POP P,H ;RESTORE H + POP P,E ; " E + POPJ P, ;RETURN FROM CALL TO IFPLUP + +IFPLU4: MOVE E,A ;POP + HRRZ A,SUPPRO(A) ;UP + JRST IFPLU3 ;AND CONTINE + +IFSTOP: PUSHJ P,RPCLSR ;STOP ROUTINE WHOSE INDEX IS IN A + HRRZ T,USTP(A) + SOJE T,IFSTP1 + SKIPE LSWB0+1(A) + JRST UPCLSR ;HAVE ALREADY HACKED THIS GUY +IFSTP1: MOVEI T,USTP(A) ;GET LOC OF USTP (WAS AOSED BY RPCLSR) + MOVEI H,LSWB0(A) ;GET LOC OF A LOCKED SWITCH BLOCK OF PROC STOPPED + MOVEM T,(H) ;SET WD1 + PUSH P,U + HRRZ T,U + IDIVI T,LUBLK + POP P,U + HRL T,LSWPR(U) + IORI T,603000 ;SOS WHEN UNLOCKED + MOVSM T,1(H) + MOVEM H,LSWPR(U) ;ADD TO LOCKED SWITCH LIST OF USER + POPJ P, + +UBLAM: SKIPL APRC(U) ;SKIP IF DISOWNED + PUSHJ P,SDTTY ;GET TTY UP TO THIS LEVEL + JFCL +UBLAST: PUSHJ P,IODCL ;CLOSE IO DEVICES ETC +UBLST2: SETZ B, + PUSH P,U ;DO NOT USE THIS ROUTINE FOR CORING UP. + HRRZ Q,U +IFE SWPWSP,[ + CAME Q,BUSR + JRST UBLST4 + SETOM BUSR ;SWAP-BLOCKED NO MORE + SOS NUSWB + MOVSI TT,(SETZ) + ANDCAM TT,USWSCD(U) +];SWPWSP +UBLST4: MOVE U,USER + PUSHJ P,ACRF1 ;CORE DOWN TO NUM OF BLOCKS IN B + BUG + MOVE U,USER ;;CHECK FOR ALLEGED BUG SOMEPLACE IN ACRF1 + SKIPL CORRQ(U) ; + BUG ;;NOT SUPPOSED TO RETURN UNTIL CORE REQUEST SATISFIED + POP P,U + SKIPE NMPGS(U) ; + BUG ;;THUS GUY'S CORE SHOULD BE GONE BY NOW + POPJ P, + + +AEOFC: UMOVE B,(J) + LDB B,[400,,B] ;OPER 50 + ADDI B,IOCHNM(U) + MOVE A,(B) + MOVE A,CLSTB(A) + HLR A,(B) +IFN NUNITS, TLNE A,%CLSDI +.ALSO SKIPA A,UTEOF(A) + MOVEI A,EOFCH + JRST APTUAJ + +;OPER TO REQUEST OR FLUSH RUNNING IN IOT USER MODE +AIOTLS: MOVSI A,400000 + MOVSI B,%PCUIO + XCTR XR,[SKIPGE (J)] + JRST AIOTL1 ;JUMP IF WANT TO ENTER IOTLSR MODE + ANDCAM A,IOTLSR(U) + ANDCAM B,UUOH + POPJ P, + +AIOTL1: SKIPGE IOTLSR(U) + JRST AIOTL2 ;ALREADY IN IOTLSR, JUST TURN THE BIT ON AGAIN FOR HIM + BUG INFO,SIXBIT,UNAME(U),SIXBIT,JNAME(U),[IOTLSR] + MOVEI T,SCRMSG ;WAIT FOR IT TO BE PRINTED (HA HA WHAT ABOUT BUFFERING?) + TDNE T,SUPCOR + PUSHJ P,UFLS + IORM A,IOTLSR(U) +AIOTL2: IORM B,UUOH + JRST CLKONJ + +SUBTTL FILENAME TRANSLATION + +;ROUTINE TO TRANSLATE A FILENAME. +;WANTS DEV, FN1, FN2, SNAME IN A, B, C, D RESP. LEFT-JUST. +;WANTS MODE IN RH OF E. +;RETURNS TRANSLATED NAMES IN SAME PLACE. +TRAN: SKIPN D ;MAYBE DEFAULT THE SNAME. +TRAN6: MOVE D,USYSNM(U) + MOVEM B,EPDLT1(U) + MOVEM C,EPDLT2(U) + MOVEM D,EPDLT3(U) + MOVEM A,EPDLT4(U) + SKIPN TRNCNT ;IF NO TRANSL. ENTRIES IN USE, + JRST POPJ1 ;SHORT CUT. + PUSHJ P,TRANRF ;GET READ ACCESS TO TRANSL LISTS. + LDB I,[100,,E] ;GET INPUT/OUTPUT BIT. + MOVEI H,10 ;MAX. NUM. TRANSLS ALLOWED. +TRAN0: HRROI Q,(U) ;1ST TRY THIS JOB'S TRNLST. + MOVE J,TRNLST(U) + JRST TRAN5 +TRAN1: SKIPGE Q,SUPPRO(Q) ;MOVE UP TREE TO TRNLS1. + SETZ Q, ;AFTER TOP OF TREE, USE SYS. +TRAN2: MOVE J,TRNLS1(Q) ;USE THIS GUY'S TRNLS1. + MOVEI Q,(Q) ;INDICATE THAT FACT IN SIGN. + JRST TRAN5 +TRAN3: CAME B,TRANI1(J) ;ENTRY'S FN1 MATCHES + SKIPN TRANI1(J) ;OR IS NULL? + SKIPA TT,TRANI2(J) ;YES, GET FN2. + JRST TRAN4 ;NO, TRY NEXT ENTRY. + CAME TT,C ;FN2 MTCHES OR NULL. + JUMPN TT,TRAN4 + CAME D,TRANIS(J) ;SNAME ? + SKIPN TRANIS(J) + SKIPA TT,TRANID(J) ;YES, GET DEV. + JRST TRAN4 + CAME A,TT + JUMPN TT,TRAN4 ;TEST DEV. + HLRZ TT,TRANLK(J) ;GET ENTRY'S MODE BITS. + TRNN TT,1(I) ;TRANSLATE OUR MODE? + JRST TRAN4 ;NO. + MOVEM B,EPDLT1(U) + MOVEM C,EPDLT2(U) + MOVEM D,EPDLT3(U) + MOVEM A,EPDLT4(U) +IRPS X,,OD O1 O2 OS + SKIPE TRAN!X(J) + MOVE A+.IRPCN,TRAN!X(J) +TERMIN ;REPLACE NAMES FROM ENTRY. + TRNE TT,400000 ;ATOMIC? + JRST TRANX3 ;YES, EXIT. + SOJG H,TRAN0 ;ELSE RETRANSL. + JRST TRANX2 ;IF TOO MANY TRANSL., DON'T SKIP. + +TRAN4: HRRE J,TRANLK(J) ;CDR DOWN LIST. +TRAN5: JUMPGE J,TRAN3 ;TRY NEXT UNLESS AT END. + JUMPL Q,TRAN2 ;IF DID TRNLST, DO SAME JOB'S TRNLS1. + JUMPN Q,TRAN1 ;ELSE DO SUPPRO'S TRNLS1. +TRANX3: AOS (P) ;EXIT IF DID SYS. +TRANX2: SOS TRNREF ;NO LONGER USING TRANSL. LISTS. + POPJ P, + +TRANRF: AOS TRNREF ;SAY USING TRANSL. LISTS. + SKIPGE TRANSW + POPJ P, ;OK IF NOT BEING CHANGED. + SOS TRNREF ;NOT REFERENCING AFTER ALL. + SKIPL TRANSW ;WAIT TILL FREE. + PUSHJ P,UFLS + JRST TRANRF ;TRY AGAIN. + ;TRANS SYSTEM CALL. +NTRNS: JSP T,DEFARG ;DEFAULT 5 ARGS TO 0. + 5 + XOR E,CTLBTS(U) ;XOR CTL BITS WITH ARG S + PUSHJ P,TRAN ;TRANSLATE NAME. + JRST OPNL3 ;FAIL IF TOO MANY TRANSL. + JRST POPJ1 ;ELSE GIVE BACK TRANSL'D NAMES. + + +DEFARG: CAML W,(T) ;IF NOT ALL SPEC'D, + JRST 1(T) + SETZM A(W) ;DEFAULT ONE AND RETRY. + AOJA W,DEFARG + +;LOCK TRANSW, AND SET UP 1ST ARG FOR NTRNAD, NTRNDL, NTRNCL. +;RH OF A HAS JOB SPEC; CONTROL BIT ARGS XOR'D INTO LH. +;THE 4.8 BIT, IF SET, INDICATES TRNLS1 RATHER THAN TRNLST. +;OTHER LH BITS IGNORED,, NOT CHANGED BY NTRNUI. +;ON RETURN, A'S LH IS UNCHANGED, RH IS SUCH THAT +; TRANLK(A) IS THE ADDR OF THE SPECIFIED TRNLS VAR. +NTRNUI: PUSHJ P,SWTL + TRANSW + TSC A,CTLBTS(U) + MOVEI J,(A) + JSP T,NCRUI2 ;DECODE THE JOB-SPEC. + JRST NTRNU1 ;JOB GUARANTEED WRITEABLE. + JUMPE J,NTRNU1 ;ALLOW JOBS TO MUNG THE SYSTEM TRANSLATION LIST. + JSP T,NCORWR ;ELSE CHECK. + JRST OPNL31 ;NOT WRITEABLE. +NTRNU1: CAIN J,-1 + JRST OPNL34 ;PDP6?? + HRRI A,TRNLST-TRANLK(J) + TLNE A,200000 ;4.8 BIT SAYS WHICH TRNLS TO USE. + ADDI A,TRNLS1-TRNLST + JRST (Q) + +;GET UP TO 4 ARGS INTO D ... D+3, FROM AOBJN PTR IN B. +NTRNGA: MOVSI H,-4 ;UP TO 4 ARGS. + JUMPGE B,NTRNG3 +NTRNG0: UMOVE J,(B) + JUMPGE W,NTRNG2 ;W IS -1 FOR .TRANA, .TRAND; + TRNN H,-1 ;IN THAT CASE LEFT-JUST. DEV. (1ST ARG) + HRLZI J,(J) +NTRNG2: CAMN J,[SIXBIT/*/] + MOVEI J,0 ;REPLACE * BY BLANK. + MOVEM J,D(H) ;STORE AWAY. + AOBJP H,CPOPJ ;DONE AFTER 4TH ARG. + AOBJN B,NTRNG0 ;ELSE GET NEXT. +NTRNG3: SETZM D(H) ;ZERO REMAINING ARGS. + AOBJN H,NTRNG3 + POPJ P, + ;TRANEX CALL -- READ IN A JOB'S TRANSL LIST. +;1ST ARG RH - JOB SPEC. BIT 4.8 - IF SET, TRNLS1 NOT TRNLST. +;2ND ARG AOBJN -> PLACE TO STORE LIST INTO. +;UPDATED AOBJN PTR IS OUTPUT ARG. +;SKIPS IF ENTIRE LIST FIT IN BUFFER. +;EACH ENTRY TAKES 9 WDS OF SPACE: MODE,, IN 1ST, +;INPUT DEV, FN1, FN2, SNAME; THEN OUTPUT DEV, FN1, FN2, SNAME. +NTRNEX: PUSHJ P,TRANRF ;GET READ ACCESS TO TRANSL LISTS. + PUSHJ P,SOSSET ;RELINQUISH IF BLOCKED. + TRNREF + TSC A,CTLBTS(U) + MOVEI J,(A) + JSP T,NCRUI2 ;DECODE THE JOB SPEC. + JFCL ;NOT TRYING TO WRITE. + HRRI A,TRNLST-TRANLK(J) + TLNE A,200000 ;MAKE TRANLK(A) BE TRNLS VAR. + ADDI A,TRNLS1-TRNLST + SUB B,[1,,1] ;SINCE WE AOBJ BEFORE ACTING. +NTRNE1: HRRE T,TRANLK(A) ;AT END -> RETURN SKIPPING. + JUMPL T,NTRNE8 + HLLZ D,TRANLK(T) ;RETURN LH ONLY OF 1ST WD. + TLOA T,-9 +NTRNE2: MOVE D,TRANLK(T) ;ALL OF OTHER 8 WDS. + AOBJP B,[ PUSHJ P,OPNL37 + JRST NTRNE9] + ;FAIL IF NO ROOM. + UMOVEM D,(B) + ADDI T,SIOMT-1 + AOBJN T,NTRNE2 ;STORE ALL 9. + MOVEI A,-9*SIOMT(T) ;GO TO NEXT. + JRST NTRNE1 + +NTRNE8: AOS (P) + AOBJP B,.+1 ;COMPENSATE FOR SUB . + PUSHJ P,LSWPOP ;RELEASE READ ACCESS. +NTRNE9: MOVE A,B + JRST SYSCPT ;RETURN AOBJN PTR. + ;TRANDL CALL -- DELETE ENTRY FROM TRANSL LIST. +;1ST ARG RH JOB SPEC. OF JOB WHICH IS OK TO MODIFY. +;1ST ARG LH MODE BITS AS FOR .TRANAD, ALSO 4.8 BIT SAYS TRNLS1 +; (SPEC'D JOB AND INFS, RATHER THAN JUST SPEC'D JOB) +;2ND ARG AOBJN -> INPUT DEV, FN1, FN2, SNAME. (ONLY DEV NEC.). +;SKIPS IF SOMETHING WAS DELETED. +NTRNDL: JSP Q,NTRNUI ;PROCESS 1ST ARG., LOCK TRANSW. +NTRND: PUSHJ P,NTRNDA ;ACTUALLY DELETE. + JRST OPNL4 ;NOTHING TO DELETE => FILE NOT FOUND + JRST LSWPJ1 ;SKIP IF NTRNDA DID. + +NTRNDA: TLZ A,-1#400003 + PUSHJ P,NTRNGA ;ELSE GET INPUT NAMES. + SKIPGE TRANLK(A) + POPJ P, + HRRZS (P) ;CLEAR SKIP FLAG. + SKIPA T,A +NTRND2: MOVEI T,(H) ;CDR DOWN BOTH PTRS. +NTRND0: HRRE H,TRANLK(T) ;LOOK AT NEXT ENTRY. + JUMPL H,NTRNDX ;EXIT IF END. + CAMN D,TRANID(H) ;ALL 4 INPUT NAMES MUST MATCH. + CAME E,TRANI1(H) + JRST NTRND2 ;ELSE NOT TO BE DELETED. + CAMN TT,TRANI2(H) + CAME I,TRANIS(H) + JRST NTRND2 + HLLZ R,A ;GET MODE FROM ARG. + TLZ R,400000 ;DONT CLOBBER ATOM BIT + ANDCA R,TRANLK(H) ;TURN OFF IN MODE FROM ENTRY. + CAME R,TRANLK(H) ;IF DELETED ONE, CALL WILL SKIP. + HRROS (P) + MOVEM R,TRANLK(H) + TLNE R,3 ;IF NEITHER DIRECTION LEFT, SPLICE OUT. + JRST NTRND2 + SKIPE TRNREF ;WAIT TILL NOONE READING TRANSL LISTS. + PUSHJ P,UFLS + SOS TRNCNT ;ONE LESS ENTRY IN USE. + HRRZ R,TRANFL ;MAKE LINK -> CURRENT FREE LIST. + EXCH R,TRANLK(H) + HRRM R,TRANLK(T) ;REST OF TRNLS INTO PREDECESSOR'S LINK. + HRRZM H,TRANFL ;ADD THIS ONE TO FREE LIST. + JRST NTRND0 + +NTRNDX: HRRES TRANLK(A) ;IN CASE DELETED 1ST ENTRY. + SKIPGE (P) + AOS (P) ;SKIP IF SET FLAG. + POPJ P, + ;TRANAD CALL. -- ADD AN ENTRY TO A TRANSL LIST. +;1ST 2 ARGS AS FOR TRANDL. +;3RD ARG LIKE 2ND BUT GIVES OUTPUT NAMES. +;SKIPS UNLESS ALL ENTRIES WERE IN USE. +NTRNAD: JSP Q,NTRNUI +NTRNA: TLNN A,3 ;IF RELLY NOTHING WOULD BE TRANSL'D, + JRST LSWPJ1 ;DON'T BOTHER ADDING.. + PUSHJ P,NTRNDA ;DELETE ANY EXISTING TRANSL. FOR THESE INPUT NAMES. + JFCL ;IF WERE NONE. + SKIPGE T,TRANFL + JRST OPNL5 ;NO FREE ENTRIES - DIRECTORY FULL. + AOS TRNCNT ;1 MORE ENTRY IN USE. +IRPS X,,ID I1 I2 IS + MOVEM D+.IRPCN,TRAN!X(T) +TERMIN ;PUT INPUT NAMES INTO ENTRY. + MOVE B,C + PUSHJ P,NTRNGA ;GET OUTPUT NAMES. +IRPS X,,OD O1 O2 OS + MOVEM D+.IRPCN,TRAN!X(T) +TERMIN ;STORE OUTPUT NAMES. + MOVE H,TRANLK(A) ;PUT CURRENT TRNLS INTO LINK. + EXCH H,TRANLK(T) + HRREM H,TRANFL ;STORE BACK REST OF FREE LIST. + MOVEM T,TRANLK(A) ;TRNLS NOW STARTS WITH THSI ONE. + HLLM A,TRANLK(T) ;STORE MODE BITS. + JRST LSWPJ1 + ;TRANCL CALL -- RESET A ONE OR BOTH TRANSL LISTS FOR A JOB. +;1ST ARG RH HAS JOB SPEC OF MODIFYABLE JOB. +; BIT 4.8 CLEAR TRNLS1 VAR. (TRANSL FOR THIS JOB & INFS). +; BIT 4.7 CLEAR TRNLST VAR. (TRANSL FOR THIS JOB ONLY). +; ALWAYS SKIPS IF VALID. +NTRNCL: JSP Q,NTRNUI ;RH(A) -> TRNLST OR TRNLS1 VAR. + TLNE A,200000 + SUBI A,TRNLS1-TRNLST ;MAKE -> TRNLST VAR. + SUBI A,TRNLST-TRANLK + JRST NTRNC4 + +NTRNCA: SUBI A,TRNLST-TRANLK ;MAKE HOLD USR IDX. +NTRNC: PUSHJ P,SWTL ;GET WRITE ACCESS. + TRANSW +NTRNC4: AOS (P) + SKIPE TRNREF ;WAIT FOR READ REFS TO FINISH. + PUSHJ P,UFLS + TLNN A,100000 ;IF 4.7, HANDLE TRNLST. + JRST NTRNC0 + HRRE T,TRNLST(A) + SETOM TRNLST(A) ;SET LIST TO NIL. + JUMPGE T,NTRNC1 ;IF WASN'T NIL, FREE ENTRIES ON IT. +NTRNC0: TLZN A,200000 ;MAYBE HANDLE TRNLS1. + JRST LSWPOP + HRRE T,TRNLS1(A) + SETOM TRNLS1(A) + JUMPL T,LSWPOP ;NOTHING TO DO IF ALREADY NIL. +NTRNC1: MOVEI C,(T) ;SAVE START OF LIST. +NTRNC2: SOS TRNCNT ;UPDATE NUM ENTRIES IN USE. + HRRES H,TRANLK(T) + JUMPL H,NTRNC3 ;AT END, SPLICE INTO FREELIST. + MOVEI T,(H) ;ELSE CDR DOWN. + JRST NTRNC2 +NTRNC3: EXCH C,TRANFL + HRRZM C,TRANLK(T) + JRST NTRNC0 ;MAYBE CONSIDER THE OTHER LIST. + ;.TRANA, .TRAND CALLS. +ATRANA: UMOVE E,(B) + JSP T,ATRNDT ;SET UP ARGS FOR NTRNA . + PUSHJ P,SWTL ;GET WRITE ACCESS. + TRANSW + JRST NTRNA + +ATRNDL: +ATRAND: XCTR XR,[SKIPN E,(B)] + JRST ATRND0 ;ZERO UNAME -> TRANCL . + JSP T,ATRNDT ;SET UP ARGS. + PUSHJ P,SWTL ;GET WRITE ACCESS. + TRANSW + JRST NTRND + +ATRND0: JSP T,ATRNDT + TLO A,300000 ;SAY CLEAR BOTH LISTS. + CAMN D,[SIXBIT/*/] + SUBI A,TRNLS1-TRNLST ;NAKE SURE -> TRNLST VAR. + JRST NTRNCA + +ATRNDT: MOVE C,JNAME(U) + MOVEM C,ATRNJN ;WHO THE HELL'S USING THESE? + CAME E,UNAME(U) ;UNAME MUST BE 0 OR THSI JOB'S. + JUMPN E,CPOPJ ;ELSE MAKE UUO FAIL. + MOVNI W,1 ;SIGNAL TO NTRNGA. + MOVEI C,5(B) ;SET UP 2 AOBJN PTRS + MOVEI B,2(B) + HRLI C,-3 ;-> INPUT NAMES (B), OUTPUT NAMES (C). + HRLI B,-3 + XCTR XR,[HLL A,(B)] ;GET MODE BITS. + UMOVE D,-1(B) + JUMPE D,CPOPJ ;JNAME MUSTN'T BE 0. + CAME D,[SIXBIT/*/] ;IF *, USE THIS JOB'S TRNLS1. + JRST ATRND2 + HRRI A,TRNLS1-TRANLK(U) + JRST (T) + +ATRND2: MOVEI H,0 ;ELSE FIND JOB WITH THAT JNAME. + MOVE E,UNAME(U) ;THIS JOB'S UNAME. +ATRND1: CAMN E,UNAME(H) + CAME D,JNAME(H) + JRST ATRND3 ;NOT THE ONE WE'RE LOOKING FOR. + HRRE E,SUPPRO(H) + CAIE U,(E) ;IS THIS OUR INF. + CAIN U,(H) ;IS IT THE CURRENT JOB? + CAIA + POPJ P, ;NO, CAN'T SET ITS TRANSL LIST. + HRRI A,TRNLST-TRANLK(H) + JRST (T) ;OK, SET ITS TRNLST VAR. +ATRND3: ADDI H,LUBLK + CAMGE H,USRHI ;LOOK AT ALL JOBS. + JRST ATRND1 + POPJ P, ;CAN'D TRANAD NON EX JOB. + +SUBTTL JOB, BOJ DEVICE ROUTINES + +EBLK +JBMN==10 ;MAXIMUM NUMBER OF JOBS ON JOB DEVICE + +JBCUI: REPEAT JBMN,-1 ;-1 => CHNL FREE, ELSE (IF JBCG POSITIVE) CREATOR'S USR IDX. +JBCG: BLOCK JBMN ;-1 IF CREATOR GONE AWAY +JBWST: REPEAT JBMN,SNJOB ;CREATED JOB'S WAIT STATUS (CREATED JOB=HANDLER JOB) +%JB==1,,525252 +%JBWIN==400000 ;4.9 => CREATED JOB HAS DONE A SUCCESSFUL JOBRET +%JBREU==200000 ;4.8 => JOB CLOSED AND MADE ITSELF AVAILABLE FOR REUSE +%JBVAL==020000 ;4.5 => VALID BIT (CREATOR CAME IN, NO JOBRET YET) +%JBSTR==010000 ;4.4 => STORED BIT (CREATOR CAME IN, NO JOBGET YET) +%JBUNH==004000 ;4.3 => BOJ BLK UNHANG BIT +%JBSIO==001000 ;4.1 => IF DOING AN IOT, THIS BITS SAYS ITS REALLY A SIOT +%JBLOS==000400 ;3.9 => CREATED JOB WAS CLOSED AND KNOWS IT, SO DON'T REUSE + ;1.1-2.9 => LAST STATUS SET BY BOJ + +JBDEV: BLOCK JBMN ;DEVICE NAME, USER-SETTABLE (MOSTLY FOR PEEK AND WHO LINES) +JBFN1: BLOCK JBMN ;FN1 +JBFN2: BLOCK JBMN ;FN2 +JBSYS: BLOCK JBMN ;SYSNAME +JBOPNM: BLOCK JBMN ;OPEN MODE +JBFNP: BLOCK JBMN ;BP TO ASCIZ FILENAME STRING IN USER ADDRESS SPACE (OR 0 IF NONE). +JBCJUI: BLOCK JBMN ;RH = CREATED JOB'S USER INDEX. + ;LH = -1 IFF CREATED JOB GOING AWAY. JOB MUST EXIST + ;SINCE WHEN IT DIES IT FLUSHES THE JOB CHANNEL + ;AND ITS CREATOR'S CHANNELS. +JBSTS: BLOCK JBMN ;STATUS OF JOB-BOJ INTERACTIONS +;4.9=1 => IMAGE =0 => ASCII +;4.8=1 => BLOCK =0 => UNIT +;4.7=1 => WRITE =0 => READ +;4.6-4.3 => NUMBER OF TIMES TO SKIP +;4.2-3.6 => OPEN LOSS +;3.5-3.2 => # OF ARGS ON LAST .CALL +;1.4 => SYSTEM CALL OTHER THAN THOSE BELOW. +;1.3-1.1 => SYSTEM CALL + ;0 OPEN + ;1 IOT OR SIOT + ;2 MLINK + ;3 RESET + ;4 RCHST + ;5 ACCESS + ;6 FDELE (DELETE OR RENAME) + ;7 FDELE (RENAME WHILE OPEN) + +JBST2: BLOCK JBMN ;SECOND WORD OF JOBGET INFO + ;FOR UNIT IOT, 1 + ;FOR SIOT, THE BYTE COUNT + ;FOR BLOCK IOT, THE BLOCK POINTER + ;NEW FN1 FOR RENAME, MLINK. +JBOFN1: BLOCK JBMN ;FN1 BEFORE LAST TRANS +JBOFN2: BLOCK JBMN ;FN2 "" "" +JBOSYN: BLOCK JBMN ;SYSNAM "" +JBODEV: BLOCK JBMN ;DEV " " +JBNFN2: BLOCK JBMN ;NEW FN2 FOR FDELE. +JBAC7: BLOCK JBMN ;7TH ARG TO .CALL, NEW SNAME FOR MLINK. +JBAC10: BLOCK JBMN ;TABLE FOR .CALL ARG 10, FIRST BP ARG TO SOPEN/RENAME/MLINK/DELETE. +JBAC11: BLOCK JBMN ;TABLE FOR .CALL ARG 11, SECOND BP ARG TO RENAME, MLINK OR RENMWO. + +JBACTB: JBST2(H) ;TABLE OF POINTERS TO .CALL ARG TABLES + JBOFN1(H) + JBOFN2(H) + JBOSYN(H) + JBODEV(H) + JBNFN2(H) + JBAC7(H) + JBAC10(H) + JBAC11(H) + +JBIOCJ: BLOCK JBMN ;IO CHNL ERROR WORD. 4.9 => IOCER ON NEXT JOB IOT + ;RH = IOCER TYPE + +JBSW: -1 ;LOCK ON ASSIGNMENT OF INDEX IN ABOVE TABLES + 0 +BBLK + +;OPEN ON BOJ: DEVICE + +;3.5 = 1 => UNHANG ON BLK IOT AFTER EACH XFER OF MAXIMAL SIZE +BOJO: JUMPN W,OPNL12 ;NO SUCH MODE + SKIPGE E,JBI(U) ;JOB CHANNEL INDEX + JRST [ MOVE E,OPTION(U) ;IF THIS JOB ISN'T A JOB DEVICE, + TLNN E,%OPOJB ;IF IT'S EXPECTING TO BE AN OJB DEVICE, OK. + JRST OPNL10 ;OTHERWISE IT CAN'T WIN. + SKIPGE JBI(U) ;IF IT CAN WIN, WAIT TILL IT HAS. + PUSHJ P,UFLS + JRST BOJO] ;THEN TRY AGAIN. + CAIL E,JBMN + BUG ;JOB CHANNEL INDEX TOO BIG + CAME U,JBCJUI(E) + BUG + HRLZ A,E + HLRZS C + MOVSI TT,%JBUNH + TRNE C,20 + IORM TT,JBWST(E) + JSP Q,OPSLC7 + BDUAI,,BDUAO + BDBI,,BDBO + BDUII,,BDUIO + BDBI,,BDBO + +;OPEN ON JOB: DEVICE +;MODE BITS: +;3.1-3.3 => IMAGE/ASCII, BLOCK/UNIT, OUTPUT/INPUT +;A,B HAVE FILENAMES, RH(C) HAS DEVICE (JOB OR OJB) +;RH(D) AND LH(C) BOTH HAVE OPEN-MODE. + +JOBO: PUSHJ P,FLDRCK + JRST JOBO3 + JRST OPNL11 ;ILLEGAL FILE NAME +JOBO3: CAMN A,[SIXBIT /M.F.D./] + CAME B,[SIXBIT /(FILE)/] + JRST JOBO2 + JRST OPNL11 ;ILLEGAL FILE NAME +JOBO2: MOVEI J,0 ;SET J TO JOBGET "COMMAND" NUMBER + CAIN W,2 + MOVEI J,2 ;MLINK, MOSTLY JUST LIKE FDELE, BUT SEE JOBOF3 + CAIN W,4 + MOVEI J,6 ;FDELE + MOVNI E,1 + MOVSI Q,-JBMN + PUSHJ P,SWTL ;LOCK JOB CHNL ASSIGN SWITCH + JBSW +JOBO5: SKIPGE TT,JBCUI(Q) ;SKIP IF NOT FREE + JRST JOBO4 + MOVE T,UUOH + TLNN T,%PCFPD + JRST JOBORU ;JUMP IF THIS IS FIRST ATTEMPT TO OPEN + HRRZ H,C + CAIN H,'OJB + JRST JOBO6 + SKIPGE JBCG(Q) ;LOOK FOR CHANNEL ON WHICH THIS USER + CAIE TT,(U) ;PREVIOUSLY ATTEMPTED TO OPEN, BUT PCLSRED + JRST JOBO6 + MOVE T,EPDLT1(U) + MOVE TT,EPDLT2(U) + CAMN T,JBFN1(Q) + CAME TT,JBFN2(Q) + JRST JOBO6 ;NOT OPENING SAME FILE + MOVE TT,EPDLT4(U) + MOVE T,EPDLT3(U) + CAMN TT,JBDEV(Q) + CAME T,JBSYS(Q) + JRST JOBO6 ;NOT FOR SAME FILE + CONO PI,CLKOFF + HLRZ H,C + HRRZ T,JBSTS(Q) + CAIN T,(J) + CAME H,JBOPNM(Q) + JRST JOBO6 ;NOT FOR SAME OPEN TYPE AND MODE + MOVE TT,JBWST(Q) + TLNE TT,%JBLOS+%JBWIN+%JBREU + JRST JOBO6 ;HANDLER JOB NOT IN CORRECT STATE + HRRZ E,Q ;REUSE SAME HANDLER JOB AS IN PREVIOUS ATTEMPT TO OPEN + SETZM JBCG(E) ;I'M BACK + PUSHJ P,LSWPOP ;FREE JBSW + TLO TT,%JBVAL + MOVEM TT,JBWST(E) ;RE-GIVE OPEN COMMAND STILL SITTING IN JBSTS ETC. + HRLI E,400000 ;OPEN-TYPE WAIT + PUSHJ P,JBWT2 ;WAIT FOR HANDLER JOB TO PROCESS IT + JRST JOBO8 ;FINISH OFF THEN OPEN + +;FIRST ATTEMPT TO OPEN, CHECK FOR REUSEABLE HANDLER JOBS BEFORE CREATING NEW +JOBORU: CONO PI,CLKOFF + MOVE TT,JBWST(Q) + SKIPGE JBCG(Q) + TLZN TT,%JBREU + JRST JOBO6 ;IN USE ALREADY OR NOT WILLING TO BE REUSED + MOVE T,EPDLT4(U) + CAMN T,JBODEV(Q) + JRST JOBOR1 ;IF SAME SIMULATED DEVICE, OK TO SIEZE + CAMN A,JBOFN1(Q) + CAME B,JBOFN2(Q) + JRST JOBO6 ;DIFFERENT HANDLER NAME + MOVE T,USYSN1(U) + CAME T,JBOSYN(Q) + JRST JOBO6 ;DIFFERENT HANDLER NAME +JOBOR1: MOVEM TT,JBWST(Q) ;THIS ONE OK, SIEZE IT + HRRZ E,Q + MOVEM U,JBCUI(E) + HLRZM C,JBOPNM(E) + SETZM JBCG(E) + SETZM JBIOCJ(E) + PUSHJ P,LSWPOP ;FREE JBSW + JRST JOBO7 + +JOBO4: HRRZ E,Q ;REMEMBER FREE JOB CHNL IN CASE NEEDED +JOBO6: CONO PI,CLKON + AOBJN Q,JOBO5 ;SCAN REST OF JOB CHANNELS + JUMPL E,OPNL6 ;DEVICE FULL + MOVEM U,JBCUI(E);STORE CREATOR'S USER INDEX + PUSHJ P,LSWPOP ;FREE JOBSW + PUSHJ P,STMSET ;SETOM JBCUI(E) ON LOSSAGE + JBCUI(E) + SETZM JBDEV(E) + SETZM JBFNP(E) + HLRZM C,JBOPNM(E) + SETZM JBCG(E) + SETZM JBIOCJ(E) + MOVEI T,SNJOB ;INITIALIZE STATUS + MOVEM T,JBWST(E) + PUSH P,R + PUSH P,U + PUSH P,J + PUSH P,D + PUSH P,E + PUSH P,A + PUSH P,B + ANDI C,-1 ;FOR OJB DEVICE, LOOK FOR EXISTING JOB. + CAIN C,'OJB + JRST JOBO6B + MOVE A,UNAME(U) ;FOR JOB DEVICE, CREATE NEW JOB. + IDIVI E,10. + MOVEI B,'0(E) + LSH B,6 + ADDI B,'0(TT) + ADD B,[SIXBIT /JOB./] ;CREATE JNAME = 'JOB.MN' + MOVE C,[7,,(SIXBIT /USR/)] + MOVE D,[SETZ 3] + PUSHJ P,USROJ ;GENERATE USER(CAN ONLY PCLSR BEFORE CREATING INFERIOR) + JRST POP7J ;USER OPEN FAILED, MUST HAVE GONE TO OPNL ALREADY + CONO PI,CLKOFF + POP P,B + POP P,A + POP P,E + SETOM SUPPRO(TT) + MOVE T,[JBSTCD,,AC0S] + ADDI T,(TT) + BLT T,AC17S(TT) + HRLZI T,%PCUSR + MOVEM T,UPC(TT) + MOVEM A,AC0S+10(TT) + MOVEM B,AC0S+11(TT) + MOVE T,USYSN1(U) + MOVEM T,USYSNM(TT) ;SET CREATED JOB'S SYS NAME TO OURS + SETZM USTP(TT) ;START JOB AS SOON AS CLK BACK ON + JRST JOBO6C + +;OJB: DEVICE, LOOK FOR JOB WHOSE NAMES ARE THE FILENAMES SPECIFIED IN THE OJB OPEN. +JOBO6B: MOVE C,[7+UBPFJ,,'USR] ;DON'T EVER CREATE JOB FOR OJB. + MOVE D,[SETZ 3+UBPFJ_<-1>] + PUSHJ P,USROOJ + JRST POP7J + SUB P,[2,,2] + POP P,E +;TT HAS USER IDX OF JOB TO BE USED; CAN'T PCLSR AFTER THIS POINT. +JOBO6C: PUSHJ P,LSWDEL ;SETOM JBCUI(E) + POP P,D + POP P,J + POP P,U + POP P,R + HRRZM TT,JBCJUI(E) + MOVEM E,JBI(TT) +JOBO7: CONO PI,CLKOFF + MOVE TT,EPDLT1(U) + MOVEM TT,JBOFN1(E) + MOVEM TT,JBFN1(E) + MOVE TT,EPDLT2(U) + MOVEM TT,JBOFN2(E) + MOVEM TT,JBFN2(E) + MOVE TT,EPDLT3(U) + MOVEM TT,JBOSYN(E) + MOVEM TT,JBSYS(E) + MOVE TT,EPDLT4(U) + MOVEM TT,JBODEV(E) + MOVEM TT,JBDEV(E) + MOVE TT,EPDL(U) + MOVEM TT,JBAC10(E) + MOVE TT,EPDL3(U) + MOVEM TT,JBAC11(E) + JUMPN J,[PUSHJ P,JFDEL5 ;DELETE/RENAME/MLINK + JRST JOBO9] + LDB TT,[000300,,JBOPNM(E)] + ROT TT,-3 + MOVEM TT,JBSTS(E) + HRRZ C,JBOPNM(E) ;GET ALL OF OPEN MODE + MOVEM C,JBNFN2(E) ;GIVE IT +JOBO9: PUSHJ P,JBWT1 ;STORE STUFF AND HANG +JOBO8: LDB TT,[350400,,JBSTS(E)] + JUMPE TT,JOBOPL ;OPEN LOST + LDB C,[000400,,JBSTS(E)] + JUMPN C,[ SETOM JBCG(E) ;DELETE/RENAME/MLINK + JRST POPJ1 ] + MOVE C,JBOPNM(E) + SETZM IOCHST-IOCHNM(R) + HRLZ A,E + JSP Q,OPSLC7 + JDUAI,,JDUAO + JDBI,,JDBO + JDUII,,JDUIO + JDBI,,JDBO + +JOBOPL: LDB C,[270600,,JBSTS(E)] + SETOM JBCG(E) + SKIPE C + CAILE C,NOPNLS + MOVEI C,22 + JRST OPNL1-1(C) + +;RENAME WHILE OPEN ON JOB CHNL +JFDEL4: HLRZ E,(TT) ;JOB CHNL INDEX + MOVEI J,7 + PUSHJ P,JFDEL5 ;DO "FDELE" + MOVE TT,EPDL3(U) ;PASS ALONG THE BP ARG IF THERE WAS ONE. + MOVEM TT,JBAC11(E) + SETZM JBAC10(E) + JRST AIOCA1 ;GET RESULTS + +;FDELE/RENMWO/MLINK ON JOB CHANNEL +JFDEL5: MOVEM J,JBSTS(E) + MOVE TT,SRN3(U) ;REMEMBER NAMES TO RENAME AS + MOVEM TT,JBST2(E) ;FOR JOBGET TO RETURN. + MOVE TT,SRN4(U) + MOVEM TT,JBNFN2(E) + MOVE TT,SRN5(U) ;IN CASE THIS IS MLINK, MAKE SURE THE "TO" SNAME + MOVEM TT,JBAC7(E) ;IS GIVEN TO JOBGET. + CONO PI,CLKOFF + POPJ P, + +;GIVE AN INTERRUPT TO THE JOB DEVICE HANDLER. +;JOB CHNL INDEX IN E, CLOBBERS TT,J,Q,H +;CALL WITH CLKOFF + +JBINT: HRRZ TT,JBCJUI(E) + MOVEI J,IOCHNM(TT) + HRLI J,-20 + MOVSI H,%CLSBJ +JBINT1: MOVE Q,(J) + TDNN H,CLSTB(Q) ;SKIP IF BOJ +JBINT2: AOBJN J,JBINT1 + JUMPGE J,CPOPJ + SUBI J,IOCHNM(TT) + MOVE Q,CHNBIT(J) + IORM Q,IFPIR(TT) + ADDI J,IOCHNM(TT) + JRST JBINT2 + +;THIS IS THE CODE PUT IN THE ACS TO LOAD IN THE JOB DEVICE HANDLER + +JBSTCD: .OPEN 1,7 ;0 + .LOGOUT + .CALL 12 + .LOGOUT + .IOT 1,2 + .CLOSE 1, + JRST (2) + 4,,(SIXBIT /DSK/) ;7 + 0 ;10 FN1 + 0 ;11 FN2 + SETZ ;12 + SIXBIT /LOAD/ + 16 + SETZ 17 + -1 ;16 (LOAD INTO SELF) + 1 ;17 + +;HAND THE JOB DEVICE HANDLER A SYSTEM CALL AND WAIT FOR IT TO BE HANDLED. +;CALL WITH CLOCK OFF, JOB CHNL IN E +JBWT1: TLOA E,400000 ;OPEN/FDELE/MLINK, CLOSE CHANNEL IF PCLSR +JBWT: TLZ E,400000 ;NORMAL ENTRY POINT, DON'T CLOSE IF PCLSR + TLZA E,200000 +JBWTI: HRLI E,200000 ;ENTER HERE TO INHIBIT SETTING %PCFPD IF PCLSR + MOVSI TT,%JBVAL+%JBSTR + IORM TT,JBWST(E) ;TURN ON VALID AND STORED +JBWT2: PUSHJ P,JBINT ;GIVE INT + PUSHJ P,LOSSET + JBPCL ;CLEAR VALID AND STORED IF PCLSR + MOVE T,E ;CAUSES EPDL2 TO HAVE JOB INDEX + PCLT +JBFLS: SKIP JBFLS + PUSHJ P,UFLS ;AWAIT RESULTS FROM HANDLER JOB + MOVSI TT,%PCFPD + ANDCAM TT,UUOH ;NOW WE KNOW WE'LL RETURN TO USER WITHOUT PCLSRING FIRST + JRST LSWDEL + +JBPCL: MOVE A,AC0S+E(U) ;HERE IF PCLSR OUT + SKIPL JBCJUI(A) ;UNLESS HANDLER GOING AWAY + TLNE A,200000 ;OR THIS SYSTEM CALL DOESN'T WANT IT, + JRST JBPCL1 + MOVSI T,%PCFPD ;SET FIRST PART DONE FLAG + IORM T,UPC(U) ;NOTE PCLSR HAS ALREADY MOVED UUOH INTO UPC +JBPCL1: MOVSI T,%JBVAL+%JBSTR ;NOT VALID, NOT STORED + ANDCAM T,JBWST(A) + JUMPGE A,CPOPJ + SETOM JBCG(A) ;SAY THE CREATOR HAS CLOSED IT +IRPS X,,E TT J Q H + PUSH P,X +TERMIN + MOVE E,A ;AND GIVE THE HANDLER AN INTERRUPT + PUSHJ P,JBINT +IRPS X,,H Q J TT E + POP P,X +TERMIN + POPJ P, + +;JOB DEVICE BLOCK MODE IOT EITHER DIRECTION +JBBI: XCTR XRW,[MOVES D,(C)] ;REFERENCE POINTER + LDB B,[410300,,D] + CAIGE B,3 + POPJ P, + MOVEM D,JBST2(A) + MOVE B,C + HRRZ T,D ;-> FIRST WORD TO TRANSFER + HLROS D ;MINUS WORD COUNT + IORI D,700000 ;FLUSH CHAR COUNT + SUBM T,D ;D -> LAST WORD + 1 TO TRANSFER + JRST JBIPG ;SWAP IN BUFFER THEN DO IOT + +;JOB DEVICE UNIT MODE IOT EITHER DIRECTION + JRST JBSI ;SIOT +JBUI: MOVSI T,%JBSIOT + ANDCAM T,JBWST(A) + MOVEI T,1 + MOVEM T,JBST2(A) + UMOVE W,(C) ;FOR UNIT OUTPUT +JBIOT1: HRRZ TT,JBOPNM(A) + ROT TT,-3 ;MODE + HRRI TT,1 ;IOT CMD + HRRZ E,A ;JOB CHNL INDEX + MOVEM TT,JBSTS(E) + MOVEM C,SRN3(U) ;MAY BE ADDRESS OF BLOCK IOT POINTER + CONO PI,CLKOFF + SKIPL TT,JBIOCJ(E) + JRST JBWTI ;GO SIGNAL HANDLER JOB + SETZM JBIOCJ(E) ;TAKE IOC ERROR INSTEAD + JRST IOCERF-MIOTER(TT) + +;JOB DEVICE SIOT EITHER DIRECTION +JBSI: AOS (P) ;SIOT SHOULD SKIP RETURN + MOVSI T,%JBSIOT + IORM T,JBWST(A) + XCTR XRW,[MOVES T,(B)] ;BYTE PNTR ARG + LDB E,[300600,,T] ;BYTE SIZE + MOVEI D,36. + IDIVM D,E ;E := # BYTES PER WORD + XCTR XRW,[MOVES D,(C)] ;BYTE COUNT ARG + MOVEM D,JBST2(A) + IDIV D,E ;D := WORD COUNT, E := EXCESS BYTES + IBP T ;-> FIRST WORD TO TRANSFER + ADD D,T + SOJLE E,JBIPG +JBSI1: IBP D + SOJG E,JBSI1 +JBIPG: HRRZS D ;-> LAST WORD TO TRANSFER + 1 + ANDI T,-2000 ;-> FIRST PAGE INVOLVED IN TRANSFER + LDB E,[.BP .UII#.UIO,JBOPNM(A)] ;0 INPUT 1 OUTPUT +JBIPG1: SKIPE E ;SWAP IN THE NECESSARY PAGES + XCTR XR,[SKIPA 20(T)] + XCTR XRW,[MOVES 20(T)] + ADDI T,2000 + CAMGE T,D + JRST JBIPG1 + JRST JBIOT1 + +;FLSINS ROUTINE TO WAIT FOR CREATOR TO BE HUNG AT JBFLS +;4.9 OF SRN3 = 1 => WAIT FOR WRITE 0 => READ +;1.1-1.4 => CODE OF UUO TO WAIT FOR + +BJWAIT: SKIPE B,FLSINS(T) + CAME B,JBFLS + POPJ P, ;NOT HUNG AT JBFLS + HRRZ B,EPDL2(T) ;JOB INDEX THAT CREATOR IS HACKING + HLRZ E,T ;JOB INDEX OF BOJ USER + CAME B,E + POPJ P, ;CREATOR HACKING JOB DEVICE ON SOME OTHER CHANNEL + MOVE TT,JBSTS(B) + LSH TT,2 ;4.9 => READ/WRITE BIT NOW + EQV TT,SRN3(U) ;4.9 OF SRN3 => WHAT TO LOOK FOR + JUMPGE TT,CPOPJ ;DOESN'T MATCH + MOVE TT,JBSTS(B) ;INSN CREATOR IS DOING + XOR TT,SRN3(U) ;INSN LOOKING FOR + TRNN TT,17 + AOS (P) ;THEY MATCH, AWAKEN BOJ JOB + POPJ P, + +;BOJ DEVICE UNIT MODE OUTPUT +BJUO: SKIPGE C + SKIPA H,(C) + UMOVE H,(C) + MOVEI B,1 ;WAIT FOR INPUT IOT + MOVEM B,SRN3(U) + HRLZ T,A ;JOB INDEX + HRR T,JBCUI(A) ;CREATOR'S USER INDEX + PUSHJ P,CWAIT ;WAIT FOR CREATOR TO BE IN IOT, RETURN WITH CLK OFF + PUSHJ P,BJWAIT + PUSHJ P,BJUO1 + JRST CLKONJ + +BJUO1: MOVE TT,JBSTS(A) + TLNE TT,200000 + JRST BJUOB ;BLOCK MODE CREATOR IOT + LDB D,[.BP (%JBSIOT),JBWST(A)] + JUMPN D,BJUOS ;CREATOR SIOT + MOVEM H,AC0S+W(T) +BJIUNH: MOVSI D,%JBWIN + IORM D,JBWST(A) ;SET SUCCESSFUL JOBRET BIT + MOVSI D,%JBVAL+%JBSTR + ANDCAM D,JBWST(A) + MOVEI D,0 + DPB D,[350400,,JBSTS(A)] ;DON'T SKIP + EXCH D,FLSINS(T) ;RESTART CREATOR + CONSO PI,1 + CAME D,JBFLS + BUG ;HE WASNT WHERE HE BELONGED + POPJ P, ;NEED NOT CLKON, CALLER WILL TURN IT ON + +;BOJ UNIT OUTPUT TO JOB SIOT +BJUOS: PUSHJ P,BJBINI + XCTRI XBYTE,[IDPB H,(B)] + SKIPA C,AC0S+C(T) + BUG + XCTR XRW,[SOSG (C)] + JRST BJIUNP + JRST PLDZ + +BJBINI: HRLI T,%UMALL + MOVE J,T + PUSHJ P,PLD1 + MOVE B,AC0S+B(T) + XCTRI XRW,[MOVE D,(B)] + POPJ P, + BUG + +;BOJ UNIT OUTPUT TO JOB BLOCK IOT +BJUOB: PUSHJ P,BJBINI + SKIPL JBSTS(A) + JRST BJUOBA ;ASCII + XCTRI XW,[MOVEM H,(D)] + CAIA + BUG + ADD D,[1,,1] + XCTRI XW,[MOVEM D,(B)] + CAIA + BUG + JUMPGE D,BJIUNP + JRST PLDZ + +;BOJ UNIT OUTPUT TO JOB BLOCK IOT, ASCII MODE +BJUOBA: LDB E,[410300,,D] ;CHAR COUNT + CAIGE E,3 + JRST BJIUNP + XCTRI XR,[MOVE W,(D)] + SKIPA E,BTOCHT-3(E) + BUG + IDPB H,E + XCTRI XW,[MOVEM W,(D)] + CAIA + BUG + ADD D,[700000,,] + TLNN D,500000 + ADD D,[500001,,1] + XCTRI XW,[MOVEM D,(B)] + CAIA + BUG + TLNE D,700000 + JRST PLDZ +BJIUNP: PUSHJ P,BJIUNH ;UNHANG CREATOR + JRST PLDZ + +;BOJ DEVICE BLOCK OUTPUT +BJBO: SKIPGE JBCG(A) + POPJ P, + XCTR XRW,[MOVES D,(C)] ;D GETS IOT POINTER + LDB E,[410300,,D] + CAIGE E,3 + POPJ P, + HLRO B,D + IORI B,700000 ;FLUSH CHAR CNT + HRRZ T,D + SUB T,B + CAILE T,-1 + JRST IOADC ;DON'T WRAP AROUND (WHY NOT?) + UMOVE H,(D) ;H GETS FIRST WORD + MOVEI B,1 + PUSHJ P,BJBWT ;WAIT FOR JOB INPUT IOT, COME BACK WITH CLK OFF. + JRST CLKONJ ;UNHANG + MOVEI I,1 ;FOR BJBB + MOVE TT,JBSTS(A) + TLNE TT,200000 + JRST BJBB ;CREATOR IOT IS IN BLOCK MODE + JUMPGE TT,BJBOA ;CREATOR IOT IS ASCII + ADD D,[1,,1] +BJBO1: PUSH P,C + PUSH P,D + PUSHJ P,BJUO1 + POP P,D + POP P,C + XCTRI XW,[MOVEM D,(C)] + SKIPA T,IOTTB+BDBO + BUG +BJBEX: TLNN D,700000 + JRST CLKONJ ;BOJ BLOCK POINTER EXHAUSTED + MOVE E,JBWST(A) + CONO PI,CLKON + TLNN E,%JBVAL ;SKIP IF JOB IOT STILL WAITING FOR MORE + TLNN E,%JBUNH + JRST (T) ;TRANSFER MORE + POPJ P, ;UNHANG BOJ IOT PREMATURELY + +;BOJ BLOCK ASCII OUTPUT FETCH CHARACTER +BJBOA: MOVE E,BTOCHT-3(E) + MOVE W,H + ILDB H,E + ADD D,[700000,,] + TLNN D,500000 + ADD D,[500001,,1] + JRST BJBO1 + +;BOJ BLOCK IOT WAIT. AWAITS JOB IOT, UNLESS UNHANGING. +;TURNS CLKOFF. SKIPS UNLESS SUPPOSED TO UNHANG. +BJBWT: MOVEM B,SRN3(U) ;SAVE WHAT JOB UUO TO WAIT FOR + HRLZ T,A ;SET UP ARG FOR BJWAIT FLSINS + HRR T,JBCUI(A) + MOVE TT,JBWST(A) ;CHECK FOR DON'T HANG MODE + TLNE TT,%JBUNH + JRST BJBWT1 + PUSHJ P,CWAIT ;WAIT FOR JOB IOT + PUSHJ P,BJWAIT + JRST POPJ1 + +BJBWT1: CONO PI,CLKOFF ;IF NOT ALREADY IN JOB IOT, DON'T WAIT + JRST BJWAIT ;TEST CREATOR STATUS, POPJ OR POPJ1 + +;BOJ DEVICE UNIT MODE INPUT +BJUI: MOVE B,[SETZ 1] ;WAIT FOR OUTPUT IOT + MOVEM B,SRN3(U) + HRLZ T,A ;JOB INDEX + HRR T,JBCUI(A) ;CREATOR'S USER INDEX + PUSHJ P,CWAIT ;WAIT FOR CREATOR TO IOT, RETURN WITH CLKOFF + PUSHJ P,BJWAIT + PUSHJ P,BJUI1 + JRST CLKONJ + +BJUI1: MOVE TT,JBSTS(A) + TLNE TT,200000 + JRST BJUIB ;BLOCK MODE CREATOR IOT + LDB D,[.BP (%JBSIOT),JBWST(A)] + JUMPN D,BJUIS + MOVE W,AC0S+W(T) + JRST BJIUNH ;SUCCESSFUL + +;BOJ UNIT INPUT FROM JOB SIOT +BJUIS: PUSHJ P,BJBINI + XCTRI XBYTE,[ILDB W,(B)] + SKIPA C,AC0S+C(T) + BUG + XCTR XRW,[SOSG (C)] + JRST BJIUNP + JRST PLDZ + +;BOJ UNIT INPUT FROM JOB BLOCK IOT +BJUIB: PUSHJ P,BJBINI + SKIPL JBSTS(A) + JRST BJUIBA + XCTRI XR,[MOVE W,(D)] + CAIA + BUG + ADD D,[1,,1] + XCTRI XW,[MOVEM D,(B)] + CAIA + BUG + JUMPGE D,BJIUNP + JRST PLDZ + +;BOJ UNIT INPUT FROM JOB BLOCK IOT, ASCII MODE +BJUIBA: LDB E,[410300,,D] ;CHAR COUNT + MOVEI W,0 + CAIGE E,3 + JRST BJIUNP + XCTRI XR,[MOVE W,(B)] + SKIPA E,BTOCHT-3(E) + BUG + ILDB W,E + ADD D,[700000,,] + TLNN D,500000 + ADD D,[500001,,1] + XCTRI XW,[MOVEM D,(B)] + CAIA + BUG + TLNN D,700000 + JRST BJIUNP + JRST PLDZ + +;BOJ DEVICE BLOCK MODE INPUT +BJBI: SKIPGE JBCG(A) + POPJ P, ;EOF + XCTR XRW,[MOVES D,(C)] ;D GETS IOT POINTER + LDB B,[410300,,D] + CAIGE B,3 + POPJ P, + HLRO E,D + IORI E,700000 ;FLUSH CHAR CNT + HRRZ T,D + SUB T,E + CAILE T,-1 + JRST IOADC ;DON'T WRAP AROUND + MOVE B,[SETZ 1] + PUSHJ P,BJBWT ;WAIT FOR JOB OUTPUT IOT, COME BACK WITH CLK OFF + JRST CLKONJ ;UNHANG + MOVEI I,0 ;FOR BJBB + MOVE TT,JBSTS(A) + TLNE TT,200000 + JRST BJBB ;CREATOR IOT IS IN BLOCK MODE + PUSH P,C + PUSH P,D + PUSHJ P,BJUI1 ;GET DATA OUT OF CREATOR UNIT MODE IOT + POP P,D + POP P,C + MOVE H,W + MOVEI T,BJBI + JUMPGE TT,BJBIA ;ASCII + XCTRI XW,[MOVEM H,(D)] + CAIA + BUG + ADD D,[1,,1] + JRST BJBIX + +;BOJ BLOCK ASCII INPUT STORE CHAR +BJBIA: LDB E,[410300,,D] + CAIGE E,3 + JRST CLKONJ + XCTRI XR,[MOVE W,(D)] + SKIPA E,BTOCHT-3(E) + BUG + IDPB H,E + XCTRI XW,[MOVEM W,(D)] + CAIA + BUG + ADD D,[700000,,] + TLNN D,500000 + ADD D,[500001,,1] +BJBIX: MOVEI T,BJBI + XCTRI XW,[MOVEM D,(C)] + JRST BJBEX + BUG + +BJOV: BJBI + BJBO + +;BOJ BLOCK IOT TO/FROM JOB BLOCK IOT +BJBB: MOVE J,T + HRLI J,%UMALL ;UMAPS FOR PURELY CREATOR IOT + MOVEM J,SRN4(U) +BJBBL: MOVE J,SRN4(U) + PUSHJ P,PLD1 + MOVE E,SRN3(T) + XCTRI XRW,[MOVES H,(E)] + CAIA ;H HAS JOB BLOCK IOT POINTER + BUG + PUSHJ P,PLDZ + XCTRI XRW,[MOVES D,(C)] + CAIA ;D HAS BOJ BLOCK IOT POINTER + BUG + JUMPGE H,[PUSHJ P,BJIUNH + MOVE T,BJOV(I) + JRST BJBEX] + JUMPGE D,CLKONJ + HLRE B,H + CAML D,H + HLRE B,D ;CHOOSE SMALLER OF TWO BLOCK SIZES + MOVNS B ;COUNT TO BE XFERRED + HRLZ E,H ;JOB ADDRESS + HRR E,D ;JOB,,BOJ (FROM,,TO FOR BOJ INPUT) + HLRZ Q,E ;JOB ADDRESS + CAIGE Q,20 + JRST BJBB1 ;JOB ADDR IS AN AC + HRRZ J,T ;SET UP UMAPS (JOB USER INDEX IN RH) + TRZE E,400000 + TLOA J,%UMMPL ;TO HI PG, HACK OUR LO PAGE + TLO J,%UMMPU ;TO LO PG, HACK OUR HI PAGE + TLZE E,400000 + TLOA J,%UMLTU ;TO POINT TO HIS UPPER + TLO J,%UMUTL ;TO POINT TO HIS LOWER + TLNN J,%UMMPU+%UMUTL ;MAPPING HIS UPPER FROM OUR LOWER? + JRST BJBB3 ;YES. MAKE SURE NOT SCREWED BY AC PNTR +BJBB3A: PUSHJ P,PLD1 + TRZ Q,400000 + MOVNS Q ;LIMIT SIZE OF XFER TO MIN OF + ADDI Q,400000 ;DIST OF TO ADR FROM SEG BOUNDARY + CAMLE B,Q ;AND DIST OF FROM ADR FROM SEG BOUNDARY + HRRZ B,Q + MOVNI Q,(E) ; - BOJ ADDR + ADDI Q,400000 + CAMLE B,Q + HRRZ B,Q + TLNN J,%UMMPL ;BUGGER ADDRESSES SO RIGHT DBRS WILL BE USED + TLOA E,400000 ;SET JOB ADDR TO HI SEG + TRO E,400000 ;SET BOJ ADDR TO HI SEG + SKIPE I + MOVSS E ;XFER OTHER DIRECTION + MOVE Q,E ;SAVE COPY OF BLT POINTER + ADDI B,(E) ;GET LA + 1 + XCTRI XBRW,[BLT E,-1(B)] ;XFER DATA + HRRZS E,B ;NO FAULT. SIMULATE STORE BACK OF POINTER (CAN BE 1,,0) + PUSH P,J + PUSHJ P,PLDZ + SUBM E,Q +BJBB2: HRLS Q ;NUMBER OF WORDS ACTUALLY XFERRED IN BOTH HALVES + XCTRI XRW,[ADDM Q,(C)] ;UPDATE BOJ BLK PNTR + JRST .+2 + BUG + MOVE J,SRN4(U) + PUSHJ P,PLD1 ;MAP TO CREATOR + POP P,J + MOVE W,SRN3(T) + XCTRI XRW,[ADDM Q,(W)] ;UPDATE JOB BLK PNTR + JRST .+2 + BUG + CAIN B,(E) + JRST BJBBL ;NO FAULT, LOOP BACK + PUSHJ P,PLD1 ;RESTORE TO FROB AT TIME OF FAULT +BJBBF: PUSHJ P,TPFLT ;TAKE FAULT (TURNS CLK ON) + PUSHJ P,MPLDZ ;RESTORE NORMAL MAP + JRST @BJOV(I) ;RESTART THE IOT + +;JOB ADDR IS AN AC +BJBB1: ADDI Q,UUOACS(T) + JUMPN I,BJBB1A + MOVE B,(Q) ;READ JOB WORD +BJBB3C: XCTRI XW,[MOVEM B,(E)] + JRST .+2 + JRST BJBBF +BJBB2A: MOVEI Q,1 ;1 WORD XFERRED + HRRZ B,E ;FAKE OUT FAULT TEST + PUSH P,J + JRST BJBB2 + +BJBB1A: XCTRI XR,[MOVE B,(E)] + JRST .+2 + JRST BJBBF + MOVEM B,(Q) + JRST BJBB2A + +BJBB3: TLNE E,777760 ;SKIP ON XFERRING FROM AC AREA, HI TO HI + JRST BJBB3A ;NO. OK TO DO BLT + JUMPN I,BJBB3B + HRLI J,%UMALL ;HACK OUR HI TO POINT TO HIS HI + PUSHJ P,PLD1 + XCTRI XR,[MOVE B,(Q)] + JRST .+2 + BUG + PUSHJ P,PLDZ + HRRZ E,D ;TO ADDRESS + JRST BJBB3C + +BJBB3B: XCTRI XR,[MOVE B,(D)] + JRST .+2 + JRST BJBBF + HRLI J,%UMALL + PUSHJ P,PLD1 ;HACK OUR HI TO POINT TO HIS HI + XCTRI XW,[MOVEM B,(Q)] + JRST .+2 + BUG + PUSHJ P,PLDZ + JRST BJBB2A + +;.CALL JOBGET +;ARG 1 - BOJ CHNL +;UP TO SIX WDS RETURNED +;WD1 BITS: +%JG==1,,525252 + ;4.9-4.7 => IMAGE/ASCII, BLOCK/UNIT, OUTPUT/INPUT + ; 4.9-4.7 SHOULDN'T BE USED, SINCE THE FULL MODE IS IN WD7 ON AN OPEN +%JGCLS==40000 ;4.6 => CLOSE (NOTE 4.5 USED TO BE A CLS BIT ALSO) +%JGSIO==1000 ;4.1 => SIOT (ONLY IF OPCODE = 1) +%JGFPD==200 ;3.8 => THIS CALL WAS PCLSRED AND IS RESTARTING +;1.4-1.1 => TYPE OF OPERATION +%JO==,,-1 +%JOOPN==0 ;OPEN +%JOIOT==1 ;IOT/SIOT +%JOLNK==2 ;MLINK +%JORST==3 ;RESET +%JORCH==4 ;RCHST +%JOACC==5 ;ACCESS +%JORNM==6 ;FDELE (DELETE OR RENAME) +%JORWO==7 ;FDELE (RENAME WHILE OPEN) +%JOCAL==10 ;SYMBOLIC .CALL + +;WD2 SET ONLY FOR BLOCK IOT POINTER, ACCESS POINTER, NEW FN1 FOR FDELE +;WD3 FN1 +;WD4 FN2 +;WD5 SYS NAME +;WD6 LEFT ADJUSTED DEVICE NAME +;WD7 NEW FN2 FOR FDELE. +;IGNORE ALL RETURNED INFO ON AN ERROR RETURN +;IF 4.5 OR 4.6 IS SET THEN ALL ELSE IS MEANINGLESS + +NJBGT: SETZM T ;INDICATE JOBGET, NOT JOBCAL +NJBCL0: HLRZ E,H ;GET JOB CHNL IDX FROM LH OF IOCHNM WD + TLNN R,%CLSBJ ;NOT A BOJ CHANNEL => WRONG TYPE DEVICE + JRST OPNL34 + CONO PI,CLKOFF + MOVE C,JBWST(E) + TLNN C,%JBVAL + JRST NJBGTE ;FAIL IF VALID NOT SET + TLZ C,%JBSTR + MOVEM C,JBWST(E) ;CLEAR STORED BIT + MOVE B,JBCUI(E) + MOVE B,SUUOH(B) + CONO PI,CLKON + MOVE A,JBSTS(E) + TLZ A,077777 ;FLUSH RANDOM BITS FROM LH + TLNE B,%PCFPD + TLO A,%JGFPD + TLNE C,%JBSIOT + TLO A,%JGSIO + JUMPN T,NJBCL1 ;BRANCH IF JOBCAL +NJBGT0: MOVE B,JBST2(E) + MOVE C,JBOFN1(E) + MOVE D,JBOFN2(E) + MOVE TT,JBODEV(E) + MOVE I,JBNFN2(E) + MOVE E,JBOSYN(E) + CONO PI,CLKON + JRST POPJ1 + +NJBGTE: SKIPL JBCG(E) ;HAS CREATOR GONE AWAY? + JRST OPNL36 ;NO, VALID CLEAR + CONO PI,CLKON ;YES, GIVE CLOSE + MOVSI A,%JBLOS + IORM A,JBWST(E) + MOVSI A,%JGCLS ;GIVE CLOSE BITS + JRST POPJ1 ;DON'T GIVE ANYTHING ELSE WHETHER JOBGET OR JOBCAL + +; .CALL ADR +; ERROR RETURN +; NORMAL RETURN + +;ADR: SETZ +; SIXBIT /JOBCAL/ +; [BOJCHNL] +; [-N,,ADR OF DATA BUFFER] ;OPTIONAL +; SETZM OPCODE +; OPCODE WILL BE THE SAME AS RETURNED IN WD1 BY JOBGET +; IF OPCODE<10 THEN WD2-WD7 OF JOBGET WILL BE WRITTEN INTO DATA BUFFER +; FOLLOWED BY JOB'S EPDL AND EPDL3 (THE BPS FOR BP-STYLE OPENS, ETC). +;IF OPCODE=10 THEN JOB'S LAST .CALL WILL BE DESCRIBED: +; WORD 1 OF DATA BUFFER => SIXBIT OF OPERATION (I.E. THE NAME +; OF THE .CALL) +; WORD 2 OF DATA BUFFER => FLAG BITS OF .CALL +; WORD 3 OF DATA BUFFER => # OF ARGS TO .CALL +; WORDS 4-12 => INPUT ARGS TO .CALL + +NJBCL: CAIL W,2 ;DID CALLER SUPPLY AOBJN POINTER? + SKIPN T,B ;IF SO AND NON-ZERO USE IT + MOVEI T,1 ;OTHERWISE SET T NONZERO + JRST NJBCL0 ;GO JOIN JOBGET CODE FOR ERROR CHECKING + +NJBCL1: JUMPGE T,POPJ1 ;BACK FROM JOBGET - ANY AOBJN PNTR? + MOVEI C,9 ;YES - OPCODE 10? + TRNN A,10 + JRST NJBCL2 ;NO - JUST COPY 9 STANDARD ARGS + HLRE D,T ;GET LENGTH OF USERS DATA BUFFER + MOVE B,JBCUI(E) ;GET JOB'S USER INDEX + MOVE C,LSCALL(B) ;GET NAME OF JOB'S LAST CALL + UMOVEM C,(T) ;PUT INTO CALLERS BUFFER + AOJE D,POPJ1 ;IF NO MORE ROOM - DONE + MOVE C,CTLBTS(B) ;GET USER'S .CALL FLAG BITS + UMOVEM C,1(T) + AOJE D,POPJ1 + LDB C,[230400,,JBSTS(E)] ;GET # OF ARGS + UMOVEM C,2(T) + JUMPE C,POPJ1 ;ANY ARGS TO PASS? + ADD T,[3,,3] ;YES - COPY INTO BUFFER +NJBCL2: JUMPGE T,POPJ1 ;ANY ROOM LEFT? + MOVNS C ;GET SMALLEST WORD COUNT + HLRE B,T + CAMLE C,B + HRL T,C ;MAKE AOBJN PNTR AS SMALL AS POSSIBLE + MOVE H,E ;JOB INDEX IN H FOR USING JBACTB + MOVEI B,JBACTB ;GET PNTR TO ARG TABLES +NJBCL3: MOVE C,@(B) ;GET NEXT ARG + UMOVEM C,(T) ;GIVE TO CALLER + AOS B + AOBJN T,NJBCL3 + JRST POPJ1 ;DONE - GO SKIP + +; .CALL ADR +; ERROR RETURN +; NORMAL RETURN + +;ADR: SETZ +; SIXBIT /JOBRET/ +; [BOJCHNL] +; [OPEN LOSS #(IF RH = 0),,# TIMES FOR CREATING JOB TO SKIP] +; SETZ [-N,,ADR OF DATA BUFFER] + +;RETURN DATA (E.G. RETURN TO RCHST,STATUS OR THE RETURN ARGS TO A .CALL) +;WILL BE COPIED FROM THE CALLER'S DATA BUFFER + +NJBRT: HLRZ E,H ;GET JOB CHNL IDX FROM LH OF IOCHNM WD + TLNN R,%CLSBJ ;NOT BOJ CHNL => WRONG TYPE DEVICE. + JRST OPNL34 + CAIGE W,3 ;RETURN ARGS PROVIDED? + SETZM C ;NO - ZERO IT + JUMPGE C,NJBRT1 ;DO NOTHING IF NO RETURNS OR NO AOBJN + HLRE D,C ;GET LENGTH OF BUFFER + CAMGE D,[-8.] ;MAKE SURE AREA AT MOST 8 LONG + MOVNI D,8 ;OVER 8 - USE 8 + HRL C,D ;FIX AOBJN PNTR + MOVMS D + ADDI D,-1(C) ;GET ADDRESS OF LAST WORD NEEDED + XCTR XR,[SKIP (C)] ;MAKE SURE PAGES ARE IN + XCTR XR,[SKIP (D)] +NJBRT1: CONO PI,CLKOFF ;NOW OK TO TURN CLOCK OFF + MOVE A,JBWST(E) + TLNE A,%JBVAL + TLNE A,%JBSTR + JRST OPNL36 ;FAIL IF STORED IS SET OR IF VALID IS CLEARED + SKIPGE JBCG(E) + JRST OPNL41 + HRRZ TT,JBCUI(E) + MOVE D,FLSINS(TT) + CAME D,JBFLS + BUG + TLO A,%JBWIN + TLZ A,%JBVAL+%JBSTR + MOVEM A,JBWST(E) ;SET SUCCESSFUL JOBRET BIT, CLEAR VALID AND STORED + DPB B,[350400,,JBSTS(E)] ;NUMBER OF TIMES TO SKIP + MOVSS B + DPB B,[270600,,JBSTS(E)] ;OPEN LOSS + MOVSI B,-6 ;DEFAULT # WDS TO RETURN FOR .RCHST IS 6. + MOVEM B,JBAC11(E) + JUMPGE C,NJBRT3 ;ANY RETURN ARGS? + MOVEM C,JBAC11(E) ;REMEMBER HOW MANY, FOR .RCHST TO RETURN THAT MANY. + MOVE H,E ;YES - COPY THEM + MOVEI D,JBACTB +NJBRT2: XCTRI XR,[MOVE B,(C)] ;GET IT + AOSA D + BUG ;PAGE IS TIED - NO? + MOVEM B,@-1(D) ;PUT INTO ARG TABLE + AOBJN C,NJBRT2 +NJBRT3: SETZM FLSINS(TT) ;RESTART CREATOR + JRST CLKOJ1 + +;JOB DEVICE CLOSE ROUTINE +JOBCLS: SETOM JBCG(A) + MOVE E,A + CONO PI,CLKOFF + PUSHJ P,JBINT ;INTERRUPT POOR BOJ GUY + JRST CLKONJ ;SINCE HE HAS NO CREATOR + +; ROUTINES FOR JOB ACCESS, RFPNTR, RESET, AND STATUS + +RFPJOB: MOVEI J,4 ;USE OLD .RCHST OPERATION, OPCODE 4 + HRRM J,JBSTS(A) + MOVE E,A + CONO PI,CLKOFF + PUSHJ P,JBWT ;SIGNAL JOB, WAIT FOR ANSWER + HLRE TT,JBAC11(E) ;GET # VALUES RETURNED + MOVNS TT + CAIL TT,5 + SKIPA A,JBODEV(E) ;GET ACCESS POINTER RETURNED + SETO A, ;NO ACCESS POINTER RETURNED, USE -1 + CAIL TT,6 ;UP TO TWO MORE EXTRA RCHST RESULTS MIGHT BE RETURNED + MOVE Q,JBNFN2(E) + CAIL TT,7 + MOVE I,JBAC7(E) + CAIL TT,5 + MOVEI W,1(TT) ;# RESULTS FOR RCHST + MOVEI B,36. ;ALWAYS RETURN 36. AS BYTE SIZE UNTIL MORE WINNING + JRST POPJ1 ;CONVENTIONS EXIST. + +JBSTAT: HLRZ A,(R) ;GET JOB INDEX + HRRZ D,JBWST(A) ;GET MOST RECENT STATUS + POPJ P, + +JBORS: +JBIRS: MOVEI D,3 ;RESET IS OPCODE 3 + HLRZ A,(R) + HRRM D,JBSTS(A) + CONO PI,CLKOFF + MOVE E,A + PUSHJ P,JBWT ;WAIT FOR IT TO GET PROCESSED + POPJ P, + +JBACCS: MOVEI D,5 ;ACCESS IS OPCODE 5 + HLRZ A,(R) + HRRM D,JBSTS(A) + MOVEM B,JBST2(A) + CONO PI,CLKOFF + MOVE E,A + PUSHJ P,JBWT + JRST POPJ1 + +;.CALL JOBIOC (OLD NAME SETIOC STILL WORKS) +;ARG1: CHANNEL BOJ DEVICE IS OPEN ON +;ARG2: TYPE OF IOCER TO CAUSE + +;THIS CALL CAUSES THE NEXT IOT EXECUTED BY THE +;PROCEDURE ON THE OTHER END OF THE CHANNEL TO GET +;THE SPECIFIED IO CHANNEL ERROR + +NSTIOC: HLRZ E,H ;GET JOB CHNL IDX FROM LH OF IOCHNM WD. + CAIL B,MIOTER + CAILE B,NIOTER + JRST OPNL33 ;BAD ARG. (NOT LEGAL IOCER) + TLO B,(SETZ) ;IN CASE IOCER 0 EVER EXISTS + TLNN R,%CLSBJ + JRST OPNL34 ;NOT BOJ CHANNEL + CONO PI,CLKOFF + MOVE A,JBCUI(E) ;PREPARE TO STOP CREATOR. + SKIPGE JBCG(E) + JRST OPNL41 ;CREATOR WENT AWAY + MOVE H,APRC(A) + TLNE H,BULGOS + JRST OPNL41 ;HE'S BEING KILLED NOW. + PUSHJ P,RPCLSR ;STOP + MOVEM B,JBIOCJ(E) + AOS (P) + JRST UPCLSR + + +;.CALL JOBSTS +;ARG1 - CHANNEL BOJ IS OPEN ON - REMAINING ARGS ARE OPTIONAL - +;ARG2 - NEW STATUS (RIGHT HALF OF STATUS WORD ONLY - I.E. DEVICE DEPENDENT STUFF) +;ARG3 - NEW DEVICE NAME FOR PEEK, WHO-LINE STATUS, RFNAME/RCHST +;ARG4 - NEW FN1 FOR .. +;ARG5 - NEW FN2 FOR .. +;ARG6 - NEW SNAME FOR .. +;ARG7 - NEW OPEN MODE FOR .. +;ARG8 - BP TO ASCIZ STRING IN USER ADDRESS SPACE CONTAINING FULL FILENAMES. + +NJBSTS: TLNN R,%CLSBJ + JRST OPNL34 + HLRZ A,(R) ;GET JOB INDEX + CAIGE W,2 ;DID HE SUPPLY STATUS? + MOVEI B,SNJOB ;NO - RESET TO INITIAL + HRRM B,JBWST(A) ;REMEMBER WHAT HE SAYS + MOVEI B,8 + SUB B,W + JUMPGE B,.+1(B) ;STORE WHATEVER ADDITIONAL ARGS WERE GIVEN + JSP B,NJBST2 ;8 + JSP B,NJBST1 ;7 + MOVEM TT,JBSYS(A) ;6 + MOVEM E,JBFN2(A) ;5 + MOVEM D,JBFN1(A) ;4 + MOVEM C,JBDEV(A) ;3 + JRST POPJ1 ;2 + JRST POPJ1 ;1 (DON'T TAKE THIS INSN OUT) + +NJBST1: XOR I,JBOPNM(A) + TRNE I,.BAO#.UAI + JRST OPNL12 ;NOT ALLOWED TO CHANGE BLOCK VS UNIT, IN VS OUT + XORM I,JBOPNM(A) + JRST (B) + +NJBST2: MOVE R,Q ;STORE BP IN Q INTO JBFNP WORD, + PUSHJ P,ASCIND ;AFTER DOING INDEXING AND INDIRECT. + MOVEM R,JBFNP(A) + JRST (B) + +; .CALL ADR ;SKIPS UNLESS JOB END OF CHNL NOT THERE + +;ADR: SETZ +; SIXBIT /JOBINT/ +; 401000,,BOJCH + +;GIVE CREATOR A SECOND WORD INT ON CHANNEL CORRESP TO BOJCH + +NJBINT: TLNN R,%CLSBJ ;ERROR IF NOT BOJ CHNL. + JRST OPNL34 + CONO PI,CLKOFF + HLRZ E,H + SKIPGE JBCG(E) + JRST OPNL41 + MOVE A,JBCUI(E) + MOVSI D,%CLSJ + SETZ C, + PUSHJ P,CHSCAA + PUSHJ P,[HRRZ B,(R) + SKIPGE R ;IOPDL CHNLS DON'T INTERRUPT + TDNN D,CLSTB(B) + POPJ P, + HRRZ B,R + SUBI B,IOCHNM(A) + IOR C,CHNBIT(B) + POPJ P,] + AND C,MSKST2(A) + JUMPE C,OPNL41 ;I CAN'T + MOVN B,C + AND C,B ;INT ONLY ONCE, ON HIGHEST NUMBERED CHANNEL + IORM C,IFPIR(A) + JRST CLKOJ1 + + +;.CALL JOBREU +;ARG 1 - SIMULATED DEVICE NAME +;ARG 2 - FN1 OF .. +;ARG 3 - FN2 OF .. +;ARG 4 - SNAME OF FILE WHICH HANDLER LOADED FROM +;ARG 5 - AMOUNT OF TIME TO SLEEP WAITING FOR SOMEONE TO OPEN + +;THIS CALL, WHEN EXECUTED BY A JOB DEVICE HANDLER JOB, MAKES +;THE HANDLER AVAILABLE FOR RE-USE. TAKES SUCCESS RETURN IF +;SOMEONE REUSES YOU; YOU SHOULD THEN DO THE "INITIAL JOBGET" + +NJBREU: SKIPGE H,JBI(U) + JRST OPNL10 ;NOT A BOJ HANDLER JOB + SKIPL JBCG(H) + PUSHJ P,UFLS ;WAIT FOR CLOSE TO FINISH HAPPENING + MOVEM A,JBODEV(H) + MOVEM B,JBOFN1(H) + MOVEM C,JBOFN2(H) + MOVEM D,JBOSYN(H) + TLNE E,1000 + JRST [ MOVNI E,(E) ;IMMEDIATE TIME, LOSE ON PCLSR + SUB E,TIME ;BUT ACCEPT ANYWAY SINCE NETBLK DOES + JRST NJBRU1 ] + MOVE TT,E + UMOVE E,(TT) ;GET TIME ARGUMENT + JUMPL E,NJBRU1 + MOVNS E + SUB E,TIME + UMOVEM E,(TT) ;POS REL TIME GIVEN, MAKE NEG ABS AND WRITE BACK +NJBRU1: MOVSI TT,%JBREU ;E NOW HAS NEGATIVE TIME TO SLEEP UNTIL + IORM TT,JBWST(H) + PUSHJ P,LOSSET + NJBRUL ;TURN OFF %JBREU WHEN CALL EXITED FOR WHATEVER REASON + SKIPA T,H + PUSHJ P,NJBRUW + PUSHJ P,UFLS + SKIPGE JBCG(H) + JRST OPNL41 ;TIMED OUT + JRST LSWPJ1 + +;FLSINS ROUTINE TO WAIT UNTIL TIMED OUT OR OPENED BY SOMEONE +NJBRUW: MOVN A,AC0S+E(U) + CAML A,TIME + SKIPL JBCG(T) + AOS (P) + POPJ P, + +;LOSSET ROUTINE TO LEAVE AWAITING-REUSE STATE +NJBRUL: MOVSI A,%JBREU + MOVE T,AC0S+H(U) + ANDCAM A,JBWST(T) + POPJ P, + +SUBTTL PERIPHERAL DEVICE ROUTINES IN SEPARATE FILES + +IFN NMTCS,[ + IFN TM10P,[ +$INSRT MTAPE + ] + IFN TM03S,[ +$INSRT NMTAPE +] +] +IFN NUNITS,[ +$INSRT UTAPE +] + +$INSRT DISK + +IFN NETP,[ ; General ITS network code, includes specific nets +OVHMTR NET +$INSRT NET +] + +IFN E.SP,[ +$INSRT ITSDIS +] + +IFN MSPP,[ +$INSRT ITSMSP +] + +$INSRT TS3TTY + +$INSRT ITSDEV + +.BYTE 0 ;RECORD THE SYMS .EVAL'ED BY USER PROGRAMS +$INSRT EVSYMS +.BYTE + +SUBTTL DM DAEMON UUO'S + +IFE DEMON,ADEMON==ILUUO + +IFN DEMON,[ +ADEMON: JUMPE J,[AOJA J,.+2] ;IF J = 0 THEN SUBTRACT ONE + UMOVE J,(J) ;GET VALUE HERE + PUSHJ P,LSWTL + 400000,,DEMSW + PUSHJ P,DEMUSR ;FIND CURRENT USER IN DEMON TABLE + JRST UTOLKJ ;FAIL, JUST RETURN, NOT DEMON + HRRE TT,DMTTBL+2(B) + SUB TT,J + HRRM TT,DMTTBL+2(B) ;PUT NEW COUNT IN DEMON TABLE + SKIPLE TT +UTOLJ1: AOS (P) +UTOLKJ: CONO PI,UTCON + JRST LSWPOP + +ADEMSIG:MOVE D,B + CONO PI,CLKOFF ;DON'T LET SYS JOB LOOK TILL WE'RE READY. + MOVSI T,SCLDMN ;TELL IT TO LOOK FOR US, AFTER UFLS TURNS CLOCK ON. + IORM T,SUPCOR + SETZB T,SRN3(U) ;SYS JOB WILL SETOM SRN3 TO RESTART US + SKIPN SRN3(U) ;WITH 0 IN T => FILE EXISTS, OR OPNL CODE. + PUSHJ P,UFLS ;SYS JOB DETECTS US BY PC=ADEMS1. + ;DEMON NAME IS EXPECTED TO BE IN A. +ADEMS1: JUMPN T,OPNL1-1(T) + CAIGE W,2 ;NO SECOND ARG, JST SIGNAL + JRST ADEMS3 + JUMPL D,NUDMTB ;IF 2ND ARG < MERELY CALL NUJBST, NO DEMON ENTRY + TDZA TT,TT ;ZERO OUT TT +ADEMS3: SETOM TT ;SET FLAG + PUSHJ P,LSWTL ;SIEZE SWITCH + DEMSW + PUSHJ P,DEMSIG + JRST LSWPOP ;SIGNAL FAILED + SKIPN TT ;FLAG NOT SET + HRLM D,DMTTBL +2(B) ;SET TIME RQ + JRST CKOPJ1 ;RELEASE SWITCH + +NUDMTB: PCLT + PUSHJ P,DMBLK1 ;WAIT TILL DEMON BLOCK IS CLEARED + PUSHJ P,UFLS + HRROI T,DMBLK + MOVEM A,DMBLK ;SAVE IN BLOCK NOW + PUSHJ P,NUJBST + JRST NUDMTB ;IF FAILURE AFTER WAIT LOOP BACK + JRST POPJ1 ;SUCCESS + +DMBLK1: SKIPGE DMBLK+1 ;FOR DEMON BLOCK TEST + POPJ P, ;RETURN, NOT FINISHED LOADING + MOVE T,UTTYCT + CAIGE T,MXCZS ;ROOM IN RING BUFFER + AOS (P) + POPJ P, ;SKIP IF ROOM + ;UTILITY ROUTINES FOR DEAMONS + +DEMSIG: PUSHJ P,DEMNAM ;LOOK FOR NAME + JRST DEMSG2 ;HAVE TO MAKE NEW ENTRY +DEMSG1: AOS (P) + HLLZ E,DMTTBL+2(B) ;18 BITS 2'S COMPLEMENT + AOS DMTTBL+2(B) + HLLM E,DMTTBL+2(B) ;MUST DO THIS WAY TO FIT ABOVE + SKIPE DMTTBL+1(B) ;DOWN, WANT SYS JOB TO LOOK AT + POPJ P, + MOVSI E,SCLDMN + IORM E,SUPCOR + AOS REQCNT ;ONLY SIGNAL IF NECESSARY + POPJ P, + +DEMSG2: SOSGE DEMCNT ;IF NO ROOM FLUSH + POPJ P, + PUSH P,A + MOVEI A,DMTLL ;BUMP POINTER + ADDB A,DMTPTR + IDIVI A,DMLNG ;TRUNCATE TO LENGNTH OF TABLE + SKIPE DMTTBL(B) + JRST .-4 ;SEARCH FOR NEW ENTRY + POP P,DMTTBL(B) ;SET NAME IN TABLE + JRST DEMSG1 + +;ROUTINES TO FIND ENTRY IN TABLE. +;DEMNAM TAKES NAME IN A, DEMUSR TAKES USER INDEX IN U +;THEY SKIP RETURN IF SUCCESSFUL, RETURN OTHERWISE +;IF SUCCESSFUL DEMON TABLE INDEX IS IN B + +DEMUSR: JUMPL U,CPOPJ + MOVSI B,-DMLNG + CAMN U,DMTTBL+1(B) + JRST POPJ1 + ADD B,[DMTLL,,DMTLL] + JUMPL B,.-3 + POPJ P, + +DEMNAM: MOVSI B,-DMLNG ;SEARCH BY NAME + CAMN A,DMTTBL(B) + JRST POPJ1 + ADD B,[DMTLL,,DMTLL] + JUMPL B,.-3 + POPJ P, + +DEMOUT: PUSHJ P,LSWTL ;CALLED BY KILLING JOB (IN CASE OWNED) + 400000,,DEMSW + PUSHJ P,DEMUSR + JRST UTOLKJ + SETZM DMTTBL+1(B) ;MARK AS DOWN,SYSTEM JOB DECIDES WHAT TO DO + AOS REQCNT + MOVSI B,SCLDMN + IORM B,SUPCOR + JRST UTOLKJ + +DEMMRV: SETZM DMTTBL+2(B) ;CALL WITH UTCOFF (SYS JOB) REMOVES ENTRY FROM TBL + SETZM DMTTBL+3(B) ;WITH INDEX OF DEMON IN B + SETZM DMTTBL(B) + MOVEI B,1 + AOSGE DEMCNT + MOVEM B,DEMCNT + JRST UTCONJ + + +;DEAMON READ AND SET STATUS ROUTINES + +ARDDMST: PUSHJ P,LSWTL ;READ DEAMON STATUS + DEMSW + PUSHJ P,DEMNAM + JRST RDDMS1 ;LOST TRY USER INDEX + MOVE A,DMTTBL+1(B) + MOVEI C,L + IDIVM C,A ;DIVIDE BY L, DON'T CLOBBER B +RDDMS2: MOVE C,DMTTBL+3(B) + MOVE B,DMTTBL+2(B) + PUSHJ P,LSWPOP + JRST POPJ1 + +RDDMS1: PUSH P,U + MOVE U,A + PUSHJ P,DEMUSR ;BAD USER + JRST LKUPOP + POP P,U + MOVE A,DMTTBL(B) + JRST RDDMS2 +LKUPOP: POP P,U + JRST LSWPOP + +ASTDMST: PUSHJ P,LSWTL ;SET DEAMON STATUS + 400000,,DEMSW + MOVE D,B + PUSHJ P,DEMNAM + JRST STDMS1 +STDMS2: JUMPL D,STDMS4 +STDMS3: SOSLE W + MOVEM D,DMTTBL+2(B) + SOSLE W + MOVEM C,DMTTBL+3(B) + JRST UTOLJ1 +STDMS1: PUSH P,U + MOVE U,A + PUSHJ P,DEMUSR + JRST UTULKP + POP P,U + JUMPGE D,STDMS2 +STDMS4: SKIPGE DMTTBL+1(B) ;REMOVE FROM TABLE IF POSSIBLE + JRST UTOLKJ ;CAN'T DELETE, LOADING + SETZM DMTTBL+1(B) ;DOWN + SETZM DMTTBL+2(B) ;REMOVE REQUESTS + AOS REQCNT ;SIGNAL SYS JOB + MOVSI B,SCLDMN + IORM B,SUPCOR + JRST UTOLJ1 +UTULKP: POP P,U + JRST UTOLKJ +] + + +SUBTTL .GETSYS UUO + +;.GETSYS AC, ;TRANSFERS SYSTEM AREA SPECIFIED BY C(AC+1) + ;TO USER AREA STARTING AT R.H. C(AC) OF LENGTH MINUS L.H. C(AC) + +AGETSYS: +; Alan 4/2/86: Took this out because people don't use .GETSYS this way +; anymore: +; PUSHJ P,UDELAY ;CAUSE A SCHEDULE TO STOP GETSYSER FROM +; ; MONOPOLIZING SYSTEM + MOVSI A,-LGSNAM ;NEGATIVE OF TABLE LENGTH + UMOVE B,1(J) ;LOOK AT USERS AC+1, THE 6BIT NAME + CAME B,GSNAME(A) ;CYCLE THROUGH TABLE + AOBJN A,.-1 ;OF NAMES, POINTER IN RIGHT HALF OF A + JUMPGE A,AGETSL ;JUMP IF NOT IN TABLE + UMOVE B,(J) ;GET POINTER TO USERS RECEPTACLE BLOCK +AGETS1: HLRZ C,GSYS1(A) ;GET LOW END OF BLOCK + HRRZS A ;CLEAR COUNT IN L.H. OF A + CAIGE A,NUTCFN ;SKIP IF UTC OFF NOT REQUIRD + CONO PI,UTCOFF ;TURN OFF ALL CHANNELS BUT CH 1 + skipn c ; If LH contains 0, RH is routine to call. + jrst @gsys1(a) ; (JUMPE C,@GSYS1(A) generates spurious + ; page faults, so don't "fix" this.) + HRRZ D,GSYS1(A) ;GET HIGH END OF BLOCK +;AT THIS POINT: ;B USER'S POINTER (UNRELOCATED) + ;C BEGINNING OF AREA IN SYS + ;D END OF AREA +agets2: SUBI D,-1(C) ;BLOCK LENGTH TO BE SENT + HLRZ E,B ;GET NEG BLK LENGTH FROM USERS PNTR + ADDI E,-1(D) ;-1 CAUSES CARRY BIT IF .GT. + TLNE E,-1 ;CARRY INDICATES LOSS + JRST AGETS5 ;MORE THAN USER WANTS + HRLS D ;BLOCK LENGTH IN BOTH HALVES + HRRZ E,B ;FIRST WORD (UNRELOCATED) + HRL E,C ;SOURCE ADDRESS FOR BLT + HRRZ C,E ;DESTINATION INTO C + ADD C,D ;FINAL ADDRESS +1 +AGETS7: XCTRI XBW,[BLT E,-1(C)] ;BLT IT TO HIM + AOSA (P) ;INCREMENT RETURN, INDICATE SUCCESS + JRST AGETS6 + CONO PI,UTCON + ADD B,D + UMOVEM B,(J) ;TELL USER HOW MUCH HE GOT +AGETS4: POPJ P, + +AGETSL: XCTR XW,[SETZM 1(J)] ;INDICATE BAD SIXBIT + POPJ P, + +AGETS5: MOVNS D ;TELL USER HOW MUCH HE NEEDS + CONO PI,UTCON ;NEGATIVE OF RIGHT BLOCK LENGTH + XCTR XRW,[HRLM D,(J)] ;SET UP PROPER BLOCK LENGTH IN HIS AC + JRST AGETS4 + +AGETS6: CONO PI,UTCON ;ONE PAGE WASN'T THERE + XCTR XRW,[MOVES (E)] ;SO TOUCH IT (TAKE MPV INTERRUPT IF REAL MPV) + JRST AGETS1 ;AND TRY AGAIN (BLT WILL GET FARTHER THIS TIME) + ;HAD TO RETRY FROM BEGINNING SINCE THIS MAY BE + ;ONE THAT HAS TO BE TRANSFERRED INTACT WITH UTCOFF + +GSNAME: SIXBIT /MEMORY/ +IFN NUNITS,SIXBIT /UTAPE/ +IFN NCPP,[SIXBIT /NCPSM/ + SIXBIT /NCPPQ/ + SIXBIT /NCPHT/ +] +NUTCFN==.-GSNAME ;NUMBER TO GET WITH UTCOFF (same as NETOFF) + SIXBIT /USERS/ + SIXBIT /USER/ + SIXBIT /GETS/ + SIXBIT /DEVS/ + SIXBIT /CALLS/ +IFN IMXP, SIXBIT /IMPX/ + SIXBIT /CLINK/ + SIXBIT /DSYMS/ + SIXBIT /USYMS/ ;.UPC, .VAL, .TTY, ETC. + SIXBIT /CHDEVS/ + SIXBIT /NCALLS/ + SIXBIT /TTYVAR/ + SIXBIT /USRVAR/ + SIXBIT /ITSNMS/ +LGSNAM==:.-GSNAME + +;ENTRIES ARE: BOTTOM,,TOP OF AREA TO BE TRANSMITTED OR INST TO EXECUTE +GSYS1: IOBFTL,,EMEMTL ;lh zero => jrst to THIS ENTRY +IFN NUNITS, UTCHNT,,UTCHE ;UTAPE +IFN NCPP,[IMSOKB,,IMSOKE ;NCP SOCKET MAP + IMPBPQ-1,,IMPEPQ ;NCP PENDING RFC QUEUE + IMPHTB,,IMPHTB+255. ;NCP HOST TABLE +] + 0,,USRSV ;USERS + 0,,USR1V ;USER + GSNAME,,GSNAME+LGSNAM-1 ;GETS + DEVTAB,,EDEVS ;DEVS + SYSYMB,,SYSYME ;CALLS +IFN IMXP, IMXTBB,,IMXTBE ;IMPX + CLVBEG,,CLVEND ;CLINK + 0,,DSYMS ;DSYMS + SYSUSB,,SYSUSE ;USYMS + DCHSTB,,DCHSTE ;CHDEVS + SYSCTB,,SYSCTB+LSYSCT-1 ;NCALLS + TYVTAB,,TYVTAB+LTYVTA-1 ;TTYVAR + USETTB,,USETTB+MXVAL-1 ;USRVAR + ITSNMS,,ITSNMS+LITSNM-1 ;ITSNMS +IFN LGSNAM-<.-GSYS1>, .ERR GSNAME and GSYS1 don't match. + +ITSNMS: ITSIRP [ + SIXBIT /ITS/ + ] +LITSNM==:.-ITSNMS + 0 + 0 ; Make it easy to add more. + +USRSV: MOVEI C,USRSTG + MOVE D,USRHI + ADDI D,USRSTG-1 + JRST agets2 + +USR1V: UMOVE C,2(J) + IMULI C,LUBLK + CAML C,USRHI + JRST USR1VL + ADDI C,USRSTG + MOVE D,C + ADDI D,LUBLK-1 + JRST agets2 + +USR1VL: XCTR XW,[SETOM 2(J)] + JRST AGETS4 + +DSYMS: HRRZ C,DDT-2 + HLRE D,DDT-2 + SETCMM D ;OFFSET BY ONE + ADD D,C + JRST agets2 + +SUBTTL .GETLOC, .EVAL, ETC. + +;GET AN ABSOLUTE LOCATION ;.GETLOC AC, ;C(A)=FROM(ABS),,TO(RELATIVE) +; +AGETLOC:UMOVE A,(J) ;GET TO ADDRESS + HLRZ B,A ;GET FROM ADDRESS + XCTRI [MOVE C,(B)] + JRST .+2 + JRST ILEXPF ;ILLEGAL EXEC PAGE FAULT + UMOVEM C,(A) ;GIVE TO USER + POPJ P, + +;SET AN ABSOLUTE LOCATION ;.SETLOC AC, ;C(AC)=FROM(RELATIVE),,TO(ABS) +; +ASETLOC:TDZA D,D ;CLEAR COND FLAG, SKIP + +;SET AN ABSOLUTE LOCATION ONLY IF C(ABS)=C(TEST) & SKIP IF SUCCESSFUL +;.IFSET AC, ;C(AC)=,,TO ADR(ABS) +;WORD 1=TEST ;WORD 2=NEW C(ABS) + +AIFSET: MOVNI D,1 ;SET COND FLAG + XCTR XR,[HRRZ A,(J)] ;GET TO ADDRESS (ABSOLUTE) + XCTR XR,[HLRZ B,(J)] + UMOVE C,(B) ;GET WORD + XCTRI [MOVES (A)] + JRST .+2 + JRST ILEXPF + JUMPE D,ASPST1 ;NORMAL SETLOC + UMOVE D,1(B) ;GET NEW VALUE + CONO PI,CLKOFF ;PREVENT INTERRUPTS + CAME C,(A) ;CHECK WORD AGAINST TEST WORD + JRST CLKONJ ;NOT EQUAL => IGNORE + MOVE C,D + AOS (P) ;CAUSE RETURN TO SKIP + CAIG A,SYSB_10. ;CHECK IF IN SYS + JRST ASPST1 ;YES SO DO REG SETLOC + EXCH D,(A) ;NO SO DO NOW BEFORE SHUFFLE & GET OLD +ASPST2: MOVE C,D + HRROS A ;LET SYS JOB KNOW ALREADY DONE +ASPST1: CAMN C,(A) ;SKIP IF DIFFERENT FROM C(TO ADR) + JRST CLKONJ ;SAME + MOVE D,SYSITM ;IF SYSTEM JOB HAS BEEN HUNG OR LOOPING FOR 30 SEC, + ADDI D,30.*30. + CAMGE D,TIME + JUMPGE A,ASPST3 ;GO DO THE WORK OURSELVES (BUT DON'T DO IT TWICE). +ASPST4: MOVE D,UNAME(U) ;GET UNAME OF SETLOCER + MOVSI T,SCLSET + PUSHJ P,CWAIT ;WAIT TILL VARIABLES TO COMMUNICATE WITH SYS JOB ARE FREE + TDNE T,SUPCOR ;ARG TO CALL IN .-1 + MOVEM A,SETSLC ;REMEMBER ABS LOCATION + MOVEM C,SETSLQ ; " NEW CONTENTS (OR OLD IF LH(SETSLC)=-1) + MOVEM D,SETSU ; " USER +CSPST: IORM T,SUPCOR ;TELL SYS JOB TO DO IT + JRST CLKONJ + +ASPST3: HRRZ D,UPC ;SYS JOB HAS BEEN HANGING FOR 30 SEC. + CAIN D,SCOR1 ;WHY? JUST SLEEPING? + JRST ASPST4 ;YES => SIGNAL IT TO DO THE WORK + MOVEM C,(A) ;ELSE GIVE UP ON IT AND DO IT NOW + JRST CLKONJ + +;LOOK UP ITS SYMBOL ;.EVAL AC, ;C(AC)=SQUOZE SYMBOL +;REPLACES SYMBOL BY VALUE & SKIPS IF SUCCESSFUL +;IF YOU WANT TO .EVAL A SYMBOL IN A PROGRAM HABITUALLY AND IMPLICITLY, +;AND WANT IT TO CONTINUE TO WORK, YOU HAD BETTER ADD AN ENTRY TO THE FILE +;AI:SYSTEM;EVSYMS > SAYING WHAT PROGRAM AND WHAT SYMBOL. THEN, ITS HACKERS +;CAN AVOID SCREWING YOU WITHOUT WARNING. + +AEVAL: PUSHJ P,SWTL + ARDFSW + UMOVE B,(J) ;GET SYM + PUSHJ P,SYMLK ;LOOK UP + JRST LSWPOP ;NOT FOUND + MOVE A,(C) ;GET VALUE + PUSHJ P,LSWPOP + AOS (P) ;CAUSE UUO TO SKIP + JRST APTUAJ ;RETURN VALUE + +;REDEFINE ITS SYMBOL ;.REDEF AC, ;C(AC)=POINTER TO 2 WORD BLOCK +;WORD 1 = SYMBOL ;WORD 2 = VALUE +;DELETE SYM IF ALL 4 FLAG BITS SET +; OTHERWISE SET SYMBOL FLAGS TO THOSE SPECIFIED, EXCEPT REJECT ANY ATTEMPT TO +; ADD A PROGRAM NAME +;ADD SYM IF NOT FOUND ;FAIL ONLY IF NOT ENOUGH ROOM +;SKIPS IF SUCCESSFUL + +AREDEF: PUSHJ P,SWTL + ARDFSW + XCTR XR,[HRRZ D,(J)] ;GET POINTER FROM AC + UMOVE B,(D) ;GET SYMBOL + PUSHJ P,SYMLK ;LOOK UP + JRST ARDF2 ;NOT FOUND, CREATE + XCTR XR,[SETCM A,(D)] ;GET SYM (COMPLEMENTED) + TLNN A,740000 ;SKIP IF ANY FLAGS NOT SET + JRST ARDF3 ;ALL SET => DELETE + SETCA A, + TLNN A,740000 + JRST LSWPOP + MOVEM A,-1(C) + UMOVE A,1(D) ;GET VALUE + MOVEM A,(C) ;STORE IN SYMTAB + JRST ARDF4 ;SORT AND SKIP-RETURN. + +ARDF2: MOVE C,DDT-2 ;GET POINTER + SUB C,[2,,2] ;DECREMENT FOR NEW ENTRY + MOVEI A,-1(C) ;FUDGE FOR BLOCK CALC + LSH A,-10. ;CONVERT TO # OF BLOCKS UP TO SYMTAB -1 + UMOVE B,(D) ;GET SYM + MOVE T,FDDTPG + LSH T,10. + TLNE B,740000 ;LOSE IF PROG NAME + CAMLE A,T ;CHECK FOR LOSSAGE + JRST LSWPOP ;DON'T OVERWRITE ITS + EXCH B,2(C) ;STORE OVER GLOBAL BLOCK HEADER, + MOVEM B,(C) ;MOVE THAT HEADER DOWN 2 WDS. + UMOVE A,1(D) ;GET VALUE + EXCH A,3(C) + ADD A,[-2,,] ;1 MORE SYM IN GLOBAL BLOCK. + MOVEM A,1(C) ;STORE + MOVEM C,DDT-2 ;UPDATE POINTER + JRST ARDF4 ;GO SORT AND SKIP-RETURN. + +ARDF3: MOVE B,DDT-2 ;GET POINTER + MOVE A,(B) ;MOVE THE GLOBAL HEADER + EXCH A,2(B) ;UP OVER 1ST SYM + MOVEM A,-1(C) ;WHICH GOES INTO FREE SLOT. + MOVE A,1(B) + ADD A,[2,,] ;GLOBAL BLOCK 1 SYM SHORTER. + EXCH A,3(B) + MOVEM A,(C) + MOVE A,[2,,2] + ADDM A,DDT-2 ;UPDATE POINTER +ARDF4: MOVSI E,(SETZ) ;TELL DDT ITS SYMTAB WAS ALTERED. + IORM E,DDT-1 + PUSHJ P,SBUBL ;DO 1 BUBBLE-SORT UP AND 1 DOWN. + JRST LSWPJ1 ;FREE ARDFSW AND EXIT. + +;DO ONE BUBBLE SORT PASS UP, ONE DOWN; LEAVE J <0 IFF DID AN EXCHANGE. +;CLOBBER A-E. +SBUBL: MOVE E,DDT-2 + HLL E,1(E) + ADD E,[2,,2] ;AOBJN -> SYMS IN GLOBAL BLOCK. +SBUBL0: SETZ J, + MOVE B,[2,,2] ;INCREMENT FOR UPWARD PASS. + MOVE C,[JUMPL A,SBUBL1] + SUBI E,2 ;(WILL INCREMENT BEFORE ACTING) + MOVE A,E + PUSHJ P,SBUBL2 + MOVNS B ;DECREMENT FOR DOWNWARD PASS. + MOVE C,[CAMN A,E] + JRST SBUBL2 + +SBUBL1: MOVE D,1(A) ;CHECK NEXT PAIR OF ENTRIES. + CAMG D,3(A) + JRST SBUBL2 ;IN CORRECT ORDER. + EXCH D,3(A) + MOVEM D,1(A) ;WRONG ORDER, EXCHANGE. + MOVE D,(A) + EXCH D,2(A) + MOVEM D,(A) + SETO J, ;SAY DID AN EXCHANGE. +SBUBL2: ADD A,B ;MOVE TO NEXT ENTRY. + XCT C ;TEST IF FINISHED. + POPJ P, + JRST SBUBL1 ;(NOT FINISHED) + +;LOOK UP SYMBOL IN B IN ITS SYMBOL TABLE (CLOBBERS A,B,C) +;RETURN WITH POINTER TO VALUE WORD IN C +;SKIPS IF SUCCESSFUL + +SYMLK: TLZ B,740000 ;FLUSH FLAGS + MOVE C,774000-2 ;PICK UP AOBJN POINTER TO SYMTAB FROM EXEC DDT +SYMLK2: MOVE A,(C) ;GET SYM + AOBJP C,[JRST 4,.+1] ;INCREMENT POINTER + TLNE C,376 ;GO THROUGH HAIR EVERY 200 SYMS + JRST SYMLK3 ;NOT THIS TIME + PUSHJ P,OPBRK +SYMLK3: TLNN A,200000 ;SKIP IF DELETE INPUT (FLAG PREVENTS MATCH) + TLZE A,740000 ;FLUSH FLAGS & CAUSE LOSS IF ALL 0 (PROG NAME) + CAME A,B ;COMPARE + AOBJN C,SYMLK2 ;LOSS, TRY ANOTHER + JUMPL C,POPJ1 ;SKIP RETURN IF FOUND + POPJ P, ;NOT SO IF LOSS + +AWSNAME:XCTR XR,[SKIPE B,(J)] ;OPER 35 + MOVEM B,USYSNM(U) + POPJ P, + +AUPISET:UMOVE B,(J) ;OPER 36 + ASH B,-35. + EXCH B,PICLR(U) + UMOVEM B,(J) + SKIPN PICLR(U) + POPJ P, + JRST APISE1 + +;GENERATE A UNIQUE SYM ;.GENSYM AC, ;LOADS AC WITH SYM +; +AGENSYM:PUSHJ P,SWTL ;WAIT TILL INTERLOCK FREE THEN SEIZE IT + GENSSW + MOVEI TT,IGNSYM + PUSHJ P,SIXAOS ;INCREMENT SYM + MOVE A,IGNSYM ;GET SYM + PUSHJ P,LSWPOP ;UNLOCK FOR NEXT USER + JRST APTUAJ ;GIVE USER GENERATED SYMBOL + +;GENERATE A UNIQUE NUM ;.GENNUM AC, ;LOADS AC WITH NUMBER +; +AGENNUM:AOS A,IGNNUM ;INCREMENT NUMBER + JRST APTUAJ ;AND GIVE IT TO USER + +EBLK + +GENSSW: -1 + 0 +IGNSYM: SIXBIT /SYS/ + +IGNNUM: 0 + +BBLK + +SIXAOS: PUSH P,I + PUSH P,J + AOS (TT) ;INCREMENT SYM + MOVE I,[440600,,(TT)] ;GET POINTER TO FIRST CHAR +SIXAS2: ILDB J,I ;GET FIRST (NEXT) CHAR + SKIPN J ;SKIP IF NOT ZERO + MOVEI J,1 ;REPLACE EMBEDDED SPACE WITH "!" + DPB J,I ;PUT BACK + CAME I,[60600,,(TT)] ;SKIP IF FIRST FIVE CHARS HAVE BEEN EXAMINED + JRST SIXAS2 ;GO TO NEXT CHAR + POP P,J + POP P,I + POPJ P, + +IFN KL10P,[ + +SUBTTL KL10 PERFORMANCE COUNTER + +;KLPERF SYMBOLIC SYSTEM CALL +;ARG 1: TO MEASURE PERFORMANCE DURING; + ;-3 => NULL JOB, -4 => ALL JOBS +;ARG 2: P.A. ENABLES WORD (SEE NON-EXISTENT KL10 SYS REF MAN) + ;0 => FREE THE FACILITY, ELSE TRIES TO GRAB IT +;NO ARGS => JUST READS THE VALUES WITHOUT CHANGING THE ENABLING CONDITIONS. + ;IN THAT CASE, IT IS OK IF FACILITY IS OWNED BY SOMEONE ELSE +;VAL 1: PREVIOUS SETTING +;VAL 2: PREVIOUS P.A. ENABLE WORD +;VAL 3: TIME BASE HIGH WORD +;VAL 4: TIME BASE LOW WORD +;VAL 5: PERF CTR HIGH WORD +;VAL 6: PERF CTR LOW WORD + +KLPERF: CONO PI,CLKOFF + JUMPN W,KLPER1 +KLPER0: MOVE J,MTRJOB ;NO ARGS => DONT CHANGE SETTINGS, + MOVE B,PAEON ;JUST RETURN CURRENT COUNT. + JRST KLPER3 + +KLPER1: JUMPN B,KLPER2 ;TRYING TO TURN IT ON? + CAME U,MTRUSR + JRST KLPER0 ;FREEING THE FACILITY WHEN DON'T OWN IT? + PUSHJ P,PRFOFF ;NO, TRYING TO FREE IT - DO SO. + MOVEI J,-2 + JRST KLPER3 + +KLPER2: SKIPGE MTRUSR ;IF FACILITY IS FREE, SIEZE IT. + MOVEM U,MTRUSR + CAME U,MTRUSR + JRST OPNL10 ;ALREADY BELONGS TO SOME OTHER JOB. + MOVEI J,2(A) + CAIN J,-2 ;ALL JOBS? + JRST KLPER4 + CAIN J,-1 ;NULL JOB? + JRST KLPER3 + MOVE J,A + JSP T,NCRUI2 ;ELSE DECODE JOB SPEC; OBJECT TO PDP6 + JFCL + CAME J,U + JRST KLPER3 +;TRYING TO TURN ON FOR SELF OR ALL JOBS - IT OUGHT TO BE ON RIGHT NOW! +KLPER4: CONO MTR,2001 ;TURN ON TIME BASE, INTERVAL PIA=1 + WRPAE B ;SET ENABLES +KLPER3: EXCH B,PAEON + SKIPGE A,MTRJOB + TRZA A,2 ;UN CONVERT -1 => -3, -2 => -4 + LSH A,-9 ;IDIVI A,LUBLK +IF2 IFN LUBLK-1000,.ERR NO DIVIDE + HRREM J,MTRJOB + RCCL C ;C,D GET TIME BASE + RPERFC E ;E,TT GET PERFC + JRST CLKOJ1 + +;TURN OFF THE PERFORMANCE COUNTER. PUT BACK IN RUN-TIME MEASURING MODE +PRFOFF: MOVNI A,2 ;NOT ATTACHED TO ANY JOB + MOVEM A,MTRJOB + WRPAE [1576,,1200] ;MEASURE MAIN-PROGRAM TIME IN 80 NS UNITS (MODEL A) + CONO MTR,4001 ;TIME-BASE OFF, INTERVAL PIA=1 + RPERFC STPERF ;START-OF-QUANTUM TIME IS NOW + RPERFC NULPRF ;ALSO FOR NULL-JOB + SETOM MTRUSR ;NO LONGER IN USE + POPJ P, +] ;END IFN KL10P + +$INSRT CORE ;CORE JOB AND MEMORY MANAGEMENT ROUTINES + +SUBTTL NULL DEVICE +; IMMEDIATE EOF ON INPUT, HAS NO EFFECT ON OUTPUT +; +NULO: HLRS A,C ;REMEMBER MODE FOR .STATUS + JSP Q,OPSLC3 ;SET UP IOCHNM WORD AND EXIT + NLIDN,,NLODN ;ARG + NLBIDN,,NLBDN ;ARG + +;UNIT NULL DEVICE INPUT +NULI: JRST UNIEOF + +;BLOCK NULL DEVICE INPUT +NULBI: POPJ P, + +;BLOCK NULL DEVICE OUTPUT ENTRY +;ADVANCE BLOCK MODE .IOT POINTER +NULBOD: XCTR XR,[HLRE A,(C)] ;GET NEG LENGTH FROM LEFT HALF + MOVNS A ;GET POSITIVE LENGTH + XCTR XR,[ADD A,(C)] ;ADD STARTING LOC (R.H.) + XCTR XW,[HRRZM A,(C)] ;STORE BACK "COUNTED OUT" POINTER + POPJ P, + +;STANDARD DEVICE .STATUS ROUTINE +STDSTA: DPB A,[60300,,D] ;A HAS LH OF IOC WORD + TRO D,1_9 ;SYS BUF CAP FULL + TRNE D,1_6 ;SKIP IF INPUT + TRC D,3_9 ;TURN OFF SYS BUF CAP FULL, SET EMPTY + POPJ P, + +SUBTTL USER DEVICE + +UBPFJ==10 ;DEMAND FOREIGN JOB (BIT IN LH (DEV) FOR .OPEN (USR)) + +USROJ: TDZA J,J ;ENTRY FROM JOB DEVICE DONT GET CORE. +USRO: MOVNI J,1 ;INDICATE NOT FROM JOB OPEN + CAIA +USROOJ: MOVEI J,1 ;OJB DEVICE; EXISTING JOB OK ONLY IF %OPOJB BIT SET. + PCLT + SKIPL CORRQ(U) + PUSHJ P,UFLS ;PREVENT ATTEMPT TO CORE, PCLSR OUT, AND THINK YOU'VE WON AT SETBF1, ETC + PUSHJ P,SWTL + TREESW + JUMPE B,USRO4 ;JNAME = 0 => UNAME IS JOB SPEC. + SKIPN A ;IF UNAME=0 + MOVE A,UNAME(U) ;MAKE IT THIS JOB'S UNAME + CAME A,UNAME(U) ;SKIP IF FIRST FILE NAME IS UNAME OF OPENER + JRST USROA + CAME B,[SIXBIT /PDP10/] ;SKIP IF SECOND FILE NAME IS "PDP10" + CAMN B,[SIXBIT /PDP6/] ;OR PDP6 +IFN PDP6P,JRST PDPO + .ELSE JRST OPNL1 +USROA: CONO PI,CLKOFF + PUSHJ P,LSWPOP ;TREESW +USROB: SETZ TT, +USRO3: CAME A,UNAME(TT) + JRST AGIN + CAMN B,JNAME(TT) + JRST UFN1 ;FOUND UNAME JNAME PAIR +AGIN: ADDI TT,LUBLK + CAMGE TT,USRHI + JRST USRO3 + TLNE C,UBPFJ ;JOB MUST EXIST TO WIN IF UBPFJ SET + JRST OPNL4 + CAME A,UNAME(U) ;INFERIOR PROCEDURE MUST HAVE SAME UNAME + JRST OPNL20 + PUSH P,U +TCORS: MOVSI T,%TBNOT+%TBDTY ;DOESN'T HAVE TTY, ISN'T GIVING IT AWAY + PUSHJ P,USTRA + JRST TCORS1 ;USTRA FAILED - SEE WHY, MAYBE RETRY (U CLOBBERED) + MOVEM A,UNAME(U) + MOVEM B,JNAME(U) + MOVEM A,USYSNM(U) + MOVE TT,U + POP P,U + MOVE A,UTMPTR(U) + MOVEM A,UTMPTR(TT) + MOVE A,HSNAME(U) + MOVEM A,HSNAME(TT) + MOVE A,XUNAME(U) + MOVEM A,XUNAME(TT) + MOVEM B,XJNAME(TT) + PUSHJ P,USRST5 ;SET UP TTY STUFF + MOVSI A,400000 + SKIPGE APRC(U) + IORM A,APRC(TT) ;NEW INFERIOR IS DISOWNED IF CREATOR IS. + JUMPE J,CLKOJ1 ;RETURN HERE FOR JOB DEVICE (INDEX IN TT) + PUSHJ P,ULUP1 ;FIND AN INTERRUPT BIT FOR THE JOB. + JRST NOGO1 ;NONE => GO KILL THE JOB AND RETURN FAILURE. + CONO PI,CLKON ;NOW CAN'T FAIL TO CREATE THE JOB FOR GOOD. + HRLZ B,B + HRR B,U + MOVEM B,SUPPRO(TT) + MOVE U,TT + PUSHJ P,UFOUND ;SET UP THE OPENER'S CHANNEL. + JFCL + MOVE Q,TT + MOVEI B,1 + PUSHJ P,ACORE1 ;MAY PCLSR OUT, BUT CORE JOB WILL DO WORK ANYWAY. + SKIPA R,UUAC(U);NO CORE AVAILABLE, KILL THE JOB + JRST POPJ1 ;SUCCESS + ADDI R,IOCHNM(U) + PUSHJ P,AUCLOSE + JRST OPNL37 ;NO CORE AVAILABLE + +ULUP1: CLEARB A,T +ULUP: HRRZ E,SUPPRO(T) + SKIPN UNAME(T) ;SKIP IF VARIABLE BLOCK IN USE + JRST ULUP2 + CAIN E,(U) ;SKIP IF NOT AN INFERIOR + IOR A,SUPPRO(T) ;IOR IN INTERRUPT BIT OF INFERIOR +ULUP2: ADDI T,LUBLK ;ADVANCE TO NEXT BLOCK + CAMGE T,USRHI ;SKIP IF ALL EXAMINED + JRST ULUP ;LOOP +UFIN: MOVEI B,1 ;SELECT INT BIT +UFIN2: TLON A,(B) + JRST POPJ1 + LSH B,1 + CAIGE B,1_ + JRST UFIN2 + POPJ P, + +NOGO1: MOVSI T,BULGO+BULGOS + IORM T,APRC(TT) ;TELL THE SYS JOB TO KILL THE JOB WE JUST GOT + MOVSI T,SCLGUN + IORM T,SUPCOR + JRST OPNL5 ;DIREC FULL (TOO MANY LOSERS) + +NOGO4: SUB P,[1,,1] + JRST OPNL6 + +TCORS1: PCLT ;COME HERE FROM TCORS IF ATTEMPT TO FIND FREE JOB SLOT FAILED. + SKIPGE SJCFF ;IF THIS IS NEGATIVE, USTRA DIDN'T EVEN REQUEST MORE + JRST [ SKIPGE SJCFF + PUSHJ P,UFLS + JRST TCORS2] + MOVE TT,USRHI + CAIL TT,MAXJ*LUBLK + JRST NOGO4 ;USER MEM EXPANDED TO MAX + SKIPGE SUPCOR .SEE SCLEX ;PRESUMABLY USTRA ASKED SYS JOB FOR MORE JOB SLOTS + PUSHJ P,UFLS ;SO WAIT TILL SYS JOB ANSWERS THE REQUEST +TCORS2: CONO PI,CLKOFF ;AND SEE IF THERE ARE NOW ENOUGH SLOTS. + JRST TCORS + +USRO4: EXCH J,A ;USR: OPEN WITH JNAME=0: USE UNAME AS JOB SPEC. + JSP T,NCORUI + JFCL +IFN PDP6P,[ + CAIN J,-1 ;SPEC'D JOB IS PDP6 => OK, + JRST PDPO +] + CONO PI,CLKOFF + PUSHJ P,LSWPOP ;SOS DIELOK(J) + PUSHJ P,LSWPOP ;TREESW + MOVE TT,J + MOVE J,A +;COME HERE WHEN JOB ALREADY EXISTS, WITH CLOCK OFF AND USR IDX IN TT. +;A, B, C STILL HAVE UNAME, JNAME AND OPEN MODE. +UFN1: JUMPE J,[ADDI B,10000 ;OPENING JOB-DEVICE AND JOB EXISTS?? + JRST USROB] ;KEEP CHANGING JNAME UNTIL WE CREATE A JOB. + CAIG TT,LUBLK + JUMPL J,UFNDF ;SKIP SOME CHECKS ON SYS & CORE + JUMPG J,[MOVSI T,%OPOJB ;OJB DEVICE OPEN; IF JOB DOESN'T HAVE %OPOJB SET, + TDNE T,OPTION(TT) ;THEN IT HASN'T GIVEN PERMISSION TO BE HACKED. + SKIPL JBI(TT) ;IF IT'S ALREADY A JOB DEVICE DON'T HACK IT. + JRST [CONO PI,CLKON ;IN EITHER CASE, WAIT TILL ALL'S OK, + SKIPL JBI(TT) + PUSHJ P,UFLS + TDNN T,OPTION(TT) + PUSHJ P,UFLS + JRST USROOJ] ;THEN RE-TRY THE OPEN. + LDB T,[.BP BULGOS_22,APRC(TT)] + JUMPN T,OPNL42 + JRST CLKOJ1] ;RETURN SUCCESS TO JOBO6C. + TLNE C,UBPFJ + JRST UFNDF ;USER WANTS IT AS FOREIGN JOB + HRRZ E,SUPPRO(TT) + CAIN E,(U) + JRST UFN1C ;OPENING UP INFERIOR + SKIPGE T,APRC(TT) + SKIPL SUPPRO(TT) ;UNLESS IT'S A TOP-LEVEL DISOWNED JOB, + JRST UFNDF ;THEN FOREIGN JOB + PUSHJ P,UFN2B ;REOWN DISOWNED TREE + POPJ P, ;CAN'T + JRST UFOUND ;DID + +UFN1C: MOVE U,TT ;OPENING PROCEDURE IMMEDIATE SUPERIOR OF PROCEDURE BEING OPENED + JRST UFOUND + +; +; REOWN A DISOWNED PROCEDURE TREE +; + +NREOWN: TLNN R,%CLSFU ;MUST BE A FOREIGN USER CHANNEL + JRST OPNL34 + CONO PI,CLKOFF + HLRZ TT,H + SKIPGE T,APRC(TT) + SKIPL SUPPRO(TT) + JRST OPNL31 ;TO A TOP-LEVEL DISOWNED JOB + HRLM R,(P) + PUSHJ P,UFN2B ;REOWN THE JOB (TURNS CLOCK ON) + POPJ P, ;FAILED + HLRZ R,(P) ;TURN THE CHANNEL INTO AN INFERIOR CHANNEL. + MOVNI T,FUWIDN-UWIDN + ADDM T,(R) + JRST POPJ1 + +;REOWN JOB TT POINTS TO, ITS APRC IS IN T. SKIPS IF SUCCESSFUL. +;CALL WITH CLKOFF, WILL TURN IT ON. +UFN2B: TLNE T,BULGOS + JRST OPNL42 ;CAN'T REOWN JOB WHICH IS LOGGING OUT. + SKIPGE APRC(U) ;IF REOWNING JOB IS DISOWNED, PROHIBIT SO THAT + JRST OPNL31 ;IT DOESN'T REOWN ITSELF AND SCREW THINGS UP + PUSHJ P,ULUP1 ;FIND AN INTERRUPT BIT FOR IT. (IN B) + JRST OPNL5 ;WE HAVE 8 INFERIORS ALREADY. + AOS (P) ;GOING TO WIN + SETOM DLSRCH ;INHIBIT SCHEDULING + CONO PI,CLKON ;TURN CLOCK BACK ON, THIS MAY TAKE A WHILE + MOVSI A,BUMRTL ;DOOMED DETACHED JOBS ARE RESCUED BY REOWNING. + ANDCAM A,APRC(TT) + MOVE A,UNAME(U) ;PICK UP NEW UNAME + SETCM D,APRC(U) + TLZ D,#400000 ;SIGN OF D SET IFF REOWNER ISN'T DISOWNED. + MOVE J,UTMPTR(U) ;PICK UP NEW USER RESOURCE POINTER + HRR D,J + SUBI J,USRRCE ;GET NEW CONSOLE # + CAIL J,NCT ;IF NEW TREE STILL HAS NO TTY, + MOVEI J,%TINON ;"DISOWNED" TTY CHNLS SHOULD REMAIN SUCH +;HERE, A HAS UNAME, D HAS ,,UTMPTR, J HAS CONSOLE # OR %TINON, +;U HAS REOWNER, TT HAS JOB BEING REOWNED. +UFN2A: PUSH P,B ;SAVE INTERRUPT BIT +UFN3: MOVEM A,UNAME(TT) ;SET TO NEW UNAME + HRRZM D,UTMPTR(TT) ;SET TO NEW USER RESOURCE POINTER + MOVEI R,IOCHNM(TT) + PUSHJ P,CHSCAN + PUSHJ P,UFN3ZZ + HLLZ T,D ;LH(D) HAS 0 IF REOWNER DISOWNED, ELSE 400000 + ANDCAM T,APRC(TT) ;MARK AS NOT DISOWNED IF REOWNER ISN'T DISOWNED. +UFNL3: MOVE B,JNAME(TT) ;PICK UP CURRENT JNAME + MOVEI E,0 ;LOOP ON ALL USERS +UFNL1: CAMN A,UNAME(E) ;SKIP ON NOT SAME UNAME + CAME B,JNAME(E) ;SKIP ON SAME UNAME-JNAME + JRST UFNL2 ;NOT SAME NAME AND/OR VAR BLK NOT IN USE + JRST UFN7 ;NAME CONFLICT, RESOLVE +UFNL2: ADDI E,LUBLK + CAMGE E,USRHI + JRST UFNL1 + MOVEI E,0 ;INITIALIZE FOR LOOP TO LOOK FOR INFERIORS AND DUPLICATE NAMES +UFN4: SKIPN UNAME(E) ;SKIP IF VAR BLOCK IN USE + JRST UFN5 ;TRY NEXT + HRRZ I,SUPPRO(E) ;PICK UP SUPERIOR POINTER OF BLOCK BEING EXAMINED + CAIN I,(TT) ;SKIP IF NOT INFERIOR + JRST UFN6 ;INFERIOR, PSEUDO-RECURSE +UFN5: ADDI E,LUBLK ;ADVANCE TO NEXT BLOCK + CAMGE E,USRHI ;SKIP IF ALL EXAMINED + JRST UFN4 ;LOOP + SKIPGE SUPPRO(TT) ;SKIP IF NOT BACK TO TOP + JRST UFNX ;BACK TO TOP LEVEL + MOVE E,TT ;POP BACK UP + HRRZ TT,SUPPRO(E) ;TO PREVIOUS LEVEL + MOVE B,JNAME(TT) ;RESTORE B + JRST UFN5 ;PROCEED AT PREVIOUS LEVEL + +UFNX: POP P,B + HRLM B,SUPPRO(TT) + HRRM U,SUPPRO(TT) ;SET UP SUPERIOR POINTER IN TO LEVEL DISOWNED + SETZM DLSRCH ;RE-ENABLE SCHEDULING + MOVE U,TT + POPJ P, + +UFN6: MOVE TT,E ;PSEUDO-RECURSE + JRST UFN3 ;START UP ON LOWER LEVEL + +UFN7: CAMN E,TT ;SKIP UNLESS FOUND SELF + JRST UFNL2 + ADDI TT,JNAME ;SET UP ARG TO SIXAOS + PUSHJ P,SIXAOS ;INCREMENT JNAME + SUBI TT,JNAME ;RESTORE TT + JRST UFNL3 ;RESTART LOOP + +;RESUSCITATE TTY CHNLS +UFN3ZZ: HRRZ Q,(R) + CAIL Q,TYIDN + CAILE Q,TYOBN + POPJ P, ;NOT A TTY CH + HLRZ Q,(R) + TRNN Q,%TICNS + POPJ P, ;NOT CONSOLE + CAIE J,%TINON + AOS TTNTO(J) + DPB J,[$TIIDX,,(R)] + POPJ P, + +UFOUND: HLRZS C ;U HAS INF PROC + HRL A,U + MOVE U,USER + HRRZ R,UUAC(U) + ADDI R,IOCHNM(U) ;CLOBBERED BY CORE + JSP Q,OPSLC3 + UWIDN,,UWODN + UBIDN,,UBODN + +UFNDF: TLNE C,1 + JRST OPNL12 ;ATTEMPTED OUTPUT + LDB A,[.BP BULGOS_22,APRC(TT)] + JUMPN A,OPNL42 ;USER GOING AWAY + HRL A,TT + JSP Q,OPSLD1 + FUWIDN,,FUBIDN + +USRST: PUSHJ P,AUCL2 ;.RESET SIMULATES CLOSING AND REOPENING + POPJ P, + CONO PI,CLKON + PUSHJ P,1USTOP + EXCH U,A ;BUT WITH LESS OVERHEAD + PUSH P,A + PUSHJ P,IODCL + MOVEI B,BULGOS ;WE'RE NOT REALLY TRYING TO KILL THE INFERIOR, + ANDCAM B,APRC(U) ;SO DON'T LET OTHERS THINK HE'S BEING KILLED. + MOVE Q,U + SETZ B, + EXCH U,(P) + PUSHJ P,ACRF1 ;FLUSH ALL OF CORE + BUG +USRST1: MOVEI B,1 + MOVE Q,(P) + PUSHJ P,ACRF1 ;THEN GET 1 PAGE + JRST [ PUSHJ P,UDELAY + JRST USRST1] + EXCH U,(P) + MOVSI T,%TBNOT+%TBDTY + MOVEM T,TTYTBL(U) + MOVE J,U + EXCH U,(P) + PUSHJ P,MPLDJ + XCTR XW,[CLEARM 0] + MOVEI T,1 + XCTR XBRW,[BLT T,1777] + PUSHJ P,MPLDZ + EXCH U,(P) + PUSHJ P,LOGUSE + CONO PI,CLKOFF + PUSHJ P,USRST2 + CONO PI,CLKON + PUSHJ P,USRST4 ;SHOULD SKIP + BUG + POP P,A + EXCH U,A + MOVE TT,A +USRST5: MOVE A,TTSTSV(U) ;INITIALIZE SAVED TTYSET OF NEW JOB EQUAL TO CREATOR'S. + SKIPL B,TTYTBL(U) ;NOTE THAT THE WHEREABOUTS OF THE CREATOR'S TTYSET + MOVE A,TTYST1(B) ;DEPENDS ON WHETHER HE HAS THE TTY NOW. + MOVEM A,TTSTSV(TT) + MOVE A,TTSTSV+1(U) + SKIPL B + MOVE A,TTYST2(B) + MOVEM A,TTSTSV+1(TT) + MOVEI A,(TT) ;RH OF NEW JOB'S SAVED TTYSTS IS HIS INDEX. + HRLI A,%TSCNS ;NOW CONSTRUCT THE LH. + MOVE B,UTMPTR(TT) ;TO DO THAT, FIND THE TREE'S TTY NUMBER + MOVE B,TTYOPT-USRRCE(B) ;TO FIND THE TTY'S TTYOPT WORD, + TLNE B,%TOROL ;WHICH TELLS HOW TO INIT THE BITS IN THE TTYSTS. + TLO A,%TSROL + TLNN B,%TOMOR + TLO A,%TSMOR + TLNE B,%TOSA1 + TLO A,%TSSAI + MOVEM A,TTSTSV+2(TT) + POPJ P, + +;.CALL USRMEM +; ARG 1 JOB WHOSE MEMORY SHOULD BE READ OR WRITTEN +; ARG 2 ADDRESS TO READ OR WRITE +; ARGS 3,4 LIKE USRVAR, TTYVAR +; VAL 1 PREVIOUS CONTENTS OF LOCATION +; VAL 2 NEW CONTENTS OF LOCATION (SAME AS PREVIOUS IF NOT WRITING). +; (NOT VALID IN BLOCK MODE) + +; BIT 1.1 IF SET, THEN IF PAGE ISN'T READABLE OR WRITEABLE, GIVE AN MPV +; OR PURE INTERRUPT TO THE JOB BEING REFERENCED. +; BIT 2.9 IF SET, ALLOWS US TO WRITE IN ANY JOB. + +NUSRMEM: + MOVE J,A + JSP T,NCORUI + JRST NUSRM1 ;WE CAN SURELY WRITE. + MOVE H,CTLBTS(U) + CAIGE W,3 ;ELSE, IF WE WANT TO WRITE, + TRNE H,1 ;OR WANT TO GIVE THE REFERENCED JOB INTERRUPTS, + TRNE H,400000 ;THEN UNLESS WE ARE FORCING IT, + JRST NUSRM1 + JSP T,NCORWR ;SEE IF IT IS A JOB WE ARE ALLOWED TO WRITE IN. + JRST OPNL31 +NUSRM1: MOVE H,CTLBTS(U) + CAIE J,-1 + CAIG J,LUBLK ;CAN'T GIVE SYS OR CORE JOBS INTERRUPTS, OR PDP6. + TRNN H,1 + CAIA + JRST OPNL31 +IFN PDP6P,[ + CAIN J,-1 + JRST NUSRMS +];PDP6P + CAILE J,LUBLK + CAMN J,U + JRST NUSRMS + MOVE A,J ;IF TARGET JOB ISN'T SELF OR PDP6 + PUSHJ P,RPCLSR ; OR SYS OR CORE, STOP IT. + PUSHJ P,SOSSET + USTP(J) +NUSRMS: PUSHJ P,NUSRM2 ;DO THE WORK + POPJ P, ;LOST, OPNL HAS LSWCLR'ED + JRST LSWCJ1 ;POSSIBLY UNLOCK USTP, DIELOK AND TAKE SUCCESS RETURN + +NUSRM2: PUSHJ P,VARCAL ;E:=ADDR, D:=DATA, W:=INSTRUCTION + HRRZS E + CAIGE E,20 + JRST NUSRM6 ;ACS ALWAYS SWAPPED-IN AND ACCESSIBLE + PUSH P,U + MOVE U,J + LDB A,[121000,,E] ;GET PAGE # IN A AND REF'D JOB IN U. +IFE PDP6P, PUSHJ P,UPLC +IFN PDP6P,[ + PUSHJ P,[ CAIE J,-1 ;SKIP IF PDP6 + JRST UPLC ;DECODE THEM FOR ORDINARY JOB. + CAIL A,LPDP6M + TDZA T,T ;FOR PDP6, MOST PAGES DON'T EXIST, + MOVE T,[002200,,[600000]] ;AND THE REST ARE WRITABLE. + POPJ P,] +];PDP6P + POP P,U + LDB A,T ;GET PAGE ACCESS HALFWORD. + TRNN A,600000 ;IF PAGE SWAPPED OUT, PUT ACCESS BITS IN PLACE THEY WOULD BE + LSH A,16. ; FOR AN IN-CORE PAGE. + JUMPE A,NUSRM9 ;LOSE IF NO PAGE THERE + TRNN A,400000 ;OR IF WE ARE TRYING TO WRITE THE WORD AND PAGE IS READ-ONLY. + JUMPN W,NUSRM8 +NUSRM6: PUSHJ P,MPLDJ ;NOW LOAD MAP OF JOB IN J + HRLI E,(SKIP) ;GET ACCESS TO DATA WORD, SWAP IN PAGE + SKIPE W + HRLI E,(MOVES) +NUSRM4: CONO PI,CLKOFF ;CLK OFF SO ONCE IN CAN'T SWAP OUT AGAIN + XCTRI XRW,E ;NOT GETTING BENEFIT OF USUAL PCLSR BEFORE + JRST NUSRM5 ;SWAP OUT FEATURE SINCE IT'S ANOTHER JOB + PUSHJ P,TPFLT + JRST NUSRM4 + +NUSRM5: UMOVE B,(E) ;NOW THAT PAGE IS IN, GET OLD CONTENTS + MOVE A,B ;IN A AND B + JUMPE W,NUSRM3 + HRRI W,B ;IF WRITING, + XCT W ;EXECUTE USER'S INSN., MODIFYING 2ND VALUE IN B, + TRNN J,-1 ;SYSTEM JOB? + JRST OPNL31 ;******* WRITING SYS, TURN INTO .SETLOC ******* + UMOVEM B,(E) ;AND STORE IT BACK INTO REF'D JOB. +NUSRM3: PUSHJ P,MPLDZ ;RESTORE NORMAL PAGE MAP, TURN CLKON. + JRST POPJ1 ;SUCCESS + +NUSRM8: SKIPA T,[%PIWRO] ;HERE IF TRYING TO WRITE IN READ ONLY PAGE. +NUSRM9: MOVEI T,%PIMPV ;HERE IF ACCESSING NONEXISTENT PAGE. + TRNN H,1 ;SKIP IF TO GIVE INTERRUPT + JRST OPNL32 + CAMN J,USER + JRST UUOERR ;INTERRUPT TO SELF + IORM T,PIRQC(J) ;INTERRUPT OTHER USER + JRST OPNL32 ;CAN'T GET THAT ACCESS TO PAGE. + +;COMMENTS BELOW APPLY TO UBI IN MANY CASES. FOR UBO, TRANSFER GOES THE +;OTHER DIRECTION + +UBO: MOVNI I,1 + JRST UBIL + +UBI: MOVEI I,0 ;SIGNAL UBI + +UBIL: JUMPL C,UBIA + XCTR XRW,[MOVES TT,(C)] ;MAKE SURE WRITE CYCLES WILL WIN +UBIB: TRNE A,200000 ;SKIP UNLESS 6 + MOVNI A,1 ;SO CAILE BELOW WILL SKIP OVER SUSTPR AMONG OTHER REASONS + CAILE A,LUBLK ;SKIP ON SYS JOB, CORE JOB, PDP6 OR JOB ALREADY STOPPED + PUSHJ P,SUSTPR ;RANDOM JOB STOP + JUMPGE TT,UBI4 ;THRU + TLO A,400000 ;INDICATE ALREADY STOPPED SO WONT TRY IT AGAIN + HLRO B,TT + MOVNS B ;COUNT TO BE XFERRED + HRLZ E,IOCHST-IOCHNM(R) ;EXAMINED USER ADDRESS + HRR E,TT ;FROM,,TO (INFERIOR ADR,,SUPERIOR ADR) + HLRZ Q,E + TLNE A,200000 + JRST UBI5A ;PDP6 +UBI5: CAIGE Q,20 ;INF ADR IN Q + JRST UBI3 ;READ AC + HRRZ J,A ;SET UP UMAPS WORD + TRZE E,400000 + TLOA J,%UMMPL ;TO HI PG, HACK OUR LOW PG + TLO J,%UMMPU ;TO LOW PG, HACK OUR HI PG + TLZE E,400000 + TLOA J,%UMLTU ;TO POINT TO HIS UPPER + TLO J,%UMUTL ;TO POINT TO HIS LOWER + TLNN J,%UMMPU+%UMUTL ;MAPPING HIS UPPER WITH OUR LOWER? + JRST UBI3A ;YES MAKE SURE NOT SCREWED BY AC PNTR +UBI3B: PUSHJ P,MPLD1 + TRZ Q,400000 + MOVNS Q ;LIMIT SIZE OF XFER TO MIN OF DESIRED + ADDI Q,400000 ;DIST OF TO ADR FROM SEG BOUNDARY + CAMLE B,Q + HRRZ B,Q + MOVNI Q,(E) ;AND DIST OF FROM ADR FROM SEQ BOUNDARY + ADDI Q,400000 + CAMLE B,Q + HRRZ B,Q + TLNN J,%UMMPL ;BUGGER ADDRESSES SO RIGHT DBRS WILL BE USED + TLOA E,400000 ;SET FROM ADR TO HI PG + TRO E,400000 ;SET TO ADR TO HI PG + SKIPE I ;SKIP ON UBI + MOVSS E ;UBO, XFERR OTHER DIRECTION + MOVE Q,E ;SAVE COPY OF BLT PNTR + ADDI B,(E) ;GET LA +1 +UBI3H: XCTRI XBRW,[BLT E,-1(B)] ;XFERR DATA +UBI3K: MOVEI E,(B) ;NO FAULT, SIMULATE STORE BACK OF BLT PNTR AFTER COMP OF BLT (RH ANYWAY) +UBI3L: PUSH P,J + PUSHJ P,MPLDZ ;RETURN TO NORMAL MAP TO STORE BACK USER PNTR + POP P,J ;SAVE PREV MAP FOR EVENTUAL USE + SUBM E,Q ;FIGURE OUT HOW MANY WDS ACTUALLY XFERRED + HRRZS Q +UBI3E: HRLS Q ;# WDS TRANSFERRED,,SAME + JUMPL C,UBIC ;UPDATE USER PNTR + XCTRI XRW,[ADDM Q,(C)] + JRST .+2 + BUG ;SHOULD HAVE ALREADY CHECKED THIS +UBID: ADD Q,IOCHST-IOCHNM(R) ;UPDATE INFERIOR PNTR + HRRM Q,IOCHST-IOCHNM(R) ;WRAPPING AROUND IF PASS 1,,0 + TLZ B,-1 + CAIN B,(E) ;WAS THERE A FAULT? + JRST UBIL ;NO, LOOP + PUSHJ P,UBI4 ;UNSTOP THE JOB. + PUSHJ P,MPLD1 ;RESTORE TO FROB AT TIME OF FAULT +UBI3C: PUSHJ P,TPFLT + PUSHJ P,MPLDZ + JRST UBIL + +UBI4: TLNN A,200000 ;SKIP ON REALLY PDP6 + TLZ A,400000 ;FLUSH RANDOM BIT SO COMPARE WILL WORK + CAILE A,LUBLK + JRST UPCLSR + POPJ P, + +UBMCK1: PUSHJ P,UBI4 + JRST IOADC + +UBIA: TRNE C,777760 + BUG + MOVE TT,(C) + JRST UBIB + +UBIC: TRNE C,777760 + BUG + ADDM Q,(C) + JRST UBID + +UBI5A: CAIL Q,400000 + JRST UBMCK1 + JRST UBI5 + +UWO: SKIPGE C + SKIPA D,(C) + UMOVE D,(C) + TDZA I,I +UWI: SETO I, ;0 FOR OUTPUT, -1 FOR INPUT. + TRNE A,200000 + MOVNI A,1 ;-1 MEANS PDP6. + CAMN A,USER + HRLI A,-1 ;DON'T STOP SELF + CAIG A,LUBLK + JRST UWI1 ;SYS, CORE, SELF, OR PDP6 + PUSHJ P,SUSTPR + PUSHJ P,SOSSET ;MIGHT TAKE PAGE FAULT AND GET PCLSRED + USTP(A) +UWI1: HRRZ E,IOCHST-IOCHNM(R) + HRRZ J,A + PUSHJ P,MPLDJ ;MAP JOB BEING IOT'ED FROM. + XCTR XRW,[ MOVE W,(E) + MOVEM D,(E)]+1(I) + AOS IOCHST-IOCHNM(R) ;ADVANCE ACCESS POINTER + CAILE A,LUBLK + PUSHJ P,LSWPOP + JRST MPLDZ + +UBI3A: TLNE E,777760 ;SKIP ON XFERRING FROM AC AREA, HI TO HI + JRST UBI3B ;NO OK + JUMPN I,UBO3A ;UBO + PUSHJ P,MPLDJ + XCTRI XR,[MOVE B,(Q)] ;PICK UP WD + JRST .+2 ;OK + JRST UBI3C ;TAKE FAULT + PUSHJ P,MPLDZ ;BACK TO NORMAL MAP + HRRZ E,TT ;TO ADR + JRST UBI3D + +;USR DEV IOT STOP ROUTINE +USUSTP: SOS USTP(A) +SUSTPR: MOVSI T,BCSTOP+BUCSTP + TDNE T,USTP(A) ;WAIT TILL NOT BEING SHUFFLED + PUSHJ P,UFLS + PUSHJ P,RPCLSR ;AOS'ES USTP + MOVSI T,BCSTOP+BUCSTP + TDNE T,USTP(A) + JRST USUSTP + POPJ P, + +UBI3: ADDI Q,AC0S(A) + JUMPN I,UBO3 ;UBO + TLNE A,200000 + TDZA B,B ;READ PDP6 AC + MOVE B,(Q) ;READ NORMAL AC +UBI3D: XCTRI XW,[MOVEM B,(E)] + JRST .+2 + JRST UBI3C ;TAKE FAULT +UBI3G: MOVEI Q,1 ;1 WD XFERRED + HRRZ B,E ;FAKE OUT FAULT TEST + JRST UBI3E + +UBO3: TLNE A,200000 + JRST UBI3G ;TRYING TO WRITE PDP6 AC IGNORE + XCTRI XR,[MOVE B,(E)] + JRST .+2 + JRST UBI3C + MOVEM B,(Q) + JRST UBI3G + + +UBO3A: XCTRI XR,[MOVE B,(TT)] + JRST .+2 + JRST UBI3C ;TAKE FAULT + PUSHJ P,MPLDJ ;MAP HIM. + XCTRI XW,[MOVEM B,(Q)] + JRST .+2 + JRST UBI3C + PUSHJ P,MPLDZ ;BACK TO NORMAL + JRST UBI3G + +SUBTTL CORE LINK DEVICE + +EBLK +CLVBEG: NCLCH +CLSYN: BLOCK NCLCH ;SYSTEM NAME ;0=>VARIABLES FREE +CLN1: BLOCK NCLCH ;FN1 +CLN2: BLOCK NCLCH ;FN2 +CLUSR: REPEAT NCLCH,-1 ;LH=WRITING USER ;RH=READING USER ;-1=>NOT OPEN THAT HALF +CLRAC: BLOCK NCLCH ;4.9=LOCKED BY CORE ALLOCATOR + ;4.8=VERY SLOW CLOCK ROUTINE CONSIDERING FLUSHING THIS BUFFER + %CAFLS==100000 ;4.7=INPUT CLOSED, TURN OUTPUT INTO NUL DEVICE + %CA==1,,500000 ;RH=UT BUFFER NUMBER (IOBFT ADR) + +CLOSW: -1 ;USER LOCK TO STOP MORE THAN ONE PERSON FROM SIMULTANEOUSLY MODIFYING + 0 ;THE CORE LINK VARIABLES +CLVEND==.-1 +BBLK + +;FORMAT OF CORE LINK 200 WORD BUFFER +; +CLBVSP==8 +CLBCHS==100. +CLBEOF==/5 +IFG CLBVSP+CLBCHS+CLBEOF-128.,.ERR CLBXXX LOSSAGE + +; +;0: CHARACTER COUNT +;1&2: READ AND WRITE CHARACTER OR WORD POINTERS +;3&4: READ AND WRITE EOF POINTERS +;CLBVSP TO CLBVSP+CLBCHS-1: CHARACTERS OR WORDS +;CLBVSP+CLBCHS UP: EOF BITS STORED AS SEVEN FIVE BIT BYTES PER WORD, +; EACH BIT CORRESPONDING TO A CHARACTER POSITION. + +CLAO: SKIPA J,[2] ;CLA .OPEN (TO ANSWER A CLI INTERRUPT) +CLIO: MOVNI J,1 ;CLI .OPEN (INTERRUPTS USER SPECIFIED BY FILE NAME) + JRST CLI2 + +CLUO: TDZA J,J ;CLU .OPEN +CLOO: MOVEI J,1 ;CLO .OPEN +CLI2: JUMPL C,CLFDEL ;JUMP IF AN .FDELE + PUSHJ P,FLDRCK + JRST CLO1 ;NOT FILE DIRECTORY + MOVEI J,2 + JRST LISTF7 + +CLFDEL: MOVEI J,3 +CLO1: PUSHJ P,SWTL ;SEIZE SWITCH TO STOP VARIABLES FROM CHANGING UNDER YOU + CLOSW + LDB H,[220100,,C] ;DIRECTION BIT + JUMPL J,CLOO5 +CLOO5B: MOVE Q,USYSN1(U) ;PICK UP SNAME + MOVSI I,-NCLCH + CAIN J,2 ;SKIP UNLESS CLA + JRST CLO1A ;JUMP IF CLA .OPEN + CAIGE J,0 +CLO1A1: MOVE Q,[SIXBIT/_CLI_/] +CLOL: CAMN Q,CLSYN(I) ;LOOK FOR SNAME, FN1, & FN2 + CAME A,CLN1(I) + JRST CLOO1 + CAME B,CLN2(I) + JRST CLOO1 + JUMPL J,OPNL23 ;"FILE LOCKED" IF ALREADY EXISTS, FOR CLI:. + CAIN J,3 ;SKIP UNLESS DELETE + JRST CLO1D ;FOUND FILE TO DELETE +CLO1A6: LDB TT,CLOOT1(H) + CAIE TT,-1 + JRST OPNL23 ;ALREADY OPEN THIS DIRECTION (FILE LOCKED) + HRRZ TT,CLRAC(I) + LDB Q,[IOSA,,IOBFT(TT)] + LSH Q,6 +CLOX: DPB U,CLOOT1(H) ;STORE USER INDEX + MOVSI TT,200000 + ANDCAM TT,CLRAC(I) ;CLEAR VERY SLOW CLOCK BIT + PUSHJ P,LSWPOP ;RELEASE SWITCH + HRL A,I + LDB C,[220300,,C] + SKIPGE J + PUSHJ P,CLOX1 ;FOR CLI:, PUT OUR UNAME AND JNAME INTO BUFFER. + MOVEI TT,44 ;WORD + TRNN C,6 + MOVEI TT,7 ;UNIT ASCII + ADD Q,H ;OFFSET FOR DIRECTION + DPB TT,[300600,,1(Q)] ;SET UP ITEM POINTER + MOVEI TT,5 ;WORD + TRNN C,6 + MOVEI TT,1 ;UNIT ASCII + DPB TT,[300600,,3(Q)] ;SETUP EOF POINTER + JSP Q,OPSLC7 ;SET UP IOCHNM OF USER + DCLUAI,,DCLUAO ;UNIT ASCII INPUT ;UNIT ASCII OUTPUT + DCLBI,,DCLBO ;BLOCK INPUT ;BLOCK OUTPUT + DCLUBI,,DCLUBO ;UNIT BINARY INPUT ;UNIT BINARY OUTPUT + DCLBI,,DCLBO + +CLOX1: MOVEI TT,44 ;CHANGE OUTPUT BYTE SIZE TO 36. + DPB TT,[300600,,2(Q)] + MOVEI TT,5 ;WHICH INVOLVES STORING 5 CHARACTERS OF EOF BITS AT ONCE. + DPB TT,[300600,,4(Q)] + PUSH P,C + HRROI C,TT + MOVE TT,UNAME(U) + PUSHJ P,CLOXO ;NOW WE CAN IOT WORDS OUT, EVEN IF CHANNEL IS ASCII MODE. + SUBI Q,1 + MOVE TT,JNAME(U) + PUSHJ P,CLOXO + SOJA Q,POPCJ ;NOW RETURN, AND SET UP THE CORRECT BYTE SIZES. + +CLOO1: AOBJN I,CLOL ;LOOP FOR ALL SETS OF CORE LINK VARIABLES + CAIE J,1 + JUMPGE J,OPNL4 ;CLA, CLU DELETE LOSE + MOVSI I,-NCLCH +CLOO3: SKIPN CLSYN(I) ;LOOK FOR FREE VARIABLES TO CREATE FILE + JRST CLOO2 + AOBJN I,CLOO3 + JRST OPNL5 ;GIVE DIREC FULL ERROR + +CLOOT1: 2200,,CLUSR(I) ;READING + 222200,,CLUSR(I) ;WRITING + +CLOO2: MOVEM A,CLN1(I) ;SET UP VARIABLES + MOVEM B,CLN2(I) + MOVEI D,SCNCLO(I) ;SYS CHNL NO + PUSHJ P,TCALL ;GET 200 WORD BUFFER + JRST IUTCONS + JRST CLOO4 ;NO MEM AVAIL + MOVEM Q,CLSYN(I) ;DONT SET UP SYS UNTIL MEM AVAIL + HRRM A,CLRAC(I) + LDB Q,[IOSA,,IOBFT(A)] ;SET UP BUFFER + LSH Q,6 + SETZM (Q) ;CHAR COUNT + MOVE TT,Q + ADDI TT,CLBVSP ;SET UP BUF POINTERS + MOVEM TT,1(Q) + MOVEM TT,2(Q) + HRLI TT,440000 + ADDI TT,CLBCHS ;SET UP EOF POINTERS + MOVEM TT,3(Q) + MOVEM TT,4(Q) + JRST CLOX + +;NO MEMORY AVAILABLE FOR 200-WD BUFFERS +CLOO4: AOS SWPOPR ;MAYBE SWAPPING SOMETHING OUT WILL HELP + PUSHJ P,LSWPOP ;UNLOCK CLOSW + PUSHJ P,UDELAY ;WAIT A WHILE + JRST CLO1 ;TRY AGAIN + +CLOO5: CONO PI,CLKOFF ;TURN OFF CLOCK TO STOP U&J NAMES FROM CHANGING + MOVEI Q,2*LUBLK +CLOO5A: CAMN A,UNAME(Q) ;LOOK FOR USER WHOSE NAMES MATCH THE SPECIFIED FILE NAMES + CAME B,JNAME(Q) + JRST CLOO6 + MOVEI T,%PICLI ;IF GET TO HERE, HAVE FOUND USER WITH RIGHT NAMES + TDNN T,MSKST(Q) ;SKIP IF HE HAS CLI INT DISABLED + JRST OPNL11 + IORM T,PIRQC(Q) ;GIVE USER INT + CONO PI,CLKON + JRST CLOO5B + +CLOO6: ADDI Q,LUBLK ;GO TO NEXT USER SLOT + CAMGE Q,USRHI ;SKIP IF ALL EXAMINED + JRST CLOO5A + JRST OPNL11 + +CLO1D: MOVE T,CLUSR(I) + AOJN T,OPNL23 ;FILE LOCKED + AOS (P) + MOVE A,I + PUSHJ P,CLIOTB ;NO TIMING ERROR SINCE CORE JOB WILL PCLSR USR ON + SKIPN B,SRN3(U) ;CORE LINK BEFORE MOVING BUFFER + JRST CLO1D2 + MOVEM B,CLN1(A) + MOVE B,SRN4(U) + MOVEM B,CLN2(A) + JRST LSWPOP ;CLOSW + +CLO1A: MOVE A,UNAME(U) + MOVE B,JNAME(U) + JRST CLO1A1 + +;CORE LINK .IOT SET UP ROUTINE + +CLIOTB: SKIPGE CLRAC(A) ;WAIT IF BUFFER LOCKED BY CORE ALLOCATOR + PUSHJ P,UFLS ;(DO NOT CHANGE ABOVE TO "SKIPGE TT,CLRAC(A)") + HRRZ TT,CLRAC(A) + LDB Q,[IOSA,,IOBFT(TT)] ;GET POINTER TO BUFFER + LSH Q,6 + POPJ P, + + +;CORE LINK .IOT ROUTINE FOR UNIT ASCII INPUT + +CLUAI: PUSHJ P,CLIOTB ;SETUP + MOVSI T,%CAFLS + TDNE T,CLRAC(A) + PUSHJ P,UFLS + SKIPN (Q) ;WAIT TILL CHAR COUNT NON-ZERO + PUSHJ P,UFLS +CLUAI1: MOVE J,3(Q) + ILDB I,J ;GET EOF BIT + JUMPN I,UNIEOF +CLUAIE: ILDB W,1(Q) ;GET CHARACTER + SOS (Q) ;DECREMENT BUF COUNT +CLFAXP: LDB TT,[700,,1(Q)] ;FIX UP POINTERS + CAIN TT,CLBVSP+CLBCHS-1 + PUSHJ P,CLFAX2 ;MAYBE TIME TO RING BUFFER + HLRZ TT,J ;GET BYTE POSITION AND SIZE + CAIN TT,010100 ;IF TO END OF 35-BIT WORD, ADVANCE + IBP J ;TO NEXT WORD (5-BIT BYTES 1 BIT AT A TIME) + MOVEM J,3(Q) + POPJ P, + +UNIEOF: HRROI W,EOFCH + JRST POPJ1 + +CLFAX2: LDB TT,[370500,,1(Q)] ;PICK UP TOP 5 BITS OF BYTE POSITION + JUMPN TT,CPOPJ ;NOT QUITE YET +CLFBX2: MOVEI TT,CLBVSP ;J HAS NEW EOF PNTR + DPB TT,[700,,1(Q)] ;RING CHAR POINTER + MOVEM J,3(Q) + MOVEI J,44 + DPB J,[360600,,1(Q)] + MOVEI TT,CLBVSP+CLBCHS + DPB TT,[700,,3(Q)] ;RING EOF POINTER + DPB J,[360600,,3(Q)] + MOVE J,3(Q) + POPJ P, + +;CORE LINK .IOT ROUTINE FOR UNIT ASCII OUTPUT + +CLUAO: MOVE T,CLRAC(A) + TLNE T,%CAFLS + POPJ P, + PUSHJ P,CLIOTB ;SETUP + MOVEI T,CLBCHS*5-11. + CAMGE T,(Q) ;WAIT TILL THERE IS SPACE IN BUF + PUSHJ P,UFLS + MOVE J,4(Q) + SKIPGE C + SKIPA B,(C) ;GET CHAR FROM EXEC + UMOVE B,(C) ;GET CHAR FROM USER + MOVEI TT,0 + IDPB TT,J ;INDICATE NOT AN EOF + IDPB B,2(Q) ;STORE IN BUF + MOVEI TT,1 ;GET MASK FOR LOW ORDER BIT + ANDCAM TT,@2(Q) ;FLUSH IN CURRENT WORD +CLCWU2: AOS (Q) ;INCREMENT BUF COUNT + MOVEI I,0 ;FAKE OUT EOF TEST + AOJA Q,CLFAXP ;FAKE OUT CLFAXP AND FIX UP POINTERS + + +CLBI: JSP W,WRDBTI ;BLOCK INPUT. + +;CORE LINK .IOT ROUTINE FOR UNIT BINARY INPUT + +CLUBI: PUSHJ P,CLIOTB ;SETUP + MOVSI T,%CAFLS + TDNE T,CLRAC(A) + PUSHJ P,UFLS + MOVEI T,5 + CAMLE T,(Q) ;WAIT TILL A WORD IS AVAILABLE + PUSHJ P,UFLS +CLUBI1: MOVE J,3(Q) + ILDB I,J ;GET EOF BITS + JUMPN I,CLUBIF ;JUMP ON EOF +CLUBIE: ILDB W,1(Q) ;GET WORD +CLCRB2: MOVNI T,5 + ADDB T,(Q) ;DECREMENT COUNT + JUMPGE T,CLFBXP + SETZM (Q) ;CAME FROM CLCLRL WITH PARTIAL WORD IN BUFFER +CLFBXP: JRST CLFAXP + +CLUBIF: TROE I,20 ;SKIP IF EOF NOT ON FIRST CHAR OF WORD + JRST POPJ1 + DPB I,J ;SET EOF ON FIRST CHAR + MOVE J,1(Q) + ILDB W,J ;PICK UP WORD WITH EOF IN MIDDLE + POPJ P, + +;CORE LINK .IOT ROUTINE FOR UNIT BINARY OUTPUT + +CLUBO: MOVE T,CLRAC(A) + TLNE T,%CAFLS + POPJ P, + PUSHJ P,CLIOTB ;SETUP +;CLI: OPEN CALLS HERE TO OUTPUT UNAME AND JNAME. +CLOXO: MOVEI T,CLBCHS*5-11. + CAMGE T,(Q) ;WAIT TILL THERE IS SPACE FOR A WORD + PUSHJ P,UFLS + MOVE J,4(Q) + SKIPGE C + SKIPA B,(C) ;GET WORD FROM EXEC + UMOVE B,(C) ;GET WORD FROM USER + MOVEI TT,0 + IDPB TT,J ;INDICATE NOT AN EOF + IDPB B,2(Q) ;STORE IN BUF +CLCWB2: MOVEI TT,5 + ADDM TT,(Q) ;INCREMENT COUNT + AOJA Q,CLFAXP ;FAKE OUT CLFBXP AND FIX UP POINTERS + + +;CORE LINK .IOT ROUTINE FOR BLOCK OUTPUT + +CLBO: MOVE I,C ;SAVE A POINTER TO USERS BLKO POINTER + XCTR XR,[SKIPL H,(I)] ;PICKUP BLKO POINTER + POPJ P, + SKIPA E,H ;SECOND COPY, ALSO FLAG TO CLBIN +CLBI2: UMOVEM E,(I) ;TO INFORM USER & IN CASE YOU ARE PCLSR'ED + HRRZ C,E + PUSHJ P,CLUBO ;TRANSFER ONE WORD + AOBJN E,CLBI2 ;TRY FOR NEXT +CLBI3: UMOVEM E,(I) ;COUNT EXHAUSTED OR EOF + POPJ P, + +;CORE LINK .CLOSE ROUTINE FOR BINARY OR BLOCK OUTPUT + +CLCLWB: PUSHJ P,CLCWC ;STORE EOF BITS FOR WORD + JRST CLCWU6 ;NO ROOM SO LAST MUST HAVE BEEN EOF HACK SO FLUSH + IBP 2(Q) ;KEEP WORD POINTER IN STEP + PUSHJ P,CLCWB2 ;FIX UP COUNT AND POINTERS +CLCWU6: MOVNI B,1 + DPB B,[222200,,CLUSR(A)] ;OBLITERATE USER INDEX + MOVSI B,%CAFLS + ANDCAM B,CLRAC(A) + JRST LSWPOP ;RELEASE SWITCH + +;CORE LINK .CLOSE ROUTINE FOR UNIT ASCII OUTPUT + +CLCLWU: PUSHJ P,CLCWC ;STORE EOF BIT FOR CHAR + JRST CLCWU6 + MOVEI TT,EOFCH + IDPB TT,2(Q) ;STORE AN EOF CHAR + PUSHJ P,CLCWU2 ;FIX UP COUNT AND POINTERS + SOS Q ;CLCWU2 AOJAS + LDB TT,[360600,,2(Q)] + SOJE TT,CLCWU6 ;JUST FILLED A WHOLE WORD => STOP PADDING. + PUSHJ P,LSWPOP ;ELSE PAD ONCE MORE. + JRST CLCLWU + + +;COMMON SUBROUTINE FOR CORE LINK OUTPUT .CLOSE ROUTINES + +CLCWC: PUSHJ P,SWTL ;LOCK SWITCH (IF SIGN OF CLRAC IS EVER REALLY USED, + CLOSW ;THIS MIGHT CAUSE A DEADLY EMBRACE). + PUSHJ P,CLIOTB ;SETUP + MOVEI T,CLBCHS*5-5. + CAMGE T,(Q) ;WAIT FOR THERE TO BE ROOM + POPJ P, + MOVE J,4(Q) + MOVNI TT,1 + IDPB TT,J ;SET EOF BIT(S) + JRST POPJ1 + +;CORE LINK .CLOSE ROUTINE FOR INPUT + +CLO1D2: SETZM CLSYN(A) ;FREE VARIABLES + HRRZS A,CLRAC(A) ;CORE LINK NO LONGER IN USE + PUSHJ P,BRTN ;RETURN BUFFER TO FREE STATE + JRST LSWPOP + +CLISTA: PUSHJ P,CLIOTB ;CORE LINK INPUT STATUS + SKIPN J,(Q) ;COUNT + TRO D,1_10. ;SYS BUF CAP EMPTY + CAIL J,CLBCHS*5-5 + TRO D,1_9 ;SYS BUF CAP EMPTY + POPJ P, + +CLCLRA: TDZA C,C ;UNIT ASCII +CLCLRB: MOVNI C,1 ;IMAGE OR BLOCK (I.E. WORDS) + PUSHJ P,CLIOTB + PUSHJ P,SWTL + CLOSW +;FLUSH ALL REAL DATA +CLCLRL: SKIPN (Q) ;SKIP IF BUFFER CONTAINS DATA, READ IT UNTIL EOF + JRST CLCLR1 + PUSHJ P,[JUMPE C,CLUAI1 ? JRST CLUBI1] + JRST CLCLRL +CLCLR2: MOVE J,3(Q) ;FOUND AN EOF, FLUSH THE EOF WORD + ILDB I,J + PUSHJ P,[JUMPE C,CLUAIE ? JRST CLUBIE] + MOVE T,1(Q) + TLNE T,760000 + JRST CLCLR2 ;NOT YET TO WORD BOUNDARY + JRST CLCLR3 + +CLCLR1: MOVSI B,%CAFLS + IORM B,CLRAC(A) + PUSH P,A + PUSH P,Q + HLRZ A,CLUSR(A) + PUSHJ P,NJRPCL + PUSHJ P,NJUPCL + POP P,Q + POP P,A +CLCLR3: HLLOS B,CLUSR(A) ;NO LONGER OPEN FOR INPUT + SKIPN (Q) ;IF NO DATA IN BUFFER + AOJE B,CLO1D2 ;AND NOT OPEN FOR OUTPUT, GO FREE THE BUFFER AND VARS + JRST LSWPOP + +SUBTTL LOCK DEVICE + +NLCKCH==:8 ; Should be enough. + +EBLK + +LCKNAM: REPEAT NLCKCH, 0 ; 0 => free lock channel, else contains + ; name of lock held by this channel. +LCKUSR: REPEAT NLCKCH, 0 ; Job that holds the lock. Nothing looks + ; at this currently. +LCKSW: -1 ? 0 ; Prevent more than one user from trying to + ; lock a lock at the same time. +BBLK + +; LCKO is .OPEN routine for LOCK device. First filename is name of lock to +; seize. 0 is illegal. Only opens for output are permitted (some day we +; might allow multiple opens for input). +; +; Bit 1.4 controls what happens if lock is already held: +; 0 => error: %ENAFL +; 1 => Hang until you can seize it +LCKO1: PUSHJ P,LSWPOP ; We lose this time + TLNN C,10 ; 1.4 => HANG MODE + JRST OPNL23 ; FILE LOCKED + MOVE T,A + CAMN T,LCKNAM(I) ; Wait for unlock, then try again + PUSHJ P,UFLS +LCKO: JUMPE A,OPNL11 ; ILLEGAL FILE NAME + PUSHJ P,SWTL ; One potential locker at a time + LCKSW + MOVSI I,-NLCKCH ; Check if it is already locked + CAME A,LCKNAM(I) + AOBJN I,.-1 + JUMPL I,LCKO1 ; Already held + MOVSI I,-NLCKCH ; Search for free lock channel + SKIPE LCKNAM(I) + AOBJN I,.-1 + JUMPGE I,OPNL6 ; DEVICE FULL + HRRZM U,LCKUSR(I) + MOVEM A,LCKNAM(I) + HRLZI T,(I) + HRRI T,DNLCK + MOVEM T,(R) ; Set up channel + JRST LSWPJ1 ; And return + +; .CALL RFNAME returns name of lock: +LCKRCH: MOVE B,LCKNAM(A) + POPJ P, + +; .CLOSE releases the lock: +LCKCL: SETZM LCKNAM(A) + POPJ P, + +SUBTTL COMMON I/O ROUTINES + +;STANDARD DEVICE OPEN + +STDOP1: MOVEI R,R ;ENTRY TO NOT CLOBBER IOCHNM +STDOPN: HLRZ A,(Q) ;LH MASK ON 4.9-3.2 OF LH OPEN WRD + AND D,A ;RH POINTER TO ..USR,..USE PAIR + ROT D,-1 ;FOLLOWING WORDS CONTAIN LIST FOR ALL MASKED STATES + ADDI D,(Q) ;LH MSKED STATE =0, RH =1, IOTTB ENTRY NUMBERS + HRRZ A,1(D) + SKIPL D + HLRZ A,1(D) + JUMPE A,OPNL12 ;MODE NOT AVAIL + HRRZ E,(Q) + CONO PI,CLKOFF + CAME U,(E) + SKIPGE 1(E) + AOSA 1(E) + JRST OPNL10 ;DEVICE NOT AVAIL + MOVEM U,(E) + HLL A,C + JRST OPNSLT + +OPSLD1: ANDI D,1 ;ENTRY TO USE BOTTOM BIT OF AC D +OPSLD3: ANDI D,3 ;ENTRY TO USE BOTTOM TWO BIT OF AC D + MOVE C,D +OPSLC3: ANDI C,3 ;ENTRY TO USE BOTTOM TWO BITS OF AC C +OPSLC7: ANDI C,7 ;ENTRY TO USE BOTTOM THREE BITS OF AC C + ROT C,-1 + ADDI C,(Q) + HRR A,(C) + SKIPL C + HLR A,(C) +OPNSLT: MOVEM A,(R) ;SET USERS IOCHNM + JRST CLKOJ1 + +;BLOCK OUTPUT TO CHARACTER DEVICE +;ADR OF CHR ROUTINE IN E +; THAT ROUTINE MUST NOT CLOBBER C, D, E, OR TT +;C POINTS TO AOBJN POINTER IN USER SPACE +;MUSTN'T CLOBBER J (TTY OUTPUT ASSUMES). + +NBTOCH: XCTR XRW,[MOVES D,(C)] ;CHECK WRITEABILITY OF AOBJN PTR + LDB TT,[410300,,D] ;USE HIGH 3 BITS OF USER PNTR AS CHR CNT + CAIGE TT,3 + POPJ P, ;USER TRYING TO XFER >32K FLUSH + SKIPA TT,BTOCHT-3(TT) ;PICK UP APPROPRIATE BYTE PTR (WORD IN W) +NBTO1: UMOVEM D,(C) ;UPDATE USER'S AOBJN PTR + UMOVE W,(D) ;FETCH CURRENT WORD FROM USER + ILDB A,TT ;FETCH CURRENT CHARACTER + PUSHJ P,(E) ;SEND TO DEVICE + ADD D,[700000,,] ;UPDATE PTR + TLNE D,500000 + JRST NBTO1 ;GO TO NEXT CHR + MOVE TT,BTOCHT+4 + ADD D,[500001,,1] ;INCR TO NEXT WORD + JUMPL D,NBTO1 + UMOVEM D,(C) ;COUNTED OUT, UPDATE FINAL TIME & RETURN + POPJ P, + +BTOCHT: REPEAT 5,<44-<4-.RPCNT>*7>_14+700,,W + +;BLOCK INPUT FROM CHARACTER DEVICE +;E AND C SET UP LIKE NBTOCH +;INTERNALLY LH OF E USED FOR FLAGS: +; 4.9 EOF FLAG (SIGN) +; 4.8 => JUST RETURN WITHOUT ERROR IF AT BEGINNING OF WORD, +; OTHERWISE IGNORE BIT. +; 4.7 => RETURN WITHOUT ERROR EVEN IF NOT AT BEGINNING OF WORD. + +INBTCH: HRRZS E ;CLEAR GARBAGE IN LH + XCTR XRW,[MOVES D,(C)] ;SET UP LIKE NBTOCH + LDB TT,[410300,,D] + CAIGE TT,3 + POPJ P, + SKIPA TT,BTOCHT-3(TT) +INBTO1: UMOVEM D,(C) + XCTR XRW,[MOVES (D)] ;CHECK WRITABILITY OF CURRENT WORD + JUMPL E,INBTO2 ;JUMP IF EOF + PUSH P,C + PUSH P,D + PUSH P,TT + PUSH P,R + HLRZ A,(R) + PUSHJ P,(E) ;RETN CHR IN W + JRST .+3 + TLO E,200000 + TLO E,400000 + MOVE I,W + POP P,R + POP P,TT + POP P,D + POP P,C + LDB W,[410300,,D] + TLNN E,100000 + CAIN W,7 ;SKIP IF NOT AT 1ST CHAR. + TLNN E,300000 + JRST INBTO3 + POPJ P, + +INBTO3: UMOVE W,(D) ;PICK UP CURRENT WORD + IDPB I,TT ;INSERT CHARACTER + UMOVEM W,(D) ;PUT WORD BACK + ADD D,[700000,,] + TLNE D,500000 + JRST INBTO1 ;DO ANOTHER CHR THIS WORD + MOVE TT,BTOCHT+4 + ADD D,[500001,,1] ;INCR TO NEXT WD + SKIPL E ;SKIP IF EOF + JUMPL D,INBTO1 + UMOVEM D,(C) ;DONE, UPDATE POINTER AND RETURN + POPJ P, + +INBTO2: MOVEI I,EOFCH ;EOF, STORE EOF CHARACTER + JRST INBTO3 + +;BLOCK IO TO WORD DEVICE +;C POINTS TO AOBJN POINTER IN USER SPACE +;Q POINTS TO WORD HANDLING ROUTINE (POINTER WILL BE IN C) +;MUST NOT CLOBBER Q OR H (PTR ROUTINES DO POPJ2 SOMETIMES) +;WRDBRT CHECKED FOR ON PDL BY TVC ROUTINES + +WRDBT: MOVE H,C + UMOVE C,(H) ;FETCH USER'S AOBJN POINTER + JUMPGE C,CPOPJ + JRST WRDBT3 + +WRDBT2: PUSHJ P,OPBRK +WRDBT3: ANDI C,-1 + PUSHJ P,(Q) +WRDBRT: JRST WRDBT5 ;NO SKIP - WORD XFERRED + SKIPA C,[1,,1] ;1 SKIP - LAST WORD XFERRED + POPJ P, ;2 SKIPS - EOF, NO WORD XFERRED + XCTR XRW,[ADDM C,(H)] + POPJ P, + +WRDBT5: MOVE C,[1,,1] + XCTR XRW,[ADDB C,(H)] + JUMPL C,WRDBT2 + POPJ P, + +;JSP W,WRDBTI TO DO WRDBT FOR A UNIT MODE INPUT ROUTINE SATISFYING NEW +;CALLING CONVENTION FOR THOSE. +WRDBTI: JSP Q,WRDBT + XCTR XRW,[MOVES (C)] + PUSH P,W + PUSHJ P,(W) + JRST WRDBT4 + JRST POPWJ2 + AOS -1(P) +WRDBT4: UMOVEM W,(C) + MOVEI Q,WRDBTI+1 + POP P,W + POPJ P, + +;CHANGED CONVENTIONS: + ;1) EOF IS NO LONGER CHECKED FOR CHARACTER BY CHARACTER. + ; INSTEAD, THE GET-BUFFER ROUTINE SHOULD SET UP THE BYTE COUNT + ; TO A SMALLER VALUE THAN USUAL. + ; AN ATTEMPT TO GET ANOTHER BUFFER AFTER REACHING EOF + ; SHOULD CAUSE THE GET-BUFFER ROUTINE TO SKIP TWICE. + ;2) THE THE BUFFER POINTER IS NOW A B.P. EVEN IN IMAGE MODE. + ; ALSO, THE L.H. OF THE B.P. IS NOT INITTED HERE. + ; IT MUST BE SET UP BY THE OPEN ROUTINE. ALSO, ACCESS ROUTINES + ; FOR DSK MUST KNOW HOW TO SET IT UP. + ; ALSO, THE BUFFER GET ROUTINE SHOULD SET IT UP, + ; INSTEAD OF RETURNING THE BUFFER ADDRESS IN TT. + ;3) THE BYTE SIZE THE FILE IS OPEN ON IS PASSED AS AN ARGUMENT. + ; THIS ROUTINE WORKS FOR ANY CHANNEL BYTE SIZE WITH ANY + ; SIOT BYTE SIZE. + +;GENERAL BLOCK I/O +;RH OF E HAS # BYTES/WORD OF FILE BYTE SIZE. LH OF E HAS B.P. 44NN00. +;RH(C) = ADDR OF COUNT, IN USER MEMORY +;RH(TT) = ADDR OF USER'S B.P. +; ARGUMENTS B -> +;0(B) ADDR OF ACTIVE BUFFER BYTE PTR, 4.9=0 => INPUT, =1 => OUTPUT +;1(B) ADDR OF COUNT OF BYTES REMAINING IN CURRENT BUFFER +;2(B) ROUTINE TO GET NEXT BUFFER. NO SKIP IF NO MEMORY +; OTHERWISE SKIP; BUFFER BYTE COUNT IN @1(B) +; AND BUFFER BYTE POINTER ALREADY SET UP. +; 2 SKIPS => THERE IS NO BUFFER, DUE TO EOF. +; WHEN THIS ROUTINE IS CALLED, E CONTAINS THE +; NUMBER OF BYTES/WORD (GOOD FOR DETERMINING CHANNEL MODE). +;3(B) ROUTINE TO PUT BUFFER (OUTPUT) OR DISCARD (INPUT) +; MAY REACTIVATE CURRENT BUFFER BY SETTING @1(B) TO NONZERO, +; IN WHICH CASE IT SHOULD CONTAIN THE NEW NUMBER OF BYTES. +;4(B) NOT USED +;5(B) IF POSITIVE, INSTRUCTION TO WAIT FOR I/O +; IF NEGATIVE, ROUTINE ASSUMES 2(B) AND 3(B) WILL WAIT + +;RELOADING ROUTINES MUST NOT CLOBBER B,E,A,C,I +;SIOKT CLOBBERS C,D,J,TT, AND WHATEVER THE RELOADING ROUTINES CLOBBER. + +SIOKT: PUSH P,E + PUSH P,TT + PUSH P,C + JRST SIOKT1 + +;NEXT BUFFER + +SIOKNB: PUSHJ P,@3(B) ;"DISCARD" BUFFER + SKIPE J,@1(B) ;CHECK AMOUNT REMAINING ONE MORE TIME + JRST SIOKT1 ;IT SPRUNG BACK TO LIFE (WRITE OVER MODE LAST BLOCK OF FILE) + SKIPG 5(B) ;NEED TO WAIT FOR DEVICE? + JRST SIOKF1 ;NO. +SIOKN1: SKIPG 5(B) ;COME HERE IF MUST WAIT FOR SOME REASON OR OTHER + JRST SIOKW1 ;DEVICE CAN'T WAIT SO UDELAY + XCT 5(B) ;DEVICE WAIT +SIOKF: PUSHJ P,UFLS + +SIOKF1: PUSHJ P,@2(B) ;NOW GET NEXT BUFFER + JRST SIOKN1 ;HMM, HAVE TO WAIT + JRST SIOKT1 ;BUFFER HAS BEEN GOT. + JRST POP3J1 ;EOF, TRANSFER IS COMPLETE + +SIOKT1: UMOVE TT,@(P) ;GET COUNT OF BYTES TO TRANSFER + JUMPLE TT,POP3J1 ;COUNT DECREMENTED TO 0; TRANSFER DONE. + SKIPG D,@1(B) ;CHECK AMOUNT LEFT IN BUFFER + JRST SIOKNB ;NEW BUFFER NEEDED + CAMLE TT,D ;AMT OF ROOM LEFT IN CURRENT BUFFER + MOVE TT,D ;TRANSFER ONLY AMT LEFT IN BUFFER + UMOVE J,@-1(P) + IBP J + LDB D,[301400,,J] + MOVE C,@(B) + IBP C ;TO TRANSFER WORD-WISE, BOTH B.P.'S MUST + HRL J,C + LDB C,[301400,,C] + CAIE C,(D) ;HAVE SAME BYTE SIZE, + JRST SIOKS1 + LDB D,[060600,,C] + ANDI C,77 + ADDI C,(D) +;DROPS THROUGH + ;DROPS IN + CAIGE TT,@-2(P) ;THERE MUST BE AT LEAST 1 WORD TO TRANSFER, + JRST SIOKS1 + CAIE C,44 ;AND MUST BE ABOUT TO START THE NEXT WORD. + JRST SIOKSL + PUSH P,TT+1 + IDIVI TT,@-3(P) ;GET # WDS TO BLT + POP P,TT+1 + SKIPGE (B) + MOVSS J ;WRITING, SWAP BLT POINTER + MOVE D,J + ADDI TT,(D) ;1+LAST WORD TO BLT INTO + SKIPGE (B) + JRST SIOKN6 ;JUMP IF WRITING + XCTRI XBW,[BLT D,-1(TT)] ;READING +SIOKN7: MOVEI D,(TT) ;NO FAULT, UPDATE PTR TO LAST WORD + 1 (LIKE KL10) +SIOKN8: SUBM D,J + HRRZS J ;# WDS ACTUALLY XFERRED + ADDM J,@(B) ;INCR BUFFER PNTR + XCTR XRW,[ADDM J,@-1(P)] + IMULI J,@-2(P) + MOVNS J + XCTR XRW,[ADDM J,@(P)] + ADDM J,@1(B) ;DECREMENT COUNT LEFT IN BUFFER + CAIE D,(TT) ;SKIP IF TRANSFERRED ALL WE COULD + PUSHJ P,TPFLT ;TAKE FAULT +SIOKN3: SKIPN @1(B) + PUSHJ P,@3(B) ;BUFFER EXHAUSTED, DISCARD (MAY COME BACK TO LIFE). + JRST SIOKT1 ;TRY AGAIN TO TRANSFER. + +SIOKW1: PUSHJ P,UDELAY + JRST SIOKF1 + +SIOKN6: XCTRI XBR,[BLT D,-1(TT)] ;WRITING TRANSFER + JRST SIOKN7 + JRST SIOKN8 + +;COME HERE FOR SLOW (BYTE AT A TIME) SIOT TO BLOCK MODE DEVICE. +;TT HAS NUMBER OF BYTES TO TRANSFER - IT IS KNOWN THAT THE DEVICE +;CAN SUPPLY THAT MANY FROM ITS CURRENT BUFFER. +SIOKSL: SUBM C,D ;D GETS SIZE; C HAS # BITS REMAINING TO BE HANDLED + IDIV C,D ;C GETS # BYTES TO XFER TILL REACH WORD BOUNDARY. + MOVE TT,C ;XFER THAT MANY, THEN TRY AGAIN, SO WILL USE FAST MODE. +SIOKS1: SKIPL (B) + JRST SIOKSI ;INPUT AND OUTPUT PART HERE + LDB D,[300600,,@(B)] ;BYTE SIZE IN THE BUFFER + MOVEI C,36. + IDIV C,D ;D := # EXTRA BITS AT RIGHT END OF WORD + MOVEI J,1 + LSH J,(D) + SOS J ;J := MASK FOR THEM + UMOVE C,@-1(P) ;GET COPY OF USER'S B.P. FOR SWAPPING IN PAGES. +SIOKS3: IBP C ;IF NOT FOR THESE 2 INSNS, ILDB MIGHT GET PAGE FAULT + UMOVE (C) ;WHICH WOULD CAUSE EXTRA INCREMENTING OF B.P. + XCTR XBYTE,[ILDB D,@-1(P)] ;FETCH NEXT BYTE, + IDPB D,@(B) + MOVE D,@(B) + ANDCAM J,(D) ;TURN OFF EXTRA BITS IN THIS WORD OF BUFFER + SOS @1(B) + XCTR XRW,[SOS @(P)] + SOJG TT,SIOKS3 + JRST SIOKN3 + +SIOKSI: UMOVE C,@-1(P) ;GET COPY OF USER'S B.P., FOR WRITEABILITY TESTING. +SIOKS2: IBP C + XCTR XRW,[MOVES (C)] ;MAKE SURE WE CAN WRITE IN NEXT BYTE. + ILDB D,@(B) ;GET NEXT BYTE FROM DEVICE BUFFER + XCTR XBYTE,[IDPB D,@-1(P)];GIVE IT TO USER. + XCTR XRW,[SOS @(P)] ;UPDATE USER'S COUNT + SOS @1(B) ;AND THE SYSTEM'S COUNT. + SOJG TT,SIOKS2 + JRST SIOKN3 + +;CONVENIENT EXIT ROUTINE FOR BUFFER-GET ROUTINES. +;ASSUMES ADDR OF START OF BUFFER IN TT, +;SIZE (IN WORDS) OF DATA AREA IN J. +;E SHOULD HAVE WHAT IT HAD WHEN SIOKT WAS CALLED. +SIOBGX: IMULI J,(E) +SIOBG1: HLL TT,E +SIOBG2: MOVEM TT,@(B) + MOVEM J,@1(B) + JRST POPJ1 + +;BYTE AT A TIME I/O TO BLOCK MODE DEVICE +;SEE PRECEDING PAGE (SIOKT) FOR COMMENTS ON CALLING SEQUENCE +;EXCEPT: ON INPUT, VALUE RETURNED IN W, AND C,D HAVE NO SIGNIFICANCE; +;ON OUTPUT, RH(C) HAS ADDRESS OF ARG, SIGN(C) SET IFF ADDRESS IS EXEC-MODE, +; AND D HAS NO SIGNIFICANCE. + +CHRKT: SKIPGE (B) + JRST CHRKTO ;WRITING + JRST CHRKTI ;READING + +CHRKTI: SOSGE @1(B) ;DECREMENT ACTIVE CHAR COUNT + JRST CHRKT1 ;GET NEW BUFFER + ILDB W,@(B) ;READ - GET NEXT CHAR + POPJ P, + +CHRKTO: SKIPGE C ;USED WHEN FILLING OUT BLOCK AT CLOSE, AND ELSEWHERE. + SKIPA J,(C) + UMOVE J,(C) ;GET CHAR. FROM USER + SOSGE @1(B) ;DECREMENT ACTIVE CHAR COUNT + JRST CHRKT1 ;GET NEW BUFFER + IDPB J,@(B) ;DEPOSIT IN BUFFER + CAIE E,5 ;SKIP IF ASCII + POPJ P, + MOVEI J,1 + MOVE D,@(B) + ANDCAM J,(D) ;CLEAR EXTRA BIT + POPJ P, + +CHRKT1: AOS @1(B) ;COMPENSATE FOR OVER-SOS + PUSHJ P,@3(B) ;GET RID OF THIS BUFFER + SKIPLE J,@1(B) ;CHECK AMOUNT REMAINING ONE MORE TIME + JRST CHRKT ;SPRUNG BACK TO LIFE (LAST BLOCK OF FILE WRITE OVER) + SKIPG 5(B) ;NEED TO WAIT FOR DEVICE? + JRST CHRKF1 ;NO. +CHRKN1: SKIPG 5(B) ;HAVE TO WAIT + JRST [ PUSHJ P,UDELAY + JRST CHRKF1 ] + XCT 5(B) ;DEVICE WAIT + PUSHJ P,UFLS + +CHRKF1: PUSHJ P,@2(B) ;GOBBLE NEW BLOCK + JRST CHRKN1 ;NOT READY, WAIT + JRST CHRKT + CAME E,[444400,,1] + JRST UNIEOF ;READING PAST EOF IN ASCII MODE. + JRST IOCER2 ;READING PAST EOF IN IMAGE MODE. + +;GENERAL BLOCK I/O +;E HAS BPLH,,# BYTES/WORD OF FILE BYTE SIZE - MUST BE 444400,,1 +;RH(C) = ADDR OF AOBJN POINTER +; AND 4.9 => AOBJN PTR IS IN EXEC ADDRESS SPACE, +; 4.8 => BLOCK IT POINTS TO IS IN EXEC ADDRESS SPACE. (INPUT ONLY) +; ARGUMENTS B -> +;0(B) ADDR OF ACTIVE BUFFER BYTE PTR, 4.9=0 => INPUT, =1 => OUTPUT +;1(B) ADDR OF COUNT OF BYTES REMAINING IN CURRENT BUFFER +;2(B) ROUTINE TO GET NEXT BUFFER. NO SKIP IF NO MEMORY +; OTHERWISE SKIP; BUFFER BYTE COUNT IN @1(B) +; AND BUFFER B.P. IN @(B) ALREADY SET UP. +; 2 SKIPS => THERE IS NO BUFFER, DUE TO EOF. +;3(B) ROUTINE TO PUT BUFFER (OUTPUT) OR DISCARD (INPUT) +; MAY REACTIVATE CURRENT BUFFER BY SETTING @1(B) TO NONZERO. +;4(B) NOT USED +;5(B) IF POSITIVE, INSTRUCTION TO WAIT FOR I/O +; IF NEGATIVE, ROUTINE ASSUMES 2(B) AND 3(B) WILL WAIT + +;RELOADING ROUTINES MUST NOT CLOBBER B,E,A,C,I +;BLKT CLOBBERS C,D,J,TT, AND WHATEVER THE RELOADING ROUTINES CLOBBER. + +;CODE IS ON NEXT PAGE + +BLKT: CAME E,[444400,,1] + BUG ;BLKT CALLED ON UNIT ASCII MODE CHANNEL?? + SKIPL C ;SKIP IF POINTER IN USER SPACE + XCTR XRW,[MOVES (C)] ;USER SPACE, MAKE SURE WRITE CYCLE WILL WIN + JRST BLKT1 + +;NEXT BUFFER + +BLKTNB: PUSHJ P,@3(B) ;"DISCARD" BUFFER + SKIPE @1(B) ;CHECK AMOUNT REMAINING ONE MORE TIME + JRST BLKT1 ;IT SPRUNG BACK TO LIFE (WRITE OVER MODE LAST BLOCK OF FILE) + SKIPG 5(B) ;NEED TO WAIT FOR DEVICE? + JRST BLKTF1 ;NO. +BLKTN1: SKIPG 5(B) ;COME HERE IF MUST WAIT FOR SOME REASON OR OTHER + JRST BLKTW1 ;DEVICE CAN'T WAIT SO UDELAY + XCT 5(B) ;DEVICE WAIT +BLKTF: PUSHJ P,UFLS + +BLKTF1: PUSHJ P,@2(B) ;NOW GET NEXT BUFFER + JRST BLKTN1 ;HMM, HAVE TO WAIT + JRST BLKT1 + POPJ P, ;EOF, TRANSFER FINISHED + +BLKT1: SKIPGE C ;SET UP FOR TRANSFER + SKIPA J,(C) ;GET EXEC MODE BLOCK .IOT (AOBJN) POINTER + UMOVE J,(C) ;GET USER MODE AOBJN POINTER + JUMPGE J,CPOPJ ;POINTER COUNTED OUT, TRANSFER DONE + SKIPG D,@1(B) ;CHECK AMOUNT LEFT IN BUFFER + JRST BLKTNB ;NEW BUFFER NEEDED + HLRE TT,J + MOVNS TT ;DESIRED SIZE OF BLOCK + CAMLE TT,D ;AMT OF ROOM LEFT IN CURRENT BUFFER + MOVE TT,D ;TRANSFER ONLY AMT LEFT IN BUFFER + MOVE D,@(B) ;CANONICALIZE THE BUFFER B.P. SO RH => NEXT WORD TO XFER + IBP D + HRL J,D ;MERGE WITH USER'S BLOCK ADDR TO GET BLT AC. + SKIPGE (B) + MOVSS J ;WRITING, SWAP BLT POINTER + MOVE D,J + ADDI TT,(D) ;1+LAST WORD TO BLT INTO + TLNE C,200000 + JRST BLKTN9 ;JUMP IF EXEC AOBJN POINTER + SKIPGE (B) + JRST BLKTN6 ;JUMP IF WRITING + XCTRI XBW,[BLT D,-1(TT)] ;READING +BLKTN7: MOVEI D,(TT) ;NO FAULT, UPDATE PTR TO LAST WORD + 1 (LIKE KL10) +BLKTN8: SUBM D,J + HRRZS J ;# WDS ACTUALLY XFERRED + ADDM J,@(B) ;INCR BUFFER PNTR + HRLS J ;PUT # WDS IN BOTH HALVES + JUMPL C,BLKTN3 ;UPDATE AOBJN PTR IN EXEC SPACE + XCTRI XRW,[ADDM J,(C)] ;UPDATE AOBJN PTR IN USER SPACE + JRST .+2 + BUG ;MUMBLE. THIS WAS SUPPOSED TO BE THERE. + +BLKTN4: MOVNI J,(J) + ADDM J,@1(B) ;DECREMENT COUNT LEFT IN BUFFER + CAIE D,(TT) ;SKIP IF TRANSFERRED ALL WE COULD + PUSHJ P,TPFLT ;TAKE FAULT IF ANY + SKIPN @1(B) + PUSHJ P,@3(B) ;BUFFER EXHAUSTED, "DISCARD" + JRST BLKT1 ;GO TRANSFER ANOTHER CHUNK + +BLKTN3: ADDM J,(C) ;UPDATE EXEC AOBJN POINTER + JRST BLKTN4 + +BLKTW1: PUSHJ P,UDELAY + JRST BLKTF1 + +BLKTN6: XCTRI XBR,[BLT D,-1(TT)] ;WRITING TRANSFER + JRST BLKTN7 + JRST BLKTN8 + +BLKTN9: BLT D,-1(TT) ;READING INTO EXEC SPACE + JRST BLKTN7 + +SUBTTL DIRECTORY AND ERR DEVICES + +QMLSTF: MOVEI J,4 ;ENTRY TO GET MASTER 2314 DIRECTORY + JRST LISTF7 + +QLISTF: MOVEI J,3 ;ENTRY FOR 2314 USER DIRECTORY +LISTF7: MOVEI I,0 +LISTFE: PUSHJ P,SWTL ;ENTER HERE FOR ALL KINDS OF DIRECTORIES. + UDCSW + MOVSI TT,-NUDCH +UD1: SKIPGE UDUSR(TT) + JRST UD2 + AOBJN TT,UD1 + PUSHJ P,LSWPOP + PUSHJ P,UDELAY ;DIRECTORY NOT AVAILABLE NOW, WAIT + JRST LISTFE + +UD2: MOVEM J,DSKLST(TT) + MOVEM I,UDUSR(TT) + MOVEM U,UDUIND(TT) + PUSHJ P,LSWPOP + MOVE Q,USYSN1(U) + MOVEM Q,UDSYSN(TT) + JUMPG J,UDIF ;JUMP IF NOT UTAPE DIR. +IFE NUNITS, BUG ;HOW DID UTAPE GET HERE? +IFN NUNITS,[ + CONO PI,CLKOFF + MOVE Q,UDIRO(I) + MOVEM Q,DIRPT(TT) + CONO PI,CLKON + MOVEI J,200 + TRNE D,2 + JRST UDBIN ;IMAGE MODE UTAPE DIR + MOVEI Q,LISTF ;ASCII MODE UTAPE DIR +] +UDIF1: MOVEM Q,DIRPC(TT) + HRL A,TT + JSP Q,OPSLD1 + DIRCHN,,DIRBN + +UDIF: HLRZ Q,UDT-1(J) ;INITIAL COROUTINE PC + HRRZ T,UDT-1(J) ;PLACE TO FINISH OPENING - USUALLY UDIF1. + JRST (T) + +UQL1: HRRZM H,UUDPP(TT) ;2314 MFD (FROM UDIF) + MOVEI J,2000 + TRNE D,2 + JRST QUDBIN + JRST UDIF1 + +UQL1A: PUSHJ P,STMSET ;DISK UFD (FROM UDIF). WE CAN STILL PCLSR, + UDUSR(TT) ;ARRANGE TO GIVE BACK THE DIRECTORY CHANNEL. +UQL1B: PUSH P,TT + PUSHJ P,QUDLK + PUSHJ P,TCALL ;GET A LOW-HALF PAGE TO COPY UFD INTO. + JRST IOMQ ;GET LOW HALF PAGE + JRST UQL1W ;NOT AVAIL NOW + MOVEI T,MU23LS + DPB T,[MUR,,MEMBLT(A)] ;MARK THE PAGE AS A UFD COPY. + LSH A,10. + MOVEM A,DIRPT(TT) + MOVEM A,UUDPP(TT) + HRL A,QSNLCN(H) + HRRI T,2000(A) + BLT A,-1(T) ;COPY UFD + PUSHJ P,QUDULK + PUSHJ P,LSWDEL ;STMSET OF UDUSR. + SKIPG QSNNR(H) + BUG ;WE ALWAYS GET OUR MAN + PUSHJ P,LSWPOP ;SOS QSNNR + POP P,TT + MOVEI J,2000 + TRNE D,2 + JRST UDBIN + JRST UDIF1 + +UQL1W: PUSHJ P,QUDULK + POP P,TT + PUSHJ P,UDELAY + JRST UQL1B + +;LH INITIAL PC RH DISP ADR AT OPEN TIME +UDT: NDLF,,UDIF1 ;NON DIR DEVICE + UCL1,,UDIF1 ;CORE LINK + UQL2,,UQL1A ;2314 UFD + QMLS1,,UQL1 ;2314 MFD + ERR1,,ERR2 ;ERR DEVICE + TTYFLD,,UDIF1 ;TTY DIR + TTYF99,,UDIF1 ;COR DIR (LAST LINE OF TTY DIR) +UDTLN==.-UDT + +QUDBIN: HRRZ T,QMDRO + MOVEM T,DIRPT(TT) +UDBIN: MOVEM J,NUM(TT) ;DOESN'T USE DIRPC THIS PC + MOVEM J,ENDT(TT) + MOVEI J,444400 + HRLM J,DIRPT(TT) + HRL A,TT + JSP Q,OPSLD1 + NDATAI,,NBLKI + +UTDCLS: MOVE B,DSKLST(A) + CAIN B,3 + JRST UTDCL1 +UTDCLX: SETOM UDUSR(A) + POPJ P, + +UTDCL1: PUSH P,A + MOVE A,UUDPP(A) + LSH A,-10. + PUSHJ P,MEMR + POP P,A + JRST UTDCLX + +;UNIT MODE IOT ON DIR DEVICE COMES HERE (RETURN CHAR IN W) +DIRCH: SETOM SRN3(U) ;SAY WE WANT ONLY 1 CHARACTER. + PUSHJ P,DIRCHR + HRRZ W,I + CAIN W,^C + JRST UNIEOF + POPJ P, + +;BLOCK MODE IOT ON DIR DEVICE. +DIRB: JSP Q,WRDBT ;PUSHJ'S TO .+1 FOR EACH WORD. +DIRB1: XCTR XRW,[MOVES (C)] ;MAKE SURE WE CAN WRITE. + PUSH P,C + PUSH P,H + SETZM SRN3(U) ;SAY WE WANT A WHOLE WORD OF CHARS. + PUSHJ P,DIRCHR + POP P,H + POP P,C + LDB Q,[350700,,SRN3(U)] + CAIN Q,^C ;IF THE WORD STARTS WITH ^C, + JRST POPJ2 ;IT IS EOF; DON'T RETURN IT, UNHANG IOT. + MOVE Q,SRN3(U) + UMOVEM Q,(C) + MOVEI Q,DIRB1 ;FASTER THAN PUSHING AND POPPING Q. + POPJ P, ;RETURN INTO WRDBT + + SKIPA T,[SIOKT] +DDATAI: MOVEI T,CHRKTI ;UNIT IMAGE INPUT FROM DIRECTORY. + CAIA +DBLKI: MOVEI T,BLKT ;BLOCK IMAGE INPUT FROM DIRECTORY + MOVE E,[444400,,1] + JSP B,(T) ;TO BLKT, SIOKT, OR CHRKTI + DIRPT(A) + NUM(A) + POPJ2 ;EOF IF TRY TO GET ANOTHER BUFFER + CPOPJ ;BUFFER DISCARD ROUTINE + BUG + SKIPA + +;ERR DEVICE AND ERROR MESSAGE TABLES +; ERR DEVICE WORKS MUCH LIKE DIR DEVICE + +ERRO: MOVEI J,5 + JRST LISTF7 + +ERR2: SOJE A,ERR21 ;LAST ERRONEOUS CHANNEL + SOJE A,ERR22 ;CHANNEL SPECIFIED IN B + SOJE A,ERR23 ;STATUS WORD IN B + SOJE A,ERR24 ;.CALL ERROR ARG IN B + SETOM UDUSR(TT) + JRST OPNL11 + +ERR21: LDB B,[BCHPTR] +ERR22: ANDI B,17 + ADDI B,IOCHST(U) + SKIPA B,(B) +ERR24: MOVSS B +ERR23: MOVEM B,UUDPP(TT) + JRST UDIF1 + +CORO: PUSHJ P,FLDRCK + JRST OPNL11 + MOVEI J,7 + JRST LISTF7 + +ERR1: SKIPN I,UUDPP(A) + JRST ERR3 + LDB B,[220600,,UUDPP(A)] ;OPEN LOSS FIELD + JUMPE B,ERR1B + CAIL B,NERMES+1 + MOVEI B,NERMES+1 + MOVE TT,ERMST1-1(B) + JSP B,MESPNT +ERR1B: LDB B,[300300,,UUDPP(A)] ;IDS ERROR FIELD + JUMPE B,ERR1C + MOVE TT,ERMST2-1(B) + JSP B,MESPNT +ERR1C: LDB B,[330400,,UUDPP(A)] ;IOCERR FIELD + JUMPE B,UCL7 + CAIL B,MIOTER + CAIL B,NERM1+MIOTER + MOVEI B,NERM1+MIOTER + MOVE TT,ERMST3-MIOTER(B) + JSP B,MESPNT + JRST UCL7 + +ERR3: MOVEI TT,[ASCIZ /ISE0 +/] + JSP B,MESPNT + JRST UCL7 + +;LISP ASSUMES THAT NO "ERR" DEVICE MESSAGE WILL EVER CONTAIN +; !, #, ^, OR LOWER CASE LETTERS. PLEASE MAINTAIN THIS STATE +; GLS (GUY STEELE) + +ERMST1: [ASCIZ /NO SUCH DEVICE +/] + [ASCIZ /WRONG DIRECTION +/] + [ASCIZ /TOO MANY TRANSLATIONS +/] + [ASCIZ /FILE NOT FOUND +/] + [ASCIZ /DIRECTORY FULL +/] + [ASCIZ /DEVICE FULL +/] + [ASCIZ /DEVICE NOT READY +/] + [ASCIZ /DEVICE NOT AVAILABLE +/] + [ASCIZ /ILLEGAL FILE NAME +/] + [ASCIZ /MODE NOT AVAILABLE +/] + [ASCIZ /FILE ALREADY EXISTS +/] + [ASCIZ /BAD CHANNEL NUMBER +/] + [ASCIZ /TOO MANY ARGUMENTS (CALL) +/] + [ASCIZ /PACK NOT MOUNTED +/] + [ASCIZ /DIRECTORY NOT AVAIL +/] + [ASCIZ /NON-EXISTENT DIRECTORY +/] + [ASCIZ /LOCAL DEVICE ONLY +/] + [ASCIZ /SELF-CONTRADICTORY OPEN +/] + [ASCIZ /FILE LOCKED +/] + [ASCIZ /M.F.D. FULL +/] + [ASCIZ /DEVICE NOT ASSIGNABLE TO THIS PROCESSOR +/] + [ASCIZ /DEVICE WRITE-LOCKED +/] + [ASCIZ /LINK DEPTH EXCEEDED +/] + [ASCIZ /TOO FEW ARGUMENTS (CALL) +/] + [ASCIZ /CAN'T MODIFY JOB +/] + [ASCIZ /CAN'T GET THAT ACCESS TO PAGE +/] + [ASCIZ /MEANINGLESS ARGS +/] + [ASCIZ /WRONG TYPE DEVICE +/] + [ASCIZ /NO SUCH JOB +/] + [ASCIZ /VALID CLEAR OR STORED SET +/] + [ASCIZ /NO CORE AVAILABLE +/] + [ASCIZ /NOT TOP LEVEL +/] + [ASCIZ /OTHER END OF PIPELINE GONE OR NOT OPEN +/] + [ASCIZ /JOB GONE OR GOING AWAY +/] + [ASCIZ /ILLEGAL SYSTEM CALL NAME +/] + [ASCIZ /CHANNEL NOT OPEN +/] + [ASCIZ /INPUT BUFFER EMPTY OR OUTPUT BUFFER FULL +/] + [ASCIZ /UNRECOGNIZABLE FILE +/] + [ASCIZ /LINK TO NON-EXISTENT FILE +/] +IFN .-ERMST1-NOPNLS,.ERR WRONG TABLE LENGTH +;ADD NEW MESSAGES HERE + +IFN 0,[ A CLASSIFICATION OF OPEN-LOSS MESSAGES + +FULL - NO CORE (MMP FULL) + DIR NOT AVAIL (DIR CHNL TABLE FULL) + DEVICE FULL + DIR FULL + MFD FULL + INPUT BUFFER EMPTY OR OUTPUT BUFFER FULL + +NO SUCH - DEVICE, FILE, JOB, DIRECTORY, PAGE (CAN'T GET ACCESS) + ILLEGAL SYSTEM CALL NAME + +ALREADY ONE SUCH - FILE (FILE ALREADY EXISTS - RENAME) + +WRITING - CAN'T MODIFY JOB + DEVICE WRITE-LOCKED + WRONG DIRECTION + MODE NOT AVAILABLE + CAN'T GET ACCESS TO PAGE + +ARGS (THE PARAMETERS ARE RIDICULOUS) - + SELF-CONTRADICTORY OPEN COMMAND + ILLEGAL FILE NAME + BAD CHANNEL NUMBER + TOO FEW ARGS + TOO MANY ARGS + MEANINGLESS ARGS + CHANNEL NOT OPEN + +NOT AVAILABLE (IT EXISTS BUT YOU CAN'T USE IT) - + DEVICE NOT READY + DEVICE NOT AVAILABLE + NOT ASSIGNABLE TO THIS PROCESSOR + LOCAL DEVICE + PACK NOT MOUNTED + FILE LOCKED + OTHER END OF PIPELINE GONE + JOB GONE OR GOING AWAY + +DEPTH - LINK DEPTH EXCEEDED + TOO MANY TRANSLATIONS + +OTHER - NOT TOP LEVEL + VALID CLEAR OR STORED SET +] + +NERMES==.-ERMST1 + [ASCIZ /OPEN TYPE NOT DETERMINED +/] + +ERMST2: [ASCIZ /IDS ILLEGAL SCOPE MODE +/] + [ASCIZ /IDS SCOPE HUNG +/] + [ASCIZ /MORE THAN 1K SCOPE BUFFER +/] + [ASCIZ /IDS MEM PROTECT +/] + [ASCIZ /IDS ILLEGAL SCOPE OP +/] + [ASCIZ /IDS MEM PROTECT ON PDL PNTR +/] + [ASCIZ /IDS ILLEGAL PARAMETER SET +/] + +ERMST3: [ASCIZ /DEVICE HUNG OR REPORTING NON-DATA ERROR +/] + [ASCIZ /END OF FILE +/] + [ASCIZ /NON-RECOVERABLE DATA ERROR +/] + [ASCIZ /NON-EXISTENT SUB DEVICE +/] + [ASCIZ /OVER IOPOP +/] + [ASCIZ /OVER IOPUSH +/] + [ASCIZ /USR OP CHNL DOES NOT HAVE USR OPEN +/] + [ASCIZ /CHNL NOT OPEN +/] + [ASCIZ /DEVICE FULL +/] + [ASCIZ /CHNL IN ILLEGAL MODE ON IOT +/] + [ASCIZ /ILLEGAL CHR AFTER CNTRL P ON TTY DISPLAY +/] + [ASCIZ /DIRECTORY FULL +/] + [ASCIZ /DIRECTORY'S ALLOCATION EXHAUSTED +/] +;INSERT NEW MESSAGES HERE +NERM1==.-ERMST3 + [ASCIZ /IOT OR OPR TYPE NOT DETERMINED +/] + +;DIRECTORY LISTING ROUTINES + +UQL3C: SKIPA I,["*] +UQL3: MOVEI I,"- + PUSHJ P,OUTC + JRST UQL3A + +UQL2: MOVEI TT,[MNAME ASCIZ /, /] ;GENERATE USER DIRECTORY + JSP B,MESPNT + MOVE I,UUDPP(A) + MOVEI J,UDNAME(I) + JSP B,SIXTYC ;SEND DIRECTORY NAME + MOVEI TT,[ASCIZ / +FREE BLOCKS /] + JSP B,MESPNT + MOVSI E,-NQS +UQL2A: SKIPGE QACT(E) + JRST UQL3 ;UNIT NOT ENGAGED + MOVE J,QTUTO(E) + TLNE J,40000 + JRST UQL3C ;TUT FOR UNIT NOT IN + MOVEI I,"# + PUSHJ P,OUTC + MOVE TT,QPKID(E) + JSP B,GDPT ;AND # + MOVEI I,"= + PUSHJ P,OUTC + MOVE TT,QSFT(E) + JSP B,GDPT ;AND # FREE TRACKS +UQL3A: PUSHJ P,OUTCS + AOBJN E,UQL2A + JSP B,MESPCR + MOVE I,UUDPP(A) + MOVEM I,DIRPT(A) + MOVE Q,UDNAMP(I) +UQL4: CAIL Q,2000 + JRST UCL7 + HRLI I,440600+Q + HLLM I,DIRPT(A) + +UQLP: ADDI Q,2 ;MOVE PNTR TO 3RD WRD OF FILE DESC + MOVE I,@DIRPT(A) + MOVEI TT,[ASCIZ /* /] ;DELETED OR BEING WITTEN + TLNN I,UNIGFL + MOVEI TT,[ASCIZ / /] + JSP B,MESPNT + MOVE I,@DIRPT(A) + TLNE I,UNLINK + JRST UQLL1 ;LINK + LDB TT,[UNPKN+@DIRPT(A)] + JSP B,GDPT ;PRINT PACK # + LDB TT,[UNPKN+@DIRPT(A)] + CAIG TT,9 +UQLL2: PUSHJ P,OUTCS + PUSHJ P,OUTCS + SUBI Q,2 ;BACK TO FIRST WD + JSP B,SIXTYA ;SEND FIRST FILE NAME + JSP B,SIXTYB ;AND SECOND (AOSES Q) + PUSHJ P,OUTCS + AOS Q ;SET Q TO POINT TO FILE DESC PNTR + LDB E,[UNDSCP+@DIRPT(A)] ;PICK UP FILE DESC PNTR + IDIVI E,UFDBPW + ADDI E,UDDESC ;COMPUTE WORD ADDRESS + MOVE I,@DIRPT(A) ;SAVE STATUS WORD + EXCH E,Q ;MOVE INTO PNTR + MOVE TT,QBTBLI(TT) + TLO TT,Q + HLLM TT,DIRPT(A) ;SET UP DIRPT TO POINT TO FILE DESC + TLNE I,UNLINK + JRST QLL1 ;LINK + MOVEI TT,0 +UQL5: JSP B,UQL5R ;CHECK IF ABOUT TO INCREMENT OFF WORD + ILDB I,DIRPT(A) + JUMPE I,UQL5A ;STOP + CAILE I,UDTKMX + JRST UQL5B + ADD TT,I + JRST UQL5 + +UQLL1: MOVEI I,"L + PUSHJ P,OUTC + JRST UQLL2 + +QLL1: CLEARM ENDT(A) ;CNTS TO 3 FOR USER NAME AND 2 FILE NAMES +QLL3: CLEARM NUM(A) ;CHR CNTR +QLLIST: JSP B,UQL5R + ILDB I,DIRPT(A) + JUMPE I,QLL4 + CAIN I,'; + JRST QLL2 + CAIN I,': + JRST QLL5 +QLL5A: ADDI I,40 + PUSHJ P,OUTC + AOS I,NUM(A) + CAIGE I,6 + JRST QLLIST +QLL2: PUSHJ P,OUTCS + AOS I,ENDT(A) + CAIGE I,3 + JRST QLL3 +QLL4: JSP B,MESPCR + MOVEI Q,3(E) ;ADVANCE Q + JRST UQL4 + +QLL5: JSP B,UQL5R + ILDB I,DIRPT(A) + JRST QLL5A + +UQL5R: MOVE I,DIRPT(A) ;CHECK IF ABOUT TO ILDB OFF WORD + TLNE I,770000 + JRST (B) ;NO + MOVEI I,440600+Q ;YES INCREMENT Q INSTEAD + HRLM I,DIRPT(A) + AOJA Q,(B) + +UQL5B: CAIGE I,UDWPH ;PLACE HOLDER + AOJA TT,UQL5 ;SKIP AND TAKE + CAIN I,UDWPH + JRST UQL5 ;NULL + REPEAT NXLBYT,[JSP B,UQL5R + IBP DIRPT(A) +] + AOJA TT,UQL5 ;SPACE OVER 2ND HALF OF LOAD ADDRESS + +UQL5A: JSP B,GDPT ;TYPE OUT # BLOCKS + PUSHJ P,OUTCS + MOVE Q,E ;FILE POINTER + MOVEI I,"! + SKIPGE B,@DIRPT(A) ;SKIP ON NOT DUMPED + MOVEI I,40 + PUSHJ P,OUTC ;HAS NOT BEEN BACKED UP + MOVEI I,"$ + TLNN B,UNREAP ;SKIP ON DON'T-REAP + MOVEI I,40 + PUSHJ P,OUTC + MOVEI Q,1(E) + LDB E,[1200,,DIRPT(A)] + JUMPN E,[JRST 4,.] + MOVE TT,@DIRPT(A) + AOJE TT,UQL5C ;DATE NOT KNOWN + LDB TT,[UNMON+@DIRPT(A)] + JSP B,GDPT ;TYPE MONTH + MOVEI I,"/ + PUSHJ P,OUTC + LDB TT,[UNDAY+@DIRPT(A)] + JSP B,GDPT ;TYPE DAY + MOVEI I,"/ + PUSHJ P,OUTC + LDB TT,[UNYRB+@DIRPT(A)] + JSP B,GDPT ;TYPE YEAR + PUSHJ P,OUTCS + HRRZ TT,@DIRPT(A) + IDIVI TT,60.*60.*2 + MOVE E,I + JSP B,G2DPT + MOVEI I,": + PUSHJ P,OUTC + MOVE TT,E + IDIVI TT,60.*2 + MOVE E,I + JSP B,G2DPT + MOVEI I,": + PUSHJ P,OUTC + MOVE TT,E + LSH TT,-1 + JSP B,G2DPT +UQL5D: JSP B,MESPCR + ADDI Q,2 ;ADVANCE Q + JRST UQL4 + +UQL5C: MOVEI I,"- + PUSHJ P,OUTC + JRST UQL5D + +;GENERATE MFD LISTING +QMLS1: CONO PI,CLKOFF + MOVE Q,QMDRO + HRLI Q,440600+Q + MOVEM Q,DIRPT(A) + MOVE Q,MDNAMP(Q) + CONO PI,CLKON +QMLS2: CAIL Q,1777 + JRST UCL7 + SKIPN @DIRPT(A) + JRST QMLS3 + JSP B,SIXTYA + JSP B,MESPCR +QMLS3: ADDI Q,LMNBLK + JRST QMLS2 + +;DIRECTORY LISTING ROUTINES FOR UTAPE + +IFN NUNITS,[ +LISTF: MOVEI Q,220600+Q + HRLM Q,DIRPT(A) + MOVEI Q,177 + MOVE TT,@DIRPT(A) + AOJE TT,LISTF1 + JSP B,SIXTYP +LISTF1: MOVEI TT,[ASCIZ / +FREE FILES /] + JSP B,MESPNT + MOVSI Q,-23. + MOVEI TT,0 +LISTF4: SKIPE @DIRPT(A) + AOJA Q,LISTF8 + AOS Q + SKIPN @DIRPT(A) + AOS TT +LISTF8: AOBJN Q,LISTF4 + JSP B,GDPT + MOVEI TT,[ASCIZ / FREE BLOCKS /] + JSP B,MESPNT + SETZB J,TT + JSP B,BLKPNT +LISTD2: JSP B,MESPCR + MOVSI Q,-23. +LISTF2: MOVEI I,440600+Q + HRLM I,DIRPT(A) + MOVE I,@DIRPT(A) + JUMPE I,LISTF5 +LISTF6: PUSHJ P,OUTCS + JSP B,SIXTYA + JSP B,SIXTYB + PUSHJ P,OUTCS + MOVEI J,1(Q) + JSP B,BLKPNN +LISTD4: JSP B,MESPCR +LISTF3: AOBJN Q,LISTF2 +];END IFN NUNITS + +UCL7: MOVEI I,14 ;END DIR WITH FORMFEED AND EOF CHARS + PUSHJ P,OUTC + HRROI I,EOFCH + JRST .-2 + +IFN NUNITS, LISTF5: AOJA Q,LISTF3 + +; DIRECTORY LISTING ROUTINES FOR MISC. DEVICES + CORE LINK + +NDLF: MOVEI TT,[ASCIZ / +NON-DIRECTORY DEVICE/] + JSP B,MESPNT + JRST UCL7 + +;DIRECTORY OF CORE LINK DEVICE +UCL1: MOVSI Q,-NCLCH +UCL6: SKIPN CLSYN(Q) + JRST UCL5A + MOVEI J,CLSYN(Q) + JSP B,SIXTYC + MOVEI J,CLN1(Q) + JSP B,SIXTYC + MOVEI J,CLN2(Q) + JSP B,SIXTYC + HLRE B,CLUSR(Q) + AOJE B,UCL2 + MOVEI J,UNAME-1(B) + MOVEM B,NUM(A) + JSP B,SIXTYC + MOVE B,NUM(A) + MOVEI J,JNAME-1(B) + JSP B,SIXTYC +UCL3: MOVEI TT,[ASCIZ /->/] + JSP B,MESPNT + HRRE B,CLUSR(Q) + AOJE B,UCL4 + MOVEI J,UNAME-1(B) + MOVEM B,NUM(A) + JSP B,SIXTYC + MOVE B,NUM(A) + MOVEI J,JNAME-1(B) + JSP B,SIXTYC +UCL5: JSP B,MESPCR +UCL5A: AOBJN Q,UCL6 + JRST UCL7 + +UCL4: MOVEI B,UCL5 + JRST .+2 +UCL2: MOVEI B,UCL3 + MOVEI J,[SIXBIT /CLOSED/] +SIXTYC: HRLI J,440600 + MOVEM J,DIRPT(A) + PUSHJ P,OUTCS + JRST SIXTYP + +; DIRECTORY LISTING ROUTINES FOR TTY + +TTYFLD: MOVEI TT,[ASCIZ / +TTY UNAME JNAME CORE TOTAL IDX +/] + JSP B,MESPNT + MOVSI Q,-NCT +TTYF1: HRRE E,TTYSTS(Q) + AOJE E,TTYF5 ;JUMP IF NOT IN USE + MOVE E,TTYSTS(Q) + MOVEI I,"T ;TTY + TLNN E,%TSCNS + MOVEI I,"D ;"DEVICE" + PUSHJ P,OUTC + HRRZ TT,Q + JSP B,G2OPT + HRRZS E +TTYF11: MOVEI J,UNAME(E) + JSP B,SIXTYC + MOVEI J,JNAME(E) + JSP B,SIXTYC + PUSHJ P,OUTCS + MOVE TT,NMPGS(E) + JSP B,G4SDPT + PUSHJ P,OUTCS + PUSHJ P,OUTCS + MOVEM E,DIRPT(A) + MOVE E,UTMPTR(E) + SETZB B,TT +TTYF3: SKIPE UNAME(B) + CAME E,UTMPTR(B) + JRST TTYF4 + ADD TT,NMPGS(B) +TTYF4: ADDI B,LUBLK + CAMGE B,USRHI + JRST TTYF3 + JSP B,G4SDPT + PUSHJ P,OUTCS + PUSHJ P,OUTCS + HRRZ TT,DIRPT(A) + SKIPL SUPPRO(TT) + JRST [ HRRZ TT,SUPPRO(TT) ? JRST .-1 ] + IDIVI TT,LUBLK + JSP B,GOPT + JSP B,MESPCR +TTYF5: AOBJN Q,TTYF1 +TTYF99: MOVEI TT,[ASCIZ /FREE CORE /] + JSP B,MESPNT + MOVE TT,MEMFR + SUB TT,NCBCOM + JSP B,GDPT + MOVEI TT,[ASCIZ / OUT /] + JSP B,MESPNT + MOVE TT,NPGSWO + JSP B,GDPT + JSP B,MESPCR + JRST UCL7 + +SIXTYB: AOS Q +SIXTYA: PUSHJ P,OUTCS + MOVEI I,440600+Q + HRLM I,DIRPT(A) + +SIXTYP: ILDB I,DIRPT(A) + ADDI I,40 + PUSHJ P,OUTC + MOVE I,DIRPT(A) + TLNE I,770000 + JRST SIXTYP + JRST (B) + +MESP3S: SKIPA TT,[[ASCIZ / /]] +MESPCR: MOVEI TT,[ASCIZ / +/] +MESPNT: HRLI TT,440700 + MOVEM TT,NUM(A) + ILDB I,NUM(A) + JUMPE I,(B) + PUSHJ P,OUTC + JRST .-3 + +OUTCS: MOVEI I,40 +OUTC: SKIPL TT,SRN3(U) ;IF WANT 1 CHAR, RETURN WITH IT, SAVING ACS. + JRST OUTC1 ;IF WANT WHOLE WORD, SEE IF WORD IS FULL. +OUTC2: MOVEM E,SAVE(A) + MOVEM Q,SAVQ(A) + MOVEM B,SAVB(A) + POP P,DIRPC(A) + POPJ P, + +OUTC1: LSH TT,6 + ADDI TT,(I) ;MERGE THIS CHAR (IN I) INTO WORD BEING ACCUMULATED. + LSH TT,1 + MOVEM TT,SRN3(U) + TLNE TT,774000 ;IF THE WORD IS FULL, RETURN TO DIRB. + JRST OUTC2 + POPJ P, ;ELSE POPJ FROM OUTC, TO GET MORE CHARS. + +;NUMERIC PRINTOUT ROUTINES FOR FILE DIRECTORIES. +;ALL CALLED WITH JSP B,. ALL TAKE ARG IN TT. + +;PRINT NUMBER IN TT IN DECIMAL, RIGHT-ADJUSTED IN FOUR COLUMNS. +G4SDPT: CAIL TT,1000. + JRST GDPT ;IF IT NEEDS 4 DIGITS, JUST PRINT IT. + MOVEM TT,NUM(A) + CAIL TT,100. ;ELSE FIGURE OUT HOW MANY LEADING SPACES ARE NEEDED + JRST G4SDP1 + CAIL TT,10. + JRST G4SDP2 + PUSHJ P,OUTCS ;AND PRINT THAT MANY. +G4SDP2: PUSHJ P,OUTCS +G4SDP1: PUSHJ P,OUTCS + MOVE TT,NUM(A) + JRST GDPT + +;PRINT CONTENTS OF TT AS TWO OCTAL DIGITS. +G2OPT: IDIVI TT,8 + JRST G2DPT2 + +;PRINT CONTENTS OF TT AS THREE DECIMAL DIGITS. +G3DPT: IDIVI TT,100. + MOVEM I,NUM(A) + MOVEI I,"0(TT) + PUSHJ P,OUTC + MOVE TT,NUM(A) +G2DPT: IDIVI TT,10. +G2DPT2: MOVEM I,NUM(A) + MOVEI I,"0(TT) + PUSHJ P,OUTC + MOVE I,NUM(A) + ADDI I,"0 + PUSHJ P,OUTC + JRST (B) + +;PRINT ARG IN TT IN DECIMAL USING AS MANY DIGITS AS IT NEEDS. +GDPT: HRLI B,10. + JRST GDPT0 + +;PRINT ARG IN TT IN OCTAL USING AS MANY DIGITS AS NECESSARY. +GOPT: HRLI B,8 +GDPT0: MOVSS B + SETZM ENDT(A) + MOVEM TT,NUM(A) +GDPT1: PUSH P,Q + MOVE Q,TT + IDIVI TT,(B) + CAME TT,ENDT(A) + JRST .-3 + MOVEM Q,ENDT(A) + POP P,Q + ADDI I,"0 + PUSHJ P,OUTC + MOVE TT,NUM(A) + CAME TT,ENDT(A) + JRST GDPT1 + MOVSS B + JRST (B) + +;ROUTINE TO CALL A DIRECTORY COROUTINE +DIRCHR: MOVE E,SAVE(A) + MOVE B,SAVB(A) + MOVE Q,SAVQ(A) + JRST @DIRPC(A) + +IFN NUNITS,[ +BLKPNA: MOVEI J,1(I) + LSH J,-1 + JRST BLKPNT+1 + +BLKPNN: LSH J,-1 +BLKPNT: MOVEI TT,0 + MOVEI I,56 +BLKPN2: MOVEI E,440500+I + HRLM E,DIRPT(A) +BLKPN1: ILDB E,DIRPT(A) + CAIN E,37 + JRST BLKPN3 + CAMN E,J + AOS TT + HLRZ E,DIRPT(A) + TRNE E,760000 + JRST BLKPN1 + AOJA I,BLKPN2 +BLKPN3: JUMPE J,GDPT + MOVSI I,-23. +BLKPN4: MOVE E,@DIRPT(A) + AOS I + CAMN J,@DIRPT(A) + JUMPE E,BLKPNA + AOBJN I,BLKPN4 + JRST GDPT +];NUNITS +EBLK + +UDUSR: REPEAT NUDCH,-1 ;-1 => FREE, ELSE UTAPE # IF UTAPE DIR, ELSE 0. +UDUIND: BLOCK NUDCH ;IF DIR CHANNEL IN USE, HOLDS JOB # OF JOB USING IT. + +IRPS X,,DIRPC:DIRPT:NUM:ENDT:SAVB:SAVQ:UDSYSN:UUDPP:SAVE: +X: REPEAT NUDCH,-1 + TERMIN +UDCSW: -1 + 0 + +DSKLST: BLOCK NUDCH ;0 LISTING UTAPE 1 NON-DIR DEVICE + ;2 CORE LINK 3 2311 +;NO BBLK SINCE VARIABLES ON NEXT PAGE + +SUBTTL UTC LEVEL INTERRUPT + +;NO EBLK SINCE VARIABLES ON PREVIOUS PAGE + +UTCPDP: -LUTCP,,UTCP-1 ;UTC-LEVEL PDL +UTCP: BLOCK LUTCP +UTACS: BLOCK 20 ;UTC-LEVEL AC SAVE + +IFE KS10P,[ ; On the KS10 we can take advantage of the Unibus interrupt + ; vectoring scheme to dispatch quicker, so this code was + ; reorganized somewhat. +UTCBRK: 0 +BBLK +IFN KL10P,[ + CONSO PI,1_<7-UTCCHN> + JRST 4,. ;HARDWARE BUG ALLEGEDLY FIXED +] + MOVEM U,UTACS+U + MOVEI U,UTACS + BLT U,UTACS+U-1 + MOVE P,UTCPDP +IFN NUNITS,[ +IFE NEWDTP,[ + CONSZ DC,6 + JRST PIPOS ;HAS CHNL >1 +PIPX: +] +IFN NEWDTP,[ + SKIPGE CUINT + JRST UTCB0 +] +];IFN NUNITS +IFN IMPP,[ ; See if it's an IMP interface interrupt +IFN KAIMP,[ + CONI IMP,TT + LDB A,[000300,,TT] + CAIE A,NETCHN + JRST UTCB2 + TRNE TT,IMPLW+IMPHER+IMPERR+IMPOD+IMPID +] +IFN DMIMP,[ + CONI FI,TT + TRNN TT,70 ;CHECK PIA + JRST UTCB2 ;DO NOT PROCESS IF NO PIA + TRNE TT,FILW+FIDOWN+FIWASD+FIOD+FIID +] + JRST IMPINT +UTCB2:] ;IFN IMPP + +IFN DC10P,[ + CONI DC0,TT + TRNE TT,DPIRQC + JRST QINT +] +IFE KA10P, CONO PI,020000+200_<-UTCCHN> ;BAG-BITING DEC LOSERS +IFN T300P,[ + SKIPE DSCDON + JRST T3INT +];T300P +IFN RP10P,[ + CONI DPC,TT + TRNE TT,7 + TRNN TT,10 ;IF BIT IS ON IT IS INTERRUPTING - LET QINT HAVE IT + SKIPGE QGTBZY + JRST QINT +] +IFN RH10P,[ + CONI DSK,TT + TRNN TT,%HIDON+%HIATN ;INTERRUPTING HARDWARILY + SKIPGE QGTBZY ;INTERRUPTING SOFTWARILY + JRST QINT +] +IFN TM10P,[ + CONI MTC,A + CONI MTS,C + LDB TT,[030300,,A] + CAIE TT,MTCCHN + JRST UTCBK2 + TRNN C,100 ;IF NOT JOB DONE + TRZ C,30000 ; THEN DON'T BELIEVE PAR ERR OF EOF + TRNN A,400 ;IF NEXT UNIT NOT ENABLED + TRZ C,2 ;THEN TURN OFF NEXT UNIT FLAG + TRNE C,440302 ; UNIT HUNG, ILLEGAL, BAD TAPE (UGH), LOAD NEXT UNIT, JOB DONE + JRST MGHBRK +UTCBK2: SKIPN MGTBZY ; SOFT WARE CALL + JRST MGSBRK +] +IFN NUNITS, JRST UTCB0 + +POPRET: +IFN NUNITS,[ + MOVE A,TIME + MOVEM A,LUTOTM +] +DSKEX: +IMPEX: +MGEX: MOVSI U,UTACS + BLT U,U + JRST 12,@UTCBRK + +] ;IFE KS10P + +IFN KS10P,[ + +UTCBRK: 0 ; Still EBLK'ed from previous page... +BBLK + MOVEM U,UTACS+U + MOVEI U,UTACS + BLT U,UTACS+U-1 + MOVE P,UTCPDP + CONO PI,020000+200_<-UTCCHN> ;BAG-BITING DEC LOSERS +IFN KSIMP,[ + AOSN IMPBZY ;-1 if IMP wants a jump-start + PUSHJ P,IMPINT +] +IFN RH11P,[ + SKIPGE QGTBZY + JRST QINT +] ;RH11P +IFN TM03S,[ + SKIPN MGTBZY + JRST MGSBRK +] +IMPEX: +MGEX: +DSKEX: MOVSI U,UTACS + BLT U,U + JRST 12,@UTCBRK + +;;; Interrupt routines that are directly dispatched to by the KS10/Unibus +;;; interrupt kludge should do JSR UTCSAV as their very first instruction. +;;; The word before the JSR is expected to contain the interrupted PC. +;;; They should then exit through DSKEX just like everybody else. + +EBLK +UTCSAV: 0 +BBLK + MOVEM U,UTACS+U + MOVEI U,UTACS + BLT U,UTACS+U-1 + MOVE P,UTCPDP + MOVE U,UTCSAV + MOVE TT,-2(U) + MOVEM TT,UTCBRK + JRST (U) + +] ;KS10P + +$INSRT SYSJOB ;SYSTEM JOB AND RELATED STUFF + + +SUBTTL DCHNTB AND DCHNTC + +EBLK +CHSPUR: BLOCK 8 ;NUM OF SPURIOUS INTS PER CH (ZERO = DCHK) +BBLK + +IFE KS10P,[ ; KS10 doesn't even pretend to have devices. + +;***** DCHNTB ***** +;4.9 = KNOWN DEVICE +;4.8 = HAS PIA 2 +;4.7-4.4 PIA 2 SHIFT +;4.3-4.1 PIA 2 ACTIVE VALUE +;3.9 = PIA 2 MAY BE ZERO +;3.8 = HAS PIA 1 +;3.7-3.4 PIA 1 SHIFT +;3.3-3.1 PIA 1 ACTIVE VALUE +;2.9 = PIA 1 MAY BE ZERO +;2.8 = ALLOW USER DATAI, BLKI +;2.7 DATAO, BLKO +;2.6 CONI, CONSO, CONSZ +;2.5 CONO +;2.4 SPECIAL KL10 DEVICE, BLKI/BLKO ARE DATAI/DATAO TO A SECOND DEVICE REGISTER +;1.6-1.1=N, IF NON ZERO: IGNORE DEV UNLESS CONI BIT N-1 IS ON + ;(IF DSDEV PRESENT) + +;***** DCHNTC ***** +;4.9 = SUSPICIOUS DEVICE +;4.8 = FOUND CLOBBERED +;4.7 = SUSPECTED OF CAUSING SPURIOUS INTS +;4.6-4.4 = CHANNEL CAUSING INTS ON +;3.9-3.1 = SUSPICION COUNT +;2.9-1.1 = CONI + +DCHNTB: +IFE KL10P,[ + 400200+APRCHN,,240000 ;0 APR + SETZ ;4 PI +] +IFN KL10P,[ + 400200+APRCHN,,250000 ;0 APR (ALLOW DATAI, "BLKI", CONI) + SETZ 010000 ;4 PI (ALLOW NOTHING) +] + +DEFINE DCHENT D,W +LOC DCHNTB+D_-2 + W + TERMIN + +IFN KL10P,[ + DCHENT PAG,SETZ 240000 ;ALLOW DATAI, CONI, BUT NOT "BLKI" + DCHENT CCA,SETZ ;ALLOW NOTHING +;XCTR of some of the instructions for these devices fails to relocate +;the address to user space, due to bugs in the hardware. Flush 'em. +; DCHENT TIM,SETZ 250000 ;ALLOW DATAI, "BLKI", CONI +; DCHENT MTR,[400201,,250000] ;INTERVAL TIMER PIA=1. ALLOW DI,BI,CI + DCHENT TIM,SETZ ;20 ALLOW NOTHING + DCHENT MTR,SETZ ;24 ALLOW NOTHING + DCHENT 30,SETZ ;30 RESERVED +] +IFN DSDP, DCHENT DSDEV,[REPEAT 2,400200+DSDCHN,,440000] ;20,24 +IFN DL10P,[ DCHENT DLB,SETZ 240000 ;60 DL10 + DCHENT DLC,[400200+TTYCHN,,240000] ;64 DL10 +] +IFN STKP, DCHENT STK,[400200+LPTCHN,,440000] ;70 STK +IFN PTRP, DCHENT PTP,[400200+PCHCHN,,440000] ;100 PTP +IFN PTRP, DCHENT PTR,[400200+PTRCHN,,440000] ;104 PTR +IFN NOTYS, DCHENT TTY,[400200+TTYCHN,,40000] ;120 TTY +IFN OLPTP, DCHENT OLPT,[400200+LPTCHN,,440000] ;124 OLPT +IFN 340P, DCHENT DIS,[630600+DISCHN+SDCHN_9,,440001] ;130 DIS +IFN E.SP, DCHENT DIS,[400200+DISCHN,,440000] ;130 E&S +IFN KL10P, DCHENT DTE,[400200+IFE PDCLKP,[APRCHN].ELSE [TTYCHN],,240000] ;200 DTE20 +IFN RP10P, DCHENT DPC,[400200+DSKCHN,,440000] ;250 DPC +IFN RH10P, DCHENT DSK,[400200+DSKCHN,,040000] ;270 RH10 +IFN NUNITS,[ +IFE NEWDTP,[ + DCHENT DC,[400000,,440000] ;200 DC + DCHENT UTC,[400200+UTCCHN,,440000] ;210 UTC + DCHENT UTS,[SETZ 40000] ;214 UTS +] +IFN NEWDTP,[ + DCHENT DTC,[630600+UTCCHN+DCCHN_9.,,440000] ;320 + DCHENT DTS,[SETZ 40000] ;324 +] +] ;END OF IFN NUNITS +IFN TM10P,[ + DCHENT MTC,[400230+MTCCHN,,440001] ;340 MTC + DCHENT MTS,[SETZ 40001] ;344 MTS +] +IFN MTYP, DCHENT MTY,[400200+TTYCHN,,40000] ;400 MORTON BOX + ;420 SPACEWAR CONSOLES +IFN DMIMP, DCHENT FI,[400230+NETCHN,,400000] ;424 DM IMP HARDWARE +IFN NDAP, DCHENT 454,[400200,,760000] ;454 D/A +IFN KAIMP, DCHENT IMP,[400000,,400001] ;460 AI-KA/ML-KA/MC-KL IMP + ; HARDWARE THIS SAYS IMP + ; HAS NO PIA BECAUSE IT + ; CHANGES +IFN NLPTP, DCHENT NLPT,[400200+LPTCHN,,440000] ;464 NEW LPT +IFN CH10P, DCHENT CHX,[400200+CHXCHN,,040000] ;470 CHAOSNET +IFE KL10P, DCHENT 500,[400000,,240000] ;500 ML-KA, DM CALENDAR; AI-KA R CLK +IFN KL10P&PDCLKP,DCHENT 500,[400200+APRCHN,,240000] ;500 MC-KL F CLK +IFN ARMP, DCHENT TIPDEV,[400200+TIPBCH,,440000] ;504 ARM TIP BREAK +IFE MCOND AIKA, DCHENT 510,[400000,,360000] ;510 ANOTHER D/A?? + ;DOES ANYONE KNOW WHAT DEVICE 510 IS?? +IFN RBTCP, DCHENT RBTCON,[400200+TABCHN,,440001] ;514 ROBOT CONSOLE +IFN ARMP, DCHENT 564,[400200,,440000] ;564 ARM TACTILE SENSE +IFN OMXP, DCHENT OMPX,[400200+OMPCHN,,440001] ;570 OMX +IFN IMXP, DCHENT MPX,[SETZ 40001] ;574 IMX +;Comment this out since the AI-KA one is no longer on the bus +;IFN TK10P, DCHENT NTY,[400200+TTYCHN,,40000] ;600 NTY +IFN NTYP, DCHENT NTY,[400200+NTYCHN,,40000] ; NTY FOR 11 KLUDGE +IFN DPKPP, DCHENT DPK,[400200+TTYCHN,,40000] ;604 DATAPOINT KLUDGE +IFN DC10P,[ + DCHENT DC0,[400200+DSKCHN,,40000] ;610 DC0 + DCHENT DC1,[400000,,] ;614 DC1 +] +IFN VIDP, DCHENT NVDX,[REPEAT 4,400200+NVDCHN,,440001] ;620-634 BAT +IFN PLTP, DCHENT PLT,[400200+PLTCHN,,440000] ;654 PLT + DCHENT 704,[400000,,440000] ;704 ??? +IFN HCLKP,[ + DCHENT CLK1,[400200,,240000] ;710 CLK1 + DCHENT CLK2,[SETZ 40000] ;714 CLK2 +] +LOC DCHNTB+127. +EBLK +DCHNTC: BLOCK 128. +DCACS: BLOCK 20 ;SAVE ACS +CCSDEV: 0 ;+ => SOME SUSPICIOUS DEVICES +BBLK + +DCHK: 0 ;TO CALL FROM DDT + MOVEM 17,DCACS+17 + MOVEI 17,DCACS + BLT 17,DCACS+16 + MOVEI J,0 + JSP E,SPUR + SKIPN W + AOS DCHK + MOVEI 17,DCACS + BLT 17,17 + JRST @DCHK + +;CHECK FOR CLOBBERED DEVS, CALL WITH JSP E, +CHECK: JSP H,DCSTUP +CHECK1: SKIPL TT,DCHNTB(I) + JRST CHECK4 ;UNKNOWN DEVICE +IFN DSDP,[ + TRNN TT,77 + JRST CHECK2 + ANDI TT,77 + JSP H,DCCONI + LSH B,-1(TT) + JUMPGE B,CHECK4 + MOVE TT,DCHNTB(I) +] +CHECK2: JSP H,DCCONI + TLNN TT,200 ;SKIP IF PI TO TEST + JRST CHECK4 + LDB T,[250400,,TT] ;GET SKIP + MOVEI Q,7 + LSH Q,(T) + AND B,Q + LDB Q,[220300,,TT] ;GET CHANNEL + LSH Q,(T) + CAME B,Q + JRST CHECK5 +CHECK3: LSH TT,-9 ;SHIFT TO PIA2 + JRST CHECK2 + +CHECK5: JUMPN B,CHECKL ;JUMP IF NONZERO AND WRONG + TRNE TT,400000 ;SKIP IF CAN NOT BE ZERO + JRST CHECK3 ;ZERO OK + JRST CHECKL + +CHECK4: ADD A,[400,,] ;INCREMENT DEVICE CODE + AOBJN I,CHECK1 +SPURCX: SKIPE C + BUG PAUSE,[BITS ],OCT,C,[MAY BE STUCK ON IN I/O BUS] + MOVSI T,SCLCK5 + SKIPE W ;SKIP IF NO TROUBLE DETECTED + IORM T,SUPCOR + JRST (E) + +DCSTUP: MOVE A,[CONI B] ;SET UP + MOVEI W,0 + MOVNI C,1 + MOVSI I,-128. + JRST (H) + +DCCONI: XCT A + AND C,B + SKIPL DCHNTC(I) ;SKIP IF DEVICE ALREADY SUSPICIOUS,SAVES FIRST SUSPICIOUS + HRRM B,DCHNTC(I) ;STORE AWAY CONI + JRST (H) + +CHECKL: JSP H,DCSAOS + MOVSI T,600000 ;CLOB + IORM T,DCHNTC(I) + JRST CHECK3 + +DCSAOS: MOVE D,A ;MAKE A CONO + TDZ D,[40,,-1] + SKIPL T,DCHNTB(I) ;SKIP IF KNOWN DEV + JRST DCSAS2 ;JUST RESET UNKNOWN TO ZERO + TLNE T,200000 ;SKIP IF NO PIA2 + TLNE T,400 ;SKIP IF PIA2 CAN NOT BE ZERO + JRST DCSAS1 + LDB TT,[330300,,T] ;GET PIA2 + LDB T,[360400,,T] ;GET PIA2 SHIFT + LSH TT,(T) + IOR D,TT ;ADD CORRECT CANNEL TO CONO + MOVE T,DCHNTB(I) ;SKIP IF NO PIA1 +DCSAS1: TLNE T,200 ;SKIP IF PIA1 CANNOT BE ZERO + TRNE T,400000 + JRST DCSAS2 + LDB TT,[220300,,T] ;GET P1A 1 + LDB T,[250400,,T] ;GET PIA 1 SHIFT + LSH TT,(T) ;OR IN PIA 1 + IOR D,TT ;ZAP +DCSAS2: XCT D + HLRZ T,DCHNTC(I) + TLNN T,300000 + AOS W ;THIS MAY BE THE CAUSE OF OUR TROUBLES + ANDI T,777 + AOS T + AOS CCSDEV + CAILE T,777 + SOJA T,[JRST 4,.+1] ;LOSEY LOSEY + DPB T,[221100,,DCHNTC(I)] + JRST (H) + +;CHANNEL IN J SPURIOUS INTERRUPT ON, CALL WITH JSP E, +SPUR: SKIPL J + CAIL J,10 + JRST 4,SPUR1 + AOS U,CHSPUR(J) +SPUR1: MOVE U,E + JSP E,CHECK + MOVE E,U + JSP H,DCSTUP +SPUR2: SKIPGE TT,DCHNTB(I) + JRST SPUR4 + JSP H,DCCONI + JUMPGE B,SPUR4 + JSP H,DCSAOS + MOVSI T,500000 + IORM T,DCHNTC(I) + DPB J,[360300,,DCHNTC(I)] +SPUR4: ADD A,[400,,] + AOBJN I,SPUR2 + JRST SPURCX + +] ;IFE KS10P + +IFN KS10P,[ + +SUBTTL KS10 UNIBUS + +DEFINE UBINT VEC,-REST +.VEC.== +IFN .VEC.&3, .ERR Bogus interrupt vector: VEC +.VEC.==.VEC./4 +IFL .VEC.-.MIN., .MIN.==.VEC. +IFG .VEC.-.MAX., .MAX.==.VEC. +IF2,[ +LOC .BAS.+.VEC. + REST +];IF2 +TERMIN + +NUBIDV==0 + +DEFINE UBIDV VEC +.VEC.== +CONC [UB]\NUBIDV,NM==:<.UBA.,,.VEC.> +CONC [UBINT .VEC., JSR UB]\NUBIDV,BK +NUBIDV==NUBIDV+1 +TERMIN + +;;; +;;; Interrupt table for Unibus Q. +;;; +UBAQIT: +.UBA.==UBAQ +.MIN.==777777 +.MAX.==0 +IF2, .BAS.==UBAQIB + +UBINT PHVEC, JSR DSKBRK ; RH11 FOR DISK + +UBAQIB==:UBAQIT-.MIN. +LOC UBAQIB+.MAX.+1 + +;;; +;;; Interrupt table for Unibus I. +;;; +UBAIIT: +.UBA.==UBAI +.MIN.==777777 +.MAX.==0 +IF2, .BAS.==UBAIIB + +IFE TM03S, UBIDV 224 ; Tape +UBIDV 300 ; NI1010 In +UBIDV 304 ; NI1010 Out +IFL DZ11NB-4,[ +REPEAT 4-DZ11NB,[ +UBIDV 340+<10*> ; DZ In +UBIDV 344+<10*> ; DZ Out +]] + +IFN TM03S,[ +UBINT %TMVEC, JSR MGHBRK ;RH11 FOR TAPE +] + +REPEAT DZ11NB,[ +UBINT 340+<10*.RPCNT>, CONC JSR DZ,\.RPCNT,RB ; DZ receive +UBINT 344+<10*.RPCNT>, CONC JSR DZ,\.RPCNT,XB ; DZ transmit +];REPEAT DZ11NB + +IFN KSIMP,[ +UBINT %LHVEC, JSR IMPIBK ;IMP Input side break +UBINT %LHVEC+4, JSR IMPOBK ;IMP output side break +] + +IFN CH11P,[ +UBINT 270, JSR CHXBKH ; Usual Chaosnet vector +UBINT 230, JSR CHXBKH ; Except some interrupt here instead +];CH11P + +UBAIIB==:UBAIIT-.MIN. +LOC UBAIIB+.MAX.+1 + +;;; Assignment of pages in Unibus pager for DMA devices. +;;; All of the Q UBA is statically assigned. The lower half of the I +;;; UBA is statically assigned, while slots in the upper half of the I UBA +;;; are assigned dynamically by the UBAASL routine and freed by the +;;; UBAFSL routine below. +;;; +;;; Note that static pages are 2000 PDP-10 words long (ITS sized) rather +;;; than 1000 (DEC sized). Each page here thus occupies -two- locations in +;;; the Unibus pager. There are 32. such pages on the Q Unibus and 16. +;;; such pages on the I unibus. +;;; +;;; Slots handed out by UBAASL are good for mapping 1000 PDP-10 words +;;; (one DEC page, and coincidentally the size of a network buffer). +;;; The number obtained from UBAASL is a direct index into the UBA +;;; paging RAM, and will range from 32. to 63. +;;; +;;; This two different page size thing is all a mess and I should fix it +;;; sometime. +;;; +;;; Unibus Q: +QUBPG==:5 ; Chosen at random. + +;;; Unibus I: + +;;; Static pages +IFN TM03S,[ +IUTPG==:5 ;Magtape IO page. well, 5 worked last time +] + +IFN KSIMP,[ +IUIMPG==:6 ;IMP Data transfer page +] + +;;; Dynamic pages + +EBLK +UBAIFS: 777777777760 ;Slot map, bit on if free +BBLK + +; Allocate a UBA I slot +; Return +1, A/ slot index + +UBAASL: PUSH P,B + CONO PI,PIOFF + MOVE A,UBAIFS + JFFO A,UBASL1 + CONO PI,PION + POP P,B ;Clean up for no good reason + BUG HALT,[Out of UBA slots] + +UBASL1: MOVNS B + MOVSI A,400000 + LSH A,B ;A/ bit to snarf + ANDCAM A,UBAIFS + CONO PI,PION + MOVN A,B + ADDI A,32. ;First dynamic slot + POP P,B + POPJ P, + +; Deallocate the UBA slot in A +; A/ UBA index to free. Bashes A,TT +UBAFSL: CAIL A,32. + CAIL A,64. + BUG HALT,[Bad UBA index],OCT,A ;Paranoid for now + MOVEI A,-32.(A) + MOVNS A + MOVSI TT,400000 + LSH TT,A + IORM TT,UBAIFS + POPJ P, + +SUBTTL UBI DEVICE + +UBIDVS:: +REPEAT NUBIDV,[ +EBLK + 0 ; Bit in -7(I) + -1 ; User or -1 in -6(I) + 0 ; Count in -5(I) + 0 ; Saved I in -4(I) +CONC UB,\.RPCNT,BK: + 0 +BBLK + MOVEM I,.-2 + JSP I,UBIBRK +CONC UB,\.RPCNT,DV: + JRST 12,@ + CONC UB,\.RPCNT,NM ; Name in 1(I) +IFE .RPCNT, LUBIDV==:.-UBIDVS +];REPEAT NUBIDV + +UBINAM==:1 +UBISVI==:-4 +UBICNT==:-5 +UBIUSR==:-6 +UBIBIT==:-7 + +UBIBRK: AOS UBICNT(I) + EXCH U,UBIUSR(I) + JUMPL U,UBIBK9 + EXCH T,UBIBIT(I) + TDNE T,MSKST2(U) + IORM T,IFPIR(U) + EXCH T,UBIBIT(I) +UBIBK9: EXCH U,UBIUSR(I) + HRLI I,UBISVI(I) + JRA I,(I) + +EBLK +UBISW: -1 ? 0 +BBLK + +; .OPEN +UBIO: MOVEI T,NUBIDV + SKIPA I,[UB0DV] +UBIO1: MOVEI I,LUBIDV(I) + CAME A,UBINAM(I) + SOJG T,UBIO1 + JUMPLE T,OPNL4 ; FILE NOT FOUND + PUSHJ P,SWTL + UBISW + SKIPL UBIUSR(I) + JRST OPNL23 ; FILE LOCKED + MOVEI T,(R) + SUBI T,IOCHNM(U) + MOVE T,CHNBIT(T) + MOVEM T,UBIBIT(I) + HRRZM U,UBIUSR(I) + HRLZI T,(I) + HRRI T,DNUBI + MOVEM T,(R) + JRST LSWPJ1 + +; .IOPUSH/.IOPOP +UBIIOP: HLRZ A,(R) + JUMPE I,UBIOP7 + SUBI R,IOCHNM(U) + SKIPA R,CHNBIT(R) +UBIOP7: SETZI R, + MOVEM R,UBIBIT(A) + POPJ P, + +; .CALL WHYINT +UBIWHY: MOVE B,UBICNT(A) + MOVEI A,%WYUBI + JRST POPJ1 + +; .CALL RFNAME +UBIRCH: MOVE B,UBINAM(A) + POPJ P, + +; .CLOSE +UBICL: SETOM UBIUSR(A) + POPJ P, + +] ;KS10P + +SUBTTL OVERHEAD METERING ROUTINE + +IFN KL10P,[ + +EBLK +;TABLE OF OVERHEAD REGIONS. ENTRY IS SIXBITNAME,,PC ? COUNT + 0 ;COUNTS STUFF BEFORE FIRST OVHMTR MACRO +OVHTBL: OVHTAB + 'USR,,-1 + 0 ;COUNTS USER-MODE PC'S +LOVHTB==.-OVHTBL + +;COME HERE ON PI CHANNEL 1 EVERY 39 MILLISECONDS +OVHSVA: 0 +OVHSVB: 0 +OVHBRK: 0 +BBLK + CONO TIM,060000+3900. ;CLEAR DONE + EXCH T,OVHBRK ;GET PC INTERRUPTED OUT OF + TLNE T,%PSUSR ;ONLY METER IF EXEC MODE + JRST OVHBRX + MOVEM A,OVHSVA + MOVEM B,OVHSVB + MOVSI A,-LOVHTB +OVHBR1: HRRZ B,OVHTBL(A) + AOBJN A,.+1 ;2-WORD ENTRIES + CAIG B,(T) ;SKIP IF PC LIES IN PREVIOUS REGION + AOBJN A,OVHBR1 + SKIPGE A ;IN CASE T = 777777 + AOS OVHTBL-2(A) ;AOS PREVIOUS REGION'S COUNT + MOVE B,OVHSVB + SKIPA A,OVHSVA +OVHBRX: AOS OVHTBL+LOVHTB-1 ;AOS COUNT OF USER-MODE PC's + EXCH T,OVHBRK + JRST 12,@OVHBRK +];KL10P + +IFN KS10P,[ +RDPCST=DATAI 14, ;INSTRUCTIONS FOR PC SAMPLING TABLE +WRPCST=DATAO 14, + +;TABLE OF OVERHEAD REGIONS. ENTRY IS PC,,SIXBITNAME +OVHTB1: 0,,'LOW ;LOWER FENCE + OVHTAB + 377777,,'USR ;UPPER FENCE +LOVHTB==.-OVHTB1 +REPEAT <1_<36.-<.LZ >>>-LOVHTB, 377777,,-1 ;PAD TO POWER OF TWO SIZE + +EBLK + +OVHTB2: BLOCK LOVHTB ;CORRESPONDING COUNTS (LAST IS FOR USER MODE) + +OVHCNT: 28. ;COUNTER TO SLOW THINGS DOWN TO CUT OVERHEAD + +LOVHPC==100 ;64 SAMPLES SHOULD BE ENOUGH +OVHPCS: BLOCK LOVHPC + +BBLK + +;CALCULATE OVERHEAD USING PC SAMPLE TABLE +;CLOBBERS A,B,C +OVHCLK: SOSL OVHCNT ;TIME TO DO IT YET? + JRST OVHCL9 ;NO, IGNORE THESE SAMPLES + MOVEI A,28. ;SEE ONLY ONE SAMPLE OUT OF EVERY 29 ON AVERAGE + MOVEM A,OVHCNT ;SO TIME SPENT IN THIS ROUTINE IS NOT EXCESSIVE + RDPCST C ;SEE HOW FULL THE PC SAMPLING TABLE IS + HRLOI C,-OVHPCS-1(C) + EQVI C,OVHPCS ;AOBJN POINTER TO SAMPLES ACTUALLY TAKEN + JUMPGE C,OVHCL9 ;NONE + CAMGE C,[-LOVHPC,,OVHPCS] + JRST OVHCL9 ;BOGUS AOBJN POINTER, MAYBE PCST NOT TURNED ON +OVHCL1: MOVE A,(C) ;NEXT SAMPLED PC + TLNE A,%PSUSR ;ONLY SEARCH TABLE IF EXEC MODE + JRST OVHCL8 ;ALL USER MODE PC'S ARE COUNTED IN LAST BUCKET + HRLO A,A ;-1 IN RH IS GREATER THAN ANY SIXBIT + MOVEI B,1_<35.-<.LZ >> ;HALF THE SIZE OF THE TABLE +REPEAT <36.-<.LZ >>,[ ;LOG SEARCH + CAMG A,OVHTB1(B) ;NOT CAMGE BECAUSE OF PADDING AT END + SUBI B,1_<35.-.RPCNT-<.LZ >> + ADDI B,1_<34.-.RPCNT-<.LZ >> +] + LOC .-1 ;OPTIMIZE OUT ADDI B,0 + AOSA OVHTB2(B) +OVHCL8: AOS OVHTB2+LOVHTB-1 + AOBJN C,OVHCL1 +OVHCL9: WRPCST [-LOVHPC,,OVHPCS] ;TURN ON / RESTART PC SAMPLING + POPJ P, +];KS10P + +;HERE IS A TABLE OF REGISTERED 3-LETTER OVERHEAD REGION CODES + +;ALC - ALLOCATE CORE PAGE FRAME +;CHx - CHAOSNET STUFF (VARIOUS VALUES OF x) +;FLT - MISCELLANEOUS FAULTS +;IMP - ARPANET INTERRUPT (NOT STYNET) +;LOW - LOW CORE, BEFORE FIRST OVHMTR MACRO & PCS IN UPPER HALF OF EXEC SPACE +;NET - ALL NETWORKS, ALL PI LEVELS, NOT OTHERWISE ACCOUNTED FOR +;PGF - PAGE FAULT +;PPI - PPIUM +;QIN - DISK INTERRUPT LOW LEVEL +;QSC - DISK INTERRUPT HIGH LEVEL, DISK SCHEDULER +;SC1 - SCHEDULER 1 - ENTRY +;SC2 - SCHEDULER 2 - SEARCH +;SC3 - SCHEDULER 3 - EXIT +;SC4 - SCHEDULER 4 - UNSWAPBLOCK +;SLW - SLOW CLOCK +;SWF - SWAP FIND NEW USER (SWAPOUT SCHEDULER) +;SWP - SWAP PAGE +;SWS - SWAP SCHEDULER +;SWU - SWAP USER +;TTI - TTY INPUT INTERRUPT LEVEL +;TTO - TTY OUTPUT INTERRUPT LEVEL +;TTY - MISC TTY CODE +;USR - USER MODE +;UUO - UUO LEVEL, MISCELLANEOUS ROUTINES, AND TOTAL MISCELLANY +;WS - WORKING SET & SWAP-BLOCK ENTRY CODE + +SUBTTL PC LSR TEST FEATURE + +;CALLED BY PCLT MACRO +;WHICH ASSEMBLES +;SKIPE PCLDBM +;PUSHJ P,PCLTST + +PCLTST: PUSH P,U + MOVE U,PCLIDX + MOVEM U,PCLHT + MOVE U,USER + CAME U,PCLUSR + JRST POPUJ +PCLX: CAIA ;PATCH IN OTHER CHECKS (SHOULD JRST POPUJ TO IGNORE) + MOVE U,USER ;PATCH ROUTINE MAY CLOBBER U + AOSN PCLNXT + JRST PCLT1 ;FOUND PLACE, CAUSE PCLSR + HRRZ U,-1(P) + CAME U,PCLL + JRST POPUJ ;NOT MARK (NOT AT RIGHT LOCN) + HRRO U,USER ;4.9 U FLAG +PCLT1: PUSH P,A ;COMPUTE HASH ADR OF RETURNS ON PDL + PUSH P,B + PUSH P,C + HRREI A,-USRSTG(P) + JUMPL A,PCLT1A ;SYS JOB'S PDL? + IDIVI A,LUBLK + IMULI A,LUBLK + MOVEI A,USRPDL(A) ;GET START OF USERS PDL IN A +PCLT3: HRRZ B,(A) + JUMPE B,PCLT2 + CAIL B,HSYSCD + JRST PCLT2 + HLRZ C,-1(B) + TRZ C,37 + CAIE C,(PUSHJ P,) + JRST PCLT2 + XOR B,PCLHT + ROT B,1 + MOVEM B,PCLHT +PCLT2: CAIGE A,-2-3(P) + AOJA A,PCLT3 + MOVE A,PCLHT ;COMPUTED HASH + JUMPGE U,PCLT4 ;GOING TO PCLSR HERE, STORE HASH AS MARK FOR NEXT TIME + CAME A,PCLHSH + JRST PCLT5 + SKIPGE PCLDBM + JRST PCLT6 ;IN HOLD MODE, PCLSR HERE + SETOM PCLNXT ;FOUND MARK, PCLSR NEXT TIME +PCLT5: POP P,C + POP P,B + POP P,A + JRST POPUJ + +PCLT4: MOVEM A,PCLHSH ;STORE HASH FOR NEXT TIME + HRRZ A,-3-1(P) + MOVEM A,PCLL +PCLT6: CONO PI,CLKOFF + MOVE B,PCLDBM + MOVEI A,%PIC.Z + CAIN B,1 ;DON'T ^Z. + IORM A,PIRQC(U) + POP P,C + POP P,B + POP P,A + POP P,U + JRST PCLME + + PUSHJ P,PCLME1 +PCLME: PUSHJ P,UFLS + JRST 4,. + +PCLME1: PUSHJ P,PCLSR + JFCL + JRST POPJ1 + +PCLT1A: TRNE U,-1 + JRST 4,. + JRST 4,. ;TEMP MODIFY END CHECK IF WANT TO WIN FOR SYS JOB + +SUBTTL ILLUO NON-RELEVANT SYSTEM CALLS +IFE E.SP,[ + ADSTEP==URET + ADCONT==URET + ADWORD==URET +] +IFE 340P\E.SP,[ + ADSTAR==URET + ADCLOS==URET + ADSTOP==URET + ADSTL==URET +] +IFE 340P,[ + ALTPEN==URET + ANDIS==URET +] +IFE VIDP,[ + AVSCAN==ILUUO + AVSTST==ILUUO +] +IFE IMXP,[ + APOTSET==ILUUO +] +IFE PDP6P,[ + AIPDP==ILUUO +] +IFE NMTCS,[ + AMTAPE==ILUUO +] + +IFE ARMP,[ + AARMOV==ILUUO + AARMRS==ILUUO + AARMOF==ILUUO +] +IFE PTRP,[ + AFEED==CPOPJ +] +IFE RBTCP,[ + ARBTC==ILUUO +] +IFE NETP,[ + ANETIM==OPNL1 ;NO SUCH DEVICE ERROR FOR SYMBOLIC SYSTEM CALLS. + ANETBL==OPNL1 + ANETHS==OPNL1 +];NETP +IFE NCPP,[ + ANETAC==CPOPJ ;MAKE OLD UUOS FAIL + ANETIN==CPOPJ +];NCPP + +IFE NUNITS,[ + AUBLAT==URET + AUTNAM==URET + AUINIT==URET + AUDISM==URET + AASSIGN==URET + ADESIGN==URET +] + +;Here generate the table for the BUG macro. Note that entries for +;bugs in the initialization code will appear here also! That's +;why we have the kludgey add 10 +BUGTAB: BLOCK LBUGTB+10 +LBUGT2==.-BUGTAB + 0 ;Marks end of table + +CONSTANTS +HSYSCD:: ;HIGHEST SYSTEM CODE + +SUBTTL RANDOM STORAGE +EBLK + +SCHHP: SCHHB ;PNTR TO SCHED HIST BUFFER +SCHHB: BLOCK SSCHDB ;SCHED HIST BUFFER + ;4.9 =1 EXEC + ;4.8 =1 QUANT TERMINATED BY PG FAULT + ;4.7-3.8 LENGTH OF RUN TIME IN 512 USEC UNITS + ; MUST ACCOMODATE 150 MILLISECOND QUANTA + ;3.7-3.1 USER ("NUMERIC INDEX) + ;RH PC QUANT STARTED AT +SWPHTP: SWPHTB +SWPHTL==200 +SWPHTB: BLOCK SWPHTL ;SWAPPING HISTORY TABLE + ;4.9-4.8 EVENT: 0=START LOADING, 1=FINISH LOADING, + ; 2=SWAP OUT, 3=SWAP BLOCK + ;4.7-3.9 WORKING SET SIZE MINUS ONE (0=0) + ;3.8-3.1 USER NUMBER + ;2.9-1.1 RH(TIME) + BLOCK SWPHTL ;CORRESPONDING UTRNTM + +PGIHTP: PGIHTB +PGIHTL==200 +PGIHTB: BLOCK PGIHTL ;PAGE-IN HISTORY TABLE + ;4.9 1 IF JOB WAS LOADING + ;4.7-3.9 USER VIRTUAL PAGE NUMBER + ;3.8-3.1 USER NUMBER + ;2.9-1.1 RH(TIME) + BLOCK PGIHTL ;CORRESPONDING UTRNTM + +IFN SCHBLN,[ +SCHMNY: 0 ;0 DO FULL SCHEDULE, -1 NEXT "SCHEDULE" SHOULD LOOK IN SCHBTB +SCHBNJ: 0 ;NUMBER OF VALID ENTRIES IN SCHBTB +SCHBTB: BLOCK SCHBLN ;RUNNABLE JOB BUFFER +SCHBPR: BLOCK SCHBLN ;PRIORITIES OF THOSE +NSCHOV: 0 ;COUNT OF BUFFER OVERFLOWS +] +;TRANSLATION ENTRY _ T +;TRANLK(T) IS MODE,,NEXT ENTRY +;MODE IS 0 IF ENTRY ON FREE LIST, ELSE NOT 0, AND + ;BITS 3.1 => INPUT, 3.2 => OUTPUT, 4.9 => ATOMIC TRANSLATION (DON'T RETRANSLATE) +;NEXT-ENTRY IS -1 FOR NIL, ELSE IDX REL TRAN!X +;TRANID(T) THRU TRANIS(T) - FROM-NAMES +;TRANOD(T) THRU TRANOS(T) - TO-NAMES + +TRANLK: REPEAT SIOMT,,,.RPCNT-1 ;GENERATE 1ST WDS, LINKED TOGETHER. +TRANID: BLOCK SIOMT +TRANI1: BLOCK SIOMT +TRANI2: BLOCK SIOMT +TRANIS: BLOCK SIOMT +TRANOD: BLOCK SIOMT +TRANO1: BLOCK SIOMT +TRANO2: BLOCK SIOMT +TRANOS: BLOCK SIOMT + +TRANFL: SIOMT-1 ;TRANSL ENTRY FREE LIST. +TRNCNT: 0 ;NUM ENTRIES IN USE. +TRNREF: 0 ;NUM. READ-ONLY ACCESSES TO TRANSL LISTS. +TRANSW: -1 ;SWITCH FOR WRITE REF. + 0 + +IFE SCHBLN, U0P: 0 ;PRIORITY OF BEST USER SO FAR + +USER: -1 ;USER # OF CURRENT LOSER +SYSL: SYSB*2000 +LITM: 0 ;LAST TIME SYS INCREASED CORE + +SLGIV: BLOCK 3 ;LOGIN + +SETSLC: 0 ;SETLOC VARIABLES +SETSLQ: 0 +SETSU: -1 + +SWUNAM: 0 ;SYS WRITE VARIABLES +SWJNAM: 0 +SWFN1: 0 +SWFN2: 0 +SWFN3: 0 +SWMOD: 0 + +DMON: SIXBIT /DRAGON/ + -1 ;USER INDEX OF DEMON JOB + +NQMFWR: 0 ;COUNT OF FILES WRITTEN ON .MAIL. - FOR MAILER DEMON TO HANG ON. +IFN XGP,[ +NXGPFW: 0 ;COUNT OF FILES WRITTEN ON .XGPR. - FOR XGPSPL +] + +;DEAMON VARIABLES +;VARIABLES FOR DEAMON CODE HACK +IFN DEMON,[ + +IFN TTLPTP,TPLFLG: 1 ;FLAG FOR TPL + +DMTLL==4 ;LEGNTH OF DEAMON TABLE SLOT +NODEAM==20. ;NUMBER OF SLOTS +DMLNG==NODEAM*DMTLL + +DEMSW: 0 + 0 ;MAIN PROG SWITCH FOR DEMON +REQCNT: 1 ;COUNT OF REQUEST'S FOR SYS JOB +DMTPTR: 0 ;POINTER FOR DEMSIG TO DEM TBL, AN INDEX INTO IT, TAKEN MODULO DMLNG +DMLSEX: -DMLNG,,0 ;POINTER TO DEAMON TABLE AOBJN +DEMCNT: ;AMOUNT OF SLOTS REMAINING IN THE TABLE + +DMBLK: 0 + 0 ;SLOT FOR NON DEAMON LOAD VIA NUJBST + +DMOBLK: SIXBIT / SYS/ + SIXBIT /ATSIGN/ + 0 ;BLOCK USED BY SYSTEM JOB TO CHECK OPEN + +;DEAMON TABLE--CONSISTS OF SLOTS OF FOUR WORDS FOR EACH DEMON +;WORD 1 CONTAINS ITS SIXIT NAME +;WORD 2 CONTAINS THE USER INDEX,-1 IF LOADING, 0 IF DOWN +;WORD 3 2 QUANTITIES IN 18 BIT 2'S COMPLEMENT-- +;LH ALWAYS > = 0, IF 0 ONLY TAKES EXPLICIT REQUESTS IN > 0 A REQUEST +;RH CONTAINS THE NUMBER OF REQUESTS PENDING FOR THE DEAMON +;FOR THE DEAMON WILL BE GENERATED EVERY 2 MINUTES +;WORD 4 CONTAINS THE TIME TILL THE NEXT IMPLICIT REQUEST WILL BE GENERATED. + + +DMTTBL: SIXBIT /DEMSTR/ + 0 + 1 ;STARTUP DEAMON + 0 + +BLOCK *DMTLL +] +TIMOFF: -1 ;TIME SINCE MIDNIGHT IN HALF SECONDS ("TIME IN DSK FORMAT"). +QDATE: -1 ;DISK FORMAT DATE: -1 => SYSTEM DOESN'T KNOW DATE, ELSE + ;BITS 3.1-3.5 HAVE DAY OF MONTH, 3.6-3.9 HAVE MONTH OF YEAR, + ;4.1-4.7 HAVE YEAR MOD 100. . +QDATEI: -1 ;-1 => SYSTEM DOESN'T KNOW DATE, ELSE + ;DATE AND TIME THE DATE AND TIME WERE FIRST DETERMINED, IN DSK FORMAT. +PDYTIM: -1 ;TIME SINCE BEGINNING OF YEAR IN HALF-SECONDS (BACKUP TO PDCLK) +FYEAR: 0 ;YEAR (E.G. 1969.) +PDTIME: 0 ;NON-ZERO => OFFSET FOR PDCLK + ;WHEN SUBTRACTED FROM PDCLK DATAI GIVES # PD-UNITS SINCE + ; BEGINNING OF YEAR + ;ONE SECOND = 60. PD-UNITS + ; Also contains similar offset for KS-10 clock in 60ths. +LPDTIM: -1 ;LAST PD CLK TIME, -1 IF PD CLK NOT RUNNING OR JUST PDSET'ED + +SUPCOR: 0 ;CONTROLS SYS JOB, SEE SYSDTB, SCOR, ETC + ;EACH BIT REQUESTS ONE FUNCTION IF SET. +SUPCOP: SCLDAT+IFN DEMON,[SCLDMN],,SCRCKS + ;THIS WORD OR'D INTO SUPCOR EVERY SECOND. +SCKPHS: 0 ;USED FOR COUNTING EVERY SECOND 1/2 SECOND CLOCK + ;TO SET SUPCOP BITS EVERY SECOND +SYSITM: 0 ;TIME SYS JOB LAST STARTED WAITING ON SUPCOR +LNETIM: 0 ;TIME AT WHICH NETWORK WAS LAST BROUGHT UP +RSWTIM: 1 ;Time (in DSK format) when last checked system resources. + +MXPARS==10. ;MAX # PAR ERRS TO PRINT OUT +PARPG: BLOCK 8 ;STORAGE OF PAGE MAP WHILE HACKING PARITY ERROR CHECK +PARCNT: 0 ;# OF PAR ERROR ENTRIES IN TABLE +PARCON: BLOCK MXPARS ;CONTENTS OF BAD PARITY LOCATIONS +PARADR: BLOCK MXPARS ;ADDRESSES OF BAD PARITY LOCATIONS +PARAND: -1 ;QND OF ALL BAD WORDS +PARIOR: 0 ;IOR OF ALL BAD WORDS +PARAAN: -1 ;AND F ALL BAD ADDRS +PARAOR: 0 ;IOR OF ALL BAD ADDRS +IFE KA10P,[ +PARPFW: 0 ;PAGE FAIL WORD +PARERA: 0 ;ADDRESS OF PAR ERR +PARWRD: 0 ;BAD DATA +] ;IFE KA10P +IFN KL10P,[ +PARRSN: 0 ;0 => PAR ERR PAGE FAULT IN PROG + ;-1 => PAR ERR INTERRUPT; NEEDN'T STOP + ;THE RUNNING JOB. +] ;KL10P +PARDIE: 0 ;-1 => FATAL PARITY ERROR +TPLSWP: 0 ;-1 => USE OLP FOR TPL +IFN PDP6P,[ +PDP6UP: 0 ;0 => PDP6 IS DOWN. (AS USUAL) +] +IFN ECCMEM,[ +IFE MCOND AIKA,[ +ECCADR: 1,,777760 ;ECC HISTORY STARTS HERE +ECCLEN==16. ;16 LOCATIONS OF ECC HISTORY +ECCIDX: 0 ;LAST LOCATION ACCESSED +]] +IFN TEN11P,[ +TEN11F: 0 ;0 -> NORMAL + ;-1 -> COMPLETELY IGNORE 10-11 INTERFACE + ; 1 -> RESET 10-11 INTERFACE, OTHERWISE IGNORE +T11ERC: 0 ;COUNT OF CONTROL PAGE RAM ERRORS +T11CCN: 0 ;CORRECT CONTENTS +T11WCN: 0 ;WRONG CONTENTS +T11PG: 0 ;PAGE # INVOLVED +] +IFN N11TYS,[ +TVBLAD: 17742 ;VIDEO BUFFER TO FLASH WHEN JOB RUNNING (PDP10 VIDEO BUFFER ADDR) +] +IFN DL10P,[ +DL10F: -1 ;-1 NORMAL, 0 => 11 DOWN +DL10HC: 0 .SEE TTDLBRK ;NUMBER OF LOOPS WHEN HUNG UP WAITING FOR 11 TO GOBBLE BUFFER +] + +DLSRCH: 0 ;-1 => DON'T RUN ANY USER BUT THE ONE ALREADY RUNNING + ;(UNLESS WE TAKE A PAGE FAULT). +CPDLP: -CPDLL,,LCPDL-1 ;CLOCK PDL POINTER +LCPDL: BLOCK CPDLL ;CLOCK INT LEVEL PDL + +CLKBSW: 0 ;READ SWITCHES INTO HERE TO DECIDE WHETHER TO GO TO DDT. + +CLROOT: SSLCKB ;CLOCK QUEUE ROOT + +SSLCKB: SCLKI ;SLOW CLOCK RQ BLOCK + .+2 .SEE CHA5CK ;OR 15SCLB + JRST SSLCK + +IFN CHAOSP,[ +CHA5CK: 5*60.-SCLKI ;5-SECOND CLOCK FOR CHAOS NET + 15SCLB ;NOTE INITIAL TRIGGERING OF CLOCKS BELOW DELAYED AN EXTRA 5 SECONDS + JRST CHA5CL +];CHAOSP + +15SCLB: 15.*60.-SCLKI + .+2 .SEE PRVCLB ;OR VSLCKB + JRST 15SCLK + +IFE SWPWSP,[ +PRVCLB: NPVSEC*60.-15.*60.-SCLKI ;PRIVILEDGED USER VARIABLE CHECK + VSLCKB + JRST PRVCLK +];SWPWSP + +VSLCKB: 0 ;VERY SLOW CLOCK BLOCK + CLINFB ;CAUSE SLOW CLOCK TICK SOON AFTER SYS COMES UP + JRST VSSLCK + +CLINFB: 377777,,-1 ;ABOUT 15 YEARS + 0 + BUG ;? + +IFN CCLKP,[ +CCLKB: 0 ;FOR CHESS CLOCK HACK + -1 + JRST RCCLK +CCLK1: 0 +CCLK2: 0 +] + +IINTIC==60. ;# TWO-MINUTE TICKS PER VERY VERY SLOW CLOCK TICK (2 HOURS) +IINCNT: 0 ;# TWO-MINUTE TICKS REMAINING UNTIL NEXT VERY VERY SLOW CLOCK TICK +.SEE VSCLK + +IFN N11TYS,[ +WHOCLB: 0 ;WHO LINE TIMER + -1 + JRST WHOSET +] + +UTTYS: BLOCK MXCZS ;RING BUFFER FOR JOBS TO BE STARTED +UTTYI: UTTYS +UTTYO: UTTYS +UTTYCT: 0 + +PCLDBM: 0 ;.NE. 0 ACTIVATE PC LSR DEBUG MODE + ;1 => ADVANCE PLACE WHERE PCLSR + ;2 => ADVANCE BUT DON'T ^Z. + ;- HOLD +PCLUSR: -1 ;USER PCLSR MODE ACTIVE FOR +PCLL: 0 ;PLACE WHERE LAST PCLSR TESTED +PCLHSH: 0 ;HASH OF RETURNS ON PDL AT LAST PLACE TRAPPED OUT OF +PCLNXT: -1 ;-1 => FROB NEXT TIME IN ADVANCE MODE +PCLHT: 0 ;TEMP +PCLIDX: 0 ;INITIALIZE PCLT TO THIS (SET TO LOOP COUNT IF NECESSARY) + +CORRNR: 0 ;LAST USER TO RUN CORE +SJSPG: 0 ;-1 => LAST FREE PG RESERVED FOR SYS JOB; DON'T GIVE IT TO ANYONE ELSE. +UTBFLF: 0 ;-1 SIGNAL TO TRY TO FLUSH I/O BLOCKS +UFDFLF: 0 ;-1 SIGNAL TO TRY TO FLUSH 2311 UFDS +CORCNT: 0 +UFLSF: 0 ;FLAG FROM UFLS TO CLKBRK +CLKFL1: 0 ;FLAG COUNTER TO CONTROL CLOCK LEVEL +SCHFLG: 0 ;SCHEDULE TIMER (DIVIDES 60 CPS) +27FCLK: 0 ;-1 IF FAST CLOCK SHOULD CALL TYP27S +SCITM: 0 ;SEE SYSEX, SYSDEC +LCLK1: 0 +SYSCKP: -LTSTB,,TSTB ;SYSTEM CHECKSUMS CHECKER POINTER +SYSPDP: -LSYSP,,SYSPDL-1 ;PDL POINTER FOR SYSTEM JOB +SYSPDL: BLOCK LSYSP ;PDL FOR SYS JOB +IFN TPLP,TPLBUF: BLOCK TPLBSZ ;PSEUDO LPT BUFFER - MUST BE ABOVE SUACS +IFN TPLP\DEMON,TPLFNO: SIXBIT /!/ ;UNIQUE TPL FIRST FILE NAME +SJCFF: 0 ;-1 WHEN SYS JOB IN PROCESS OF FLUSHING CORE + ;AVOIDS TIMING ERROR DUE TO HUSRAD NOT REALLY REFLECTING WHAT ITS GOING TO BE +SLSWPR: 0 ;STORE SYS JOB'S LSWPR WHILE HACKING UUOS + +BBLK + +IFN TPLP, TPLFN: 2,,(SIXBIT /TPL/) +IFN KL10P,[ +KLEBCC: 0 ? <1_23.>/<4*25./2> ;EBOX COUNTER CONVERSION TO 4 USEC CONSTANT (FOR 25 MHZ) + ;RESULT IS IN AC+2 AFTER DMUL AC,KLEBCC +KLMBCC:; 1 ? 110000,, ;FOR CONVERTING AN MBOX COUNT TO THE TIME (IN EBOX UNITS) + ;IT SUPPOSEDLY AMOUNTS TO. + ;WE ASSUME 102.5 NANOSEC OD WAITING TIME PER MBOX CYCLE + ;THIS NUMBER IS 102.5/80. + ;DMUL AC,KLMBCC PUTS ANSWER IN AC+1, AC+2 + ;WITH BINARY POINT BETWEEN THE WORDS. + 0 ? 0 ;M8538 MODIFIED SO EBOX COUNTER CONTINUES TO COUNT + ;DURING MBOX WAIT TIME, SO SET KLMBCC = ZERO. +EBLK + +MTRUSR: -1 ;USER TO WHOM PERF CTR IS ASSIGNED +MTRJOB: -2 ;USER BEING MEASURED BY PERF CTR, + ;OR -1 => NULL JOB, OR -2 => ALL JOBS. + +PAEON: 0 ;SELECTED PERF CTR ENABLE WORD +PAEOFF: 0 ;DISABLE THE PERF CTR (WHEN WRONG JOB IS RUNNING) +STPERF: 0 ? 0 ;VALUE OF PERF COUNTER AT START OF QUANTUM +STEBOX: 0 ? 0 ;VALUE OF EBOX COUNTER AT START OF QUANTUM +STMBOX: 0 ? 0 ;VALUE OF MBOX COUNTER AT START OF QUANTUM +] ;KL10P +IFE KL10P, EBLK +IFN TPLP,[ +TPLFN1: 0 +TPLFN2: 0 +TPLFN3: 0 +] +IFN NLPTP, NTNLPL: 0 ;NUMBER OF TIMES NLPT LOST PIA +VARIABLES + + +TSTB: REPEAT CKNUM,CONC CK,\.RPCNT, +LTSTB==.-TSTB + +CKSUMS: BLOCK CKNUM +CKXORS: BLOCK 36. ;XOR OF ALL ADRS IN PURE AREAS IN SYS WITH CORRESP + ;BIT SET (RH) +TCKXOR: BLOCK 36. ;TEST XORS + +SSYSCL==SSYS +SYSCLB==SSYSCL_-10.+IFN 1777&SSYSCL,1 + +IFE KA10P,[ +AC1PTR: UUOACS ;-> WHERE AC BLOCK 1 IS CURRENTLY LOADED FROM +] ;IFE KA10P + +USRHI: 0 ;HIGHEST LOC USED FOR USER STORAGE + +SUBTTL LOCATIONS TO PATCH WHEN DEBUGGING + +SYSDBG: 0 ;0 NORMAL TIMESHARING + ;+ GIVE "ITS BEING DEBUGGED" MESSAGE + ;-N ALSO ALLOW ONLY CONSOLE #N AND T00 TO CTRL/Z. + ;-512.*N => ALLOW ONLY HOST N TO TELNET IN. + ;-512.*N+M => ALLOW HOST N AND TTY M. +DMLLDF: -1 ;-1 => START DAEMONS AUTOMATICALLY, 0 DON'T. +IFN DEMON,DMNFLG: 1 ;1 => START DM-STYLE DAEMONS, 0 DON'T. + +IFN NETP,NETUSW: 0 ;-1 => DON'T START UP A JOB IN ANSWER TO A CONNECT REQUEST + ;FROM A HOST OTHER THAN OURSELVES + +SYSCN: SYSCON ;NUMBER OF TTY TO RECEIVE SYSTEM CONSOLE OUTPUT. + ;-1 TO THROW IT AWAY. YOU CAN CHANGE THIS ANY TIME. + +SUPPLG: 0 ;-1 => SUPPRESS LOGIN/LOGOUT MESSAGES ON SYSTEM CONSOLE. + +IFE KS10P,[ ; KS has no lights. +MIPGDS: 0 ;-1 => DON'T LIGHT LIGHTS (KA HAS HARDWARE SWITCH, KL NEEDS + ; THIS) +] ;IFE KS10P + +IFN RH10P+RH11P,[ +USFHLT: 0 ;-1 => HALT ON DISK UNSAFES AND OTHER BAD ERRORS + ;0 => RETRY. NOTE SET POSITIVE FOR 1/2 SECOND AFTER + ; A RETRY TO AVOID LOOPING, DETECT SOLID ERRORS. +] ;RH10P+RH11P + +.SEE USEHM ;NONZERO => USE HIGH MOBY, ELSE ONLY 256K + +.SEE USEMDM ;NONZERO => USE MEDIUM MEMORY AS ADDITIONAL "LOW HALF" PAGES + +IFN N11TYS,[ +TT11P: 1 ;0 => PDP11-TTYS ARE NOT IN USE + ;1 => SYSTEM SHOULD INITIALIZE THEM + ;-1 => INITIALIZED AND IN USE + ;TO BRING THE TV'S DOWN, ZEROING TT11P ISN'T ENOUGH + ;EITHER DO WHAT TT11LS DOES, OR JUST SET SCR11D IN SUPCOR + ;(THE LATTER MAY NOT TAKE EFFECT INSTANTLY, HOWEVER) + ;TO BRING THE TV'S UP, JUST SET TT11P TO 1 AND WAIT 2 SECONDS +] + +.SEE IMPUP ;0 UP, -1 DOWN, 1 DOWN AND DON'T TRY TO BRING BACK UP + +.SEE TEN11F ;0 UP, -1 TOTALLY DOWN, 1 RESET PLEASE + +.SEE DL10F ;0 PDP11 DOWN, -1 UP + +.SEE PDP6UP ;0 PDP6 DOWN, -1 UP + +.SEE LASTGC ;NAME OF LAST DISK DIRECTORY GARBAGE COLLECTED + + +SUBTTL SWAPPING ALGORITHM CONTROL SWITCHES + +IFE SWPWSP,[ ;THESE AREN'T LOOKED AT IN SWPWSP SYSTEM +ENSWSC: SWBLK ;ENABLE CALLING OF SWSCD FROM 15 SEC CLOCK +ENUPC: 1-SWBLK ;ENABLE USER-PC PAGE OF RUNNING USER NOT BE SWAPPED OUT +ENPZRO: SWBLK ;ENABLE PAGE-ZERO OF RUNNING USER NOT BE SWAPPED OUT +ENSWBK: SWBLK ;ENABLE SWPNX1 TO SWAP BLOCK A USER +ENPVCL: 1-SWBLK ;ENABLE PRVCLK ROUTINE +ENPREE: 1-SWBLK ;ENABLE PREEMPTION ON PAGE SWAP IN (SEE QSWI1) +ENAGE: 1-SWBLK ;ENABLE AGE BITS TO ABORT SWAP OUT IF PAGE IS USED +];SWPWSP +AGERTE: 8 ;NUMBER OF PAGES TO AGE EACH 1/2 SECOND. + ;IN A 512K SYSTEM, LAP TIME IS ABOUT 200/AGERTE SECONDS. + +SUBTTL SYSTEM LOCKS + +CIRPSW: -1 ;CIRCULAR POINTER SWITCH + 0 + +MEMFRZ: -1 ;MEMORY FROZE + 0 + +CASW: -1 ;CORE ALLOCATE INTERLOCK SWITCH (REQUESTS TO CORE JOB) + 0 + +SHUTLK: -1 ;LOCK VAR FOR SHUTDN + 0 ;USED TO TELL WHO CAUSED SYS DOWN + +TREESW: -1 ;LOCK MANIPULATION OF JOB TREE STRUCTURE + 0 ;ATTACH, DETACH, DISOWN, REOWN ALL LOCK. + +CUSER: -1 ;CORE ALLOCATOR USER + 0 ;DUMMY CORE ALOC USE VAR + +ARDFSW: -1 ;LOCK VAR FOR .REDEF + 0 + +IFN 340P\E.SP,[ +DISUSR: -1 ;340 USER + 0 ;DUMMY 340 USE VAR +] + +IFN CODP,[ +CODUSR: -1 ;CODE SENDER +CODUSE: -1 +] + +IFN PLTP,[ +PLTUSR: -1 ;PLOTTER USER +PLTUSE: -1 +] + +IFN LPTP\TTLPTP,[ +LPTUSR: -1 ;LINE PRINTER USER +LPTUSE: -1 +] +IFG LPTP-1,[ +OLPUSR: -1 +OLPUSE: -1 +] +IFN LPTP,[ + IFE LPTP-1,[ + IFN NLPTP,[ + NLUSR==LPTUSR + NLUSE==LPTUSE + ] + IFN OLPTP,[ + OLUSR==LPTUSR + OLUSE==LPTUSE + ] + ] + IFG LPTP-1,[ + OLUSR==OLPUSR + OLUSE==OLPUSE + NLUSR==LPTUSR + NLUSE==LPTUSE + ] +] + +IFN PTRP,[ +PTPUSR: -1 +PTPUSE: -1 + +PTRUSR: -1 +PTRUSE: -1 +] + +IFN VIDP,[ +NVDUSR: -1 +NVDUSE: -1 +] + +IFN PDP6P,[ +PDPUSR: -1 ;PDP-6 USER +PDPUSE: -1 +PDPISR: -1 ;PDP6 AS INFERIOR (INTS ON IO CHANNEL) +PDPISE: -1 ;PDP6 USE VAR +] + +IFN TABP,[ +TABUSR: -1 ;TABLET USER +TABUSE: -1 +] + +IFN STKP,[ + STKUSR: -1 + STKUSE: -1 +] + +TIME: 0 ;TIME SINCE SYSTEM START IN 1/30'THS +SUSRS: 0 ;NUMBER USERS ON SYS +RVVTIM: 0 ;VALUE OF TIME WHEN SYSTEM WAS LAST REVIVED FROM A CRASH +USRRCE: BLOCK NCT+1 ;USER RESOURCE +1 FOR DISOWNED JOBS +SYSRCE: 0 ;SYS JOB RESOURCE +SLOADU: 0 ;100. * , IN FIXED POINT. +RNABLU: 0 ;RUNNABLE USERS +NPGWTU: 0 ;NUMBER OF JOBS CURRENTLY WAITING FOR A PAGE +LOUTIM: 0 ;TOTAL TIME USED BY LOGGED OUT USERS +UMASTER: -1 ;INDEX OF MASTER USER +SWRCE: BLOCK NCT+2 ;SWAP SCHED RESOURCE +SWIPRQ: 0 ;TOTAL # SWAP IN REQUESTS +SHUTDN: 0 ;"TIME" SYS WILL DIE, 0 IF NOT DYING, -1 IF DEAD +DEDTIM: 0 ;TIME TILL DEATH AFTER NEXT CLK QUEUE INT + ; < 0 => SYSTEM ACTUALLY DOWN (CHECKED BY ^Z, NUJBST, %OPLIV JOBS) +DTHTIM: 0 ;TIME SYSTEM DIED +DEDBLK: 0 + -1 + JRST DEATHZ + +ATRNJN: 0 ;JNAME OF LAST JOB TO DO A .TRANAD OR .TRANDL + ;(SO I CAN SEE IF THEY'RE USED AT ALL). + +IFN DZ11P,[ +DZXSPR: 0 ;Count of spurious DZ-11 transmitter interrupts. +DZRSPR: 0 ;Count of spurious DZ-11 receiver interrupts. +];DZ11P + +NCORRQ: 0 ;NUMBER CORE RQS HERE SO TRANSFERRED TO PEEK +NCBCOM: 0 ;NUMBER CORE BLOCKS COMMITTED TO CORGP + +NQDE: BLOCK NQS ;NUMBER OF 2314 DATA ERRORS +NQHE: BLOCK NQS ;NUMBER OF 2314 HARDWARE ERRORS + BLOCK 1 ;NQSE-1 COUNTS SPUR INTS WHILE NO XFER (QSDU -1) +NQSE: BLOCK NQS ;NUMBER OF SPURIOUS 2314 ERROR INTERRUPTS +NQCMPE: BLOCK NQS ;NUMBER OF 2314 READ/COMPARE ERRORS +NQWDE: BLOCK NQS ;# DATA ERRS ON WRITE +NQRDE: BLOCK NQS ;# DATA ERRS ON READS +NIRSWE: 0 ;# IRRCV ERRS ON SWAPPING XFERS +QIRRCV: 0 ;IRRECOVERABLE DISK ERRORS +QIRCBK: 0 ;BLOCK # W/ IRRCV ERROR +QIRUNT: 0 ;UNIT OF ABOVE +NQWRE: 0 ;# WRITE ERRS RCC OK +NQWIRE: 0 ;# WRITE ERRS RCC LOST +NWXFR: 0 ;NUMBER WRITE TRANSFERS (FILE, DIR, ETC.) +NRXFR: 0 ;NUMBER READ +NSWXFR: 0 ;NUMBER WRITE SWAPS +NSRXFR: 0 ;NUMBER READ SWAPS + +;DON'T CHANGE ORDER .SEE MEMTYP +PARERR: 0 ;COUNT OF CORE PARITY ERRORS +NXMERR: 0 ;COUNT OF NXMS +IFE KA10P, BPFERR: 0 ;COUNT OF BAD PAGE FAILS +PARPC: 0 ;PC ON CORE PARITY INTERRUPT +NXMPC: 0 ;PC ON NXM +IFE KA10P, BPFPC: 0 ;PC ON BAD PAGE FAIL +PARUSR: -1 ;USER ON PAR ERR +NXMUSR: -1 ;USER ON NXM +IFE KA10P, BPFUSR: -1 ;USER ON BAD PAGE FAIL +IFE KA10P, BPFPFW: 0 ;PFW ON BAD PAGE FAIL + +IFN KS10P,[ +ECCERR: 0 ;COUNT OF ECC CORRECTED ERRORS LOGGED +ECCERA: 0 ;MEMORY STATUS AND ADDRESS OF MOST RECENT +ECCAND: -1 ;AND OF ALL ERRORS +ECCIOR: 0 ;IOR OF ALL ERRORS +] ;IFN KS10P + +IFN DPKPP, NDPKPE: 0 ;# PARITY ERRS FROM DATAPOINT KLUDGE + +SNMPGS: 0 ;SYSTEM, NUMBER OF VIRTUAL USER PAGES +SNSWPG: 0 ;SYS, NUM OF SWAPPED OUT VIR. PGS + +USRTM1: 0 ;4USEC TICKS USED BY USERS SINCE LAST (1/2 SEC) UPDATE TO USRTIM +USRTIM: 0 ;TIME USED BY ALL USERS 1 SEC UNITS +NULTM1: 0 ;4USEC TICKS USED BY NULJOB SINCE LAST (1/2 SEC) UPDATE TO NULTM3 +NULTM3: 0 ;NUMBER OF SECONDS USED BY NULJOB +NULTIM: 0 ;TIME USED BY NULL JOB (60'THS) - OBSOLETE BUT STILL MAINTAINED +IFN KL10P,[ +NULEBC: 0 ? 0 ;EBOX COUNT WHEN NULL JOB ENTERED +NULMBC: 0 ? 0 ;MBOX COUNT WHEN NULL JOB ENTERED +NULPRF: 0 ? 0 ;PERF COUNT WHEN NULL JOB ENTERED +] ;KL10P +IFE KA10P,[ +PFAILF: 0 ; KL: -1 => ENTRY TO CLOCK LEVEL WAS VIA PFAIL + ; -2 => VIA INTPFL + ; KS: -1 => BOTH CASES +] ;IFE KA10P +LOSTM1: 0 ;4USEC TICKS LOST SINCE LAST (1/2 SEC) UPDATE TO LOSTIM +LOSTIM: 0 ;SECONDS OF LOST TIME (ALL OTHERWISE RUNNABLE JOBS WAITING FOR PAGES) +IDLTM1: 0 ;4 USEC TICKS IDLE SINCE LAST (1/2 SEC) UPDATE TO IDLTIM +IDLTIM: 0 ;SECONDS OF IDLE TIME (NO JOBS WANT TO RUN) +LOSRCE: 0 ;USRRCE WORD FOR LOST TIME +IDLRCE: 0 ;USRRCE WORD FOR IDLE TIME + +UREALT: -1 ;RH=INDEX OF THE REAL TIME USER + ;LH=0=> THIS USER HAS HIGHEST PRIORITY + ;LH>0=> USER NOT IN HIGH PRIORITY PHASE + ;LH<0=> FACILITY IDLE +INFORM [HIGHEST USED]\<.-1> + SUBTTL USER VARIABLES + +;ONE COPY FOR EACH PROCEDURE +;FOR KL AND KS, THIS IS THE UPT + +IFN KL10P,[ +DEFINE KLUPT N,NAME/ ;CHECKS "HARD-WIRED" UPT LOCATIONS +IFN .-USRSTG-,[ +.ERR "NAME" LOST IN UPT +LOC USRSTG+ +] +TERMIN +] ;KL10P + +IFE KL10P,[ +DEFINE KLUPT N,NAME/ +TERMIN +] ;IFE KL10P + +IFN KL10P, LOC <.+777>&-1000 ;KL UPT MUST START AT HARDWARE PAGE BOUNDARY + +IFN KS10P, LOC <.+7>&-10 ; KS UPT must be 0 mod 8 (see UUOPCW) + +USRSTG:: KLUPT 0,;USER PAGE MAP + +UPGMP: BLOCK NUVPG/2 ;PAGE MAP STORAGE (PROGRAMS UP TO NUVPG LONG) +; 2.9-2.8 ACCESS RIGHTS +; 00 NO ACCESS (BY SOFTWARE CONVENTION, 1.2-1.1 +; HAVE THE "REAL" ACCESS BITS, WHICH MAY BE 00, +; BUT MAY NOT, E.G. FOR A SWAPPED OUT PAGE). +; 01 READ ONLY +; 10 READ/WRITE/FIRST +; 11 READ/WRITE +.SEE PMCSHM ;CACHE BIT +.SEE PMAGEM ;AGE BITS +.SEE PMRCM ;LOW N BITS ARE PHYSICAL CORE PAGE NUMBER (IN 1K PAGES) +UPGCP: BLOCK NUVPG/2 ;CIRCULAR POINTERS (CORRESPONDS 1-1 WITH UPGMP) +; IF -1, ABSOLUTE PAGE, NOT LINKED. OTHERWISE: +; 2.9 IF 0: +; 2.8-1.9 USER INDEX +; 1.8-1.1 PAGE NUMBER IN THAT USER'S UPGCP +; IF 1: +; 2.8 IF 0: +; 2.7-1.1 LINK TO MMP TABLE +; IF 1: +; 2.7-1.1 LINK TO MEM PNT TABLE +UMAPS: 0 ;USER MAP STATUS + .SEE %UM +UDBR1A==UPGMP ;ADDRESS TO PUT IN DBR1 +UDBR2A==UPGMP+ ;ADDR FOR DBR2 +UPGCPH==UPGCP+ ;ADDR OF HIGH HALF OF CIRC PNTRS + +TTYTBL: 0 ;TTY ASSIGNED THIS USER OR INDICATION THAT THERE IS NONE +%TBNOT==400000 ;4.9 DOES NOT HAVE TTY NOW +%TBNVR==200000 ;4.8 IF JOB DOESN'T HAVE TTY, OPENS SHOULD FAIL. +%TBINT==100000 ;4.7 IF JOB DOESN'T HAVE TTY, ATTEMPT TO USE TTY SHOULD INTERRUPT. + ;JOB CAN SET BITS 4.8 AND 4.7. +%TBWAT==40000 ;4.6 IF 1, %TBINT AND %TBNVR ARE OVERRIDDEN AND TTY USE ATTEMPTS + ; ALWAYS HANG. SET BY DDT FOR $P, CLEARED BY ^P. ONLY SUPERIOR CAN SET. +%TBDTY==010000 ;4.4 TTY TAKEN FROM --ME--. WHEN GIVEN BACK, + ;DON'T PASS IT ON TO MY INFERIOR. +%TBOUT==004000 ;4.3 ALLOW THIS JOB TO OUTPUT WHETHER OWNS TTY OR NOT +%TBINF==002000 ;4.2 ALLOW MY INFERIORS TO OUTPUT IF THEY HAVE %TBOUT. +%TBOIG==001000 ;4.1 IGNORE MY OUTPUT +%TBIIN==000400 ;3.9 INTERRUPT IF I TRY TO DO INPUT +$TBECL==220600 ;3-6-3.1 # ECHO LINES IF I DONT HAVE DISPLAY + ;RH USER NUM GAVE TTY AWAY TO OR TTY NUM IF HAS IT +%TBCLR==410077 ;CLEAR THESE BITS IN TTYTBL OF A JOB RECEIVING THE TTY + +TTSTSV: BLOCK 3 ;JOB'S SAVED TTYST1,TTYST2,TTYSTS, WHEN JOB DOESN'T HAVE THE TTY. + +NMPGS: 0 ;NUMBER OF NON-ABSOLUTE PAGES (INCLUDES PURE) +NSWPGS: 0 ;NUMBER SWAPPED OUT PAGES (AOSED FOR EACH USER OF SHARED PAGE SWAPPED OUT) +HUSRAD: 0 ;MEM ADR OF PAGE ABOVE HIGHEST THAT EXISTS (MAX 1,,0) +UPC: 0 ;USER PC STORAGE +LUBTM: 0 ;TIME LAST UNBLOCKED (FOR IDENTIFYING INACTIVE JOBS) +JBI: -1 ;JOB DEVICE INDEX. IF NOT -1, THIS JOB IS A JOB-DEVICE, + ;AND JBI HAS INDEX INTO JOB DEVICE TABLES. + +UPGML: ;USER PAGE MAP LOAD (EIGHT WORDS FOR LPM AND SPM INSTRUCTIONS) +IFE KS10P,[ ; KS10 version given below. + UPJPC: 0 ;JPC. KA HAS FAULT ADDRESS IN LH. +IFE KL10P, UPOPC: 0 ;OLD PC FLAGS,,OPC (UNUSED ON KL-10) + UPMAR: 0,,0 ;MAR ADDRESS AND CONDITION + ;FOR KA-10: + ; 3.3 0=EXEC, 1=USER + ; 3.2-3.1 MAR CONDITION: + ; 0 NEVER + ; 1 INSTR FETCH + ; 2 WRITE + ; 3 ALWAYS + ; 2.9-1.1 VIRTUAL ADDRESS + ;FOR KL-10: + ; 3.9-3.7 ADDRESS BREAK CONDITIONS: + ; 3.9 FETCH + ; 3.8 READ + ; 3.7 WRITE + ; 3.6 0=EXEC, 1=USER + ; 3.5-1.1 VIRTUAL ADDRESS +IFE KL10P, UPQUAN: EXPGNG+1,,0 ;F.S. QUAN AND FAULT BITS +IFN KL10P, UPFW: 0 ;PAGE FAIL WORD +IFE KL10P,DBL==100_1 +IFN KL10P,DBL==0 + UPDBR1: DBL,,UPGMP ;DBR1 + UPDBR2: DBL,,UPGMP+100 ;DBR2 +IFE KL10P, UPDBR3: DBL,,EXEUMP ;DBR3 +IFE KL10P, UPACP: 1040,,UUOACS ;B KEY,C KEY,,AC POINTER +] ;IFE KS10P + +IFN KS10P,[ +UPDBR1: UPGMP ; DBR1 +UPDBR2: UPGMP+100 ; DBR2 +UPQUAN: 0 ; Runtime counter +UPJPC: 0 ; User mode JPC if microcode supports +UPEJPC: 0 ; Exec mode JPC if microcode supports +] ;KS10P + +UPGMLE:: ;END OF PAGE MAP (+1) + +IFN KL10P,[ + KLUPT 420, ;RESERVED UPT 420 +UPT420: 0 + KLUPT 421, ;TRAP 1 INSN ;ARITHMETIC OVERFLOW +TR1INS: JSR ILLTRP ;FOR ITS-STYLE INTERRUPT, CONTAINS 0,,%PIARO + KLUPT 422, ;TRAP 2 INSN ;PDL OVERFLOW +TR2INS: JSR ILLTRP ;SYS JOB SHOULDN'T OVERFLOW ;FOR ITS-STYLE, 0,,%PIPDL + KLUPT 423, ;TRAP 3 INSN ;USED FOR ONE-PROCEED +TR3INS: JSR ILLTRP ;SYS JOB SHOULDN'T ONE-PROCEED ;FOR ITS-STYLE, 0,,%PI1PR + KLUPT 424, ;MUUO DEPOSIT LOCATION +SV40:: +MUUODP: 0 .SEE FORTY + KLUPT 425, ;MUUO OLD PC STORAGE +SUUOH:: +XUUOH: 0 + KLUPT 426, ;MUUO PAGING AND CONTEXT WORD +MUUOCX: 0 + KLUPT 427, ;RESERVED UPT 427 +UPT427: 0 + KLUPT 430, ;MUUO NEW PC WORDS +MUUOKN: %PSPCU,,UUOH0 ;FOR OTHER JOBS, MUUOEX (A JRST 4,). +MUUOKT: %PSPCU,,MUUOEX ;NO JOB SHOULD EVER TRAP IN EXEC MODE. +MUUOSN: %PSPCU,,MUUOEX ;NO JOB SHOULD EVER RUN IN SUPERV. STATE. +MUUOST: %PSPCU,,MUUOEX ;.. +MUUOCN: %PSPCU,,UUOH0 ;NORMAL UUOS +MUUOCT: %PSPCU,,MUUOTR ;UUOS AS TRAP INSN +MUUOPN: %PSPCU,,UUOH0 ;PUBLIC MODE IDENTICAL TO CONCEALED MODE, +MUUOPT: %PSPCU,,MUUOTR ; ALTHOUGH IT'S A SCREW FOR A LOSER TO BECOME PUBLIC +] ;END OF IFN KL10P + +IFN KS10P,[ +DEFINE KSUPT UPTNAM +IFN .-USRSTG-,[ +.ERR UPTNAM lost in UPT +LOC USRSTG+ +] +TERMIN + +UPFW: 0 ; Saved page fail word from last fault. Copied from EPTPFW + ; at time of fault usually. + +KSUPT UPTTR1 +TR1INS: JSR ILLTRP + +KSUPT UPTTR2 +TR2INS: JSR ILLTRP + +KSUPT UPTTR3 +TR3INS: JSR ILLTRP + +KSUPT UPTUUO +SV40:: +MUUODP: 0 + +KSUPT UPTUPC +SUUOH:: +XUUOH: 0 + +KSUPT UPTUCX +MUUOCX: 0 + +KSUPT 427 +UPT427: 0 + +KSUPT UPTUEN +MUUOKN: %PSPCU,,UUOH0 ;UUO in Exec mode new PC + ;For other jobs: %PSPCU,,MUUOEX +KSUPT UPTUET +MUUOKT: %PSPCU,,MUUOEX ;UUO as trap instruction in Exec mode new PC + +KSUPT UPT1PO ;PC saved here after one-proceed +1PROPC: 0 + +KSUPT UPT1PN ;One-proceed sets PC to this +1PRNPC: %PSPCU,,ONEPRO + +KSUPT UPTUUN +MUUOCN: %PSPCU,,UUOH0 ;Normal UUO new PC + +KSUPT UPTUUT +MUUOCT: %PSPCU,,MUUOTR ;UUO as trap instruction new PC + +EXPUNGE KSUPT + +] ;KS10P + +UUOACS: BLOCK 20 +AC0S: BLOCK 15 ;SWAP OUT AC S +AC15S: 0 +AC16S: 0 +AC17S: 0 + +IFN KL10P,[ +;KLUPT 500, ;PAGE FAIL WORD STORAGE ;MICROCODE MOD PUTS +;KLUPT 501, ;PAGE FAIL OLD PC STORAGE ; THESE LOCATIONS IN +;KLUPT 502, ;PAGE FAIL NEW PC ; THE EPT FOR ITS +] ;END OF IFN KL10P + +UUO:: ;THE FOLLOWING LOCATIONS (UP TO SUEXND) ARE SWAPPED IN & OUT OF + ;UEXIT ETC. WITH THE USER +SUEXIT: JRST 2,@XUUOH ;USER UUO EXIT INS +SCLUSV: MOVEM U,AC17S ;CLOCK U SAVE + +IFN KA10P,[ +SUUOH: 0 ;C(@41) (ABSOLUTE) +SUEXND:: + +SV40: 0 ;C(40) WHEN USER OUT (SEE SWITCH) +] ;KA10P + +IFE KA10P,[ +SCLCXS: DATAI PAG,CLCX ;CLOCK SAVE OF CONTEXT +SUEXND:: +] ;IFE KA10P + +IFN -, .ERR SUEXIT BLOCK LOST + +IFE KA10P,[ +CLCX: 0 ;SAVED CONTEXT (DATAI PAG,) AT CLKBRK AND PFAIL +] ;IFE KA10P + +IFN KL10P,[ +KLUPT 504, ;EBOX COUNT +EBOXCT: 0 ? 0 ;NUMBER OF EBOX TICKS (25 MHZ) OVER 2 LEFT 12. THAT EBOX + ;RAN FOR THIS USER +KLUPT 506, ;CACHE COUNT +MBOXCT: 0 ? 0 ;NUMBER OF MBOX CYCLES REQUESTED BY EBOX FOR THIS USER LEFT 12. + +EXPUNGE KLUPT +] ;KL10P + +UTIME: 0 ;RH=CLOCK INTERVAL IN 60'THS, LH=COUNT OF TICKS SINCE READ +UTRNTM: 0 ;TOTAL RUN TIME IN 4 MICROSEC UNITS +USIPRQ: 0 ;# SWAPIN REQUESTS + +USWST: 0 ;SWAPPING STATUS BITS. +%SW==525252(1) ;IN THE LEFT HALF +%SWDSO==400000 ;4.9 => DESIRED TO BE SWAPPED OUT (MUST BE SIGN BIT). +%SWPGW==200000 ;4.8 => FLSINS IS WAITING FOR A PAGE +%SWBEM==100000 ;4.7 => BEST EFFORT MADE TO SWAP OUT, DON'T LOOK AT JOB AGAIN +%SWRUN==040000 ;4.6 => SWAPPED OUT WHILE RUNNABLE, SO CONSIDER MEM STATUS BEFORE REACTIVATION + ; THIS BIT IS NEVER LOOKED AT. +%SWPCL==020000 ;4.5 => PAGE SWAPPED OUT WHILE BLOCKED IN EXEC MODE + ; SO WHEN FLSINS SKIPS DON'T CLEAR IT BUT PCLSR INSTEAD. +%SWINT==010000 ;4.4 => IF WAITING FOR PAGE, NEED IT TO INTERRUPT +%SWPRV==004000 ;4.3 => "PRIVELEGED USER" +IFN SWPWSP,[ +EXPUNGE %SWPRV +%SWOUT==000400 ;3.9 => JOB IS SWAPPED OUT OR SWAP BLOCKED +%SWSB== 000200 ;3.8 => JOB IS SWAP BLOCKED +%SWLOD==000100 ;3.7 => JOB IS LOADING + ;VALID STATES OF ABOVE 3 BITS: 0=SWAPPED IN, 1=LOADING, 4=SWAPPED OUT, 6=SWAP BLOCKED + +UWRKST: 0 ;WORKING SET. 2**18 TIMES SUM(ALL THIS JOB'S PAGES) 1 OVER # SHARERS + ;INCREMENTALLY MAINTAINED WHILE JOB IS LOADING OR SWAPPED IN. + ;NOTE # SHARERS IS IN RH(MMSWP) +USVWRK: 0 ;SAVES UWRKST AS OF LAST TIME SWAPPED IN +USWTIM: 0 ;TIME ENTERED LOADING, SWAPPED OUT, OR SWAP BLOCKED STATE. + ;WHILE SWAPPED IN, HAS THE TIME AT WHICH IT CEASES TO BE PROTECTED + ;AGAINST MEMORY PREEMPTION. +];SWPWSP +USWPRI: 0 ;JOB SWAP PRIORITY. LOWER NUMBER MEANS MORE LIKELY TO STAY IN + ; AND MORE LIKELY TO COME IN. SEE ALSO SWRCE, WHICH IS SIMILAR. +IFE SWPWSP, ;THIS IS THE AVERAGE (DECAYS BY 1/2 IN 30 SECONDS) OF THE PRODUCT + ;OF THE WORKING SET TIMES THE FRACTION OF CPU USED + ;WHICH IS A MEASURE OF MEMORY USE WITH INTERACTIVE JOBS GIVEN AN ADVANTAGE. +IFN SWPWSP, ;THIS IS THE AVERAGE (DECAYS BY 1/2 IN 30 SECONDS) OF THE "ADJUSTED + ;MEMORY USAGE", WHICH IS THE (LOGARITHM OF THE WORKING SET SIZE) + ;MULTIPLIED BY THE SUM OF CPU TIME AND I/O WAIT TIME. ALSO, WHEN + ;A DISOWNED JOB IS SWAPPED OUT, USWPRI IS MULTIPLIED BY 4 TO PREVENT + ;IT FROM COMING BACK IN FOR A WHILE UNLESS THERE IS REALLY NO + ;COMPETITION FOR MEMORY. ALSO, WHEN A SWAPPED-OUT JOB WAKES UP FROM + ;AN I/O WAIT, USWPRI IS DIVIDED BY 2 TO GIVE INTERACTIVE JOBS AN + ;ADVANTAGE. THE SWPWSP SYSTEM DOES NOT CURRENTLY LOOK AT SWRCE. +IFE SWPWSP,[ +USWSCD: 0 ;SWAP SCHEDULING WORD 4.9=1 SWAPIN INHIBITED THIS JOB (SWAP BLOCKED) +LTRNTM: 0 ;SAVED RUN TIME FOR PRIV USR +LSIPRQ: 0 ;SAVED SWAP IN REQ FOR PRIV USER +UPGSEC: 0 ;NUMBER OF PAGE FAULTS PER RUN TIME SECONDS +LPRVTM: 0 ;LAST TIME PRIV USER +];SWPWSP +PAGRAN: 0 ;.PAGRANGE. 1ST PG #,,LAST PG # INCLUSIVE RANGE OF PAGES TO BE PAGED AHEAD. +PAGAHD: 0 ;.PAGAHEAD. 0, OR PAGE-AHEAD-DISTANCE,,PAGE-BEHIND-DISTANCE + +TRUNTM: 0 ;IF NOT TOP LEVEL, MINUS RUNTIME (4.069 US) ALREADY SENT TO SUPERIOR + ;IF TOP LEVEL, RUNTIME USED BY SUBTREE MINUS TIME SENT TO DEMON ALREADY +TSIPRQ: 0 ;DITTO FOR SWAPIN REQUESTS +UTMPTR: SYSRCE ;POINTER TO RESOURCE WORD FOR THIS LOSER (JTMU FOR TREE) +JTMU: 0 ;REDUCED BY 1/16 EVERY 1/2 SEC + ;INCREMENTED BY TIME RUN IN 4 USEC + ;MAX EQV VAL 1000000/8-1/16X=0 + ;EQV VAL=2X10^6 + ;AMONG JOBS WITH EQUAL RESOURSE + ;LOWEST JTMU HAS HIGHEST PRIORITY + +IOCHNM: REPEAT NIOCHN,0 ;IO CHANNEL ASSIGNMENT + ;RH INDEX INTO IOTTB AND CLSTB + ;LH DEV CHNL AND/OR OTHER +SIOCHN: BLOCK LUIOP ;MUST FOLLOW IOCHNM + ;I/O CHANNEL PDL +SIOCP: SIOCHN-1 ;POINTER INTO I/O CHANNEL PDL +IOCHST: BLOCK NIOCHN ;I/O CHANNEL STATUS FOR CH'S AT IOCHNM + ;3.1-4.9 IO STATUS + ;1.1-2.9 .ACCESS POINTER + +CORRQ: -1 ;RQ TO CORE JOB + ;4.9=1=>NO REQUEST + ;4.8=0 OLD TYPE RQ,1.1-1.9 # BLKS,3.1-3.8=USR NUMBER RQ'ED FOR + ;4.8=1 NEW TYPE + ;4.3 ADD FRESH BLOCK (IGNORE 4.2,4.1) + ;4.1=1=> ADDING ABSOLUTE BLOCK + ;3.9=1=>REQUEST WRITE ABILITY + ;2.9=1 INSERT, =0 DELETE ONLY IGNORE 4.1-4.3 + ;2.1-2.8 VIRTUAL PAGE AFFECTED + ;1.1-1.9 USER RQ IS FOR + +APRC: APRCHN ;R.H. CONO TO APR WHEN USER STARTS (HAS AR OV ENABLE, ETC.) + ;4.9=1=> PROCEDURE IS IN A DISOWNED TREE +BUMRTL==100000 ;4.7 => GUN TREE IF HASN'T RUN FOR AN HOUR + ;(MEANINGFUL ONLY IN TOP LEVEL JOB). + ;CLEARED BY REOWNING OR ATTACHING. +BUSRCR==40000 ;4.6 CORE RQ PENDING ON THIS JOB +BULGO==20000 .SEE SYSGUN ;USER IS DISABLED, WAITING TO BE FLUSHED BY SYS JOB. +BCHPTR==330400,,APRC(U) ;4.1-4.4 LAST CH ON WHICH AN ERR OCCURED (SEE ERR DEV) +BULGOS==400 ;AN ATTEMPT IS BEING MADE TO DELETE OR LOG OUT THIS JOB + ;SO NO-ONE ELSE SHOULD START TO. THIS BIT ALSO LOCKS OUT + ;MOST WAYS OF HACKING THE JOB (INCL. THOSE THAT SET DIELOK). + ;3.1-3.5 MUST BE ZERO + +DIELOK: 0 ;NUMBER OF JOBS LOOKING AT OR HACKING THIS JOB. + ;BEFORE KILLING A JOB, WAIT FOR ITS DIELOK TO BECOME 0. + +USTP: 0 ;0 RUNNABLE, (IS SET NON ZERO FOR IDLE SETS OF VARS TO SPEED SEARCH) +%UST==1,,537777 +%USTCM==400000 ;CORE BEING SHUFFLED (SHOULD ACTUALLY BE OBSOLETE). +%USTCJ==200000 ;CORE BEING GIVEN BY CORE JOB. +%USTSP==100000 ;STOPPED BY SUPERIOR +%USTCG==40000 ;STOPPED BY SUPERIOR TO GIVE IT CORE (CORBLK, OR .USET OF .MEMT). + +BCSTOP==400000 ;BIT IN USTP FOR CORE MOVAGE +BUCSTP==200000 ;CORE STOPPING LOSER TO GIVE MORE CORE RQSTED BY ANOTHER LOSER +BUSRC==100000 ;USER CONTROL BIT, SET & CLEARED BY SUPERIOR PROCEDURE +BSSTP==40000 ;SET BY SUPERIOR WHEN HACKING MEM BOUND AT URMEMT OR UMEMEX +;1.1-2.9 ;USED BY UBO AND FRIENDS INHIBITS RELOCATION BY CORE ALLOCATOR + ;MUST BE MODIFIED WITH CLKOFF MUST NOT BE SET IF CSTOP IS SET + ;IS A COUNTER OF TRANSIENT REASONS FOR PROCEDURE BEING STOPPED + +PIRQC: 0 ;INT REQ AWAITING SERVICE (SOFTWARE INTS EFFECTED BY SEARCH) +MSKST: 0 ;INT MASK REGISTER FOR BITS IN PIRQC +IFPIR: 0 ;SECOND WORD OF INTERRUPT REQUESTS + ;3.8-3.1 INF PROC INT + ;2.7-1.1 IO CHANNEL INT + ;1.1= CHANNEL 0 +MSKST2: 0 ;INT MASK FOR IFPIR +IDF1: 0 ;DEFER BITS FOR 1ST WD INTERRUPTS. +IDF2: 0 ;FOR 2ND WORD INTERRUPTS. + ;IF AN INTERRUPT IS DEFERRED, IT IS TREATED AS + ;IF THE JOB'S PICLR VAR HELD 0. +PICLR: 0 ;INT IN PROGRESS FLAG, -1=>ENABLED, 0=>IN PROGRESS + +SUPPRO: 0 ;-1 => TOP LEVEL PROCEDURE + ;OTHERWISE: INT BIT,,PNTR TO SUPERIOR PROCEDURE + +FLSINS: 0 ;USER BLOCKING INSTRUCTION; STATE: + ; 0 => RUNABLE (UNLESS USTP .NE. 0) + ; OTHERWISE HUNG, IF NO SKIP SAFE TO RESTART AT UUO (UNLESS UFINAL .NE. 0) +RPCL: 0 ;0,,N RPCLSR'ING N + ;-1,,N BEING RPCLSR'ED BY N + +UNAME: 0 ;USER NAME + ;THIS WORD FOR EACH PROCEDURE IS COPIED FROM THE UNAME OF THE PROCEDURE + ;THAT CREATES IT (SEE USR DEV). FOR AN INITIAL TOP LEVEL PROCEDURE IT + ;IS INITIALLY -1 BUT IS MODIFIED BY ALOGIN. IT IS THE SAME FOR ALL + ;PROCEDURES IN A TREE. +JNAME: 0 ;JOB NAME + ;EACH LOGGED IN PROCEDURE HAS A UNIQUE UNAME, JNAME PAIR. THE JNAME + ;OF AN INITIAL TOP LEVEL JOB IS "HACTRN". FOR OTHER JOBS IT IS THE SECOND + ;FILE NAME SPECIFIED IN THE .OPEN ON THE USR DEVICE THAT CREATES THEM. +USYSNM: 0 ;USER SYSTEM NAME + ;THIS VARIABLE IS INITIALLY SET TO THE SAME VALUE AS UNAME FOR + ;A PROCEDURE. IT CAN BE READ OR WRITTEN BY THE PROCEDURE (ASUSET) + ;OR BY ITS SUPERIOR (AUSET). ITS ONLY USE IS AS THE DEFAULT THIRD FILE NAME ON + ;USER SHARED DEVICES (2311'S (SEE QSKO), AND CORE + ;LINK (SEE CLOO)). +USYSN1: 0 ;3RD NAME FOR QSKO, CLOO (AFTER DEFAULTING AND TRANSLATION) +HSNAME: 0 ;HOME SNAME + +IOTLSR: 0 ;4.9 IOT USER MOD (=1 ENABLES USER TO DO DIRECT I/O + ; INSTRUCTIONS) + ;RH VIRTUAL PAGE # OF LAST MPV, WIRO OR NXI (SHIFTED TO + ; ADDRESS SIZE) +UMARPC: 0 ;PC AT MAR INTERRUPT +LSWPR: 0 ;LOCKED SWITCH POINTER +UCLBLK: 0 ;CLOCK QUEUE BLOCK + -1 + JRST UREALB +URTIME: 0 ;LH=0=>LOW PRIORITY PHASE 1=> LOW PRIORITY WITH BLOCKING + ;LH=-1=>HIGH PRIORITY PHASE 2=> HIGH PRIORITY WITH BLOCKING + ;RH=LENGTH OF HIGH PRIOITY IN 60'THS +RTIMER: -1 ;POSITIVE => MICROSEC RUNTIME TILL RUNTIME INT + +LSPCL: 0 ;UPC AT LAST PCLSR,,DIFFERENT UPC AT PREVIOUS PCLSR +LEXFDR: 0 ;DEBUGGING INFO FOR PAGE FAULTS WHICH SIGNAL AN INTERRUPT + ; TO THE LOSER + ;LH FAULT BITS OF LAST SUCH FAULT + ;RH PC OF LAST SUCH FAULT THAT WAS FROM EXEC MODE (WENT TO + ; IOADCR) + ;PAGE FAULTS WHICH JUST SWAP IN A PAGE DON'T SET THIS. +LSUUO: 0 ;LAST SYS UUO (FOR DEBUGGING PURPOSE) +LSCALL: 0 ;SIXBIT NAME OF LAST .CALL 0, (FOR PEEK) +CTLBTS: 0 ;CTL BITS TO .CALL 0, XORED TOGETHER IN HERE (RIGHT HALF) +SYSCVL: 0 ;CONTROLS OUTPUT ARGS FROM SYSTEM .CALL + %SCV==1,,525252 + %SCVOT==400000 ;4.9 CALL HAS OUTPUT ARGS FLAG (TO SAVE TIME) + %SCVER==200000 ;4.8 CALL HAS ERROR CODE ARG FLAG + ;3.6-4.7 UNUSED 3.1-3.5 MUST BE ZERO + ;1.1-2.9 ADDRESS OF ERROR CODE ARG +IOTBTS: 0 ;DEVICE-INDEPENDENT IOT CONTROL BITS GO HERE, IN IOT AND SIOT +USTYN: 0 ;TTY NO OF THE STY WHICH THIS JOB KNOWS AS "STY:" (WITHOUT + ; NUMBER). +UUAC: 0 ;AC FLD OF LAST UUO OR DESIRED CHANNEL IN CASE OF NOPEN ETC + ;SELECTS CHNL FOR ALL IOTS, OPENS ETC + ;LH -1 IF STORED BY CHNDCD, ELSE ZERO (SEE WHO LINE ROUTINES) +TRMNAM: 0 ;TERMINAL IDENTIFICATION +TRNLST: 0 ;TRANSL LIST FOR THIS JOB. -1 => NIL, OR IDX INTO TRAN!X +TRNLS1: 0 ;TRANSL LIST FOR THIS JOB & INFERS. +UTRAPM:: ;SIGN BIT OF OPTIONS IS UUO-TRAP-TO-SUPERIOR MODE +OPTION: 0 ;OPTIONS WORD, SETTABLE BY USER + ;EACH BIT CONTROLS SOME SYSTEM ACTION FOR THIS JOB + .SEE %OP +XUNAME: 0 ;"WHO I REALLY AM" AS OPPOSED TO "WHO I AM LOGGED IN AS" +XJNAME: 0 ;JOB NAME USER SPEC'ED AS OPPOSED TO UNIQUIZED VERSION + +40ADDR: 20,,40 ;RH=ADDRESS OF USER'S 6-WORD BLOCK FOR UUO'S, INTS, SWITCHES, LOCKING. + ;LH=ADDRESS OF USER'S 20-WORD BLOCK FOR SUPERIOR'S USE. 0=20. +IFN N11TYS,[ +TVCREG: -1 ;TV CONSOLE REG FOR THIS USER OF -1 NONE +TVVBN: -1 ;-1 OR CONSOLE REG FOR RUN BLINKING +NVDBA: 0 ;# VIDEO BUFFERS ASSIGNED (WITH NVDBA SYSTEM CALL). +];N11TYS +UWHO1: 0 ;WHOLINE FLAGS +UWHO2: 0 ;TWO HALFWORDS, PRINTING CONTROLLED BY UWHO1 4.9-3.3 +UWHO3: 0 ;TWO MORE HALF WORDS, CONTROLLED BY UWHO1 3.2-1.5 +IFN KL10P,[ +ULSPBR: 0 ;STBR,,GCSTBR FOR SPECIAL LISP INSTRUCTIONS +] +SERVER: -1 ;User index of server job who is allowed write access to + ; this job to implement some oddball protocol. -1 if none. +;INSERT NEW USER VARIABLES HERE^ + +USRPDL: -LUPDL,,UPDL-1 ;USER PDL +UPDL: BLOCK LUPDL-1 +EPDL2: 0 ;SAVES C(T) FOR FLSINS +QLD: 0 ;LINK DEPTH +VALUE:: ;PROCEDURE "VALUE" RETURN +SRN3: 0 ;SAVED N3, N4 FOR RENAMES AT AOPEN ALSO USER INDEX AT NLOAD + ;SRN3, SRN4 USED BY CORBLK .CALL +.SEE IODCS2 ;SRN3 contains saved user mode PC for unlocking own locks. +.SEE ALOGO4 ;NO CLOSE ROUTINE MAY USE SRN4 OR SRN5 +SRN4: 0 ;ALSO DEVICE CHNL IOCHNM POINTER AT NLOAD +SRN5: 0 ;SAVED N5 FOR LINK ALSO VIRTUAL PAGE NUMBER AT NLOAD +EPDL3: 0 ;USED BY 2311 ROUTINES (QFNG) ALSO QSMDN ADDR AT NLOAD ALSO BY TYOW2 +.SEE ALOGO4 ;NO CLOSE ROUTINE MAY USE EPDL + ;FOR BP-STYLE RENAME, RENMWO AND MLINK, + ;HOLDS BP (OR BP BLK PTR) TO NAMES TO RENAME OR LINK TO. +EPDL: 0 ;USED BY 2311 ROUTINES. + ;FOR SOPEN AND BP-STYLE RENAME, DELETE, HOLDS BP OR BP BLOCK PTR. +EPDLT1: 0 ;FN1 BEFORE LAST TRANSLATION, USED BY NLOAD +EPDLT2: 0 ;FN2 " " " , USED BY NLOAD +EPDLT3: 0 ;SYS NAME " " " +EPDLT4: 0 ;LEFT ADJ DEVICE NAME " " " + +STTYOP: 0 ;IN THE TOP OF A DETACHED TREE, THIS CONTAINS THE SAVED USER TTY + ; OPTIONS. 2.9=1 IF IT IS VALID, 2.7-2.8 ARE QUERY AND REFUSE MODE, + ; THE REST ARE TTYOPT BITS. + +IFN 0,[ ;FAKE OUT @ +LSWB0: +] +REPEAT NULBLK,[ +CONC LSWB,\.RPCNT,: BLOCK 2 +] ;SWITCH BLOCK FORMAT + ;WD1 ASSOCIATED ADDRESS OR QUANTITY + ;3.6-3.1 USER NUMBER OF SWITCH HOLDER + ;2.9-1.1 PNTR TO NEXT SWITCH ON LIST OR 0 IF NONE + ;FOR REMAINDER OF FORMAT SEE LSWDIS + +IFN KL10P,[ +IFGE USRSTG+1000-., INFORM SPACE LEFT IN UPT,\1000-<.-USRSTG> +IFL USRSTG+1000-., .ERR USER VARS TOO BIG FOR UPT! +.ELSE LOC USRSTG+1000 +] ;IFN KL10P + +IFN KS10P, LOC <.+7>&-10 ; KS UPT must be 0 mod 8 (see UUOPCW) + +LUBLK==.-USRSTG +L==LUBLK +INFORM [STORAGE PER LOSER]\LUBLK + BLOCK LUBLK ;USER VARIABLES FOR CORE JOB +SYSB==<1777+.>_-10. +MXC==SYSUSB-SYSB ;AVAIL BLOCKS AFTER SYS+DDT + + SUBTTL TSS INITIALIZATION +;NEXT LINE COMMENTED OUT BECAUSE IT CAUSES MORE TROUBLE THAN IT SAVES +;.HKALL==1 ;(THE FOLLOWING CODE IS WIPED OUT AT ICLR) +EXEUMP=UPGMP+100 ;EXEC UPPER MAP LIVES IN SYSTEM JOB'S PAGE TABLE + ;SYMBOL IS DEFINED HERE SINCE UPGMP WAS JUST DEFINED 6 PGS AGO + +BEG: SKIPN SALV ;SEE IF LOSER FORGOT TO LOAD SALV WHEN BUILDING SYSTEM, + ;OR SALV MEM IS NXM. EVIL! EVIL! + BUG AWFUL,[HEY! WHERE'S THE SALVAGER?] + JSR SALV+1 ;CALL NO-QUESTIONS-ASKED SALVAGER +GO: JFCL 17,.+1 + JRST .+1 + JFCL 1,[JRST 4,.] ;SYSTEM WONT RUN ON 6 +IFN KL10P,[ + CONSO PAG,600000 + SWPIA ;IF CACHE OFF, FLUSH CRUFT THAT MAY BE IN IT + CONSZ PAG,600000 + SWPUA ;IF CACHE ON, UPDATE CORE SO DDT IS GOOD + CONSZ 200000 + JRST .-1 + SPCCTX 0,1,USRSTG,DISABLE ;SET UP UPT ADDR, BUT NO ACCTING TILL + MOVEI T,0 ;MORE INIT IS DONE. + XCTR XBW,[BLT T,17] ;CLEAR BLK 1 TO AVOID RANDOM PARITY + ; ERRORS +] ;KL10P +IFN KS10P,[ + CONO 20700+APRCHN ; Clear memory related APR flags + ; (ECC, Bad, NXM) + MOVSI TT,%KEHLD+%KEREF+%KEPWR + IOWR TT,[KSECCS] ; Reset memory status register. + MOVEI TT,%UBTIM+%UBBAD+%UBPAR+%UBNXD+%UBINI + IOWRQ TT,UBASTA ; Reset both Unibus's and both adaptors. + IOWRI TT,UBASTA + MOVEI TT,DSKCHN_3 ; Set PI level for RH11. (No, you can't do + IOWRQ TT,UBASTA ; this at the same time you reset the Unibus.) + MOVEI TT,MTCCHN_3+TTYCHN ; PI for Tape, for Chaos and TTYs. + IOWRI TT,UBASTA + WRHSB [HSB] ; Set halt status block location. + CLRCSH ; Reset cache once for good measure. + SPCCTX 0,1,USRSTG ; Set up UPT and AC blocks. +] ;KS10P +IFN TEN11P,[ + MOVEI TT,600000+ + SKIPGE TEN11F + MOVEI TT,0 + DPB TT,[.T11CP+EXEUMP] + SETOM T11MP+_-10. ;DONT USE MAP PAGE AS 10-11 PAGE +;IFN PDP6P,[ ;THESE ARE IN SEPARATE MOBIES NOW +; MOVE TT,[-LPDP6M,,_-10.] +; SETOM T11MP(TT) ;CONFLICTS WITH PDP-6 MEM +; AOBJN TT,.-1 +;] +;IFG TSYSM-256.,[ +; MOVSI TT,-TSYSM+256. +; SETOM T11MP(TT) ;CONFLICT PAGES +; AOBJN TT,.-1 +;] +] + MOVE P,SYSPDP + +;INIT THE EXEC PAGE MAP'S DDT PAGES. + HRRZ A,DDT-2 ;LOWEST ADDR IN SYMBOL TABLE + SUBI A,100 ;LEAVE ROOM FOR EXTRA SYMS, 340 ROUTINES' LOSSAGE, ETC. + LSH A,-10. ;GET PAGE SYMTAB STARTS IN + MOVEM A,FDDTPG + MOVEI Q,NQS-1 ;PUT THE TUTS JUST BELOW THE DDT PAGES +BEGTT1: SKIPE QACT(Q) + JRST BEGTT3 ;UNIT NOT IN USE + MOVE T,NTBL(Q) ;NUMBER OF PAGES IN THIS TUT +BEGTT2: SUBI A,1 + MOVE B,[MU23TT_<.TZ .BM >] + MOVEM B,MEMBLT(A) + DPB Q,[MNUMB,,MEMBLT(A)] + SOJG T,BEGTT2 + MOVE B,A + LSH B,10. + HRLI B,640000 + MOVEM B,QTUTO(Q) +BEGTT3: SOJGE Q,BEGTT1 + MOVEM A,FTUTPG + ;NOW MAKE SURE ALL THOSE PAGES ARE MAPPED + MOVEI B,-200(A) ;ASSUMING TSYSM AT LEAST 128K + LSH B,-1 ;GET A B.P. TO IDPB MAP HWD OF 1ST DDT PAGE + ADD B,[442200,,EXEUMP] + TRNE A,1 + IBP B + MOVEI C,600000+PMCSHM(A) ;COMPUTE CONTENTS OF THAT MAP WORD. + MOVE D,[MUDDT_<.TZ .BM >] +BEG3: CAML A,FDDTPG + MOVEM D,MEMBLT(A) +IFG TSYSM-128., IDPB C,B + AOS C +IFG TSYSM-400, CAIE A,400 +.ELSE CAIE A,TSYSM ;STORE THAT MAP WORD AND ALL REST THERE ARE. + AOJA A,BEG3 + +;INITIALIZE REST OF EXEC PAGE MAP +IFN DIRMAP,[ + MOVE Q,[222200,,EXEUMP] + SETZB A,B + SKIPE USEMDM ;MAKE MEDIUM MEM NXM IF DIRMAP NOT TURNED ON + MOVEI B,600200+PMCSHM ;THIS MAY BE USEFUL FOR DEBUGGING + MOVE T,FTUTPG + SUBI T,201 ;STOP AT 1ST TUT PAGE. +BEG2: CAIL A,NEXPGS + DPB B,Q + IBP Q + ADDI B,1 + CAMGE A,T + AOJA A,BEG2 +];END IFN DIRMAP +;DROPS THROUGH + ;DROPS IN + +;SET UP EXEC LOWER MAP (EVEN ON KA, WILL BE LOOKED AT BY .CALL CORBLK) + MOVE A,[600000,,600001+PMCSHM] ;PAGE 0 IS NOT CACHED + MOVSI B,-100 + MOVEM A,EXELMP(B) + TLO A,PMCSHM + ADD A,[2,,2] + AOBJN B,.-3 + +;SET UP SYS JOB'S CIRCULAR POINTERS SO ALL THE PAGES IT HAS ARE ABSOLUTE + + MOVE A,[442200,,UPGMP] + MOVE B,[442200,,UPGCP] + MOVEI D,0 +BEG6: ILDB T,A + MOVEI E,-1 + JUMPN T,BEG7 + CAIL D,200+MMP0 ;ALLOW USERS TO COPY MMP EXEC PGS + CAILE D,200+NEXPGS + MOVEI E,0 ;PG IT DOESN'T HAVE, AND NOT COPYABLE EXEC PG +BEG7: IDPB E,B + CAIGE D,377 + AOJA D,BEG6 + +;EXEC MAP PREPARED, NOW TURN ON PAGING + +IFN KA10P,[ + LPMR UPGML + CONO 633550 +] ;KA10P +IFN KS10P,[ + CONO 67760 ; Disable and Clear all flags + CONO 127660 ; Enable and Clear all flags except memory ECC + APRID A + TLNN A,%UCITS + BUG AWFUL,[ITS WON'T RUN WITH THE DEC MICROCODE] + LDBR3 EXEUMP ; Load exec DBRs. + LDBR4 EXELMP + LPMR UPGML + SPCCTX 1,1,USRSTG ; Select AC blocks and set UBR. + WREBR 020000+ ; Paging on and set EBR. +] ;KS10P +IFN KL10P,[ + CONO 327740 ;ENABLE AND CLEAR ALL FLAGS EXCEPT SWEEP DONE + APRID A + TLNN A,%UCITS + BUG AWFUL,[ITS WON'T RUN WITH THE DEC MICROCODE] + SPCCTX 6,6 ;LOAD MICROCODE CONSTANTS NEEDED BY PAGEING INTO + ; BLOCK 6. + MOVEI 3,EXEUMP ;DBR3 + MOVEI 4,EXELMP ;DBR4 + MOVSI 5,PMAGEM ;LH.AGE + MOVEI 6,PMAGEM ;RH.AGE + MOVEI 7,1000 ;CN1000 + MOVEI 10,100 ;CN100 + CONO PAG,660000+ ;CACHE ON, ITS PAGER, TRAP ENB, EPT ADDR + SPCCTX 1,1,USRSTG,DISABLE + LPMR UPGML +] ;END IFN KL10P + MOVE P,SYSPDP + +;INITIALIZE FREE LISTS IN MEMBLT + + MOVEI A,1 ;A PG NO - NOTE: DON'T DO PAGE ZERO +BEGF0: CAML A,FTUTPG ;IF THIS ISN'T A DDT OR TUT PAGE, THEN + CAIL A,400 + PUSHJ P,CIMEMR ;PUT THIS PAGE ON THE RIGHT FREE LIST + CAIGE A,TSYSM-1 + AOJA A,BEGF0 +IFN TEN11P,[ + SKIPGE TEN11F + JRST BEG4 + MOVSI A,-256. ;CLEAR THE INTERFACE'S "VALID" BITS. + SETZM 400000+T11CP*2000(A) + AOBJN A,.-1 +BEG4:] +IFN XGP,[ + SKIPE TEN11F + JRST BEGX1 + MOVE A,[600000+,,1777] + PUSHJ P,T11AD + BUG ;NO 10-11 PAGES AVAILABLE? + MOVEI TT,600000+<_8>(B) ;GET CORRESP EXEC MAP PG SETUP + DPB TT,[.XGPC+EXEUMP] + MOVEI TT,600000+<_8>+XGPTP + DPB TT,[.XGPB+EXEUMP] ;SETUP PAGE FOR PDP-11 BUFFER +BEGX1:] + +;CHECK AVAIL MEM FOR EXISTANCE + +IFN ECCMEM,[ + LDB TT,[121200,,ECCADR] ;GET PAGE THAT ECC HISTORY IS ON + IORI TT,200000 ;GRANT READ ACCESS + DPB TT,[.ECCPG+EXEUMP] + LPMR UPGML + MOVE A,400000+ECCPG*2000+1760 ;GET CURRENT HISTORY POINTER + LSH A,-32. + MOVEM A,ECCIDX +];ECCMEM + MOVEI A,TSYSM-1 +CKML: MOVEI TT,600000(A) + DPB TT,[.PAREP+EXEUMP] + LPMR UPGML +IFN ECCMEM,[ + LDB TT,[121200,,ECCADR] ;GET PAGE THAT ECC HISTORY IS ON + CAMN A,TT ;THIS PAGE? + JRST CKML1A ;YES, TREAT AS IF OFFLINE, THOUGH WILL ACCESS IT + ; DIRECTLY FROM TIME TO TIME +] + MOVE TT,A + LSH TT,10. + MOVSI T,-8 + CAML TT,MEMLZL(T) + CAML TT,MEMLZH(T) + AOBJN T,.-2 + JUMPL T,CKML1A ;THIS BLOCK KNOWN TO BE LOSING + SKIPL USEHM + CAIGE A,256. + JRST .+2 + JRST CKML1A ;HIGH MOBY NOT TO BE USED +IFN KL10P,[ + MOVEI TT,CKML1 ;KL10 CAN GET PARITY FAULT ON REFERENCE TO NXM + MOVEM TT,PFNPC + HRRM TT,MUUOKN ;IT CAN ALSO GET A UUO +] ;KL10P +IFN KS10P,[ + MOVEI TT,CKML1 + MOVEM TT,EPTPFN +] ;KS10P + CAIL A,256. ;IF NOT IN BOTTOM 256K, DON'T ASSUME GOOD DATA + SETZM 400000+PAREP*2000+20 ;STORE ZERO SO DON'T GET PARITY ERROR + MOVE 0,400000+PAREP*2000+20 ;IF THIS NXMS, MEM THE SYS THINKS + ; IT HAS IS NON EXISTANT +IFN KA10P,[ + CONSZ 10000 + JRST CKML1 ;THAT MEM NXM +] ;KA10P +IFN KL10P,[ + MOVEI TT,PFAIL + MOVEM TT,PFNPC + MOVEI TT,UUOH0 + HRRM TT,MUUOKN + CONSZ 2000 + JRST CKML1 ;THAT MEM NXM +] ;KL10P +IFN KS10P,[ + MOVEI TT,PFAIL + MOVEM TT,EPTPFN + CONSZ 400 + JRST 4,. ; This can't happen, right? (If we got a NXM, we + ; would have trapped to CKML1 already.) +] ;KS10P + SKIPL CKMBLK ;WINS + JRST CKML6 ;THUS ENDING BLOCK OF LOSERS +CKML2: SOJGE A,CKML + AOSN CKMFLG ;ANY MEM OFF UNEXPECTEDLY? + JRST CKML5 ;NO + MOVEI TT,[ASCIZ/ +IS THIS OK? /] ;YES, MAKE SURE SOMEBODY KNOWS ABOUT IT. MAY BE SERIOUS SCREW. + PUSHJ P,T00ASZ + PUSHJ P,T00TYI + ANDI A,137 + CAIE A,"Y + JRST DDT + MOVEI TT,[ASCIZ/ +/] + PUSHJ P,T00ASZ ;CRLF +CKML5: +IFN KL10P,[ + CONO 26400 ;CLEAR ANY NXM AND PARITY INTERRUPTS + CONI MTS,TT + TLNN TT,400 + BUG PAUSE,[TAPE DF-10 IS IN KA MODE, PLEASE FLIP THE SWITCH] + CONI DSK,TT + TLNN TT,4000 + BUG PAUSE,[DISK DF-10 IS IN KA MODE, PLEASE FLIP THE SWITCH] +] ;KL10P +IFN KS10P, CONO 20400 ; Clear NXM flag +;DROPS THROUGH + ;DROPS IN + +IFN RP10P,[ + DATAI DPC,A + TLNN A,NOWRIH ;CHECK FOR FORMAT SWITCH ON RP10 + BUG PAUSE,[RP-10 WRITE HEADERS ENABLED, PLEASE FLIP THE SWITCH] +];RP10P + +IFE &,[ ;CHECK FOR LOSING SWITCHES ON MEMORY ON ML-KA AND DM + + MOVSI D,(DWRITC) ;MAKE COMMAND FOR VERY LAST BLOCK ON DISK + MOVEI A,NCYLS+XCYLS-1 + DATAO DPC,[DNOOPC] ;DETERMINE TYPE OF DRIVE 0 + DATAI DPC,B + TRNE B,RP03BT + MOVEI A,MCYLS+XCYLS-1 ;RP03 + DPB A,[DCYL D] + LSH A,-8 + DPB A,[DCYLXB D] + MOVEI A,NHEDS-1 + DPB A,[DSURF D] + ADDI D,QICWA + MOVEM D,CKMSWC + SUB D,[DWRITC-DREADC] + MOVEM D,CKMSRC + SUB D,[DREADC-DSEEKC] + MOVEM D,CKMSSC + MOVEI A,0 +CKMS1: LDB TT,[MUR,,MEMBLT(A)] ;MEM EXIST? + CAIE TT,MUFR ;AND NOT DDT? + JRST CKMS2 + MOVEI B,600000(A) + DPB B,[.PAREP+EXEUMP] + LPMR UPGML + CAIGE A,CKMSZZ ;MEM LOADED? + JRST CKMS3 ;YES + MOVSI B,'FOO ;NO, LOAD IT + MOVEM B,CKMSBF + MOVE B,[CKMSBF,,CKMSBF+1] + BLT B,CKMSBF+177 + MOVEI B,'BAR + HRRM B,CKMSBF+69. + HRRM A,CKMSBF+6 ;MAKE DIFF FROM OTHER SUCH PAGES + MOVEI C,1 + MOVE B,A + LSH B,-4 ;16K BLOCK # IN B + LSH C,(B) ;GET UNIQUE BIT SO PARITY ERR IF TWO AT SAME ADDR + MOVEM C,CKMSBF+35 + MOVE B,[CKMSBF,,400000+PAREP*2000] + BLT B,400000+PAREP*2000+177 +CKMS3: MOVE B,A ;MAKE IOWD + LSH B,10. + SOS B + HRLI B,-200 + LDB C,[100300,,A] ;MA 15-17 + TRC C,7 + DPB C,[410300,,B] + MOVEM B,QICWA + SETZM QICWA+1 + CONO DPC,175700 + DATAO DPC,CKMSSC ;POSITION HEADS + CONSO DPC,10 + JRST .-1 + DATAO DPC,CKMSWC ;WRITE OUT SECTOR + CONSZ DPC,20 + JRST .-1 + CONI DPC,B + TLNE B,17 + JRST CKMS4 ;CHANNEL ERROR MEM LOSING + TRNE B,177700 + JRST CKMS2 ;FOO, DISK LOSING + MOVE B,[-200,,CKMSBF-1] ;READ IT BACK + MOVEM B,QICWA + SETZM QICWA+1 + SETZM CKMSBF+69. + CONO DPC,175700 + DATAO DPC,CKMSRC + CONSZ DPC,20 + JRST .-1 + CONI DPC,B + TLNE B,17 + JRST CKMS2 ;MEM LOSS IN CKMSBF? + TRNE B,177700 + JRST CKMS2 ;FOO, DISK LOSING + MOVSI B,-200 ;COMPARE + MOVE C,CKMSBF(B) + CAME C,400000+PAREP*2000(B) + JRST CKMS4 ;NOT SAME SWITCHES LOSING + AOBJN B,.-3 +CKMS2: +IFE MCOND DM, ADDI A,16. ;MA10'S !! +IFE MCOND MLKA, ADDI A,32. ;ML-KA MEM IS IN 32K MODULES + CAIGE A,TSYSM + JRST CKMS1 + CONO DPC,175700 ;RESET THE DISK CONTROL + DATAO DPC,[DEASEC+776] ;AT EASE! + CONO PI,20000 ;TURN OFF IOB PI REQ LIGHT + JRST CKMSX ;DONE WITH THIS, CONTINUE INITIALIZATION + +CKMSBF: BLOCK 200 + +CKMS4: MOVEI TT,[ASCIZ/MEM ADDR SWITCHES DISAGREE CPU VS DSK AT LOC /] + PUSHJ P,T00ASZ + PUSHJ P,T00BKO + MOVEI TT,[ASCIZ/0000/] + PUSHJ P,T00ASZ + JRST DDT + +CKMSZZ==./2000+2 ;ABOVE HIGHEST CODE + +CKMSX: +] ;END IFE MCOND MLKA & DM + ;DROPS IN + MOVEI TT,0 + DPB TT,[.PAREP+EXEUMP] + LPMR UPGML +IFN KA10P, CONO PI,240000+11577+IFN C1MXP,20000 +IFE KA10P, CONO PI,11577 +IFN NOTYS, CONO TTY,TTYCHN +IFN NETYS,[ + SETOM DTEODN ;CAN GET SET ON WHILE LOADING, BUT INTR GETS LOST +IFE PDCLKP, CONO DTE,1170+APRCHN ;CLEAR ALL FLAGS AND ASSIGN PI CHANNEL +IFN PDCLKP, CONO DTE,1170+TTYCHN ;CLEAR ALL FLAGS AND ASSIGN PI CHANNEL +] ;END OF IFN NETYS +IFN E.SP,[ + CONO DIS,515330 ;RESET E&S + MOVEI TT,E.SPM + MOVEM TT,34 ;SET PAGER LOC (USED BY DSKDUMP) +] +IFN TM10B,[ + MOVEI TT,MIOWD + MOVEM TT,MICWA ;SETUP LOC FOR MEM CHAN TAPE +] +IFN RP10P+RH10P,[ + MOVEI TT,QIOWD + MOVEM TT,QICWA ;SETUP FOR DEC DISK CHANNEL +] +IFN ARMP, DATAO 760,[0] ;RESET LITE ON ARM +IFN DSDP, CONO DSDEV,10 ;RESET INT RQ FROM PDP10 +IFN RBTCP, CONO RBTCON,0 ;RESET TABLET + + MOVE A,DDT-2 ;PUT GLOBAL BLOCK HEADER AT BEGINNING + MOVE B,[SQUOZE 0,GLOBAL] + CAME B,(A) ;SEARCH FOR GLOBAL BLOCKS + AOBJN A,[ AOBJN A,.-1 + JRST BEGS1] + MOVE C,DDT-2 + MOVEI D,(C) + SUBI D,(A) ;GET ,,-#WDS BEFORE GLOBAL BLOCK + MOVSI D,(D) + ADDM D,1(A) ;GLOBAL BLOCK NOW LARGER + EXCH B,(C) ;EXCHANGE IT WITH FIRST SYM + MOVEM B,(A) + MOVE B,1(A) + EXCH B,1(C) + MOVEM B,1(A) +BEGS1: PUSHJ P,SBUBL + JUMPL J,BEGS1 ;KEEP SORTING UNTIL SYMS IN ORDER + MOVSI A,400000 + IORM A,DDT-1 + +; SORT THE UUO/SUSET/BIT SYMBOL TABLE BY VALUE + + MOVE E,[SYSYMB-SYSYME-1,,SYSYMB] + PUSHJ P,SBUBL0 + JUMPL J,.-2 + + MOVE A,[-LTSTB,,TSTB] +BEG1: MOVE B,(A) + MOVEI C,(B) + EQV C,(B) + AOBJN B,.-1 + MOVEM C,CKSUMS-TSTB(A) + MOVE B,(A) +CKXC2: MOVE C,(B) +REPEAT 36.,[ + IFL .RPCNT-18., TLNE C,400000_<-.RPCNT> + .ELSE TRNE C,400000_<18.-.RPCNT> + XORM B,CKXORS+.RPCNT +] + AOBJN B,CKXC2 + AOBJN A,BEG1 + HRRZS 37 ;MAKE SURE SYS DOESNT IMMEDIATELY COME DOWN +;DROPS THROUGH + ;DROPS IN + MOVEI A,0 + CLEARM QACTB +QSETUP: MOVE B,DCHBT(A) + SKIPN QACT(A) + IORM B,QACTB + CAIGE A,NQS-1 + AOJA A,QSETUP +IFN DC10P, CONO DC0,DCCSET+DCDENB+DSKCHN ;RESET 2314 AND SET DATA ERROR ENABL +IFN 340P, CONO DIS,100 +IFN TK10P, CONO NTY,TTYCHN +IFN MTYP, CONO MTY,TTYCHN + CLEARM USRHI + CLEARB U,USER + MOVE P,SYSPDP +IFN DPKPP,[ + CONO DPK,400070+TTYCHN ;INITIALIZE DP KLUDGE + DATAO DPK,[4,,DPKBAS] + MOVE T,[-NDPTYS,,NFDPTY] + MOVEI B,0 ;LINE # +DPIL: LDB A,[$TTOSP,,TTYTYP(T)] ;OUTPUT SPEED + MOVE A,DPSP(A) ;MAP TO DPK SPEED CODE + DPB B,[140400,,A] ;LINE # + CONO DPK,500+TTYCHN(A) ;LOAD OUT SPEED + LDB A,[$TTISP,,TTYTYP(T)] ;INPUT SPEED + MOVE A,DPSP(A) ;MAP TO DPK SPEED CODE + DPB B,[140400,,A] + CONO DPK,700+TTYCHN(A) ;LOAD IN SPEED + AOS B + AOBJN T,DPIL +] +IFN DZ11P,[ + PUSHJ P,DZINIT +];DZ11P +IFN N11TYS,[ + SKIPE TEN11F + JRST BEG5 + MOVSI R,-NTTPG-NTVBP+1 + MOVE T,[.TTPG0+EXEUMP] +BEG9: MOVEI A,(R) ;SET UP 1 MORE TEN-11 MAP ENTRY + LSH A,20. + IORI A,1777 ;A FULL PAGE + TLO A,600000+TT11NM*400 + PUSHJ P,T11AD + BUG + ADDI B,600000+<_8> ;READ-WRITE, IN HIGH MOBY. + DPB B,T + IBP T + AOBJN R,BEG9 + MOVE A,[(600000+TT11NM*400)TT11CR_8] ;POINTER TO CONSOLE REG + PUSHJ P,T11AD + BUG + ADDI B,600000+<_8> + DPB B,T + LPMR UPGML + SKIPE TT11P ;IF WE'RE SUPPOSED TO USE THE TV 11, + SETZM TT11UP ;REQUEST IT TO RE-INIT. + ;IF TT11UP BECOMES NONZERO, THE 11 IS UP. +BEG5: ];END IFN N11TYS +IFN CH11P,[ + XCTRI [IORDI A,CAIMYN] + CAIA + BUG HALT,[CHAOSNET INTERFACE NOT RESPONDING (CHECK THE BREAKER ON THE UNIBUS)] +] ;CH11P +IFN CHAOSP,[ IFN T11CHP,[ + SKIPE TEN11F ;SET UP TEN-11 CHAOS NET INTERFACE PAGE + JRST BEG8 + MOVE A,[(600000+CH11NM*400)1004_8+1777] + PUSHJ P,T11AD + BUG + ADDI B,600000+<_8> + DPB B,[.CHSPG+EXEUMP] +BEG8: ]] ;CHAOSP, T11CHP +IFN DL10P,[ ;INITIALIZE DL10 + CONO DLC,400000 ;MR CLR + CONO DLB,1 ;TURN OFF EXCESS LIGHTS + CONO DLB,2 ;.. + CONO DLB,3 ;.. + CONO DLB,DL10AR ;64 WORDS FOR PDP11 #0 AT DL10AR + DATAO DLC,[200001,,] ;KA INTERRUPT MODE + SKIPE DL10F + CONO DLC,100020+TTYCHN ;ENB PDP11 PORT #0 AND ENB INTR + MOVSI T,1 + SKIPN DL10UP + SOJG T,.-1 + SKIPGE T ;IF THE 11 DIDN'T SAY IT WAS UP, + SETZM DL10F ;MARK IT NON-FUNCTIONAL. +] +IFN KL10P,[ + CONO TIM,460000+3900. ;SET INTERVAL TIMER TO 39 MILLISECONDS FOR OVHMTR + CONO MTR,433001 ;TIME BASE ON, ACCOUNT FOR USER + EXEC NO PI, INTERVAL PIA=1 + PUSHJ P,PRFOFF ;INIT PERFORMANCE COUNTER +] ;KL10P + +;DROPS IN + MOVSI T,%TBNOT+%TBDTY+%TBNVR ;SYS JOB HAS NO CONSOLE ALL TO ITSELF + MOVEI U,LUBLK + PUSHJ P,USSINI ;INITIALIZE SYS JOB VARIABLES BLOCK + JRST .-1 + AOS NMPGS +IFE KA10P,[ + MOVEI T,UUOH0 ;CLOBBERED BY USSINI + HRRM T,MUUOKN +] ;IFE KA10P + MOVSI T,600000 + HLLM T,UPGMP ;GIVE PG 0 TO SYS JOB + MOVSI T,-1 + HLLM T,UPGCP + MOVEI T,2000 + MOVEM T,HUSRAD + MOVEI T,SYSRCE ;SET SYS JOB RESOURCE POINTER + MOVEM T,UTMPTR + MOVSI A,(SIXBIT /SYS/) ;""" NAMES + MOVEM A,USYSNM(U) + MOVEM A,UNAME(U) + MOVEM A,XUNAME(U) + MOVEM A,JNAME(U) + MOVEM A,XJNAME(U) + SETZM USTP(U) + MOVSI T,%TBNOT+%TBDTY+%TBNVR ;CORE JOB HAS NO CONSOLE + MOVEI U,2*LUBLK + PUSHJ P,USSINI ;SET UP CORE JOB VARIABLES BLOCK + JRST .-1 + MOVE A,[SIXBIT /CORE/] + MOVEM A,USYSNM(U) + MOVEM A,UNAME(U) + MOVEM A,XUNAME(U) + MOVSI A,(SIXBIT /JOB/) + MOVEM A,JNAME(U) + MOVEM A,XJNAME(U) + MOVEI T,SYSRCE + MOVEM T,UTMPTR+LUBLK + SETZM USTP(U) + MOVEI A,CORJI +IFE KA10P, HRLI A,%PSPCU ;DOES CORE JOB XCTR? + MOVEM A,UPC(U) +IFE KA10P,[ + MOVE T,[JSR ILLTRP] ;SYS AND CORE JOBS SHOULDN'T TRAP + MOVEM T,TR1INS ;THESE WON'T BE USED ANYWAY UNLESS + MOVEM T,TR2INS ;SOMEDAY THEY SHOULD RUN IN USED MODE + MOVEM T,TR3INS + MOVEM T,TR1INS+L + MOVEM T,TR2INS+L + MOVEM T,TR3INS+L +] ;IFE KA10P + MOVEI A,SYSB+2 ;GIVE SYSTEM CORE TO SYS JOB, WITH A COUPLE + MOVEM A,CORRQ ; SPARE JOB SLOTS + AOS NCORRQ + SOS A + ADDM A,NCBCOM +; DATAI CLK1,LCLK1 + CONO PI,100+UTCON-1 ;ALL EXCEPT 7 +IFN KA10P, CONO 3000+APRCHN +IFN KL10P,[ +IFN PDCLKP, CONO CLK,APRCHN +.ELSE [ MOVEI A,%DTCLN ;TURN ON 60-CYCLE CLOCK + MOVEM A,DTECMD + SETZM DTEFLG + CONO DTE,%DBL11 + SKIPN DTEFLG + JRST .-1 +] + CONO APRCHN ;ENABLE APR FAULT INTERRUPTS + SWPUA ;UPDATE MEMORY AGAIN TO MAKE SURE DDT + SYMBOL + ; TABLE OUT OF CACHE + CONSZ 200000 + JRST .-1 +] ;KL10P +IFN KS10P,[ + WRINT [KSFREQ] ; 60 cycle clock. + CONO APRCHN ; Enable APR faults and clock ints. + CLRCSH ; Is this necessary? What the heck... +] ;KS10P +IFN CH10P,[ + CONI CHX,T ;CHECK CHAOS ADDRESS SWITCHES + LDB T,[$CHXAD,,T] + CAIE T,MYCHAD + JRST [ MOVEI TT,[ASCIZ/CHAOSNET ADDRESS SWITCHES ARE SET WRONG/] + PUSHJ P,T00ASZ + JRST DDT ] + CONO CHX,@CHXCNO ;ENABLE INTERRUPTS +];CH10P + JRST ICLR + +CKML1: ;MEM NON-EXISTANT PATCH OUT +IFN KA10P, CONO 10000 ;TURN OFF NXM FLAG +IFN KL10P,[ + CONO 22000 + MOVEI TT,PFAIL + MOVEM TT,PFNPC + MOVEI TT,UUOH0 + HRRM TT,MUUOKN +] ;KL10P +IFN KS10P,[ + CONO 20400 + MOVEI TT,PFAIL + MOVEM TT,EPTPFN +] ;KS10P + SKIPGE CKMBLK + MOVEM A,CKMBLK ;HIGHEST IN BLOCK OF LOSERS +CKML1A: LDB TT,[MUR,,MEMBLT(A)] + CAIE TT,MUFR + BUG ;? + CAIG A,SYSB+1 + JRST 4,. ;SYS MEM NON EX? (BUG PROBABLY WON'T WORK) + PUSHJ P,MPOUT2 ;FLUSH THAT BLOCK + MOVEI TT,MUHOLE + DPB TT,[MUR,,MEMBLT(A)] + CAIL A,400 ;IF NXM IN LOW MOBY + JRST CKML2 + MOVEI U,0 + PUSHJ P,UPLC + LDB TT,T + ANDI TT,PMRCM + CAIE TT,(A) + JRST CKML2 + DPB U,T ;PATCH THIS BLOCK OUT OF EXEC MAP + DPB U,Q + JRST CKML2 + +; REPORT A BLOCK OF LOSING MEMORY + +CKML6: PUSH P,A + MOVEI TT,[ASCIZ/MEM OFF /] + AOSN CKMFLG + PUSHJ P,T00ASZ + ADDI A,1 ;LOWEST LOSER = HIGHEST WINNER + 1 PAGE + PUSHJ P,T00BKO + MOVEI A,"- + PUSHJ P,T00TYO + MOVE A,CKMBLK + PUSHJ P,T00BKO + MOVEI A,40 + PUSHJ P,T00TYO + SETOM CKMBLK + POP P,A + JRST CKML2 + +USEHM: -1 ;-1 => USE MEM IN HIGH MOBY (IF PRESET) + +CKMBLK: -1 ;IF + HIGHEST LOSING BLOCK IN CONTIG RANGE +CKMFLG: -1 ;IF + PRINTED MESSAGE ALREADY +CKMSWC: 0 ;WRITE CMD +CKMSRC: 0 ;READ CMD. +CKMSSC: 0 ;SEEK CMD. +;UP TO 8 RANGES OF ADDRESSES THAT SHOULD NOT BE USED BECAUSE THEY +;DON'T WORK BUT AREN'T NXM. +MEMLZL: BLOCK 8 ;LOWEST LOC +MEMLZH: BLOCK 8 ;HIGHEST LOC+1 +FTUTPG: 0 ;FIRST PAGE USED FOR TUTS + +;INPUT CHAR FROM CONSOLE TTY AND ECHO + +T00TYI: +IFN KA10P,[ + CONSO TTY,40 + JRST .-1 + DATAI TTY,A + ANDI A,177 +] ;KA10P +IFN KL10P,[ + SETZM DTEFLG + MOVEI A,%DTTYI + MOVEM A,DTECMD + CONO DTE,%DBL11 + SKIPN DTEFLG + JRST .-1 + SKIPN A,DTEF11 + JRST T00TYI +] ;KL10P +IFN KS10P,[ + SKIPN A,8CTYIN + JRST .-1 + ANDI A,177 +] ;KS10P + +; TYPE CHAR IN A ON CONSOLE TTY + +T00TYO: +IFN KA10P,[ + CONSZ TTY,20 + JRST .-1 + DATAO TTY,A +] ;KA10P +IFN KL10P,[ + SETZM DTEFLG + MOVEM A,DTECMD + CONO DTE,%DBL11 + SKIPN DTEFLG + JRST .-1 +] ;KL10P +IFN KS10P,[ + PUSH P,A + ANDI A,177 + IORI A,400 + MOVEM A,8CTYOT + CONI A + IORI A,80INT + CONO (A) + SKIPE 8CTYOT + JRST .-1 + POP P,A +] ;KS10P + POPJ P, + +; TYPE BLOCK NO IN A AS HIGH 3 OCTAL DIGITS OF ADDR +; (ALL MEMORIES MULTIPLE OF 4K. MAX MEMORY 2M WORDS.) + +T00BKO: PUSH P,A + PUSH P,B + LSHC A,-8 +REPEAT 3,[ + ADDI A,"0 + PUSHJ P,T00TYO + MOVEI A,0 + LSHC A,3 +] + JRST POPBAJ + +; TYPE ASCIZ IN TT ON T00 + +T00ASZ: PUSH P,A + HRLI TT,440700 +T00AZ1: ILDB A,TT + JUMPE A,POPAJ + PUSHJ P,T00TYO + JRST T00AZ1 + +IFN DPKPP,[ ;MAP SYSTEM SPEED CODES TO DATAPOINT KLUDGE CODES +DPSP: 0_9 ;134 + 1_9 ;600 + 2_9 ;110 + 3_9 ;150 + 4_9 ;300 + 5_9 ;1200 + 5_9 ;1800 * + 6_9 ;2400 + 7_9 ;4800 +REPEAT 20-<.-DPSP>, 7_9 ;FAST * +];DPKPP + +CONSTANTS +VARIABLES + +IEND: +.HKALL==0 + +; Define location known as start of SALV disk salvager. If system overruns +; this address, must either reduce system size or increase the SALV start +; address. If SALV is changed, the SALV program must also be changed to +; start at the right place. There is a limit to how high it can go, +; however. +IFN KL10P, SALV==:105*2000 ; MC-KL is getting huge +.ELSE SALV==:100*2000 +IFG IEND-SALV,.FATAL System overruns SALV start addr! + +IFGE TSYSM-256.,DDT=774000 +.ELSE DDT=TSYSM*2000-4000 +DSKDMP==DDT+3700 + +IFG LBUGTB-LBUGT2,[ +.ERR MAKE THE BUGTAB BIGGER +INFORM LBUGTB-LBUGT2,\LBUGTB-LBUGT2 +.FATAL FATAL ERROR, RUNNING THIS WOULD CAUSE TOTALLY WEIRD BUGS +] + +IF2 EXPUNGE FOO,ZZZQ,FNM,ZCHR,ZZ,ZZZ,BUGB,BUGF,BUGN,BUGNN + +END BEG ;START AT BEG TO SALVAGE AND RUN ITS, START AT GO TO JUST ITS diff --git a/src/system/itsdev.974 b/src/system/itsdev.974 new file mode 100755 index 00000000..caef28fd --- /dev/null +++ b/src/system/itsdev.974 @@ -0,0 +1,5321 @@ +; I T S MISCELLANEOUS DEVICES + +IFN PTRP,[ + +SUBTTL PAPER TAPE PUNCH ROUTINES + +PTPO: JSP Q,STDOPN + 7,,PTPUSR + PTPA,,PTPB + PTPWA,,PTPWB + PTPI,,0 + PTPI,,0 + +BPIPUN: JSP E,NBTOCH + CAIN A,EOFCH + POPJ P, + JRST APIPU2 + +APIPUN: SKIPGE C + SKIPA A,(C) + UMOVE A,(C) + ANDI A,177 +APIPU2: CAIN A,14 + JRST PUNFF + TRO A,200 + JRST PIPUN3 + +PIPUN: SKIPGE C + SKIPA A,(C) + UMOVE A,(C) +PIPUN3: SKIPG PUNCC + JRST PUNW1 +PIPUN2: IDPB A,PUNIP + HRRZ A,PUNIP + CAIN A,PUNBE-1 + MOVEI A,PUNBO + HRRM A,PUNIP + SOS PUNCC +PUNST: SKIPGE PUNNT + POPJ P, ;PUNCH OUT OF TAPE + CONSO PTP,7 + CONO PTP,10+PCHCHN + POPJ P, + + PUSHJ P,PUNW2 +PUNW1: PUSHJ P,UFLS + JRST PIPUN2 + +PUNW2: SKIPG T,PUNCC + POPJ P, + CAIL T,PUNSIZ*2 + JRST POPJ1 + JRST POPJ3 + +PUNFF: MOVEI T,55 + CAMLE T,PUNCC + PUSHJ P,UFLS + MOVSI B,-4 + PUSHJ P,PUNFF2 + MOVEI A,214 + PUSHJ P,PIPUN2 + MOVSI B,-50 +PUNFF2: MOVEI A,0 + PUSHJ P,PIPUN2 + AOBJN B,PUNFF2 + POPJ P, + +WBPIPN: JSP Q,WRDBT +WAPIPN: MOVEI T,6 + CAMLE T,PUNCC + PUSHJ P,UFLS + SKIPGE C + SKIPA B,(C) + UMOVE B,(C) + MOVSI E,-6 +WPIPN2: MOVEI A,2 + LSHC A,6 + PUSHJ P,PIPUN2 + AOBJN E,WPIPN2 + POPJ P, + +PBRK1: MOVEI A,PUNSIZ*4-4 + CAMG A,PUNCC + JRST PUNSTP + CONSZ PTP,100 ;CHECK NO TAPE FLAG + JRST PBRK2 ;PUNCH OUT OF TAPE + ILDB A,PUNOP + DATAO PTP,A + HRRZ A,PUNOP + CAIN A,PUNBE-1 + MOVEI A,PUNBO + HRRM A,PUNOP + AOSA PUNCC +PUNSTP: CONO PTP,0 + JRST LPBKRT + +PBRK2: SETOM PUNNT ;PTP OUT OF TAPE + JRST PUNSTP + +;PTP SLOW CLOCK ROUTINE +PTPCHK: SKIPGE PUNNT + CONSZ PTP,100 + POPJ P, + HRRZM P,PUNNT + JRST PUNST ;PTP HAS TAPE NOW + +EBLK + +PUNNT: 105 ;-1 => PTP OUT OF TAPE +PUNCC: PUNSIZ*4-4 +PUNIP: (1000)PUNBO-1 +PUNOP: (1000)PUNBO-1 +PUNBO: BLOCK PUNSIZ +PUNBE: + +BBLK + +PUNCLR: MOVEI A,PUNSIZ*4-4 + MOVE B,PUNIP + MOVEM A,PUNCC + MOVEM B,PUNOP + POPJ P, + +PUNFIN: MOVE T,PUNSIZ*4-4 ;.CALL FINISH + CAMLE T,PUNCC + PUSHJ P,UFLS + POPJ P, + +AFEED: HRRZ A,(R) + CAIL A,PTPI ;LOWEST PTP DEV # + CAILE A,PTPWB ;HIGHEST PTP DEV # + POPJ P, ;PTP NOT OPEN ON CHNL + MOVEI A,0 + PUSHJ P,PIPUN3 + JRST POPJ1 + +SUBTTL PAPER TAPE READER ROUTINES + + PTRCHX==10 ;NUMBER OF CHARACTERS IGNORED AT END OF TAPE + +PTRO: PUSH P,[PTRO1] ;SO STDOPN WILL RETURN + JSP Q,STDOPN + 7,,PTRUSR + REDUAI,,REDBAI ;ASCII MODE + REDUII,,REDBII ;IMAGE MODE + REDUTI,,0 ;ALL 8 HOLES MODE + REDUTI,,0 ;" " " " + + ;RETURN FROM STDOPN +PTRO1: POPJ P, ;OPEN LOST + AOS (P) ;OPEN WON, MAKE RETURN SKIP + SKIPE PTRUSE + POPJ P, ;READER ALREADY OPEN, DON'T RESET + ;READER NOT ALREADY OPEN, SO + ;RESET PTR POINTERS AND START UP READER + CONO PI,PTROFF ;INHIBIT INTERRUPTS + MOVEI T,20 ;BUSY FLAG + PUSHJ P,PTRST ;START UP READER IF NOT ALREADY RUNNING + ;RESET PTR BUFFER POINTERS +PTRZAP: MOVE A,[041000,,PTRBUF-1] ;BUFFER BYTE POINTER + MOVEM A,PTRIP ;BUFFER INPUT (INTERRUPT) POINTER + MOVEM A,PTROP ;BUFFER OUTPUT (IOT) POINTER + MOVEI A,PTRCHX ;REINITIALIZE CHARACTER COUNT + MOVNM A,PTRCC ;" " " + CONO PI,PTRON ;RE-ENABLE INTERRUPTS + JRST PTRSIW ;RESET STATUS OF IMAGE WORD AND RETURN + + ;CLOSE CHANNEL ON WHICH PTR OPEN + +PTRCLS: CONO PI,PTROFF ;INHIBIT INTERRUPTS + SOSL PTRUSE ;DECREMENT USE COUNTER + JRST PTRONJ ;PTR OPENED ON MORE CHANNELS + SETOM PTRUSR ;NO MORE OPENS ON READER, INDICATE NO USER + SETOM PTRDIE ;EVENTUALLY TURN OFF READER + JRST PTRZAP ;RESET BUFFER STATUS + +PTRRS: CONO PI,PTROFF ;PTR .RESET ROUTINE + JRST PTRZAP + + ;BLOCK ASCII INPUT + +PTRBAI: JSP E,INBTCH ;DO IT A CHARACTER AT A TIME + + ;GET AN ASCII CHARACTER IN W + +PTRUAI: +PTRCHA: PUSHJ P,PTRCH ;GET CHARACTER - SKIPS IF EOF. + TRZA W,200 ;CLEAR 200 BIT + JRST POPJ1 + JUMPE W,PTRCHA ;IF RESULT ZERO THEN DON'T CALL IT ASCII + CAIN W,177 ;IF RUBOUT, + JRST PTRCHA ;THEN IGNORE IT + POPJ P, ;ASCII, USE IT + +PTRBII: JSP W,WRDBTI ;BLOCK IMAGE INPUT. + + ;UNIT IMAGE INPUT + ;END-OF-FILE GIVES SIXBIT /######/ + +PTRUII: PUSHJ P,PTRCH ;GET CHARACTER + TRNE W,200 + CAIA ;CALL IT BINARY IF 200 SET, OR IF EOF. + JRST PTRUII + IDPB W,PTRIBP + JUMPL W,PTRUI2 ;IF REACHED EOF, SKIP 1 OR 2. + SOSLE PTRICC ;IF WORD NOT FULL, + JRST PTRUII ;THEN GO BACK FOR MORE + JRST PTRUI1 ;ELSE RETURN THE WORD. + +PTRUI2: SOSG B,PTRICC + JRST PTRUI3 + CAIE B,5 + JRST PTRUII + JRST PTRUI4 + +PTRUI3: AOS (P) ;IF WE REACHED EOF, SKIP TWICE. +PTRUI4: AOS (P) ;REACHED EOF BEFORE WORD; SKIP ONCE. +PTRUI1: MOVE W,PTRIW ;WORD FULL, +PTRSIW: MOVEI B,6 ;NOW REINITIALIZE POINTERS TO WORD + MOVEM B,PTRICC ;CHARACTER COUNT OF WORD + MOVE B,[440600,,PTRIW] ;POINTER TO WORD + MOVEM B,PTRIBP + POPJ P, + + ;GET A CHARACTER IN W OR SKIP RETURNING -1,,EOFCH IF NONE AVAILABLE + +PTRUTI: ;UNIT MODE ALL-HOLES INPUT. +PTRCH: MOVEI T,20 ;BUSY FLAG + PUSHJ P,PTRCHW ;WAIT FOR A CHARACTER + PUSHJ P,UFLS + SOSGE I,PTRCC ;DECREMENT CHARACTER COUNT + JRST PTRCH1 ;BUFFER EMPTY + MOVEI T,10 ;DONE FLAG + CAIGE I,REDSIZ-PTRCHX ;IF BUFFER LESS THAN 1/4-FULL, + PUSHJ P,PTRST ;THEN MAKE SURE READER RUNNING + ILDB W,PTROP ;GET CHARACTER + HRRZ B,PTROP ;RING THE BUFFER + CAIL B,PTRBUF+REDSIZ-1 + MOVEI B,PTRBUF + HRRM B,PTROP + POPJ P, + + ;END-OF-FILE ENCOUNTERED DURING PTRCH + +PTRCH1: AOS PTRCC ;RESTORE CHARACTER COUNT TO ITS ORIGINAL STATE + JRST UNIEOF + + ;SKIP IF CHARACTER IN BUFFER OR END-OF-TAPE + +PTRCHW: SKIPG PTRCC ;IF CHARACTER IN BUFFER, + CONSO PTR,400 ;OR POWER IS OFF, + JRST POPJ1 ;THEN EXIT SKIPPING + ;OTHERWISE, + ;MAKE SURE READER RUNNING + +PTRST: CONSZ PTR,7 + CONSO PTR,30 ;IF RUNNING, + JRST .+2 + POPJ P, ;THEN THAT'S ALL + CONO PTR,PTRCHN(T) ;NOT RUNNING, RESTART WITH SELECTED FLAG + SETOM PTRDIE ;LET SLOW CLOCK FIGURE OUT IF THERE'S TAPE + POPJ P, + + ;PTR INTERRUPT ROUTINE + +PTRBRK: AOSN PTRSTP ;IF READER SHOULD BE STOPPED THIS BREAK, + JRST PTRFUL ;THEN STOP IT (BUFFER FULL) + DATAI PTR,A ;GET CHARACTER + SETOM PTRDIE ;TELL SLOW CLOCK THAT BREAK HAS HAPPENED + IDPB A,PTRIP ;PUT IN BUFFER + HRRZ A,PTRIP ;RING THE BUFFER + CAIN A,PTRBUF+REDSIZ-1 + MOVEI A,PTRBUF + HRRM A,PTRIP + AOS A,PTRCC ;TOTAL CHARACTER COUNT-PTRCHX + CAIGE A,REDSIZ*4-10-PTRCHX + JRST LPBKRT + SETOM PTRSTP ;STOP READER AT NEXT BREAK + JRST LPBKRT + +PTRFUL: CONO PTR,PTRCHN ;BUFFER FULL, STOP READER + MOVEI A,1 ;TELL SLOW CLOCK... + MOVEM A,PTRDIE ;NOT TO TURN IT OFF + JRST LPBKRT + + ;SLOW CLOCK ROUTINE + ;CHECKS READER EVERY HALF-SECOND + +PTRCHK: AOS A,PTRDIE + CAIN A,1 ;IF UNINTENTIONALLY STOPPED FOR OVER HALF-SECOND + CONO PTR,400 ;THEN TURN THE READER OFF + POPJ P, + +EBLK + ;PTR VARIABLES + +PTRDIE: -264 ;END-OF-TAPE DETECTION +PTRSTP: 0 ;-1 => STOP READER AT NEXT BREAK (SET DURING BREAK WHEN BUFFER FULL) +PTRIP: 041000,,PTRBUF-1 ;BUFFER INPUT (INTERRUPT) POINTER +PTROP: 041000,,PTRBUF-1 ;BUFFER OUTPUT (IOT) POINTER +PTRBUF: BLOCK REDSIZ ;READER BUFFER +PTRCC: -PTRCHX ;NUMBER OF CHARACTERS IN BUFFER -PTRCHX + +PTRIW: 0 ;CURRENT WORD FOR IMAGE MODE +PTRIBP: 440600,,PTRIW ;POINTER TO CURRENT WORD +PTRICC: 0 ;CHARACTER COUNT TO CURRENT IMAGE MODE WORD + +BBLK + +] ;END OF IFN PTRP + +SUBTTL LINE PRINTER ROUTINES + +IFN NLPTP,[ +NLPTO: MOVE A,UTMPTR(U) + SKIPGE NLUSR + SKIPL TTYTYP-USRRCE(A) + JRST TPLO + SETOM NLFREE + MOVEI T,LPTBSZ + CAME T,NLPTBR ;WAIT TILL LPT BUFFER IS EMPTY. + PUSHJ P,UFLS + CONSZ NLPT,207 ;AND LPT ISN'T STILL PRINTING LAST WD + PUSHJ P,UFLS + PUSH P,[NLPTO1] + JSP Q,STDOPN + 1,,NLUSR + NLPTDN,,NLPTBN + +NLPTO1: POPJ P, ;LPT NOT AVAIL & NOT ASSIGNED. + ;LPT ASSIGNED, INIT IT. + CONO NLPT,1000 ;PUT LPT INTERFACE IN IMAGE MODE, + DATAO NLPT,[23*2] ;TURN ON THE LPT'S MOTOR. + MOVEI I,1000 + CONSZ NLPT,200 ;WAIT TILL IT IS ON. + SOJG I,.-1 + AOS (P) +NLPTO3: HRROI I,NLPTCF + HRROI C,I + PUSHJ P,BNLPTO ;CAN'T PCLSR SINCE BUFFER IS EMPTY. + HRRZ I,NLPTBP + HRLI I,010700 + MOVEM I,NLPTIP + POPJ P, + +NLPTCF: 15_29.+14_22.+177_15.+177_8+177_1 +] + +IFN GLPTP,[ ;GOULD ELECTROSTATIC PRINTER ROUTINES + +IFE DL10P,.ERR GOULD PRINTER WITHOUT A PDP11 TO RUN IT? + +;OPEN ROUTINE + +GLPTO: SKIPE GLPTER + JRST OPNL7 ;DEV NOT READY IF 11 UNHAPPY + MOVEI Q,[1,,LPTUSR + GLPTDN,,GLPTBN] + PUSHJ P,STDOPN + POPJ P, + SETZM GLPGRF + TLNE C,10 ;BIT 3.4 => GRAPHICS MODE. + SETOM GLPGRF + JRST POPJ1 + + + + + + +;IOT ROUTINES + + SKIPA T,[SIOKT] ;SIOT HANDLER = UNIT HANDLER MINUS ONE +GLPTDO: MOVEI T,CHRKTO + MOVE E,[440700,,5] + JRST GLPTOO + +GLPTBO: MOVEI T,BLKT + MOVE E,[444400,,1] +GLPTOO: JSP B,(T) + SETZ GLPMPP + GLPMPC + GLPBGB + GLPBWW + JRST 4,. + SKIPE GLPTBC + +;CLOSE ROUTINE + +GLPCLS: SKIPE GLPMPP ;IF THERE'S AN UN-SENT BUFFER, + PUSHJ P,GLPBWW ;BARK AT THE PDP11 + SKIPE GLPTBC ;WAIT FOR ALL BUFFERED STUFF TO BE SENT + PUSHJ P,UFLS + PUSHJ P,GLPBG0 ;AVOID IOCERR AT NEXT OPEN + IRPS CH,,12 14 177 105 + MOVE C,[SETZ I] ;AT CLOSE SEND FF, EOF + MOVEI I,CH ;THIS CAN'T PCLSR ONCE IT GETS A NEW BUFFER. + PUSHJ P,GLPTDO + TERMIN + SETZM GLPGRF + PUSHJ P,GLPBWW ;WRITE LAST BUFFER + SETOM LPTUSR + SETOM LPTUSE + POPJ P, + +;BUFFER GET ROUTINE + +GLPBGB: SKIPE GLPTER + JRST IOCER1 ;DEV NOT READY IF 11 UNHAPPY ABOU IT. + SKIPE GLPTBC + POPJ P, ;BUFFER BUSY +GLPBG0: MOVEI TT,GLPTBF + MOVEI J,GLPBSZ + JRST SIOBGX + +;BUFFER DISCARD ROUTINE + +GLPBWW: MOVE D,[450000,,GLPTBF-1] ;DL10 BYTE POINTER (7-BIT BYTES) + SKIPE J,GLPGRF + HRLI D,340000 ;GRAPHICS MODE => 8-BIT BYTES + MOVEM D,GLPTBP + SKIPN D,GLPMPP ;COMPUTE # CHARS IN BUFFER + POPJ P, + JUMPL D,[SOJA D,GLPBW1] + MOVEI TT,15 ;INDEPENDENT OF E, BLOCK VS UNIT, ETC. + TLNE D,760000 + JRST [ IDPB TT,D ? JRST .-1 ] +GLPBW1: MOVEI D,-GLPTBF+1(D) + IMUL D,[4 ? 5]+1(J) ;GRAPHICS => 4, ELSE 5. + MOVEM D,GLPTBC ;START THE PDP11 + SETZM GLPMPP ;FLAG THAT BUFFER IS NOT ACTIVE AT M.P. LEVEL + SETZM GLPMPC + POPJ P, + +;NOTE: TPL CODE HAS DELIBERATELY BEEN OMITTED. +;THE DL10 LIMITS THE BUFFER SIZE TO 256 WORDS. WITH THIS SMALL +;A BUFFER THE SYSTEM JOB CAN'T DRIVE THE PRINTER AT FULL SPEED +;BECAUSE IT CAN ONLY IOT ONCE A SECOND OR SO. +;ANYWAY, THE NECESSARY TPL CODE IS HAIRY. +] ;END IFN GLPTP + +IFN OLPTP,[ + +LPTLPP==60. + +LPTO: CAMN U,OLUSR + JRST LPTO2 ;ALREADY HAS IT + MOVE A,UTMPTR(U) ;GET POINTER TO USER RESOURCE + ;(TTY DEPENDANT) + SKIPL TTYTYP-USRRCE(A) + JRST TPLO +LPTO2: PUSH P,[LPTO1] + JSP Q,STDOPN + 1,,OLUSR + LPTDN,,LPTBN + +LPTO1: POPJ P, ;OPEN LOST + SKIPE OLUSE ;OPEN WON + JRST POPJ1 ;NOT FIRST OPEN BY THIS USER + AOS (P) +LPTRS2: MOVEI A,15 ;ENTRY FROM LPTRS, DUMP OUT CRUD ON THIS LINE THEN FORM FEED + PUSHJ P,PILPT + MOVEI A,14 + JRST PILPT + +BLPTO: MOVEI E,PILPT + JRST NBTOCH + +PILPT1: SKIPGE C + SKIPA A,(C) + UMOVE A,(C) + ANDI A,177 +PILPT: CAIN A,177 + POPJ P, ;IGNORE RUBOUTS + MOVEI T,130. ;LPTCC COMPARED WITH 132. BY SYSTEM JOB BEFORE TRY OF .OPEN + CAMLE T,LPTCC + JRST LPTW1 ;WAIT +LPTIM: CAIGE A,40 + JRST LPTRC + CAIL A,140 + SUBI A,40 +LPTIM2: AOSN LPTBSF + PUSHJ P,LPC ;PRINT PREV STUFF AND SPACE OVER + AOS T,LINEPOS +BADCOL: CAIN T,-1 ;PATCH NUM OF BAD COL IN HERE WHEN NECESSARY + JRST LPTBC1 + CAILE T,120. + JRST PILPT2 +LPC1: SUBI A,40 + IDPB A,LPTIP + HRRZ A,LPTIP + CAIN A,LPTBE-1 + MOVEI A,LPTBO + HRRM A,LPTIP + SOS LPTCC + CONSO OLPT,7 + CONO OLPT,LPTCHN + POPJ P, + +LPTBC1: PUSH P,A + MOVEI A,40 + PUSHJ P,LPC1 + POP P,A + JRST LPC1 + +LPTRC: CAIN A,10 + JRST LPTBS ;BACK SPACE + CAIN A,11 + JRST LPTTAB + CAIN A,12 + JRST LPTLF + CAIN A,14 + JRST LPTFF + CAIN A,EOFCH + JRST LPTEOF + SETOM PCL + CAIE A,15 + JRST LPTRCH +LPT.CR: SETZM LINEPOS + SETZM LPTBSF + JRST LPC1 + + PUSHJ P,LPTW2 +LPTW1: PUSHJ P,UFLS + JRST LPTIM + +LPTW2: CAMLE T,LPTCC + POPJ P, + MOVE T,LPTCC + CAIL T,*2 + JRST POPJ1 + JRST POPJ3 + +LPTBS: SKIPG LINEPOS + POPJ P, ;AT BEG OF LINE, IGNORE + SOS LINEPOS + SETOM LPTBSF + POPJ P, + +LPTRCH: CAIN A,33 + JRST LPTALT + MOVE B,A + MOVEI A,"^ + PUSHJ P,LPTIM2 + MOVEI A,100(B) + JRST LPTIM2 + +LPTALT: MOVEI A,"$ + JRST LPTIM2 + +PILPT2: SOS LINEPOS + POPJ P, + +LPTEOF: SKIPE OLUSR + POPJ P, + SUB P,[1,,1] ;SYSTEM JOB HACKING SO CLOBBER TO EOF + XCTR XRW,[CLEARM (C)] + POPJ P, + +LPTCLS: SKIPLE OLUSE ;LPT CLOSE, IS THIS THE ONLY CHANNEL LPT OPEN ON + JRST LPTCL3 + SKIPN LINEPOS ;THIS IS LAST CLOSE, CHECK TO SEE IF LOSER LEFT POSITION SCREWED + SKIPE LPTPPS + PUSHJ P,LPTCL2 ;INCREMENT TO NEXT PAGE + MOVEI T,SCRTPC + IORM T,SUPCOR ;LOOK FOR TPL FILES TO PRINT + SETOM OLUSR ;DO THIS FIRST SO DONT NEED CLOCK OFF LPT HACKED BY ONE JOB AT A TIME +LPTCL3: SOS OLUSE ;DECREMENT USE COUNT + POPJ P, + +LPTCL2: MOVEI A,100. + CAMLE A,LPTCC + POPJ P, ;NO ROOM FORGET IT + MOVEI A,15 + PUSHJ P,LPTIM + MOVEI A,14 + JRST LPTIM + LPTTAB: PUSHJ P,LPTS + LDB J,[300,,LINEPOS] + JUMPE J,CPOPJ + JRST .-3 + +LPTS: MOVEI A,40 + JRST LPTIM2 + +LPTLF: AOS J,LPTPPS ;LINE FEED, INCREMENT LINE # + CAIL J,LPTLPP ;END OF PAGE? +LPTFF: SETZM LPTPPS ;END OF PAGE CLEAR OUT PAGE POS (ENTRY FOR FF) + PUSHJ P,LPC + JRST LPC1 + +LPC: MOVE J,LINEPOS ;CR AND SPACE BACK OVER TO LINPOS + MOVE B,A + MOVEI A,15 + AOSN PCL + SKIPE LINEPOS + PUSHJ P,LPT.CR + CLEARM LPTBSF ;IN CASE WAS ALREADY AT BEG OF LINE + SOJL J,LPC2 + PUSHJ P,LPTS + JRST .-2 + +LPC2: MOVE A,B + POPJ P, + +EBLK + +LPTCC: *5-5 +LINEPOS: 0 ;LINE POSITION # CHARS PRINTED THIS LINE BEFORE CURRENT +LPTPPS: 0 ;PAGE POSITION (# LINES PRINTED BEFORE CURRENT) + +PCL: 0 ;INCREMENTED BY LF OR FF, SETOMED BY OHTER CONTROL CHARS + ;PROBABLY UNNECESSARY BUT NOT WORTH FLUSHING +LPTBSF: 0 ;-1 => BACKSPACES HAVE BEEN TYPED, CR AND SPACE OVER BEFORE MAKING INK + +LPTIP: 700,,LPTBO-1 +LPTOP: 700,,LPTBO-1 + +BBLK + +LPTCN: CAIN A,<15-40>&177 + JRST LPTCR ;CRR + CAIN A,<12-40>&177 + MOVEI A,400 ;LINE FEED + CAIN A,<14-40>&177 + MOVEI A,401 ;FORM FEED + CAIE A,177 ;SKIP IF LOOKS LIKE A LEFT ARROW + JRST LPTCN1 ;GO TO PRINT + HRRZ A,LPTOP ;LOAD OUPUT POINTER + CAIE A,LPTBE-1 ;SKIP IF CURRENT PNTR = END OF BUFFER + JRST LPENT3 ;REAL LEFT ARR + MOVE A,[350700,,LPTBO] + MOVEM A,LPTOP + JRST LPENT2 +] + +IFN NLPTP,[ +NLPT1: SKIPGE C + SKIPA A,(C) + UMOVE A,(C) + MOVE B,NLPTIP + TLNN B,760000 + JRST NLPTW ;MAY NOT BE ROOM +NLPTW1: IDPB A,NLPTIP + MOVE T,NLPTIP + CAMN T,NLPTEP + SUBI T,LPTBSZ + HRRM T,NLPTIP + TLNE T,760000 + POPJ P, + SOSGE NLPTBR + JRST 4,. +NLPTGO: CONO PI,LPTOFF + CONSO NLPT,7 + CONO NLPT,100+LPTCHN ;SET OUTPUT DONE + JRST LPTONJ + +NLPTW: SKIPG NLPTBR + PUSHJ P,UFLS + JRST NLPTW1 + +EBLK + +NLPTIP: 010700,,NLPTBO-1 +NLPTBO: BLOCK LPTBSZ +NLPTEP: 010700,,NLPTBO+LPTBSZ-1 +NLPTPP: NLPTBO ;OUTPUT PNTR (PI) +NLPTBR: LPTBSZ +NLPTBP: 004400,,NLPTBO-1 ;BLKT POINTER +NLPTBC: LPTBSZ ;BLKT CNT = MIN(# WDS TILL END OF BUF,NLPTBR) +NLPTOP: NLPTBO ;VALUE OF NLPTBP BEFORE BLKT CALL +NLFREE: -1 ;-1 => LPT IN USE RECENTLY. + ;0 => NOT IN USE SINCE LAST VSCLK. + ;1 => NOT SINCE NEXT-TO-LAST VSCLK. + ;=>2 => LPT MOTOR NOW OFF. + +BBLK + +BNLPTO: MOVE B,NLPTBP + MOVEM B,NLPTOP + PUSH P,[BNLPT1] + MOVE E,[444400,,1] + JSP B,BLKT + SETZ NLPTBP + NLPTBC + BNLPTG + BNLPT1 + @J + SKIPG NLPTBR + +BNLPT1: MOVE T,NLPTBP + MOVE W,T + CAMN T,[004400,,NLPTBO+LPTBSZ-1] + MOVE T,[004400,,NLPTBO-1] + MOVEM T,NLPTBP + EXCH T,NLPTOP + SUB T,W ;- # WORDS WRITTEN + ADDB T,NLPTBR ;DECREASE ROOM + JUMPL T,[JRST 4,.] + JRST NLPTGO + +BNLPTG: MOVE TT,NLPTBP + MOVE J,NLPTBR + MOVEI T,NLPTBO+LPTBSZ-1 + SUBI T,(TT) ;# WORDS UNTIL END OF BUFFER + CAMLE J,T + MOVE J,T + MOVEM J,NLPTBC + JRST POPJ1 + +NLPTCL: SKIPLE NLPTBR ;ENOUGH ROOM? + PUSHJ P,NLPTO3 + SETOM NLFREE + SETOM NLUSR + SETOM NLUSE + POPJ P, + +NLPDCL: MOVSI H,760000 + SKIPA A,[177] +NLPDC1: PUSHJ P,NLPTW1 + TDNE H,NLPTIP + JRST NLPDC1 + HRRZ A,NLPTIP + CAIN A,NLPTBO+LPTBSZ-1 + MOVEI A,NLPTBO-1 + HRLI A,004400 + MOVEM A,NLPTBP + MOVNI A,(A) + ADDI A,NLPTBO+LPTBSZ-1 + MOVE B,NLPTBR + CAMLE A,B + MOVE A,B + MOVEM A,NLPTBC + JRST NLPTCL +] + +IFN NTYP\OLPTP\NLPTP\PLTP\340P\PDP6P\STKP\PTRP,[ + +EBLK +LPTA: 0 +LPTB: 0 +LPTACS: BLOCK 15 + +LPTBRK: 0 +BBLK + MOVEM A,LPTA +IFN NTYP,[ ;A KLUDGE FOR THE PDP 11 ON DM + CONI NTY,A + TRNE A,7 ;NO PIA + TRNN A,200000 ;NO FLAG + CAIA + JRST NTYBRK ;AHH, FLAG AND PIA +] + +IFN OLPTP,[ + CONSZ OLPT,7 + CONSZ OLPT,10 + JRST .+2 + JRST LPENT1 ;LINE PRINTER +] +IFN NLPTP,[ + CONSZ NLPT,7 + CONSO NLPT,100 ;DONE + JRST .+2 + JRST NLPENT ;NEW LINE PRINTER +] +IFN 340P,[ + CONI DIS,A + TRNN A,77 + JRST LPTBR2 + CONSZ DIS,7400 + JUMPL A,SRECYC ;SPECIAL DISPLAY CHNL +] +LPTBR2: MOVEM B,LPTB +IFN PLTP,[ + CONSZ PLT,SDS+PDS + JRST PLTBRK ;PLOTTER +] +IFN PTRP,[ + CONSZ PTR,7 + CONSO PTR,10 + JRST .+2 + JRST PTRBRK + CONSZ PTP,10 + JRST PBRK1 ;PAPER TAPE PUNCH +] +IFN PDP6P,[ + CONSO DSDEV,7 + JRST .+3 + CONSZ DSDEV,10 + JRST DSDBRK ;INTERRUPT FROM OTHER PROCESSOR +] +IFN STKP,[ + CONSZ STK,7 + CONSO STK,10 + JRST .+2 + JRST STKINT ;STANFORD KEYBOARD +] +LPBKRT: MOVE A,LPTA + JRST 12,@LPTBRK + +LPTRT1: MOVS A,[C,,LPTACS] + BLT A,17 +LPTRT3: MOVE B,LPTB + MOVE A,LPTA + JRST 12,@LPTBRK +] ;END IFN OLPTP\ ETC. +.ELSE [ +EBLK +LPTBRK: 0 +BBLK + JRST 4,. +] + +IFN OLPTP,[ +LPENT3: MOVEI A,177 + JRST LPTCN1 + +LPTCR: CONO OLPT,10+LPTCHN ;PRINT LINE + AOS LPTCC + JRST LPBKRT + +LPENT1: MOVEI A,*5-5 + CAMG A,LPTCC + JRST LPTSTP +LPENT2: ILDB A,LPTOP + TRNE A,100 + JRST LPTCN +LPTCN1: DATAO OLPT,A ;OUTPUT CHARACTER + AOS A,LPTCC + CONSZ OLPT,10 + JRST LPBKRT + CAIGE A,*5-5 + JRST LPENT2 +LPTSTP: CONO OLPT,0 ;CLEAR PIA + MOVEI A,SCRTPC + SKIPGE LPTUSR + IORM A,SUPCOR ;LPT NOW IDLE + JRST LPBKRT + +EBLK + +LPTBO: BLOCK LPTBSZ-1 + -1 +LPTBE: + +BBLK + +STALPT: MOVE E,LINEPOS + DPB E,[130700,,D] + DPB A,[60300,,D] ;MODE + MOVE E,LPTCC + CAIG E,150. + TRO D,1_9. + CAIL E,30000 + TRO D,1_<9.+1> + POPJ P, + +LPTRS: CONO PI,LPTOFF + MOVEI A,5*-5 + MOVEM A,LPTCC + MOVE A,[700,,LPTBO-1] + MOVEM A,LPTIP + MOVEM A,LPTOP + SETZM LINEPOS + CONO PI,LPTON + JRST LPTRS2 + +] + +IFN NLPTP,[ +NLPENT: MOVE A,NLPTBR + CAIN A,LPTBSZ + JRST NLPTST + CAIL A,LPTBSZ + JRST 4,. + DATAO NLPT,@NLPTPP + AOS A,NLPTPP + CAIN A,NLPTBO+LPTBSZ + MOVEI A,NLPTBO + MOVEM A,NLPTPP + AOS NLPTBR + JRST LPBKRT + +NLPTST: CONO NLPT,200 ;CLEAR DONE AND PIA + MOVEI A,SCRTPC + SKIPGE NLUSR + IORM A,SUPCOR ;LPT NOW IDLE + JRST LPBKRT + +NLPTRS: CONO PI,LPTOFF + MOVE A,[010700,,NLPTBO-1] + MOVEM A,NLPTIP + MOVEI A,NLPTBO + MOVEM A,NLPTPP + MOVE A,[004400,,NLPTBO-1] + MOVEM A,NLPTBP + MOVEM A,NLPTOP + MOVEI A,LPTBSZ + MOVEM A,NLPTBR + MOVEM A,NLPTBC + CONO PI,LPTON + JRST NLPTO3 +] + +SUBTTL STANFORD KEYBOARD + +IFN STKP,{ +;3.4 => DON'T HANG ON IOT IF NO CHAR (RETURN -1 INSTEAD) +;3.5 = 1 => DON'T DO CHAR CONVERSION +; = 0 => CONVERT ACCORDING TO OTHER BITS +;3.6 = 1 => ITS MODE (CTRL DOES CTRL AND META IS 8TH BIT) +; = 0 => STANFORD MODE (400 = META, 200 = CTRL, AND ALL THE +; CHARS FROM 1-177 CAN BE GENERATED WITH TOP AND SHIFT.) +;3.7 = 1 => IF 3.5 = 0, 3.6 = 1, THEN DON'T INPUT META BIT + +STKO: TLNE C,3 ;BLOCK OR OUTPUT + JRST OPNL12 ;MODE NOT AVAILABLE + CONO PI,CLKOFF + SKIPL STKUSR + JRST OPNL10 ;DEVICE NOT AVAILABLE + MOVEM U,STKUSR + AOSE STKUSE + JRST 4,. ;CAN ONLY BE OPEN ONCE + CONO PI,CLKON + HRRZ A,UUAC(U) + MOVE A,CHNBIT(A) + ROT D,-2 + DPB D,[220400,,A] + MOVEM A,STKMSK + MOVE A,STKBP + MOVEM A,STKIP + MOVEM A,STKOP + SETZM STKBC + DATAI STK,A ;CLEAR DONE + CONO STK,LPTCHN + MOVEI A,STKDP + MOVEM A,(R) + JRST POPJ1 + +STKCLS: CONO STK,0 ;CLEAR PIA + SOSL STKUSE + JRST 4,. ;CAN ONLY BE OPEN ONCE + SETOM STKUSR + POPJ P, + +STKRS: CONO PI,LPTOFF + MOVE A,STKBP + MOVEM A,STKIP + MOVEM A,STKOP + SETZM STKBC + JRST LPTONJ + +STKI: MOVE TT,STKMSK + TLNE TT,1 + JRST STKI1 + PCLT + SKIPG STKBC + PUSHJ P,UFLS +STKI2: ILDB A,STKOP + SOS STKBC + TLNN TT,2 + JRST STKCV ;DO CONVERSION +STKI3: MOVE W,A + MOVE A,STKOP + CAMN A,STKEP + SUBI A,STKBL + HRRM A,STKOP + POPJ P, + +STKI1: SKIPLE STKBC + JRST STKI2 + JRST STTYI3 + +STKINT: MOVEM B,LPTB + DATAI STK,B + ANDI B,1777 ;CURRENTLY 10 BITS + MOVE A,STKBC + CAIL A,STKBS + JRST LPTRT3 ;NO ROOM. JUST IGNORE CHAR + IDPB B,STKIP + AOS STKBC + MOVE A,STKIP + CAMN A,STKEP + SUBI A,STKBL + HRRM A,STKIP + MOVE A,STKUSR + HRRZ B,STKMSK + AND B,MSKST2(A) + IORM B,IFPIR(A) + JRST LPTRT3 + +EBLK +STKBL==40 +STKBS==STKBL*3 +STKIP: 001400,,STKIB-1 +STKIB: BLOCK STKBL +STKEP: 001400,,STKIB+STKBL-1 +STKBP: 001400,,STKIB-1 +STKOP: 001400,,STKIB-1 +STKBC: 0 +STKMSK: 0 ;BIT FOR CHANNEL STK OPEN ON + ;3.1 => DON'T HANG ON IOTS MODE + ;3.2 => DON'T CONVERT CHARS + ;3.3 => ITS MODE + ;3.4 => DON'T INPUT META IN ITS MODE +BBLK + +STKCV: LDB B,[000600,,A] ;LOW 6 BITS + CAIN B,33 + JRST STKCV1 ;33 + CAIL B,35 + CAILE B,47 + JRST .+2 + JRST STKCV2 ;35-47 + CAIL B,74 + CAILE B,77 + JRST .+2 + JRST STKCV3 ;74-77 + TRNE A,400 + JRST STKCVT ;TOP IS ON + CAIG B,32 + JRST STKCV4 ;0-32 + CAIN B,34 ;SKIP IF 50-73 + JRST STKCVB ;34 +STKCVX: TLNN TT,4 ;SKIP ON ITS MODE + JRST STKCVY ;STANFORD MODE + ANDI A,1000 ;META BIT + LSH A,-2 + TLNN TT,10 ;SKIP ON DON'T INPUT META BIT + IORI B,(A) + MOVE A,B + JRST STKI3 + +STKCVY: LDB D,[110100,,A] ;META BIT + LSH D,8 ;IN 400 POSITION + ANDI A,200 ;CTRL BIT + IORI A,(D) + IORI A,(B) + JRST STKI3 + +STKCV1: MOVEI B,15 + JRST STKCVX + +STKCV2: MOVEI Q,-35(B) ;35-47 (-35) + IDIVI Q,5 + LDB B,STKBPT(J) + JRST STKCVX + +STKCV3: CAIE B,74 + JRST STKCV5 ;75-77 + MOVEI B,177 + JRST STKCVX + +STKCV5: MOVEI B,33 + JRST STKCVX + +STKCVT: CAIG B,32 ;TOP IS ON + JRST STKCT1 ;0-32 + CAIN B,34 + JRST STKCT2 ;34 + MOVEI Q,-50(B) ;50-73 (-50) + MOVE D,B + IDIVI Q,5 + LDB B,STKBP1(J) + TRNE A,200 ;SKIP IF CTRL IS OFF + TLNN TT,4 ;SKIP IF ITS MODE + JRST STKCVX + CAIL D,52 + CAILE D,72 + TRZ B,100 ;50,51,73 + JRST STKCVX + +STKCT1: MOVE Q,B ;0-32 TOP ON + MOVE D,B + IDIVI Q,5 + LDB B,STKBP2(J) + TRNE A,200 ;SKIP IF CTRL IS OFF + TLNN TT,4 ;SKIP IF ITS MODE + JRST STKCVX + CAIN D,12 + TRZ B,100 + JRST STKCVX + +STKCT2: MOVEI B,16 + JRST STKCVX + +STKCV4: TLNN TT,4 ;SKIP IF ITS MODE + JRST STKCV6 + TRNE A,200 + JRST STKCVX ;ITS, CTRL +STKCV6: TRO B,100 + TRNN A,100 + TRO B,40 ;SHIFT WAS OFF + JRST STKCVX + +STKCVB: MOVEI B,134 + TRNE A,200 ;SKIP IF CTRL IS OFF + TLNN TT,4 ;SKIP IF ITS MODE + JRST STKCVX + TRZ B,100 + JRST STKCVX + +DEFINE STKM A,B,C,D,E + A_29.+B_22.+C_15.+D_8+E_1 +TERMIN + +DEFINE STKM1 TBL + 350700,,TBL(Q) + 260700,,TBL(Q) + 170700,,TBL(Q) + 100700,,TBL(Q) + 010700,,TBL(Q) +TERMIN + +STKBPT: STKM1 STKTBL +STKTBL: STKM 12,0,0,40,0 + STKM 33,0,0,11,14 + STKM 13,0,0,0,0 + +STKBP1: STKM1 STKTB1 +STKTB1: STKM 133,135,26,174,41 + STKM 5,77,17,60,36 + STKM 22,23,20,21,44 + STKM 45,32,30,1,136 + +STKBP2: STKM1 STKTB2 +STKTB2: STKM 0,34,7,6,74 + STKM 100,76,33,75,47 + STKM 137,31,27,25,24 + STKM 173,176,4,43,35 + STKM 46,140,10,37,3 + STKM 42,2,0,0,0 +};IFN STKP + +SUBTTL INTERFACE (?) TO DM PDP11 ON NTY (REALLY WANT A CAIOS) +IFN NTYP,[ +IFN TK10P, .ERR YOU REALLY WILL LOSE WITH BOTH TTY AND 11 ON NTY +NTYOPN: PUSHJ P,NTYOP1 ;SET UP OPEN + POPJ P, ;OPEN LOST? + SKIPE NTYUSE ;IF THIS IS FIRST OPEN, DO SOME INITIALIZING + JRST POPJ1 + CONO NTY,0 ;STOP INTS + SETOM NTYOAC + MOVE A,[NTYIOI,,NTYIOR] + BLT A,NTYORM ;INITIALIZE ALL THE POINTERS AND COUNTERS + CONO NTY,620000+NTYCHN + JRST POPJ1 + +NTYOP1: ROT D,1 ;MODE BACK, TO GET INPUT & OUTPUT + JSP Q,STDOPN + 3,,NTYUSR + NTYIT,,NTYOT + 0,,0 ;NTYBIT,,NTYBOT + +NTYRS==CPOPJ + +NTYCLS: SOSL NTYUSE ;-1 MEANS FREE (USE STDCLS?) + POPJ P, + SETOM NTYUSE + SETOM NTYUSR + POPJ P, + +;MAIN PROGRAM ROUTINES FOR IOT/SIOT ... + +NTYBI==IOCR10 +NTYBO==IOCR10 + +NTYTO:: +NTYOPT: PCLT ;PUT OUTPUT INTO BUFFER + SKIPG C + SKIPA A,(C) + UMOVE A,(C) ;FETCH THE USERS BYTE + SKIPG NTYORM ;WAIT FOR ROOM + PUSHJ P,UFLS + IDPB A,NTYOIP + SOSGE A,NTYORM + JRST 4,. ;WENT BELOW ZRO? + AOSN NTYOAC + CONO NTY,10+NTYCHN ;NOT ACTIVE, START PI LEVEL + AOSGE NTYOIR + POPJ P, + MOVE A,[NTYOII,,NTYOIR] ;RING AROUND THE ROSY + BLT A,NTYOIP + POPJ P, +NTYTI:: +NTYIGT: MOVEI T,NTYIBS*4 + PCLT + CAMG T,NTYIRM + PUSHJ P,UFLS ;WAIT UNTIL A BYTE COMES IN + ILDB W,NTYIOP + AOS NTYIRM ;NOW MORE ROOM + AOSGE NTYIOR ;RING? + POPJ P, + MOVE B,[NTYIOI,,NTYIOR] ;REDO POINTERS + BLT B,NTYIOP + POPJ P, + +;INTERRUPT ROUTINES + +NTYBRK: TRC A,2000 ;DEVICE # + TRNE A,7000 + JRST NTYSEL ;STOPPED ON OTHER DEVICE + TRNE A,40 + JRST NTYIPT ;INPUT + TRNE A,20 + JRST NTYOGT ;OUTPUT +NTYRET: CONO NTY,620000+NTYCHN ;RESTART + JRST LPBKRT + +NTYSEL: TRC A,2000 ;HAVE TO KNOCK DOWN SOME OTHER FLAG + ANDI A,7000 + LSH A,3 + CONO NTY,400000+NTYCHN(A) + CONSZ NTY,40 + DATAI NTY,A ;CLEAR INPUT + CONSZ NTY,20 + CONO NTY,20+NTYCHN ;CLEAR OUTPUT + AOS NTYERR + JRST NTYRET + +NTYOGT: MOVEI A,NTYOBS*4 + CAMG A,NTYORM + JRST [SETOM NTYOAC + CONO NTY,20+NTYCHN + JRST NTYRET] + ILDB A,NTYOOP + AOS NTYORM + DATAO NTY,A + AOSGE NTYOOR + JRST NTYRET + MOVE A,[NTYOOI,,NTYOOR] + BLT A,NTYOOP ;ZAP THE POINTER AND COUNT (RING BUF) + JRST NTYRET + +NTYIPT: SOSG NTYIRM + CONO NTY,100+NTYCHN ;IF HDWE NOT IN, BUFFER WILL BE CLOBBERED + ;BUT ALSO, THE COUNT WILL BE NEG!!! + DATAI NTY,A + IDPB A,NTYIIP + AOSGE NTYIIR + JRST NTYRET + MOVE A,[NTYIII,,NTYIIR] + BLT A,NTYIIP ;RING THE BUFFER POINTERS + JRST NTYRET + +;DATA AREAS FOR THE NTY INTERFACE TO DM PDP 11 + +NTYIBS==1000 +NTYOBS==100 + +NTYIOI: -NTYIBS*4 ;STUFF TO INITIALIZE INPUT SIDE + 041000,,NTYIBF-1 +NTYIII: -NTYIBS*4 + 041000,,NTYIBF-1 + NTYIBS*4 + +NTYOOI: -NTYOBS*4 ;INITIALIZES OUTPUT SIDE + 041000,,NTYOBF-1 +NTYOII: -NTYOBS*4 + 041000,,NTYOBF-1 + NTYOBS*4 + +EBLK + +NTYIOR: -NTYIBS*4 ;RING COUNTER, INPUT BUFFER, OUTPUT PART +NTYIOP: 041000,,NTYIBF-1 ;BYTE POINTER, " " +NTYIIR: -NTYIBS*4 ;RING CTR, INPUT BUFFER, INPUT PART +NTYIIP: 041000,,NTYIBF-1 ;BYTE POINTER, " " +NTYIRM: NTYIBS*4 ;ROOM EMPTY IN IN BUFFER + +NTYOOR: -NTYOBS*4 ;RING CTR, OUTPUT BUFF, OUT PART +NTYOOP: 041000,,NTYOBF-1 ; BYT PTR, " " +NTYOIR: -NTYOBS*4 ;RING CTR, OUT BUFF, IN PART +NTYOIP: 041000,,NTYOBF-1 ;BYT PTR, " " +NTYORM: NTYOBS*4 ;ROOM IN THE OUTPUT BUFFER + +NTYIBF: BLOCK NTYIBS ;INPUT BUFFER +NTYOBF: BLOCK NTYOBS ;OUTPUT BUFFER + +NTYOAC: -1 ;FLAG, OUTPUT ACTIVE UNLESS -1 +NTYUSR: -1 +NTYUSE: -1 + +NTYERR: 0 + + BBLK +];NTYP + +SUBTTL PDP-10 TO PDP-11 INTERFACE AND XGP + +IFN TEN11P,[ +EBLK +T11MP: BLOCK 256. ;CONTENTS OF TEN11 MAP, -1 => CONFLICT PAGE +BBLK + ;ELSE 0 => AVAIL + ;4.9=1 => CONTENTS OF MAP WD EXCEPT 4.7-4.3 => USE COUNT +IFN XGP,XGPTP==376 ;PAGE NUMBER IN 10-11 RESERVED FOR CLK LEVEL XGP HACKS + +;PLACE WD IN A IN AVAIL 10-11 MAP ENTRY (RETURN IN RH B) +T11AD: SKIPE TEN11F + POPJ P, + MOVE C,A + JSP Q,T11FND ;SKIP UNLESS NO MAP ENTRIES AVAIL + JRST T11A1 ;WD ALREADY IN PAGE + MOVEI C,0 ;FIND FREE PAGE + JSP Q,T11FND + JRST T11A2 + POPJ P, ;NO FREE PGS AVAIL + +T11A1: LDB E,[350500,,T11MP(B)] + CAIN E,37 + JRST T11FN2 ;USAGE COUNT MAX FOR THAT ENTRY + AOS E + DPB E,[350500,,T11MP(B)] + JRST POPJ1 + + +T11A2: MOVEM A,T11MP(B) + MOVEM A,400000+T11CP*2000(B) ;STORE IN HARDWARE + JRST POPJ1 + +T11FND: MOVSI B,-256. +T11FN1: +IFN XGP,[ CAMN B,[-256.+XGPTP,,XGPTP] ;DON'T ALLOCATE SPECIAL XGP ENTRY TO OTHER USERS + JRST T11FN2 +] + MOVE E,T11MP(B) + TLZ E,174000 ;USE COUNT BITS + CAMN E,C + JRST (Q) ;FOUND IT +T11FN2: AOBJN B,T11FN1 + JRST 1(Q) ;CANT FIND IT + + +;DELETE REF TO T11 PAGE IN B +T11DL: SKIPE TEN11F + POPJ P, + MOVE E,T11MP(B) + AOJE E,CPOPJ ;REALLY CONFLICT PAGE + LDB E,[350500,,T11MP(B)] + SOJL E,T11DL1 ;DELETING LAST REF TO PAGE? + DPB E,[350500,,T11MP(B)] + POPJ P, + +T11DL1: CLEARM T11MP(B) + CLEARM 400000+T11CP*2000(B) + POPJ P, +] + +IFN TEN11P,[ + +;.CALL ADR +; LOSE +; WIN +;ADR/ SETZ +; SIXBIT /T11MP/ +; ARG 1 VIRT PAGE # +; ARG 2 DESIRED T11 MAP WORD + +NT11M: TDNE A,[-400] ;TEMP? TEN11 CALL A HAS USER PG + JRST OPNL33 ;INVALID ARG - BAD USER PAGE #. + SKIPE TEN11F + JRST OPNL7 ;DEVICE NOT READY. + PUSHJ P,UPLC + MOVE W,A + JUMPGE B,OPNL33 + TLZ B,174000 ;DONT ALLOW ANYTHING IN USAGE COUNT BITS + MOVE D,B + LDB E,Q + JUMPE E,NT11M1 ;PAGE MUST BE FREE OR ABS, OTHERWISE ERROR + CAIE E,-1 + JRST OPNL13 ;FILE ALREADY EXISTS + LDB B,T + ANDI B,PMRCM + LDB E,[.BP B] ;GET MOBY # + ANDI B,377 + CAIN E,T11CPA_-18. + PUSHJ P,T11DL + MOVEI B,0 + DPB B,Q + DPB B,T +NT11M1: MOVE R,Q + MOVE A,D + PUSHJ P,T11AD + JRST OPNL37 ;NO CORE AVAILABLE. + ADDI B,200000+<_8> ;ADDRESS CORRECT MOBY + TLNE A,200000 + TRO B,400000 ;WRITE PERMISSION + DPB B,T + MOVEI C,-1 + DPB C,R + LSH W,10. + ADDI W,2000 + CAMLE W,HUSRAD(U) + MOVEM W,HUSRAD(U) + JRST POPJ1 +] +.ELSE NT11M: JRST OPNL1 ;NO SUCH DEVICE. + IFN XGP,[ +;CLOCK LEVEL XGP CODE FOR FILLING IMAGE MODE BUFFERS +;ASSUMES XGP11P IS POINTER TO FIRST 11 RING NODE +;AND THAT THE 11 BUFFER RING STRUCTURE IS: + +; POINTER TO NEXT NODE OF BUFFER +; USE WORD (0=> EMPTY) +; POINTER TO BUFFER (ASSUMED TO BE 1K 10 STYLE, 2K 11 STYLE) + +; +;THE NODES AND THE BUFFERS MUST BEGIN ON EVEN PDP-11 WORDS +;I.E. 11 ADDRESSES ENDING WITH TWO ZEROES. + +;THIS CODE USES A SPECIAL 10-11 INTERFACE ENTRY +;NAMELY, XGPTP, AND THREE EXEC PAGES, XGPC WHICH POINTS TO +;THE LOW 2K OF PDP-11 CORE, USED FOR THE RING NODE POINTERS +;XGPUB WHICH POINTS TO THE CURRENTLY HACKED USER PAGE +;AND XGPB WHICH POINTS PERMANENTLY TO THE 10-11 PAGE CORRESPONDING +;TO XGPTP + +XGP11==1 ;PDP-11 RUNNING XGP +XGPCA==XGPC*2000+400000 ;EXEC ADR OF LOW PDP-11 CORE +XGPBA==XGPB*2000+400000 ;EXEC ADR OF BUFFER IN PDP-11 +XGPUBA==XGPUB*2000+400000 ;EXEC ADR OF CURRENT PAGE IN USER'S MAP +XGNTPG==117. ;MAX # TIED DOWN PAGES (WOULD YOU BELIEVE...) +X11BFP==102 ;LOC OF XGP BUFF HEAD IN 11 (PDP11 ADR 410) + +XGPCLK: PUSH P,A + PUSH P,B + MOVE A,XGPTM1 ;TIME FIRST PAGE LOCKED IN CORE + ADDI A,30.*60. ;1 MINUTE + CAMGE A,TIME ;WIN? + JSP Q,XGPFLS ;LOSE... + SKIPL XGPINI ;DON'T HACK UNTIL MAIN PGM HAS PAGES TIED DOWN + JRST POPBAJ + SPM XGPSPM ;SAVE OLD MAP +XGPC1: MOVE A,XGP11P ;GET POINTER TO FIRST PDP-11 BUFFER + MOVE A,XGPCA(A) ;GET CONTENTS FROM PDP-11 + LDB B,[242000,,A] ;GET NEXT RING POINTER + LDB A,[042000,,A] ;GET USE WORD + JUMPN A,POPBAJ ;BUFFERS FULL + TRNE B,3 + JSP Q,XGPFLS ;NEW BUF POINTER NOT ON EVEN WD BNDY + LSH B,-2 ;CONVERT TO 10 ADDRESS + SKIPE B + CAIL B,2000 ;IS IT WITHIN CONTROL PAGE? + JSP Q,XGPFLS ;FLUSH + EXCH B,XGP11P ;SETUP NEXT POINTER, GET BACK OLD ONE + MOVEM B,XGPOB ;SAVE OLD POINTER FOR HACKING BUFF FULL + MOVE B,XGPCA+1(B) ;GET POINTER TO 11 BUFFER + LDB B,[242000,,B] + TRNE B,3 + JSP Q,XGPFLS + LSH B,8 ;SETUP 10-11 ENTRY + IOR B,[600000+,,1777] ;R/W, PROT INFINITE + MOVEM B,400000+2000*T11CP+XGPTP ;GRONK INTO 10-11 INTERFACE + MOVEM B,T11MP+XGPTP ;FOR DEBUGGING ONLY + ILDB A,XGP10P ;GET POINTER TO NEXT 10 PAGE + CAIL A,TSYSM ;LOSE + JRST 4,. ;MAIN PGM HAS POINTER TO NXM + JUMPE A,XGPFIN ;HERE WE ARE DONE, I HOPE. DEUS GRATIUS + MOVE B,A ;SAVE MMSWP ENTRY # TO CLEAR OUT TIE DOWN + IORI A,600000 ;R/W + DPB A,[.XGPUB+EXEUMP] ;GRONK EXEC MAP + LPMR XGPSPM ;RESET ASSOC REGS + MOVE A,[XGPUBA,,XGPBA] + BLT A,XGPBA+1777 ;DO THE STUFF! + MOVSI A,-1 + ADDM A,MMSWP(B) ;CLEAR TIE DOWN, PHEW! + SKIPGE MMSWP(B) ;STOP BUGGY LOSSAGE + JRST 4,. + PUSHJ P,XGPBIT ;GET TABLE INFO + TDNN A,XGPMTB(B) + JRST 4,. ;UNTIED PAGE NOT TIED DOWN + ANDCAM A,XGPMTB(B) ;CLEAR THE BIT + MOVEI A,0 + DPB A,[.XGPUB+EXEUMP] ;CLEAR EXEC PAGE MAP + MOVE A,XGPOB ;GET OLD RING PTR + MOVEI B,30 ;CHANGE RH ONLY TO A 1 + MOVEM B,XGPCA(A) ;SET BUFFER FULL + JRST XGPC1 ;LOOP TO GET A NEW BUFFER + + + +XGPFIN: SETZM XGPINI + JSP Q,XGPFLS + +;MMSWP ENTRY IN B, +;RETURNS BIT IN A +;WD OF TABLE IN B +XGPBIT: MOVE A,B + IDIVI A,36. + MOVNS B + PUSH P,A + MOVSI A,400000 + LSH A,(B) + JRST POPBJ + +;CALLED FROM CORE ALLOCATOR WHEN FLUSHING PAGES +;OF A JOB WHICH HAVE LH OF MMSWP NON ZERO. + +XGPCFL: CAME U,XGPUSR ;ARE WE CONCERNED? + POPJ P, ;NOPE + PUSH P,A + PUSH P,B + MOVE B,TT ;B GETS MMSWP INDEX + PUSHJ P,XGPBIT ;GET INDEXES INTO XGPMTB + TRNN A,XGPMTB(B) ;IS THIS A PAGE BEING HACKED BY XGP? + JRST POPBAJ ;NOPE + ;FALLS THRU + +;XGPFLS IS CALLED AT THE CLOCK LEVEL IF ANYTHING GOES WRONG WITH ANYTING +;AND AT THE END OF THE RUN. +;IT FREES THE WORLD, AND FLUSHES THE XGP USER + +XGPFLS: MOVEM Q,XFLSPC + SETOM XGPUSR ;FLUSHES XGP, ALSO PREVENTS TIMING ERRORS IF XGPFLS CALLED + ;AT CLOCK LEVEL, SINCE IT WON'T BE ANY MORE + PUSH P,C + PUSH P,D + CLEARB A,B + MOVSI C,400000 + MOVSI D,-1 +XGPFL1: TDNN C,XGPMTB(B) + JRST XGPFL3 ;THIS PAGE NOT HACKED + ADDM D,MMSWP(A) ;UNTIE THIS PAGE + SKIPGE MMSWP(A) + JRST 4,. + ANDCAM C,XGPMTB(B) ;AND FLUSH THIS BIT +XGPFL3: ROT C,-1 ;MOVE ON TO NEXT BIT + SKIPGE C ;BEG OF NEW WORD? + AOS B ;YES, AOS XGPMTB INDEX + CAIGE A,TSYSM-1 ;FINISHED WITH ALL OF MMSWP ENTRIES? +XGPFL2: AOJA A,XGPFL1 ;NOPE, LOOP BACK FOR MORE FUN + POP P,D + POP P,C + JRST POPBAJ + + +;MAIN PROGRAM BUFFER TIE DOWN ROUTINES +;.CALL FOO +;FOO: SETZ +; SIXBIT /XGPIM/ +; SETZ POINTER TO [# OF PAGES,,FIRST PAGE] + +NXGPIM: XCTR XRW,[MOVES B,(A)] ;GET POINTER, AND CHECK FOR WRITE + JUMPL B,XCONT ;CONTINUING A PREVIOUS CALL + SKIPN TEN11F + SKIPL XGPUSR + POPJ P, ;LOSE + MOVEI C,X11BFP ;BUFF HEAD IN 11 DEFINED AS 1000 + MOVEM C,XGP11P + MOVE C,XGPCA(C) ;GET BUFF POINTER FROM 11 + JUMPE C,CPOPJ ;LOSE, THE 10-11 IS LOSING OR PGM LOSING + MOVE C,TIME + MOVEM C,XGPTM1 ;SET UP TIMEOUT ON PAGE LOCK + SETZM XGPINI ;SAY NOT ACTIVE + MOVEM U,XGPUSR ;AND BEING LOADED + SETZM XGPTAB + MOVE C,[XGPTAB,,XGPTAB+1] + BLT C,XGPTAB+LXTAB-1 ;CLEAR OUT OLD PAGE BUF TABLE + MOVE C,[441400,,XGPTAB] + MOVEM C,XGP10P ;SETUP BYTE POINTER TO PAGE LIST +XTIE: TLO B,400000 + UMOVEM B,(A) + HRRZ C,B + HRRZ E,B ;C,E GET PAGE # NEXT TO BE TIED DOWN + HLRZ D,B ;D GETS COUNT OF PAGES LEFT + LSH C,10. + UMOVE B,20(C) ;BRING IN THAT LOSING PAGE + PUSHJ P,SWTL + CIRPSW + TRZ D,400000 + CAIL D,XGNTPG ;MAX # PAGES TIED DOWN + JRST XLOSE + EXCH E,A + CAIL A,400 + JRST XLOSE ;PAGE OUT OF REASONABLE RANGE + PUSH P,A + PUSHJ P,UPLC ;FIND OUT PAGE MAP ENTRY + LDB B,Q + CAIN B,-1 + JRST XLOSE1 + LDB B,T + ANDI B,PMRCM + CAIL B,TSYSM + JRST 4,. + PUSHJ P,XGPBIT + CONO PI,CLKOFF ;CLOCK OFF TO PREVENT PAGES 1/2 TIED DOWN + TDNN A,XGPMTB(B) ;WE HAVE HIT THIS PAGE ALREADY + CAME U,XGPUSR ;TIMEOUT OR OTHER GROSS LOSSAGE + JRST XLOSE1 ;DON'T TIE THIS ONE DOWN, AND FLUSH ALL THE REST + IORM A,XGPMTB(B) ;SET BIT IN XGP MEM TABLE + LDB B,T + ANDI B,PMRCM + IDPB B,XGP10P ;PUT IN BUFFER LIST + MOVSI A,1 + ADDM A,MMSWP(B) ;TIE IT DOWN GOOD (FOR ALL YOU BONDAGE FREAKS) + CONO PI,CLKON + PUSHJ P,LSWPOP ;CIRPSW + POP P,B + SOJLE D,XBFIN ;WE ARE DONE TYING START XGPING + AOS B + HRL B,D + MOVE A,E ;NOW, LOOP FOR MORE CRUFTIES, OR +XCONT: CAME U,XGPUSR ;REENTER HERE IF THE MAD SWAPPER HAD US SWAPPED OUT + POPJ P, + JRST XTIE + +XLOSE1: CONO PI,CLKON ;CLEANUP AFTER LOSSAGE + SUB P,[1,,1] +XLOSE: PUSHJ P,LSWPOP ;CIRPSW + PUSH P,A + PUSH P,B + JSP Q,XGPFLS ;FLUSH THE LAST VESTIGE OF THIS ABORTIVE ATTEMPT TO CAUSE WINNAGE + +XBFIN: SETOM XGPINI ;THE WORST IS OVER, SIT BACK AND RELAX + MOVE A,[441400,,XGPTAB] + MOVEM A,XGP10P + JRST POPJ1 ;TELL HIM HE MAY EVEN WIN SOMEDAY + +XPLO: CONO PI,CLKOFF + PUSHJ P,XPLST + JRST XPLO1 + CONO PI,CLKOFF + PUSHJ P,XPLWT + PUSHJ P,UFLS + MOVE T,XPLU + SKIPE IOCHNM(T) + JRST XPLO2 + MOVE T,SV40(T) + CAME T,[.SLEEP 17,] +XPLO2: JRST OPNL10 + CONO PI,CLKON + MOVNI A,1 + MOVSI B,(SIXBIT /XPL/) + PUSHJ P,CLIO + POPJ P, + MOVE A,UTMPTR(U) + MOVE B,XPLU + MOVEM A,UTMPTR(B) + JRST POPJ1 + +XPLO1: PUSHJ P,UDELAY + JRST XPLO + +XPLST: SKIPL T,XPLU + PUSHJ P,XPLIN + JRST POPJ1 + HRROI A,XPL + CONO PI,UTCOFF + PUSHJ P,NUJBST + JRST UTCONJ + JRST UTCOJ1 + +XPLWT: SKIPGE T,XPLU + POPJ P, + PUSHJ P,XPLIN + SKIPGE IOCHNM(T) + JRST POPJ1 + MOVS Q,SV40(T) + CAIN Q,(.SLEEP 17,) + AOS (P) + POPJ P, + +XPLIN: PUSH P,U + CAML T,USRHI + JRST XPLIN1 + HLRE U,UNAME(T) + AOJN U,XPLIN1 + MOVSI U,(SIXBIT /XPL/) + CAME U,JNAME(T) +XPLIN1: AOS -1(P) + POP P,U + POPJ P, + +;VARIABLES AREA +EBLK + +XGPTAB: BLOCK XGNTPG/3+1 ;PAGE #'S OF XGP BUFS IN 12 BIT BYTES +LXTAB==.-XGPTAB +XGP11P: 0 ;POINTER TO 11 RING STRUCTURE (10 STYLE ADR INTO XGPC) +XGPOB: 0 ;TEMP FOR OLD XGP11P +XGP10P: 0 ;BYTE POINTER INTO XGPTAB FOR GETTING 10 BUFFERS +XGPMTB: BLOCK TSYSM/36.+1 ;BIT TABLE FOR KEEPING + ;TRACK OF AOSES OF MMSWP +XGPUSR: -1 ;XGP USER INDEX, -1 IF NONE +XGPINI: 0 ;IF -1, SIGNAL TO CLK CODE THAT ALL BUFFERS ARE NOW TIED DOWN. +XFLSPC: 0 ;PC OF LAST CALL TO XGPFLS +XGPSPM: BLOCK 8 ;STORAGE FOR PAGE MAP ENTRIES +XGPTM1: 0 ;TIME FIRST PAGE TIED DOWN +XPL: SIXBIT /XPL/ ;FILE + JNAME OF XPL INTERPRETER +XPLU: 0 ;INDEX OF LOADED XPL + +BBLK +] + +IFE XGP,NXGPIM: JRST OPNL1 ;NO SUCH DEVICE + +SUBTTL ROBOT ARM ROUTINES + +IFN ARMP,[ +NARMCH==11. + +AARMOVE: UMOVE A,(J) + JUMPGE A,CPOPJ + CAMGE A,[-100,,] + JRST ILUUO + CONO PI,CLKOFF + CAMN U,ARMUSR + JRST AARM1A + SKIPL ARMUSR + JRST ILUUO +; CONO TIPDEV,0 +; CONI TIPDEV,C +; JUMPE C,ILUUO ;DONT ALLOW ARM TO RUN WITHOUT TIPBRK +; DATAI TIPDEV,C +; TRNN C,1 +; JRST ILUUO ;WRIST DETENT OFF NORMAL- BARF +; CONO TIPDEV,TIPBCH + MOVEM U,ARMUSR +AARM1A: CONO PI,CLKON + MOVSI B,-NARMCH +AARM1: SETZM ARMDF(B) + SKIPN ARMF + SETOM DESTIN(B) ;NOT PREV IN USE, INITIALIZE + AOBJN B,AARM1 + SKIPN ARMF + SETOM OMPXIF + SKIPN ARMF + PUSHJ P,IMXON ;START IMX + SETOM ARMF ;ARM NOW IN USE + SETOM DLSRCH +ARML: UMOVE E,(A) ;PICK UP COMM + LDB C,[220400,,E] + JUMPE C,ARML1 ;NO INDEX + XCTR XRW,[HRRZ Q,(C)] + ADD E,Q + TLZ E,17 +ARML1: TLZE E,20 + XCTR XRW,[HRR E,(E)] + LDB D,[360600,,E] ;CHNL + LDB C,[300600,,E] ;OP + CAIGE D,NARMCH + CAIL C,NARMOP + JRST ARMLOS + PUSHJ P,@ARMOPT(C) + AOBJN A,ARML + ADF1: MOVSI D,-NARMCH +ADFL: SKIPL A,ARMDF(D) + JRST ADF2 + TLNE A,100000 + JRST .+3 + MOVE C,RMAXV(D) + MOVEM C,MAXV(D) +ADF2: AOBJN D,ADFL + SETZM DLSRCH + JUMPL B,POPJ1 + POPJ P, + +ARMLOS: SETZM DLSRCH + JRST ILUUO + +ARMOPT: ASDEST ;0 SET DEST + ASVEL ;1 SET VELOC + ATDEST ;2 COMPARE COMPUTED POSN + ATVEL ;3 COMPARE COMPUTED VELOC + AADST ;4 COMPARE ACTUAL POS + ARPOST ;5 READ CURRENT POSITION +NARMOP==.-ARMOPT + +ARPOST: LDB B,IMPXPP(D) ;READ POSITION + UMOVEM B,(E) + POPJ P, + +ASDEST: ANDI E,7777 + CAMGE E,DESMIN(D) + MOVE E,DESMIN(D) + CAMLE E,DESMAX(D) + MOVE E,DESMAX(D) + MOVEM E,DESTIN(D) + MOVSI E,600000 +ADFSET: IORM E,ARMDF(D) + POPJ P, + +ASVEL: ANDI E,7777 + CAMLE E,RMAXV(D) + MOVE E,RMAXV(D) + MOVEM E,MAXV(D) + MOVSI E,500000 + JRST ADFSET + +AADST: LDB C,IMPXPP(D) ;COMPARE ACTUAL POSITION + SUB C,DESTIN(D) + JRST ATD1 + +ATDEST: SKIPA C,DESTIN(D) ;COMPARE COMPUTED POSITION +ATVEL: SKIPA C,VELOC(D) ;COMPARE COMPUTED VELOCITY + SUB C,POST(D) +ATD1: MOVMS C + CAMLE C,E + TLO B,400000 + POPJ P, + +SERVO: MOVSI A,-NARMCH + AOSN OMPXIF + JRST SERVI +SERV1: MOVE T,DESTIN(A) + SUB T,POST(A) + SKIPN VELOC(A) + JUMPE T,SERVX +SERV1A: MOVN B,MAXV(A) + MOVE C,VELOC(A) + SUB C,MAXA(A) + CAMGE C,B + MOVE C,B + MOVE B,VELOC(A) + ADD B,MAXA(A) + CAMLE B,MAXV(A) + MOVE B,MAXV(A) + CAMG T,B + CAMGE T,C + JRST SERV2 + MOVM D,T + CAMLE D,MAXA(A) + JRST SERV2 +SERV3: MOVEM T,VELOC(A) + ADDB T,POST(A) + IOR T,OMPXP(A) + DATAO OMPX,T +SERVX: AOBJN A,SERV1 +SERVR: JRST ARMSVR + +SERV2: SKIPGE T + SKIPA D,C + MOVE D,B + SUB T,VELOC(A) + MOVM E,D + IMUL D,E + IDIV D,MAXA(A) + ASH D,-1 + CAMGE D,T + SKIPA E,B + MOVE E,C + MOVE C,E + XOR C,VELOC(A) + JUMPGE C,SERV2A + MOVE C,E + XOR C,T + JUMPGE C,SERV2A + SKIPA T,VELOC(A) +SERV2A: MOVE T,E + JRST SERV3 + +SERVI: LDB B,IMPXPP(A) ;INITIALIZE TO CURRENT ARM STATE + MOVEM B,POST(A) + SETZM VELOC(A) + SKIPGE DESTIN(A) + MOVEM B,DESTIN(A) + IOR B,OMPXP(A) + DATAO OMPX,B + AOBJN A,SERVI + JRST SERVR + +AARMOFF: CAME U,ARMUSR + POPJ P, + CONO TIPDEV,0 + SETZM ARMF + PUSHJ P,IMXCL1 + SETOM ARMUSR + POPJ P, + +AARMRS: CAME U,ARMUSR ;RESET ARM LOCK FLAGS + POPJ P, + MOVSI A,-NARMCH +AARMR1: SKIPL ARMLOK(A) + JRST AARMR2 + CONO PI,OMXOFF + SETOM DESTIN(A) ;RELOAD ARM COMM FROM CURRENT POS + CLEARM ARMLOK(A) + SETOM OMPXIF + CONO PI,OMXON +AARMR2: AOBJN A,AARMR1 + POPJ P, + + +TIPBRK: DATAI TIPDEV,B + TRNE B,1 ;WRIST DETENT + JRST TIPBR2 + SETOM ARMLOK+ARMVRT ;UNHAPPINESS +TIPBR2: EXCH B,TIPBR + XOR B,TIPBR + SKIPGE A,ARMUSR + JRST TIPBR1 + ANDI B,7 + LSH B,ATPSFT + IORM B,PIRQC(A) +TIPBR1: JRST OMXRET + + +EBLK + +;JOINT ASSIGN +;0-10 AMF SWING VERT HORIZ YAW TILT GRIP ROTATE EXTEND ROLL +;11-12 NEW VIDI FOCUS IRIS + +ARMVRT==1 ;CHNL # OF ARM VERT + +DESMIN: IRPS A,,0 41 233 0 0 0 0 0 0 0 0 + A +TERMIN +DESMAX: IRPS A,,7777 7777 7323 7777 7777 7777 7777 7777 7777 7777 7777 + A +TERMIN +DESTIN: BLOCK NARMCH ;-1 NOT COMMANDED + VAL OF POSITION COMMAND +POST: BLOCK NARMCH ;POSITION OF ARM AT PI LEVEL +VELOC: BLOCK NARMCH +MAXV: BLOCK NARMCH +ARMDF: BLOCK NARMCH ;4.9 VARIABLE CHANGED 4.5 POS VAR 4.7 VEL 4.6 ACC +ARMLOK: BLOCK NARMCH ;IF -1 AXIS LOCKED DO NOT ALLOW CHNG IN COMMAND + +MAXA: REPEAT NARMCH,14 +RMAXV: REPEAT NARMCH,140 + +OMPXP: IRPS A,,2 3 4 6 7 12 11 10 5 32 31 + A,, + TERMIN + +IMPXPP: IRPS A,,102 103 104 106 107 112 111 110 105 132 131 + 301400-140000*,,MPXBUF+A/3 + TERMIN + +ARMUSR: -1 ;-1 OR INDEX OF USER DOING ARMOVE +OMPXIF: 0 ;-1 => INITIALIZE DESTINS'S TO CURRENT ARM POSITION +ARMF: 0 ;-1 ARM IN USE, 0 NO ARMOV EXECUTED +TIPBR: 0 ;TIP BREAK REG LAST TIME READ IN +BBLK +] + +SUBTTL INPUT MULTIPLEXOR + +IFN IMXP,[ +APOTSE: CONI MPX,T + JUMPE T,ILUUO ;MPX NOT AVAIL + MOVE C,B +APOTS1: UMOVE A,(C) + ANDI A,377 ;GET IMPX CHNL + JUMPE A,CPOPJ ;CHNL 0 = END OF LIST + IDIVI A,3 ;COMPUTE MPXBUF INDEX + ADD A,MPXPT(B) ;FORM BYTE PTR + MOVSI B,-NPOTCH ;SET UP TN DELETE PREVIOUS POT CONN +PTS1: CAMN A,POTBPT(B) ;IS ENTRY FOR SAME CHNL + SKIPG POTUSR(B) ;AND ACTIVE + JRST PTS2 ;NO,KEEP LOOKING + CAME U,POTUSR(B) ;IS THIS USER THE ONE WHO MADE ENTRY + JRST ILUUO ;NO,ILLEGAL + PUSHJ P,NARK ;DEACTIVATE AND FREE ENTRY + +PTS2: AOBJN B,PTS1 ;TRY NEXT ENTRY + MOVEI B,400000 ;MASK FOR DELETE ONLY + XCTR XRW,[TDNE B,(C)] ;SKIP ON NEW ENTRY WANTED + JRST PTSR ;TRY FOR NEXT BLOCK + MOVSI B,-NPOTCH ;SET UP TO FIND FREE ENTRY +PTS3: SKIPL POTUSR(B) ;SKIP ON FREE +PTS4: AOBJN B,PTS3 ;TRY OTHER SLOTS + JUMPGE B,ILUUO ;NO SLOTS AVAIL + CONO PI,CLKOFF ;PREVENT OTHER GRABBERS + SKIPGE POTUSR(B) ;SKIP IF JUST TAKEN + JRST PTS5 ;OKAY FOR SURE + CONO PI,CLKON ;REENABLE + JRST PTS4 ;TRY ANOTHER + +PTS5: SETZM POTUSR(B) ;MARK TAKEN + AOS IMXNTO + AOS POTCON ;INCREMENT NUMBER SLOTS IN USE + PUSHJ P,IMXON ;START IMPX + CONO PI,CLKON ;AND ENABLE +PTS6: MOVEM A,POTBPT(B) ;SAVE PTR TO MPXBUF FOR MPX ROUTINE + XCTR XRW,[HRRZ A,1(C)] ;GET USER ADR + XCTRI XRW,[MOVES (A)] + JRST .+2 + JRST PTSL1 ;NO,LOSE + XCTR XRW,[HLL A,1(C)] ;GET BYTE FIELDS + TLNN A,777700 ;IF NONE SPECIFIED + TLC A,4400 ;ASSUME FULL WORD + TLZ A,77 ;FLUSH INDEX,INDIRECT + MOVEM A,POTVPT(B) ;SAVE AS USER MEM PTR FOR MPX ROUTINE +PTS7: UMOVE A,(C) + ANDI A,3 ;GET FLOAT + ABS BITS + MOVEI D,PUFLI ;ADDR OF FLOATING INCREMENTAL UPDATE + TRNN A,1 ;SKIP ON FLOATING + MOVEI D,PUFXI ;ADDR OF FIXED INCREMENTAL UPDATE + TRNE A,2 ;SKIP ON NOT ABSOLUTE + SOS D ;ABS ROUTINE STARTS ONE BEFORE INCREMENTAL + MOVEM D,POTUPD(B) ;SAVE ROUTINE ADDR FOR MPX ROUTINE +PTS8: XCTR XRW,[MOVN D,2(C)] ;GET LOWER LIMIT + MOVNM D,POTOFS(B) ;SAVE AS OFFSET FOR MPX ROUTINE + TRNE A,1 ;SKIP ON FIXED + JRST PTS9 ;GO SET FLOATING PARAMS + XCTR XRW,[ADD D,3(C)] ;UL-LL + ASH D,-2 ;SCALE MULTIPLIER + +PTS9R: MOVEM D,POTSCL(B) ;STORE SCALE FACTOR FOR MPX ROUTINE + LDB D,POTVPT(B) ;GET CURRENT VARIABLE VALUE + TRNE A,1 ;SKIP ON FIXED + JRST PTS10 ;COMPUTE FLOATING INCR VALUE + SUB D,POTOFS(B) ;D_VAL-LL FIXED + MOVSI E,200000 ;SET TO ROUND VALUE + ASHC D,-25. ;SCALE TO GET 12 BIT VALUE + DIV D,POTSCL(B) ;COMPUTE INCR VAL FOR VAR +PTS10R: HRROM D,POTVAL(B) ;STORE INCR VALUE FOR MPX ROUTINE + MOVEM U,POTUSR(B) ;STORE USER TO ACTIVATE MPX ROUTINE +PTSR: ADDI C,4 ;ADVANCE POINTER TO NEXT 4 WORD BLOCK + JRST APOTS1 ;GO SET MORE TABLE ENTRIES + +PTS9: FADR D,3(C) ;UL-LL IN FLOATING + FSC D,-12. ;SCALE DOWN FOR POT RANGE + JRST PTS9R ;RETURN WITH SCALE FACTOR + +PTS10: FSBR D,POTOFS(B) ;D_VAL-LL FLOATING + FDVR D,POTSCL(B) ;COMPUTE INCR VAL FLOATING + MULI D,400 ;FIX INCR VAL + TSC D,D ;WORK FOR BELOW LOWER LIMIT + ASH E,-243(D) ;VALUE IN E + MOVE D,E ;TO D LIKE FIXED + JRST PTS10R ;RETURN WITH INCR VALUE + + +PTSL1: PUSHJ P,NARK + PUSHJ P,TPFLT + JRST UUOTRO + +;POTS UPDATE CALLED BY MPX ROUTINE + +UPOTS: SPM UPTPGT + MOVSI A,-NPOTCH ;SET UP TO LOOP FOR ALL POT TABLE POSITIONS + SETZM UPUSR ;INDICATE NO USER SET UP +UPOT1: SKIPLE U,POTUSR(A) ;SKIP ON SLOT UNUSED OR IN PROCESS + JRST UPOT2 ;GO TRY TO UPDATE VAR +UPOTR: AOBJN A,UPOT1 ;TRY NEXT POT TABLE ENTRY + LPMR UPTPGT ;RESTORE MAP + JRST UPOTRT ;DONE + +UPOT2: CAMN U,UPUSR ;IS THIS USER LAST UPDATED + JRST UPOT3 ;YES, RELOCATION IS SETUP + MOVE T,USTP(U) ;TEST TO SEE IF + SKIPN UMAPS(U) ;MAP LOADED TO POINT TO OTHER USER + TLNE T,BUCSTP+BCSTOP ;USER BEING MOVED + JRST UPOTR ;YES DON'T UPDATE FOR HIM + MOVEM U,UPUSR ;SAVE AS LAST USER SET UP + LPMR UPGML(U) ;LOAD USERS MAP + UPOT3: LDB B,POTBPT(A) ;GET CURRENT ABS POSITION + HLRZ C,POTVAL(A) ;GET POS LAST TIME + TRNE C,400000 ;SKIP UNLESS FIRST TIME + JRST UPOT3A + MOVE T,B + SUB T,C + MOVMS T + CAMG T,PTNOIS + JRST UPOTR +UPOT3B: HRLM B,POTVAL(A) ;SAVE FOR NEXT TIME + SUB B,C ;GET AMOUNT OF INCREMENT + CAIL C,5252 ;SKIP IF NOT IN UPPER THIRD + JUMPG B,UPOT4 ;JUMP IF IN UPPER THIRD AND GOING UP + CAIGE C,2525 ;SKIP IF NOT IN LOWER THIRD + JUMPL B,UPOT5 ;JUMP IF IN LOWER THIRD AND GOING DOWN +UPOT6: HRRE C,POTVAL(A) ;GET PREV INCREMENTAL VALUE + ADD C,B ;UPDATE BY POT INCR + CAILE C,7777 ;IF NEW VALUE WOULD EXCEED 7777 + MOVEI C,7777 ;CLAMP IT TO 7777 + CAIGE C,0 ;IF NEW VALUE WOULD BE LESS THAN 0 + MOVEI C,0 ;CLAMP IT TO 0 + HRRM C,POTVAL(A) ;STORE NEW INCR VALUE + JSP B,@POTUPD(A) ;CALL ROUTINE TO COMPUTE NEW VARIABLE VALUE + HRRZ T,POTVPT(A) ;STORE VAR IN USER MEM + XCTRI XR,[MOVE B,(T)] + JRST .+2 + JRST INARK + MOVEI D,B + HLL D,POTVPT(A) + DPB C,D + XCTRI XW,[MOVEM B,(T)] ;STORE VAR IN USER MEM + JRST UPOTR + +INARK: SETOM POTUSR(A) ;THIS POT A LOSER, FLUSH + SOS POTCON + SOS IMPXF + SOSGE IMXNTO + DATAO DSDEVN,[MPX] + JRST UPOTR ;RETURN FOR MORE POTS + +UPOT4: HRREI C,-6(B) ;C_DELTA-6 + IMULI C,3 ;C_DELTA*3-22 + CAMLE C,B ;IF POT TURNED UP FAST + MOVEM C,B ;THEN BOOST INCREMENT + JRST UPOT6 ;RETURN TO STORE + +UPOT5: HRREI C,6(B) ;C_DELTA+6 + IMULI C,3 ;C_DELTA*3+22 + CAMGE C,B ;IF POT TURNED DOWN FAST + MOVEM C,B ;THEN DECREASE DECREMENT + JRST UPOT6 ;RETURN TO STORE + +PUFXA: HLRZ C,POTVAL(A) ;ABS ENTRY, USE DIRECT VALUE +PUFXI: MUL C,POTSCL(A) ;INCR ENTRY, SCALE VALUE + ASHC C,25. ;200000,,=FULL WORD + ADD C,POTOFS(A) ;OFFSET VALUE + JRST (B) ;RETURN WITH USER FIELD VALUE + +PUFLA: HLRZ C,POTVAL(A) ;ABS ENTRY FOR FLOAT PT +PUFLI: TLC C,232000 ;FLOAT POT VALUE + FAD C,C ;NORMALIZE + FMPR C,POTSCL(A) ;SCALE FLOATING VALUE + FADR C,POTOFS(A) ;ADD OFFSET + JRST (B) ;RETURN WITH NEW FLOATING VAR VALUE + +UPOT3A: MOVE C,B ;FIRST TIME USE CURRENT VALUE + JRST UPOT3B + + +NARK: SETOM POTUSR(B) ;TURN OFF AND FREE POT CHANNEL + SOS POTCON ;DECREMENT # OF SLOTS IN USE + JRST IMXCL1 ;FLUSH THIS USE OF MPX AND MAYBE DEASSIGN MPXR + +POTCLS: MOVEI A,NARK ;ON CLOSE FLUSH ALL ENTRIES FOR USER +POTCLA: MOVSI B,-NPOTCH ;SET UP TO TEST ALL ENTRIES FOR USER U +POTCL1: CAMN U,POTUSR(B) ;SKIP IF DIFFERENT USER + PUSHJ P,(A) ;FLUSH IT MAYBE + AOBJN B,POTCL1 ;TRY ALL SLOTS + POPJ P, ;DONE + +EBLK +POTUSR: REPEAT NPOTCH,-1 ;-1=FREE, 0=PROCESS, +=USER INDEX +POTBPT: BLOCK NPOTCH ;BYTE PTR INTO MPXBUF +POTVPT: BLOCK NPOTCH ;BYTE PTR INTO USER MEM INDEXED BY R +POTVAL: BLOCK NPOTCH ;DIRECT VALUE,,INCR VALUE +POTUPD: BLOCK NPOTCH ;ADDR OF ROUTINE TO COMPUTE NEW VALUE +POTSCL: BLOCK NPOTCH ;SCALE FACTOR FOR VARIABLE +POTOFS: BLOCK NPOTCH ;OFFSET FOR VARIABLE +MPXPT: REPEAT 3,301400-140000*.RPCNT,,MPXBUF ;POINTERS FOR 12 BIT MPX BYTES +UPUSR: 0 ;USER FOR WHOM RELOC SETUP AND NOT STOPPED +UPTPGT: BLOCK 8 ;SAVE MAP + +POTCON: -1 ;-1 + +PTNOIS: 3 ;IGNORE ANY CHANGE < OR = THIS AS POT NOISE +] + +SUBTTL 340 DISPLAY + +IFN 340P,[ +; +; DISPLAY INTERRUPT ROUTINE +; +DRECYC: 0 +; +BBLK +; + MOVEM A,LPTA + MOVE A,DRECYC + MOVEM A,LPTBRK + MOVE A,[B,,LPTB] + BLT A,LPTB+17-B+1-1 + JRST DRECY1 +SRECYC: MOVE A,[B,,LPTB] + BLT A,LPTB+17-B+1-1 + CONSZ DIS,2000 + JRST DSLTPB ;LIGHT PEN BREAK + SKIPGE 340MD + JRST SRCYRB ;RANDOM BREAK + CONSZ DIS,5000 + JRST SRCY4 +DRECY1: +; DATAI 710,A +; SUB A,LQTIM +; CAIL A,32000./2 +; JRST DISF2 ;MISSING CLOCK BREAK DUE TO DIS + HLRE A,DBLKOP + SKIPL A + TDZA A,A + MOVNS A + ADDB A,DWDS ;CREDIT BACK WDS NOT USED + JUMPL A,DISF2 + HRRZS DBLKOP + SKIPE 340MD + JRST SRCY3 ;IDS OR DIS +SRCY1: HRRZ A,LDISP + JUMPE A,ENDLIS + JSP B,DPFTCH + JUMPL A,SRCY2A ;SINGLE BLKO PNTR + MOVEM A,LDISP ;LIST + HLRZS A + JUMPE A,SRCY5 ;THIS ENTRY NULL + JSP B,DPFTCH + SKIPGE LMODE + JRST SRCY1A ;DSTRT +SRCY1C: JUMPGE A,SRCY5 + MOVEM A,LUBLKP ;SAVE FOR DEBUGGING + HLRO C,A + MOVNS D,C ;+ COUNT + LDB E,[1200,,A] ;WD WITHIN PG + ADD E,D + LSH E,-10. + AOS E + MOVE J,E ;SAVE # EXEC PGS REQD + SUBI E,N340PB + JUMPG E,SRCY2B ;CANT MAKE IT IN ONE WHACK + MOVN Q,E ;SAVE MAX ACCEPT STARTING EXEC PG # + HRLZS E + HRRZ C,A + CAIGE C,20 + JRST DISLOS + ANDI C,776000 ;USER PG # + MOVNI R,1 ;BEST STARTING PLACE SO FAR +SRCY2D: CAMN C,340DA(E) ;LOOK FOR PG SET UP TO RIGHT USER PG + JRST SRCY2F ;FOUND ONE +SRCY2I: AOBJN E,SRCY2D + HRRZ E,R + JUMPGE R,SRCY2C ;PARTIALLY SET UP PLACE FOUND + AOS 340DP + CAML Q,340DP ;NONE AVAIL, IS RING PNTR IN ACCEPTABLE AREA? + SKIPA E,340DP ;YES + CLEARB E,340DP ;NO RESET +SRCY2C: MOVE R,DDAD(E) + LSH R,-10. + DPB R,[121000,,A] ;SWITCH BLKO PNTR TO EXEC MD PG + MOVEM A,LDBLKP + MOVEM A,DBLKOP + HLRES A ;FOR GROSS DISPLAY LISTS + ADDM A,DWDS ;APPROX TO WDS TO DISPLAY + IDIVI A,1000. + SOS A ;QUOTIENT MAY BE ZERO + MOVEM A,DISDIE + MOVNI A,EWRT + ADDM A,DWDS + ADDI E,2 ;OFFSET FOR POINTER PAGES + MOVEI A,0 +SRCY2E: CAME C,A340P1(E) ;PG SET TO RIGHT ADR? + JRST SRCY2J ;NO SET UP +SRCY2K: ADDI C,2000 + AOS E + SOJG J,SRCY2E ;SET UP ALL PGS IN BLOCK + CONSZ DIS,5400 + CONO DIS,100\SDCHN_3\DISCHN + JRST SRCYCX + +SRCY2J: JSP B,DDFTC + MOVEI B,-2(E) + MOVEM B,340DP + JRST SRCY2K + +SRCY2B: JRST DISLOS ;TEMP + +SRCY2F: MOVE D,J ;FIRST PAGE MATCHES, DO ENOUGH ADDITIONAL PAGES MATCH? + SOJLE D,SRCY2C ;ONLY ONE PAGE NEEDED. WINS + MOVEI TT,2000(C) + MOVEI R,1(E) +SRCY2H: CAME TT,340DA(R) + JRST SRCY2G ;NOT SET UP FOR WHOLE BLOCK + ADDI TT,2000 + AOS R + SOJG D,SRCY2H + JRST SRCY2C ;SET UP FOR WHOLE BLOCK. WIN + +SRCY2G: HRRZ R,E ;SAVE BEST SO FAR + JRST SRCY2I + DPFTCH: HRRZ C,A + CAIGE C,20 + JRST DISLOS + TRZ C,1777 + MOVSI E,-N340PB-2 +DPFTC2: CAME C,A340P1(E) ;PG SET UP TO RIGHT ADR? + JRST DPFTC1 ;NO + TRZ A,776000 ;YES RETCH REL ADR + XCTRI [MOVE A,@DPAP(E)] + JRST (B) ;NO FAULT + JRST 4,. ;SHOULD HAVE BEEN VERIFIED WHEN LOADED + +DPFTC1: AOBJN E,DPFTC2 ;LOOP ON ALL EXEC PNTR PAGES + MOVE E,340PP ;NONE SET UP SO SELECT ONE TO SET UP + AOS D,340PP ;INCR IT FOR NEXT TIME + CAILE D,1 + CLEARM 340PP ;RESET +DDFTC: SPM DPBS ;ENTRY FOR DATA PGS STORE MAP + SKIPGE U,DISUSR + JRST 4,. + SKIPL CIRPSW + JRST DDFTC2 ;MAP MIGHT CHANGE + SKIPGE A340P1(E) + JRST DDFTC3 + SETOM A340P1(E) ;WIPE OUT OLD ENTRY + LDB W,DPEP(E) ;PICK UP OLD PAGE + TRZN W,600000 ;NO ACCESS + JRST 4,. + ANDI W,PMRCM + CAIL W,TSYSM + JRST 4,. + MOVEI R,0 + DPB R,DPEP(E) + SKIPGE DDEXCF+340P1(E) + JRST DDFTC3 + LDB R,[MUR,,MEMBLT(W)] + CAIE R,MURUSR + JRST 4,. + MOVSI R,-1 + ADDM R,MMSWP(W) ;REDUCE COUNT OF EXEC REFS +DDFTC3: MOVE W,C ;SET PAGE IN E TO PNT TO ADR IN C + LSH W,-10. ;GET USR PG # + ROT W,-1 ;GET WD # AND SAVE WHICH HALF IN SIGN + ADDI W,UPGMP(U) + HLRZ R,(W) + SKIPGE W + HRRZ R,(W) ;PICKS UP PAGE ENTRY + HLRZ T,UPGCP-UPGMP(W) + SKIPGE W + HRRZ T,UPGCP-UPGMP(W) + TRNN R,600000 + JRST DDFTC1 ;NO ACCESS OR SWAPPED OUT + LDB Q,[PMRCAD,,R] + CAIN T,-1 + JRST DDFTC4 ;ABS PG + CAILE Q,TSYSM + JRST 4,. + SKIPGE MEMBLT(Q) + JRST DDFTC2 ;CAN'T SET UP EXEC PG POINTING TO THIS ONE + LDB TT,[MUR,,MEMBLT(Q)] + CAIE TT,MURUSR + JRST 4,. + CLEARM DDEXCF+340P1(E) + MOVSI TT,1 + ADDM TT,MMSWP(Q) ;AOS COUNT OF EXEC PGS +DDFTC5: MOVEM C,A340P1(E) + DPB R,DPEP(E) ;STORE USERS PG ENTRY IN EXEC MAP + LPMR DPBS ;RESET ASSOC REG + ANDI A,1777 ;FLUSH USER ADR EXCEPT WD IN PAGE + XCTRI [MOVE A,@DPAP(E)] ;REF PAGE TO MAKE SURE ITS THERE, ETC + JRST (B) + JRST 4,. + +DDFTC4: SETOM DDEXCF+340P1(E) ;INDICATE PAGE POINTING TO ABS PAGE + JRST DDFTC5 + +DDFTC1: JUMPE R,DISLOS ;MAP COMPLETELY 0 MUST BE ILM + JUMPE T,DISLOS ;ILM + MOVEM U,DISSWI + LDB W,[121000,,C] + MOVEM W,DISSPG ;RQ PG IN +DDFTC2: MOVNI A,3 ;HANG FOR 3 60THS + JRST DISF2A + +SRCY1A: JUMPGE A,SRCY1B + MOVEI A,-1(A) +SRCY1D: JSP B,DPFTCH + SOJA A,SRCY1C + +SRCY1B: TLNN A,777000 + JRST SRCY5 + HLRZ A,LDISP + JRST SRCY1D + +SRCY3: SOSGE DTIME + JRST DISF ;LIMIT REPETITION RATE + SKIPL NDSFMS ;SKIP ON FRAME HACK NOT ACTIVE + JSP B,ENDFM1 ;MAYBE STOP DISPLAY AFTER SPEC # OF FRAMES + MOVE A,IDBLKP + MOVEM A,DBLKOP + CONO DIS,100\SDCHN_3\DISCHN + SETOM DISDIE + JRST SRCYCX + +SRCY4: CONO DIS,200\SDCHN_3\DISCHN ;EDGE GRONK DIS AND KEEP GOING + JRST SRCYCX + +DISF2: MOVNI A,300. +DISF2A: MOVEM A,DTIME + SETOM DISON + JRST DISF3 + +DISF: SETOM DISON +DISF1: MOVEI A,1 + MOVEM A,DTIME +DISF3: CONO DIS,100 +DISF4: MOVEI A,DIS300-1 + MOVEM A,DBLKOP +SRCYCX: MOVE A,[JSR DBLKPB] +SRCYB1: MOVEM A,40+2*DISCHN +SRCYB2: JRST LPTRT1 + +DIS300: 3000 + 3000 + +DCRSTP: SKIPE 340MD ;STOP DISPLAY FOR CORE SHUFFLING + POPJ P, ;BUFFER NOT IN USER CORE SO NO ACTION +DCRST1: SETOM CDISOF + CONO DIS,0 + POPJ P, + +DCRRST: SKIPE 340MD ;DISPLAY RESTART + POPJ P, + SKIPL DISOFF + CONO DIS,SDCHN_3+DISCHN + CLEARM CDISOF + POPJ P, + +DSLTPB: DATAI DIS,LLTPSN + AOS LTPCNT + HRRZ A,LLTPSN + ADDM A,LTPCY + HLRZ A,LLTPSN + ADDM A,LTPCX + SKIPGE B,DISUSR + JRST 4,. + MOVEI A,%PILTP + AND A,MSKST(B) + IORM A,PIRQC(B) + CONO DIS,@LTPDCN + JRST SRCYCX + +EBLK + +DBLKP1: 0 +DBLKPB: 0 + +BBLK + MOVEM A,DBLKP1 + MOVE A,[BLKO DIS,DBLKOP] + MOVEM A,40+2*DISCHN + MOVE A,DBLKP1 + JRST 12,@DBLKPB + +SRCYRB: CONI DIS,A + SKIPGE A + CONO DIS,100 ;WOULD ASSIGN IF IDLE + MOVE A,[JSR DIGNOR] + JRST SRCYB1 + +EBLK + +DIGNOR: 0 + +BBLK + CONO DIS,0 + DATAO DSDEV,[DSNDIS] + JRST 12,@DIGNOR + +ENDLIS: SETOM DISDIE + MOVE A,DROOT + MOVEM A,LDISP + SOSGE DTIME + JRST DISF ;LIMIT REPETION RATE + SKIPL NDSFMS + JSP B,ENDFM1 ;HACK FRAME HACK + CONO DIS,100\SDCHN_3\DISCHN + JRST SRCY1 + +ENDFM1: SKIPE NDSFMS ;STOP DISPLAY IF SPEC # OF FRAMES UP ELSE RETURN + SOSGE NDSFMS + JRST ENDFM2 ;STOP WORLD + JRST (B) + +ENDFM2: SETOM DISOFF + JRST DISF1 + +SRCY5: MOVNI A,EWRT/2 + ADDB A,DWDS + JUMPGE A,SRCY1 + JRST DISF2 + +DISLOS: SKIPE 340MD + JRST 4,. + SKIPGE A,DISUSR + JRST 4,DISF2A + MOVEI B,%PIDIS + IORM B,PIRQC(A) + MOVSI A,(SETZ) + JRST DISF2A ;DIE FOR A LONG TIME + +SRCY2A: SOSGE DTIME + JRST DISF + SKIPL NDSFMS + JSP B,ENDFM1 + CONO DIS,100\SDCHN_3\DISCHN + JRST SRCY1C + + +SUBTTL 340 DISPLAY - .DSTART, .DSTRTL + +DISACR: CAME U,DISUSR + POPJ P, + SKIPE 340MD ;COME HERE IF PAGE BEING FLUSHED + EXEC PAGE POINTING TO IT + JRST 4,. ;SHOULD NOT BE SET UP TO USER PAGE + CONO PI,UTCOFF + SETOM A340P1-340P1(T) + SKIPGE DDEXCF(T) + JRST DISAC1 + ADDB J,MMSWP(TT) + SKIPGE J + JRST 4,. +DISAC1: SKIPGE DISOFF + JRST POPJ1 + PUSH P,T + PUSHJ P,DISZAP + POP P,T + JRST POPJ1 + +;ROUTINES TO START 340 DISPLAY WITH DIS BUFF IN USERS CORE +ADSTART: TDZA E,E ;CALL 10, +ADSTL: MOVNI E,1 ;CALL 12, + MOVEI A,0 + PUSHJ P,ADSDV + POPJ P, + SETOM DISOFF + CONO DIS,0 + CLEARM 340MD + MOVEM E,LMODE + HRRZ C,40 + MOVEM C,DROOT + MOVEM C,LDISP + SETZM DISOFF + PUSHJ P,DISZAP + JRST CLKOJ1 + +ANDIS: CAME U,DISUSR + POPJ P, + UMOVE A,(J) + JUMPL A,ANDIT1 ;WAIT FOR COMPLETION OF LAST NDIS + JUMPE A,ANDIT2 ;RETURN COUNT LEFT FROM LAST NDIS + MOVEM A,NDSFMS ;DISPLAY N TIMES AND THEN STOP + SKIPL DISOFF + JRST POPJ1 + SETOM DISDIE + CLEARM DISOFF + PUSHJ P,DISZAP + JRST POPJ1 + +ANDIT1: SKIPL DISOFF + PUSHJ P,UFLS + POPJ P, + +ANDIT2: MOVE A,NDSFMS + JRST APTUAJ + +SUBTTL 340 DISPLAY - .DSTOP, .DCLOSE, .LTPEN +ADSTOP: CAMN U,DISUSR ;OPER 16 + SKIPGE DISOFF + POPJ P, +ADCLB: PUSH P,B + PUSH P,C + MOVSI C,-1 + SETOM DISOFF + SETZM DBLINK + CONO DIS,0 + MOVEI A,1 + MOVEM A,DTIME + SETZM DISON + SETOM DISDIE + CONO PI,UTCOFF + MOVSI A,-N340CL +ADCLB1: SETOM A340P1(A) + LDB B,DPEP(A) + ANDI B,600000+PMRCM + SKIPGE DDEXCF+340P1(A) + JRST ADCLB2 ;POINTING TO EXEC PG + TRZE B,600000 + ADDM C,MMSWP(B) +ADCLB2: AOBJN A,ADCLB1 + CLEARM 340PP + CLEARM 340DP + CLEARM EXEUMP+.340P1 + REPEAT N340PB/2,CLEARM EXEUMP+.DPG0+.RPCNT + MOVE A,[JSR DIGNOR] + MOVEM A,40+2*DISCHN + CONO PI,UTCON + POP P,C + JRST POPBJ + +ADCL1: SOSE DISNTO + POPJ P, + JRST AIDS7 + +ADCLOSE: CAME U,DISUSR ;OPER 15 + POPJ P, + SKIPLE 340MD + JRST AIDS8 +AIDS7: PUSHJ P,ADCLB + PUSHJ P,ADCL2 + JFCL +AIDS9: SETOM 340MD + SETOM DISUSR + DATAO DSDEV,[DSNDIS] ;DEASSIGN DIS + POPJ P, + +AIDS8: MOVE A,U ;FLUSH CHNLS IN CASE OF .DCLOSE FROM DIS OR IDS + PUSHJ P,CHSCAA + PUSHJ P,ADSDV4 + JRST AIDS7 + +ALTPEN: MOVE C,B + CAME U,DISUSR ;CALL 14, + JRST ALTPP2 + XCTR XR,[SKIPL A,(C)] + JRST ALTPP1 + TLNN A,377777 + JRST .+3 + SKIPN LTPCNT + PUSHJ P,UFLS +ALTPP1: CONO PI,LPTOFF ;INHIBITS LPEN BREAKS + MOVE A,LDISP + XCTRI XW,[MOVEM A,4(C)] + SKIPA A,DBLKOP + JRST ALTPPL + TRZ A,400000 + LDB B,[121000,,A] + LDB B,[121000,,A340P1-340P1(B)] + DPB B,[121000,,A] + XCTRI XW,[MOVEM A,5(C)] + SKIPA B,C + JRST ALTPPL + HRLI B,LLTPSN + XCTRI XBW,[BLT B,3(C)] + JRST .+2 + JRST ALTPPL + SETZB A,LTPCNT + MOVEM A,LTPCY + MOVEM A,LTPCX + JRST LPTONJ + +ALTPP2: XCTR XW,[SETZM (C)] + XCTR XW,[SETZM 1(C)] + POPJ P, + +ALTPPL: CONO PI,LPTON + PUSHJ P,TPFLT + JRST ALTPEN + +SUBTTL 340 DISPLAY + +ADSDV: ;A HAS NEW 340MD + CONO PI,CLKOFF + CONI DIS,T ;DIS AVAILABLE + JUMPN T,ADSDV1 ;YES + CONO DIS,0 + CONI DIS,T + JUMPE T,ADSDVN ;DIS NOT AVAIABLE +ADSDV1: SKIPL T,DISUSR + CAMN U,DISUSR + JRST ADSDVY ;YES + CAME U,UMASTER + JRST ADSDVM ;MAYBE +ADSDV2: SKIPGE A,DISUSR ;TAKE AWAY DISPLAY + JRST ADSDV3 + PUSHJ P,RPCCK +ADSDV7: SKIPL DISUSR + SKIPG 340MD + JRST ADSDV3 + PUSH P,R + PUSHJ P,CHSCAA ;CHANGE 340 CHANNELS TO NUL DEV + PUSHJ P,ADSDV4 + POP P,R + SETZM DISNTO +ADSDV3: MOVE A,340MD +ADSDVY: SETZM DBLINK + SETOM NDSFMS ;TURN OFF FRAMER HACK + CAME A,340MD + JUMPE A,ADSDV5 ;SAME USER CLOBBERING HIS IDS OR DIS +ADSDV6: PUSHJ P,ADCLB + MOVEM U,DISUSR +ADCL2: SKIPGE A,340BF + JRST CLKOJ1 + LSH A,-10. + PUSHJ P,MEMR + SETOM 340BF + JRST CLKOJ1 + +ADSDV4: HRRZ Q,(R) + CAIG Q,DN340L + CAIGE Q,DN340B + POPJ P, ;NOT A 340 CH + CAIL Q,DN340C + SKIPA T,[NLODN] ;UNIT MODE + MOVEI T,NLBDN ;BLOCK MODE + SOS DISNTO + HRRM T,(R) + POPJ P, + +ADSDV5: SKIPGE 340MD + JRST ADSDV6 + MOVE A,DISUSR + JRST ADSDV7 + +ADSDVM: CAMN T,UMASTER + JRST ADSDVN ;CURRENT USER UMASTER + MOVE T,UTMPTR(U) + MOVE T,TTYTYP-USRRCE(T) ;GET BITS FOR NEW GUY IN LH OF T + HRR T,DISUSR + HRR T,UTMPTR(T) + HLR T,TTYTYP-USRRCE(T) + TRNE T,%TT3HP + JRST ADSEQ1 ;CURRENT USER HAS HIGH PRIORITY + TRNE T,%TT340 + JRST ADSEQ2 ;CURRENT USER NEAR 340 + TLNN T,%TT340+%TT3HP ;GIVE TO NEW GUY IF HE IS EITHER + JRST ADSEQ +ADSWIN: JRST ADSDV2 + +ADSEQ1: TLNN T,%TT3HP + JRST ADSDVN ;NO +ADSEQ: SKIPL TTYTBL(U) ;MAYBE + JRST ADSWIN +ADSDVN: JRST CLKONJ + +ADSEQ2: TLNE T,%TT3HP + JRST ADSWIN + TLNN T,%TT340 + JRST ADSDVN + JRST ADSEQ + +SUBTTL 340 DISPLAY AS ASCII DEVICE + +DISO: PUSHJ P,AIDS1 + JRST OPNL10 ;NOT AVAILABLE + AOS DISNTO + SETOM 340DMD + LDB B,[20200,,D] + AOS B + LSH B,4 + MOVEM B,CSCALE + LDB TT,[40200,,CSCALE] + MOVNS TT + MOVEI T,170. + LSH T,(TT) + TRZ T,7 + MOVEM T,DISCHS ;CHARS THAT WILL FIT THIS SIZE + MOVEI T,88. + LSH T,(TT) + MOVEM T,DISLNL ;LINES THAT WILL FIT + PUSHJ P,DSIZAP + MOVSI T,-1777 + HRR T,340BF + SOS T + MOVEM T,IDBLKP + SETZM DISOFF + PUSHJ P,DISZAP + SETOM 340T + JSP Q,OPSLD3 + DN340C,,DN340B + DN340H,,DN340W + +340FF: SKIPL 340T + JRST 340FF1 + MOVE A,TIME + MOVEM A,340T +340FF1: MOVE T,340T + ADDI T,30.*3 + CAML T,TIME + PUSHJ P,UFLS + SETOM 340T + PUSHJ P,ADCLB + PUSHJ P,DSIZAP + JRST DISZAP + +DSIZAP: SETZM DBLOAT + SETZM 340XMD + SETZM DBLINK + MOVE T,340BF + MOVEI A,34117 + IOR A,CSCALE + MOVEM A,(T) + PUSH T,[221700060000] + HRLI T,0600 + MOVEM T,340BFP + MOVE A,[403737403737] + MOVEI B,1(T) + HRLS B + AOS B + MOVEM A,1(T) + BLT B,1775(T) + MOVE A,DISLNL + MOVEM A,DISLNS + MOVE A,DISCHS + MOVNM A,DISCHC + MOVEI T,(HRRZ I,(A)) + HRLM T,AIDC1 + POPJ P, + + +340B: MOVEI E,340D + JRST NBTOCH + +340C: SKIPGE C + SKIPA A,(C) + UMOVE A,(C) + ANDI A,177 +340D: CAIN A,^C + POPJ P, + CAIN A,^L + JRST 340FF + CAIN A,^T + JRST DSIZAP + SKIPE DISLNS + SKIPGE DBLOAT + POPJ P, + CAIN A,^B + JRST BLNKON + CAIN A,^E + JRST BLNKOF + SKIPE 340XMD + PUSHJ P,340D1 ;ENTER CHR MOD INF NOT ALREADY +340E: EBLK +AIDC1: HRRZ\HLRZ I,DISTBL(A) + BBLK + TRNN I,-100 + JRST 340FC ;NORMAL CHR + TRNN I,-200 + JRST 340K ;FAKE OUT 340 NON-SPACING CHRS + PUSHJ P,(I) ;ROUTINE DISPATCH (MAY SKIP OR SKIP TWICE) + JRST 340E ;WRONG CASE OR SOMETHING, TRY AGAIN +340F: IDPB I,340BFP +340F2: MOVE J,340BFP + ANDI J,1777 + CAIL J,1776 + SETOM DBLOAT + POPJ P, + +340FC1: SKIPL DISCHC ;DISPLAY IF COUNT NOT OUT BUT DONT INCR COUNT +340FC: AOSG DISCHC ;INCR COUNT + DISPLAY IF NOT OUT + JRST 340F + JRST 340F2 + +340HD1: SKIPN 340XMD ;ESCAPE TO PARAM MODE + PUSHJ P,340H1 +340D1: MOVEI I,74117 ;PARAM WD + IOR I,CSCALE + PUSHJ P,340F ;STORE PARAM WD + MOVEI I,6 + DPB I,[300600,,340BFP] ;SWITCH TO CHR MODE + SETZM 340XMD + POPJ P, + +340K: MOVEI I,40 ;SPACE TO MAKE SPACING + PUSHJ P,340FC1 + XCT AIDC1 ;GET NON-SPACING LETTER AND DISPLAY + JRST 340FC + +340W: JSP Q,WRDBT + XCTR XRW,[MOVSS (C)] + PUSHJ P,340H + XCTR XRW,[MOVSS (C)] +340H: SKIPGE DBLOAT + POPJ P, + SKIPN 340XMD + PUSHJ P,340H1 ;ENTER HALF WD MODE IF NOT ALREADY + UMOVE I,(C) ;PICK UP LOSERS HALF WD + JRST 340F + +340H1: MOVEI I,37 ;IN CHR MODE, EXCAPE + PUSHJ P,340F + LDB I,[360600,,340BFP] + JUMPE I,340H2 + CAIE I,22 + JRST 340H1 +340H2: MOVEI A,22 + DPB A,[300600,,340BFP] + SETOM 340XMD + POPJ P, + +BLNKON: MOVE A,DBLINK + CAIL A,DBLNKN + POPJ P, + PUSHJ P,340HD1 + MOVE B,340BFP + AND B,[770060,,1777] ;ADR OF PARAM WD TO BLINK INTEN OF + TLO B,300+B + MOVE A,DBLINK + MOVEM B,DBLNKB(A) + AOS DBLINK + MOVEI T,15. + PUSHJ P,CLQADD + BLINKB + JRST 340F2 + +BLNKOF: PUSHJ P,340HD1 + JRST 340F2 + +BLNKBR: SKIPN A,DBLINK + JRST CLQRET ;BLINKING TURNED OFF + SKIPL B,340BF + SKIPGE CDISOFF + JRST BLNKB3 + MOVE C,DBLNKF +BLNKB2: DPB C,DBLNKB-1(A) + SOJG A,BLNKB2 + SETCMM DBLNKF ;COMPLEMENT FLAG +BLNKB3: MOVEI T,15. ;1/4 SEC + MOVEI C,BLINKB + JRST CLQREE + +SUBTTL 340 DISPLAY + +AIDS1: MOVEI A,2 + PUSHJ P,ADSDV ;DETERMINE IF THIS LOSER SHOULD GET DISPLAY + POPJ P, +AIDS3: PUSHJ P,TCALL + JRST IOMQ + JRST AIDS2 ;NO MEM AVAIL + MOVEI B,MUDISB + MOVE T,A + LSH T,10. + MOVEM T,340BF + DPB B,[MUR,,MEMBLT(A)] + MOVEI B,2 + MOVEM B,340MD + JRST POPJ1 + +AIDS2: SKIPG MEMFR + JRST AIDS9 + PUSHJ P,LOSSET + AIDS9 + PUSHJ P,UDELAY + PUSHJ P,LSWDEL + JRST AIDS3 + +IFN 0,[ +;INTERPRETIVE DISPLAY COMPILER + +IDISO: PUSHJ P,AIDS1 + JRST OPNL10 ;NOT AVAIL + AOS DISNTO + SETZM 340DMD + SETOM AISWS + HRLI T,442200 + MOVEM T,340BFP + MOVEI Q,10135 ;TURN OFF LP SCALE 1 INT 5 + IDPB Q,340BFP + MOVEI T,1_4 + MOVEM T,CSCALE + MOVEM T,VSCALE + MOVEM T,ISCALE + MOVSI A,(MOVE) ;DONT HACK CHR'S PER LINE + MOVEM A,DISCHS + MOVNM A,DISCHC + CONO DIS,500 + MOVEI A,DN340I + JRST OPNSLT + + +340I: MOVEM C,AIDPCP + UMOVE C,(C) + +AIDL: UMOVE R,(C) +AIDL2: TRNE R,1 + JRST AIDL1 ;NOT CHR MODE + MOVEI Q,(HRRZ I,(A)) + HRLM Q,AIDC1 + MOVE Q,CSCALE + IORI Q,60100 + PUSHJ P,AIDPY + MOVE J,[220600,,Q] +AIDCL: MOVE B,[440700,,R] +AIDC3: ILDB A,B +EBLK +AIDC1: HRRZ\HLRZ I,DISTBL(A) +BBLK + TRNN I,-100 + JRST AIDC5 + TRNN I,-200 + JRST AIDC7 + PUSHJ P,(I) + JRST AIDC1 +AIDC5: IDPB I,J + TLNN J,770000 + PUSHJ P,AIDC2 + TLNE B,760000 + JRST AIDC3 + AOS C + UMOVE R,(C) + MOVE I,UEXIT + CAMN I,[JRST ONEFLS] + JRST AIDC6 + TRNN R,1 + JRST AIDCL +AIDC6: MOVEI I,37 + IDPB I,J + TLNE J,770000 + JRST .-2 + PUSHJ P,AIDC2 + +AIDL1: MOVE B,UEXIT + CAMN B,[JRST ONEFLS] + JRST AIDI + LDB B,[30300,,R] + AOJA C,@AIDTB(B) + +AIDC7: MOVEI I,40 + PUSHJ P,AIDC4 + XCT AIDC1 + JRST AIDC5 + +AIDI: MOVE R,AIDPCP + UMOVEM C,(R) + SOS UUOH + JRST UUOE1 + +AIDTB: AIER1 + AIPT + AIVC + AIINC + AIOP + AIVC + REPEAT 2,AIER1 + +AIPT: LDB I,[251600,,R] ;PICK UP Y + SUB I,DWDB + MOVEI TT,220000 + DPB I,[1200,,TT] + LSH I,-10. + ANDI I,17 + MOVEM I,YFLD + LDB I,[61600,,R] ;X + SUB I,DWDL + MOVEI E,0 + TRNE R,2 + TRO E,2000 ;INTENSIFY + DPB I,[1200,,E] + LSH I,-10. + ANDI I,17 + MOVEM I,XFLD + MOVEI Q,20000 + PUSHJ P,AIDPY + MOVE Q,TT + PUSHJ P,AIDPY + MOVE Q,E + PUSHJ P,AIDPY + JRST AIDL + +AIDC4C: SKIPL DISCHC + POPJ P, + JRST AIDC4 +] +AIDC4B: AOSLE DISCHC + POPJ P, +AIDC4: +IFN 0,[ + SKIPGE 340DMD + JRST AIDC4A ;DIS + IDPB I,J + TLNE J,770000 + POPJ P, +AIDC2: PUSHJ P,AIDPY + MOVEI Q,0 + MOVE J,[220600,,Q] + POPJ P, +] +AIDC4A: IDPB I,340BFP + POPJ P, +IFN 0,[ +AIDPY: HRLS Q + DATAI DIS,AIDPIC + DATAO DIS,Q +AIDP1: MOVEI H,50 +AIDP1A: CONSZ DIS,DVEF+DHEF ;EDGE FLAGS + JRST DEGFS + CONSO DIS,200 + SOJG H,AIDP1A + JUMPE H,AIER2 + CONSZ DIS,DVEF+DHEF + JRST DEGFS + SKIPN XFLD + SKIPE YFLD + JRST AIDP2 +DEG4B: HRRZ H,340BFP + SUB H,340BF + CAIL H,1777 + JRST AIER3 + IDPB Q,340BFP +AIDP2: MOVEI Q,0 + POPJ P, + +DEGFS: DATAI DIS,DEGVCC + CONI DIS,H + LSH H,-15. + ANDI H,7 + CAIN H,4 ;VECTOR + JRST DEGVC + SKIPN XFLD + SKIPE YFLD + JRST DEG5A + MOVEI Q,400000 + CAIN H,3 + MOVEI Q,373737 + PUSH P,H + PUSHJ P,DEG4B ;LEAVING INSERT APPROPRIATE ESCAPE INSTEAD + POP P,H +DEG5A: CONO DIS,200 + MOVEI TT,50. + CONSO DIS,DVEF+DHEF+200 + SOJG TT,.-1 + JUMPE TT,AIER2 + CONSO DIS,200 + JRST DEG5A ;RIDE OUT TO FINAL EDGE + DATAI DIS,TT + XOR TT,AIDPIC + TRNN TT,1000 + JRST DEG5B + HRR TT,AIDPIC + TRNE TT,1000 + AOS XFLD + TRNN TT,1000 + SOS XFLD +DEG5B: TLNN TT,1000 + JRST DEG4 + HLL TT,AIDPIC + TLNN TT,1000 + SOS YFLD + TLNE TT,1000 + AOS YFLD + JRST DEG4 + +DEG5: MOVE TT,DEGVCC + CONSZ DIS,DVEF + JRST DEG1 +DEG3: CONSO DIS,DHEF + JRST DEG4 + TRNE TT,1000 + SOS XFLD + TRNN TT,1000 + AOS XFLD +DEG4: MOVEI TT,0 + DPB TT,[44000,,XFLD] + DPB TT,[44000,,YFLD] + CONSO DIS,200 + CONO DIS,200 ;CONTINUE + MOVEI TT,100. + CONSO DIS,200+DVEF+DHEF + SOJG TT,.-1 + JUMPE TT,AIER2 + SKIPN XFLD + SKIPE YFLD + JRST AIDP1 ;NOT COMING ON +DEG4F: DATAI DIS,TT + CAIN H,4 + MOVE TT,DEGVCC + PUSH P,Q ;COMING ON PRODUCE SETPOINT + PUSH P,H + MOVEI Q,20100 + IOR Q,@DEGSCT(H) + PUSHJ P,DEG4B + HLRZ Q,TT + IORI Q,220000 + PUSHJ P,DEG4B + HRRZ Q,TT + CONI DIS,H + LSH H,-15. + DPB H,[150300,,Q] + MOVE TT,(P) + CAIN TT,4 + JRST DEGVC1 +DEG4D: SUB P,[2,,2] + JRST AIDP1 + +DEGSCT: [0] + [0] + [0] + CSCALE + VSCALE + VSCALE + ISCALE + [0] + +DEG1: TLNE TT,1000 + SOS YFLD + TLNN TT,1000 + AOS YFLD + JRST DEG3 + +DEGVC: SETOM DEGVCF + SKIPN XFLD + SKIPE YFLD + JRST DEG5 ;NOT GOING OFF + CLEARM DEGVCF + HRRZ A,AIDPIC + HLRZ B,AIDPIC + PUSHJ P,DEG4C + CONSZ DIS,DVEF + SUBI B,2 + CONSZ DIS,DHEF + SUBI A,2 + SKIPGE A + MOVEI A,0 + SKIPGE B + MOVEI B,0 + DPB B,[100700,,Q] + DPB A,[700,,Q] + TRO Q,400000 + PUSHJ P,DEG4B + JRST DEG5 + +DEGVC1: SKIPN XFLD + SKIPE YFLD + SKIPLE DEGVCF + JRST .+2 + JRST DEG4D ;VECTOR TOTALLY OUT OF IT + IORI Q,100000 + PUSHJ P,DEG4B + POP P,H + POP P,Q + DATAI DIS,A + HLRZ B,A + HRRZS A + PUSHJ P,DEG4C + DPB B,[100700,,Q] + DPB A,[700,,Q] + MOVE A,DEGVCC + MOVEM A,AIDPIC + JRST AIDP1 + +DEG4C: HRRZ I,DEGVCC + SUB A,I + HLRZ I,DEGVCC + SUB B,I + MOVMS A + MOVMS B + CAIGE A,1000 + JRST .+3 + MOVNS A + ADDI A,2000 + CAIGE B,1000 + JRST .+3 + MOVNS B + ADDI B,2000 + LDB I,[40200,,VSCALE] + MOVNS I + ASH A,(I) ;GET X INC IN A + ASH B,(I) ;Y IN B + POPJ P, + +AIINC: MOVE Q,ISCALE + IORI Q,140100 + PUSHJ P,AIDPY + SETOM DDINCI + MOVEI Q,0 + MOVE B,[200400,,Q] +AIIN1: MOVE D,[440600,,R] +AIIN8: ILDB T,D + LDB E,[200,,T] ;LOAD COUNT + JUMPE E,AIIN5 ;NULL INCREMENT +AIIN7: TRNN T,4 ;SKIP ON INTENSIFY + JRST AIIN2 + SKIPG DDINCI ;SKIP ON SET TO INTENSIFY + JRST AIIN3 + +AIIN7A: LDB H,[30300,,T] + MOVE H,DINCT(H) + IDPB H,B + PUSHJ P,AIIN6 ;MAYBE START NEW WORD + SOJG E,AIIN7 + +AIIN5: TLNE D,700000 + JRST AIIN8 + UMOVE R,(C) + LDB H,[30300,,R] + TRNE R,1 + CAIE H,3 ;INC MODE + TROA Q,400000 + AOJA C,AIIN1 + PUSHJ P,AIIN6A + JRST AIDL2 + +AIIN6: TLNE B,770000 + POPJ P, + +AIIN6A: PUSHJ P,AIDPY + MOVEI Q,0 + SETOM DDINCI + MOVE B,[200400,,Q] + POPJ P, + +AIIN2: SKIPN DDINCI + JRST AIIN7A ;INTENSITY AGREES +AIIN3: SKIPL DDINCI + PUSHJ P,AIIN6A + HRRZM P,DDINCI + TRNE T,4 + TROA Q,200000 + CLEARM DDINCI + JRST AIIN7 + +AIVC: MOVE Q,VSCALE + IORI Q,100100 + LDB A,[251700,,R] ;DY + LDB B,[61700,,R] ;DX + TRNE A,40000 + ORCMI A,77777 + TRNE B,40000 + ORCMI B,77777 + MOVM E,A + MOVM TT,B + MOVE H,VSCALE + LSH H,-4 + ANDI H,3 + MOVNS H + LSH E,(H) + LSH TT,(H) + JUMPN E,.+2 + JUMPE TT,AIDL + PUSHJ P,AIDPY +AIVCL: MOVE H,E + MOVE J,TT +AIVC3: CAIG J,177 + CAILE H,177 + JRST AIVC2 + SUB E,H + DPB H,[100700,,Q] + SKIPGE A + TRO Q,1_<8+7> + SUB TT,J + DPB J,[700,,Q] + SKIPGE B + TRO Q,1_7 + TRNE R,1_1 + TRO Q,200000 + JUMPN E,.+3 + JUMPN TT,.+2 + TRO Q,400000 + PUSH P,A + PUSH P,B + PUSH P,E + PUSH P,TT + PUSHJ P,AIDPY + POP P,TT + POP P,E + POP P,B + POP P,A + JUMPN E,AIVCL + JUMPN TT,AIVCL + JRST AIDL + +AIVC2: LSH J,-1 + LSH H,-1 + JRST AIVC3 + +AIOP: LDB B,[60300,,R] + JRST @AIOPT(B) + +AIOPT: AIER5 + AIPSJ + AIPPJ + AIJMP + AIPSH + AIIPOP ;5 + AIPS + AIER5 + AIER5 + +AIPSJ: XCTR XRW,[AOS D,43] ;PICK UP PDL PNTR AND INCR + XCTR XRW,[MOVEM C,(D)] ;STORE RETURN PC +AIJMP: HLRZ C,R + JRST AIDL + +AIPPJ: UMOVE D,43 + XCTR XRW,[HRRZ C,(D)] + JUMPE C,AIEXT ;POPJ INTO 0 START SIGNAL + XCTR XRW,[SOS 43] + JRST AIDL + +AIEXT: SKIPL AISWS + JRST AIDST3 +AIDST: MOVEI Q,3000 + PUSHJ P,DEG4B + MOVE A,340BF + ADD A,[-2000-1,,-1] + MOVEM A,IDBLKP + MOVEM A,DBLKOP + MOVEI A,1 + MOVEM A,DTIME + SETZM DISOFF + CONO DIS,1100\DISCHN\SDCHN_3 +AIDST3: POPJ P, + +AIPSH: HLRZ TT,R + UMOVE TT,(TT) + XCTR XRW,[AOS D,43] + UMOVEM TT,(D) + JRST AIDL + +AIIPOP: HLRZ TT,R + XCTR XRW,[SOS D,43] + UMOVE E,1(D) + UMOVEM E,(TT) + JRST AIDL + +AIPS: LDB A,[140600,,R] + HLRZ B,R + CAIL A,AIMXP + JRST AIER7 + ANDI B,3 + LSH B,4 + XCT AIPST(A) + JRST AIDL + +AIPST: JRST AIER7 + HLLEM R,AISWS ;START MODE + MOVEM B,CSCALE + MOVEM B,ISCALE + MOVEM B,VSCALE + JRST AIPSA + HLRM R,DWDL + HLRM R,DWDB +AIMXP==.-AIPST + +AIPSA: MOVEM B,CSCALE + MOVEM B,ISCALE + MOVEM B,VSCALE + JRST AIDL +] +EBLK +XFLD: 0 ;HIGH ORDER BITS OF X COOR REG (LIGHT=0) +YFLD: 0 ; ... Y +CDISOF: 0 ;DISPLAY OFF IN CORE ALLOC +340BF: -1 ;POINTER TO 1K BLOCK FOR 340 BF (MEM ADR) +340BFP: 0 ;POINTER TO 340BF + DBLNKN==10. +DBLINK: 0 ;0=IDLE ;+N=NUM OF ENTRIES +DBLNKF: 0 ;BLINK FLAG, -1 MEANS START BLINK OFF +DBLNKB: BLOCK DBLNKN ;BYTE POINTER TO PARAMETER HW TO CHANGE +BLINKB: 0 ;CLOCK QUEUE BLOCK + -1 + JRST BLNKBR +AIDPCP: 0 ;USER LOCN WHERE TO STORE BACK PC IF NECC +CSCALE: 0 ;SCALE FOR CHR WRDS +ISCALE: 0 ;SCALE FOR INCREMENT +VSCALE: 0 ;SCALE FOR VECTOR WDS +DWDL: 0 ;14 BIT COOR OF LH 340 +DWDB: 0 ;14 BIT COOD OF BOT 340 +DEGVCF: 0 ;EDGE FLAG FOR VECT -1 UNLESS GOING AWAY +DEGVCC: 0 ;COORD AT EDGE +DDINCI: 0 ;-1 CURRENT INTENSITY NOT COMMITED (IN INCREMENT MODE) + ;+ => 1 - => 0 +AISWS: 0 ;SELECT DISPLAY START MODE -1 STARTS DISPLAY AFTER IOT +AIDPIC: 0 ;COORDINATES AT START OF AIDPY + +LLTPSN: 0 ;. TO .+3 BLTED TO USER +LTPCNT: 0 +LTPCY: 0 +LTPCX: 0 +LTPDCN: 200\SDCHN_3\DISCHN + +LDISP: 0 ;DISPLAY LINK POINTER +LMODE: 0 ;LISP LINK MODE FLAG +DISOFF: -1 ;-1 IF DIS NOT IN USE OR STOPPED DUE TO FRAME HACK +DTIME: 0 + +340MD: -1 ;MODE IN WHICH DISPLAY OPEN + ;-1 NOT DISPLAYING 0 .DSTART ETC 2 AS DIS OR IDS +340DMD: 0 ;0 IDS -1 DIS +340XMD: 0 ;IN DIS, 0=CH 1=IMAGE +DBLOAT: 0 +340T: 0 ;TIMER FOR DIS PAGE +LUBLKP: 0 ;LAST USER BLKO PNTR SET UP AT IN LEVEL, FOR DEBUGGING + +;START 340 EXECPG AREA + +A340P1: -1 ;USER ADR THAT EXEC PG SET UP FOR +A340P2: -1 +340DA: REPEAT N340PB,-1 +N340CL==.-A340P1 ;THIS BLOCK MUST BE CONSEC +340DP: 0 ;0=> N30PB-1 PNTR TO DATA PGS +340PP: 0 ;PNTR TO 340P1 OR P2 ALTNERATELY + +DPAP: 400000+340P1*2000(A) ;EXEC ADR TO REF PAGE + 400000+340P2*2000(A) +DDAD: REPEAT N340PB, 400000+*2000(A) + +DPEP: .340P1+EXEUMP ;BYTE PNTR TO EXEC MAP PAGE ENTRY + .340P2+EXEUMP +DDEP: REPEAT N340PB, CONC .DPG,\.RPCNT,+EXEUMP + +DPBS: BLOCK 8 ;SAVE PAGE BOX AT PI DIS LVL + +DROOT: 0 ;DIS RESTART POINTER TO LOSER CORE +DBLKOP: 0 ;TEMP DIS BLKO PTR +LDBLKP: 0 ;LAST +DISON: 0 ;-1 IF DIS STOPPED AFTER SPECIAL INT OR BLKO OVERFLOW + ;IE RESTART AFTER PASSAGE OF TIME +DISDIE: 0 ;0 ;-1 IF DIS HASNT DIED +DISTPR: 0 ;-1 TO TURN OFF DISPLAY +IDBLKP: 0 ;BLKO PNTR IF IN INTERP DISPLAY MODE +NDSFMS: -1 ;-1 NOT HACKING FRAME HACK ELSE NUMBER OF FRAMES REMAINING +DISNTO: 0 ;# TIMES DIS OR IDS OPEN +DWDS: 0 ;- # WDS SENT TO DIS-EWRT PER TRIP THRU SRECYC + ;RESET TO MDISWD EVERY 1/30 + ;IF <0 DISPLAY STOPS FOR 5 SEC -300.->DTIME + +DISCHS: 0 ;LENGTH OF LINE IN CURRENT SIZE +DISCHC: 0 ;-# CHR POS REMAINING +DISLNL: 0 ;# OF LINES WILL FIT CURRENT SIZE +DISLNS: 0 ;# LINES REMAINING +BBLK + +DEFINE LC A +A,,DISLC +TERMIN + +DEFINE UC A +DISUC,,A +TERMIN + +DEFINE AC A +A,,A +TERMIN + + + +ADISCR: MOVE I,DISCHS + MOVNM I,DISCHC + MOVEI I,34 + JRST POPJ1 + +DISALF: SOS DISLNS + MOVEI I,33 + JRST POPJ1 + +DSATB: MOVEI I,40 ;B + PUSHJ P,AIDC4B + LDB I,[300,,DISCHC] + SKIPG DISCHC + JUMPN I,DSATB + JRST POPJ2 + +DISBLB: MOVEI I,50 ;DOWN ARROW + PUSHJ P,AIDC4B + TRO A,100 ;CONVERT TO UC LETTER +DISUC: SKIPA I,[HRRZ I,35(A)] ;SWITCH TO UC +DISLC: MOVE I,[HLRZ I,36(A)] ;SWITCH TO LC + PUSHJ P,AIDC4 ;STORE CASE CODE + HLLM I,AIDC1 + POPJ P, + +ADISBS: MOVEI I,72 ;BACKSPACE + SOS DISCHC + JRST POPJ1 + +DISRUB: MOVEI I,"X&77 ;LC X + PUSHJ P,AIDC4 + MOVEI I,72 ;340 BACKSPACE + PUSHJ P,AIDC4 + MOVEI A,"O ;YES, A + POPJ P, ;LOOP BACK + +DISTBL: POPJ2,,POPJ2 ;IGNORE 0 + REPEAT 6,LC DISBLB + LC 63 ;BELL + LC ADISBS + AC DSATB + AC DISALF + LC DISBLB + LC DISBLB + AC ADISCR + REPEAT 33-16,LC DISBLB + LC 47 ;ALT MD (RT ARROW) + REPEAT 4,LC DISBLB + AC 40 + REPEAT 133-41,UC <.-DISTBL>&77 + LC 53 + LC 52 ;BACKSLASH + LC 54 + LC 100+67 + LC 60 + LC 100+66 + REPEAT 173-141,LC <.-DISTBL-140> + LC 55 + LC 62 ;VERTICAL BAR=174 + LC 56 + LC 43 ;TILDE=176 + LC DISRUB +IFN .-DISTBL-200,PRINTX /DISTBL LOSS/ + + +DINCT: 10 + 2 + 14 + 3 + 12 + 16 + 17 + 13 + + + +REPEAT NDOPL, CONC AIER,\.RPCNT+1,: JSP D,AIER + +AIER: HRRZ R,UUAC(U) + ADDI R,IOCHNM(U) + MOVEI D,1+1-AIER1(D) + LSH D,6+18. + IORM D,IOCHST-IOCHNM(R) + MOVE T,AIDPCP + UMOVEM C,(T) + JRST IOCERR +] + +IFN VIDP,[ +; +SUBTTL NEW VIDISECTOR ROUTINES +; +TVCO: HLRZ D,C + SKIPA Q,[TVCOBK] +NVIDI: MOVEI Q,NVDOBK + PUSH P,R + PUSH P,[NVIDI2] + JRST STDOP1 + +NVIDI2: JRST POPAJ + POP P,R + PUSHJ P,NVDGET + JRST NVIDI3 +NVIDI1: MOVEM A,(R) + CAIN Q,TVCOBK + AOS NTVCOS + CAIN Q,TVCOBK + TLNE C,1 ;ONLY DO IF TVC OUTPUT OPEN + PUSHJ P,TVCNOS + JRST POPJ1 + +NVIDI3: PUSHJ P,OPNL25 + JRST NVDCLS + +NVDOBK: 1,,NVDUSR + NVIDOP,,BNVIDO + +BNVIDI: JSP Q,WRDBT +NVIDIT: SKIPGE NVDIFL + PUSHJ P,UFLS + UMOVE B,(C) + MOVEM B,NVDCOR + CONO PI,OMXOFF + SETOM NVDIFL + PUSHJ P,NVDVS1 ;TURNS OMPCH ON + SKIPGE NVDIFL + PUSHJ P,UFLS + MOVE B,NVDCOR + UMOVEM B,(C) + POPJ P, + +RNVDIB: JSP Q,WRDBT +RNVDIU: SKIPN NVDCNT ;TVC INPUT + JRST RNVDO2 + XCTR XRW,[MOVES (C)] ;MAKE SURE GOING TO WIN + MOVE T,NVDOPT + CAMN T,NVDVPT + PUSHJ P,UFLS + MOVE B,(T) + SOS NVDCNT + UMOVEM B,(C) + AOS T,NVDOPT + CAIL T,NVDBUF+NVDLNG + MOVEI T,NVDBUF + MOVEM T,NVDOPT + POPJ P, + +TVCOBK: 3,,NVDUSR + DNVDIU,,DNVDOU + DNVDIB,,DNVDOB + +TVCCLS: SOSGE NTVCOS + PUSHJ P,TVCINI ;TRY TO AVOID GARBAGE PNT PART WAY VIDISECTED +NVDCLS: SOSGE NVDUSE + PUSHJ P,VIDFLS + POPJ P, + +TVCNOS: LDB A,[251700,,C] ;TVC OPEN ROUTINE +TVCN1: TRZ A,703000 ;DONT LET LOSER FOOL AROUND + IORI A,NVDCHN_15. + LDB B,[20300,,A] ;DCO + JUMPE B,TVCO3 + CAIN B,7 + JRST TVCO6 ;DCO DISABLED FOR DCL=7 + IMUL B,[-100] +TVCO4: ADDI B,1300 +TVCO7: MOVEM B,NVDDK ;DARK VALUE CORRECT FOR DCO + MOVE TT,A + XOR TT,TVCONO + TRNE T,340 + JRST TVCO5 ;CHANGE IN VIDI SELECTION STATUS +TVCO5A: MOVEM A,TVCONO + POPJ P, + +TVCO3: LDB T,[200,,A] ;CONF + CAIN T,3 + MOVNI B,100 ;IF CONF=3 & DCO=0 VALUE 100 LESS THAN PREDICTED ABOVE + JRST TVCO4 + +TVCO5: TRZ A,700000 ;CLEAR CHNL OUT OF TVCONO + CONO NVDX,(A) ;START RLYS + MOVEI T,2 + SKIPL TVQBLK+1 ;WAIT IF PREV RQ NOT SATISFIED + PUSHJ P,UFLS + PUSHJ P,CLQADD ;RQ LATER TRANSFER TO VIDD1 + TVQBLK + JRST TVCO5A + +TVCO6: LDB T,[200,,A] ;CONF + IMUL T,[-200] ;CALCULATE WHEN OVF HAPPENS + ADDI T,2000 + JRST TVCO7 + +TVCINI: CONO PI,OMXOFF + SETZM NVDCNT + MOVE T,NVDIPT + MOVEM T,NVDVPT + MOVEM T,NVDOPT + MOVE T,NVDBKR + CAIN T,1 + SETOM NVDBKR + JRST OMXONJ + +VIDFLS: SKIPL NVDUSE ;SKIP IF OPENS ON NVD, .VSCAN + POPJ P, + DATAO DSDEV,[DSNVID] ;DEASSIGN VIDI + SETOM NVDUSR + POPJ P, + +NVDGET: CONO NVDX,@TVCONO ;TRY TO ASSIGN BAT + CONI NVDX,TT + JUMPE TT,CPOPJ + JRST POPJ1 + + +NVDBRK: MOVE T,NVDBKR + JRST NVTAB(T) ;DISPATCH ON REASON FOR BREAK + + JRST NEWORK ;STARTUP OF SOME NEW FUNCTION +NVTAB: JRST SCNB1 ;NEW VSCAN POINT + JRST TVB1 ;NEW TVC POINT + JRST INVD1 ;NEW NVD PNT +; JRST DRET ;NEW DAEMON POINT + +TVB1: DATAI NVDX,@NVDVPT ;READ IN OF TV POINT + CONI NVDX,T + LSH T,-11. + DPB T,[220200,,@NVDVPT] ;READ ALL RELAVENT INFO FROM BAT + TRNE T,3 + JRST TVB2 ;DCO OR OVFL + MOVE T,@NVDVPT + ANDI T,1777 + CAMLE T,NVDDK + JRST TVB2 ;DUE TO NOISE/PROB DARKER THAN DCO +TVB3: AOS T,NVDVPT + CAIL T,NVDBUF+NVDLNG + MOVEI T,NVDBUF + MOVEM T,NVDVPT ;INCREMENT TO NEXT POINT + JRST NEWORK + +TVB2: MOVE T,NVDDK + DPB T,[1200,,@NVDVPT] + DPB T,[240600,,@NVDVPT] ;PUT IN FLOATING PART + LSH T,-6 + DPB T,[330400,,@NVDVPT] + JRST TVB3 + +TVNEXT: MOVE T,NVDVPT + CAMN T,NVDIPT + JRST TVCFIN + MOVEI T,1 ;SET UP FOR NEXT TV POINT + MOVEM T,NVDBKR + MOVE T,NVDVPT + HLRZ T,@NVDVPT + CONO NVDX,@TVCONO + DATAO NVDX,T + EXCH T,VIDXOL + SUB T,VIDXOL + MOVMM T,VIDTEM + HRRZ T,@NVDVPT + DATAO NVDY,T + EXCH T,VIDYOL + SUB T,VIDYOL + MOVMS T + CAMGE T,VIDTEM + MOVE T,VIDTEM + CAIL T,1000 + JRST TVB5 + DATAO NVDT,[-4] +NVDBR4: JRST OMXRET + +TVB5: TLC T,232000 ;CALCULATE SETTLING TIME + FAD T,T + LDB T,[330400,,T] + DATAO NVDT,SETLL-10.(T) + JRST NVDBR4 + +SETLL: ;SETTLING TIME IN 10 MICROSEC + -6 ;DEFLECTING 512 - 1023 + -10 ;1024 - 2047 + -16 ;2048 - 4095 + -26 ;4096 - 8191 + -45 ;8192 - 16383 + -70 ;16384 + +RNVDOB: JSP Q,WRDBT +RNVDOU: MOVEI T,NVDLNG-1 ;TO PREVENT HANGUP AT PI ON WRAPAROUND + CAMG T,NVDCNT + JRST RNVDO2 + UMOVE B,(C) + MOVEM B,@NVDIPT + AOS NVDCNT + AOS T,NVDIPT + CAIL T,NVDBUF+NVDLNG + MOVEI T,NVDBUF + MOVEM T,NVDIPT + CONO PI,OMXOFF + SETOM TVFLG +NVDVS1: MOVE T,TVCONO + SKIPGE NVDBKR + CONO NVDX,2000(T) + JRST OMXONJ + +RNVDO2: POP P,T ;CALLED FROM RNVDI ALSO + ANDI T,-1 + CAIE T,WRDBRT + JRST IOCER9 + POPJ P, + +NEWORK:; SKIPGE DAEMFL +; JRST DNEXT + SKIPL SCNUSR ;DEFLECT FOR NEW VSCAN POINT + JRST SCNB2 + SKIPGE NVDIFL ;NVD + JRST INVD2 + SKIPGE TVFLG ;DEFLECT FOR NEW TVC POINT + JRST TVNEXT + SETOM NVDBKR ;NO MORE CROCKS FOR VIDISECTOR TO DO + MOVE T,TVCONO + TRZ T,703000 ;SAVE STATE OF VIDI SELECT + CONI NVDX,A + CONO NVDX,(T) + SKIPN A + DATAO DSDEV,[DSNVID] ;RE DEASSIGN VIDI IF WAS DEASSIGNED + ;(CONO DID CLEAR PIA, DONE, AND SET MODE FLOPS THO) + JRST OMXRET + +TVCFIN: SETZM TVFLG + JRST NEWORK + +INVD1: DATAI NVDX,NVDCOR + CONI NVDX,T + LSH T,-11. + DPB T,[220200,,NVDCOR] + SETZM NVDIFL + JRST NEWORK + +INVD2: MOVEI T,2 + MOVEM T,NVDBKR + CONO NVDX,@TVCONO + HLRZ T,NVDCOR + DATAO NVDX,T + HRRZ T,NVDCOR + DATAO NVDY,T + DATAO NVDT,[-7] + JRST NVDBR4 + +SUBTTL NEW VIDISECTOR ROUTINES - .VSTST + +AVSTST: UMOVE A,(J) + CAME U,NVDUSR + JRST AVST4 + JUMPE A,AVST1 ;READ CURRENT STATE + JUMPL A,AVST2 +AVST3: SKIPL SCNUSR ;HANGUP TILL VSCAN FINISHED + PUSHJ P,UFLS +AVST2: +SCNSTP: CONO PI,OMXOFF ;FLUSH VSCAN ENTIRELY + SKIPGE SCNUSR + JRST OMXONJ ;ALREADY FINISHED + SETOM SCNUSR + SOSGE NVDUSE + SETOM NVDUSR + SKIPN NVDBKR ;IGNORE VSCAN POINT IN PROGRESS IF ANY + SETOM NVDBKR +VSLS2: PUSH P,A + PUSH P,B + PUSH P,W + MOVSI B,-1 + MOVSI W,-2 +SCNS2: LDB A,VEXT(W) + TRNN A,600000 + JRST SCNS4 + ANDI A,PMRCM + ADDM B,MMSWP(A) +SCNS4: MOVEI A,0 + DPB A,VEXT(W) + AOBJN W,SCNS2 + MOVE A,USER + SPM UPGML(A) + LPMR UPGML(A) + POP P,W + POP P,B + POP P,A + PUSHJ P,VIDFLS + JRST OMXONJ + +AVST4: JUMPE A,ILUUO + POPJ P, + +AVST1: SKIPGE SCNUSR + POPJ P, + MOVE A,NVDPTR + SUBI A,400000+VSB1*2000 + JRST APTUAJ + +;CHECK TO SEE IF MEM PROTECT STILL OK +SCNACR: CAMN U,SCNUSR + POPJ P, + AOS (P) + JRST SCNSTP + +;STOP SCAN +SCNSTC: CONO NVDX,0 + POPJ P, + +;RESTART SCAN AFTER STOP FOR SHUFFLING +SCNRST: CONO NVDX,NVDCHN_17 + POPJ P, + + +SUBTTL NEW VIDISECTOR ROUTINES - .VSCAN + +AVSCAN: XCTR XRW,[MOVES (C)] + XCTR XRW,[MOVES 12(C)] + SKIPL SCNUSR + PUSHJ P,UFLS + CONO PI,CLKOFF + CAME U,NVDUSR + SKIPGE NVDUSE + AOSA NVDUSE + JRST ILUUO + MOVEM U,NVDUSR + CONO PI,CLKON + PUSHJ P,NVDGET + JRST VSLOS +A.VS1: SETZM BATMXA + XCTR XRW,[HLRZ A,2(C)] + MOVEM A,NVDCNX + MOVEM A,NVDCN3 + XCTR XRW,[HRRZ A,2(C)] + MOVEM A,NVDCNY +IRPS XY,,X Y P X Y P,A12,,1 1 1 2 2 2,N,,3 6 11 4 7 12,YX,,X X X Y Y Y + UMOVE A,N(C) + IDIV A,NVDCN!YX + MOVEM A,BATD!XY!A12 +TERMIN +IRP XY,,[P,X,Y]ADR,,[[[1,,]],5(C),10(C)] + MOVE A,BATD!XY!1 + ADD A,BATD!XY!2 + ASH A,-1 +IFE .IRPCNT, ADD A,ADR +IFN .IRPCNT, XCTR XRW,[ADD A,ADR] + MOVEM A,BAT!XY!1 + MOVEM A,BAT!XY!2 + IFN .IRPCN,[IDIV A,BATP1 + MOVEM A,NVID!XY] +TERMIN + XCTR XRW,[HRRZ B,1(C)] + LDB A,[121000,,B] + CAIL A,376 + JRST VSLOS + MOVEI W,0 + PUSHJ P,VSMS1 + MOVEI W,1 + PUSHJ P,VSMS1 + SPM UPGML(U) + LPMR UPGML(U) + HRRZ R,B + ANDI R,776000 + ADDI R,4000-2000 + XCTR XRW,[HLRO D,1(C)] + MOVE A,NVDCNX + IMUL A,NVDCNY + JUMPLE A,VSLOS ;SIZE OF RASTOR + MOVNS D ;PLUS COUNT + CAMLE A,D + JRST VSLOS ;WON'T FIT + CAML A,R + JRST VSLOS ;WON'T FIT IN EXEC PGS + ADD A,B + MOVEM A,BATMXA + LDB A,[121000,,A] + PUSHJ P,UPLC + LDB A,T + TRC A,600000 + TRCE A,600000 ;SKIP ON R/W/F + JRST VSLOS ;TOP PAGE LOSES + ANDI B,1777 + ADDI B,400000+VSB1*2000 + MOVEM B,NVDPTR + XCTR XRW,[HRRZ A,(C)] + PUSHJ P,TVCN1 + MOVE A,[JRST SCNG1] + MOVEM A,SCNB1A + CONO PI,OMXOFF + MOVEM U,SCNUSR + MOVE A,TVCONO + SKIPGE NVDBKR + CONO NVDX,2000(A) + CONO PI,OMXON + XCTR XRW,[SKIPL (C)] + POPJ P, + JRST AVST3 + +VSLS3: PUSHJ P,LSWPOP +VSLOS: PUSHJ P,VSLS1 + JRST ILUUO + + +VPGLOS: PUSHJ P,VSLS1 + PUSHJ P,TPFLT + JRST UUOTRO + +VSLS1: SOSGE NVDUSE + SETOM NVDUSR + CONO PI,OMXOFF + JRST VSLS2 + +VSMS1: PUSHJ P,SWTL + CIRPSW + LDB A,[121000,,B] + ADD A,W + MOVEM A,VSMPG + PUSHJ P,UPLC + CONO PI,CLKOFF + LDB A,Q + JUMPE A,VSMS2 ;NO ACCESS + CAIN A,-1 + JRST VSLS3 + LDB A,T + TRNN A,600000 + JRST VSMS3 ;SWAPPED OUT + TRNN A,400000 + JRST VSLS3 ;RD ONLY + TRO A,200000 +VSMS2: DPB A,T ;CHANGE R/W/F TO R/W + LDB TT,VEXT(W) + DPB A,VEXT(W) + MOVSI Q,1 + ANDI A,PMRCM + SKIPE A + ADDM Q,MMSWP(A) + JUMPE TT,VSLS4 + ANDI TT,PMRCM + MOVSI Q,-1 + ADDM Q,MMSWP(TT) +VSLS4: PUSHJ P,LSWPOP + JRST CLKONJ + +VSMS3: PUSHJ P,LSWPOP + MOVE A,VSMPG + SOSGE NVDUSE + SETOM NVDUSR + PUSHJ P,CWAIT + SKIPL VIDSWI + MOVEM U,VIDSWI + MOVEM A,VIDSPG + SKIPL VIDSWI + PUSHJ P,UFLS + SUB P,[1,,1] + JRST AVSCAN + SCNB1: DATAI NVDX,@NVDPTR + CONI NVDX,T + LSH T,-11. + DPB T,[220200,,@NVDPTR] + TRNE T,3 + JRST SCNB1C ;OVF OR DCO? + MOVE T,@NVDPTR + ANDI T,1777 + CAMG T,NVDDK ;OR VALUE GREATER THAN DCO LEVEL + JRST NEWORK +SCNB1C: MOVE T,NVDDK + DPB T,[1200,,@NVDPTR] + DPB T,[240600,,@NVDPTR] ;PUT IN FLOATING PART + LSH T,-6 + DPB T,[330400,,@NVDPTR] + JRST NEWORK + +SCNB2: CONO NVDX,@TVCONO ;SETUP FOR NEXT VSCAN POINT + DATAO NVDX,NVIDX + DATAO NVDY,NVIDY + MOVE T,NVIDX + EXCH T,VIDXOL + SUB T,VIDXOL + MOVMM T,VIDTEM + MOVE T,NVIDY + EXCH T,VIDYOL + SUB T,VIDYOL + MOVMS T + CAMGE T,VIDTEM + MOVE T,VIDTEM + CAIL T,1000 + JRST SCNT5 + DATAO NVDT,[-4] +SCNT4: CLEARM NVDBKR + EBLK +SCNB1A: JRST SCNG1 ;OR AOS (AOSA) NVDPTR + BBLK + JRST SCNS1 ;HOMO LINEAR FROB +SCNB1B: SOSG NVDCNX ;SIMPLE MINDED + JRST SCNB3 +IRPC X,,XY + MOVE T,BATD!X!1 + ADDB T,BAT!X!1 + HLRZM T,NVID!X +TERMIN +SCNBX: JRST OMXRET + +SCNT5: TLC T,232000 ;CALCULATE SETTLING TIME + FAD T,T + LDB T,[330400,,T] + DATAO NVDT,SETLL-10.(T) + JRST SCNT4 + +SCNB3: SOSG NVDCNY + JRST SCNB4 +IRPC X,,XY + MOVE T,BATD!X!2 + ADDB T,BAT!X!2 + MOVEM T,BAT!X!1 + HLRZM T,NVID!X +TERMIN + + MOVE T,NVDCN3 + MOVEM T,NVDCNX + JRST SCNBX + +SCNB4: SKIPL NVDCNY ;WAIT FOR LAST DATAO TO RETURN A POINT + JRST SCNBX + SETOM SCNUSR + SOSL NVDUSE + JRST NEWORK + SETOM NVDUSR + DATAO DSDEV,[DSNVID] ;DEASSIGN BAT + MOVSI B,-1 + MOVSI W,-2 +SCNB4B: LDB A,VEXT(W) + TRNN A,600000 + JRST SCNB4A + ANDI A,PMRCM + ADDM B,MMSWP(A) +SCNB4A: MOVEI A,0 + DPB A,VEXT(W) + AOBJN W,SCNB4B + JRST NEWORK + +SCNS1: MOVEM U,NVDTMU + SOSG NVDCNX + JRST SCNS3 +IRPC X,,PXY + MOVE T,BATD!X!1 + ADDB T,BAT!X!1 + IFN .IRPCN,[IDIV T,BATP1 + MOVEM T,NVID!X] +TERMIN + +SCNBX1: MOVE U,NVDTMU + JRST SCNBX + +SCNS3: SOSG NVDCNY + JRST SCNB4 +IRPC X,,PXY + MOVE T,BATD!X!2 + ADDB T,BAT!X!2 + MOVEM T,BAT!X!1 + IFN .IRPCN,[IDIV T,BATP1 + MOVEM T,NVID!X] +TERMIN + MOVE T,NVDCN3 + MOVEM T,NVDCNX + JRST SCNBX1 + +SCNG1: MOVSI T,(AOSA) + SKIPN BATDP1 + SKIPE BATDP2 + MOVSI T,(AOS) + HRRI T,NVDPTR + MOVEM T,SCNB1A + TLNN T,(AOSA-AOS) + JRST SCNS1 + JRST SCNB1B + + +SUBTTL NEW VIDISECTOR ROUTINES + +EBLK + +NVDIPT: NVDBUF ;POINTER TO INSERT IN BUF +NVDVPT: NVDBUF ;POINTER TO WORD BEING VIDISECTED +NVDOPT: NVDBUF ;POINTER TO WITHDRAW FROM BUF +NVDCNT: 0 ;NUMBER PTS IN BUF +NVDBUF: BLOCK NVDLNG +VIDSTRT: 0 +LBTCNO: 0 ;LAST CONO TO BAT +NVDIFL: 0 ;+=> RQ TO READ NVD PNT +NVDCOR: 0 ;NVD DEV, COORDINATES TO PI, READ DATA FROM PI +NTVCOS: -1 ;# TVC OPENS + +IRPC X,,XYP + IRPC N,,12 + BAT!X!!N: 0 + BATD!X!!N: 0 + TERMIN +TERMIN + +NVDCNX: 0 +NVDCNY: 0 +NVDCN3: 0 +NVIDX: 0 +NVIDY: 0 +BATMXA: 0 +NVDPTR: 0 +NVDTMU: 0 +SCNUSR: -1 ;USER IN CURRENT .VSCAN, -1 .VSCAN FREE +SCNREL: 0 +TVCONO: 0 ;CONO FOR TVC DEVICE AND VSCAN (NORM HAS CHNL BUT NOT IF IN VIDDLY) +NVDDK: 0 ;-1=>VID VALUE CORRESP TO DCO +TVFLG: 0 ;-1=>TVC WORK IN PROGRESS +NVDBKR: -1 ;REASON LAST POINT READ IN, DISPATCH ADDRESS FOR INTS + ;-1 NONE 0 VSCAN 1 TVC 2 NVD +TVQBLK: 0 ;CLOCK QUEUE BLOCK + -1 + JRST VIDD1 +VIDXOL: 0 ;OLD VIDI CORDS +VIDYOL: 0 ;OLD VIDI CORDS +VIDTEM: 0 ;LARGEST DELTA +VSMPG: 0 +VEXT: .VSB1+EXEUMP + .VSB2+EXEUMP + +BBLK + +VIDD1: MOVEI A,NVDCHN_15. + IORB A,TVCONO ;RESTORE CHNLS TO TVCONO + CONO NVDX,2000(A) ;CAUSE EVENTUAL VIDI INT TO SEE IF ANYTHING YO DO + JRST CLQRET ;RETURN TO CLOCK ROUTINE +] + +SUBTTL VIDEO SWITCH AND VIDEO BUFFER ROUTINES + +;SYSTEM CALLS FOR HACKING THE VIDEO SWITCH AND VIDEO BUFFERS. + +IFE N11TYS,[ +NVDBF==OPNL1 +NVIDSW==OPNL1 +] + +IFN N11TYS,[ + +VBDFLS: PUSH P,B + PUSH P,T + PUSH P,I + PUSH P,Q + PUSH P,C + MOVSI B,-MXVBN ;FLUSH ALL BUFFERS ASSIGNED TO JOB IN U +VBDFL3: CAMN U,VBAST(B) + JRST VBDFL1 +VBDFL2: AOBJN B,VBDFL3 + SKIPE NVDBA(U) + JRST 4,. +VBDFL6: POP P,C + POP P,Q + POP P,I + POP P,T + POP P,B + POPJ P, + +VBDFL1: JSP Q,11CM1 + JRST VBDFL4 ;LOST.. + PUSH P,B + JSP Q,NVDBU2 ;FLUSH BUFFER + JFCL ;PDP11 TIMED OUT + JFCL ;PDP11 GAVE NEGATIVE REPLY + POP P,B + JRST VBDFL2 + +VBDFL5: CAMN U,VBAST(B) +VBDFL4: SETOM VBAST(B) + AOBJN B,VBDFL5 + CLEARM NVDBA(U) + JRST VBDFL6 + +;VIDBUF SYSTEM CALL - ASSIGN OR DEASSIGN VIDEO BUFFERS +NVDBF: JSP Q,11CM1 ;SET UP ACS, LOCK SWITCH. + JRST OPNL7 ;LOST + JUMPGE A,NVDBU1 ;JUMP IF DEASSIGN COMMAND + MOVSI C,2_<16.+4-18.> + JSP Q,NVDCMD ;TELL PDP11 TO ASSIGN BUFFER. + JRST OPNL7 ;PDP11 TIMED OUT + JRST OPNL6 ;PDP11 GAVE NEGATIVE REPLY + HRRZ A,C + CAIL A,MXVBN + JRST OPNL6 ;PDP11 HAS MORE VIDEO BUFFERS THAN WE DO + AOS NVDBA(U) ;WON + MOVEM U,VBAST(A) + JRST POPJ1 + +NVDBU1: MOVE B,A ;DEASSIGN VIDEO BUFFER + CAIGE B,MXVBN ;CHECK THAT VIDEO BUFFER IS LEGAL + CAME U,VBAST(B) ;AND BELONGS TO THIS JOB + JRST OPNL33 ;NOT LEGAL VIDEO BUFFER NO + JSP Q,NVDBU2 ;TELL PDP11 TO FREE THE BUFFER. + JRST OPNL7 ;TIMED OUT + JRST OPNL23 ;GAVE NEG REPLY + JRST POPJ1 ;WON + +EBLK +;TABLE OF VIDEO BUFFER ASSIGNMENTS. +VBAST: REPEAT MXVBN,-1 ;-1 => FREE, ELSE USR IDX. +11CVSR: -1 ? 0 ;SWITCH TO LOCK TO PROTECT 10-TO-11 COMMAND VARS. +BBLK + +;VIDSW SYSTEM CALL - SET VIDEO SWITCH. +NVIDSW: JSP Q,11CM1 ;LOCK SWITCH, ETC. + JRST OPNL7 + LSH A,4.+16. + LSH B,4.+16. + MOVEM A,1(I) + MOVEM B,2(I) + MOVSI C,1_<16.+4-18.> + JSP Q,NVDCMD + JRST OPNL7 ;TIMED OUT + JRST OPNL23 ;PDP11 DIDN'T FEEL LIKE SWITCHING THE SWITCH + JRST POPJ1 + +NVDBU2: SETOM VBAST(B) ;GIVE DEASSIGN COMMAND TO 11 + LSH B,4.+16. + MOVEM B,1(I) ;WHICH ONE TO DEASSIGN + SOSGE NVDBA(U) + JRST 4,. + MOVSI C,3_<16.+4-18.> +;GIVE COMMAND IN C TO PDP11, WAIT, RETURN (Q) IF 11 TIMES OUT, +;1(Q) IF 11 GIVES NEGATIVE REPLY AND 2(Q) IF SUCESSFUL +;IN ANY CASE, SWITCH IS UNLOCKED +;ASSUMES ARGS ALREADY SET UP, AND 11CVSR LOCKED. +NVDCMD: MOVEM C,(I) ;STORE COMMAND-TYPE, TELLING PDP11 TO GO. +NVDCM1: CAME C,(I) + JRST NVDCM2 ;IT'S FINISHED, WE WIN. + SOJG T,NVDCM1 ;LOOP FOR A WHILE, + PUSHJ P,LSWPOP + JRST (Q) ;FAIL - 11 TIMED OUT + +NVDCM2: MOVE C,1(I) ;RETURNED ARG IN CASE OF ASSIGN VIDEO BUFFER + LSH C,-4.-16. + SKIPGE (I) ;PDP11 FINISHED: DID COMMAND SUCCEED? + AOS Q ;YES SKIP EXTRA TIME + SETZM (I) + PUSHJ P,LSWPOP + JRST 1(Q) + +;LOCK SWITCH AND SET UP.. RETURN TO (Q) IF FAILS (SWITCH NOT LOCKED IN THAT CASE) +;RETURN TO 1(Q) IF SUCEEDS + +11CM1: SKIPL TT11P + JRST (Q) + PUSHJ P,SWTL + 11CVSR + LDB T,[061600,,TT11HA] + LDB I,[061600,,400000+TTPG0*2000(T)] + ADDI I,400000+TTPG0*2000 ;I HAS 10-TO-11 COMMAND BFR ADDR. + MOVSI T,1 ;# TIMES TO LOOP WAITING FOR 11 TO ACKNOWLEDGE +11CM2: SKIPG (I) + JRST 1(Q) ;11 READY FOR COMMAND. + SOJG T,11CM2 + PUSHJ P,LSWPOP + JRST (Q) ;TIMED OUT +] + +SUBTTL TABLET AND ROBOT CONSOLE + +IFN TABP,[ + +ITAB: IFE TABCLK,[ + SOSLE TABRTC + JRST ITAB6 + SKIPGE TABUSR + JRST ITAB7 + MOVE A,TABRTE + MOVEM A,TABRTC + CONO RBTCON,RTABC_3+TABCHN +] IFN TABCLK, CONO RBTCON,RTABC_3 + ROT A,36.*2 + DATAI RBTCON,A + JUMPL A,ITAB ;TRY AGAIN + LDB B,[400300,,A] + CAME B,TABLSZ + JRST ITAB2 + CAIN B,7 + JRST ITAB3 ;PEN OUT OF CONTACT + LDB B,[221400,,A] ;X + SUB B,TABLSX + MOVMS B + CAML B,TABDTA + JRST ITAB2 + LDB B,[1400,,A] + SUB B,TABLSY + MOVMS B + CAML B,TABDTA + JRST ITAB2 +ITAB3: AOS B,TABSMC + CAIL B,77 + JRST ITAB2 +ITAB5: IFN TABCLK,[ + MOVE T,TABRTE + MOVEI C,TABQBK + SKIPL TABUSR + JRST CLQREE + JRST CLQRET +] IFE TABCLK,[ + JRST OMXRET + +ITAB6: DATAI RBTCON,A ;FLUSH DATA + JRST OMXRET + +ITAB7: CONO RBTCON,0 + JRST OMXRET +] +ITAB2: MOVE B,TABSMC + DPB B,[140600,,TABLST] + SETZM TABSMC + HRRZM A,TABLSY + LDB B,[221400,,A] + MOVEM B,TABLSX + LDB B,[400300,,A] + MOVEM B,TABLSZ + EXCH A,TABLST + JUMPE A,ITAB5 ;JUST STARTING UP + MOVE B,TABCC + CAIL B,LTABBF + JRST ITAB4 ;FULL + MOVEM A,@TABIP + AOS TABCC + AOS B,TABIP + CAIL B,TABBFE + MOVEI B,TABBUF + MOVEM B,TABIP + JRST ITAB5 + +ITAB4: MOVSI B,(SETZ) ;SET DATA LOST + IORM B,TABLST + JRST ITAB5 + +] + +IFN RBTCP,[ + + ;ROBOT CONSOLE READ SWITCHES +ARBTC: UMOVE A,(J) + CONO PI,TABOFF + CONO RBTCON,RLTSWC_3+IFE TABCLK,TABCHN + ROT A,36.*2 + DATAO RBTCON,A + ROT A,36.*2 + DATAI RBTCON,A + CONO PI,TABON + UMOVEM A,(J) + POPJ P, + +;DATA FORM +;4.9 DATA LOST BEFORE THIS +;4.8-4.6 TAB "Z" +;4.5-4.4 USUSED +;4.3-3.1 TABLET X +;2.9-2.4 REPEAT COUNT +;2.4-1.1 TABLET Y + +TABO: PUSH P,[TABO1] + JSP Q,STDOPN + 1,,TABUSR + DTABUI,,DTABBI + +TABO1: POPJ P, ;OPEN LOST + SKIPE TABUSE ;OPEN WON + JRST POPJ1 ;NOT FIRST OPEN + LDB T,[250300,,C] + AOS T + MOVEM T,TABRTE ;TABLET RATE (IGNORE THIS MANY BETWEEN TAKES) + LDB T,[300600,,C] + MOVEM T,TABDTA ;DELTA FOR COORD TO BE DIFFERENT + PUSHJ P,TABCLR +IFE TABCLK, CONO RBTCON,RTABC_3+TABCHN +IFN TABCLK,[ PUSHJ P,CLQAD1 ;START UP CLOCK LEVEL + TABQBK +] JRST POPJ1 + +BTABI: UMOVE J,(C) ;INITIAL AOBJN PNT + JSP Q,WRDBT +UTABI: SKIPG TABCC ;TABLET .IOT + JRST TABI1 ;NO DATA AVAIL, SEE IF BEING ACCUMULATED +UTABI1: MOVE A,@TABOP + UMOVEM A,(C) + AOS T,TABOP + CAIL T,TABBFE + MOVEI T,TABBUF + MOVEM T,TABOP + SOS TABCC + POPJ P, + +TABI1: HRRZ T,(P) + CAIN T,WRDBRT + JRST TABI2 +TABI3: SKIPG TABCC + PUSHJ P,UFLS + JRST UTABI1 + +TABI2: XCTR XRW,[CAMN J,(H)] + JRST TABI3 ;NO WDS TRANSFERRED + SUB P,[1,,1] ;RETURN TO USER SOME HAVE BEEN TRANSFERRED + POPJ P, + +TABCLR: CONO PI,TABOFF + SETZM TABCC + MOVEI T,TABBUF + MOVEM T,TABIP + MOVEM T,TABOP + SETZM TABSMC + SETZM TABLST + CLEARM TABLSX + CLEARM TABLSY + CLEARM TABLSZ +IFE TABCLK, SETZM TABRTC + CONO PI,TABON + POPJ P, +EBLK + +TABBUF: BLOCK LTABBF +TABBFE: +TABOP: TABBUF ;OUTPUT PNTR (MP) +TABIP: TABBUF ;INPUT PNTR (PI) +TABCC: 0 ;ACTIVE WDS IN TAB BUFFER +TABSMC: 0 ;COUNT OF TIMES "SAME" DATA RECEIVED FOR TAB +TABLST: 0 ;LAST DATA +TABLSZ: 0 ;Z OF LAST DATA +TABLSX: 0 ;X +TABLSY: 0 ;Y +TABDTA: 0 ;DELTA FOR COORD TO BE DIFFERENT +TABRTE: 0 ;TABLET RATE (TAKE EVERY N'TH ONE) +IFN TABCLK,[TABQBK: 0 ;CLOCK QUEUE BLOCK + -1 + JRST ITAB +] +IFE TABCLK,[ +TABRTC: 0 ;COUNT WITHIN TABRTE +] + BBLK +] + IFN IMXP,[ + +SUBTTL INPUT MULTIPLEXOR ROUTINES + +IMPXO: CONI MPX,T + JUMPE T,OPNL25 + TRNN D,2 + JRST IMPXO2 ;READ AT MN PRGM + SKIPGE IMPXF ;IMAGE (READ AT PI) + SETOM MPXWF + PUSHJ P,IMXON +IMPXO2: AOS IMXNTO + HLL A,C + JSP Q,OPSLD3 + IMXDN,,BIMXDN + IMPXDN,,BIMPXD + +IMXON: AOSGE IMPXF + JRST 4,. ;SHOULD NOT HAVE BEEN LESS THAN -1 + PUSHJ P,CLQAD1 ;START CLOCK LEVEL + MPXBLK + POPJ P, + +BIMPXS: JSP Q,WRDBT +IMPXS: SKIPGE MPXWF + PUSHJ P,UFLS + UMOVE A,(C) + ANDI A,377 + CAILE A,LCHN + JRST IMPXS1 +AIMXW5: IDIVI A,3 + LDB A,IMPXT(B) + UMOVEM A,(C) + POPJ P, + +IMPXCL: TRNE A,4 ;SKIP ON WAS READING AT MP +IMXCL1: SOS IMPXF ;WAS READING AT PI + SOSGE IMXNTO + DATAO DSDEVN,[MPX] + POPJ P, + +IMPXRS: SETOM MPXWF + POPJ P, + +IMPXT: 301400,,MPXBUF(A) + 141400,,MPXBUF(A) + 1400,,MPXBUF(A) + +BIMXS1: JSP Q,WRDBT +IMPXS1: UMOVE A,(C) + TDZE A,[-400] + JRST IOCER4 +AIMXW4: MOVE T,MPXWF + CAILE A,LCHN + MOVNI T,2 ;CHNL NOT READ IN BY PI HACK +AIMXW2: SKIPL IMXSW + PUSHJ P,UFLS + CAME T,MPXWF + AOJGE T,AIMXW3 ;PI FROB HAS CYCLED (MAYBE) + AOSE IMXSW + JRST AIMXW2 ;READING IMX AT PI + DATAO MPX,A ;SELECT CHNL + CONO MPX,0 ;START CONVERSION + MOVEI B,62 + CONSO MPX,10 + SOJG B,.-1 + JUMPE B,IMPXFE + XCTR XRW,[DATAI MPX,(C)] +IMX1: SETOM IMXSW + POPJ P, + +AIMXW3: SKIPGE MPXWF + JRST AIMXW4 ;IT WAS JUST SETOMMED + JRST AIMXW5 ;HAS BEEN READ IN BY PI HACK SO GOBBLE DATA + +IMPXFE: XCTR XRW,[SETOM (C)] + JRST IMX1 + +IMPXSR: AOSE IMXSW + JRST MPXRT1 ;USING IMX AT MN PRGM LVL + MOVE T,[<-LCHN>/3-1,,MPXBUF-1] + MOVEM T,MPXPTR ;SET UP BLKI POINTER + MOVE T,[BLKI MPX,MPXPTR] + MOVEM T,IMXLC ;SET UP DC INTERUPT LOCN + MOVE T,[JSR MPXCYC] + MOVEM T,IMXLC+1 ;SET UP DC INT LOC+1 + DATAO MPX,[0] ;READ STARTING WITH CHNL 0 + CONO MPX,140+DCCHN + MOVEI T,5 ;12TH SEC +IFN ARMP,SKIPN ARMF + SKIPL POTCON + MOVEI T,2 ;1/30 SEC, HAIRY POTS + JRST .+2 +MPXRT1: MOVEI T,1 ;LOST RETRY IN 1/60 + MOVEI C,MPXBLK + SKIPL IMPXF + JRST CLQREE ;RE-ENTER RQ + JRST CLQRET ;RETURN + +EBLK + +OMXNTO: -1 +IMXNTO: -1 +IMPXF: -1 ;-1 IF MPX NOT RUNNING +MPXWF: 0 +MPXBLK: 0 ;CLOCK QUEUE BLOCK + -1 + JRST IMPXSR +MPXPTR: 0 +IMXST: 0 +IMXSW: -1 ;-1 IF IMX AVAIL +IMXTBB: LCHN +MPXBUF: BLOCK /3+1 +IMXTBE==.-1 + +IMXACS: BLOCK 20 +MPXCYC: 0 + +BBLK + + CONO MPX,0 + SETOM IMXSW + AOS MPXWF + MOVEM T,IMXST + MOVE T,[JSR MPXCYC] + MOVEM T,IMXLC + MOVE T,IMXST +; SKIPGE POTCON +; SKIPE ARMF +; JRST MPXCYG + JRST 12,@MPXCYC + +MPXCYG: MOVEM 17,IMXACS+17 + MOVEI 17,IMXACS + BLT 17,IMXACS+16 +IFN ARMP,[ + SKIPE ARMF + JRST SERVO +ARMSVR:] + SKIPL POTCON + JRST UPOTS +UPOTRT: MOVSI 17,IMXACS + BLT 17,17 + JRST 12,@MPXCYC +] + IFN OMXP,[ + +SUBTTL OUTPUT MULTIPLEXOR ROUTINES + +OMPXO: CONI OMPX,T + JUMPE T,OPNL25 + AOS OMXNTO + HLL A,C + JSP Q,OPSLD3 + OMPXDN,,BOMPXDN + OMXDN,,BOMXDN + +BOMXDS: +BOMPXS: JSP Q,WRDBT +OMXDS: +OMPXS: XCTR XRW,[DATAO OMPX,(C)] ;ZAP CHNL + POPJ P, + +OMPXCL: SOSGE OMXNTO + DATAO DSDEVN,[OMPX] + POPJ P, + +EBLK +OMXACS: BLOCK 20 + +OMPXBK: 0 +BBLK + MOVEM 17,OMXACS+17 + MOVEI 17,OMXACS + BLT 17,OMXACS+16 +IFN VIDP,[ + CONSZ NVDX,700000 + CONSO NVDX,1000 + JRST .+2 + JRST NVDBRK +] +IFN ARMP,[ + CONSZ TIPDEV,10 + JRST TIPBRK +] +IFN TABP,[ + CONSZ RBTCON,7 + CONSO RBTCON,10 + JRST .+2 + JRST ITAB +] +; MOVEI J,OMPCHN +; JSP E,SPUR ;SPURIOUS INT +OMXRET: MOVSI 17,OMXACS + BLT 17,17 + JRST 12,@OMPXBK +] + +SUBTTL MORSE CODE SENDER (COD DEVICE) + +IFN CODP,[ +; CODITC==CODBFL*5-1 ;WHEN TO TRY TO INTERRUPT + +CLKCOD: SETOM TT ;USED AS A FLAG + MOVE B,CODWD + LSH B,-1 +CLKCC3: CAIN B,1 + JRST CLKCC1 + LDB A,[100,,B] + EXCH A,LSTBIT + CAME A,LSTBIT + DATAO 70,LSTBIT + MOVEM B,CODWD + MOVE T,CODSPD + MOVEI C,CODTIM + JRST CLQTTR ;RE-ENTER OR NOT DEPENDING ON TT + +CLKCC1: MOVE A,CODCC + CAIL A,CODBFL*5 + JRST CLKCC5 +CLKCC8: AOS CODCC + ILDB B,CODPTR + MOVE A,CODPTR + CAMN A,[10700,,CODBUF+CODBFL-1] + HRRI A,CODBUF-1 + HRRM A,CODPTR + CAIL B,140 + JRST CLKCC2 + CAIGE B,40 + JRST CLKCC1 + MOVE B,CODTBL-40(B) + JRST CLKCC3 +CLKCC6: MOVE B,CDRUB + JRST CLKCC3 +CLKCC2: CAIN B,177 + JRST CLKCC6 + SUBI B,137 + MOVEM B,CODSPD + JRST CLKCC1 + +CLKCC5: +; CAIN A,CODITC +; JRST CLKCC7 + MOVEI B,2 + SETZM TT ;INDICATE IDLE + JRST CLKCC3 + +;CLKCC7: MOVE A,CODUSR ;GET INDEX OF USER +; MOVE B,CODITB ;GET CHANNELS OPEN MASK +; AND B,MSKST2(A) ;FIND OUT WHAT CODE CHANNELS ENABLED, +; MOVNM B,CODITD +; AND B,CODITD +; IORM B,IFPIR(A) ;AND REQUEST INTERRUPT ON LOWEST NUMBERED ONE +; JRST CLKCC8 ;SEND REMAINING CHARACTER(S) IN BUFFER + + ;RETURN HERE FROM STDOPN +CODO1: POPJ P, ;NON-SKIP RETURN + AOS (P) ;DO NOT CHANGE TO JRST POPJ1 AT END + MOVEI I,1 ;INDICATE "IOPOP" + + ;CODE DEVICE IOPUSH AND IOPOP ROUTINE (SETS INTERRUPT MASK) + +CODIOP: SUBI R,IOCHNM(U) ;GET "AC FIELD" (ROUTINES THAT NEED IT RESTORE R) + MOVE A,CHNBIT(R) ;SET UP INTERRUPT BIT + XCT CDPTBL(I) ;IORM OR ANDCAM TO CODITB + POPJ P, + +CDPTBL: ANDCAM A,CODITB ;IOPUSH AND CLOSE + IORM A,CODITB ;IOPOP AND OPEN + + ;COD CLOSE ROUTINE +CODCLS: MOVEI I,0 ;TO SIMULATE IOPUSH + PUSHJ P,CODIOP ;CLEAR RELEVANT INTERRUPT BIT + CONO PI,CLKOFF ;CLOSE, USE STANDARD SEQUENCE + SOSGE CODUSE + SETOM CODUSR + JRST CLKONJ + +SEND: SKIPGE C + SKIPA A,(C) + XCTR XRW,[MOVE A,(C)] ;UNIT OUTPUT + CAIA +BSEND: JSP E,NBTOCH ;BLOCK OUTPUT + ANDI A,177 + CAIN A,"S-100 + JRST CODSSS + SKIPE CODSSF + JRST CODSST + SKIPG CODCC ;WAIT FOR ROOM + PUSHJ P,UFLS + IDPB A,CODIPT + MOVE A,CODIPT + CAMN A,[10700,,CODBUF+CODBFL-1] + HRRI A,CODBUF-1 + HRRM A,CODIPT + SOS CODCC + MOVE T,CODSPD + PUSHJ P,CLQADD ;START UP CLOCK LEVEL + CODTIM + POPJ P, + +CODO: PUSH P,[CODO1] ;CODO1 SETS UP INTERRUPT BIT + JSP Q,STDOPN + 1,,CODUSR + CODDN,,CODBN + + +CODSSS: SETOM CODSSF + POPJ P, + +CODSST: SETZM CODSSF + SUBI A,137 + JUMPLE A,CPOPJ + MOVEM A,CODSPD + POPJ P, + +CODRS: CONO PI,CLKOFF + MOVEI A,CODBFL*5 + MOVEM A,CODCC + MOVE A,CODIPT + MOVEM A,CODPTR + JRST CLKONJ + +CODFIN: MOVE T,CODBFL*5 ;.CALL FINISH + CAMLE T,CODCC + PUSHJ P,UFLS + POPJ P, + +EBLK +CODITB: 0 ;MASK OF CHANNELS OPEN, 1.1=>0 +CODITD: 0 ;RANDOM SCRATCH LOCATION +CODWD: 2 ;CURRENT WORD +CODTIM: 0 ;CLOCK QUEUE BLOCK + -1 + JRST CLKCOD +CODSPD: 3 ;CODE SPEED (SET FROM CHARS >=140) WPM= 75./(CODSPD) +CODCC: CODBFL*5 +CODPTR: 440700,,CODBUF +CODIPT: 440700,,CODBUF +LSTBIT: 0 ;FLUSH 60 CPS CHIRPS +CODSSF: 0 + +CODBUF: BLOCK CODBFL +BBLK + +DEFINE GCODE A +BIT=1 +WRD=0 +IRPC B,,[A] +IFSE B,-,[WRD=WRD+7*BIT +BIT=BIT_4] +IFSE B,.,[WRD=WRD+BIT +BIT=BIT_2] +IFSE B, ,[BIT=BIT_2] +TERMIN +WRD+4*BIT +TERMIN + +CODTBL: 20 + GCODE -.-.- + GCODE .-..-. + GCODE -. .-. + REPEAT 2,1 + GCODE . ... + GCODE .----. + REPEAT 2,GCODE -.--.- + GCODE .-.- + GCODE . ... + GCODE --..-- + GCODE -....- + GCODE .-.-.- + GCODE -..-. + IRP A,,[-----,.----,..---,...--,....-,.....,-....,--...,---..,----.] + GCODE A + TERMIN + GCODE ---... + GCODE -.-.-. + 27727 ;K WITH LONG LAST DAH + GCODE -...- + GCODE ...-.- + GCODE ..--.. + GCODE ...-. + IRP A,,[.-,-...,-.-.,-..,.,..-.,--.,....,..,.---,-.-,.-..,--,-.,---,.--.,--.- +.-.,...,-,..-,...-,.--,-..-,-.--,--..] + GCODE A + TERMIN + GCODE -.--. + GCODE -.-..-.. + GCODE .-.-. + GCODE .-... + GCODE -.. . + +CDRUB: GCODE ........ + +EXPUNGE WRD,BIT + +] + IFN PLTP,[ + +SUBTTL CALCOMP PLOTTER ROUTINES + +PLOT: SKIPGE C + SKIPA A,(C) + UMOVE A,(C) +PLOT1: SKIPE A + CAIN A,EOFCH + POPJ P, + SKIPG PLBFS + JRST PLOTW1 +PLOTW2: IDPB A,PLPTR + MOVE A,PLPTR + CAMN A,[600,,PLBUF+LPLBUF-1] + HRRI A,PLBUF-1 + HRRM A,PLPTR + SOS PLBFS + AOSN PLON + CONO PLT,SDS+PLTCHN + POPJ P, + + PUSHJ P,PLOTW3 +PLOTW1: PUSHJ P,UFLS + JRST PLOTW2 + +PLOTW3: SKIPG T,PLBFS + POPJ P, + CAIL T,LPLBUF*5 + JRST POPJ1 + JRST POPJ3 + +BPLOT: MOVEI E,PLOT1 + JRST NBTOCH + +PLOTO: MOVEI Q,PLOTOC + PUSHJ P,STDOPN + POPJ P, + AOS (P) +PLOTEL: ;TELL WHO'S USING THE PLOTTER + BUG INFO,[PLOTTER USER],SIXBIT,UNAME(U),SIXBIT,JNAME(U) + POPJ P, + +PLOTOC: 1,,PLTUSR + PLTDN,,PLTBN + +PLTRS: MOVEI A,LPLBUF*6 + MOVE B,PLPTR + CONO PI,LPTOFF + MOVEM A,PLBFS + MOVEM B,PLIPTR + JRST LPTONJ + +PLTBRK: MOVE A,PLBFS + CAIN A,LPLBUF*6 + JRST PLSTP + AOS PLBFS + ILDB A,PLIPTR + MOVE B,PLIPTR + CAMN B,[600,,PLBUF+LPLBUF-1] + HRRI B,PLBUF-1 + HRRM B,PLIPTR + ANDI A,77 + LSH A,3 + TRO A,SDC+PDC+SD+PLTCHN + TRNE A,PUP+PDN + TRC A,SD#PD + CONO PLT,(A) + JRST LPTRT3 + + +PLSTP: CONO PLT,SDC+PDC + SETOM PLON + JRST LPTRT3 + +EBLK +PLBUF: BLOCK LPLBUF +PLON: -1 +PLPTR: 440600,,PLBUF +PLIPTR: 440600,,PLBUF +PLBFS: LPLBUF*6 +IPL: SIXBIT /IPL/ ;FILE NAME 2 OF IPL JOB (USED FOR LOADING ASO JNAME OF IPL JOB) +IPLU: 0 ;USER INDEX OF IPL JOB IF IT EXISTS OR -1 IF IPL BEING LOADED + +;INTERPRET PLOTTER OPEN ROUTINE +BBLK +IPLO: CONO PI,CLKOFF + PUSHJ P,IPLST ;INITIATE LOADING OF IPL JOB + JRST IPLO1 + PUSHJ P,PLOTEL + CONO PI,CLKOFF + PUSHJ P,IPLWT ;WAIT FOR IPL JOB TO FINISH LOADING + PUSHJ P,UFLS + MOVE T,IPLU ;INDEX OF IPL JOB + SKIPE IOCHNM(T) + JRST IPLO2 ;IPL JOB OPNS CLA ON CNNL 0 + MOVE T,SV40(T) + CAME T,[.SLEEP 17,] ;IPL JOB DOES SLEEP 17, WHEN READY +IPLO2: JRST OPNL10 ;DEVICE NOT AVAILABLE + CONO PI,CLKON + MOVE T,IPLU + MOVE A,UNAME(T) ;SET UP CLI OPEN + MOVSI B,(SIXBIT /IPL/) + PUSHJ P,CLIO + POPJ P, + MOVE A,UTMPTR(U) + MOVE B,IPLU + MOVEM A,UTMPTR(B) + JRST POPJ1 + +IPLO1: PUSHJ P,UDELAY + JRST IPLO + +IPLST: SKIPL T,IPLU ;MAKE SURE IPL JOB NOT ALREADY BEING LOADED + PUSHJ P,IPLIN ;MAKE SURE IPL JOB NOT ALREADY IN + JRST POPJ1 ;DONT LOAD + HRROI T,IPL + CONO PI,UTCOFF + PUSHJ P,NUJBST + JRST UTCONJ + JRST UTCOJ1 + +;ROUTINE TO SEE IF IPL JOB WINS. CLKOFF OR CLKBRK IN PROGRESS +IPLWT: SKIPGE T,IPLU ;CHECK IPL JOB LOADING FLAG + POPJ P, ;IPL JOB STILL LOADING WAIT + PUSHJ P,IPLIN ;SEE IF IPL JOB IN CORE + SKIPE IOCHNM(T) ;SEE IF IPL JOB IN USE + JRST POPJ1 ;LOSE + MOVE T,SV40(T) ;SEE IF IPL JOB READY + CAMN T,[.SLEEP 17,] ;IPL JOB DOES .SLEEP 17, WHEN READY + AOS (P) ;READY WIN + POPJ P, ;NOT READY YET, WAIT + +IPLIN: PUSH P,U ;ROUTINE TO SEE IF IPL JOB IN. C(T)=C(IPLU), CLKOFF OR CLKBRK IN PROGRESS + CAML T,USRHI + JRST IPLIN1 ;USER VARIABLES SLOT FLUSHED + HLRO U,UNAME(T) + AOJN U,IPLIN1 ;UNAME OF IPL JOB IS -1 (IN LH) + MOVSI U,(SIXBIT /IPL/) + CAME U,JNAME(T) +IPLIN1: AOS -1(P) ;IPL JOB NOT IN, SO SKIP + POP P,U + POPJ P, + +] +;UTC MUST BE OFF! +NUJBST: MOVEI TT,MXCZS ;ENTRY FROM ELSEWHERE TO DO SIMILAR THINGS + SKIPL DEDTIM ;SKIP IF SYS DEAD + CAMG TT,UTTYCT + POPJ P, ;RING BUFFER FULL, WAIT + MOVEM T,@UTTYI + AOS UTTYCT + AOS TT,UTTYI + CAIL TT,UTTYS+MXCZS + MOVEI TT,UTTYS + MOVEM TT,UTTYI + SETOM 1(T) ;SET JOB LOADING FLAG + JRST POPJ1 + +SUBTTL PDP-6 AS INFERIOR + +IFN PDP6P,[ +;.IPDP CH, +;INTERRUPT THE PDP6, I/O CH SHOULD HAVE PDP6 OPEN AS INFERIOR +;THIS CALL DOESNT SKIP OR INTERRUPT TO THE USER + +AIPDP: MOVSI T,%CLS6 + SKIPGE A,(R) + TDNN T,CLSTB(A) + POPJ P, + CONO PI,LPTOFF + CONI DSDEV,T + ANDI T,7 + CONO DSDEV,20(T) + JRST LPTONJ + +;PDP-6 DEVICE +;INTERRUPT FROM PDP6, MAYBE GENERATE IO CHANNEL USER INTERRUPT + +DSDBRK: CONO DSDEV,10 ;TURN OFF FLAG + ;ALSO KEEP IT FROM INTERRUPTING FOR A WHILE + ;GETS TURNED ON AT DISMISS, SETOM PICLR AND SLOW CLK + SKIPGE A,PDPISR + JRST LPTRT3 ;NO ONE WANTS AN INT + MOVE B,PDPMSK + AND B,MSKST2(A) + MOVNM B,PDPTMP + AND B,PDPTMP + IORM B,IFPIR(A) ;GENERATE USER INT + JRST LPTRT3 + + ;PDP6 .OPEN ROUTINE (GET HERE FROM USR OPEN) + +PDPO: SKIPL PDP6UP ;MAKE IT EASY TO MARK PDP6 AS DOWN. + JRST OPNL10 + TLNN C,20 + JRST PDPO1 ;DON'T TRY TO ENABLE INTERRUPTS + TLO C,400000 ;TRY TO ENABLE INTERRUPTS + SKIPL PDPISR + CAMN U,PDPISR + JRST PDPO1 + JRST OPNL12 + +PDPO1: PUSH P,U + PUSHJ P,PDPO2 + JRST POPUJ + AOS -1(P) + POP P,U + SKIPL (R) + JRST .+3 + AOS PDPISE + MOVEM U,PDPISR;GOT IT AS INFERIOR + PUSHJ P,LSWPOP ;RELEASE TREESW + MOVEI I,1 ;DO "IOPOP" INTO CHNL + +PDPIOP: SKIPL (R) + POPJ P, ;NOT OPEN TO INTERRUPT + SUBI R,IOCHNM(U) + MOVE A,CHNBIT(R) + ADDI R,IOCHNM(U) ;RESTORE R + XCT PDPIOT(I) + POPJ P, + +PDPIOT: ANDCAM A,PDPMSK + IORM A,PDPMSK + +PDPCLS: MOVEI I,0 ;CLOSE + PUSHJ P,PDPIOP ;=> DO "IOPUSH" +PDPCL1: CONO PI,CLKOFF + SOSGE PDPUSE + SETOM PDPUSR ;LAST CHANNEL CLOSED + SKIPL (R) + JRST CLKONJ ;NOT INTERRUPT ENABLED THIS CHNL + SOSGE PDPISE + SETOM PDPISR ;LAST CHANNEL CLOSED + JRST CLKONJ + + +PDPO3: MOVEI U,(A) ;MAKE U INDEX OF SUPERIOR +PDPO2: SKIPL A,SUPPRO(U) ;GET POINTER TO SUPERIOR, SKIP IF TOP LEVEL + JRST PDPO3 ;TRY AGAIN + HLRZ D,C + TLO C,200000 ;SIGNAL PDP6 TO UBI ETC + JSP Q,STDOPN + 3,,PDPUSR + PDPUII,,PDPUIO + PDPBII,,PDPBIO + +;.UCLOSE PDP6 +PDPUCL: MOVSI C,%CLS6 ;GET PDP6 CLSTB BIT + MOVEI R,IOCHNM(U) ;GET PNTR TO USER'S IO CHNL AREA + HRLI R,-20 ;MAKE AOBJN PNTR TO ALL CHNLS + PUSHJ P,PDPCCK ;CHECK CHNL + PUSHJ P,PDPCZP ;CLOSE CHNL IF PDP6 OPEN ON IT + AOBJN R,.-2 ;REPEAT FOR ALL CHNLS + HRLI R,-LUIOP/2 ;MAKE AOBJN PNTR TO IO PDL (ADR ALREADY THERE) + PUSHJ P,PDPCCK ;CHECK ENTRY FOR PDP6 + PUSHJ P,PDPPZP ;CLEAR ENTRY IF PDP6 CHNL + AOJ R, ;INCR TO SKIP IOCHST ENTRY + AOBJN R,.-3 ;REPEAT FOR WHOLE IO PDL + POPJ P, ;ALL PDP6 CHNLS THIS JOB SHOULD NOW BE CLOSED + +PDPCCK: HRRZ B,(R) ;GET CLSTB INDEX FROM IOCHNM + TDNN C,CLSTB(B) ;IF NOT PDP6 CHNL + AOS (P) ;SKIP CLOSING CHNL + POPJ P, + +;CLOSE PDP6 USER CHNL +PDPCZP: PUSHJ P,PDPCLS ;ADJUST PDP6 VARS + JRST STDCLX ;CLOBBER CHNL & RETURN + +;CLEAR PDP6 IO PDL ENTRY +PDPPZP: PUSHJ P,PDPCL1 ;ADJUST PDP6 VARS (EXCEPT PDPMSK) + SETZB A,(R) ;CLEAR SAVED IOCHNM + DPB A,[4000,,1(R)] ;CLEAR SAVED IOCHST (SAVING CHNL # FOR .IOPDL) + POPJ P, + PDPCLR: OFFSET 20-. ;ROUTINE TO BE MOVED + CONO PI,11577 ;CLEAR PI + CONO 655550 ;CLEAR PROCESSOR + DATAO 20,.+1 ;RELEASE DEVICES + SETZ ;CLEAR 0, ALSO BIT FOR DEASSIGNMENT (^) + HRRZI 1,1 ;BLT POINTER 0,,1 + BLT 1,41 ;CLEAR AC'S, SELF, AND 41 +PDPCLE==. + OFFSET 0 ;BACK TO NORMAL +EBLK + +PDPTMP: 0 ;TEMP FOR INT +PDPMSK: 0 ;MASK OF INT BITS OF CHNLS OPEN + +BBLK + +PDPRST: PUSHJ P,MP6LD + MOVE C,[400020,,400021] + XCTR XW,[CLEARM 400020] + XCTR XBRW,[BLT C,437777] + MOVE C,[PDPCLR,,400020] + XCTR XBW,[BLT C,400000+PDPCLE-1] + MOVE C,[JRST 20] + UMOVEM C,400041 + PUSHJ P,UDELAY + UMOVE A,400041 + JUMPE A,PDPRS2 ;JUMP ON ROUTINE WON, DON'T HAVE TO CLEAR IT OUT + XCTR XW,[CLEARM 400020] + MOVE C,[400020,,400021] + XCTR XBRW,[BLT C,400041] +PDPRS2: JRST MPLDZ +];IFN PDP6P + +SUBTTL DL10MP SYSTEM CALL + +IFN DL10P,[ +;.CALL DL10MP +; ARG 1 - PAGE # +;CREATES A READ/WRITE, UNENCACHED, ABSOLUTE PAGE AT THAT POINT +;IN THE USER'S MAP. THE PAGE CONTAINS THE DL10 CONTROL AREA. +; VAL 1 - AOBJN POINTER TO DL10 CONTROL AREA WITHIN PAGE +; VAL 2 - POINTER TO 3 WORDS USED FOR PDP11 EXAMINE/DEPOSIT COMMANDS +; VAL 3 - POINTER TO FIRST FREE WORD WITHIN DL10 CONTROL AREA + +DL10MP: TDNE A,[-400] + JRST OPNL33 ;PAGE NUMBER TOO BIG + PUSHJ P,UPLC + LDB C,Q ;GET CIRC POINTER + CAIE C,-1 + JUMPN C,OPNL13 ;PAGE SLOT ALREADY IN USE + BUG INFO,[DL10MP BY],SIXBIT,UNAME(U),SIXBIT,JNAME(U) + MOVEI C,600000+ ;SUITABLE PTW + DPB C,T + MOVEI C,-1 ;ABS CIRC PNTR + DPB C,Q + CLRPGM (U) + LSH A,10. ;USER'S VIRTUAL ADDRESS + ADDI A,2000 + CAMLE A,HUSRAD(U) + MOVEM A,HUSRAD(U) + SUBI A,2000- ;VIR ADDR OF START OF DL10 CONTROL AREA + HRLI A,-100 ;SIZE OF DL10 CONTROL AREA + MOVEI B,DL10XD-DL10AR(A) + MOVEI C,DLXEND-DL10AR(A) + JRST POPJ1 +];DL10P + +SUBTTL TRAP DEVICE + +;.CALL TRPOPN +; ARG 1 - SPEC +; ARG 2 - CHANNEL NUMBER IN THAT JOB TO BE OPENED AS TRAP DEVICE +; ARG 3 - IOCHNM WORD (ONLY LH IS USED) +; ARG 4 - IOCHST WORD +;THIS GIVES THE INFERIOR A TRAP DEVICE CHANNEL, WHICH GIVES +;A %PITRP INTERRUPT ON MOST OPERATIONS. THE INFERIOR SIGNALS +;ITS DESIRE TO GET SUCH A CHANNEL BY OPENING THE TRAP DEVICE, +;WHICH ALSO GIVES A %PITRP INTERRUPT. +;TRPOPN IS ALSO USEFUL FOR STORING ERROR CODES INTO IOCHST OF AN ALREADY-OPEN TRAP CHANNEL + +TRPOPN: TDNE B,[-NIOCHN] + JRST OPNL14 ;BAD CHANNEL NUMBER + MOVE J,A + JSP T,NCORUI + JFCL +IFN PDP6P,[ + CAIN J,-1 + JRST OPNL34 +];PDP6P + JSP T,NCORWR + JRST OPNL31 ;CAN'T MODIFY JOB + ADDI B,IOCHNM(J) ;GET IOCHNM WORD ADDRESS + HRRZ T,(B) + CAIE T,DNTRAP + JUMPN T,OPNL13 ;FILE ALREADY EXISTS (YOU MUST CLOSE THE CHANNEL FIRST) + HRRI C,DNTRAP + MOVEM C,(B) + MOVEM D,IOCHST-IOCHNM(B) + JRST LSWPJ1 ;UNLOCK DIELOK, TAKE SUCCESS RETURN diff --git a/src/system/itsdis.50 b/src/system/itsdis.50 new file mode 100755 index 00000000..73302f14 --- /dev/null +++ b/src/system/itsdis.50 @@ -0,0 +1,320 @@ + +;DEVICE CODES +DIS==130 ;DISPLAY PROCESSOR +DISMAP==134 ;MEM PROT & REL +LIPSH==(040000) +NWSTK==LIPSH 3, + +ADSTAR: CONO PI,CLKOFF ;TURN OFF CLOCK TO PREVENT POSSIBLE GOBBLING BY ANOTHER USER + PUSHJ P,DISCHK ;CHECK IF THIS USER OWNS THE DISPLAY + JRST CLKONJ ;RESTART THE CLOCK + SETZM E.SPGH ; QSWI1 switch + SETZM E.SCLS ; clear clobber switch + SKIPL DISUSR ; no user + CAMN U,DISUSR ; skips if different index + JRST NOCLBR ; dont untie pages + MOVEM U,E.SCLS ; else remember to untie + SKIPA ; and dont hack disusr +NOCLBR: MOVEM U,DISUSR ;GIVE IT TO HIM IF NO ONE ELSE OWNS IT + CONO PI,CLKON ;RESTORE THE CLOCK + CONO DIS,5010 ;SET STOP, CLEAR PIA + XCTR XR,[HRRZ A,(C)] ; causes pg ld, fetches droot + HRRM A,DSTADD ; remember for restarts + XCTR XR,[MOVE B,(A)] ; load display page + PUSHJ P,SWTL ; circular switch gobble + CIRPSW + LSH A,-10. ; page number + SKIPN E.SCLS ; clobbering old user index ? + JRST RDSCLB ; if not, skip it + MOVE U,DISUSR ; old useri + PUSHJ P,E.SCLB ; untie pages + MOVEI U,0 + EXCH U,E.SCLS ; clear switch, fetch new usri + MOVEM U,DISUSR +RDSCLB: PUSHJ P,UPLC ; users pg n into circular pointer + PUSHJ P,CHACK ; go in circles + SKIPL C ; 4.9 implies real core in loop + JRST NOTIED ; if not, dont tie down -- still swapped out + MOVE T,J ; MEMPNT INDEX + MOVE E,D ; MMP INDEX + PUSHJ P,E.SPG1 ; go tie it down +NOTIED: PUSHJ P,LSWPOP ; clear switch + ; now set up E&S dbrs + MOVEI T,UDBR1A(U) + HRLI T,_1 ;DBL left 1 relative to 10 + MOVEM T,E.SPM+2 + HRRI T,UDBR2A(U) + MOVEM T,E.SPM+3 + + ; now start (or restart if from E.SPGI) E&S + +RDSTAR: CONO DIS,515330 ;RESET THE WORLD + SETOM E.SSYS ;FLAG=MAP ON (USER MODE) + CONO DIS,515330 ;CLEAR 3D CLIPPER + MOVEI I,1000 ;SET COUNT FOR TIMEOUT + MOVE H,DSTADD ; fetch c(0) + MOVEM H,E.SPM ; store in status block + MOVSI H,140000 ; status bits -- map high and low + MOVEM H,E.SPM+1 ; set status + SKIPA H,[-ADSTN,,ADSTL-1] + BLKO DIS,H + CONSO DIS,604000 ;SKIP IF DONE OR ERROR + SOJG I,.-1 + JUMPL H,.-3 + JUMPE I,CPOPJ ;FAIL IF TIME OUT ON START + CONSZ DIS,600000 ;CHECK FOR EXECUTIVE ERRORS + JRST ADXIT ;GIVE INTERRUPT, NO SKIP + + AOS (P) +ADCON1: CONO DIS,400 ;RUN +ADXIT: CONO DIS,222010+DISCHN ;ALARM+MPV+STOP+PIA + POPJ P, + +ADSTPX: CONSZ DIS,1040 ;FAIL TO SKIP IF MEM OR SEL STOP + JRST ILUUO ;ERROR IF STOP +ADSTOP: CAME U,DISUSR ;SKIP IF USER OF SCOPE + JRST URET ;EXIT IF NOT SCOPE USER +ADSTPY: CONO DIS,5000 ; IOSTOP+STOP.INT.OFF + CONO DIS,300 ;LR.PROG+CLR.HIT + CONSO DIS,640000 ;SKIP IF PARITY, NXM, MPV ON + JRST E.SUSM ;MAP IS STILL ON + CONO DIS,400000 ;CLEAR MASTER STUFF (TURNS OFF MAP) + CONO DIS,400000 ;CLEAR 3D CLIPPER + + AOS E.SSYS ;REMEMBER PAGING IS OFF +E.SUSM: CONSO DIS,4000 ;SKIP IF STOPPED AND READY + PUSHJ P,UFLS ;ELSE WAIT UNTIL READY + POPJ P, + +ADCONT: PUSHJ P,ADSTPX ;ILLEGAL IF MEM OR SEL STOP + PUSHJ P,E.SFU ; force user mode if necessary + POPJ P,0 ; gross lossage (hardware) + JRST ADCON1 + +ADSTEP: PUSHJ P,ADSTPX ;ILLEGAL IF MEM OR SEL STOP + PUSHJ P,E.SFU ; Force User mode (reloads map and skips) + POPJ P,0 ; lossage if here + CONO DIS,40 + POPJ P, + +ADWORD: XCTR XR,[MOVE J,(J)] ; fetch c(AC) + PUSHJ P,ADSTOP ;MAKE SURE IT IS STOPPED + PUSHJ P,E.SFU ;RELOAD MAP IF NECESSARY + POPJ P,0 ;MAP NOT IN USER MODE + DATAO DIS,J + POPJ P, + +ADCLOS: CAME U,DISUSR + POPJ P, + CONO DIS,5010 ;STOP, PI OFF + SETZM E.SPGW ;CLEAR PAGE WAIT + PUSHJ P,SWTL ;LOCK CIRCULAR SWITCH + CIRPSW + PUSHJ P,E.SCLB + PUSHJ P,LSWPOP ;RESTORE SWITCH + SETOM DISUSR + POPJ P, + +DISCHK: MOVE B,UNAME(U) + SKIPL T,DISUSR + CAMN B,UNAME(T) + AOS (P) + +ADRSTA: ;READ STATE, WRITE STATE NOT IN. +ADSSTA: POPJ P, + +;E&S PAGER HAS TO REFERENCE 0 TO INITIALLIZE MAP. +;E&S FORCE USER MODE + +E.SFU: SKIPGE E.SSYS + JRST POPJ1 ;SKIP IF MAP OFF +E.SFU2: MOVSI T,140000 ;ENTRY FOR DCRRST + MOVEM T,E.SPM+1 ;RESETS STATUS + DATAO DIS,[NWSTK 1] ;STORE SP AT 0 + PUSHJ P,E.SWT ;CANNOT UFLS -- NWSTK MIGHT BE REISSUED + POPJ P,0 ;HARDWARE LOSSAGE + DATAO DIS,E.SPM ;OUTPUTS C(0) (RELOADS SP) + PUSHJ P,E.SWT + POPJ P,0 ;LOST + SETOM E.SSYS ;REMEMBER MAP ON + JRST POPJ1 + +E.SWT: PUSH P,J + MOVEI J,100 ;COUNT FOR TIMEOUT + CONSZ DIS,4000 ;STOPPED AND READY? ELSE SKIP + JRST POPJJ1 ;SKIP RET IF READY + CONSO DIS,640000 ;OTHER FLAVORS OF LOSSAGE + SOJG J,E.SWT+2 ;COUNT IF STILL OK + CONO DIS,10 ;STOP FOR GOOD + JRST POPJJ ;LOSES, NO SKIP RETURN + +ADSTL: 000501052405 ;LI DIR,052405(PROGM) + 300541,,[-1,,] ;LOCLA SELINT,[-1,,](1) + 300441,,[102521,,] ;LOCLA CDIR,[102521,,](1) + 302641,,[3777,,3777] ;LOCLSA VIEW,[3777,,3777](1) + 302701,,[377777377777] ;LOCLSA WIND,[377777377777](1) + 100,,0 ; (JMP 0) load page map and go +ADSTN==.-ADSTL +EBLK + +DSTADD: 000100,, ;JMP TO CODE (FILL IN ADDRESS) + +; E&S PAGE MAP STATUS BLOCK +E.SPM: 0 ; c(0) + 0 ; status word + 0 ; dbr low + 0 ; dbr high + +MXDISP==16. ; maximum number of tied pages +DISPGP: -MXDISP,,0 ; page pointer for mmp pages +DISSWP: BLOCK MXDISP ; MMSWP INDICES TIED +E.SPGW: 0 ; if non zero, E&S page wait page +E.SPGH: 0 ; flag for QSWI1 +E.SCLS: 0 ; if non zero, new userI flushing disusr +E.SSYS: 0 ; flag for pager on/off +E.SIST: 0 ; ststus word at last interrupt + +; counts for debugging + +E.SNTI: 0 ; # pages tied down (total during system run) +E.SNUT: 0 ; # pages untied (should = .-1 after dclose) + +E.SREL: 0 ; # times pages in DISSWP table were relocated + +; end of debug counts + + +DSTPCT: -1 ; STOP COUNT TO HANDLE REDUNDANT STOPS +DSCONI: 0 ;LAST CONI FROM DISPLAY +EBRKA: 0 ;INTERRUPT SAVE AC +EBRKU: 0 ; DITTO + +ESBRK: 0 ;HANDLE E&S INTERRUPT + +BBLK + + CONSO DIS,7 ;PI CHAN ASSIGNED? + JRST 12,@ESBRK ;NO, CANNOT INTERRUPT + CONI DIS,DSCONI + CONO DIS,10 ;DEASSIGN PI CHANNEL + MOVEM U,EBRKU ;SAVE AC'S + MOVEM A,EBRKA + MOVEI A,%PILTP ;GIVE "LTPEN" INT (CLASS 3) + CONSZ DIS,640040 ;PAR, NXM, MPV, SELECT + JRST E.SFLT ; check page fault +E.SUIN: SKIPL U,DISUSR + IORM A,PIRQC(U) +E.SPFR: MOVE A,EBRKA ;UNSAVE AC'S + MOVE U,EBRKU + JRST 12,@ESBRK ;RETURN + +E.SFLT: CONSZ DIS,200000 ; skip if not NXM (ie not fault) + SKIPL E.SPM+1 ; error bit set in status word ? + JRST E.SILM ; if not, real illegal mem + LDB U,[121000,,E.SPM+1] ; get page # + HRROM U,E.SPGW ; save for loading (LH is flag) + MOVE U,E.SPM+1 ; get status + MOVEM U,E.SIST ; save status for later (debugging) + LDB U,[330300,,U] ; access and pgerr + CAIE U,2 ; read write/first error + SKIPN U ; no access -- page fault + JRST E.SPFR ; gives a page fault +E.SILM: SETZM E.SPGW ; if not page fault, don't rq load + MOVEI A,%PIDIS; mem fault bits + JRST E.SUINT ; give user interrupt + +DCRSTP: CAMN U,DISUSR ;IS THIS U ON DIS + AOSE DSTPCT ; HERE IF THIS USER, SKIP IF FIRST CALL TO STOP + POPJ P, ;RETURN IF NOT + CONSO DIS,7 ; SKIP IF CURRENTLY RUNNING + POPJ P, ; RETURN IF NOT RUNNING NOW + CONI DIS,DSCONI ;SAVE STATE FOR RESTART + CONO DIS,5000 ;OTHERWISE STOP IT +DISSTQ: MOVEI TT,100 + CONSO DIS,4000 ;SKIP IF STOP ACTUALLY TAKES HOLD + SOJG TT,.-1 ;TIME-OUT LOOP + JUMPG TT,CPOPJ ;DID NOT TIME OUT, OK + CONO DIS,10 ;DISABLE DISPLAY (CLEAR PIA) + AOS DISSTQ ;CAUSE "SYSTEM CLOBBERED" ... ON SYS CONSOLE + POPJ P, + + +E.SLPM: PUSHJ P,DCRSTP ; stop before loading page map +DCRRST: CAMN U,DISUSR ;IS THE CURRENT U ON DISPLAY? + SOSL T,DSTPCT ; SKIP IF LAST START CALL, (FROM MORE THAN 1 STOP) + POPJ P, ;NO + AOSE T ;SKIP IF ONLY ONE STOP + JRST 4,. ;SOME ONE IS OUT OF PHASE! + MOVE T,DSCONI + CONSZ DIS,7 ;SKIP IF NOT RUNNABLE + TRNE T,4000 ;1=> WAS STOPPED + POPJ P, ;SO QUIT + PUSHJ P,E.SFU2 ; load E&S page map + POPJ P,0 ; lost somehow + CONO DIS,400 ;ELSE SET RUN + CONO DIS,2000 ;THEN ALLOW STOP INT + POPJ P, + + ; tie down hacks + +;E.SPCH checks MMSWP ind in T against DISSWP +; R0 if already there, R1 if not. ret index in H + +E.SPCH: MOVSI H,-MXDISP + CAMN T,DISSWP(H) + POPJ P,0 ; found + AOBJN H,.-2 ; look some more + JRST POPJ1 ; not found, skip + +E.SCLB: MOVSI H,-MXDISP + SKIPE T,DISSWP(H) ; VALID IF NON-ZERO + PUSHJ P,UNTIE ; UNTIE PAGE IN T (MMSWP INDEX) + AOBJN H,E.SCLB+1 + POPJ P,0 + +; UNTIE PG T/ MMSWP index +; H/ display table index + +UNTIE: AOS E.SNUT ; count unties + PUSH P,H + MOVSI H,-1 + ADDB H,MMSWP(T) ; sos # exec pgs + SKIPGE H ; if less than zero, untied an untied page + JRST 4,. ; exec pg count < 0 + POP P,H + SETZM DISSWP(H) ; clear table entries + POPJ P,0 + +; ties down page. T/ MMSWP ind. + +E.SPG1: SKIPL MEMBLT(T) ; frozen, so dont tie + PUSHJ P,E.SPCH ; skips if not there + POPJ P,0 ; dont tie + AOS E.SNTI ; count number of ties. + MOVSI H,1 + ADDM H,MMSWP(T) ; aos # exec pgs + MOVE H,DISPGP ; fetch dis pg pointer + AOBJN H,.+2 + MOVSI H,-MXDISP ; reset pointer if table full + MOVEM H,DISPGP ; update pointer + PUSH P,T ; now checks if slot in use + SKIPE T,DISSWP(H) + PUSHJ P,UNTIE ; untie page in T + POP P,T + MOVEM T,DISSWP(H) ; remember mmswp ind + POPJ P,0 + +; E.SPGI called from CFHPI on page in core after fault + +E.SPGI: SKIPGE U,DISUSR + JRST 4,. ; why here ? + HRRO I,CFHUVP ; user virtul page from CFH... + CAME I,E.SPGW ; is the sam as E&S rq ? + POPJ P,0 ; no, return + SETOM E.SPGH ; set flag for QSWI1 (read/write/first hack) + PUSHJ P,E.SPG1 ; tie down + SETZM E.SPGW ; clear page wait + PUSHJ P,RDSTART ; restart display + POPJ P,0 + POPJ P,0 ; skip return from rdstart if wins + \ No newline at end of file diff --git a/src/system/itsmsp.30 b/src/system/itsmsp.30 new file mode 100755 index 00000000..fb93252f --- /dev/null +++ b/src/system/itsmsp.30 @@ -0,0 +1,315 @@ +;.OPEN CHNL,PNTR1 + +;PNTR1: MODE,,(SIXBIT /NET/) +; PNTR2 +; MYNAME1 +; MYNAME2 + +;PNTR2: HISNAME1 +; HISNAME2 +; COUNT +; buffer + +;MODES=> BITS 3.1== READ FROM ANY +; 3.2== READ FROM SPECIFIC +; 3.3== SEND AND HANG +; 3.4== SEND IMMEDIATE +; 3.5== USE UNAME JNAME AS MY1 AND MY2 +; 3.6== USE UNAME AS HIS1 + +;OPEN FAILURES: +; 4 HIS NAME 1 & HIS NAME 2 WERE ZERO +; 6 TABLE FULL +; 7 ON WRITE, RELOCATION OF READ BUFFER FAILED +; 11 ATTEMPT TO SEND TO SELF +; 12 NOT A LEGAL MODE +; 20 SEND IMMEDIATE, GUY WASN'T THERE +; 22 BUFFER NOT IN YOUR CORE IMAGE + + +EBLK + +MSENTS==40 ;# OF ENTRIES IN THE TABLE + +MSUSER: BLOCK MSENTS ;USER INDEX +MSCHNL: BLOCK MSENTS ;USERS CHANNEL +MSBADR: BLOCK MSENTS ;RELATIVE ADDRR OF USER'S BUFR +MSBCNT: BLOCK MSENTS ;SIZE OF USERS BUFFER + +MSWRIT: BLOCK MSENTS ;SENDING NAME 1 +MSWRT2: BLOCK MSENTS ;SENDING NAME 2 +MSREAD: BLOCK MSENTS ;READING NAME 1 +MSRED2: BLOCK MSENTS ;READING NAME 2 + +MSPSW: -1 ;SWITCH FOR MSP VARIABLES + 0 ;EXTRA WORD, FOR SWTL ROUTINE + +BBLK + + IPCO: PUSHJ P,SWTL ;LOCK THE MSP SWITCH + MSPSW + TLNE C,1 ; read from any? + JRST MSRA ; yes + TLNE C,2 ; read from specific? + JRST MSRS ; yes + TLNE C,4 ; send and hang? + JRST MSSH ; yes + TLNE C,8 ; send immediate? + JRST MSSI ; yes + JRST OPNL12 ; none of the above + +; read from any (RA) and read from specific (RS) +MSRA: SETOM H ; H/-1 =>RA 0=>RS + SKIPA +MSRS: SETZM H + +; find first free user slot + MOVSI W,-MSENTS ; W/ slot index +MSR1: SKIPG MSUSER(W) ; is this slot free? + JRST MSR2 ; yes + AOBJN W,MSR1 + JRST OPNL6 ; no free slots, device full + +; W/ slot index of a free slot +MSR2: MOVEM U,MSUSER(W) ; occupies this slot +; make sure we have a legal buffer + HRRZ D,A ; relative address of second buffer + MOVEI E,3(D) ; E/ relative address of data area + XCTR XRW,[MOVES (D)] ;CHECK COUNT FETCH? + XCTR XRW,[MOVES TT,2(D)] ;CHECK ACTUAL COUNT PLACE + +; bufr ok, now put data in table + MOVEM E,MSBADR(W) ; stores buffer address + MOVEM TT,MSBCNT(W) + +; store sender name only if RS + JUMPL H,MSR3 + XCTR XR,[MOVE TT,(D)] ; his name 1 + XCTR XR,[MOVE I,1(D)] ; his name 2 + TLNE C,40 ; his1 = UNAME? + MOVE TT,UNAME(U) ; yes + SKIPA +MSR3: SETZB TT,I ; zero if RA + MOVEM TT,MSWRIT(W) + MOVEM I,MSWRT2(W) + +; 3.5 bit in C means use UNAME JNAME as myname1 and myname2 + TLNN C,20 ; skips if want default + JRST .+4 + MOVE TT,UNAME(U) + MOVE I,JNAME(U) + JRST .+3 + ; else me1 is in B and me2 is in SRN3(U) + MOVE TT,B + MOVE I,SRN3(U) + MOVEM TT,MSREAD(W) + MOVEM I,MSRED2(W) + + MOVEI TT,(R) ;GET CHANNEL + SUBI TT,IOCHNM(U) + MOVEM TT,MSCHNL(W) ;STORE FOR LATER INTERRUPT + + PUSHJ P,LSWPOP ;UNLOCK MSP SWITCH + +; now put tabl index in lh of IOCHNM(U)(R) + HRLZ A,W + JSP Q,OPSLD1 + MSPIO,,MSPIO ; attempted IOT will get IOCER 10. + ; send and hang (SH) and send immediate (SI) +MSSI: SETOM H ; H/-1=>SI 0=>SH + SKIPA +MSSH: SETZM H + +; validate his buffer specs + HRRZ D,A ; relative buffer address + MOVEI E,3(D) ; E/ relative data addr + XCTR XRW,[MOVES (D)] ;CHECK NAME + XCTR XRW,[MOVES Q,2(D)] ;CHECK COUNT + +; other data + ; E/ absolute data addr + ; Q/ count + XCTR XR,[MOVE T,(D)] ; T/ his name 1 + TLNE C,40 ; 3.6 bit means use UNAME + MOVE T,UNAME(U) ; yes + XCTR XR,[MOVE TT,1(D)] ; TT/ his name 2 + JUMPN T,.+3 ; T and TT can not both be zero + SKIPN TT + JRST OPNL4 + MOVEM TT,EPDL(U) ; EPDL(U)/ hisname2 + +; 3.5 bit in C means use UNAME JNAME as myname1 and myname2 + TLNN C,20 ; skips if wants default + JRST .+4 + MOVE TT,UNAME(U) + MOVE I,JNAME(U) + JRST .+3 + ; else myname1 is in B and myname2 is in SRN(U) + MOVE TT,B + MOVE I,SRN3(U) + MOVEM TT,EPDL3(U) ; EPDL3/ myname1 + MOVEM I,SRN4(U) ; SRN4/ myname2 + +; see if entry is in the table + PUSHJ P,MSSTBL + SKIPA ; no, will havee to wait + JRST MSS2 ; yes, service the transfer + JUMPL H,OPNL20 ; was an SI, lose +MSS1: XCTR XR,[MOVE T,(D)] ; in case it got munged + TLNE C,40 ; 3.6 bit means use UNAME + MOVE T,UNAME(U) + + +; wait for entry to appear in table +MSDM3: PUSH P,T ;LSWPOP CLOBBERS T + PUSHJ P,LSWPOP ;UNLOCK MSPSW FOR WAITING + MOVE T,(P) ;RESTOR T + SKIPA ; forces a call to ufls + PUSHJ P,MSSTBL + PUSHJ P,UFLS ; hang . . . . + PUSHJ P,SWTL ;RELOCK SWITCH NOW + MSPSW + POP P,T ;RESTORE T AFTER CLOBBERING BY SWTL + PUSHJ P,MSSTBL ; read has been done, get details + JRST MSS1 ; oops, must have been aborted + +; FALLS THRU IF MSSTBL SKIPS +; table index of the user is now in T +MSS2: MOVE H,T ; H/ table index + MOVE A,MSUSER(H) ; A/ user index + CAMN A,U + JRST [PUSHJ P,LSWPOP ;POP MSPSW + JRST OPNL11] + PUSHJ P,RPCLSR ; stop or i'll shoot + PUSHJ P,SOSSET ;SET TO SOS USTP(A) ON PCLSR + USTP(A) + +; get the absolute address of the read data buffer +MSS3: MOVE A,MSBADR(H) ; relative +;SET UP PAGE MAP FOR RECEIVER (USER IN MSUSER(H)) + PUSH P,R + MOVE J,MSUSER(H) ;USER TO RECEIVE + PUSHJ P,MPLDJ ;LOAD MAP +; fix count (sender cnt in Q, receiver cnt in MSBCNT(H)) + CAMG Q,MSBCNT(H) ; will it fit? + JRST MSS4 ; yes + XCTRI XRW,[SETOM -1(A)] ; no, indicate overflow will be lost + CAIA ;REFERENCE WORKED, SKIP + JRST MSS7 ;FAIL, RESTORE STOPS ETC. + MOVE B,MSBCNT(H) ; B/ count + JRST MSS5 +MSS4: MOVE B,Q ; B/ count + MOVE TT,MSBCNT(H) + SUB TT,B + XCTRI XRW,[MOVEM TT,-1(A)] ; amount that will be xfered + CAIA ;REFERENCE WORKED, SKIP + JRST MSS7 ;FAIL, RESTORE STOPS ETC. + +; if MSWRIT was zero (RA), fill it in +MSS5: SKIPN MSWRIT(H) + SKIPE MSWRT2(H) + JRST MSS6 + MOVE TT,EPDL3(U) + XCTRI XRW,[MOVEM TT,-3(A)] ; read's him1 + CAIA ;REFERENCE WORKED, SKIP + JRST MSS7 ;FAIL, RESTORE STOPS ETC. + MOVE TT,SRN4(U) ; + XCTRI XRW,[MOVEM TT,-2(A)] ; read's him2 + CAIA ;REFERENCE WORKED, SKIP + JRST MSS7 ;FAIL, RESTORE STOPS ETC. + +; RESTORE USER MAP TO CURRENT USER +MSS6: PUSHJ P,MPLDZ + POP P,R +; XFER => B/ CNT A/READ BUFR E/WRIT BUFR J/UNRELOCATED BUFFER (READ) + HRRM A,IOCHST-IOCHNM(R) ;STORE RECEIVER ADDRESS FOR UBO + MOVN W,B ;-COUNT + MOVSS W ;-COUNT,, + HRR W,E ;-COUNT,,ADR + MOVE C,[SETZ W] ;POINTER FOR UBO + MOVE A,MSUSER(H) ;GET OTHER USERS NUMBER FOR UBO + PUSHJ P,UBO ;USER BLOCK OUTPUT - DO WRITE TRANSFER + +; RESTART THE LOSER + PUSHJ P,LSWPOP ;UNDO RPCLSR (SOS USTP(MSUSR(H))) + MOVE A,MSUSER(H) ;GET TARGET USER + MOVE B,MSCHNL(H) ;CHANNEL HE OPENED + MOVE B,CHNBIT(B) ;BIT CORRESPONDING TO CHAN + TDNE B,MSKST2(A) ;SKIP IF NOT ENABLED + IORM B,IFPIR(A) ;SET HIS INTERRUPT + +; flush read entry from the table + SETZM MSCHNL(H) + SETZM MSREAD(H) + SETZM MSRED2(H) + SETZM MSWRIT(H) + SETZM MSWRT2(H) + SETZM MSBADR(H) + SETZM MSBCNT(H) + SETZM MSUSER(H) + + PUSHJ P,LSWPOP ;UNLOCK MSPSW + +; end open + SETOM A ; LH IOCHNM==-1 MEANS SEND (FOR CLOS) + JSP Q,OPSLD1 ;DOES POPJ BACK TO UUOH + MSPIO,,MSPIO +; (DOES NOT COME BACK) + +;HERE FOR FAILURE OF XCTRI WHILE MAP SET TO RECEIVER +MSS7: POP P,R ;RESTORE STACK + PUSHJ P,LSWPOP ;RESTART USER (SOS USTP) + PUSHJ P,TPFLT ;TAKE PAGE FAULT, CAUSE PAGE LOAD + PUSHJ P,MPLDZ ;RESTORE MY PAGE MAP + JRST MSS1 ;TRY AGAIN + +; FIND LOSER IN TABLE SKIP IF WINS +; IN => T/READ1 EPDL/READ2 EPDL3/WRITE1 SRN4/WRITE2 +; OUT => IF WINS, T/TABLE OFFSET +MSSTBL: PUSH P,A + PUSH P,B + PUSH P,C + PUSH P,D + MOVSI A,-MSENTS + MOVE B,EPDL(U) ; B/ READ2 + MOVE C,EPDL3(U) ; C/ WRITE1 + MOVE D,SRN4(U) ; D/ WRITE2 +MSSTB1: CAMN T,MSREAD(A) + CAME B,MSRED2(A) + JRST MSSTB2 + SKIPN MSWRIT(A) ; if it was read from any + SKIPE MSWRT2(A) ; win if WRIT and WRT2 are both zero + JRST .+2 + JRST MSSTB3 + CAMN C,MSWRIT(A) + CAME D,MSWRT2(A) + JRST MSSTB2 +MSSTB3: HRRZ T,A + AOSA -4(P) +MSSTB2: AOBJN A,MSSTB1 + POP P,D + POP P,C + JRST POPBAJ + +; close routine +; A/ lf IOCHNM +; R/ addr of IOCHNM(USER)(CHNL) + +MSCLOS: TRNE A,400000 ; -1 means write + POPJ P, + CAIL A,MSENTS ; in bounds of table? + POPJ P, ; no + CAME U,MSUSER(A) ; is this still me? + POPJ P, + +; yes, make this a free slot + SETZM MSCHNL(A) + SETZM MSREAD(A) + SETZM MSRED2(A) + SETZM MSWRIT(A) + SETZM MSWRT2(A) + SETZM MSBADR(A) + SETZM MSBCNT(A) + SETZM MSUSER(A) + POPJ P, +  \ No newline at end of file diff --git a/src/system/kaimp.defs1 b/src/system/kaimp.defs1 new file mode 100755 index 00000000..c37b820f --- /dev/null +++ b/src/system/kaimp.defs1 @@ -0,0 +1,63 @@ +;;; -*- Mode: Midas -*- +.AUXIL + +;;; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + +; Hardware description of AI-KA/ML/MC IMP interface, device "IMP". +; For a more detailed description, see AI Hardware Memo #10, +; "ARPA Network Interface". +; In particular, the "channel 1 multiplexing" feature of the ITS KA's +; is used, so that: +; When PI level 2 (NETCHN) is assigned, the IMP interface takes +; all interrupts on the normal channel (goes to IMPINT). +; When PI level 1 (IMPCHN) is assigned, +; IMPID+(-IMPLIW) => Pseudo channel 4, location 70 (IMPILC)-> various +; IMPOD => Pseudo channel 5, location 72 (IMPOLC)-> various +; else normal PI channel 1 (PI0LOC+2)-> IMPBRK + +; CONI bits - starred items cause interrupt on PIA channel + ; 1.1-1.3 => PIA +DEFSYM IMPID==10 ;* INPUT DONE - on when word avail for DATAI +DEFSYM IMPI32==20 ; Input in 32 bit mode +;DEFSYM IMPIB==40 ; Input Busy +DEFSYM IMPOD==100 ;* OUTPUT DONE - Word sent to IMP +;DEFSYM IMPO32==200 ; Output in 32 bit mode +;DEFSYM IMPOB==400 ; Output Busy +DEFSYM IMPERR==1000 ;* Imp Error (interrupt if IMPIC zero) +DEFSYM IMPR==2000 ;* Imp Ready (interrupt if IMPIC set) +;DEFSYM IMPIC==4000 ; Imp interrupt condition + ; (0 = int on IMPERR, 1= int on IMPR) +DEFSYM IMPHER==10000 ;* Host Error (interrupt if IMPIHE zero) +;DEFSYM IMPHR==20000 ; Host Ready +;DEFSYM IMPIHE==40000 ; Inhibit interrupt on Host Error (IMPHER) +DEFSYM IMPLW==100000 ;* Last Imp Word + +; CONO bits - starred flags are always copied directly to set states + ;* 1.1-1.3 => PIA set from these bits +DEFSYM IMPIDC==10 ; Clear Input Done +DEFSYM IMI32S==20 ; Set input to 32 bit mode +DEFSYM IMI32C==40 ; Clear input in 32 bit mode +DEFSYM IMPODC==100 ; Clear Output Done +DEFSYM IMO32S==200 ; Set output to 32 bit mode +DEFSYM IMO32C==400 ; Clear output in 32 bit mode +DEFSYM IMPODS==1000 ; Set Output Done +DEFSYM IMPIR==4000 ;* Copied to IMPIC; 1= Enable int on imp ready +DEFSYM IMPHEC==10000 ; Clear Host Error +;DEFSYM IMIIHE==40000 ;* Copied to IMPIHE + ; 1= Inhibit int on host error +DEFSYM IMPLHW==200000 ; Set Last Host Word + ; (do this before last DATAO of msg) +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/ksdefs.193 b/src/system/ksdefs.193 new file mode 100755 index 00000000..d5325fcc --- /dev/null +++ b/src/system/ksdefs.193 @@ -0,0 +1,561 @@ +; -*- Midas -*- This is the file AI:KSHACK;KSDEFS > + +;;; "Devices" + +PI==:4 ;Interrupts +PAG==:10 ;Paging + ..D010==:0 ;(For DDT) +.RD.==:20 ;Read various kludges. + ..D020==:0 +.WR.==:24 ;Write various kludges. + ..D024==:0 + +;;; XCTR and paging instructions + +UMOVE=:704^9 ;"BLKI 40," + ;Same as XCTR XR,[MOVE ...] + +UMOVEM=:705^9 ;"BLKI 50," + ;Same as XCTR XW,[MOVEM ...] + +XCTR=:103^9 ;XCT with mapping. +XCTRI=:102^9 ;Same, but page fails cause it to skip. Done by + ;software as on the KL. + ;;XCTR bits for the KS are theoretically the same as those on the KL. + ;;These values were generated by reading the documentation rather + ;;than by copying the bits for XCTR on MC. + XR==:4 + XW==:4 + XRW==:4 + XBYTE==:7 ;On MC-KL this is 5. The manual don't list 5 as a + ;reasonable value at all. The 2 bit causes the EA + ;calculation for the byte pointer to take place in + ;the user's context. Since ITS does the EA + ;calculation for byte pointers it XCTRs ahead of + ;time, perhaps it doesn't matter? + XBR==:1 + XBW==:4 + XBRW==:5 + XEA==:10 ; On MC-KL this is #o16. The processor manual for + ; the KL contains some waffling about how 10 won't + ; work and you should use 14 instead. The KS + ; manual is silent on this point. Seemingly no + ; bits other than 10 can effect an immediate + ; instruction. This option doesn't exist on the KA + ; and is used by ITS in only two places, both in + ; the KL-specific page fail code. One occurance is + ; commented out with the claim that it is buggy. + ; For the moment let us assume that this value will + ; just work on the KS. + +;;; Traditional instructions. + +RDAPR==:CONI 0, ;= 700240,, C(E) <- System flags + ;4.3 - 3.5 Flags enabled + ; (on KL 2.8 says the cache is being swept) + ;2.3 - 1.5 Flags set + ;1.4 Some flag is interrupting + ;1.3 - 1.1 PI level + +WRAPR==:CONO 0, ;= 700200,, System flags <- E + ; (on KL 2.8 Clears all IO devices) + ;2.7 - 2.4 Function to perform on flags: + ; 2.7 Enable + ; 2.6 Disable + ; 2.5 Clear + ; 2.4 Set + ;2.3 - 1.5 Flags to perform function upon: + ; 2.3 "Flag 24" + ; 2.2 KS interrupting the 8080 + ; 2.1 Power failure + ; 1.9 No memory + ; 1.8 Bad memory data + ; 1.7 Corrected memory data + ; 1.6 Interval done + ; 1.5 8080 interrupting the KS + ; (on KL flags are: + ; 2.3 S bus error + ; 2.2 No memory + ; 2.1 IO page failure + ; 1.9 MB parity + ; 1.8 Cache directory parity + ; 1.7 Address parity + ; 1.6 Power failure + ; 1.5 Cache sweep done) + ;1.3 - 1.1 PI level + +80INT==:12000 ;Interrupt 8080 from KS. + +RDPI==:CONI PI, ;= 700640,, C(E) <- PI status + ;3.7 - 3.1 interrupts requested with CONO PI, + ; (on KL 2.9 - 2.7 control parity) + ;2.6 - 1.9 Interrupt in progress + ;1.8 PI system is on + ;1.7 - 1.1 Levels turned on + +WRPI==:CONO PI, ;= 700600,, PI status <- E + ; (on KL 2.9 - 2.7 control parity) + ;2.5 Drop requests on selected levels + ;2.4 Clear PI system + ;2.3 Initiate interrupts on selected levels + ;2.2 Turn on selected levels + ;2.1 Turn off selected levels + ;1.9 Turn off PI system + ;1.8 Turn on PI system + ;1.7 - 1.1 Select level + +;;; More traditional looking instructions, sort of... + +APRID==:BLKI 0, ;= 700000,, C(E) <- Processor ID + ;4.9 - 4.1 Microcode options: + ; 4.5 ITS microcode + ; (on KL options are: + ; 4.9 Tops-20 Paging + ; 4.8 Extended addressing + ; 4.7 Exotic microcode + ; 4.5 ITS microcode) + ;3.9 - 3.1 Microcode version number + ;2.9 - 2.7 Hardware options: + ; None defined. + ; (on KL options are: + ; 2.9 50 Hz line frequency + ; 2.8 Cache + ; 2.7 Channel + ; 2.6 Extended KL10 + ; 2.5 Master Oscillator) + ;2.6 - 1.1 Processor serial number + +RDEBR=:CONI PAG, ;= 701240,, C(E) <- EBR +WREBR=:CONO PAG, ;= 701200,, EBR <- E + ;2.6 Tops-20 style + ;2.5 Enable pager (and traps) + ;2.2 - 1.1 EBR physical DEC page number + ;WREBR resets the cache and page table. + ; + ; In the ITS microcode setting bit 2.6 only effects + ; the style in which MUUOs are trapped. It should + ; never be set. + +RDUBR=:DATAI PAG, ;= 701040,, C(E) <- UBR +WRUBR=:DATAO PAG, ;= 701140,, UBR <- C(E) + ;4.9 Set AC blocks + ;4.7 Set UBR + ;4.3 - 4.1 Current ACs + ;3.9 - 3.7 Previous ACs + ;3.2 - 1.1 UBR physical base address + ;RDUBR always returns a word with 4.9 and 4.7 set. + ;WRUBR resets the cache and page table. + +CLRPT=:BLKO PAG, ;= 701100,, Clear page table entry + ;Invalidate the page table entry for the page + ;referenced by E and reset the cache. + ; + ;In the ITS microcode this will only invalidate the + ;page table entry for half page referenced by E. + +CLRCSH=:BLKI PAG, ;= 701000,, Clear Cache + ;In the ITS microcode only. + ;Resets the cache. + + +;;; Instructions for maintaining the DBRs. LPMR and SPM. + +LDBR1=:BLKI .WR., ;= 702400,, DBR1 <- E +SDBR1=:BLKI .RD., ;= 702000,, C(E) <- DBR1 +LDBR2=:DATAI .WR., ;= 702440,, DBR2 <- E +SDBR2=:DATAI .RD., ;= 702040,, C(E) <- DBR2 +LDBR3=:BLKO .WR., ;= 702500,, DBR3 <- E +SDBR3=:BLKO .RD., ;= 702100,, C(E) <- DBR3 +LDBR4=:DATAO .WR., ;= 702540,, DBR4 <- E +SDBR4=:DATAO .RD., ;= 702140,, C(E) <- DBR4 + ;LDBR1, LDBR2, LDBR3 and LDBR4 all reset the cache + ;and page table. someday they may be careful and + ;not reset the half of the page table they don't + ;effect. + +;;; And there is also the traditional: + +LPMR=:CONSO .WR., ;702740,, DBR1, DBR2, ... <- C(E, E+1, ...) +SPM=:CONSO .RD., ;702340,, C(E, E+1, ...) <- DBR1, DBR2, ... + ;The format of the block read and written by these + ;two instructions is: + ; (E) DBR1 + ; (E+1) DBR2 + ; (E+2) Quantum timer + ; (E+3) U.JPC (If this ucode supports it) + ; (E+4) E.JPC ( " " ) + ;LPMR resets the cache and page table. + +RDTIM=:CONO .RD., ;= 702200,, C(E, E+1) <- Time +WRTIM=:CONO .WR., ;= 702600,, Time <- C(E, E+1) + ; The time is a 71. bit unsigned number. The bottom + ; 12. bits cannot be set. The bottom 2 bits cannot + ; even be read. It increments at 4.1 MHz. The top + ; 59. bits (the ones you can set) thus measure + ; (almost) milliseconds. The top 69. bits (the + ; ones you can read) thus measure "short" + ; microseconds. The time wraps around every 18. + ; million years. To make the top 59. bits actually + ; measure milliseconds, the clock would have to run + ; at 4.096 MHz. However it -really- -does- run at + ; exactly 4.1 MHz! + +RDINT=:CONI .RD., ;= 702240,, C(E) <- Interval +WRINT=:CONI .WR., ;= 702640,, Interval <- C(E) + ;The interval is a 35. bit number in the same units + ;as the time. At the end of every interval the + ;interval done interrupt occurs (CONI APR, bit + ;1.5). The biggest interval you can set is about 2 + ;hours and 20 minutes. In the DEC microcode the + ;interval is effectively rounded up to the next + ;millisecond, so it is really only worth your while + ;to set the top 23. bits. In the ITS microcode all + ;bits of the interval are signifigant. Although + ;the length of a -single- interval cannot be + ;controlled more accurately than under the DEC + ;microcode, the average time between interval done + ;interrupts should converge to the full 35. bit + ;value. + +RDHSB=:CONSZ .RD., ;= 702300,, C(E) <- HSB base address +WRHSB=:CONSZ .WR., ;= 702700,, HSB base address <- C(E) + ;4.9 Base address is invalid. If this is set + ; nothing will be written anywhere when the + ; machine halts. + ;3.1 - 1.1 Physical address of first location in + ; which to store debugging info when the + ; machine halts. + ;In the ITS microcode, the initial HSB base address + ; is #o500. + ;When the machine halts it stores a halt code in + ; physical location 0 and the PC in location 1. + ; Then if 4.9 is not set (and the machine has not + ; just powered on) the contents of the 2901's + ; registers are dumped in the halt status block, + ; followed by the VMA. + +;;; Halt Codes + + ;CODES 0 TO 77 ARE "NORMAL" HALTS +; POWER=0 ;POWER UP +; HALT=1 ;HALT INSTRUCTION +; CSL=2 ;CONSOLE HALT + ;CODES 100 TO 777 ARE SOFTWARE ERRORS +; IOPF=100 ;I/O PAGE FAIL +; ILLII=101 ;ILLEGAL INTERRUPT INSTRUCTION +; ILLINT=102 ;BAD POINTER TO UNIBUS INTERRUPT VECTOR + ;CODES 1000 TO 1777 ARE HARDWARE ERRORS +; BW14=1000 ;ILLEGAL BWRITE FUNCTION (BAD DROM) +; NICOND 5=1004 ;ILLEGAL NICOND DISPATCH +; MULERR=1005 ;VALUE COMPUTED FOR 10**21 WAS WRONG + +;;; Halt Status Block definition + +IFNDEF HSB, HSB==:500 +HSBMAG=:HSB+0 +HSBPC=:HSB+1 +HSBHR=:HSB+2 +HSBAR=:HSB+3 +HSBARX=:HSB+4 +HSBBR=:HSB+5 +HSBBRX=:HSB+6 +HSBONE=:HSB+7 +HSBEBR=:HSB+10 +HSBUBR=:HSB+11 +HSBMASK=:HSB+12 +HSBFLG=:HSB+13 +HSBPI=:HSB+14 +HSBXWD1=:HSB+15 +HSBT0=:HSB+16 +HSBT1=:HSB+17 +HSBVMA=:HSB+20 + +;;; ITS I/O instructions. + +UBAQ==:1 ; QSK is on Unibus #1 +UBAI==:3 ; Everything else is on Unibus #3 + +IORDI=:710^9 ; C(AC) <- IO(UBAI,,E) +IORDQ=:711^9 ; C(AC) <- IO(UBAQ,,E) +IORD=:712^9 ; C(AC) <- IO(C(E)) +IOWR=:713^9 ; IO(C(E)) <- C(AC) +IOWRI=:714^9 ; IO(UBAI,,E) <- C(AC) +IOWRQ=:715^9 ; IO(UBAQ,,E) <- C(AC) + +IORDBI=:720^9 +IORDBQ=:721^9 +IORDB=:722^9 +IOWRB=:723^9 +IOWRBI=:724^9 +IOWRBQ=:725^9 + +;;; Byte packing and unpacking instructions. + +;;; These are new with microcode 262, but came from DEC. +;;; Variations of BLT that the convert format of each word moved. +;;; These are legal in user mode, too. Good thing DECUUO doesn't use them. +BLTBU=:716^9 ;Source 8-bit bytes, Destination Unibus format +BLTUB=:717^9 ;Source Unibus format, Destination 8-bit bytes + +;;; Future byte packing and unpacking instructions + +;;; =:730^9 +;;; =:731^9 +;;; =:732^9 +;;; =:733^9 +;;; =:734^9 +;;; =:735^9 +;;; =:736^9 +;;; =:737^9 + +;;; Format of ITS page fail word: + +%PF==:1,,525252 ;Left handed bits. +%PFUSR==:400000 ;4.9 Indicates user address space. +%PFNXI==:200000 ;4.8 Nonexistent IO register. +%PFNXM==:100000 ;4.7 Nonexistent memory. +%PFPAR==:040000 ;4.6 Uncorrectable memory error. + ; (AC0 in block 7 has the word unless 4.7 is + ; also set.) + ;4.5 +%PFWRT==:010000 ;4.4 Soft fault reference called for writing. +%PF2.9==:004000 ;4.3 - 4.2 Access bits for referenced page in soft +%PF2.8==:002000 ; fault. +%PFPHY==:001000 ;4.1 Address given was physical. + ;3.9 +%PFIO==:000200 ;3.8 Indicates an IO operation. + ;3.7 + ;3.6 +%PFBYT==:000020 ;3.5 Indicates a byte IO operation. + ;3.4 - 1.1 IO address + ; or + ;3.1 - 1.1 Memory address +$PFPNO==:121000 ;2.9 - 2.2 Virtual page number + +;;; Format of ITS page table entry: + + ;2.9 - 2.8 Access bits + ; 00 Inaccessible + ; 01 Read only + ; 10 Read/Write/First + ; 11 Read/Write +PMAGEM==:020000 ;2.5 Age bit +PMCSHM==:010000 ;2.4 Cache enable bit +PMRCM==:001777 ;2.1 - 1.1 Physical page number + ; (The page table supports 20 bit physical + ; addresses.) +PMUNSD==:146000 ;Unused bits + +;;; UPT Offsets +;;; In non-time sharing and at clock level in ITS UPT=EPT. + +UPTTR1==:421 ;Exec mode arith ovfl trap. +UPTTR2==:422 ;Exec mode pdl ov trap. +UPTTR3==:423 ;Exec mode trap 3 in non-one-proceed microcode. + +UPTUUO==:424 ;MUUO stored here. +UPTUPC==:425 ;MUUO old PC stored here. +UPTUCX==:426 ;MUUO context (from RDUBR (= DATAI PAG,)) stored here. + +;;; 427 ;Unused. + +UPTUEN==:430 ;MUUO new PC obtained from here in exec mode when + ;traps are not enabled. (MUUO as a trap + ;instruction for example.) +UPTUET==:431 ;MUUO new PC obtained from here in exec mode when + ;traps are enabled. + +UPT1PO==:432 ;One-proceed old PC stored here in one-proceed + ;microcode. +UPT1PN==:433 ;One-proceed new PC obtained from here in + ;one-proceed microcode. + +UPTUUN==:434 ;MUUO new PC obtained from here in user mode when + ;traps are not enabled. +UPTUUT==:435 ;MUUO new PC obtained from here in user mode when + ;traps are enabled. + +;;; 436 ;Unused. +;;; 437 ;Unused. + +;;; EPT Locations + +IFNDEF EPT, EPT==:0 ;Absolute location of EPT. + +PI0LOC=:EPT+40 ;PI0LOC+2*PICHN = Address of instr pair for PICHN. +IRP I,,[1,2,3,4,5,6,7] +PI!I!LOC=:PI0LOC+<2*I> +TERMIN + +EPTUIT=:EPT+100 ;EPTUIT+I contains address of the interrupt table + ; for unibus adapter I. Only adapters 1 and 3 ever + ; exist. + +EPTTR1=:EPT+421 ;Exec mode arith ovfl trap. +EPTTR2=:EPT+422 ;Exec mode pdl ov trap. +EPTTR3=:EPT+423 ;Exec mode trap 3 (1 proceed?). + +;;; When EPT = UPT the following are useful to have defined: + +EPTUUO=:EPT+UPTUUO +EPTUPC=:EPT+UPTUPC +EPTUCX=:EPT+UPTUCX +EPTUEN=:EPT+UPTUEN +EPTUET=:EPT+UPTUET +EPT1PO=:EPT+UPT1PO +EPT1PN=:EPT+UPT1PN +EPTUUN=:EPT+UPTUUN +EPTUUT=:EPT+UPTUUT + +;;; In the ITS microcode the three words used to deliver a page fail are +;;; determined from the current interrupt level. At level I, the page fail +;;; word is stored in EPTPFW+<3*I>, the old PC is stored in EPTPFO+<3*I>, +;;; and the new PC is obtained from EPTPFN+<3*I>. If no interrupts are in +;;; progress we just use EPTPFW, EPTPFO and EPTPFN. + +EPTPFW=:EPT+440 ;Page fail word stored here. +EPTPFO=:EPT+441 ;Page fail old PC stored here. +EPTPFN=:EPT+442 ;Page fail new PC obtained from here. + +IRP I,,[1,2,3,4,5,6,7] +EPTP!I!W=:EPTPFW+<3*I> +EPTP!I!O=:EPTPFO+<3*I> +EPTP!I!N=:EPTPFN+<3*I> +TERMIN + +;;; 8080 communication area + +8SWIT0=:30 ;Simulated switch 0. Set by 8080 SH command. +8KALIV=:31 ;Keep Alive & Status. +8CTYIN=:32 ;CTY input. +8CTYOT=:33 ;CTY output. +8KLKIN=:34 ;KLINIK user input word (from 8080). +8KLKOT=:35 ;KLINIK user output word (to 8080). +8RHBAS=:36 ;BOOT RH11 base address. +8QNUM=:37 ;BOOT Unit Number. +8BOOTP=:40 ;Magtape Boot Format and Slave Number. + +;;; 8080 front end (FE) filesystem format + +;;; Disk addresses for the 8080 are stored in 36-bit words in "FE format": +;;; (These fields are larger than those given in the DEC document because +;;; the cylinder field given there is too small! These numbers reflect the +;;; way that the 8080 manipulates 8 bit quantities instead.) +%88==:777700,,177400 +%88CYL==:100,, +$88CYL==:301400,, ; 4.9 - 3.7 Cylinder +%88TRK==:400 +$88TRK==:101000,, ; 2.7 - 1.9 Track +%88SEC==:1 +$88SEC==:001000,, ; 1.8 - 1.1 Sector + +;;; The 8080 looks for the "home sector" on cylinder 0, track 0, sector 1. +;;; If it fails to find it there it tries sector 10. The home sector is +;;; recognized by having SIXBIT /HOM/ in location 0. Location 103 of the +;;; home sector contains an FE format address of the first sector of the +;;; "FE directory", which is 1000 words (4 sectors) long. Odd numbered +;;; locations in the FE directory are not looked at by the 8080. Even +;;; numbered locations contain FE format addresses of the first sector of +;;; the various "FE files". The following are apparently the only FE files +;;; used by the 8080: +88RAM==:2 ; Microcode. Always 6 blocks long. + ; The rest are always 1000 words long. (1/2 block) +88BT==:4 ; Bootstrap used by BT command and autoboot. +88BT1==:6 ; Bootstrap used by BT1 command. +88B2==:12 ; Bootstrap used by B2 command. +88FI0==:22 ; First indirect file. Contains a sequence of + ; 8-bit bytes containing ASCII characters packed + ; backwards and right justified: + ; ------------------------------- + ; | 0's | 4th | 3rd | 2nd | 1st | + ; ------------------------------- + ; The 8080 stops on a zero byte (or perhaps 377?). + ; Lines must be no longer than 80 characters. + ; Lines are separated by a single ^M. + ; + ; Additional indirect files follow. FIn either + ; runs the file at 88FI0+n or at 88FI0+2*n, I can't + ; tell which. + +;;; Note that the only thing described here that doesn't fit inside a +;;; single ITS block is the microcode. All we need from the filesystem are +;;; the first 2 blocks (for the home sector and the alternate home sectors) +;;; and 6 contiguous blocks elsewhere (for the microcode). + +;;; External register addresses + +KSECCS==:100000 ;Memory Status Register (Controller 0) +%KE==:1,,520040 ; Left half bits. Right half unnamed. + ; [R=Read, W=Write, C=Cleared by writing a 1] +%KEHLD==:400000 ; 4.9 Error currently being held [R/C] +%KEUNC==:200000 ; 4.8 Uncorrectable error [R] +%KEREF==:100000 ; 4.7 Refresh error [R/C] +%KEPAR==:040000 ; 4.6 Parity error [R/W] +%KEENA==:020000 ; 4.5 ECC enabled [R] +%KEECC==:017700 ; 4.4 - 3.7 ECC bits [R] +%KEPWR==:000040 ; 3.6 Memory backup power is low [R/C] + ; 3.4 - 1.1 Error address [R] + ; 1.8 - 1.2 Force ECC bits if non-zero [W] + ; 1.1 Disable ECC [W] + +;; The 7 ECC bits are decoded as follows: The top bit is a parity bit for +;; the bottom 6. The bottom 6 are decoded: +;; +;; ECC code: Location of failing bit: +;; +;; 01 ECC 01 bit +;; 02 ECC 02 bit +;; 04 ECC 04 bit +;; 10 ECC 10 bit +;; 20 ECC 20 bit +;; 40 ECC 40 bit +;; 11 - 16 4.9 - 4.4 +;; 21 - 26 4.3 - 3.7 +;; 31 - 36 3.6 - 3.1 +;; 41 - 46 2.9 - 2.4 +;; 51 - 56 2.3 - 1.7 +;; 61 - 66 1.6 - 1.1 + +UBAPAG==:763000 ;(to 763077) UBA Paging RAM (One per Unibus) +UBALEN==:64. ;Length of UBA Paging RAM + ;When read: +%UP==:1,,525377 ; Left half bits. +%UPPAR==:020000 ; 4.5 RAM parity bit +%UPRPW==:010000 ; 4.4 Force read-pause-write +%UP16B==:004000 ; 4.3 Disable upper two bits on Unibus transfers +%UPFST==:002000 ; 4.2 Fast mode enable +%UPVAL==:001000 ; 4.1 Entry is valid +%UPPVL==:000400 ; 3.9 Parity is valid +$UPPAG==:121200,, ; 3.2 - 2.2 ITS page number + ; 2.1 ITS half page + ; 3.2 - 2.1 DEC page number + ;When written: +%UQ==:0,,537777 ; Right half bits +%UQRPW==:400000 ; 2.9 Force read-pause-write +%UQ16B==:200000 ; 2.8 Disable upper two bits on Unibus transfers +%UQFST==:100000 ; 2.7 Fast mode enable +%UQVAL==:040000 ; 2.6 Entry is valid + ; 2.2 - 1.2 ITS page number + ; 1.1 ITS half page + ; 2.2 - 1.1 DEC page number + +UBASTA==:763100 ;UBA Status Register (One per Unibus) + ; [R=Read, W=Write, C=Cleared by writing a 1, + ; *=Cleared by any write] +%UB==:0,,525270 ; Right half bits. +%UBTIM==:400000 ; 2.9 Unibus timeout [R/C] +%UBBAD==:200000 ; 2.8 Bad mem data (on NPR transfer) [R/C] + ; (Master will timeout instead if %UBDXF set) +%UBPAR==:100000 ; 2.7 KS10 bus parity error [R/C] +%UBNXD==:040000 ; 2.6 CPU addressed non-ex device [R/C] +%UBHIG==:004000 ; 2.3 Interrupt request on BR7 or BR6 (high) [R] +%UBLOW==:002000 ; 2.2 Interrupt request on BR5 or BR4 (low) [R] +%UBPWR==:001000 ; 2.1 Power low [R/*] +%UBDXF==:000200 ; 1.8 Disable tranfer on uncorrectable data [R/W] +%UBINI==:000100 ; 1.7 Issue Unibus init [W] +%UBPIH==:000070 ; 1.6 - 1.4 PI level for BR7 or BR6 (high) [R/W] +%UBPIL==:000007 ; 1.3 - 1.1 PI level for BR5 or BR4 (low) [R/W] + +UBAMNT==:763101 ;UBA Maintenance (One per Unibus) + ; 1.2 Spare maintenance bit (?) + ; 1.1 Change NPR address (?) diff --git a/src/system/ksnet.1 b/src/system/ksnet.1 new file mode 100755 index 00000000..ed9fea1d --- /dev/null +++ b/src/system/ksnet.1 @@ -0,0 +1,58 @@ +;;; Chaosnet interface on Unibus + +CAICSR=3,,764140 ;COMMAND STATUS REG +CH%CSR==0 + %CABSY==1 ;0 XMT BUSY (RO) + %CALUP==2 ;1 LOOP BACK (R/W) + %CASPY==4 ;2 RECIEVE MSGS FOR ANY DESTINATION (R/W) + %CARCL==10 ;3 CLEAR THE RECEIVER, IT CAN NOW GOBBLE ANOTHER MSG (WO) + %CAREN==20 ;4 RCV INT ENB (R/W) + %CATEN==40 ;5 XMT INT ENB (R/W) + %CATAB==100 ;6 TRANSMIT ABORTED BY ETHER CONFLICT (RO) + %CATDN==200 ;7 TRANSMIT DONE. SET WHEN TRANSMITTER IS DONE + %CATCL==400 ;8 CLEAR THE TRANSMITTER, MAKING IT READY (WO) + $CALOS==110400 ;9-12 LOST COUNT (RO) [# MSGS RCVED WITH RCV BFR FULL] + ; WHEN MSG IS WAITING IN BUFFER, THIS COUNTS + ; THE MESSAGES THAT MATCHED OUR DESTINATION OR + ; WERE BROADCAST, BUT COULDN'T BE RECIEVED. + ; WHEN RECEIVER IS RE-ENABLED (WRITE 1 INTO %CARDN) + ; THE COUNT IS THEN CLEARED. + ; WHEN A MESSAGE IS LOST, RECEIVER ZAPS ETHER + ; SO TRANSMITTER WILL ABORT (IF MESSAGE WAS DESTINED + ; TO US.) + %CARST==20000 ;13 I/O RESET (WO) + %CAERR==40000 ;14 CRC ERROR (RO) + %CARDN==100000 ;15 RCV DONE. + +CAIMYN==3,,764142 ;MY # (READ ONLY) +CH%MYN==2 ;RETURNS THE [SOURCE] HOST# OF THIS INTERFACE. + +CAIWBF=3,,764142 ;WRITE BUFFER (WRITE ONLY) +CH%WBF==2 ;FIRST WAIT FOR TDONE. (OR SET IT VIA CSR) + ;FIRST WORD IN RESETS TRANSMITTER AND CLEARS TDONE. + ;STORE INTO THIS REGISTER TO WRITE WORDS OF MESSAGE, + ;LAST WORD IN IS DESTINATION ADDRESS, THEN READ CAIXMT. + ;SOURCE ADDRESS AND CHECK WORD PUT IN BY HARDWARE. + +CAIRBF=3,,764144 ;READ BUFFER (READ ONLY) +CH%RBF==4 ;THE FIRST WORD READ WILL BE FILLED TO THE LEFT + ;TO MAKE THE MESSAGE RECIEVED A MULTIPLE OF 16 BITS. + ;IF THE NUMBER OF DATA BITS IN THE MESSAGE WAS A + ;MULTIPLE OF 16, THIS WORD WILL BE THE FIRST WORD PUT + ;INTO THE BUFFER BY THE TRANSMITTING HOST. + ;THE LAST 3 WORDS READ ARE DESTINATION, SOURCE, CHECK. + +CAIRBC=3,,764146 ;RECEIVE BIT COUNTER (READ ONLY) +CH%RBC==6 ;WHEN A MESSAGE HAS BEEN RECEIVED THIS IS ONE LESS THAN + ;THE NUMBER OF BITS IN THE MESSAGE (16 X THE + ;NUMBER OF WORDS INCLUDING THE THREE OVERHEAD WORDS.) + ;AFTER THE LAST WORD (THE CRC WORD) HAS BEEN READ, IT IS 7777 + ;BITS 10 AND 11 ARE THE HIGH ORDER BITS, AND IF THEY ARE ONE, + ;THEN THERE WAS A BUFFER OVERFLOW + +CAIXMT=3,,764152 ;READING THIS INITIATES TRANSMISSION (!!) +CH%XMT==12 ;THE VALUE READ IS ONE'S OWN HOST#. + +;REFERENCING ADDRESSES IN THE GROUP OF 8 WORDS NOT LISTED HERE, OR +;USING COMBINATIONS OF READ/WRITE NOT LISTED HERE, WILL TYPICALLY CAUSE +;STRANGE AND BIZARRE EFFECTS. diff --git a/src/system/lhdh.defs5 b/src/system/lhdh.defs5 new file mode 100755 index 00000000..89562dbb --- /dev/null +++ b/src/system/lhdh.defs5 @@ -0,0 +1,80 @@ +;;; -*- Mode: Midas -*- +.AUXIL + +;;; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + +; The ACC IMP interface on the KS implements two separate Unibus IO +; devices, for input and output. Both of these devices transfer data in +; 32-bit mode only over the Unibus via DMA. Because of the DMA data +; transfer the interrupt structure is trivial, and uses NETCHN only. +; +; Apparently the reset bits in the two CSRs are wired together, so +; resetting one side of the machine resets both. This action also drops +; the HOST READY line to the IMP. +; +; You must set %LHSE whenever hte HOST READY line is high, or the IMP +; will be allowed to freely throw away data. This is true across IMP +; message boundaries, and even if no input request is active. +; + +;ACC LH-DH IMP Interface Bits + +;Interrupt information +DEFSYM %LHVEC==250 ;Input side interrupt vector (non-standard) + ;Output side assumed to be %LHVEC+4 +DEFSYM %LHPRI==6 ;Interrupt priority (non-standard) + +DEFSYM %LHBAS==767600 ;Base of LH/DH Unibus register address space + +;Unibus Registers +DEFSYM %LHICS=:%LHBAS ;Control and Status, Input side +DEFSYM %LHIDB=:%LHBAS+2 ;Data Buffer, Input +DEFSYM %LHICA=:%LHBAS+4 ;Current Word Address, Input +DEFSYM %LHIWC=:%LHBAS+6 ;Word Count, Input + +DEFSYM %LHOCS=:%LHBAS+10 ;Control and Status, Output side +DEFSYM %LHODB=:%LHBAS+12 ;Data Buffer, Output +DEFSYM %LHOCA=:%LHBAS+14 ;Current Word Address, Output +DEFSYM %LHOWC=:%LHBAS+16 ;Word Count, Output + +;Bits in CSRs +; Bits common to input and output +DEFSYM %LHERR==1_15. ;Error present +DEFSYM %LHNXM==1_14. ;Non Existant Memory on DMA +DEFSYM %LHMRE==1_9. ;Master Ready Error (ready bounce during xfr) +DEFSYM %LHRDY==1_7. ;Device Ready (modifying LHDH regs allowed) +DEFSYM %LHIE==1_6. ;Interrupt Enable +DEFSYM %LHA17==1_5. ;Address bit 17 for extended unibus xfrs +DEFSYM %LHA16==1_4. ;Address bit 16 for extended unibus xfrs +DEFSYM %LHRST==1_1. ;Interface Reset +DEFSYM %LHGO==1 ;GO - Start DMA Transfer + +; Input side +DEFSYM %LHEOM==1_13. ;End-of-Message received from IMP +DEFSYM %LHHR==1_11. ;Host Ready (ACC's relay closed, debounced) +DEFSYM %LHINR==1_10. ;IMP not ready +DEFSYM %LHIBF==1_8. ;Input Buffer Full +DEFSYM %LHSE==1_3. ;Store Enable (0 == flush data instead) +DEFSYM %LHHRC==1_2. ;Host Ready Relay Control (1 to close relay) + +; Output side +DEFSYM %LHWC0==1_13. ;Output Word Count is zero +DEFSYM %LHOBE==1_8. ;Output Buffer Empty +DEFSYM %LHBB==1_3. ;Bus Back (loopback enable for testing) +DEFSYM %LHELB==1_2. ;Send EOM indication to IMP at end of xfr + ; (enable Last Bit Flag) +IFN $$TEMP,EXPUNG DEFSYM + diff --git a/src/system/mtape.197 b/src/system/mtape.197 new file mode 100755 index 00000000..edeed6e5 --- /dev/null +++ b/src/system/mtape.197 @@ -0,0 +1,1461 @@ +;******************************** +;** +;** TO BE DONE: +;** +;** RECORDS LONGER THAN 1K +;** AUTOMTAIC DETERMINATION OF DENSITY AND RECORD LENGTH WHEN READING +;** ALLOW CLOSE WHEN TAPE HAS BEEN TAKEN OFF +;** BE MORE FORGIVING OF CONTROLLER LOSSAGE +;** PASS .MTAPE TO JOB DEVICE +;** HAVE AN IGNORE ERRORS SWITCH +;** THIS HORRIBLE BLETCHEROUS IOT CODE SHOULD BE REDESIGNED +;** +;******************************** + + +IFN TM10A,TM10B==0 +IFE TM10A,TM10B==1 +IFN TM10A,INFORM IO BUSS MAG TAPE,1 +IFN TM10B,INFORM DATA CHANNEL MAG TAPE,1 +MSCBL==8 ; COMMAND BUFFER LENGTH +MGQDLL==6 ; INTERUPT LEVEL PDL +IF2 IFN MNUMB-140600, .ERR IMPLICIT DEPENDENCY ON MNUMB +MSEOFP==210100 ;HIGH BIT OF MNUMB IN MEMBLT IS EOF FLAG +MSCHN==140500 ;OTHER 5 BITS OF MNUMB IN MEMBLT IS DRIVE NUMBER + +MTXP==410300,, ;XPORT NUMBER +MUNITF==170300 ; UNIT FIELD IN MTC CONI +MNOPIN==10000 +MWRITE==4000 +MW3IN==14000 +MSPRR==7000 +MREAD==2000 +MSPFR==6000 +MSPFF==16000 +MSPRF==17000 +MREWND==1000 +MRWNDD==11000 +MWEOF==5000 +MGNRTY==10. ;NUMBER OF READ RETRIES + +SUBTTL MAG TAPE OPEN ROUTINE + +; C/ MODE,,DEV +; D/ MODE (ROT 1) 4.9=1=>OUTPUT +; I/ DEVICE NUMBER +; R/ IOCHNM WORD POINTER + +MAGTO: SKIPL W,I ; GET DEVICE + CAIL W,NMTCS ; TO BIG? + JRST OPNL1 ; NO SUCH DEVICE + MOVSI T,%MAREW + TDNE T,MSRAC(W) ; REWINDING + PUSHJ P,UFLS ; YES, THEN WAIT + CONO PI,CLKOFF ; DON'T WANT STATUS CHANGED FROM UNDER ME + SKIPGE MTUSE(W) ; CHECK FOR FIRST USER + JRST MAGTU1 ; FIRST + CAME U,MTUSR(W) ;SAME USER + JRST OPNL10 ; DIFFERENT USER IS ERROR + MOVE B,D + EQV B,MSCRW(W) + SKIPL B ; CHECK FOR SECOND OPEN IN SAME DIRECTION + JRST OPNL2 ; WRONG DIRECTION +MAGTU: MOVEM U,MTUSR(W) ; STORE USER + SETZM MSCRW(W) ; INDICATE READ UNTIL FOUND TO BE OTHERWISE + TLNE C,1 ; READ OR WRITE + SETOM MSCRW(W) ;INDICATE WRITE + AOS MTUSE(W) ;INDICATE 1 MORE USER + PUSHJ P,SOSSET + MTUSE(W) ; SOS IF PCLSRED + CONO PI,CLKON ; LET UM GET ME + PUSHJ P,MTSTAT ; GET CONIS OF 340 AND 344 IN I AND J + MOVE A,MSRAC(W) + TLNE A,%MAERR ; PI ERROR MEANS DEVICE NOT THERE + JRST MTOL1 + TRNN J,200040 + JRST OPNL7 ; DEVICE NOT ONLINE + SKIPN MSCRW(W) ;WRITING? + JRST MTOW1 + TRNE J,10 ; AND WRITE LOCKED + JRST OPNL26 ; DEVICE WRITELOCKED + SKIPE MSRAC(W) ; WRITING + TRNN J,4000 ;EOT? + JRST MTOW1 ; NO + MOVSI A,%MAETW+%MAERR ; IF WRITE AND EOT,MAKE .IOT GIVE IOC ERROR BUT LET OPEN WIN + IORM A,MSRAC(W) +MTOW1: TRNN J,400000 ; XPORT HUNG + JRST MTOW2 ; OK + TRNN J,20000 ; OK IF REWINDING + JRST OPNL7 ;DEVICE NOT WORKING +MTOW2: TLNN C,400 ; GET CORE DUMP MODE + JRST MTOW3 + TLNN C,300 + JRST MTOW3 + TLC C,300 + TLCE C,300 ; IBM AND DENSITY 800 BPI OK + JRST OPNL12 ; MODE NOT AVAILABLE +MTOW3: ;BY THIS POINT OPEN WILL WIN + PUSHJ P,LSWDEL ; RELEASE MTUSE SWITCH + MOVEI A,MTCCHN_3 ;SET UP MAG TAPE CONO +IFN TM10A, TRO A,1 ; DATA PI CHANNEL + LDB B,[300200,,C] ; GET DENSITY FROM OPEN + SKIPN B + MOVEI B,3 + SUBI B,1 ; CONVERT TO PROPER PARITY + DPB B,[060200,,A] + TLNN C,400 ; CORE DUMP + TRO A,20000 ; YES + TLNN C,40 ; PARITY CHECK + TRO A,40000 ; SET ODD PARITY + DPB W,[170300,,A] ; SET UNIT NUMBER + MOVEM A,MTCONO(W) ; STORE IT + LDB B,[330300,,C] ; GET WORDS PER BLOCK + TRC B,7 + MOVEI A,10 + LSH A,(B) ;NUMBER OF WORDS PER RECORD + MOVEM A,MTBLKS(W) ;BLOCKSIZE + LDB A,[230200,,C] ; GET MODE (BUT NOT READ/WRITE BIT) + HLR C,MTOPTB(A) ; GET INPUT DISPATCH + TLNE D,400000 ; OPEN FOR OUTPUT? + HRR C,MTOPTB(A);CHANGE TO OUTPUT IF SO + MOVEM C,(R) ;STORE IN IOCHNM + DPB W,[MTXP(R)] ; STORE XPORT NUMBER + JRST POPJ1 ; SKIP RETURN + +MTOPTB: MTUAIX,,MTUAOX + MTBIX,,MTBOX + MTUIIX,,MTUIOX + MTBIX,,MTBOX + +MAGTU1: SETZM MSBUFP(W) ; INDICATE NO BUFFERS ON CHAIN + SETZM MSNBOL(W) ; ANOTHER WAY OF SAYING ABOVE + SETZM MSMPRC(W) ; BUFFER WORDS REMAINING + SETZM MSMPRP(W) ; POINTER TO BUFFERS + SETOM MTMDN(W) ;NO BUFFER AT MP + SETOM MGCABN(W) ;NONE AT PI + SETZM MSRAC(W) + MOVEI A,2 + MOVEM A,MTCEFW(W) ; NUMBER OF EOF'S WRITTEN + MOVSI A,%MANWT + IORM A,MSRAC(W) ; INDICATE NOTHING WRITTEN ON TAPE + JRST MAGTU + +MTOL1: SETZM MSRAC(W) + JRST OPNL1 + +SUBTTL MAG TAPE INPUT .IOT ROUTINES + + SKIPA B,[SIOKT] +MTUAI: MOVEI B,CHRKTI ;UNIT ASCII INPUT + MOVE E,[440700,,5] + JRST MTREAD + + SKIPA B,[SIOKT] +MTUII: MOVEI B,CHRKTI ;UNIT IMAGE + MOVE E,[444400,,1] + JRST MTREAD + +MTBI: MOVE E,[444400,,1] ;BLOCK INPUT + MOVEI B,BLKT +MTREAD: LDB W,[MTXP(R)] ; W <= XPT # + PUSHJ P,MTIECK + MOVEM P,MTPSAV(W) ; SAVE P FOR EOF RETURN + JSP B,(B) ;BLKT,CHRKT,SIOKT + MSMPRP(W) ;LOC OF NEXT WORD + MSMPRC(W) ;COUNT REMAINING + SETZ MTRBG ; GET NEW BUFFER (SETZ FOR CHRKT RETURN ON EOF) + MTRBD ; DISCARD BUFFER + JRST 4,. + PUSHJ P,MTRBFW ; FLUSH INSTRUCTION WAIT FOR BUFFERS TO COME FROM PI + +;MAG TAPE READ BUFFER GET ROUTINE +; BUFFER ASSUMED TO HAVE COME IN FROM PI LEVEL. (I.E. MTRBFW WAS CALLED) + +MTRBG: SKIPG MSNBOL(W) ;ANY BUFFER AVAILABLE? + JRST MTRBG3 ;NO, MUST BE ERROR OR EOF + CONO PI,UTCOFF + HLRZ A,MSBUFP(W) ; GET IN POINTER + HRRZ TT,MSBUFP(W) ; GET OUT POINTER + MOVEM TT,MTMDN(W) ; STORE BUFFER ACTIVE AT MP + CAMN A,TT ;IN = OUT? + JRST MTRBG1 ; YES + LDB T,[MLO,,MEMBLT(TT)] ; BACK POINTER TO NEXT BLOCK + HRRM T,MSBUFP(W) ;STORE NEW OUT POINTER + JRST MTRBG2 + +MTRBG1: SETZM MSBUFP(W) ;EMPTY BUFFER LIST +MTRBG2: SOS MSNBOL(W) ; ONE LESS BUFFER ON LIST + CONO PI,UTCON + LDB J,[MWC,,MEMBLT(TT)] ;WORD COUNT OF BLOCK + MOVEM J,MTBLKS(W) ;SAVE FOR MTAPE 13 + LSH TT,10. ;MAKE BLOCK NUMBER AN ADDRESS + MOVEM TT,MSMPRP(W) + JRST SIOBGX + +MTRBG3: SKIPGE MSRAC(W) .SEE %MAEOF + JRST [ MOVSI T,%MAEFA ;THE EOF IS NOW NO LONGER READ-AHEAD + ANDCAM T,MSRAC(W) ;TELL THE USER ABOUT IT + JRST POPJ2 ] + PUSHJ P,MTIECK + JRST 4,. ;BULLSHIT, WHY DID MTRBFW SKIP? + +;MAG TAPE READ BUFFER DISCARD ROUTINE +MTRBD: SKIPGE A,MTMDN(W) ; ANY BUFFERS + JRST MOVTWJ ;SET UP T FOR BUFFER WAIT,RETURN + CONO PI,UTCOFF ; SHUT UP WORLD + SETOM MTMDN(W) ; NO BUFFER ACTIVE AT M.P. + SETZM MSMPRC(W) + LDB TT,[MSEOFP,,MEMBLT(A)] ;GET EOF FLAG FROM PI + PUSHJ P,MGMEMR ;RETURN MEM, TURN UTCON + JUMPN TT,MTRBD2 ;EOF? +MOVTWJ: MOVE T,W ; T NEEDS CHANNEL NUMBER FOR BUFFER WAIT UFLUSH + POPJ P, ;ALSO MTRBG, MTRBFW RELY ON THIS SETTING T + +MTRBD2: MOVSI A,%MAEOF ; SET EOF + IORM A,MSRAC(W) + JRST MOVTWJ + +;MAG TAPE READ WAIT FOR DATA ROUTINE +MTRBFW: SKIPG MSNBOL(T) ; ANY FREE BUFFERS ON LIST? + SKIPGE MSRAC(T) .SEE %MAEOF + JRST POPJ1 ;INPUT AVAILABLE, OR AT EOF, UNHANG + MOVE TT,MSRAC(T) + TLNE TT,%MAERR ; CHECK FOR ERRORS + JRST POPJ1 ;WAKE UP SO YOU CAN GET YOUR IOC ERROR + TLNE TT,%MARAC ; IF NOT ALREADY DONE SO, SEND OUT A CALL FOR TAPE READ + POPJ P, + PUSH P,W ;THIS BEING DONE UNDER A UFLS. ONLY T GOOD + PUSH P,B + MOVE W,T + MOVEI B,MGREAD ;WHERE TO GO AT PI LEVEL + MOVEI T,MSCBL ;MAKE SURE THAT THERE IS ROOM IN THE RING BUFFER + CAMG T,MSCMDC(W) + JRST MTRBW2 ; NO ROOM, GO AWAY + MOVSI TT,%MARAC + IORM TT,MSRAC(W) ;READ IS ACTIVE NOW, OR WILL BE SHORTLY + PUSHJ P,MTCMD1 +MTRBW2: MOVE T,W + POP P,B + POP P,W + POPJ P, + +SUBTTL MAG TAPE OUTPUT .IOT ROUTINES + + SKIPA B,[SIOKT] +MTUAO: MOVEI B,CHRKT ;UNIT ASCII OUTPUT + MOVE E,[440700,,5] + JRST MTWRIT + + SKIPA B,[SIOKT] +MTUIO: MOVEI B,CHRKT ;UNIT IMAGE OUTPUT + MOVE E,[444400,,1] + JRST MTWRIT + +MTBO: MOVE E,[444400,,1] ; BLOCK OUT + MOVEI B,BLKT +MTWRIT: LDB W,[MTXP(R)] ; GET XPORT NUMBER + PUSHJ P,MTIECK + HRLZI A,%MAETW ; END OF TAPE CHECK + TDNE A,MSRAC(W) + JRST IOCER9 + JSP B,(B) + SETZ MSMPRP(W) ;LOC OF WORD + MSMPRC(W) ; COUNT + SETZ MTWBFG ; GET NEW BUFFER + MTWBFD ; WRITE OUT BUFFERS + JRST 4,. + TRNA ;NO WAIT FOR BUFFER + +;MAG TAPE WRITE BUFFER GET ROUTINE + +MTWBFG: PUSHJ P,MTIECK + PUSHJ P,TCALL ; TURN OFF UTC + JRST IOMQ + POPJ P, ;GO BACK NO SKIP IF NO CORE + MOVEM A,MTMDN(W) ; STORE ACTIVE BUFFER NUMBER + MOVEI T,MUMGB + DPB T,[MUR,,MEMBLT(A)] ; TELL WORLD THAT IT IS A MAG TAPE BUFFER + DPB W,[MSCHN,,MEMBLT(A)] ; CHANNEL NUMBER + SETZM TT + DPB A,[121000,,TT] ;CONVERT BLOCK NUMBER TO ADDRESS IN TT + MOVE J,MTBLKS(W) ;GET WRITE BLOCK SIZE + JRST SIOBGX + +;MAG TAPE WRITE BUFFER DISCARD ROUTINE + +MTWBFD: PUSHJ P,MTIECK + SKIPGE A,MTMDN(W) + POPJ P, + MOVEI T,MSCBL + CAMG T,MSCMDC(W) + PUSHJ P,UFLS ; MAKE SURE ROOM IN COMMAND BUFFER EXISTS IN CASE OF PCLSRING + MOVE T,MTBLKS(W) ; DISCARD BUFFER. FIRST SEE HOW BIG IT IS + SUB T,MSMPRC(W) + CONO PI,UTCOFF ;CAN'T TOLERATE ANY HANKY PANKY + SETOM MTMDN(W) ;CLEAR IT + SETZM MSMPRC(W) ; CLEAR COUNT + JUMPE T,MEMR ; DON'T DO ANYTHING BUT RETURN BLOCK IF NO WORDS + DPB T,[MWC,,MEMBLT(A)] ; STORE WORD COUNT + SKIPG MSNBOL(W) ; LIST STARTED YET? + JRST MTWBD1 ;NO + HLRZ TT,MSBUFP(W) ; GET OLD IN POINTER + DPB A,[MLO,,MEMBLT(TT)] ;CHAIN BACK + SKIPA +MTWBD1: HRRM A,MSBUFP(W) ; START NEW LIST + HRLM A,MSBUFP(W) ; IN = OUT = (A) +MTWBD2: SETZM TT + DPB TT,[MLO,,MEMBLT(A)] ; INDICATE END OF LIST + AOS MSNBOL(W) ; ONE MORE BUFFER ON LIST + CONO PI,UTCON + PUSH P,B + MOVEI B,MGWRIT + PUSHJ P,MTCMD + MOVSI B,%MANWT + ANDCAM B,MSRAC(W) + SETZM MTCEFW(W) ; INDICATE SOMETHING WRITTEN + JRST POPBJ ; RETURN + +SUBTTL MTCMD - GIVE COMMAND TO PI LEVEL + +;PUSHJ P,MTCMD + ;RH(W) HAS XPORT NUMBER + ;RH(B) HAS ADDR OF INTERUPT ROUTINE + +MTCMD: MOVEI T,MSCBL ; COMAND BUFFER LENGTH + CAMG T,MSCMDC(W) ;COMAND COUNT + PUSHJ P,UFLS ; WAIT FOR ROOM +MTCMD1: MOVE T,MTCMBP(W) ; GET POINTER TO RING BUFFER + AOBJN T,.+2 + SUB T,[MSCBL,,MSCBL] ; REACHED END OF BUFFER, RING IT + MOVEM B,(T) ; STORE COMMAND + MOVEM T,MTCMBP(W) ; STORE NEW POINTER + CONO PI,UTCOFF + AOS MSCMDC(W) ; INDICATE ONE MORE COMMAND + JRST MSTRTR ; START UP PI ROUTINE + +SUBTTL MTIECK - CHECK FOR IOC ERROR + +MTIECK: PUSH P,A ; CHECK FOR IOTERR + MOVE A,MSRAC(W) + TLNN A,%MAERR ; ERROR AT PI? + JRST POPAJ + SKIPLE MSCMDC(W) + PUSHJ P,UFLS ; LET PI CLEAR BEFORE MUNGING BUFFERS + SKIPL A,MTMDN(W) + PUSHJ P,MEMR + SETOM MTMDN(W) + SETZM MSMPRP(W) + SETZM MSMPRP(W) + PUSHJ P,MTCBFF ; FREE CHAIN + POP P,A + MOVE T,MGCMTS(W) ; GET CONI MTS, + TRNE T,440000 ; XPT HUNG,ILLOP + JRST IOCER1 + TRNE T,23600 ; PAR ERROR,R/C, RLI,DL,BT + JRST IOCER3 ; IRRECORVERABLE DATA ERROR + TRNE T,4000 ; EOT + JRST IOCER9 ; EOT, DEV FULL + MOVE A,MGEOFR(W) ; LOGICAL EOT + CAIL A,2 + JRST IOCER9 + JRST IOCER3 ; UNKNOWN, GIVE IRR DATA + +SUBTTL MAG TAPE .STATUS ROUTINE + +STAMTC: LDB W,[MTXP(R)] ; LOAD W + DPB A,[60300,,D] ; OPEN MODE + PUSHJ P,MTSTAT + LDB A,[.BP %MAETW_22,MSRAC(W)] ; EOT ON WRITE + LDB B,[.BP %MAETR_22,MSRAC(W)] ; EOT ON READ + IOR A,B + DPB B,[140100,,D] ;EOT + LDB A,[20100,,J] + TRC A,1 + DPB A,[150100,,D] ; 7 OR 9 + LDB A,[160100,,MTCONO(W)] + TRC A,1 + DPB A,[200100,,D] ;PARITY + LDB A,[60200,,MTCONO(W)] ; DENSITY + ADDI A,1 + CAIN A,3 + SETZM A ; 800 IS 00 + DPB A,[160200,,D] + LDB A,[.BP %MARCE_22,MSRAC(W)] ; READ COMPARE ERROR + DPB A,[130100,,D] + MOVE A,MTCONO(W) + TRNN J,4 ; 7 TRACK + TRNE A,20000 ; OR CORE DUMP + POPJ P, ; THEN DONE + TRO D,140000 ; IBM, 9 TRACK AND 800 BPI + POPJ P, + + +;RCHST ROUTINE FOR MAG TAPE + +RCHMGT: HLRZ E,(R) ;OPEN-MODE IS KEPT IN LH OF IOCHNM WORD - HOW CONVENIENT! + LDB J,[MTXP(R)] ;GET THE MAG TAPE DRIVE NUMBER + MOVSI J,'MT0(J) ;RETURN THAT DRIVE'S DEVICE NAME. + TRZ E,(.BM MTXP) ;CLEAR THE PLACE IN THE OPEN-MODE THAT HAS THE DRIVE #. + JRST POPJ1 ;SKIP SO THAT J OVERRIDES BUILT-IN DEVICE NAME. + + EBLK + +SUBTTL MAG TAPE STORAGE AREA + +MGVTC: 0 ; 1 SCRATCH WORD FOR VIRGIN TAPE CHECK +MGRWCD: BLOCK NMTCS ; REWIND COMMAND +MGEOTT: BLOCK NMTCS ; TIMEOUT FOR VIRGIN TAPE +MGJDTI: 0 ; WAIT FOR JOB DONE TIME OUT +MGEOFR: BLOCK NMTCS ; NUMBER OF EOFS SINCE LAST READ +MGNWRD: 0 ; NUMBER OF WORDS READ IN A PI LEVEL READ +MTPSAV: BLOCK NMTCS ; STORAGE TO RESTORE P ON EOF +MSRAC: BLOCK NMTCS ; MAG TAPE GENERAL GARBAGE + %MA==1,,525252 + %MAEOF==400000 ; 4.9 EOF ON READ + %MAETR==200000 ; 4.8 EOT ON INTERNAL READ + %MAETW==100000 ; 4.7 EOT ON WRITE + %MAERR==040000 ; 4.6 PI ERROR + %MARCE==020000 ; 4.5 READ COMPARE ERROR + %MACTH==014000 ; 4.4 CORE ALLOCATOR SAYS STOP + ; 4.3 " (WHY 2 BITS?) + %MASTP==002000 ; 4.2 STOP READ AHEAD + %MANWT==001000 ; 4.1 NOTHING WRITTEN ON TAPE YET + %MAEFA==000400 ; 3.9 EOF SEEN ON READ-AHEAD, USER HASN'T SEEN YET + %MAESO==000200 ; 3.8 EOF READ SINCE OPEN + %MAMSO==000100 ; 3.7 TAPE MOVED SINCE FIRST OPEN + %MAREW==000040 ; 3.6 REWINDING FLAG + %MARAC==000020 ; 3.5 READ ACTIVE FLAG +MGTBZY: -1 ; FLAG TO GET INTURPT STARTED +MTCONO: REPEAT NMTCS,\.RPCNT_17+20 ; MAIN CONO STORAGE +MGUNIT: -1 ; UNIT EXPECTING INTERUPT +MGCMTS: BLOCK NMTCS ; PI CONI MTS STORAGE +MGCMTC: BLOCK NMTCS ; PI MTC STORAGE +MGWCW: 0 ; WAIT FOR CONTROL WORD WRITTEN FLAG +LMIOWD: 0 ; LAST MIOWD +MGERRC: BLOCK NMTCS ; ERROR COUNT +MTMFNC: BLOCK NMTCS ; .MTAPE FUNCTION STORAGE +MTMCNT: BLOCK NMTCS ; .MTAPE COUNT +MTMTAP: BLOCK NMTCS ; MTAPE CALL WORD +MTCEFW: BLOCK NMTCS ; NUMBER OF EOF'S WRITTEN AT CLOSE +MSCMDC: REPEAT NMTCS,0 ; NUMBER OF COMMANDS +MSBUFP: REPEAT NMTCS,0 ; MAG TAPE BUFFER POINTER IN,,OUT +MSCRW: BLOCK NMTCS ; -1=>OUTPUT 0=>INPUT +MSMPRC: BLOCK NMTCS ; WORDS LEFT IN BUFFER +MSMPRP: BLOCK NMTCS ;NEXT WORD IN BUFFER +MTMDN: REPEAT NMTCS,-1 ; BLOCK ACTIVE AT MP +MTUSE: REPEAT NMTCS,-1 ; NUMBER OF CHANNELS OPEN ON THIS MTAPE +MTUSR: REPEAT NMTCS,-1 ; USER INDEX OF XPORT +MSNBOL: BLOCK NMTCS ; NUMBER OF BUFFERS ON LIST +MGCABN: REPEAT NMTCS,-1 ; BUFFER ACTIVE AT PI LEVEL +MTBLKS: BLOCK NMTCS ; WRITE, BUFFER SIZE + ; READ, SIZE OF LAST RECORD READ +MGQDLP: REPEAT NMTCS,-MGQDLL,,CONC MGQD,\.RPCNT,-1 ;QDL POINTER +REPEAT NMTCS,[ + CONC MSCB,\.RPCNT,: BLOCK MSCBL ; COMMAND BUFFER + MGRCV ; TO RING BUFFER + + MGNCMD ; GET NEW COMMAND + CONC MGQD,\.RPCNT,: BLOCK MGQDLL + IFE .RPCNT,MSLCTB==.-MSCB0 ; LENGTH OF EACH TABLE +] +MTCMBP: REPEAT NMTCS,-MSCBL-1,,CONC MSCB,\.RPCNT,-1 ; INPUT TO COMMAND TABLE +MGCMBP: REPEAT NMTCS,4400,,CONC MSCB,\.RPCNT,-1 ; OUTPUT FROM COMAND TABLE +IFE KL10P,MIOWD: BLOCK 2 ; CHANNEL PROGRAM +IFN TM10A,[ +MGDBRK: 0 + CONO MTS,1 + JRST 12,@MGDBRK +];TM10A +MGEMTC: 0 ;CONI MTC, AT LAST ERROR +MGEMTS: 0 ;CONI MTS, AT LAST ERROR +BBLK + +SUBTTL MAG TAPE PI LEVEL + +;ROUTINES TO GET INTERUPT ROUTINES STARTED +MGXGO: MOVE Q,MGQDLP(W) ;GET QDLPOINTER + PUSHJ P,QPOPJ ;CALL ROUTINE . SHOULD FINISH WITH POPJ P,OR PUSHJ Q,CPOPJ + ;PUSHJ Q,CPOPJ IF ROUTINE WANTS TO RETURN + ;POPJ P, IF AT END OF COMAND. AND NEW IS TO BE GOTTEN + MOVEM Q,MGQDLP(W) ; STORE NEW QDL + POPJ P, + +MGRCV: MOVNI A,MSCBL+1 ;AT END OF COMAND LIST,RING IT + ADDM A,MGCMBP(W) ;RING THE BUFFER +MGNCM1: ILDB B,MGCMBP(W) ; GET NEW COMMAND + JRST (B) + +MGNCMD: AOBJN Q,MGNCM1 ; AT BOTTOM OF QDL, SIMULATE PUSHJ AND GET NEW COMMAND + JRST 4,. ;QDL POINTER CLOBBERED + +QPOPJ1: AOS (Q) +QPOPJ: POPJ Q, + +MSTRTR: CONO PI,UTCOFF ; GET MAGTAPE INTURPT STARTED + SETZM MGTBZY + CONO PI,MTCRQ + CONO PI,UTCON + POPJ P, + +;HERE FOR MAG TAPE FLAG CHANNEL INTERUPT +MGHBRK: SKIPGE W,MGUNIT ; LOAD UNIT + JRST MGUBRK ;NO ONE WANTS IT + LDB B,[MUNITF,,A] + CAME W,B ; UNITS AGREE + JRST 4,. ; WE MUST NOT MIX UNITS + MOVE J,C + PUSH P,[DSKEX] +IFN TM10B,[ + TLNE C,160 + JRST MGERR +];TM10B + TRNE C,40000 + JRST MGERR + JRST MGXGO + +MGSBRK: SETOM MGTBZY ;HERE FOR ANY RANDOM MP PI STARTUP + MOVEI B,NMTCS-1 + SKIPG MSCMDC(B) ;ANY COMMANDS IN BUFFER +MGSBK1: SOJGE B,.-1 + SKIPGE B ;LAST UNIT? + JRST DSKEX ; THEN GOTO DSKEX + MOVE W,B + PUSH P,B + MOVSI B,%MACTH + TDNN B,MSRAC(W) ; CORE ALLOCATOR SAYING GO AWAY + PUSHJ P,MGXGO ; START UP THAT ROUTINE + POP P,B + JRST MGSBK1 ; ANY MORE? + +MGUBRK: LDB W,[MUNITF,,A] ; WHO CAUSED INTERUPT? + MOVE B,MTCONO(W) + CONO MTC,(B) + CONO MTS,31 ; CLEAR INTERUPT + JRST DSKEX + +; ROUTINE TO WAIT FOR JOB DONE TO SET +MGWTJD: CONI MTS,J + TRNE J,440000 ;SKIP IF STARTED SUCCESSFULLY + JRST MGERR ;JOB-DONE ISN'T EVER GOING TO SET +MGWJD1: CONI MTS,J + SKIPN MGJDTI ; TIME OUT? + JRST MGWJD2 + MOVE T,TIME + CAML T,MGJDTI + JRST MGERR +MGWJD2: TRNN J,100 ; JOB DONE? + JRST MGOVER ; NOT SET + CONI MTS,J + CONI MTC,I ; GET CONI MTC + MOVEM J,MGCMTS(W) + MOVEM I,MGCMTC(W) + SKIPE MGWCW ; SHOULD I WAIT FOR CONTROL WORD WRITTEN + PUSHJ Q,MGWCWC ; CHECK TO SEE IF IT IS WRITTEN + SETZM MGWCW ;CLEAR FLAG + CONO MTS,30 ; CLEAR CHANNEL CONDITIONS + MOVE B,MTCONO(W) + CONO MTC,(B) ; RELESE MTC, CLEAR JOB DONE +IFN TM10B,[ + TLNE J,160 + POPJ Q, ;CHANNEL ERROR +] + TRNE J,463600 + POPJ Q, ; RANDOM OTHER NON PERFECTIONS, NOT NECESSARILY ERRORS + JRST QPOPJ1 ; SUCCESS + +; GET XPORT +MGGXPT: CONSO MTS,2 ; LOAD NEXT UNIT SET? + JRST MGOVER ; NO, WAIT FOR IT + MOVEM W,MGUNIT + MOVE T,TIME + ADDI T,10.*30. ; TIME OUT IN 10. SECONDS + MOVEM T,MGJDTI + MOVE B,MTCONO(W) + CONO MTC,MNOPIN(B) ; SELECT DRIVE + PUSHJ Q,MGWJD1 + JFCL ; WAIT FOR JOB DONE, BUT ALLOW ANY ERRORS + SETZM MGJDTI + POPJ Q, + +MGOVER: CONSZ MTS,440020 ; ANY PROBLEMS? + JRST MGERR ;TAPE HUNG, ILL FUNCTION, CHANNEL ERROR + SOS (Q) + POPJ P, + +;ERROR +MGERR: CONI MTS,MGEMTS + CONI MTC,MGEMTC + MOVSI T,%MARAC ;READ NOT ACTIVE, FOR SURE + ANDCAM T,MSRAC(W) + SETZM MSCMDC(W) ; NO COMMANDS + SETOM MGUNIT ; CLEAR UNIT WAIT FLAG + SETZM MGJDTI +IFN TM10B,[ + TLNE J,160 ; CHANNEL ERROR? + BUG PAUSE,[MTAPE: CHANNEL ERROR, STATUS=],OCT,J,[MICWA+1=],OCT,MICWA+1,[MIOWD=],OCT,MIOWD +];TM10B + SKIPL A,MGCABN(W) ; ANY PI BUFFERS? + PUSHJ P,IMEMR + SETOM MGCABN(W) + HRLZI B,%MAERR ; PI ERROR + IORM B,MSRAC(W) ; STORE IN STATUS WORD + MOVE Q,[-MGQDLL,,MGQD0-1] + MOVE T,MSLCTB + IMUL T,W + ADD Q,T ; RESTORE Q + PUSH P,Q + MOVE Q,[-MSCBL-1,,MSCB0-1] + ADD Q,T + MOVEM Q,MTCMBP(W) ; INITIALIZE MP AND PI COMMND POINTERS + MOVE Q,[4400,,MSCB0-1] + ADD Q,T + MOVEM Q,MGCMBP(W) + MOVSI B,%MAREW + ANDCAM B,MSRAC(W) ; CLEAR REWINDING + SKIPN MSCRW(W) ; DONE IF READING + JRST POPQJ + SKIPN MSNBOL(W) ; ANY BUFFERS ON LIST? + JRST POPQJ +MGERR1: HRRZ A,MSBUFP(W) + PUSHJ P,MTICL1 + PUSHJ P,IMEMR + SOSLE MSNBOL(W) ; ANY MORE + JRST MGERR1 + SETZM MSBUFP(W) ;EMPTY LIST + JRST POPQJ + +MGWCWC: +IFN TM10B,[ + SKIPE MICWA+1 ; CONTROL WORD WRITTEN? + POPJ Q, + CONO MTS,4 ; TELL IT TO WRITE IT +MGWCW1: SKIPE MICWA+1 + JRST MGWCW2 ; DONE + PUSHJ Q,CPOPJ ; WAIT + JRST MGWCW1 + +MGWCW2: MOVE I,MGCMTC(W) + MOVE J,MGCMTS(W) ;RESTORE STATUS + TLO J,10 ;SET CONTROL WORD WRITTEN +] ;END OF IFN TM10B + POPJ Q, + +IFN TM10A,[ +MGDCSI: SKIPA A,[BLKI MTC,MIOWD] +MGDCSO: MOVE A,[BLKO MTC,MIOWD] + MOVEM A,MAGLOC + MOVE A,[JSR MGDBRK] + MOVEM A,MAGLOC+1 + POPJ Q, +] ;END OF IFN TM10A + +SUBTTL MAG TAPE PI LEVEL WRITE + +MGWRIT: PUSHJ Q,MGGXPT ; GET XPORT + TRNE J,600010 ; WRITE LOCKED,HUNG OR REWINDING + JRST MGERR + MOVEM W,MGUNIT ; SET UNIT + MOVSI A,%MACTH ; CORE ALLOC WANT QUIT TEMPORARLY + TDNE A,MSRAC(W) + JRST MGWRT4 + HRRZ A,MSBUFP(W) ; GET BUFFER POINTER + HLRZ B,MSBUFP(W) ; IN POINTER + SOS MSNBOL(W) ; ONE LESS BUFFER + MOVEM A,MGCABN(W) ; BUFFER ACTIVE AT PI + SKIPN MSCRW(W) ; WRITING + JRST 4,. + CAME A,B ; IN = OUT + JRST MGWRT1 + SETZM MSBUFP(W) ; EMPTY BUFFER LIST + JRST MGWRT2 + +MGWRT1: LDB B,[MLO,,MEMBLT(A)] ; BACK POINTER + HRRM B,MSBUFP(W) ; NEW OUT POINTER +MGWRT2: LDB B,[MWC,,MEMBLT(A)] ; WORD COUNT + MOVNS B ; NEGATE + HRLZS B ; FORM COUNT +IFN KL10P, LSH B,4 ; SHIFT IF KL10 DATA CHANNEL +IFN KL10P, MOVE R,A ; SAVE CORE PAGE NUMBER FOR CACHE SWEEP + LSH A,10. ; FORM WORD POINTER + SUBI A,1 + HRRM A,B ; CHANNEL POINTER IN B +IFN TM10B, DATAO MTS,[MICWA] ; SET TO GO TO MAG TAPE +IFN TM10A, PUSHJ Q,MGDCSO + MOVEM B,MIOWD + MOVEM B,LMIOWD ; LAST MIOWD + SETZM MIOWD+1 ; TELL CHANNEL TO STOP +IFN KL10P,[ + PUSHJ P,CSHSWP ; UNLOAD BUFFER FROM CACHE INTO CORE + CAI +] + MOVE B,MTCONO(W) + CONO MTC,MWRITE(B) ; DO IT + PUSHJ Q,MGWTJD ; WAIT FOR JOB DONE + JRST MGWBT ; WRITE BLANK TAPE AND TRY AGAIN +MGWRT3: MOVE A,MGCABN(W) ; GET BUFFER NUMBER + HRLZI B,%MAETW+%MAERR ; END OF TAPE CHECK + TRNE J,4000 ; END POINT + IORM B,MSRAC(W) ; TELL MP + LDB T,[MUR,,MEMBLT(A)] + CAIE T,MUMGB ; DO I OWN BLOCK + JRST 4,. + SETOM MGCABN(W) ; NO BUFFER ACTIVE AT PI + PUSHJ P,IMEMR ; GIVE BACK BUFFER + MOVSI A,%MAMSO + IORM A,MSRAC(W) ; TAPE MOVEMENT + JRST MGCMDR + +MGWBT: +IFN TM10B, SETZM MIOWD ; WRITE BLANK TAPE OVER POSSIBLE BAD SPOT +IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD ; ONE RECORD +] + TRNE J,644010 ; BAD TYPES OF ERRORS + JRST MGERR + MOVE B,MTCONO(W) + CONO MTC,MSPRR(B) ; REVERSE 1 RECORD + PUSHJ Q,MGWTJD ; WAIT FOR JOB DONE + JRST MGERR ; ERROR + MOVE B,LMIOWD + MOVEM B,MIOWD ; RESTORE MIOWD + MOVE B,MTCONO(W) + CONO MTC,14000(B) ; WRITE WITH EXTENDED EOR + PUSHJ Q,MGWTJD ; WAIT + JRST MGWBT ; INFINITE RETRIES ; JRST MGERR ; ERRORS + JRST MGWRT3 + +MGWRT4: PUSHJ Q,CPOPJ ; WAIT A WHILE + JRST MGWRIT + +SUBTTL MAG TAPE PI LEVEL READ + +MGREAD: PUSHJ Q,MGGXPT ; GET XPORT +MGRD0: TRNE J,600000 ; UNIT HUNG OR REWINDING OR EOT + JRST MGERR + MOVE B,MGEOFR(W) ; EOF'S READ + CAIL B,2 + JRST MGERR + MOVEM W,MGUNIT ; STORE UNIT NUMBER + SKIPE MSCRW(W) ; MAKE SURE READING + JRST 4,. + MOVSI B,%MACTH ; CORE ALLOCATOR WANT OUT + TDNN B,MSRAC(W) + PUSHJ P,IOMQ + JRST MGROVR ; WAIT FOR IT + MOVEM A,MGCABN(W) ; STORE ACTIVE BUFFER AT PI LEVEL + MOVEI B,MUMGB + DPB B,[MUR,,MEMBLT(A)] ; CLAIM BLOCK + HRREI B,-MGNRTY ; NUMBER OF RETRIES + MOVEM B,MGERRC(W) ; STORE ERROR COUNT +IFN KL10P, MOVE R,A + LSH A,10. ; FORM ADDRESS + SUBI A,1 +IFE KL10P, HRLI B,-2000 +IFN KL10P, HRLI B,-2000_4 + HRR B,A + MOVEM B,LMIOWD ; STORE LAST IOWD FOR RETRY +IFN TM10B, DATAO MTS,[MICWA] ; SET CHANNEL STARTING ADDRESS +IFN TM10A, PUSHJ Q,MGDCSI +IFN TM10B, SETZM MICWA+1 + SETZM MIOWD+1 +MGRD1: MOVEM B,MIOWD ; CHANNEL COMMAND + MOVEI B,2000 + MOVEM B,MGNWRD ; ASSUME AT FIRST THAT THE RECORD TO BE READ HAS 2000 WORDS +IFN KL10P,[ + PUSHJ P,CSHSWP ; ENSURE NO RESIDUE OF THIS PAGE IN CACHE + CAIA +] + MOVE B,MTCONO(W) + CONO MTC,MREAD(B) ; DO IT +IFN TM10B, SETOM MGWCW ; TELL IT TO WAIT FOR CONTROL WORD WRITTEN + PUSHJ Q,MGWTJD ; WAIT FOR JOB DONE + JRST MGRERR +MGRD2: SKIPG A,MGCABN(W) + BUG ;BUFFER SHOULDN'T BE -1, WOULD SCREW UP MEMBLT + SETOM MGCABN(W) ; NO BUFFER ACTIVE AT PI + HLRZ T,MSBUFP(W) ;LAST BUFFER IN + SETZM B + DPB B,[MLO,,MEMBLT(A)] ; BACK POINTER IS 0 + SKIPG MSNBOL(W) + HRRM A,MSBUFP(W) ; ONE BUFFER MEANS IN = OUT + HRLM A,MSBUFP(W) ; NEW IN POINTER + SKIPLE MSNBOL(W) + DPB A,[MLO,,MEMBLT(T)] ; CHAIN BACK BUFFERS + AOS C,MSNBOL(W) ; ONE MORE BUFFER ON LIST (COUNT TO C) + MOVE B,MGNWRD + DPB B,[MWC,,MEMBLT(A)] ; NUMBER OF WORDS IN BUFFER + TRNE J,10000 ;EOF? + JRST [ MOVSI B,%MAESO+%MAEFA ;YES + IORM B,MSRAC(W) + SETO B, + DPB B,[MSEOFP,,MEMBLT(A)] + AOS A,MGEOFR(W) + CAIL A,2 + JRST MGRD4 ; LOGICAL EOT, SPACE BACK OVER IT + JRST .+2 ] + SETZM MGEOFR(W) ; NO EOF + MOVSI A,%MAMSO + IORB A,MSRAC(W) ; TAPE MOVEMENT + TRNE J,4000 ; EOT? + JRST MGRD3 + TRNN J,10000 ;IF NO EOF, NOT 6 BUFFERS YET, + CAIL C,6 + JRST MGRD5 + TLNN A,%MASTP + JRST MGRD0 ; AND NO REQUEST TO STOP, KEEP READING +MGRD5: MOVSI A,%MASTP+%MARAC ;GIVE UP FOR NOW, CLEAR READ ACTIVE + ANDCAM A,MSRAC(W) + JRST MGCMDR ;MP LEVEL WILL SEND NEW READ COMMAND WHEN READY + +MGRD3: DPB B,[MSEOFP,,MEMBLT(A)] ;PHYSICAL EOT + DPB B,[420100,,MSRAC(W)] .SEE %MAETR ; INDICATE EOT ON READ + JRST MGRD5 ; RETURN + +MGRD4: MOVSI A,%MAESO+%MARAC+%MASTP ;SECOND EOF, LOGICAL EOT + ANDCAM A,MSRAC(W) + JRST MGSPRF + +MGRERR: +IFN TM10B,[ + TLNE J,160 + JRST MGERR ; CHANNEL ERROR +] + TRNE J,642000 + JRST MGERR + TRNE J,20600 + JRST MGMRT ; DATA TYPE OF ERROR OR OVERRUN, MAYBE TRY AGAIN +;RECORD LENGTH ERROR, ADJUST MGNWRD +IFN TM10B, HRRZ A,MICWA+1 +IFN TM10A, HRRZ A,MIOWD + HRRZ B,LMIOWD + SUB A,B +IFN TM10B, SOS A ; CHANNEL FUNNYNESS + CAIN A,1 ; POS EOF IS ALL + JRST MGRER2 +MGRER1: MOVEM A,MGNWRD + JRST MGRD2 + +MGRER2: TRNE J,14000 ; 1 WORD, EOF? EOT? + SETZM A ; YES, THIS RECORD HAS ZERO LENGTH, IT JUST CARRIES MSEOFP + JRST MGRER1 + +MGMRT: AOSL MGERRC(W) + JRST MGERR ; TOO MANY ERRORS +IFN TM10B, SETZM MIOWD +IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD ; ONE RECORD + PUSHJ Q,MGDCSO +] + MOVE B,MTCONO(W) + CONO MTC,MSPRR(B) ; REVERSE RECORD + PUSHJ Q,MGWTJD + JRST MGERR ; NO ERRORS ALLOWED +IFN TM10A, PUSHJ Q,MGDCSI ; PUT BACK PI 1 BLKI + MOVE B,LMIOWD + JRST MGRD1 ; TRY AGAIN + +MGROVR: PUSHJ Q,CPOPJ + JRST MGREAD + +SUBTTL MAG TAPE PI LEVEL SPACE + +MGSPCF: PUSHJ Q,MGGXPT ; GET XPORT SPACE FORWARD + TRNE J,600000 + JRST MGERR +MGSPC: MOVEM W,MGUNIT + MOVE B,MGRWCD(W) ; GET COMMAND + ADD B,MTCONO(W) +IFN TM10B,[ + SETZM MIOWD + DATAO MTS,[MICWA] +] +IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD + PUSHJ Q,MGDCSO +] + CONO MTC,(B) ; DO IT + PUSHJ Q,MGWTJD + JRST MGERR ; NO RETRIES + TRNN J,10000 ; EOF + SETZB B,MGEOFR(W) + TRNE J,10000 + AOS B,MGEOFR(W) + CAIL B,2 ;TOO MANY EOF'S + JRST MGSPRF +MGCMDR: SOS MSCMDC(W) ; GENERAL EXIT ROUTINE + SETOM MGUNIT + SKIPG MSCMDC(W) + POPJ P, ; NO MORE + MOVE B,MTCONO(W) + CONO MTC,MNOPIN(B) ; INTERUPT WHEN UNIT READY + MOVEM W,MGUNIT ; RESTORE UNIT NUMBER + PUSHJ Q,MGWTJD + JRST MGERR + SETOM MGUNIT + POPJ Q, ; MORE + +MGSPFR: MOVEI B,MSPFR ; SPACE FOR RECORD + MOVEM B,MGRWCD(W) + MOVSI B,%MAMSO + IORM B,MSRAC(W) ; TAPE MOVEMENT + JRST MGSPCF + +MGSPFF: MOVSI B,%MAESO + TDZE B,MSRAC(W) + JRST MGCMDR ; EOF ALREADY READ DURING THE READ + AOS MSCMDC(W) ;SO IT WILL RETURN + MOVEI B,MSPFR + MOVEM B,MGRWCD(W) + PUSHJ Q,MGSPCF + SKIPE MGEOFR(W) + JRST MGCMDR ; EOF READ ON SPACE RECORD. DONE + MOVEI B,MSPFF + MOVEM B,MGRWCD(W) + JRST MGSPCF + +MGSPRR: MOVEI B,MSPRR + MOVEM B,MGRWCD(W) + MOVSI B,%MAMSO + IORM B,MSRAC(W) + JRST MGSPCR + +MGSPCR: PUSHJ Q,MGGXPT ; SPACE REVERSE + TRNE J,600000 ; ERR + JRST MGERR + TRNE J,100000 ; BOT + JRST MGCMDR ; THEN DO NOTHING + MOVEM W,MGUNIT + MOVE B,MGRWCD(W) + ADD B,MTCONO(W) +IFN TM10B,[ + SETZM MIOWD + DATAO MTS,[MICWA] +] +IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD + PUSHJ Q,MGDCSO +] + CONO MTC,(B) + PUSHJ Q,MGWTJD + JRST MGERR + TRNE J,10000 + SOSGE MGEOFR(W) ; ONE LESS EOF + SETZM MGEOFR(W) + JRST MGCMDR + +MGSPRF: MOVEI B,MSPRF ; REVERSE FILE + MOVEM B,MGRWCD(W) + MOVSI A,%MAESO ; EOF READ IN FORWARD DIRECTION + TDNN A,MSRAC(W) + JRST MGSPCR + AOS MSCMDC(W) ; YES DO IT TWICE + PUSHJ Q,MGSPCR + MOVSI B,%MAESO + ANDCAM B,MSRAC(W) ; TURN OFF FLAG + JRST MGSPCR ; SECOND TIME + +MGRWD1: PUSHJ Q,MGGXPT ; REWIND + MOVEM W,MGUNIT + MOVE B,MGRWCD(W) ; GET COMMAND + ADD B,MTCONO(W) + CONO MTC,(B) + PUSHJ Q,MGWTJD ; WAIT + JRST MGERR + SETZM MGEOFR(W) + MOVSI A,%MAMSO + ANDCAM A,MSRAC(W) ;CLEAR TAPE MOTION +MGRWD2: TRNN J,200000 ; STILL REWINDING? + JRST MGRWD3 ; NO + PUSHJ Q,CPOPJ ; WAIT + CONI MTS,J + MOVEM J,MGCMTS(W) + JRST MGRWD2 + +MGRWD3: MOVE T,TIME ;WAIT 1 SECOND MORE + ADDI T,30. ;THIS IS AN ATTEMPT TO FIX A HARDWARE BUG + MOVEM T,MGJDTI +MGRWD4: MOVE T,TIME + CAML T,MGJDTI + JRST [ SETZM MGJDTI + POPJ Q, ] + PUSHJ Q,CPOPJ + JRST MGRWD4 + +MGRWND: MOVEI B,MREWND ; NORMAL REWIND + CAIA +MGRWDM: MOVEI B,MRWNDD ; REWIND AND DISMOUNT + MOVEM B,MGRWCD(W) + PUSHJ Q,MGRWD1 + MOVSI A,%MAMSO+%MAREW + ANDCAM A,MSRAC(W) + JRST MGCMDR + +MGSEOT: PUSHJ Q,MGGXPT ; SKIP TO LOGICAL EOT + TRNE J,600000 + JRST MGERR + MOVEM W,MGUNIT + TRNE J,100000 ; BOT? + JRST MGVTCK ; VIRGIN TAPE CHECK +MGNVT: MOVE B,MTCONO(W) +IFN TM10A,[ + PUSHJ Q,MGDCSO + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD ; ONE RECORD +] +IFN TM10B, SETZM MIOWD + CONO MTC,MSPRR(B) ; SPACE REVERSE FIRST + PUSHJ Q,MGWTJD ; WAIT + JRST MGERR + SETZM MGEOFR(W) + AOS MGEOFR(W) +MGEOT2: MOVE B,MTCONO(W) + CONO MTC,MSPFF(B) ; SKIP FORWARD FILE + PUSHJ Q,MGWTJD + JRST MGERR + MOVSI B,%MAETR ; EOT CHECK + TRNE J,4000 + IORM B,MSRAC(W) ; TELL MP + MOVE B,MTCONO(W) +IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD ; ONE RECORD +] +IFN TM10B, SETZM MIOWD + CONO MTC,MSPFR(B) ; SPACE FORWARD RECORD + PUSHJ Q,MGWTJD + JRST MGERR + MOVSI B,%MAETR ; EOT AGAIN + TRNE J,4000 + IORM B,MSRAC(W) ; TELL MP + TRNN J,10000 ; EOF ALSO? + JRST MGEOT2 ; NO, TRY AGAIN + MOVE B,MTCONO(W) ; YES, NOW GO BACK OVER LAST + CONO MTC,MSPRF(B) + PUSHJ Q,MGWTJD + JRST MGERR + MOVSI B,%MAEOF+%MAETR ; TELL MP,EOF + IORM B,MSRAC(W) + JRST MGCMDR + +MGVTCK: MOVE T,TIME + ADDI T,60. ; TWO SECOND TIME OUT + MOVEM T,MGEOTT(W) ; EOT TIME +IFN TM10B,[ + SETZM MIOWD + DATAO MTS,[MICWA] +] +IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD + PUSHJ Q,MGDCSO +] + MOVE B,MTCONO(W) + CONO MTC,MREAD(B) ; DO READ, WAIT EITHER FOR JOB DONE OR TIME OUT +MGVTC1: CONI MTS,J + MOVEM J,MGCMTS(W) + TRNE J,100 ; J D? + JRST MGNVT ; NOT VIRGIN TAPE + TRNE J,440000 + JRST MGERR ; ERRORS? + MOVE T,MGEOTT(W) + CAMG T,TIME ; TIME UP? + JRST MGVT ; YES + PUSHJ Q,CPOPJ ; WAIT + JRST MGVTC1 + +MGVT: MOVE B,MTCONO(W) + CONO MTS,31 + CONO MTC,MNOPIN(B) ; NO-OP WAIT FOR JOB DONE + PUSHJ Q,MGWTJD + JFCL ; SEE IF I CARE IF THERE ARE ERRORS + MOVEI B,MREWND + MOVEM B,MGRWCD(W) + PUSHJ Q,MGRWD1 ; REWIND + SETZM MGEOFR(W) + AOS MGEOFR(W) + JRST MGCMDR ; RETURN + +MGMEOT: PUSHJ Q,MGGXPT + TRNE J,600000 + JRST MGERR + MOVEM W,MGUNIT + SKIPE MTCEFW(W) ;HOW MANY EOF WRITTEN? + JRST MGMET1 + AOS MSCMDC(W) ; SO WILL RETURN + AOS MTCEFW(W) + PUSHJ Q,MGWEOF +MGMET1: MOVE A,MTCEFW(W) + SOSLE A + JRST MGMET2 + AOS MSCMDC(W) + AOS MTCEFW(W) + PUSHJ Q,MGWEOF +MGMET2: MOVE A,MSRAC(W) + TLNE A,%MANWT ; BACK OVER LAST? + JRST MGMET3 ; NO + AOS MSCMDC(W) ; SO IT WILL RETURN + PUSHJ Q,MGSPRF +MGMET3: MOVSI A,%MANWT + IORM A,MSRAC(W) + JRST MGCMDR ; DONE + +; WRITE EOF +MGWEOF: PUSHJ Q,MGGXPT + TRNE J,600010 + JRST MGERR + MOVEM W,MGUNIT + MOVE B,MTCONO(W) + CONO MTC,MWEOF(B) + PUSHJ Q,MGWTJD + JRST MGERR + MOVSI A,%MAMSO + IORM A,MSRAC(W) ; TAPE MOVEMENT + JRST MGCMDR ; RETURN + +MGSTAT: PUSHJ Q,MGGXPT ; GETS STATUS + JRST MGCMDR + +MGW3IN: PUSHJ Q,MGGXPT + TRNE J,600010 + JRST MGERR + MOVEM W,MGUNIT +IFN TM10B,[ + SETZM MIOWD + DATAO MTS,[MICWA] +] +IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD + PUSHJ Q,MGDCSO +] + MOVE B,MTCONO(W) + CONO MTC,MW3IN(B) ; WRITE THE RANDOM WORD PRECEEDED BY 3 INCHES OF BLANK TAPE + PUSHJ Q,MGWTJD + JFCL ; ALLOW BAD TAPE ERROR + JRST MGSPRR ; NOW SPACE RECORD REVERSE OVER THE ONE WORD + +SUBTTL .MTAPE UUO + +;.MTAPE AC, +; AC/ CHNM,COMMAND +; COMMAND/ COUNT,,FUNCTION + +AMTAPE: XCTR XR,[HLRZ R,(J)] + TRNE R,-NIOCHN + JRST ILUUO + HRRZM R,UUAC(U) ; SO THAT ERRORS WILL BE REPORTED ON THE + ; CORRECT CHANNEL + ADDI R,IOCHNM(U) ; FORM IOCHNM POINTER + HRRZ A,(R) ; A: CLSTB/IOTTB index + CAIL A,MTUAIX ; Min index for tape + CAILE A,MTBOX ; Max + POPJ P, ; Laconic error reportage. + LDB W,[MTXP(R)] ; GET XPORT NUMBER + CAME U,MTUSR(W) ; SAME USER + POPJ P, ; NO + UMOVE J,(J) + MOVEM J,MTMTAP(W) ; SAVE J + HRRZ A,MTMTAP(W) + PUSHJ P,MTIECK + UMOVE A,(A) + HRRZM A,MTMFNC(W) ;STORE FUNCTION + HLREM A,MTMCNT(W) ;AND COUNT + SKIPN MTMCNT(W) ;A COUNT OF ZERO ALWAYS MEANS ONE, FOR COMPATIBILITY + AOS MTMCNT(W) ; WITH THE OLD CODE. + HRRZS A + CAIL A,NMTAPC ; LEGAL COMMAND + POPJ P, ; NO + AOS (P) ; SKIP RETURN + JRST @MTAPDT(A) + +MTAPDT: MTHANG ;0 HANG TILL TAPE MOTION DONE + MTRWND ;1 REWIND + MTRWDM ;2 REWIND AND DISMOUNT + MTWEOR ;3 WRITE EOR IF APPROPRIATE + MTW3IN ;4 WRITE 3 INCHES OF BLANK TAPE + MTWEOF ;5 WRITE EOF + MTSPR ;6 SPACE RECORDS + MTSPF ;7 SPACE FILES + MTSPEOT ;10 SPACE TO EOT + MTSTOP ;11 STOP ALL COMMAND ASSOCIATED WITH THIS COMMAND + MTSBKS ;12 SET BLOCK SIZE (TO COUNT) + MTRBKS ;13 READ BLOCK SIZE (TO AC) +NMTAPC==.-MTAPDT + +MTSBKS: MOVE A,MTMCNT(W) ;DESIRED BLOCKSIZE + CAIL A,4 ;CHECK REASONABLENESS + CAILE A,2000 + SOSA (P) ;FAIL IF TOO BIG OR TOO SMALL + MOVEM A,MTBLKS(W) ;OK, CHANGE WRITE-BUFFER SIZE + POPJ P, + +MTRBKS: MOVE A,MTBLKS(W) + JRST APTUAJ + +MTHANG: SKIPLE MSCMDC(W) ; HANG UNTILL ALL MOTION FINISHED + PUSHJ P,UFLS + JRST MTIECK + +MTRWND: MOVEI B,MGRWND ; REWIND +MTRWD1: SKIPE MSCRW(W) + JRST MTSOSP + MOVSI A,%MAREW + IORM A,MSRAC(W) + JRST MTCMD + +MTRWDM: MOVEI B,MGRWDM ; REWIND AND DISMOUNT + JRST MTRWD1 + +;"WRITE END OF RECORD" - THIS IS REALLY THE FORCE SYSTEM CALL, OR SHOULD BE. +MTWEOR: SKIPG MTMDN(W) ; ANY BUFFERS STARTED + POPJ P, ; NO + SKIPE MSCRW(W) ; WRITING + JRST MTWBFD ; DISCARD BUFFER +MTSOSP: SOS (P) ; NOT WRITING, ERROR + POPJ P, + +MTWEOF: SKIPN MSCRW(W) ; WRITING? + JRST MTSOSP ; NO + PUSHJ P,MTWEOR + MOVEI B,MGWEOF ; WRITE EOF + AOS MTCEFW(W) + MOVSI TT,%MANWT + ANDCAM TT,MSRAC(W) ; SOMETHING WRITTEN + JRST MTCMD + +MTW3IN: SKIPN MSCRW(W) ; WRITING? + JRST MTSOSP + MOVEI B,MGW3IN + SETZM MTCEFW(W) + MOVSI TT,%MANWT + ANDCAM TT,MSRAC(W) + JRST MTCMD + +;SPACE RECORDS, +=FORWARD, -=BACK +MTSPR: SKIPE MSCRW(W) ; NOT ALLOWED IF WRITING + JRST MTSOSP + PUSHJ P,MTFLRA ;FLUSH READ-AHEAD, FIND OUT HOW FAR OFF WE ARE + ADD B,C ;NUMBER OF RECORDS TAPE IS AHEAD OF USER (EOF=RECORD) + MOVNS B ;SUBTRACT THIS FROM USER'S REQUEST + ADDB B,MTMCNT(W) + JUMPE B,CPOPJ ;IF COUNT IS NOW ZERO, WE ARE DONE +MTSPR1: PUSHJ P,MTCNTR ;UPDATE USER'S COPY IN CASE PCLSR + JUMPG B,MTSPFR ; SPACE FORWARD + MOVEI B,MGSPRR ; SPACE REVERSE + PUSHJ P,MTCMD + AOSGE B,MTMCNT(W) + JRST MTSPR1 ;MORE + POPJ P, + +MTSPFR: MOVEI B,MGSPFR + PUSHJ P,MTCMD + SOSLE B,MTMCNT(W) + JRST MTSPR1 ;MORE + POPJ P, + +;THIS ROUTINE FLUSHES READAHEAD. CALL BEFORE DOING A SPACING OPERATION +;THIS DOESN'T ACTUALLY UNDO THE EFFECT ON THE DRIVE +;OF THE READ-AHEAD. IT DOES MAKE SURE THAT READ-AHEAD'S EFFECT CAN'T +;CHANGE, THEN RETURNS IN B THE NUMBER OF RECORDS AHEAD (NON-NEGATIVE) +;AND IN C THE NUMBER OF EOF'S AHEAD (0 OR 1). IF CALLED TWICE IT WILL +;RETURN ZERO THE SECOND TIME. BE SURE TO UPDATE YOUR PARAMETERS. +MTFLRA: PUSHJ P,MTCNTR ;FIRST, ENSURE WRITEABILITY, MUSTN'T PCLSR IN MTCNTR LATER + MOVSI B,%MASTP + MOVSI T,%MARAC + IORM B,MSRAC(W) ;IF READ IS ACTIVE, TELL IT TO STOP + TDNE T,MSRAC(W) ;AWAIT CESSATION OF READ + PUSHJ P,UFLS ;IF THIS PCLSR'S OUT WITH %MASTP SET, NO GREAT HARM DONE. + ANDCAM B,MSRAC(W) ;THEN TURN OFF %MASTP, THINGS ARE NOW QUIET + SKIPLE MSCMDC(W) ;BEFORE MESSING WITH BUFFERS, WAIT FOR PI TO QUIESCE + PUSHJ P,UFLS + MOVE B,MSNBOL(W) ;NUMBER OF BUFFERS = NUMBER OF RECORDS + LDB C,[.BP (%MAEFA),MSRAC(W)] ;1 IF PAST EOF WHICH THE USER DOESN'T KNOW ABOUT + MOVSI T,%MAEFA ;NOW GET RID OF THE READ-AHEAD + ANDCAM T,MSRAC(W) + JRST MTCBFF + +MTSPF: SKIPE MSCRW(W) ; NOT ALLOWED IF WRITING + JRST MTSOSP + PUSHJ P,MTFLRA ;FLUSH READ-AHEAD + MOVN B,C ;NUMBER OF FILES TAPE IS AHEAD OF USER + ADDB B,MTMCNT(W) + JUMPE B,CPOPJ ;DONE +MTSPF1: PUSHJ P,MTCNTR ;UPDATE USER'S COUNT IN CASE OF PCLSR + JUMPG B,MTSPFF ; SPACE FORWARD FILES + MOVEI B,MGSPRF + PUSHJ P,MTCMD + AOSGE B,MTMCNT(W) + JRST MTSPF1 ;MORE + POPJ P, + +MTSPFF: MOVEI B,MGSPFF + PUSHJ P,MTCMD + SOSLE B,MTMCNT(W) + JRST MTSPF1 ;MORE + POPJ P, + +MTCNTR: HRRZ A,MTMTAP(W) + MOVE T,MTMFNC(W) + HRL T,MTMCNT(W) + UMOVEM T,(A) + POPJ P, + +MTSTAT: SKIPLE MSCMDC(W) ; WAIT TILL ALL COMMANDS DONE + PUSHJ P,UFLS + MOVEI B,MGSTAT ; GET CONI'S + PUSHJ P,MTCMD ; GIVE TO PI + SKIPLE MSCMDC(W) ; WAIT TILL DONE + PUSHJ P,UFLS + MOVE I,MGCMTC(W) + MOVE J,MGCMTS(W) + POPJ P, + +MTSPEOT: MOVEI B,MGSEOT ; SPACE TO LOGICAL EOT + JRST MTCMD ;NOTE THIS IS INDEPENDENT OF READ-AHEAD + +MTSTOP: CONO PI,UTCOFF ;THIS DOESN'T DEAL WITH READ-AHEAD, PROBABLY OK + SETZM MSCMDC(W) ;NO MORE COMANDS + MOVE Q,[-MGQDLL,,MGQD0-1] + MOVE T,MSLCTB + IMUL T,W + ADD Q,T + MOVEM Q,MGQDLP(W) ; RESTORE Q + MOVE Q,[-MSCBL-1,,MSCB0-1] + ADD Q,T + MOVEM Q,MTCMBP(W) ; INITIALIZE MP AND PI COMAND POINTERS + MOVE Q,[4400,,MSCB0-1] + ADD Q,T + MOVEM Q,MGCMBP(W) + SKIPL A,MTMDN(W) + PUSHJ P,IMEMR ; RELEASE MP BUFFER + SETOM MTMDN(W) + SETZM MSMPRP(W) + SETZM MSMPRC(W) ; SO BLKT WON'T GET UNHAPPY + PUSHJ P,MTCBFF ; FLUSH BUFFER LIST + CAME W,MGUNIT ; SAME UNIT? + JRST UTCONJ + SETOM MGUNIT ; SO INTERUPT WILL GO AWAY + CONI MTC,I ; SEE WHAT DRIVE IS BEING TALKED TO + LDB B,[MUNITF,,I] + CAME W,B + JRST UTCONJ ; IF NOT SAME UNIT, DON'T DO ANYTHING + MOVE B,MTCONO(W) + CONO MTS,31 ; STOP THE TAPE + CONO MTC,(B) ; CLEAR INTERUPTS + SKIPGE A,MGCABN(W) ; ANY BUFFERS ACTIVE AT PI + JRST UTCONJ ; NO + PUSHJ P,IMEMR ; RETURN IT + SETOM MGCABN(W) + JRST UTCONJ + +SUBTTL MAG TAPE CLOSE ROUTINES + +MTOCL: LDB W,[MTXP(R)] + SOSL MTUSE(W) + POPJ P, ; NOT ONLY CHANNEL OPEN + AOS MTUSE(W) ; INCASE PCLSRED + MOVSI A,%MAERR ;ERROR? + TDNE A,MSRAC(W) + PUSHJ P,MTOCL3 +; MOVEI T,MSCBL-4 +; CAMG T,MSCMDC(W) +; PUSHJ P,UFLS ; WAIT FOR ROOM FOR THREE COMMANDS + SKIPL MTMDN(W) ; MAG TAPE OUTPUT CLOSE + PUSHJ P,MTWBFD ; WRITE OUT BUFFERS +; MOVEI B,MGWEOF ; WRITE OUT TWO EOF(S) +; SKIPE MTCEFW(W) +; JRST MTOCL2 ; MAY HAVE BEEN PCLSRED +;MTOCL1: PUSHJ P,MTCMD +; AOS MTCEFW(W) ; ONE MORE CLOSE EOF WRITTEN +;MTOCL2: MOVE A,MTCEFW(W) +; SOSG A ; DON'T WRITE EOF IF PCLSRED +; PUSHJ P,MTCMD ; DO IT TWICE +; SKIPG A +; AOS MTCEFW(W) +; MOVEI B,MGSPRF +; MOVE A,MSRAC(W) +; TLNN A,1000 +; PUSHJ P,MTCMD ; NOW BACK UP OVER ONE +; MOVSI A,1000 +; IORM A,MSRAC(W) + MOVEI B,MGMEOT ; MAKE EOT + PUSHJ P,MTCMD + SKIPLE MSCMDC(W) ; NOW WAIT TILL DONE + PUSHJ P,UFLS + MOVEI A,1 + MOVEM A,MGEOFR(W) + SKIPL MTMDN(W) ;ANY ACTIVE BUFFERS + JRST 4,. + SKIPL MGCABN(W) + JRST 4,. + SKIPE MSNBOL(W) + JRST 4,. + SETOM MTUSR(W) + SETOM MTUSE(W) + SETZM MSRAC(W) + POPJ P, + +MTOCL3: SKIPL A,MTMDN(W) + PUSHJ P,MEMR ; IF BUFFER AROUND,FLUSH IT + SETOM MTMDN(W) + SETZM MSMPRC(W) + POPJ P, + +MTICL: LDB W,[MTXP(R)] + SOSL MTUSE(W) ; LAST USER + POPJ P, + AOS MTUSE(W) + MOVEI T,1 + CAMGE T,MSCMDC(W) ; ALLOW ONE COMMAND IF REWINDING + PUSHJ P,UFLS ; ALL COMMANDS DONE + MOVE T,MSRAC(W) + TLNE T,%MAREW ; REWINDING? + JRST MTICL3 ; YES + SKIPLE MSCMDC(W) ; NO, WAIT TILL COMMAND DONE + PUSHJ P,UFLS +MTICL3: SKIPL MGCABN(W) ; ANY PI BUFFERS LEFT + JRST 4,. + PUSHJ P,MTRBD ;GET RID OF M.P. BUF, IF ANY + SETOM MTUSR(W) + PUSHJ P,MTCBFF ; FREE BUFFERS + SOS MTUSE(W) + MOVE T,MSRAC(W) + TLNE T,%MAREW ; DON'T HAVE TO SKIP TO EOF IF REWINDING + JRST MTICL2 + MOVSI A,20 + TDNE A,(R) ;CHECK TO SKIP TO EOF + JRST MTICL2 + MOVSI A,%MAMSO + TDNN A,MSRAC(W) ;TAPE MOVEMENT + JRST MTICL2 ; NO + SKIPE MGEOFR(W) ;NO TIMING CONFLECT HERE SINCE WE WAITED FOR PI TO CLEAR + JRST MTICL2 ;NOTE THAT THIS DISPOSES OF A READ-AHEAD EOF. + PUSHJ P,MTSTAT + MOVE B,MGCMTS(W) + TRNE B,100000 + JRST MTICL2 + MOVEI B,MGSPFF + PUSHJ P,MTCMD + SKIPLE MSCMDC(W) + PUSHJ P,UFLS +MTICL2: MOVSI T,%MAREW + ANDM T,MSRAC(W) ;CLEAR ALL BUT REWINDING + POPJ P, ; NO, DONE + +MTCBFF: SKIPN MSNBOL(W) ;ANY BUFFERS ON CHAIN? + POPJ P, + HRRZ A,MSBUFP(W) ;YES, FREE ONE + PUSHJ P,MTICL1 ; FIX CHAIN + PUSHJ P,MEMR ; RETURN BUFFER + SOSLE MSNBOL(W) ;ANY MORE? + JRST MTCBFF + SETZM MSBUFP(W) ;EMPTY LIST + POPJ P, + +MTICL1: LDB T,[MLO,,MEMBLT(A)] ; GET BACK POINTER + HRRM T,MSBUFP(W) + POPJ P, diff --git a/src/system/ncp.9 b/src/system/ncp.9 new file mode 100755 index 00000000..22a2c60a --- /dev/null +++ b/src/system/ncp.9 @@ -0,0 +1,2761 @@ +SUBTTL ARPANET NCP variables and tables + +EBLK +IMPMQS==13. ;MESSAGE QUEUE SIZE (LENGTH WORD, 6-WORD LEADER, 6-WORD TEXT) +;MAIN PROGRAM CONTROL MESSAGE VARIABLES +IMPMPU: -1 ;-1 => FREE + 0 ;SWTL THREAD +IMPMPL: -1 ;LINK WORD FOR CONTROL LINK QUEUE +IMPMPC: BLOCK IMPMQS ;FIRST WORD HAS IMPHTB INDEX,,LENGTH OF TEXT + +;PI CONTROL MESSAGE VARIABLES +IMNPIC==NNETCH+3 ;NUMBER OF BLOCKS IN PI CONTROL QUEUE +;HOPEFULLY THIS IS ENOUGH. THE CODE RESPONDS VERY UNGRACEFULLY TO THIS +;QUEUE FILLING UP. IN PARTICULAR, WHEN IT HOLDS UP INPUT IT CAN CAUSE +;A DEADLOCK BY PREVENTING ITSELF FROM SEEING A CONTROL-LINK RFNM IT +;NEEDS IN ORDER TO SEND SOMETHING THAT'S IN THE QUEUE AND FREE UP SOME +;SPACE. FURTHERMORE THE IMP IS UNGRACEFUL AND WILL SOMETIMES REFUSE TO +;READ INPUT FROM US (EVEN IN THE MIDDLE OF A MESSAGE) UNTIL WE READ +;INPUT FROM IT. BUT WE DO THE SAME THING WHEN THIS QUEUE FILLS UP. +;FURTHERMORE SOMETIMES THE CORE JOB WILL WAIT FOR A NETWORK +;TRANSMISSION TO COMPLETE SO IT CAN MOVE A NETWORK BUFFER, HANGING THE +;ENTIRE SYSTEM. THE CORE-JOB WILL UNHANG AFTER THE IMP TIMES OUT AND +;FLASHES ITS READY LINE (SEE IMPBER). +;** BUT SOMETIMES THE IMP NEVER TIMES OUT AND SO THE SYSTEM IS HUNG ** + +IMPCQ: REPEAT IMNPIC-1,[ + .+IMPMQS+1 ;POINTER TO NEXT FREE OR NEXT IN QUEUE + BLOCK IMPMQS ;FIRST WORD HAS IMPHTB INDEX,,LENGTH OF TEXT +] + -1 + BLOCK IMPMQS +IMPNCQ: -1 ;NEXT ENTRY TO BE SENT. -1 IF NONE +IMPLCQ: -1 ;POINTER TO LAST ENTRY IN CONTROL QUEUE +IMFFCQ: IMPCQ ;POINTER TO FIRST FREE. -1 IF NONE +IMFCQL: IMNPIC ;NUMBER FREE CONTROL QUEUE ENTRIES LEFT + +;PENDING RFC QUEUE +IMNPQ==20 ;NUMBER OF PENDING QUEUE ENTRIES +;(0) POINTER TO NEXT IN CHAIN OR NEXT FREE. -1 IF NONE +;(1) LOCAL SOCKET NUMBER +;(2) FOREIGN SOCKET NUMBER +;(3) 4.9 = 1 => RTS = 0 => STR +; 1.1-1.8 = LINK NUMBER OR BYTE SIZE +; 1.9-2.7 = FOREIGN HOST NUMBER +; 3.1-3.9 = TIME RFC RECEIVED, IN SECONDS MOD 512. + IMPPQ ;IMPBPQ-1 IS BEGINNING OF GETSYS BLOCK, THIS WORD FOR UNRELOCATION +IMPBPQ: -1 ;BEGINNING OF PENDING QUEUE. -1 IF EMPTY +IMPPQ: REPEAT IMNPQ-1,[ + .+4 + BLOCK 3 +] + -1 + BLOCK 3 +IMPEPQ: -1 ;END OF PENDING QUEUE. -1 IF EMPTY (IMPEPQ IS END FOR GETSYS BLOCK) +IMFFPQ: IMPPQ ;FIRST FREE PENDING QUEUE ENTRY. -1 IF NONE + +;SOCKET TABLE + +IMSOKB: IMPSTL ;BEGIN OF GETSYS BLOCK, LENGTH STORED HERE + +IMSOC1: REPEAT IMPSTL,0 ;0 => FREE + ;>0 MEANS ALLOCATED, NOT SET UP YET + ;4.9 = 1 => SOCKET IN USE + ;4.8 = 1 => CHNL TRYING TO BE CLOSED + ;3.1-4.7 = MASK FOR CHANNEL SOCKET IS OPEN ON. + ;RH = USER INDEX + +IMSOC2: BLOCK IMPSTL ;1.1-4.5 = LOCAL SOCKET NUMBER + ;4.6-4.9 0 (MAKES COMPARISONS EASIER) +IMSOC3: BLOCK IMPSTL ;1.1-4.5 = FOREIGN SOCKET NUMBER + ;4.6-4.9 = 0 +IMSOC4: BLOCK IMPSTL ;3.1-3.8 = LINK NUMBER + ;3.9-4.7 = FOREIGN HOST NUMBER (IMPHTB INDEX) + ; 377 MEANS NOT USING ANY HOST + ;4.8 = SET BY RCV CLS - MAKES MATCH USING IMSCHD FAIL + ;4.9 = SEND THIS BUFFER NOW + .SEE %NS ;RH = SOCKET STATE +IMSOC5: BLOCK IMPSTL ;1.1 - 1.9 => TTY # OF STY, IF CONNECTED TO ONE. + ;2.1-2.9 = CLOSE-REASON + ;3.1-3.8 = CONNECTION BYTE SIZE + ;3.9 => ASCII MODE - 7 BIT + ;4.1 => ASCII MODE - 8 BIT + ;4.2 => 1 BIT BYTES + ;4.3 => NET INT (INR\INS) RECEIVED + ;4.4 => HAVE BEGUN COUNTING THE CLOSE TIME-OUT. + ;4.5 => CLOSED WHILE IN RFNM WAIT, EXPECT ANOTHER RFNM + ;4.6 => CONNECTED DIRECTLY TO A STY. + ;4.7 => DON'T BUFFER MORE OUTPUT THAN ALLOCATION + ;4.8 => STY WANTS WAKEUP AT 1/2 SEC CLK + ;4.9 => TRANSFER IN 32 BIT MODE +IMSOC6: BLOCK IMPSTL ;RH => BUFFER ADDRESS + ;4.9 => LOCKED BY CORE JOB + ;4.8 => ACTIVE AT PI LEVEL + ;4.7 => INPUT OCCURRED WHILE BUFFER LOCKED + ;3.1-3.8 => IOBFT INDEX (377 IF USING BIG BUFFER) +IMSOC7: BLOCK IMPSTL ;BIT ALLOCATION +IMSOC8: BLOCK IMPSTL ;MESSAGE ALLOCATION +IMSC7I: BLOCK IMPSTL ;AMT TO INCREASE BIT ALLOCATION BY IN NEXT ALLOC MSG (INPUT) + ;FOR OUTPUT, HAS NUMBER OF BITS IN BUFFER +IMSC8I: BLOCK IMPSTL ;AMT TO INCREASE MESSAGE ALLOCATION BY NEXT ALLOC MSG (INPUT) +IMSOCT: BLOCK IMPSTL ;TIME WHEN FIRST MESS PUT INTO BUF + ;(DURING INPUT HAS NUMBER OF DATA BYTES LEFT IN CUR MSG) + ;(DURING CLOSE HAS TIME TIME-OUT STARTED) +IMSMPP: BLOCK IMPSTL ;MAIN PROGRAM POINTER, ILDB OR IDPB FOR NEXT BYTE +IMSMPC: BLOCK IMPSTL ;MAIN PROGRAM COUNTER, FOR OUTPUT HAS NUMBER OF DATA + ; BYTES OF ROOM LEFT IN BUFFER. FOR INPUT HAS TOTAL + ; NUMBER OF DATA BYTES IN BUFFER. +IMSPIP: BLOCK IMPSTL ;INTERRUPT LEVEL POINTER, FOR OUTPUT ILDB TO GET NEXT + ; BYTE OUT AT P.I. LEVEL. FOR INPUT POINTS TO WHERE + ; HEADER WORD OF NEXT MESSAGE IN WILL BE STORED. +IMSBFE: BLOCK IMPSTL ;BYTE POINTER TO LAST BYTE IN BUFFER + ;USE CAILE X,@IMSBFE(I) TO CHECK A WORD ADDRESS +IMSOKE==.-1 ;END OF BLOCK FOR GETSYS CALL + +BBLK + +IMSCLN: 221000,,IMSOC4(I) ;LINK NUMBER +IMSCBS: 221000,,IMSOC5(I) ;BYTE SIZE +IMSCLS: 111100,,IMSOC5(I) ;CLOSE REASON +IMSCFH: 321000,,IMSOC4(I) ;FOREIGN HOST +IMSCHD: 222100,,IMSOC4(I) ;FOREIGN HOST AND LINK NUMBER + ; EXTRA BIT, SET WHEN RCV CLS +IMSCHL: 222000,,IMSOC4(I) ;FOREIGN HOST AND LINK WITHOUT EXTRA BIT + +NTRFCL: SIXBIT /NETRFC/ ;FOR ICP ON ANY SOCKET < 1000 +EBLK + 0 + +NETSRS==1000 ;SMALLEST USER RECEIVE SOCKET NUMBER +NRSOC: NETSRS ;NUMBER OF NEXT RECEIVE SOCKET TO BE GENERATED +NETOSW: -1 ;SWITCH LOCKED AT NET OPEN + 0 +NETHSW: -1 ;SWITCH LOCKED IF HACKING HOST TABLE (IMPHTB) + 0 +NETLST: 0 ;LIST OF USERS IN NETWORK OPEN CODE + +;INPUT BUFFER FORMAT: +;THE BUFFER IS CIRCULAR, AND EITHER 200 OR 2000 WORDS LONG. +;MAY CONTAIN SEVERAL MESSAGES. EACH CONSISTS OF A HEADER WORD CONTAINING +; THE NUMBER OF BYTES IN THE MESSAGE, FOLLOWED BY THE BYTES, FOLLOWED BY +; UNUSED BITS UP TO THE NEXT WORD BOUNDARY. THIS WEIRD FORMAT IS USED +; TO AVOID HAVING TO DO BYTE OPERATIONS AT P.I. LEVEL. +;A HEADER WORD OF -1 MEANS THAT THAT MESSAGE HAS NOT YET BEEN STORED. +;IMSPIP(I) ALWAYS CONTAINS THE ADDRESS OF A HEADER WORD OF -1. +;IMSMPP(I) HAS A BYTE POINTER TO THE NEXT DATA BYTE TO BE READ. +;P.I. LEVEL CAN STORE A MESSAGE INTO THE PART OF THE BUFFER FROM +;@IMSPIP TO @IMSMPP-1. +;IMSOCT(I) HAS THE NUMBER OF BYTES THAT MAIN PROGRAM LEVEL CAN +; READ BEFORE IT GETS TO THE END OF THE CURRENT MESSAGE AND HAS +; TO CHECK THE NEXT HEADER. +;IMSMPC(I) HAS THE TOTAL NUMBER OF DATA BYTES IN ALL THE MESSAGES +; IN THE BUFFER. + +;OUTPUT BUFFER FORMAT: +;THE BUFFER IS CIRCULAR, AND EITHER 200 OR 2000 WORDS LONG. +;IT SIMPLY CONTAINS A STRING OF BYTES. +;IMSMPP(I) HAS A BYTE POINTER TO WHERE THE NEXT BYTE TO BE OUTPUT WILL BE DEPOSITED. +;IMSPIP(I) HAS A BYTE POINTER TO WHERE THE NEXT BYTE TO BE SENT OUT AT P.I. +; LEVEL WILL COME FROM. P.I. LEVEL TRIES TO KEEP EVERYTHING ALIGNED ON +; WORD BOUNDARIES SO THAT IT DOESN'T HAVE TO DO BYTE OPERATIONS. +;IMSMPC(I) HAS THE NUMBER OF BYTES THAT MP LEVEL MAY STORE BEFORE RUNNING +; INTO OLD BYTES THAT HAVEN'T YET BEEN TRANSMITTED. +;IMSOCT(I) IS SET TO THE TIME THE FIRST BYTE IS PUT INTO THE BUFFER. +; IT IS CLEARED WHENEVER THE BUFFER GETS EMPTIED. + +BBLK + +SUBTTL ARPANET NCP Main Prog system call routines + +;NET .CALL RCHST/RFNAME +NETRCH: MOVEI W,8 ;WE RETURN 8 VALUES. + HRRE I,A + JUMPL I,NETRC3 ;NET WENT DOWN AFTER THIS CHANNEL WAS OPENED. + MOVE B,IMSOC2(I) ;LOCAL SOCKET NUMBER + MOVE C,IMSOC3(I) ;FOREIGN SOCKET NUMBER + LDB TT,IMSCFH ;FOREIGN HOST FOR 4TH WORD. + CAIN TT,377 + TDZA D,D ; 377 MEANS NOT USING ANY HOST +IFN 1,[ + JRST [MOVE D,A + MOVE A,IMPHTN(TT) ; Get host addr + TLO A,(NW%ARP) ; Make full HOSTS3 format + CALL CVH2NA ; Convert to HOSTS2 for compatibility + EXCH A,D + JRST .+1] +] ;IFN 1 +IFN 0,[ + TDZA Q,Q + MOVE Q,IMPHTN(TT) + LDB D,[112000,,Q] ;TRANSLATE NEW HOST NUMBER TO OLD + ANDI Q,377 ;IF IT WILL FIT IN OLD NOTATION + CAIGE D,100 + CAIL Q,4 + SKIPA D,IMPHTN(TT) + DPB Q,[060200,,D] +] ;IFN 0 + + LDB Q,IMSCBS ;GET BYTE SIZE FOR HERE AND BELOW +;FOLLOWING LINE HAS BEEN PUNTED, AN INCOMPATIBLE CHANGE +; DPB Q,[111100,,D] ;INTO 2.9-2.1 OF 4TH WORD + MOVE A,IMSOC5(I) ;RANDOM WORD + TLNE A,4000 ;SKIP IF 4.3 BIT OFF (NETWRK INT) + TLO D,400000 ;SET FOR USER + PUSHJ P,NETRC1 ;GET TIME IMP GOING DOWN, + HRR TT,IMSOC4(I) ;MERGE IN SOCKET STATE. + IMUL Q,IMSMPC(I) ;MULTIPLY BYTE SIZE BY BYTES AVAIL TO GET BITS AVAIL + LDB I,IMSCLS ;CLS REASON + POPJ P, + +NETRC3: MOVEI I,%NCNCP ;GIVE CLOSE REASON THAT OUR NCP WENT DOWN. +NETRC1: SKIPG TT,IMPDWN+1 ;SYS TIME AT WHICH IMP IS GOING DOWN + JRST NETRC2 + SUB TT,TIME ;(TIME TIL IMP DOWN -1=NOT. 0=DOWN, +=GOING DOWN, N/30. SEC) + SKIPG TT + MOVEI TT,1 ;IF SET TO GO DOWN, AND TIME "PASSED", SAY SOON IF NOT ALREADY DOWN +NETRC2: HRLZS TT + POPJ P, + +;NET .CALL STATUS - SOCKET STATE IN BITS 2.4-2.9 +STANET: TRNN A,400000 ;SKIP IF NET WENT DOWN ON THIS LOSER + SKIPA E,IMSOC4(A) ;GET STATE + MOVEI E,0 ;IF NCP WENT DOWN, STATE IS "CLOSED" + DPB E,[140600,,D] + POPJ P, + +;NET .CALL RESET - ONLY RESETS "INT FM NETWORK" BIT (INR/INS) +NETRS: HLRZ A,(R) ;GET LH IOCHNM + MOVSI B,4000 ;4.3 BIT + TRNN A,400000 ;SKIP IF SET TO -1 (NET WENT DOWN ON THIS CHAN) + ANDCAM B,IMSOC5(A) ;CLEAR BIT + POPJ P, + +;NET .CALL IOPUSH/IOPOP - ALTER THE CHANNEL-OPEN MASK IN IMSOC1. +NETIOP: HRRZ T,UUAC(U) + IMUL I,CHNBIT(T) ;PUSHING => 0; ELSE BIT FOR CHANNEL BEING POPPED. + HLRZ T,(R) ;GET SOCKET TABLE IDX + TRNN T,400000 ;SKIP IF NET WENT DOWN ON THIS LOSER + DPB I,[222000,,IMSOC1(T)] ;STORE MASK AWAY. + POPJ P, + +;NET .CALL WHYINT +;RESULTS ARE %WYNET, SOCKET STATE, BYTES AVAIL, CLS REASON +NETWHY: HRRE I,A ;GET IMSOC INDEX + MOVEI A,%WYNET ;FIRST RESULT IS DEVICE CODE + SETZB B,C ;SET UP RESULTS 2-4 IN CASE NCP WENT DOWN + MOVEI D,%NCNCP + JUMPL I,POPJ1 ;RETURN IF NCP WENT DOWN ON THIS LOSER + HRRZ B,IMSOC4(I) ;SECOND RESULT IS SOCKET STATE + MOVE Q,IMSOC5(I) + TLNE Q,4000 + TLO B,400000 ;SIGN OF SECOND RESULT SET IF NETWRK INT + TLNE Q,40000 ;DIRECT CONNECTED? + TDZA C,C ;YES, NO BYTES AVAILABLE FOR INPUT + MOVE C,IMSMPC(I) ;THIRD RESULT IS BYTES AVAILABLE + LDB D,IMSCLS ;FOURTH RESULT IS CLOSE REASON + JRST POPJ1 + +;AIDS TO NETWORK OPEN AND NETHST CALLS + +;SET THINGS UP AND ALLOCATE AN IMSOC INDEX. +;SKIP RETURNS WITH NETLST AND IMSOC1(I) LOCKED. +;OR, RETURNS NO-SKIP WITH NOTHING LOCKED AND AN ERROR SIGNALLED. +NETO00: PUSHJ P,LSTSET ;ADD THIS JOB TO LIST OF NET OPENERS + NETLST + PUSHJ P,SWTL ;GET AN IMSOC ENTRY TO GC-PROTECT OUR IMPHTB ENTRY + NETOSW + MOVSI I,-IMPSTL + SKIPE IMSOC1(I) + AOBJN I,.-1 + JUMPG I,OPNL6 ;DEVICE FULL + MOVEI H,377 ;NO HOST YET + DPB H,IMSCFH + HRRZM U,IMSOC1(I) ;IMSOC1 POSITIVE MEANS ALLOCATED BUT NOT INITED YET + PUSHJ P,LSWPOP ;NETOSW + PUSHJ P,LOSSET ;RETURN IMSOC ENTRY IF PCLSR + NETIRT + JRST POPJ1 + +;LOSSET ROUTINE TO RETURN IMSOC ENTRY +NETIRT: MOVE T,AC0S+I(U) + HRRZ A,U + CAME A,IMSOC1(T) + JRST 4,. + SETZM IMSOC1(T) + POPJ P, + +;SUBROUTINE TO OPEN UP COMMUNICATIONS WITH THE DESIRED HOST. +;ENTER WITH HOST NUMBER IN SRN3(U), SKIP-RETURN WITH HOST +;UP AND IMPHTB INDEX IN H AND IMSCFH. OR NON-SKIP RETURN WITH ERROR SIGNALLED. +NETOR: MOVE T,SRN3(U) ;USER-SPECIFIED HOST NUMBER + JSP J,STDHST ;STANDARDIZE, OPNL25 IF IT IS NO GOOD + CONO PI,NETOFF + PUSHJ P,FNDHST ;H GETS HOST TABLE INDEX + JRST OPNL6 ;DEVICE FULL (HOST TABLE FULL) + DPB H,IMSCFH ;PROTECT IN IMSOC4 + CONO PI,NETON + PUSHJ P,SWTL ;POSSIBLY SEND RST TO HOST OPENING CONNECTION TO + NETHSW + LDB J,IMHSBT ;GET STATUS + SOJG J,NETORS ;-1 => DOWN, 0 => RST SENT, 1 => UP + JUMPE J,NETOR1 ;WAIT FOR REPLY + PUSHJ P,NETOW ;WAIT FOR IMPMPC TO BE FREE + LDB W,[051100,,TIME] + DPB W,[221100,,IMPHTB(H)] + MOVEI J,1 + DPB J,IMHSBT ;MARK AS SENT + AOS IMRFCT + PUSHJ P,STHSTM ;STORE HOST#, LINK 0 , MESSAGE TYPE 0 + MOVE W,[8_24.+1_8] ;BYTE SIZE = 8, BYTE COUNT = 1 + MOVEM W,IMPMPC+6 + MOVE W,[12._28.] ;RST + MOVEM W,IMPMPC+7 + MOVEI W,1 + HRRM W,IMPMPC ;MESSAGE LENGTH + PUSHJ P,IMPMPQ ;SEND IT OUT +NETOR1: PUSHJ P,LSWPOP ;NETHSW + PCLT + MOVSI T,1000 + TDNE T,IMPHTB(H) ;RRP -> 2000, DOWN -> 0000 + PUSHJ P,UFLS + LDB J,IMHSBT ;GET STATUS + SOJL J,OPNL41 ;HOST DOWN + JUMPE J,NETOR ;TRY ALL THIS AGAIN + JRST POPJ1 ;HOST UP + +NETORS: PUSHJ P,LSWPOP ;NETHSW + JRST POPJ1 ;HOST IS UP + +;NETWORK OPEN + +; .OPEN CH,BLK +; ERROR RETURN +; NORMAL RETURN + +;BLK: MODE BITS,,(SIXBIT /NET/) +; LOCAL SOCKET NUMBER (1.1-4.5) +; FOREIGN SOCKET NUMBER (1.1-4.5) +; FOREIGN HOST NUMBER + +;BLK: 3.1-3.3 => STANDARD ASCII/IMAGE, UNIT/BLOCK, INPUT/OUTPUT +; 3.4 = 1 => GENERATE UNIQUE LOCAL RECEIVE (SEND) SOCKET NUMBER +; 3.4 = 0 => USE LOCAL SOCKET NUMBER SPECIFIED IN BLK+1 +; 3.5 => OPEN SOCKET IN LISTEN MODE +; 3.6 => IF IMAGE MODE, USE BYTE SIZE IN 4.1-4.6 +; IF ASCII MODE, USE 8 BIT BYTES RATHER THAN 7 +; 3.7 => USE BIG BUFFER (2000 WORDS INSTEAD OF 200) +; 3.8 => DON'T BUFFER MORE OUTPUT THAN ALLOCATION +; 4.1-4.6 = BYTE SIZE IN IMAGE MODE + + +;OPEN CODE +NETO: SKIPN IMPUP + JRST NETOUP + SKIPL IMPUP + JRST OPNL7 ;DEVICE NOT READY + CONO PI,NETOFF + SKIPN IMPTCU + AOS IMPTCU + CONO PI,NETON + MOVSI I,SCLIMP + IORM I,SUPCOR ;HAVE SYS JOB BRING UP THE NETWORK + PCLT + SKIPE IMPTCU ;WAIT WHILE IT TRIES TO COME UP + PUSHJ P,UFLS + SKIPE IMPUP + JRST OPNL7 ;LOSE IF NOT UP BY NOW +NETOUP: TLZ A,740000 ;IGNORE EXTRA BITS IN SOCKET NUMBERS + TLZ B,740000 + PUSHJ P,NETO00 ;INITIALIZE THINGS + POPJ P, ;NETWORK NOT UP OR FULL + TLNE C,20 ;SKIP IF NOT LISTEN + JRST NETO10 + PUSHJ P,NETOR ;DO RESET STUFF, OPEN COMMUNICATIONS WITH HOST + POPJ P, ;HOST DOWN OR ILLEGAL + MOVE J,B ;CHECK GENDER OF FOREIGN SOCKET + ROT J,-1 + XOR J,D + JUMPGE J,OPNL2 ;WRONG DIRECTION +;DROPS THROUGH + ;DROPS IN +NETO10: PUSHJ P,SWTL ;ONLY ONE PROCESS AT A TIME COMPARING SOCKET NUMBERS + NETOSW + TLNN C,20 ;SKIP IF LISTEN + PUSHJ P,NETOW ;GOBBLE MP CONTROL LINK BLOCK (FOR NETOS) + TLNN C,10 + JRST NETO1 ;USE SOCKET NUMBER GIVEN IN WORD 2 + MOVEI A,10 ;ADVANCE SYSTEM UNIQUE SOCKET NUMBER + ADDB A,NRSOC + SUBI A,10 ;UNIQUE RECEIVE SOCKET NUMBER + SKIPGE D ;SKIP IF OPEN IS FOR READ (RECEIVE) + IORI A,1 ;MAKE INTO SEND SOCKET + JRST NETO6 + +NETO1: MOVE J,A ;USER SPECIFIED SOCKET NUMBER + ROT J,-1 ;J 4.9: 0 => RECEIVE 1 => SEND + EQV J,D ;D 4.9: 0 => READ 1 => WRITE + JUMPGE J,OPNL2 ;WRONG DIRECTION + MOVE J,A + CAIL A,NETSRS ;SKIP IF SPECIAL SOCKET + TRZA J,7 ;J HAS BASE OF SOCKET GROUP + MOVNI J,1 ; OR -1 IF NOT IN A GROUP + MOVSI Q,-IMPSTL + MOVEI E,0 +NETO2: SKIPL W,IMSOC1(Q) + JRST NETO3 ;NOT HOOKED UP + CAMN A,IMSOC2(Q) + JRST NETO2A ;DUPLICATE LOCAL SOC # + MOVE T,IMSOC2(Q) + TRZ T,7 + CAMN J,T + JRST NETO4 ;JUMP IF PART OF SOCKET GROUP +NETO3: AOBJN Q,NETO2 + SKIPL J ;SKIP IF NOT PART OF A SOCKET GROUP + JUMPE E,OPNL23 ;FOUND NO EVIDENCE THAT THIS GUY OWNS THIS GROUP + JRST NETO6 ;WINNING + +NETO2A: TLNN W,200000 ;SKIP IF BEING CLOSED + JRST OPNL13 ;NO, GIVE ERROR + TLNN C,20 + PUSHJ P,LSWPOP ;POP MP CONTROL LINK BLOCK + PUSHJ P,LSWPOP ;NETOSW + MOVSI T,200000 + PCLT + TDNE T,IMSOC1(Q) + PUSHJ P,UFLS ;WAIT TILL CLOSED + JRST NETO10 ;TRY AGAIN + +NETO4: CAIE U,(W) + JRST OPNL23 ;SOMEONE ELSE HAS IT + MOVNI E,1 ;OK IF NO OTHER CONFLICTS + JRST NETO3 + +;HERE WITH SUITABLE LOCAL SOCKET IN A +NETO6: TLNN C,4 ;SKIP IF IMAGE MODE + JRST NETOC ;ASCII MODE + MOVEI TT,36. + TLNN C,40 ;SKIP IF BYTE SIZE SUPPLIED + JRST NETOB + LDB E,[330600,,C] ;USE USER SUPPLIED BYTE SIZE + IDIVI E,36. ;TT GETS BYTE SIZE MOD 36. + JUMPN TT,NETOB + MOVEI TT,36. ;36 BITS ANYWAY +NETOB: PUSH P,TT + MOVEI E,36. + IDIV E,TT ;36/BS + JUMPE TT,NETOB1 ;EXACT + MOVEI E,32. + IDIV E,(P) ;32/BS + JUMPE TT,[MOVEI TT,400000 ;32BIT MODE FLAG + JRST NETOB1] + MOVEI TT,2000 ;FUNNY BYTESIZE FLAG +NETOB1: POP P,E ;BS + ADD TT,E ;FLAGS+BS + JRST NETOA + +NETOC: MOVEI TT,400410 ;7 BIT + TLNE C,40 + MOVEI TT,401010 ;8 BIT +NETOA: TLNE C,200 + TRO TT,100000 ;DON'T BUFFER MORE OUTPUT THAN ALLOCATION + HRLZM TT,IMSOC5(I) ;STORE FLAGS AND BC, CLEAR CLOSE REASON + MOVEM A,IMSOC2(I) ;LOCAL SOCKET NUMBER + MOVEM B,IMSOC3(I) ;FOREIGN SOCKET NUMBER + SETZM IMSOCT(I) ;IF INPUT, NOT IN MIDDLE OF A MESSAGE + MOVEI W,%NSRFS + TLNE C,20 ;3.5 LISTEN + MOVEI W,%NSLSN + DPB H,[321000,,W] ;DON'T CHANGE HOST NUMBER FIELD OF IMSOC4 + MOVEM W,IMSOC4(I) ;SET INITIAL STATE, CLEAR FLAGS + SKIPE IMSOC6(I) ;SKIP IF HAVEN'T ASSIGNED BUFFER YET + JRST 4,. + PUSH P,A + PUSH P,B + PUSH P,D +NETOE1: TLNN C,100 ;LAST PLACE TO PCLSR (REALLY NETMW) + JRST NETOE7 + PUSHJ P,TCALL ;GET FULL-PAGE BUFFER + JRST IOMQ + JRST NETMW + MOVEI W,MUNET + DPB W,[MUR,,MEMBLT(A)] + DPB I,[MNUMB,,MEMBLT(A)] + LSH A,10. + MOVE W,A ;BUFFER START ADDRESS + HRLI W,377 ;NOT AN IOBFT-TYPE BUFFER + MOVEI A,1777(A) ;BUFFER END ADDRESS + JRST NETOE4 + +NETOE7: MOVEI D,NFNETC(I) + PUSHJ P,TCALL + JRST IUTCO1 ;GET 200-WD BUFFER + JRST NETMW ;NO MEM AVAIL + LDB W,[IOSA,,IOBFT(A)] + LSH W,6 ;STARTING ADDRESS + HRL W,A ;IOBFT INDEX + MOVEI A,177(W) ;BUFFER END ADDRESS +NETOE4: MOVEM A,IMSBFE(I) ;(LH WILL BE STORED LATER) + MOVEM W,IMSOC6(I) +;CLEAR THE BUFFER FOR EASE IN DEBUGGING. COMMENT USED TO CLAIM +;THAT CLEARING IT WAS NECESSARY IN ORDER TO OUTPUT CORRECT HEADERS, +;BUT THAT WAS FRAUDULENT SINCE HEADERS NEVER COME FROM THE BUFFER. + MOVEI D,1(W) + HRLI D,(W) + SETZM (W) + BLT D,(A) + POP P,D + POP P,B + POP P,A +;DROPS THROUGH + ;DROPS IN + + MOVSI Q,000100 ;SET UP THE VARIOUS BYTE POINTERS + LDB TT,IMSCBS ;TO POINT TO END OF BUFFER + MOVE E,IMSOC5(I) ;SO ILDB WILL GET FIRST BYTE IN BUFFER + TLNN E,2000 ;SKIP IF ONE BIT BYTES + DPB TT,[300600,,Q] ;OTHERWISE USE USER BYTE SIZE + SKIPGE E + TLO Q,040000 ;32 BIT WORD ENDS 4 BITS OVER + HRR Q,IMSBFE(I) + MOVEM Q,IMSMPP(I) + MOVEM Q,IMSPIP(I) + MOVEM Q,IMSBFE(I) + MOVE T,C ;GET 3.5 BIT OF C INTO + LSH T,13. ;4.9 OF T + JUMPL D,NETOE5 ;JUMP IF SENDER + SETOM (W) ;NULL FIRST HEADER WORD + TLO Q,440000 ;-> LEFT END OF WORD + HRR Q,W + MOVEM Q,IMSPIP(I) ;SET PI PNTR TO POINT TO FIRST MESSAGE HEADER + SETZM IMSMPC(I) ;NO INPUT BYTES AVAILABLE YET + MOVEI TT,20. ;MESSAGE ALLOCATION ALWAYS 20 + MOVEM TT,IMSOC8(I) + HRRZ TT,IMSBFE(I) ;COMPUTE BIT ALLOCATION + SUBI TT,2*20.(W) ;TT := # WORDS IN BUFFER, -1 FOR LUCK, -2 FOR EACH MSG + SKIPGE IMSOC5(I) ; (-1 FOR HEADER WORD, AND -1 FOR BREAKAGE) + IMULI TT,32. ;CONVERT TO # BITS + SKIPL IMSOC5(I) + IMULI TT,36. + LDB Q,IMSCBS ;BREAKAGE WAS OVER-ESTIMATED BY 1 BYTE PER MSG + IMULI Q,20. + ADD TT,Q + MOVEM TT,IMSOC7(I) ;STORE CORRECT BIT ALLOCATION + SETZM IMSC8I(I) + SETZM IMSC7I(I) + MOVEI Q,2(I) ;LINK # + DPB Q,IMSCLN ;STORE IN LINK # FIELD + JRST NETOE6 + +NETOE5: SETZM IMSOC7(I) ;INITIALIZE SENDER'S ALLOCATIONS + SETZM IMSC7I(I) + SETZM IMSOC8(I) + HRRZ TT,IMSBFE(I) + SUBI TT,(W) ;# BUFFER WORDS, -1 FOR LUCK + SKIPGE IMSOC5(I) ;SKIP IF 36BIT + IMULI TT,32. ;ALLOW 32 BITS PER WORD + SKIPL IMSOC5(I) + IMULI TT,36. ;OR 36 BITS PER WORD + LDB E,IMSCBS + IDIVM TT,E ;CONVERT TO NUMBER OF BYTES + MOVEM E,IMSMPC(I) ;THAT MANY ARE FREE AT FIRST +NETOE6: PUSHJ P,IMPSPQ ;SEARCH PENDING QUEUE (LEAVES UTCOFF) + JRST NETOG ;NOTHING THERE + JUMPGE T,NETOH ;JUMP IF NOT LISTENING STATE + MOVE W,2(Q) ;FOREIGN SOCKET NUMBER + MOVEM W,IMSOC3(I) + LDB H,[101000,,3(Q)] ;FOREIGN HOST IMPHTB INDEX + DPB H,IMSCFH + SKIPA W,[%NSRFC] +NETOH: MOVEI W,%NSOPN + HRRM W,IMSOC4(I) + JUMPGE D,NETOD1 ;JUMP IF RECEIVER + SKIPL W,3(Q) ;SKIP IF RTS, GET LINK # + JRST 4,. ;HE SENT STR + DPB W,IMSCLN ;STORE LINK NUMBER +NETOD: HRRZ Q,UUAC(U) ;CHANNEL OPEN ON + MOVE Q,CHNBIT(Q) + PUSHJ P,IMPUIM ;INTERRUPT SELF + JRST NETOG ;GO FINISH THE OPEN + +NETOD1: SKIPGE W,3(Q) ;SKIP IF STR, GET BYTE SIZE + JRST 4,. ;HE SENT RTS + ANDI W,377 + LDB Q,IMSCBS + CAMN W,Q + JRST NETOD ;BYTE SIZES DIFFER, LOSE + PUSHJ P,IMPBRT ;RETURN THE BUFFER + JRST OPNL22 ;SELF-CONTRADICTORY OPEN? + +NETOG: HRRZ W,UUAC(U) + MOVS W,CHNBIT(W) + TLO W,400000 ;IN USE + HRR W,U ;SETZ+<,,> + MOVEM W,IMSOC1(I) ;WE ARE NOW FULLY SET UP TO THIS SOCKET + CONO PI,NETON + TLNN C,20 ;SKIP IF LISTENING TYPE SOCKET + PUSHJ P,NETOS ;SEND RFC (CAN'T HANG, ALREADY GOT NETOW) + PUSHJ P,LSWPOP ;UNLOCK NETOSW, NOW THAT IMSOC1 4.9 IS SET + PUSHJ P,LSWDEL ;UNLOCK IMSOC1(I) + PUSHJ P,LSWPOP ;REMOVE FROM LIST OF NETWORK OPENS IN PROGRESS + HRLZ A,I ;LEFT HALF OF IOCHNM GETS SOCKET INDEX + HLRZS C + JSP Q,OPSLC7 + NETDUI,,NETDUO + NETDBI,,NETDBO + NETDUI,,NETDUO + NETDBI,,NETDBO + +;GOBBLE MAIN PROGRAM CONTROL LINK BLOCK + +NETOW: JUMPL U,NETOW1 ;FROM STYNET CLOCK LEVEL + PCLT + SKIPGE IMPHTB(H) ;SKIP IF NOT RFNM WAIT ON LINK 0 + PUSHJ P,UFLS + PUSHJ P,SWTL ;GRAB CONTROL LINK BLOCK + IMPMPU + SKIPL IMPHTB(H) ;DID CTL LINK TO THIS HOST GET BACK INTO RFNM WAIT? + POPJ P, ;NO, OK + PUSHJ P,LSWPOP ;YES, RELEASE RESOURCE WHILE AWAITING RFNM + JRST NETOW + +;FROM NETIDC (AT CLOCK INTERRUPT LEVEL) +NETOW1: SKIPL IMPHTB(H) + AOSE IMPMPU + CAIA ;INPUT CAN'T BE READ YET. + POPJ P, + CONO PI,NETOFF + PUSHJ P,IMPUIN ;REACTIVATE SO WILL CHECK AGAIN + SUB P,[2,,2] ;THROW THROUGH NETI6, NETID + JRST NETOJ1 ;TAKE NO-INPUT-AVAILABLE EXIT + +;WAIT FOR MEMORY SO CAN ALLOCATE BUFFER + +NETMW: PCLT + MOVEI T,3 + CAMG T,LMEMFR + JRST [ PUSHJ P,UDELAY ;MAYBE MEMORY FROZEN, GIVE CORE JOB + JRST NETOE1 ] ;A CHANCE TO PCLSR US, THEN TRY AGAIN + CAMLE T,LMEMFR ;SKIP WHEN MORE THAN 3K FREE + PUSHJ P,UFLS + JRST NETOE1 + +;SEND RFC AND MAYBE ALLOCATE. IMSOC INDEX IN I, HOST INDEX IN H. + +NETOS: PUSHJ P,STHSTM ;STORE HOST ADDRESS IN IMPMPC+n, ALSO MESSAGE TYPE + MOVE J,[8_24.+13._8] ;BYTE SIZE = 8, BYTE COUNT = 13. + MOVEM J,IMPMPC+6 + MOVEI J,1_4 ;3 NOPS + RTS + SKIPGE D ;SKIP IF INPUT + MOVEI J,2_4 ;3 NOPS + STR + MOVEM J,IMPMPC+7 + LSH A,4 ;LOCAL SOCKET NUMBER + MOVEM A,IMPMPC+10 + LSH B,4 ;FOREIGN SOCKET NUMBER + MOVEM B,IMPMPC+11 + MOVEI TT,2(I) ;LINK NUMBER FOR RECEIVE SOCKET + SKIPGE D + LDB TT,IMSCBS ;BYTE SIZE FOR SEND SOCKET + LSH TT,28. + HRRZ J,IMSOC4(I) + CAIE J,%NSRFC + CAIN J,%NSOPN ;SKIP IF CONNECTION NOT YET OPEN + JUMPGE D,NETOS2 ;JUMP IF CONNECTION OPEN AND READ + MOVEM TT,IMPMPC+12 + MOVEI TT,4 ;TEXT LENGTH +NETOS3: HRRM TT,IMPMPC + JRST IMPMPQ + +NETOS2: MOVEI J,<4_8>+2(I) ;NOP + ALL + LINK # + LSH J,4 + IOR TT,J + MOVEM TT,IMPMPC+12 + MOVE TT,IMSOC8(I) ;SEND MESSAGE ALLOC + LSH TT,16.+4 + MOVEM TT,IMPMPC+13 + MOVE TT,IMSOC7(I) ;SEND BIT ALLOC + LSH TT,16.+4 + MOVEM TT,IMPMPC+14 + MOVE TT,[8_24.+22._8] ;BYTE COUNT = 22. + MOVEM TT,IMPMPC+6 + MOVEI TT,6 ;MESSAGE LENGTH + JRST NETOS3 + +;.NETAC CH, ;ACCEPT CONNECTION +;ERROR RETURN +;NORMAL RETURN + +ANETAC: JSP T,NETCHK + HRRZ T,IMSOC4(I) ;SOCKET STATE + CAIE T,%NSRFC + JRST OPNL41 ;NOT IN RFC RECEIVED STATE + LDB H,IMSCFH + PUSHJ P,NETOW ;GET IMPMPC + MOVE A,IMSOC2(I) ;LOCAL SOCKET NUMBER + MOVE B,IMSOC3(I) ;FOREIGN SOCKET NUMBER + MOVE D,A + ROT D,-1 + PUSHJ P,NETOS ;SEND RFC (AND MAYBE ALL) + CONO PI,NETOFF + HRRZ T,IMSOC4(I) + MOVEI TT,%NSOPN + CAIN T,%NSRFC + HRRM TT,IMSOC4(I) ;CONNECTION OPEN + JRST NETOJ1 + +NETCHK: HRRZ A,(R) + CAIL A,NETDUI + CAILE A,NETDBO + JRST OPNL34 ;NOT A NETWORK CHANNEL + HLRE I,(R) ;SOCKET TABLE INDEX + JUMPGE I,(T) + JRST OPNL41 ;OTHER END OF PIPELINE GONE (NET WENT DOWN) + +;.NETS CH, ;SEND BUFFER NOW +;RETURN + +NETFRC: JSP T,NETCHK ;ENTRY FROM .CALL FORCE + MOVE T,IMSOC2(I) + TRNN T,1 + JRST OPNL2 ;NOT SEND SOCKET + CONO PI,NETOFF + MOVE T,IMSMPP(I) + CAMN T,IMSPIP(I) + JRST NETOJ1 ;BUF EMPTY + MOVSI TT,400000 ;TURN ON SEND BUFFER BIT + IORM TT,IMSOC4(I) + PUSHJ P,IMPOST ;TURNS NETON + JRST POPJ1 + +NETFIN: HRRZ TT,IMSBFE(I) ;ENTRY FROM .CALL FINISH (NETFRC HAS BEEN CALLED) + SUB TT,IMSOC6(I) .SEE NETOE5 ;FOR COMMENTS FOR THIS CODE + HRRZS TT + SKIPGE IMSOC5(I) + IMULI TT,32. + SKIPL IMSOC5(I) + IMULI TT,36. + LDB T,IMSCBS + IDIVM TT,T ;T NOW HAS SIZE OF OUTPUT BUFFER IN BYTES + CAME T,IMSMPC(I) ;WAIT FOR BUFFER TO EMPTY OUT + PUSHJ P,UFLS + MOVEI T,%NSRFN ;WAIT FOR RFNM + HLL T,IMSOC4(I) ;4.9 IS KNOWN TO BE OFF NOW! + CAMN T,IMSOC4(I) + PUSHJ P,UFLS + JRST POPJ1 + +;.NETINT CH, ;SEND NETWORK INTERRUPT "INR" OR "INS" + ;INR FROM RECEIVER TO SENDER (LOCAL SOCKET EVEN, FOREIGN ODD) + ;INS FROM SND TO RCV ( -", -") +;ALSO .CALL NETINT, ARG 1 IS CH + +NNETINT:JSP T,NETCHK + AOSA (P) ;GOING TO WIN, SKIP RETURN +ANETINT: JSP T,NETCHK ;I<- SOCKET TABLE INDEX + LDB H,IMSCFH ;HOST INDEX FOR NETOW + PUSHJ P,NETOW ;WAIT FOR IMPMPU + MOVEI A,1 ;SET COUNT + MOVEM A,IMPMPC + PUSHJ P,STHSTM ;STORE HOST ADDRESS + MOVE A,[8_24.+2_8] ;BYTE SIZE 8, COUNT 2 + MOVEM A,IMPMPC+6 + MOVE A,IMSOC2(I) ;LCL SOCK # + MOVSI B,7_10. ;INR + TRNE A,1 ;SKIP IF RCV + MOVSI B,8_10. ;INS + LDB A,IMSCLN ;LINK # + DPB A,[241000,,B] + MOVEM B,IMPMPC+7 + JRST IMPMPQ ;QUE IT, START OUTPUT (IMPOST) + +;STORE HOST ADDRESS FROM H INTO LEADER IN IMPMPC. BASHES W, Q. +STHSTM: MOVEI Q,IMPMPL + HRLM H,IMPMPC ;ALSO SAVE HOST INDEX FOR PI LEVEL +;STORE HOST ADDRESS FROM H INTO LEADER IN (Q), BASHES W. +STHSTP: MOVE W,IMPHTN(H) ;FOREIGN HOST NUMBER +IFN 1, DPB W,[103000,,3(Q)] ; Store host address +IFN 0,[ DPB W,[301000,,3(Q)] ;STORE HOST NUMBER + LSH W,-9 + DPB W,[102000,,3(Q)] ;STORE IMP NUMBER +] ;IFN 0 + MOVSI W,17_10. ;NEW-FORMAT FLAG + MOVEM W,2(Q) ;MESSAGE TYPE 0 (LINK, ETC. ARE ALWAYS ZERO) + POPJ P, + +;.CALL NETBLK ;WAIT FOR STATE TO CHANGE OR TIME OUT +; ARG 1 - CHANNEL +; ARG 2 - STATE +; ARG 3 - TIME, AS IN .SLEEP (OPTIONAL) (WRITTEN BACK) +; VAL 1 - NEW STATE +; VAL 2 - TIME LEFT + +ANETBLK:JSP T,NETCHK + MOVE T,I ;SAVE INDEX IN T + HRL T,B ;STATE ALSO + CAIGE W,3 ;SKIP IF 3 ARGS (TIME GIVEN) + JRST ANETB3 ;USE DEFAULT TIME + TLNE C,1000 ;SKIP IF POINTER, RATHER THAN IMMEDIATE + JRST ANETB5 + XCTR XRW,[MOVES B,(C)] ;GET TIME FROM USER (CHECK WRITE ALSO) + JUMPL B,ANETB1 ;NEG MEANS ALREADY ABS TIME + MOVNS B ;MAKE NEG + SUB B,TIME ;-TIME TO GO TO +ANETB1: UMOVEM B,(C) ;STORE NEG TIME FOR PCLSR + MOVNS B ;MAKE + +ANETB4: MOVEM B,EPDL(U) ;ALSO USED IN B LATER + PUSHJ P,ANETB2 ;SKIP IF STATE CHANGE OR TIMEOUT + PUSHJ P,UFLS + SUB B,TIME ;HOW MUCH USED? + HRRZ A,IMSOC4(I) ;RETURN STATE + JRST POPJ1 + +ANETB2: HLR A,T ;DESIRED STATE + XOR A,IMSOC4(T) ;CURRENT STATE + TRNE A,-1 ;SKIP IF STILL MATCH + JRST POPJ1 + MOVE A,EPDL(U) ;SAVED TIME HERE + CAMG A,TIME + AOS (P) ;TIME OUT! + POPJ P, + +ANETB3: HRLOI B,377777 ;NO TIME SUPPLIED, USE INFINITY + JRST ANETB4 + +ANETB5: HRRZ B,C ;IMMEDIATE TIME SUPPLIED + ADD B,TIME ;(TIMEOUT WILL RESTART ON EACH PCLSR, TOO BAD) + JRST ANETB4 + +IFE INETP,[ +;.CALL STYNET +;ARG 1 - STY CHANNEL +;ARG 2 - NET INPUT CHANNEL TO CONNECT STY OUTPUT TO, OR -1 TO DISCONNECT +;ARG 3 - NET OUTPUT CHANNEL TO CONNECT STY INPUT TO +;ARG 4 - CHARS TO SEND WHEN OUTPUT .RESET HAPPENS ON STY'S TTY +; UP TO 3 8-BIT CHARACTERS, LEFT JUSTIFIED. + +NSTYNT: TLNN R,%CLSST + JRST OPNL34 ;1ST ARG NOT A STY CHANNEL. + HLRZ I,(R) ;GET TTY # OF STY + HRRES B ;ALLOW IMMEDIATE -1 + JUMPGE B,NSTYN2 ;JUMP IF CONNECTING. + PUSHJ P,NSTYN0 ;DISCONNECT + JRST OPNL41 ;WASN'T CONNECTED + JRST POPJ1 + +;VARIOUS ROUTINES CALL HERE WITH THE TTY# OF A STY IN I, TO DISCONNECT THE +; STY FROM THE NETWORK. NOTE THIS ROUTINE MUST NOT CHANGE U AND MUST NOT +; LSWCLR, SINCE IT COULD BE CALLED FROM IODCL VIA STYCLS OR NETCLS. + +NSTYN0: MOVSI B,%SSNET ;DISCONNECTING BOTH SIDES. + CONO PI,NETOFF + TDNN B,STYSTS-NFSTTY(I) + POPJ P, ;THIS STY NOT CONNECTED? + ANDCAB B,STYSTS-NFSTTY(I) ;MARK AS NO LONGER CONNECTED + MOVE C,STYNTL-NFSTTY(I) ;REMOVE THIS STY FROM ACTIVATION LIST + MOVEI D,STYNTA-STYNTL+NFSTTY +NSTYN1: CAMN I,STYNTL-NFSTTY(D) ;FIND THE STY THAT POINTS TO THIS ONE, + MOVEM C,STYNTL-NFSTTY(D) ;AND PATCH US OUT OF THE LIST. + SKIPE D,STYNTL-NFSTTY(D) ;SEARCH WHOLE LIST TILL FIND WHO POINTS TO US. + JRST NSTYN1 + SETOB C,STYNTL-NFSTTY(I) + EXCH C,STYNTI-NFSTTY(I) ;MARK THIS STY AS HAVING NO CONNECTION, GET SOCKET INDICES +IFN CHAOSP,[ + TLNE B,%SSCHA + JRST [ MOVSI B,%SSCHA ;DISCONNECT FROM CHAOS NET + ANDCAM B,STYSTS-NFSTTY(I) + MOVSI B,%CFSTY + TDNN B,CHSSTA(C) + JRST 4,. ;CHAOS DOESN'T THINK IT WAS CONNECTED? + ANDCAM B,CHSSTA(C) + JRST NETOJ1 ] +];CHAOSP + MOVE B,[40000,,777] + TDNN B,IMSOC5(C) + JRST 4,. ;SOCKET DOESN'T THINK IT WAS CONNECTED? + ANDCAM B,IMSOC5(C) ;AND MARK SOCKETS WE WERE CONNECTED TO AS DISCONNECTED + MOVSS C + TDNN B,IMSOC5(C) + JRST 4,. ;SOCKET DOESN'T THINK IT WAS CONNECTED? + ANDCAM B,IMSOC5(C) + JRST NETOJ1 + +NSTYN2: MOVE Q,I ;SAVE TTY # OF STY + MOVEI E,1 + MOVE A,B ;DECODE THE NETWORK INPUT CHANNEL + JSP T,CHNDCD +IFN CHAOSP,[ + HRRZ A,(R) + CAIE A,CHAIDN + CAIN A,CHAODN + JRST [ HLRZ I,(R) ;CONNECT TO CHAOS NET + CONO PI,NETOFF + MOVSI B,%CFSTY + TDNE B,CHSSTA(I) + JRST OPNL23 ;ALREADY CONNECTED, FILE LOCKED + MOVSI C,%SSNET+%SSCHA + TDNE C,STYSTS-NFSTTY(Q) + JRST OPNL23 ;ALREADY CONNECTED, FILE LOCKED + IORM B,CHSSTA(I) ;OK, HOOK UP + DPB Q,[$CFTTN,,CHSSTA(I)] + JRST NSTYN3 ] +];CHAOSP + JSP T,NETCHK ;TEST LEGALITY; OPNL IF LOSES + TDNE E,IMSOC2(I) + JRST OPNL2 ;WRONG DIRECTION IF IT'S AN OUTPUT CHANNEL + MOVE B,I ;SAVE INPUT IMSOC INDEX + MOVE A,C ;DECODE OUTPUT CHANNEL + JSP T,CHNDCD + JSP T,NETCHK + TDNN E,IMSOC2(I) + JRST OPNL2 ;WRONG DIRECTION IF INPUT SOCKET + CONO PI,NETOFF + MOVE E,[40000,,777] + TDNN E,IMSOC5(B) ;ERROR IF EITHER CHANNEL ALREADY CONNECTED + TDNE E,IMSOC5(I) + JRST OPNL23 ;"FILE LOCKED" + MOVSI C,%SSNET + TDNE C,STYSTS-NFSTTY(Q) + JRST OPNL23 ;SIMILAR ERROR IF STY ALREADY CONNECTED + HRR E,Q ;GET 40000,,TTY # + IORM E,IMSOC5(I) + IORM E,IMSOC5(B) ;MARK SOCKETS AS CONNECTED +NSTYN3: SKIPGE STYNTL-NFSTTY(Q) ;HALT IF STY'S VARS ARE NOT CORRECT FOR A + SKIPL STYNTI-NFSTTY(Q) ;NON-CONNECTED STY. + JRST 4,. + IORM C,STYSTS-NFSTTY(Q) ;ALL ERROR CAUGHT, SO MARK STY CONNECTED. + HRL B,I ;PUT INPUT IMSOC IDX,, OUTPUT IMSOC IDX + MOVSM B,STYNTI-NFSTTY(Q) ;INTO THE STY + TRZ D,7777 ;STORE THE OUTPUT RESET CHARACTERS - AT MOST 3 + MOVEM D,STYORC-NFSTTY(Q) +IFN CHAOSP,[ ;ACTIVATE IN CASE HAS UNREAD INPUT + TLNN C,%SSCHA + PUSHJ P,IMPUIN + TLNE C,%SSCHA + PUSHJ P,CHINTI +];CHAOSP +.ELSE PUSHJ P,IMPUIN + JRST NETOJ1 +] ;IFE INETP + +SUBTTL ARPANET MP I/O ROUTINES + +IFE INETP,[ +;CALL STYNTC AT CLOCK LEVEL TO PROCESS ALL NECESSARY TRANSFERS OF DATA +;BETWEEN CONNECTED STYS AND NET SOCKETS + +STYNTC: CONO PI,NETOFF + SKIPN I,STYNTA ;GET HEAD OF ACTIVATE LIST + JRST NETONJ ;EMPTY + SETZM STYNTA ;COPY LIST IN CASE A STY IS PUT BACK ON + CONO PI,NETON +STYNT7: MOVE A,STYNTL-NFSTTY(I) ;GET NEXT ON LIST + MOVEM A,STYNTB ;SAVE FOR NEXT TIME AROUND LOOP + SETOM STYNTL-NFSTTY(I) ;THIS ONE IS NO LONGER ON ACTIVATE LIST + MOVE A,STYSTS-NFSTTY(I) + TLNN A,%SSNET + JRST 4,. ;STY CLAIMS NOT TO BE CONNECTED?? + MOVE R,I ;SAVE TTY # +IFN CHAOSP,[ + TLNE A,%SSCHA + JRST STYCHA ;CONNECTED TO CHAOS NET +];CHAOSP +] ;IFE INETP +IFN INETP,STYNCP: + + SKIPGE TTYOAC(I) + JRST STYNT1 ;NO OUTPUT, CHECK FOR INPUT +;HANDLE OUTPUT TO NET + HRRZ I,STYNTI-NFSTTY(I) ;GET IMSOC IDX OF OUTPUT CHANNEL + MOVSI A,40000 + TDNN A,IMSOC5(I) + JRST 4,. ;SOCKET CLAIMS NOT TO BE CONNECTED?? +STYNT5: CONO PI,NETOFF ;INCLUDES TTYOFF + PUSHJ P,NSOSE0 ;CAN WE OUTPUT TO NET NOW? + JRST STYNT6 ;NO, WAIT TILL LATER, PI LVL WILL REACTIVATE WHEN STATE CHANGES + LDB T,IMSCBS ;SINCE THIS IS PI LEVEL, + MOVE Q,IMSOC7(I) ;NO POINT IN SENDING MORE OUTPUT THAN ALLOCATED + SUB Q,IMSC7I(I) + IDIVM Q,T ;T GETS NUMBER OF BYTES ALLOCATED AND NOT BUFFERED + CAMLE E,T + MOVE E,T + JUMPLE E,STYNT6 ;NO ALLOC, SEND NOTHING + EXCH R,I ;BEFORE EXCH, R HAS TTY #, I HAS NET IMSOC IDX + MOVEM D,DBBBP ;SET UP BUFFER-POINTING VARS FOR TTY OUTPUT INTERRUPT LEVEL + MOVEM E,DBBCC + MOVEM E,DBBCC1 + PUSH P,R + SETOM TYPNTF + PUSHJ P,TYP ;OUTPUT THROUGH THOSE POINTERS, INTO THE NET CHNL BUFFER + SETZM TYPNTF + POP P,R + EXCH I,R + MOVE D,DBBBP + MOVE E,DBBCC + MOVE Q,DBBCC1 + PUSHJ P,NSOFIN ;FIGURE OUT HOW MANY CHARS WERE TYPED, AND UPDATE SOCKET. + JRST STYNT4 ;MORE ROOM IN BUFFER => MAYBE TYPE SOME MORE. + JRST STYNT6 ;ELSE TRY INPUT FROM NET, BUT SEND WHATEVER WE GOT + +STYNT4: SKIPL TTYOAC(R) ;MORE OUTPUT IN TTY BUFFER? + JRST STYNT5 ;YES, PROCESS IT +STYNT6: PUSHJ P,NSOFN1 ;NO, BE SURE NET BUFFER GETS SENT SOON + +;HERE TO TRY TO HANDLE INPUT FROM NET +STYNT1: HLRZ I,STYNTI-NFSTTY(R) ;INPUT IMSOC INDEX + MOVSI A,40000 + TDNN A,IMSOC5(I) + JRST 4,. ;SOCKET CLAIMS NOT TO BE CONNECTED? +STYNT2: PUSHJ P,NETIDC ;GET CHAR FROM NET SOCKET + JRST STYNT3 ;GOT CHAR IN W + JRST STYNT8 ;NO CHAR AVAIL, HANDLE OTHER STYS + ;2 SKIPS => GIVE UP, SPECIAL CHARACTER SEEN, OR BAD STATE + PUSHJ P,IMPUIP ;WAKE UP THE TELNET SERVER + MOVE I,R ;DISCONNECT THE STY AND SOCKETS + PUSHJ P,NSTYN0 + JRST 4,. +IFE INETP,[ +STYNT8: SKIPE I,STYNTB ;GET NEXT STY FROM COPIED ACTIVATION LIST + JRST STYNT7 + POPJ P, +] ;IFE INETP +.ELSE JRST STYNT8 + +STYNT3: EXCH I,R ;HERE IF GET CHAR FROM NET IN W. I GETS TTY #. + PUSH P,R + PUSH P,I + MOVE A,W + CONO PI,TTYOFF + PUSHJ P,NTYI5 ;GIVE CHARACTER TO TTY INPUT INTERRUPT LEVEL. + CONO PI,TTYON + POP P,R ;TTY #; POP IN REVERSE ORDER TO UNDO THE EXCH + POP P,I ;IMSOC IDX + JRST STYNT2 ;TRY TO GET ANOTHER INPUT CHARACTER. + +;STYNTC'S INTERFACE TO NET INPUT IOT. +;I HAS IMSOC IDX OF INPUT SOCKET. +;1 SKIP => NO DATA AVAILABLE. +;2 SKIPS => TELNET CONTROL CHARACTER FOUND, SO DISCONNECT STY AND +;INTERRUPT THE USER PROGRAM. +NETIDC: MOVNI U,1 ;U=-1 TELLS NETI IT CAME FROM HERE + HRRZ H,IMSOC4(I) ;CHECK SOCKET STATE + CAIN H,%NSOPN + JRST POPJ1 ;NO DATA + CAIGE H,%NSCLI ;SKIP IF IN ONE OF THE TWO INPUT AVAILABLE STATES + JRST POPJ2 ;STATE IS ABNORMAL, SO DISCONNECT FROM STY. + JRST NETID ;ELSE TRY AN IOT. + +;NETWORK UNIT INPUT. +NETI: HRRE I,A ;SOCKET TABLE INDEX + JUMPL I,IOCER1 +NETIB: MOVE A,IMSOC5(I) ;ENTER HERE FROM BLOCK-MODE INPUT + TLNE A,40000 + JRST IOCR10 ;CAN'T IOT AT M.P. LEVEL WHILE SOCKET CONNECTED TO A STY. +NETID: MOVE A,IMSC8I(I) + LDB B,IMSCBS + IMUL B,IMSMPC(I) + ADD B,IMSOC7(I) ;TOTAL NUMBER OF BITS YET TO BE READ + CAIGE A,8. ;IF MESS REALL OF 8 OR MORE + CAMG B,IMSC7I(I) ;OR BIT REALL SATISFIES "DOUBLE BUFFERING" CRITERION + PUSHJ P,NETI6 ;THEN SEND ALLOCATE + JUMPL U,NETI4 ;JUMP IF READING INPUT TO GIVE DIRECTLY TO A STY +NETI0: CONO PI,NETOFF ;DON'T ALLOW INTO IMPUIN WHILE CHECKING STATE, #BITS + HRRZ A,IMSOC4(I) + JUMPE A,NETIB1 ;CONNECTION CLOSED + CAIE A,%NSINP + CAIN A,%NSCLI + JRST .+3 + CAIE A,%NSOPN + JRST IOCR10 ;SOCKET IN BAD STATE + PCLT + SKIPG IMSMPC(I) ;WAIT FOR BITS TO ARRIVE + PUSHJ P,UFLS + CONO PI,NETON ;NETON IN CASE DIDN'T UFLS + SKIPG IMSMPC(I) ;DID THEY? + JRST NETI0 ;NO, STATE MUST HAVE CHANGED, CHECK IT AGAIN + +NETI4: SOSL IMSOCT(I) ;TAKE BYTE + JRST NETI4A + MOVE A,IMSMPP(I) ;END OF MESSAGE, FIND ADDRESS OF NEXT HEADER WORD + MOVEI A,1(A) ;WHICH IS IN NEXT WORD AFTER LAST BYTE LOADED + CAILE A,@IMSBFE(I) + HRRZ A,IMSOC6(I) ;WRAP AROUND + SOSGE B,(A) ;GET HEADER WORD, COUNT DOWN FOR BYTE ABOUT TO TAKE + JRST 4,. ;NO MESSAGE, ALTHOUGH IMSMPC > 0 + MOVEM B,IMSOCT(I) ;SAVE # BYTES LEFT IN THIS MESSAGE + HLL A,IMSBFE(I) ;SET UP BYTE POINTER LH TO LAST BYTE IN WORD + MOVEM A,IMSMPP(I) ; SO ILDB WILL GET FIRST DATA BYTE OF THIS MSG + AOS IMSC8I(I) ;INCREASE MESSAGE ALLOCATION +NETI4A: MOVE TT,IMSMPP(I) ;CHECK FOR WRAP-AROUND + MOVE H,IMSOC5(I) + TLNE H,2000 + JRST NETI2 ;JUMP IF ONE BIT BYTES + CAMN TT,IMSBFE(I) + JRST [ HRRZ TT,IMSOC6(I) + HLL TT,IMSPIP(I) ;B.P. TO FIRST BYTE IN BUFFER + JRST .+1 ] + ILDB W,TT + JRST NETI3 + +NETI2: LDB E,IMSCBS ;BITS PER BYTE + MOVEI W,0 +NETI1: CAME TT,IMSBFE(I) + JRST NETI1A + HRRZ TT,IMSOC6(I) ;WRAP AROUND + HLL TT,IMSPIP(I) +NETI1A: ILDB A,TT + LSH W,1 + IORI W,(A) + SOJG E,NETI1 +;DROPS THROUGH + ;DROPS IN + +NETI3: TRNN W,200 ;IS THIS A TELNET CONTROL CHAR (>= 200)? + JRST NETI3A + JUMPL U,[AOS IMSOCT(I) ;YES; IF DIRECT-CONNECTED TO A STY, BREAK CONNECTION. + JRST POPJ2] ; WITHOUT GOBBLING THAT CHARACTER + TLNE H,400 ;IF 7-BIT ASCII MODE, REPLACE CHARACTER BY ^@. + SETZ W, +NETI3A: MOVEM TT,IMSMPP(I) + LDB TT,IMSCBS + ADDM TT,IMSC7I(I) ;INCREASE BIT ALLOCATION + CONO PI,NETOFF ;WHILE CHANGING STATE + SOSLE IMSMPC(I) ;ONE LESS BYTE IN BUFFER + JRST NETONJ ;OK, THERE IS MORE IN BUFFER + MOVNI E,1 ;YES, STATE IS CHANGING. + HRRZ A,IMSOC4(I) + CAIN A,%NSCLI + MOVEI E,%NSCLS + CAIN A,%NSINP + MOVEI E,%NSOPN ;NO INPUT AVAILABLE + JUMPL E,[JRST 4,.] ;WAS IN SOME RANDOM STATE + CAIN E,%NSCLS + PUSHJ P,IMPUIP ;IF STATE CHANGING TO "CLOSED", GIVE USER AN INTERRUPT. + HRRM E,IMSOC4(I) + JRST NETONJ + +;COME HERE WHEN INPUT IOT FINDS THAT CONNECTION IS CLOSED +NETIB1: CONO PI,NETON + LDB D,IMSCLS + CAIE D,%NCFRN + JRST IOCR10 ;ABNORMAL CLOSURE, GIVE IOCER INSTEAD OF EOF + MOVE TT,IMSOC5(I) + POP P,D ;GET OUR RETURN ADDRESS. + ANDI D,-1 + CAIE D,AIOT3 ;IF WE ARE NOT DOING A UNIT MODE IOT, + JRST 1(D) ;JUST RETURN WITH 1 SKIP. + TLNN TT,1400 ;SKIP IF ASCII MODE + JRST IOCER2 ;EOF IN IMAGE MODE IS IOCERROR. + HRROI W,EOFCH ;EOF IN ASCII MODE RETURNS ^C. + JRST 1(D) + +NETI6: HRRZ H,IMSOC4(I) ;SEND ALL MSG + CAIE H,%NSINP + CAIN H,%NSOPN + CAIA + POPJ P, ;CLOSED, DON'T SEND ALLOCATE + LDB H,IMSCFH ;HOST INDEX FOR NETOW + PUSHJ P,NETOW ;GOBBLE MAIN PROG CONTROL LINK BLOCK + MOVEI J,2(I) ;LINK # + IORI J,<4_8> ;SEND ALLOC + LSH J,16. + ADD J,IMSC8I(I) + LSH J,4 + MOVEM J,IMPMPC+7 + MOVE J,IMSC7I(I) + LSH J,4 + MOVEM J,IMPMPC+10 + PUSHJ P,STHSTM ;STORE HOST ADDRESS, MESSAGE TYPE + MOVE J,[8_24.+8_8] + MOVEM J,IMPMPC+6 + MOVEI J,2 + HRRM J,IMPMPC ;TEXT LENGTH + SETZB A,TT + EXCH A,IMSC8I(I) + EXCH TT,IMSC7I(I) + ADDM A,IMSOC8(I) + ADDM TT,IMSOC7(I) + JRST IMPMPQ + +;UNIT MODE NETWORK OUTPUT (DOESN'T CLOBBER C) + JRST NETSIO ;SIOT VECTOR +NETW: HRRE I,A ;SOCKET TABLE INDEX + JUMPL I,IOCER1 + SKIPGE C + SKIPA A,(C) + UMOVE A,(C) +NETWB: CONO PI,NETOFF ;BYTE TO OUTPUT IN A. HERE FROM BLOCK MODE. + HRRZ B,IMSOC4(I) + CAIE B,%NSOPN + CAIN B,%NSRFN + JRST .+2 + JRST IOCR10 + SKIPG IMSMPC(I) ;SKIP IF ROOM TO PUT BYTE IN BUF + JRST [ MOVSI B,400000 + IORM B,IMSOC4(I) ;SET TO SEND IT NOW + IFN DMIMP,CONSZ FI,70 + PUSHJ P,IMPIOS + SKIPG IMSMPC(I) ;WAIT FOR AT LEAST ONE BYTE OF ROOM + PUSHJ P,UFLS + CONO PI,NETON + SKIPG IMSMPC(I) + JRST NETWB ;NO ROOM, STATE MUST HAVE CHANGED + JRST .+1] + MOVE E,IMSOC5(I) + MOVE T,IMSOC7(I) + TLNE E,100000 + CAML T,IMSC7I(I) + JRST NETW4 + MOVSI B,400000 ;ALLOCATION USED UP (AND FEATURE ENABLED) + IORM B,IMSOC4(I) ;SEND BUFFER NOW + PUSHJ P,IMPOST + CAMN T,IMSOC7(I) ;WAIT FOR DATA TO GO OUT OR ALLOC TO COME IN + PUSHJ P,UFLS + JRST NETWB ;TRY AGAIN + +NETW4: MOVE T,IMSMPP(I) ;GET POINTER + MOVE E,TIME + CAMN T,IMSPIP(I) ;SKIP UNLESS BUFFER EMPTY + MOVEM E,IMSOCT(I) ;SET TIME FOR FIRST BITS INTO BUF + LDB B,IMSCBS ;BYTE SIZE + MOVE E,IMSOC5(I) ;FLAGS + CONO PI,NETOFF ;WANT TO MUNG POINTERS WITHOUT PI INTERFERENCE + TLNE E,2000 ;SKIP IF BYTES FIT EXACTLY IN WORD + TLNN T,770000 ;SKIP IF NOT AT RIGHT END OF WORD + JRST NETW2 ;IDPB, CHECK FOR POINTER WRAP + LDB TT,[360600,,T] ;GET BYTE POS + CAML TT,B ;SKIP IF BYTE SPLITS ACROSS WORDS + JRST NETW1 ;JUST DO IDPB + DPB TT,[301400,,T] ;SET BYTE TO STORE IN RIGHT OF THIS WORD + SUB TT,B ;=> -(# OVERFLOW BITS) + ROT A,(TT) ;HIGH PART OF BYTE IN RIGHT END OF A + DPB A,T ;STORE PART BYTE + AOS T,IMSMPP(I) ;INCR TO NEXT WORD + MOVEI E,(T) + CAILE E,@IMSBFE(I) + HRR T,IMSOC6(I) ;WRAP + MOVEM A,@T ;STASH REST OF BYTE IN LEFT PART OF NEXT WORD + ADDI TT,36. ;SET TO NEW POSITION + DPB TT,[360600,,T] ;NEW BYT POS + MOVEM T,IMSMPP(I) ;STORE UPDATED PTR + JRST NETW3 ;WRAP UP + +;DEPOSIT A BYTE WHICH MAY WRAP AROUND + +NETW2: CAME T,IMSBFE(I) + JRST NETW1 ;NO WRAP + HRR T,IMSOC6(I) + TLO T,440000 + MOVEM T,IMSMPP(I) + +;DEPOSIT BYTE KNOWN TO FIT IN WORD + +NETW1: IDPB A,IMSMPP(I) ;STORE IT + +;COUNT THE BITS NOW + +NETW3: SOS IMSMPC(I) ;1 BYTE LESS FREE + LDB T,IMSCBS + ADDM T,IMSC7I(I) + JRST NETONJ + +;NETWORK OUTPUT SIOT +NETSIO: CONO PI,NETOFF + PUSHJ P,NSOSET ;SET UP FOR FAST SIOT + JRST NSIOT1 ;CHANNEL ISN'T SET UP FOR IT => USE NORMAL SIOT LOOP. + PUSH P,B + PUSH P,C +NETSO0: XCTR XRW,[MOVES B,@-1(P)] ;COPY ARGS + XCTR XRW,[MOVES C,@(P)] +NETSO1: IBP B .SEE NSIOOL ;FOR WHY THIS HAIR IS NEEDED + XCTRI XR,[MOVE TT,(B)] + SKIPA T,B + JRST NETSO3 ;PAGE FAULT, CLEAN UP IMSMPP BEFORE TAKING IT + HRRI T,TT + LDB TT,T + IDPB TT,D + SOS E + UMOVEM B,@-1(P) ;UPDATE USER'S ARGS + XCTR XRW,[SOSLE C,@(P)] + JUMPG E,NETSO1 ;LOOP IF BOTH USER AND SYSTEM WILLING + SKIPL E + SKIPGE C + JRST 4,. ;WENT TOO FAR!! + PUSHJ P,NSOFIN ;FINISH UP HACKING NET CHANNEL. + JRST NETSO2 ;OUTPUT BUFFER HAS MORE ROOM + JUMPLE C,PPBAJ1 ;NO ROOM BUT DON'T WANT ANY MORE ANYWAY, SO RETURN + SKIPG IMSMPC(I) ;NO ROOM, WAIT FOR SOME + PUSHJ P,UFLS ;NOTE ANY STATE CHANGE WILL UNHANG + POP P,C ;NOW TRY TO SIOT SOME MORE + POP P,B + MOVE D,IOTTB(H) ;RESTORE D IN CASE GOES TO NSIOT1 + JRST NETSIO + +NETSO3: PUSHJ P,NSOFIN ;TOOK PAGE FAULT, CLEAN UP + JFCL + PUSHJ P,TPFLT +NETSO2: JUMPLE C,PPBAJ1 ;BUFFER HAS ROOM BUT NO DESIRE TO SEND ANY MORE, RETURN + CONO PI,NETOFF + PUSHJ P,NSOSE0 ;SET UP TO SEND MORE + JRST IOCR10 ;STATE MUST HAVE GONE BAD + JRST NETSO0 ;OK, SEND MORE + +;SET UP FOR NET OUTPUT SIOT, OR (NSOSE0) FOR DIRECT OUTPUT FROM STY. +;AT ENTRY, A HAS LH(IOCHNM). +;CALL WITH NETOFF, AND DON'T TURN IT BACK ON BEFORE CALLING NSOFIN, +;BECAUSE WE HAVE A COPY OF IMSMPP IN D, AND PI LEVEL MIGHT BE TRYING TO MUNG IT. +;SETS D TO POINTER, E TO COUNT OF CHARS OF SPACE, AND Q TO COPY OF COUNT. +;SETS I TO IMSOC IDX. CLOBBERS T AND TT. +;NO SKIP => CAN'T USE FAST SIOT, OR CAN'T DO DIRECT OUTPUT AT THIS MOMENT. +;IN THAT CASE, D HASN'T BEEN CLOBBERED YET. +NSOSET: HRRE I,A + JUMPL I,IOCER1 +NSOSE0: MOVE E,IMSOC5(I) + HRRZ T,IMSOC4(I) + CAIE T,%NSOPN + CAIN T,%NSRFN ;STATE BAD, OR BYTES CROSS WORD BOUNDARIES, + TLNE E,2000 + JRST NETONJ ;IMPLIES CAN'T WIN THIS WAY. + SKIPG E,IMSMPC(I) + JRST NSOFN1 ;JUMP IF BUFFER FULL, SET SEND BUFFER AND NETONJ + MOVE D,IMSMPP(I) + CAME D,IMSBFE(I) + JRST NSOSE2 + HRR D,IMSOC6(I) ;IF BUFFER STORING PTR POINTS AT END OF BUFFER, + TLO D,440000 ;WRAP AROUND. +NSOSE2: LDB Q,IMSCBS + MOVEI TT,36. + SKIPGE IMSOC5(I) + MOVEI TT,32. + IDIVM TT,Q ;GET # BYTES/WD OF CONNECTION. + HRRZ TT,IMSBFE(I) + SUBI TT,(D) + IMUL TT,Q ;# BYTES BETWEEN POINTER AND END OF BUFFER. + LDB T,[360600,,D] + LDB Q,IMSCBS + IDIVM T,Q ;# BYTES NOT STORED IN WORD POINTER POINTS AT + ADD TT,Q ;THEY ARE AVAILABLE, TOO. + CAML E,TT + MOVE E,TT ;GET MINIMUM OF FULL BYTES AND BYTES AFTER THE POINTER. + MOVE T,TIME + MOVE Q,IMSMPP(I) + CAMN Q,IMSPIP(I) ;SKIP IF BUFFER NOT EMPTY + MOVEM T,IMSOCT(I) ;TIME FOR FIRST BITS INTO BUF. + CAILE E,600 ;DON'T LEAVE NETOFF FOR MORE THAN ONE CLOCK TICK OR SO + MOVEI E,600 + MOVE Q,E ;ORIGINAL E. (FOR NSOFIN) + JRST POPJ1 + +;FINISH UP AFTER NET OUTPUT SIOT OR DIRECT OUTPUT FROM STY. +;SKIP IF BUFFER FULL +;ASSUME Q,I LEFT OVER FROM NSOSET, AND D,E ADVANCED BY STORING CHARS. +NSOFIN: PI2SAF ;NETOFF SHOULD STILL BE IN EFFECT FROM NSOSET + SUBM E,Q ;- <# BYTES XFERED> + JUMPE Q,NETONJ ;IF OUTPUT NO BYTES, DON'T CHANGE IMSMPP (IMPORTANT!) + MOVEM D,IMSMPP(I) ;UPDATE STORING POINTER OF SOCKET BUFFER + LDB TT,IMSCBS + IMUL TT,Q + MOVNS TT + ADDM TT,IMSC7I(I) ;INCREASE COUNT OF BITS IN BUFFER + ADDB Q,IMSMPC(I) ;UPDATE COUNT OF FREE SPACE IN BUFFER. + JUMPG Q,.+2 ;ANY SPACE LEFT => NO SKIP. + AOS (P) + JUMPG E,NETONJ ;ONLY SEND BUFFER IF CALL OUTPUT ALL IT COULD +NSOFN1: MOVSI TT,400000 ;SEND BUFFER NOW. + IORM TT,IMSOC4(I) + JRST IMPOST ;TURNS NETON + +NETBO: HRRE I,A + JUMPL I,IOCER1 + XCTR XRW,[MOVES D,(C)] ;TAKE TRAP GETTING POINTER IF SWAPPED OUT + MOVE E,IMSOC5(I) + TLNE E,1400 ;SKIP IF IMAGE MODE + JRST NETBOA ;ASCII MODE + JUMPGE D,CPOPJ ;TRANSFER NO WORDS +NETBO1: UMOVEM D,(C) + UMOVE A,(D) + PUSHJ P,NETWB + UMOVE D,(C) + AOBJN D,NETBO1 + UMOVEM D,(C) + POPJ P, + +NETBOA: TLNN E,400 ;SKIP IF 7 BIT + JRST NETBA8 + MOVEI E,NETBOR + JRST NBTOCH + +NETBOR: PUSH P,D + PUSH P,TT + PUSHJ P,NETWB + POP P,TT + POP P,D + MOVEI E,NETBOR + POPJ P, + +NETBA8: XCTR XRW,[MOVES D,(C)] + LDB TT,[410300,,D] + CAIGE TT,4 ;ONLY 4 BYTES PER WORD (3 < CNT < 8) + POPJ P, + SKIPA TT,NETCHT-4(TT) +NTBA8A: UMOVEM D,(C) + UMOVE W,(D) + ILDB A,TT + PUSH P,TT + PUSHJ P,NETWB + POP P,TT + UMOVE D,(C) + ADD D,[700000,,] ;ADVANCE CHAR CNT + JUMPL D,NTBA8A ;GO TO NEXT CHAR + MOVE TT,NETCHT+3 + ADD D,[400001,,1] ;INCR TO NEXT WORD + JUMPL D,NTBA8A + UMOVEM D,(C) + POPJ P, + +NETCHT: REPEAT 4,<44-<3-.RPCNT>*10>_12.+1000,,W + +NETBI: HRRE I,A + JUMPL I,IOCER1 + XCTR XRW,[MOVES D,(C)] ;ENSURE POINTER WILL BE WRITABLE + MOVE E,IMSOC5(I) + TLNE E,1400 ;SKIP IF IMAGE MODE + JRST NETBIA ;ASCII MODE +NETBI1: UMOVEM D,(C) ;STORE BACK POINTER + XCTR XRW,[MOVES (D)] ;ENSURE BYTE WILL BE WRITABLE + PUSH P,C + PUSHJ P,NETIB ;GET NEXT BYTE + CAIA ;NORMAL RETURN. + JRST POP1J ;NO INPUT AVAIL. + POP P,C + UMOVE D,(C) + UMOVEM W,(D) + AOBJN D,NETBI1 + UMOVEM D,(C) + POPJ P, + +NETBIA: TLNN E,400 ;SKIP IF 7 BIT ASCII + JRST NTBIA8 + MOVEI E,NETBIR + JRST INBTCH + +NETBIR: PUSHJ P,NETI + JRST [ MOVEI E,NETBIR ;INPUT IN W + POPJ P, ] + MOVE E,[600000,,NETBCC] ;NO INPUT AVAIL + JRST POPJ1 + +NETBCC: MOVEI H,EOFCH + JRST POPJ2 + +NTBIA8: HRRZS E ;8-BIT ASCII BLOCK MODE + XCTR XRW,[MOVES D,(C)] + LDB TT,[410300,,D] + CAIGE TT,4 + POPJ P, + SKIPA TT,NETCHT-4(TT) +NTBI8A: UMOVEM D,(C) + XCTR XRW,[MOVES (D)] + JUMPL E,NTBI8B + PUSH P,C + PUSH P,TT + PUSHJ P,NETIB + JRST [ MOVEI E,0 + JRST NETBI5 ] ;NORMAL RETURN - BYTE IN W. + MOVSI E,600000 ;NO BYTES AVAIL - SOCKET CLOSED. +NETBI5: MOVE H,W + POP P,TT + POP P,C + UMOVE D,(C) + LDB W,[410300,,D] + CAIN W,7 + TLNN E,200000 + JRST NTBI8C + POPJ P, +NTBI8C: UMOVE W,(D) + IDPB H,TT + UMOVEM W,(D) + ADD D,[700000,,] + JUMPL D,NTBI8A + MOVE TT,NETCHT+3 + ADD D,[400001,,1] + SKIPL E + JUMPL D,NTBI8A + UMOVEM D,(C) + POPJ P, + +NTBI8B: MOVEI H,EOFCH + UMOVE D,(C) + JRST NTBI8C + +NETCLS: HRRE I,A ;SOCKET TABLE INDEX + JUMPL I,CPOPJ + MOVE T,IMSOC2(I) + TRNN T,1 ;SKIP IF SEND SOCKET + JRST NETCL2 + MOVSI T,400000 + IORM T,IMSOC4(I) ;CAUSE BUFFER TO BE SENT + PUSHJ P,IMPOST +NETCL2: MOVSI B,600000 + CONO PI,CLKOFF + IORM B,IMSOC1(I) ;MARK CHANNEL TO BE CLOSED + AOS IMNCS + HRRZ R,UUAC(U) + MOVE A,CHNBIT(R) + TDNE A,MSKST2(U) + ANDCAM A,IFPIR(U) + MOVE I,IMSOC5(I) ;IF CHANNEL CONNECTED TO A STY, + TLNN I,40000 + JRST CLKONJ + ANDI I,777 ;DISCONNECT THEM. + PUSHJ P,NSTYN0 + JRST 4,. + JRST CLKONJ + +;SEARCH PENDING QUEUE FOR LOCAL SOCKET NUMBER IN A, +;T 4.9 = 1 => LISTENING, 4.9 => 0 => ALSO CHECK +;FOREIGN SOCKET NUMBER IN B AND FOREIGN HOST NUMBER (IMPHTB INDEX) IN H +;SKIPS IF ENTRY IS FOUND. RETURNS ENTRY TO FREE LIST. +;Q GETS ADDRESS OF ENTRY BLOCK. RETURN WITH NETOFF + +IMPSPQ: CONO PI,NETOFF +IMSPQP: SKIPGE Q,IMPBPQ ;BEGINNING OF QUEUE + POPJ P, ;QUEUE EMPTY + MOVNI J,1 ;PREVIOUS ENTRY +IMSPQL: CAME A,1(Q) ;SKIP IF SAME LOCAL SOCKET NUMBER + JRST IMSPQ1 ;TRY NEXT + JUMPL T,IMSPQW ;WIN IF LISTENING SOCKET + LDB W,[101000,,3(Q)] ;FOREIGN HOST IMPHTB INDEX + CAMN W,H ;SKIP IF WRONG FOREIGN HOST + CAME B,2(Q) ;SKIP IF FOREIGN SOCKET NUMBER AGREES + JRST IMSPQ1 ;TRY NEXT +IMSPQW: SKIPGE W,(Q) ;FOUND IT + MOVEM J,IMPEPQ ;PATCH OUT OF THE QUEUE + SKIPGE J + MOVEI J,IMPBPQ + MOVEM W,(J) + MOVE W,IMFFPQ ;ADD TO FREE LIST + MOVEM W,(Q) + MOVEM Q,IMFFPQ + JRST POPJ1 + +IMSPQ1: MOVE J,Q ;PREVIOUS ENTRY + SKIPL Q,(Q) ;NEXT ENTRY + JRST IMSPQL ;LOOP + POPJ P, ;NOT FOUND + +SUBTTL ARPANET CLOCK LEVEL + +OVHMTR IMP ;NETWORK INTERRUPT LEVEL (NOT STYNET STUFF) + +;HERE TO TIME OUT THE RFC QUEUE +IMFCT1: CONO PI,NETOFF + SKIPGE Q,IMPBPQ + JRST NETONJ ;... IF QUEUE IS EMPTY + MOVNI J,1 ;J HAS PTR TO PREV ELT OF LIST, FOR IMSPQW TO PATCH (DELQ). +IMFCT2: LDB E,[221100,,3(Q)] ;TIME IN 16/15'THS, MOD 512., THAT RFC WAS RECEIVED + LDB TT,[051100,,TIME] ;TIME, IN SAME UNITS, NOW. + CAMLE E,TT ;MAKE SURE THE SUB TT,E GIVES A POSITIVE ANSWER. + ADDI TT,1_9 ;WE ASSUME THAT TIME >= TIME OF RECEIPT. + SUB TT,E + CAIGE TT,IMFCTO_<-5> + JRST IMFCT3 ;THIS RFC HASN'T TIMED OUT - LOOK AT NEXT + PUSHJ P,IMSPQW ;IT HAS - FLUSH IT + JFCL + JRST IMFCT1 ;AND START AGAIN LOOKING FOR RFC'S TO FLUSH + +IMFCT3: MOVE J,Q + SKIPL Q,(Q) + JRST IMFCT2 + JRST NETONJ ;END OF QUEUE + +;FLUSH CLOSED NETWORK CHANNELS (CALLED AT HALF SEC CLOCK) +IMPCCL: MOVSI I,-IMPSTL +IMPCCR: CONO PI,NETON + MOVSI T,200000 +IMPCCZ: TDNN T,IMSOC1(I) ;LOOK FOR CHANNELS NO LONGER OPEN. + AOBJN I,IMPCCZ + JUMPL I,IMPCCA + POPJ P, + +IMPCCA: CONO PI,NETOFF + MOVE B,IMSOC6(I) + TLNE B,600000 ;ACTIVE AT PI LEVEL OR LOCKED BY CORE JOB + JRST IMPCCS + HRRZ B,IMSOC4(I) ;DISPATCH ON SOCKET STATE. + JRST @IMPCCT(B) + +IMPCCT: OFFSET -. +%NSCLS::IMPCC1 +%NSLSN::IMPCC1 +%NSRFC::IMPCC2 +%NSRCL::IMPCC1 +%NSRFS::IMPCC2 +%NSOPN::IMPCC5 +%NSRFN::IMPCC6 +%NSCLW::IMPCC7 +%NSCLI::IMPCC1 +%NSINP::IMPCC2 + OFFSET 0 + +;IMP BUFFER RETURN +IMPBRT: SKIPN IMSOC6(I) + POPJ P, ;NO BUF?? + LDB A,[221000,,IMSOC6(I)] + CAIE A,377 + JRST IMBRT1 + LDB A,[121000,,IMSOC6(I)] + PUSHJ P,IMEMR + CAIA +IMBRT1: PUSHJ P,IBRTN + SETZM IMSOC6(I) + POPJ P, + +IMPCC1: PUSHJ P,IMPBRT + MOVSI A,20000 + TDNE A,IMSOC5(I) + JSP T,IMPC5D ;WAITING FOR FINAL RFNM + SETZM IMSOC1(I) + SOS IMNCS ;WE HAVE FINISHED CLOSING ONE SOCKET +IMPCCS: AOBJN I,IMPCCR ;WE CLOSED ONE, OR GAVE UP ON ONE; LOOK AT NEXT + JRST NETONJ ;OR WE'RE FINISHED LOOKING AT ALL. + +IMPCC2: PUSHJ P,IMPBRT + SKIPLE T,IMFCQL + CAIG T,2 ;SKIP IF MORE THAN 2 FREE + JRST IMPCCS ;NOT ENUF PI CONTROL QUEUE BLOCKS AVAIL + LDB A,IMSCFH ;GET HOST# + SKIPGE IMPHTB(A) ;SKIP IF NO RFNM WAIT ON LINK 0 + JRST IMPCCS ;NOT NOW! + PUSH P,IMPCSH + MOVEM A,IMPCSH + JSP T,IMSTCM + 12.,,3 ;12. BYTES, 3 WORDS + JRST 4,. ;NO SLOTS AVAIL. CHECKED BEFORE + MOVEI H,3_4 ;3 NOPS + CLS + MOVEM H,10(Q) + MOVE H,IMSOC2(I) ;LOCAL SOCKET + LSH H,4 ;MOVE INTO 32 BIT FIELD + MOVEM H,11(Q) + MOVE H,IMSOC3(I) ;FOREIGN SOCKET + LSH H,4 + MOVEM H,12(Q) + PUSHJ P,IMWCQ ;SEND CLS + POP P,IMPCSH + MOVEI H,%NSCLW + HRRM H,IMSOC4(I) + MOVE H,TIME + MOVEM H,IMSOCT(I) ;TIME CLS SENT + JRST IMPCCS + +IMPCC5: MOVE H,IMSOC2(I) + TRNN H,1 ;SKIP IF SEND SOCKET + JRST IMPC5B ;RECEIVE SOCKET + MOVE A,IMSPIP(I) + CAMN A,IMSMPP(I) ;IS THERE STILL DATA TO SEND? AT MP LEVEL + CAMN I,IMPOPI ;OR PI LEVEL? OR RFNM WAIT? +IMPCC6: JSP T,IMPC5D ;YES, SEND IT AND GET RFNM BEFORE SENDING CLS +IMPC5B: MOVEI H,%NSRFS ;NO, OK TO SEND A CLS NOW. + HRRM H,IMSOC4(I);SET STATE SO WILL LOOP BACK TO IMPCC2 + JRST @IMPCCT(H) + +IMPC5A: IORM H,IMSOC5(I) + MOVE H,TIME + MOVEM H,IMSOCT(I) + JRST IMPCCS + +IMPC5D: MOVSI H,10000 + TDNN H,IMSOC5(I) + JRST IMPC5A ;TIME-OUT NOT ALREADY STARTED - START IT. +IMPC7A: MOVE H,TIME ;ALREADY STARTED, OVER YET? + SUB H,IMSOCT(I) + CAIG H,IMPCTO ;SKIP IF TIMED OUT + JRST IMPCCS ;NOT YET + JRST (T) + +IMPCC7: JSP T,IMPC7A ;IF CLOSE TIME-OUT ISN'T UP, GIVE UP TO IMPCCS. + JRST IMPCC1 ;ELSE FLUSH. + +;HERE FROM 1/2 SECOND CLOCK IF IMNAS IS NON-ZERO. +;WE WAKE UP ANY STYNET CHANNELS THAT NEED IT. +IMPAAA: SOS IMNAS ;DECREASE NEED-THIS-ROUTINE COUNT + MOVSI I,-IMPSTL +IMPAA1: MOVSI T,200000 + TDNN T,IMSOC5(I) + AOBJN I,.-1 + JUMPGE I,CPOPJ + CONO PI,NETOFF + ANDCAM T,IMSOC5(I) + PUSHJ P,IMPUIN + CONO PI,NETON + JRST IMPAA1 + +SUBTTL ARPANET NCP INPUT INTERRUPT LEVEL + +;GET HERE PI IN PROG ON NETCHN +;IMP HAS NETCHN PIA, TT HAS CONI WORD, A HAS LAST WD OF CONTROL LINK MSG +;PROCESS THE CONTROL LINK HOST-HOST PROTOCOL OPCODES. +IMPBK3: AOS B,IMBLKI ;STORE LAST WORD AS IF BLKI HAD + MOVEM A,(B) + MOVEI B,-IMPINB+1(B) ;B HAS NUMBER OF WORDS READ + CAMGE B,IMPNIW + JRST IMPCIS ;MESSAGE IS SHORT + MOVE A,IMPCBC ;NUMBER OF BYTES + MOVE B,[441000,,IMPINB] ;8 BIT BYTE POINTER TO MESSAGE + SETZM IMPNEA + SETZM IMPNRA +IMPBKL: SOJL A,IMPIR1 ;LOOP HERE TO PROCESS CONTROL MESSAGE + MOVE H,IMPCSH ;RESTORE HOST INDEX + ILDB C,B + CAIL C,IMPCDL + JRST IMPCIG ;ILLEGAL OPCODE + AOS IMPCMR(C) ;COUNT CTL MSG RCD + JRST @IMPCDT(C) ;DISPATCH ON OPCODE + +IMPCIG: BUG INFO,[NET: NEW CTL MSG FM HST ],OCT,IMPHTN(H),[COD=],OCT,C,[CT=],OCT,A + JRST IMPIR1 + +IMPCIS: MOVE H,IMPCSH + BUG INFO,[NET: SHORT CTL MSG FM HST ],OCT,IMPHTN(H) + AOS IMNSCM + JRST IMPIR1 + +IMPCDT: IMPBKL ;NOP ( 0) + IMPRFC ;RTS ( 1) + IMPRFC ;STR ( 2) + IMPCLS ;CLS ( 3) + IMPALL ;ALL ( 4) + IMPCIG ;GVB ( 5) + IMPCIG ;RET ( 6) + IMPINR ;INR ( 7) + IMPINS ;INS (10) + IMPECO ;ECO (11) + IMPCIG ;ERP (12) + IMPERM ;ERR (13) + IMPRST ;RST (14) + IMPRRP ;RRP (15) + IMPCIG ;RAR (16) + IMPCIG ;RAS (17) + IMPCIG ;RAP (20) + IMPNXR ;NXR (21) + IMPNXR ;NXS (22) +IMPCDL==.-IMPCDT + +IMSHRT: MOVNS A + BUG INFO,[NET: SHORT CTL MSG HST ],OCT,IMPHTN(H),[COD=],OCT,C,[MISSING],OCT,A + JRST IMPIR1 + +IMPNXR: ILDB C,B ;LINK NUMBER FOR NXR OR NXS + SOJA A,IMPBKL ;JUST IGNORE IT, USELESS ANYWAY + +;RFC RECEIVED C HAS OPCODE +IMPRFC: SUBI A,9 ;MUST BE AT LEAST 9 MORE BYTES + JUMPL A,IMSHRT ;MESSAGE IS SHORT + ILDB D,B ;D GETS 32 BIT FOREIGN SOCKET NUMBER +REPEAT 3,[ + LSH D,8 + ILDB T,B + IORI D,(T) +] + ILDB E,B ;E GETS 32 BIT LOCAL SOCKET NUMBER +REPEAT 3,[ + LSH E,8 + ILDB T,B + IORI E,(T) +] + ILDB R,B ;LINK NUMBER OR BYTE SIZE + MOVE Q,E + EQVI Q,(C) ;Q 1.1 = 1 IF E 1.1 = C 1.1 + ANDI Q,1 + JUMPE Q,IMPRF3 ;WRONG DIRECTION RFC + CAIE C,2 ;SKIP IF STR + JRST IMPRF5 + CAILE R,36. ;SKIP IF STR AND BYTE SIZE < 37 + JRST IMREFU ;REFUSE CONNECTION +IMPRF5: PUSHJ P,IMPLLS ;LOOK FOR LOCAL SOCKET (RET INDEX IN I) + JRST IMPRFQ ;NO SUCH SOCKET. QUEUE IT + HRRZ W,IMSOC4(I) ;SOCKET STATE + CAIE W,%NSLSN ;SKIP IF LISTENING + JRST IMPRF4 + MOVEM D,IMSOC3(I) ;STORE FOREIGN SOCKET NUMBER + DPB H,IMSCFH ;STORE FOREIGN HOST INDEX + MOVEI Q,%NSRFC + HRRM Q,IMSOC4(I) ;RFC RECEIVED STATE + CAIN C,2 ;SKIP IF RTS + JRST [ LDB Q,IMSCBS ;STR, CHECK CONNECTION BYTE SIZE + CAME Q,R + JRST IMCLDA + JRST .+2 ] + DPB R,IMSCLN ;RTS, STORE LINK # + PUSHJ P,IMPUIN ;INTERRUPT USER +IMRFCX: LDB Q,IMHSBT + CAIN Q,1 + SOS IMRFCT + MOVEI Q,2 + DPB Q,IMHSBT ;MARK HOST UP + JRST IMPBKL + +IMPRF3: BUG INFO,[NET: WRONG DIR RFC HST ],OCT,IMPHTN(H),[OP ],SIXBIT,[(C)[SIXBIT /RTS STR/]-1],[SOK],OCT,E + JRST IMPBKL + +IMPRF4: CAIE W,%NSRFS ;SKIP IF IN RFC SENT STATE + JRST IMPRFQ ;QUEUE IT + LDB Q,IMSCFH + CAMN Q,IMPCSH + CAME D,IMSOC3(I) ;FROM CORRECT FOREIGN SOCKET? + JRST IMREFU ;NO, REFUSE + AOS IMSOC4(I) ;PUT INTO STATE 5 - OPEN + CAIE C,1 ;SKIP IF RTS + JRST IMPRF2 ;STR + DPB R,IMSCLN ;STORE LINK # +IMPRF1: PUSHJ P,IMPUIN ;INTERRUPT USER + JRST IMPBKL + +IMPRF2: LDB Q,IMSCBS + CAME Q,R + JRST IMCLDA ;BYTE SIZES DIFFER, REFUSE + JSP T,IMSTCM + 8,,2 ;TEXT: 8 BYTES, 2 WORDS + JRST [ AOS IMNANS + JRST IMPRF1 ] + MOVEI H,2(I) + LSH H,16. ;LINK # + IOR H,IMSOC8(I) ;MSG ALLOC + LSH H,4 + TLO H,(4_28.) ;ALL + MOVEM H,10(Q) + MOVE H,IMSOC7(I) ;BIT ALLOC + LSH H,4 + MOVEM H,11(Q) + PUSHJ P,IMWCQ ;SEND IT OUT + JRST IMPRF1 + +IMPRFQ: CAIL E,NETSRS ;IF < 1000, START JOB "NETRFC" + JRST IMRFQ5 + MOVE T,IMPHTN(H) +; CAIE T,+_9 + CAME T,[IMPUS3-NW%ARP] ; Compare with our own host (minus net #) + SKIPL NETUSW + CAIA + JRST IMREFU ;REFUSE CONNECTION + HRROI T,NTRFCL + PUSHJ P,NUJBST ;LOAD SERVER + JRST IMREFU ;RING BUFFER FULL +IMRFQ5: SKIPGE Q,IMFFPQ ;SKIP IF ANY FREE SLOTS + JRST IMRFQ1 ;CLS OLDEST + MOVE W,(Q) + MOVEM W,IMFFPQ ;NEW FIRST FREE +IMRFQ9: SETOM (Q) ;END OF QUEUE + MOVEM E,1(Q) ;LOCAL SOCKET NUMBER + MOVEM D,2(Q) ;FOREIGN SOCKET NUMBER + CAIE C,2 ;SKIP IF STR + TLO R,400000 ;MARK AS RTS + MOVEM R,3(Q) ;LINK NUMBER OR BYTE SIZE + DPB H,[101000,,3(Q)] ;FOREIGN HOST INDEX + LDB W,[051100,,TIME] ;STORE TIME OF RECEIPT, IN 16/15 MOD 512. + DPB W,[221100,,3(Q)] + SKIPGE W,IMPEPQ ;END OF QUEUE + JRST IMRFQ2 ;QUEUE EMPTY + MOVEM Q,(W) ;PUT IN AT END OF QUEUE + MOVEM Q,IMPEPQ ;NEW END OF QUEUE + JRST IMRFCX + +IMRFQ2: MOVEM Q,IMPEPQ ;END OF QUEUE + MOVEM Q,IMPBPQ ;AND BEGINNING OF QUEUE + JRST IMRFCX + +IMRFQ1: MOVE J,IMPBPQ ;BEGINNING OF PENDING QUEUE + MOVE E,1(J) ;LOCAL SOCKET + MOVE D,2(J) ;FOREIGN SOCKET + PUSH P,IMPCSH + LDB H,[101000,,3(J)] ;FOREIGN HOST INDEX + MOVEM H,IMPCSH + PUSHJ P,IMPSCL ;SEND CLS + JRST IMRFQ3 ;NO BUFFERS AVAILABLE + AOSA IMNRFC ;# RFCS CLOSED +IMRFQ3: AOS IMNRFI ;# RFCS IGNORED + POP P,IMPCSH + MOVE H,IMPCSH + MOVE Q,IMPBPQ ;FLUSH FIRST ENTRY ON PENDING QUEUE + MOVE W,(Q) + MOVEM W,IMPBPQ + JRST IMRFQ9 + +IMREFU: PUSHJ P,IMPSCL ;SEND CLS + AOS IMNCNS ;CAN'T + AOS IMNRFI + JRST IMPBKL + +IMPCLS: SUBI A,8 ;MUST BE AT LEAST 8 MORE BYTES + JUMPL A,IMSHRT ;MESSAGE IS SHORT + ILDB D,B ;D GETS 32 BIT FOREIGN SOCKET NUMBER +REPEAT 3,[ + LSH D,8 + ILDB T,B + IORI D,(T) +] + ILDB E,B ;E GETS 32 BIT LOCAL SOCKET NUMBER +REPEAT 3,[ + LSH E,8 + ILDB T,B + IORI E,(T) +] + PUSHJ P,IMPLC ;LOOK FOR CONNECTION + JRST IMCLSQ ;LOOK IN QUEUE + MOVSI W,200000 ;SET CLS RCD BIT + IORB W,IMSOC4(I) ;RH IS STATE FOR DISPATCH + JRST @IMCLDT(W) + +IMCLDT: OFFSET -. +%NSCLS::IMPCLI +%NSLSN::IMPCLI +%NSRFC::IM2CLS +%NSRCL::IMPCLI +%NSRFS::IM4CLS +%NSOPN::IM5CLS +%NSRFN::IM6CLS +%NSCLW::IM7CLS +%NSCLI::IMPCLI +%NSINP::IMECLS + OFFSET 0 + +IM4CLS: HLLZS IMSOC4(I) .SEE %NSCLS + MOVEI W,%NCRFS + JRST IMCLDB + +IMECLS: MOVEI W,%NSCLI + JRST IMCCLS + +IMCLDA: HLLZS IMSOC4(I) .SEE %NSCLS + MOVEI W,%NCBYT ;BYTE MISMATCH + JRST IMCLDB + +IM6CLS: MOVSI W,20000 ;CLSED DURING RFNM WAIT + IORM W,IMSOC5(I) +IM5CLS: TDZA W,W .SEE %NSCLS +IM2CLS: MOVEI W,%NSRCL +IMCCLS: HRRM W,IMSOC4(I) ;CHANGE STATE + MOVEI W,%NCFRN +IMCLDB: DPB W,IMSCLS ;CLS REASON + PUSHJ P,IMPUIN ;INTERRUPT USER +IMCLQ2: PUSHJ P,IMPSCL ;SEND CLS + AOS IMNCNS + JRST IMPBKL + +IMPSCL: JSP T,IMSTCM ;SEND A CLS TO LOCAL SOCKET IN E AND FOREIGN SOCKET IN D (CLOBBERS D AND E) + 12.,,3 ;TEXT: 12 BYTES, 3 WORDS + POPJ P, + MOVEI H,3_4 ;3 NOPS + CLS + MOVEM H,10(Q) + LSH E,4 + MOVEM E,11(Q) ;LOCAL SOCKET NUMBER + LSH D,4 + MOVEM D,12(Q) ;FOREIGN SOCKET NUMBER + PUSHJ P,IMWCQ ;SEND CLS + JRST POPJ1 + +IMPCLI: AOS IMNCLI + JRST IMPBKL + +IM7CLS: HLLZS IMSOC4(I) .SEE %NSCLS + JRST IMPBKL + +IMCLSQ: PUSH P,A + PUSH P,B + MOVE A,E ;LOCAL SOCKET NUMBER + MOVEI T,0 + MOVE B,D ;FOREIGN SOCKET NUMBER + PUSHJ P,IMSPQP ;SEARCH PENDING QUEUE + JRST IMCLQ1 ;NOT THERE + MOVE E,A + POP P,B + POP P,A + JRST IMCLQ2 ;SEND HIM A CLS + +IMCLQ1: POP P,B + POP P,A + JRST IMPCLI ;CAN'T FIND HIM. IGNORE + +IMPALL: SUBI A,7 ;MUST BE AT LEAST 7 MORE BYTES + JUMPL A,IMSHRT ;MESSAGE IS SHORT + ILDB R,B ;LINK # + ILDB D,B + LSH D,8 + ILDB T,B + IORI D,(T) ;D GETS MESSAGE ALLOCATION + ILDB E,B ;E GETS BIT ALLOCATION +REPEAT 3,[ + LSH E,8 + ILDB T,B + IORI E,(T) +] + MOVE T,IMPCSH ;FOREIGN HOST + LSH T,8 + IOR R,T ;HEADER (HOST AND LINK #) + MOVEI W,1 ;TO TEST DIRECTION OF SOCKET + MOVSI I,-IMPSTL +IMPAL2: LDB T,IMSCHD ;FOREIGN HOST AND LINK NUMBER + SKIPGE IMSOC1(I) ;SKIP IF SLOT NOT IN USE + CAME T,R ;SKIP IF HEADER AGREES + JRST IMPAL1 + TDNE W,IMSOC2(I) ;SKIP IF NOT SEND + JRST IMPAL3 +IMPAL1: AOBJN I,IMPAL2 + ANDI R,377 + BUG INFO,[NET: IGNORED ALLOC HST ],OCT,IMPHTN(H),[LNK],OCT,R + AOS IMNALI + JRST IMPBKL ;IGNORE + +IMPAL3: SKIPL D + SKIPGE E + JRST 4,. + LDB T,IMSCBS ;GET BYTESIZE + IDIV E,T ;TRUNCATE TO 0 MODULO BYTESIZE + IMUL E,T ;(CLOBBER TT) + SKIPL IMSOC8(I) + SKIPGE IMSOC7(I) + JRST 4,. + ADDB D,IMSOC8(I) ;INCREASE ALLOCATIONS + ADDB E,IMSOC7(I) + MOVE Q,IMSOC5(I) + TLNE Q,140000 ;ACTIVATE IF USER (OR DIRECT CONN) CHECKING ALLOC + PUSHJ P,IMPUIN + MOVE T,IMSPIP(I) + CAME T,IMSMPP(I) ;SKIP IF OUTPUT BUFFER EMPTY + PUSHJ P,IMPIOS ;THIS GUY MAY HAVE STUFF TO GO OUT + JRST IMPBKL + +IMPLLS: MOVSI I,-IMPSTL ;LOOK FOR SOCKET IN E + MOVSI W,200000 +IMPLL2: TDNN W,IMSOC1(I) + SKIPL IMSOC1(I) ;NOT IN USE + JRST IMPLL1 + CAME E,IMSOC2(I) ;SKIP IF RIGHT LOCAL SOCKET NUMBER +IMPLL1: AOBJN I,IMPLL2 + JUMPL I,POPJ1 ;RETURN SOCKET TABLE INDEX IN RH OF I + POPJ P, ;NOT FOUND + +;INTERRUPT USER ASSOCIATED WITH CHANNEL IN I +IMPUIN: MOVSI U,200000 + TDNE U,IMSOC1(I) + POPJ P, ;CHNL BEING CLOSED + MOVE U,IMSOC5(I) + TLNE U,40000 + JRST IMPUIS ;JUMP IF SOCKET IS CONNECTED TO A STY. +IMPUIP: HRRZ U,IMSOC1(I) ;USER INDEX + LDB Q,[222000,,IMSOC1(I)] ;MASK FOR CHANNEL OPEN ON +IMPUIM: AND Q,MSKST2(U) ;ONLY ENABLED CHANNELS. + PUSH P,T ;VALIDATE THE USER INDEX + MOVEI T,LUBLK + IDIVM U,T + IMULI T,LUBLK + CAMN T,U + CAML U,USRHI + JRST 4,. + MOVSI T,(SETZ) ;PCLSR SO IT GETS IOC ERROR IF NEEDFUL + IORM T,PIRQC(U) ; EVEN IF IT DOESN'T HAVE NORMAL INTERRUPTS ENABLED + POP P,T + IORM Q,IFPIR(U) ;GEN SECOND WORD INTERRUPT + POPJ P, + +IMPUIS: PI2SAF ;HERE FOR INT. ON SOCKET CONNECTED TO A STY: + ANDI U,777 + SKIPL STYNTL-NFSTTY(U) + POPJ P, ;ALREADY ACTIVATED + MOVE Q,STYNTA ;PUT THAT STY ON THE XFER ACTIVATION LIST. + MOVEM Q,STYNTL-NFSTTY(U) + MOVEM U,STYNTA ;THEN RETURN. DON'T ACTUALLY INTERRUPT THE JOB; + POPJ P, ;IF ANYTHING FUNNY HAS HAPPENED, STYNTC WILL INTERRUPT. + +;LOOK FOR CONNECTION: LOCAL SOCKET IN E, FOREIGN SOCKET IN D, FOREIGN HOST IN H +IMPLC: MOVSI I,-IMPSTL +IMPLC2: SKIPGE IMSOC1(I) ;NOT IN USE + CAME E,IMSOC2(I) ;LOCAL SOCKET NUMBER + JRST IMPLC1 + LDB T,IMSCFH + CAMN D,IMSOC3(I) ;FOREIGN SOCKET NUMBER + CAME H,T +IMPLC1: AOBJN I,IMPLC2 + JUMPL I,POPJ1 + POPJ P, + +IMPINR: SOJL A,IMSHRT ;SHORT COUNT + ILDB D,B ;LINK # + DPB H,[101000,,D] ;CONCAT HOST&LINK + MOVSI I,-IMPSTL + LDB E,IMSCHD ;GET HOST FOR SOCKET + CAME D,E + AOBJN I,.-2 ;SEARCH FOR MATCHING HOST&LINK + JUMPGE I,IMPILS ;NOT FOUND +NCPIRS: HRRZ E,IMSOC4(I) ;STATE + MOVE E,CHNBIT(E) ;BIT TO CORRESPOND + TRNN E,1_%NSRFC+1_%NSRFS+1_%NSOPN+1_%NSRFN+1_%NSCLW+1_%NSINP + ;OK STATES RFCRCV, RFCSNT, OPEN, RNMWT, CLSSNT, DATA + JRST IMPILS ;IN BAD STATE + TRNE E,1_%NSCLW ;IGNORE INT IF CLSSNT STATE (NOT ERROR) + JRST IMPBKL + MOVSI D,4000 + IORM D,IMSOC5(I) ;INT FLAG 4.3 BIT OF IMSOC5(SOCK) + PUSHJ P,IMPUIN ;INT TO USER + JRST IMPBKL + +IMPINS: SOJL A,IMSHRT ;SHORT + ILDB D,B ;LINK + MOVEI I,-2(D) ;0,1 -> 777776,777777 ILLEGAL LINKS + CAIGE I,IMPSTL ;CHECK IN RANGE 2 TO IMPSTL+1 + SKIPL IMSOC1(I);AND IN USE + JRST IMPILS ;BAD LINK + LDB T,IMSCFH + CAMN T,IMPCSH ;SKIP IF HOST NOT MATCHED BY MSG + JRST NCPIRS +IMPILS: BUG INFO,[NET: BAD INT CTL MSG HST ],OCT,IMPHTN(H),[LNK ],OCT,D,[IMSOC4],OCT,IMSOC4(I) + JRST IMPBKL ;NOTE- I MAY BE -1 OR -2 OR UP TO 256, IF LNK BAD, IGNORE + +IMPECI: AOS IMPNEI ;WILL EVENTUALLY GIVE JOB TO MAIN PROG + JRST IMPBKL + +IMPECO: ILDB D,B ;GET 8 BIT DATA TO ECHO + SOJL A,IMSHRT + SKIPE IMPNEA + JRST IMPECI ;ONLY ONE TO A CUSTOMER + JSP T,IMSTCM + 2,,1 ;TEXT: 2 BYTES, 1 WORD + JRST IMPECI + LSH D,20. ;DATA TO BE ECHOED + TLO D,(10._28.) ;ERP + MOVEM D,10(Q) + PUSHJ P,IMWCQ ;SEND IT OUT + AOS IMPNEA + JRST IMPBKL + +IMPERM: SUBI A,11. ;COUNT BYTES + MOVE C,TIME + MOVEM C,IMPERB + MOVE C,IMPHTN(H) ;REAL HOST NUMBER + MOVEM C,IMPERB+1 + MOVE C,[441100,,IMPERB+2] + MOVEI D,11. ;BYTES TO COPY + ILDB T,B ;COPY BYTES FROM THEIR MSG + IDPB T,C + SOJG D,.-2 + BUG INFO,[NET: ERR MSG FM HST ],OCT,IMPERB+1,[MSG],OCT,IMPERB+2,OCT,IMPERB+3 + ;ONLY PRINTS FIRST 8 BYTES OF ERR INFO + JUMPGE A,IMPBKL ;IF COUNT OK, GET MORE + JRST IMSHRT ;SHORT COUNT + +IMPRSI: AOS IMPNRI + JRST IMPBKL + +IMPRST: MOVE T,IMPHTN(H) +; CAIE T,+_9 ;IF RST FROM OURSELVES, JUST SEND RRP + CAME T,[IMPUS3-NW%ARP] + PUSHJ P,IMPRSR + SKIPE IMPNRA + JRST IMPRSI + JSP T,IMSTCM + 1,,1 ;TEXT: 1 BYTE, 1 WORD + JRST IMPRSI + MOVSI D,(13._28.) ;RRP + MOVEM D,10(Q) + PUSHJ P,IMWCQ ;SEND IT OUT + PUSHJ P,IMPIOS + AOS IMPNRA + JRST IMPBKL + +IMPRSR: MOVSI I,-IMPSTL ;LOOK FOR USERS OF THIS HOST + MOVSI TT,200000 +IMPRS2: TDNN TT,IMSOC1(I) ;GUY GOING AWAY ANYHOW + SKIPL IMSOC1(I) + JRST IMPRS1 + LDB C,IMSCFH ;FOREIGN HOST + CAME C,IMPCSH + JRST IMPRS1 ;WRONG HOST + HRRZ C,IMSOC4(I) + MOVEI D,%NSCLS + CAIN C,%NSINP + MOVEI D,%NSCLI ;INPUT STILL AVAILABLE + HRRM D,IMSOC4(I) + MOVEI D,%NCRST + DPB D,IMSCLS ;CLS REASON IS RST + PUSHJ P,IMPUIN ;INTERRUPT USER +IMPRS1: AOBJN I,IMPRS2 + ;IF HOST CAN SEND A RST, IT IS UP, BUT DON'T + ;REALLY CONSIDER IT UP UNTIL RRP, RTS, OR STR IS RECEIVED + ;I DON'T KNOW WHY IT'S DONE THIS WAY + POPJ P, + +IMPRRP: LDB J,IMHSBT + SOJL J,IMPRR1 + JUMPG J,IMPBKL ;ALREADY UP, MAYBE BECAUSE OF PRIOR RTS,STR + MOVEI J,2 + DPB J,IMHSBT ;MARK HIM UP + SOS IMRFCT + JRST IMPBKL + +IMPRR1: BUG INFO,[NET: RRP W-O RST HST],OCT,IMPHTN(H) + JRST IMPBKL + +;GET CONTROL QUEUE SLOT +IMGCQS: SKIPG IMFCQL ;SKIP IF ANY LEFT + JRST IMGCQL ;NONE + SKIPG Q,IMFFCQ ;POINTER TO SLOT + JRST 4,. + MOVE W,(Q) + MOVEM W,IMFFCQ ;PATCH OUT OF FREE LIST + SETOM (Q) + SOS W,IMFCQL ;NUMBER FREE LEFT + CAIN W,1 ;SKIP IF MORE THAN ONE LEFT + SETOM IMPHI ;SET FLAG TO HOLD UP INPUT + JRST POPJ1 + +IMGCQL: AOS IMNPIL + POPJ P, + +IMWCQ: PUSHJ P,IMWPCQ + JRST IMPIOS ;START OUTPUT + +;ADD BLOCK IN Q TO OUTPUT CONTROL QUEUE, BASHES W +IMWPCQ: SETOM (Q) + SKIPGE W,IMPLCQ + JRST IMWCQ1 ;CONTROL QUEUE EMPTY + AOSE (W) + JRST 4,. ;END OF QUEUE DIDN'T POINT TO -1 + MOVEM Q,(W) + MOVEM Q,IMPLCQ + POPJ P, + +IMWCQ1: MOVEM Q,IMPLCQ + MOVEM Q,IMPNCQ + POPJ P, + +;ADD MAIN PROGRAM BLOCK TO PI QUEUE (CALL AT MP LEVEL) +IMPMPQ: MOVSI Q,777 + IORM Q,IMPMPU+1 ;NOT LOCKED BY THIS JOB ANY MORE + SKIPL U ;SKIP IF CALLED FROM DIRECT-CONNECT CLOCK LEVEL + PUSHJ P,LSWDEL ;PI LEVEL WILL UNLOCK + CONO PI,NETOFF + MOVEI Q,IMPMPL + PUSHJ P,IMWPCQ + CONO PI,NETON + JRST IMPOST + +;CALL BY JSP T,IMSTCM +;SET UP STANDARD PI CONTROL MESSAGE +;BYTE COUNT,,TEXT LENGTH +;ERROR RETURN + +IMSTCM: PUSHJ P,IMGCQS ;GET CONTROL QUEUE SLOT IN Q + JRST 1(T) ;NONE AVAILABLE + MOVSI H,17_10. ;MESSAGE TYPE = 0, LINK # = 0, NEW FMT + MOVEM H,2(Q) + MOVE H,IMPCSH ;GET IMP AND HOST + MOVE H,IMPHTN(H) +IFN 1, DPB H,[103000,,3(Q)] ; Store host addr +IFN 0,[ DPB H,[301000,,3(Q)] ;STORE HOST + LSH H,-9 + DPB H,[102000,,3(Q)] ;STORE IMP +] ;IFN 0 + HLRZ H,(T) ;BYTE COUNT + LSH H,8 + IOR H,[8_24.] ;BYTE SIZE = 8 + MOVEM H,7(Q) + HRLZ H,(T) + HRR H,IMPCSH + MOVSM H,1(Q) ;HOST INDEX,,TEXT LENGTH + JRST 2(T) ;NORMAL RETURN (NOTE THAT H HAS BEEN RESTORED TO IMPCSH) + +;RECEIVED LEADER OF REGULAR MESSAGE NOT ON CONTROL LINK +;THE HOST-HOST LEADER WORD (WD 6) HAS NOT YET BEEN DATAI'ED. +;SWITCH TO 32-BIT MODE FIRST IF NECESSARY. +IMPRMD: +IFN INETP,[ + CAIE B,IMPILB+4 ; Verify that NCP leader is next word + JRST IMPLD3 ; Barf... +] + MOVE D,IMPCSH + LSH D,8 + MOVE I,IMPCLN + IOR D,I ;HEADER + SUBI I,2 ;SOCKET TABLE INDEX + JUMPL I,IMPRM7 ;BAD LINK # + SKIPGE A,IMSOC1(I) + TLNE A,200000 ;SKIP IF NOT BEING CLOSED + JRST IMPRM7 ;SOCKET DOESNT EXIST OR BEING CLOSED + MOVEI A,1 + CAIGE I,IMPSTL + TDNE A,IMSOC2(I) ;SKIP IF RECEIVER + JRST IMPRM7 ;BAD LINK # OR MESSAGE FOR A SENDER + LDB C,IMSCHD ;HEADER + CAME D,C ;SEE IF HEADERS AGREE + JRST IMPRM7 ;NOPE, I.E. FROM WRONG HOST OR CLOSED + HRRZ D,IMSOC4(I) + CAIE D,%NSOPN + CAIN D,%NSINP + JRST IMPRMA + JRST IMPRM7 +IMPRMA: SKIPGE IMSOC6(I) ;SKIP IF NOT LOCKED BY CORE JOB + JRST IMPRMP ;LOCKED, COME BACK LATER +IFN KAIMP,[ + SKIPL IMSOC5(I) ;SKIP IF 32 BIT TRANSFER + CONO IMP,IMI32C ;SET 36 BIT INPUT + SKIPGE IMSOC5(I) ;SKIP IF NOT 32 BIT TRANSFER + CONO IMP,IMI32S ;SET 32 BIT INPUT +]IFN DMIMP,[ + SKIPL IMSOC5(I) ;SKIP IF 32BIT + CONO FI,FII32C ;SET 36BIT + SKIPGE IMSOC5(I) ;SKIP IF 36 BIT + CONO FI,FII32S ;SET 32 BIT +] + DATAI IMP,IMPILB+5 ;GET THE HEADER WORD + LDB A,IMCBBP + MOVEM A,IMPCBS + LDB B,IMSCBS ;Check for fraudulent byte size + CAME A,B + JRST IMPRMZ ;Discard message + LDB B,IMBCBP + MOVEM B,IMPCBC + MOVEM B,IMPNBI ;SAVE BYTE COUNT FOR LATER + SOSGE IMSOC8(I) + JRST IMRMAF ;MESSAGE ALLOCATION EXCEEDED + JUMPE B,IMPIRT ;ZERO LENGTH MESSAGE + IMUL A,B ;BIT COUNT + MOVN D,A + ADDB D,IMSOC7(I) ;REMAINING BIT ALLOCATION + JUMPL D,IMRMAH ;BIT ALLOCATION EXCEEDED + TRNE TT,IMPLW + JRST IMRMAG ;MESSAGE IS SHORT + MOVSI D,200000 + IORB D,IMSOC6(I) ;ACTIVE AT PI LEVEL + SKIPGE IMSOC5(I) + IDIVI A,32. + SKIPL IMSOC5(I) + IDIVI A,36. + SKIPE B + ADDI A,1 ;NUMBER OF WORDS MESSAGE WILL TAKE + HRRZ B,IMSPIP(I) ;ADDRESS WHERE MESSAGE HEADER WILL GO + SKIPL (B) + JRST 4,. ;HEADER WORD SHOULD BE -1 + HRRZ C,IMSBFE(I) ;GET ADDRESS OF LAST WORD IN BUFFER + CAML B,C + MOVEI B,-1(D) ;HEADER IS LAST IN BUFFER, SO DATA IS FIRST + MOVE E,B ;RH(BLKI POINTER) IN E + ADD A,B ;ADDRESS WHERE LAST WORD OF MESSAGE WILL GET STORED + SETZM IMNWSI ;ASSUME WILL ONLY NEED ONE BLKI + CAMG A,C + JRST IMPRM8 ;JUMP IF NO WRAP +;DROPS THROUGH + ;DROPS IN + SUB B,C ;- # WDS TO READ FIRST TIME + SUB A,C ;+ # WDS TO READ SECOND TIME + SKIPGE B + SKIPG A + JRST 4,. ;SCREW + MOVN C,A ;NEG OF REMAINING WORD COUNT + MOVSS C ;TO LEFT HALF FOR BLKI POINTER + HRRI C,-1(D) ;RING AROUND TO BEGIN OF BUFFER + MOVEM C,IMNWSI ;STORE FOR INTCHN BLKI RUNOUT (FLAG IF -) + ADD C,A ;ADR+COUNT + HRRZM C,IMPNIW ;EXPECTED END OF BLKI + SKIPA A,B +IMPRM8: SUBM B,A ;A GETS - # WORDS TO READ + MOVE B,E + HRL B,A ;BLKI POINTER + SUB E,A ;EXPECTED LAST WORD + SKIPE IMNWSI ;IF DOING 2 BLKIS, EXPECTED END ALREADY STORED + SKIPA E,IMPNIW + MOVEM E,IMPNIW ;EXPECTED LAST BLKI ADDRESS + HRRZ A,IMSPIP(I) ;SEE IF CLOBBERING GOOD-DATA PART OF BUFFER + CAIL A,@IMSMPP(I) ;SKIP IF MPP > PIP + JRST [ CAIG E,(A) + CAIGE E,@IMSMPP(I) + JRST IMPRMT + JRST 4,. ] + CAIGE E,@IMSMPP(I) + CAIG E,(A) + JRST 4,. +IMPRMT: HRRZ A,IMSOC6(I) ;SEE IF CLOBBERING CORE NOT PART OF BUFFER + CAIL E,(A) + CAILE E,@IMSBFE(I) + JRST 4,. + HRRZM I,IMPIPI ;THIS SOCKET NOW ACTIVE AT P.I. LEVEL + MOVEI C,%ISIND ; New state = reading NCP data message + JRST IMPRM9 ; Start reading + +IMPRMP: MOVSI D,100000 ;SET INPUT HELD UP BY CORE JOB + IORM D,IMSOC6(I) +IFN KAIMP,[ + MOVE D,IMPPIA + MOVEM D,IMPSVP + SETZM IMPPIA ;TURN OFF NETWORK FOR A WHILE +] +IFN DMIMP,CONO FI,FIIN+0 ;SET PIA TO 0 FOR A WHILE, CORE JOB WILL GET BACK + JRST IMPRET + +IMRMAH: AOSA IMNBAE +IMRMAF: AOS IMNMAE + JRST IMPIRT + +IMPRM7: AOSA IMNMNC +IMRMAG: AOS IMNMSS + JRST IMPIRT + +; Got Last Imp Word (in A) of regular NCP data message +; Comes here from IMPBKX. + +IMPRMB: MOVE I,IMPIPI + MOVE B,IMBLKI + CAMN B,IMPNIW + JRST IMPRMC ;ONE EXTRA WORD OF IMP PADDING, IGNORE IT + ADD B,[1,,1] ;ADDR TO NEXT WORD, COUNT TO ZERO + CAME B,IMPNIW + JRST IMPRMY + MOVEM A,(B) ;STORE LAST WORD +IMPRMC: MOVE E,IMPNBI ;# BYTES IN + ADDM E,IMSMPC(I) ;MAKE AVAIL TO M.P. + MOVEM E,@IMSPIP(I) ;STORE HEADER + AOS E,IMPNIW ;WORD AFTER MSG WILL BE NEXT HEADER + CAILE E,@IMSBFE(I) + HRRZ E,IMSOC6(I) ;WRAP + HRRM E,IMSPIP(I) ;LEAVE LH OF IMSPIP ALONE + CAIN E,@IMSMPP(I) + JRST 4,. ;BUFFER 1 WORD TOO SMALL? + SETOM (E) + MOVEI E,%NSINP + HRRM E,IMSOC4(I) ;INPUT AVAILABLE + PUSHJ P,IMPUIN ;INTERRUPT USER + MOVSI D,200000 ;CLEAR ACTIVE AT P.I. LEVEL + ANDCAM D,IMSOC6(I) + SETOM IMPIPI + JRST IMPIR1 + +IMPRMY: HRRZ E,IMPNIW ;NOT ENDING WHERE IT'S SUPPOSED TO + SUBI E,(B) ;E GETS NUMBER OF MISSING WORDS + MOVE H,IMPCSH + BUG INFO,[NET: MSG FM HST ],OCT,IMPHTN(H),[SHORT ],DEC,E,[WDS, BC],DEC,IMPCBC + JRST IMPRMC ;PRETEND HOST TRANSMITTING GARBAGE + +IMPRMZ: MOVE H,IMPCSH + BUG INFO,[NET: HST ],OCT,IMPHTN(H),[SENT BYTE SIZE ],DEC,A,[SHOULD BE],DEC,B + JRST IMPIRT ;Discard message + +SUBTTL ARPANET NCP OUTPUT INTERRUPT LEVEL + +;HERE ON COMPLETION OF TRANSMISSION OF CONTROL MESSAGE + +IMPOB6: SETZM IMPOS + SKIPN A,IMPSVQ + JRST IMPRET ;THAT WAS A NOP + HLRZ B,1(A) ;HOST TABLE INDEX + MOVSI D,400000 + IORM D,IMPHTB(B) ;SET RFNM WAIT BIT + AOS IMRFCT + LDB D,[051100,,TIME] + DPB D,[221100,,IMPHTB(B)] ;STORE TIME TOO + HLRZ T,A + HRRZS A + MOVE B,(A) + MOVEM B,(T) + JUMPGE B,IMOB7A + CAME A,IMPLCQ + JRST 4,. ;IMPLCQ GAVE WRONG LAST MESS NO. + MOVEM T,IMPLCQ + CAIN T,IMPNCQ + SETOM IMPLCQ +IMOB7A: CAIN A,IMPMPL ;SKIP IF NOT MAIN PROG BLOCK + JRST [ SETOM IMPMPU + JRST IMPRET ] + MOVE B,IMFFCQ + CAIN B,(A) + JRST 4,. ;MAKING INFINITE LOOP + MOVEM B,(A) + MOVEM A,IMFFCQ + AOS A,IMFCQL + SKIPGE B,IMPHI ;RETURN IF INPUT NOT HELD UP + CAIG A,1 ;SKIP IF INPUT HELD UP AND NOW ENOUGH FREE + JRST IMPRET + SETZM IMPHI + AOJE B,IMPRET ;INPUT WAS NOT YET SUCCESSFULLY HELD UP + AOJN B,[JRST 4,.] ;IMPHI SHOULD HAVE BEEN -2 + AOS IMPNUH + MOVE TT,IMSTAS ;GET OLD CONI + TRNE TT,IMPLW +IFN KAIMP,[ + CONO IMP,IMI32C + DATAI IMP,A +];KAIMP +IFN DMIMP,[ + CONO FI,FII32C + MOVE A,IMPSUS +];DMIMP + TRNE TT,IMPLW ;RESUME INPUT + JRST IMPBKV + SKIPE IMPIS + JRST 4,. + JRST IMSTRT + +;HERE ON COMPLETION OF TRANSMISSION OF DATA MESSAGE + +IMPOBG: SETZM IMPOS + MOVE I,IMPOPI + HRRZ Q,IMSOC4(I) + CAIN Q,%NSOPN + AOS IMSOC4(I) .SEE %NSRFN ;PUT INTO RFNM WAIT STATE + MOVSI A,20000 + CAIN Q,%NSCLS + IORM A,IMSOC5(I) + MOVSI Q,200000 + ANDCAB Q,IMSOC6(I) ;NO LONGER ACTIVE AT P.I. LEVEL + SETOM IMPOPI + MOVN A,IMPNBT ;BITS SENT + ADDM A,IMSC7I(I) ;DECREASE BITS IN BUFFER + ADDB A,IMSOC7(I) ;DECREASE ALLOCATION + SKIPL A ;SKIP IF ALLOC LOST + SOSGE IMSOC8(I) ;SKIP IF MSG ALLOC DIDN'T LOSE + JRST 4,. ;LOST + MOVE Q,IMSOC5(I) + TLNN Q,140000 ;INTERRUPT USER IF DIRECT CONNECT (CHEAP), DEPEND ON ALLOC, + SKIPN IMSMPC(I) ; OR IF OUTPUT BUFFER WAS FULL, + PUSHJ P,IMPUIN ; SINCE HE MAY WANT TO SEND MORE + MOVE A,IMPNBO ;# BYTES FREED IN BUFFER BY REMOVAL OF MSG + ADDM A,IMSMPC(I) ;SPACE USED BY MESSAGE NOW FREE + MOVE A,IMPNPT ;UPDATE IMSPIP + HRRZ Q,IMSOC6(I) ;VALIDATE THIS + CAILE Q,(A) + JRST 4,. ;POINTS BEFORE BUFFER + HRRZ Q,IMSBFE(I) + CAIGE Q,(A) + JRST 4,. ;POINTS AFTER BUFFER + MOVEM A,IMSPIP(I) ;.. + JRST IMPRET + +;OUTPUT A DATA MESSAGE. + +IMPOBD: MOVE T,TIME + SUB T,IMSOCT(I) + SKIPL IMSOC4(I) ;SKIP IF WANT TO SEND THIS BUFFER + CAIL T,30.*2 ;SKIP IF BUFFER FIRST WRITTEN LESS THAN 2 SEC AGO + JRST IMOBD1 + JRST IMPOBA ;DON'T SEND NOW, GO BACK AND LOOK FOR OTHERS + +IMOBD1: MOVE TT,IMSPIP(I) + CAMN TT,IMSMPP(I) ;SKIP IF ANY BITS TO SEND + JRST IMPOBA ;NO + SKIPE IMSOC7(I) ;SKIP IF NO BITS ALLOCATED + SKIPN IMSOC8(I) ;SKIP IF MSG ALLOCATED + JRST IMPOBA ;NO BITS OR NO MSGS ALLOWED + MOVSI Q,200000 + IORB Q,IMSOC6(I) ;ACTIVE AT PI LEVEL + +;CODE TO SEND OUT A BUFFER OR PARTIAL BUFFER +;ON ENTRY - I/ SOCKET TABLE INDEX +; Q/ BUFFER POINTER FROM IMSOC6 +; TT/ BYTE POINTER TO FIRST BYTE TO SEND +;SETS UP - T/ WORD SIZE (32 OR 36) +; E/ FLAGS FROM IMSOC5 +; B/ BYTE SIZE +; C/ # BITS TO SEND + + SETZM IMPNBO + MOVE T,IMSMPP(I) + MOVEM T,IMOB0Z ;SAVE FOR DEBUGGING + MOVEI T,32. + SKIPL E,IMSOC5(I) ;SKIP IF IN 32BIT MODE + MOVEI T,36. ;SET 36BIT + LDB B,IMSCBS ;BYTE SIZE + HRRZ C,IMSMPP(I) ;COMPUTE # OF BYTES TO SEND + SUBI C,(TT) + JUMPL C,[MOVE D,IMSBFE(I) ;WRAPS AROUND + SUB D,Q + ADDI C,1(D) ;SO ADD # WDS IN BUFFER + JRST .+1] + IMUL C,T ;FIRST GUESS AT NUMBER OF BITS + LDB A,[360600,,TT] ;GETS POSITION FIELD OF BYTE PTR + LDB D,[360600,,IMSMPP(I)] + SUBM A,D ;CORRECTION TO NUMBER OF BITS + ADD C,D ;C NOW HAS NUMBER OF SENDABLE BITS IN BUFFER + SKIPL E ;SKIP IF 32BIT + JUMPN A,IMOB5A ;36BIT - JUMP IF NOT 0 (MIDDLE OF WORD) + CAILE A,4 ;32BIT - SKIP IF 4, OR 36BIT 0 - SKIP IF NOT MID-WORD + JRST IMOB5B ;32BIT MID-WORD - SEND PART OR REST OF WORD + CAME TT,IMSBFE(I) ;AT RIGHT OF WORD, IS IT LAST WORD? + AOSA TT ;NO, ADVANCE TO NEXT + HRR TT,Q ;YES, WRAP AROUND TO FIRST + TLO TT,440000 ;SWITCH FROM RIGHT OF WORD TO LEFT OF WORD + CAMG C,IMSOC7(I) ;SKIP IF TOO BIG FOR ALLOCATE + CAILE C,8000. ;FITS IN ALLOCATE, SKIP IF FITS IN IMP MESSAGE + JRST IMOB1 ;MUST SEND LESS THAN ALL THE BITS IN BUFFER +IMOB0F: MOVE D,IMSMPP(I) ;SENDING WHOLE BUFFER + LDB J,[360600,,D] ;ADVANCE IMSMPP TO NEXT WORD BOUNDARY + ADDI J,-36.(T) ;RH(J) := # BITS TO ADVANCE TO WORD BOUNDARY + MOVNI J,(J) + IDIV J,B + ADDM J,IMSMPC(I) ;SUBTRACT FROM FREE THE BYTES SKIPPED OVER + MOVNM J,IMPNBO ;BUT RETURN TO FREE AFTER TRANSMISSION + HLL D,IMSBFE(I) ;NOW ADVANCE IMSMPP TO RIGHT END OF WORD + MOVEM D,IMSMPP(I) ;AND IMSPIP WILL GET SET EQUAL TO IMSMPP +IMOB0A: MOVEM D,IMPNPT ;ILDB -> FIRST BYTE TO SEND OUT NEXT TIME + JUMPLE C,[JRST 4,.] ;SOMEBODY COMPUTED BAD # BITS + MOVE A,C + IDIV C,B ;C := # BYTES GETTING SENT + JUMPN D,[JRST 4,.] ;LOSS, TRYING TO SEND PARTIAL BYTE + ADDM C,IMPNBO ;# BYTES TO RETURN TO FREE AFTER MSG SENT + MOVEM A,IMPNBT ;# BITS TO SUBTRACT FROM ALLOCATION THEN +;DROPS THROUGH + ;DROPS IN +;NOW SET UP BUFFER HEADER FOR IMP MESSAGE IN IMOLDR +; TT -> FIRST WORD TO SEND +; A NUMBER OF BITS TO SEND +; C NUMBER OF BYTES +; B BYTE SIZE +; T WORD SIZE +; E FLAGS + + LDB H,IMSCFH ;HOST TABLE INDEX + MOVEI Q,IMOLDR-2 ;HACK HACK + PUSHJ P,STHSTP ;STORE HOST NUMBER, MESSAGE TYPE 0 + LDB Q,IMSCLN ;LINK NUMBER + DPB Q,[001000,,IMOLDR+1] + LDB Q,[221000,,IMSOC6(I)] ;GET BUFFER TYPE + MOVEI D,4 + CAIN Q,377 + MOVEI D,7 + DPB D,[400400,,IMOLDR+1] ;STORE HANDLING TYPE, DEPENDING ON BUFFER SIZE + DPB B,[201000,,C] ;STORE SIZE IN SAME WD AS COUNT + LSH C,8 + MOVEM C,IMOLDR+5 ;HOST-HOST HEADER - 00,SIZE,BYTE-COUNT,0000 +IFN KAIMP,CONO IMP,IMO32C +IFN DMIMP,CONO FI,FIO32C ;36BIT MODE FOR HEADER, AND NO PIA YET + DATAO IMP,IMOLDR ;OUTPUT THE FIRST LEADER WORD + SETZM IMOPNT ;START AT BEGINNING OF IMOLST + MOVE B,[-5,,IMOLDR] ;SEND REST OF LEADER + MOVEM B,IMOLST + MOVEI B,3 + SKIPGE E + MOVEI B,2 + MOVEM B,IMOMOD ;SEND DATA IN 32 OR 36 BIT MODE AS APPROPRIATE + ADDI A,-1(T) ;ROUND UP IF NOT EXACT + IDIV A,T ;# WDS TO SEND + MOVEI D,-1(TT) ;FIRST WORD TO SEND MINUS ONE + ADDI D,(A) ;LAST WORD TO SEND + CAIG D,@IMSBFE(I) ;SKIP IF WRAP + JRST IMOB7 + HRRZ B,IMSBFE(I) ;COMPUTE # TO SEND FIRST TIME + SUBI B,-1(TT) ;B GETS PLUS NUMBER TO SEND FIRST TIME + SUBM B,A ;A GETS MINUS NUMBER TO SEND SECOND TIME + MOVNI C,(B) + HRLI C,-1(TT) ;C GETS SWAPPED BLKO POINTER FOR FIRST TIME + MOVE Q,IMSOC6(I) ;POINTER TO BUFFER +IFN KAIMP,[ + MOVEI B,3 ;SEND LAST WORD SEPARATELY + MOVEM B,IMOBK2 + AOJE A,.+3 +] HRLI A,-1(Q) ;BLKO POINTER FOR SECOND TIME + MOVSM A,IMOBK2 +IFN KAIMP,[ + MOVNI A,(A) + ADDI A,-1(Q) + HRROM A,IMOBK3 ;STORE BLKO POINTER TO LAST WORD +] + JRST IMOB8 + +IMOB7: MOVSI C,3 ;NO WRAP, SO NO SECOND BLKO + MOVSM C,IMOBK2 +IFN KAIMP,[ + SOS D + HRROM D,IMOBK3 ;DO LAST WORD SEPARATELY + SOJE A,IMOB8 ;SPECIAL CASE LAST WORD IS ONLY WORD +] + MOVNI C,(A) ;MAKE BLKO POINTER + HRLI C,-1(TT) +IMOB8: MOVSM C,IMOBK1 + MOVSI TT,400000 ;TURN OFF "SEND ME" + ANDCAM TT,IMSOC4(I) + HRRZM I,IMPOPI ;SAVE INDEX FOR BLKO RUNOUT + AOS IMPMSS+0 + MOVEI C,%ISOND ;STATE FOR "END OF DATA" + JRST IMOB9 + +;BUFFER CANNOT BE SENT AS 1 MSG. GRT ALLOC OR 8000 BITS. + +IMOB1: MOVE C,IMSOC7(I) ;ALLOC + CAILE C,8000. + MOVEI C,8000. ;C := MIN(BITS IN BUFFER, ALLOC, MAX IMP MSG SIZE) + TLNE E,2000 ;SKIP IF BYTES EXACTLY FIT IN WORD + JRST IMOB3 ;MUST SEND MULTI WORDS + CAMGE C,T ;SKIP IF ALLOC GEQ WDSIZ + JRST IMOB2 ;MUST SEND PART WORD + IDIV C,T ;#WDS + MOVE D,C + IMUL C,T ;#BITS IN THOSE WDS +IMOB1A: ADDI D,-1(TT) ;LAST WORD OUTPUT + CAIG D,@IMSBFE(I) + JRST .+3 + SUBI D,@IMSBFE(I) ;WRAP AROUND + ADDI D,-1(Q) + HLL D,IMSBFE(I) ;PUT IN BYTE PART (RIGHT END OF WORD) + JRST IMOB0A ;BUILD HEADER AND OUTPUT + +;SEND PART OF WORD BECAUSE ALLOC IS TOO SMALL + +IMOB2: MOVE D,TT ;-> FIRST BYTE TO BE SENT + MOVNI A,-36.(C) ;36-BITS SENT + DPB A,[360600,,D] ;IS NEXT BYTE TO GO + JRST IMOB0A + +;SEND PARTIAL BUFFER OF BYTES WHICH DO NOT FIT EXACTLY IN WORDS (E.G. 7BIT BYTES) +;MUST SEND A "QUANTUM" WHICH FOR LAZINESS' SAKE IS 36 BYTES + +IMOB3: MOVEI A,36. ;#BITS IN A WORD + IMUL A,B ;#BITS IN A QUANTUM + IDIV C,A ;# QUANTA + JUMPE C,IMOB4 ;NOT ENOUGH ALLOC FOR EVEN 1 QUANTUM, SORRY CHARLIE + MOVE D,C + IMUL C,A ;#BITS TO SEND + IMUL D,B ;#WDS TO SEND (36 BYTES TAKE WDS) + JRST IMOB1A + +;NEED MORE ALLOCATE TO SEND A BUFFER FOR THIS ODD-SIZE CONNECTION + +IMOB4: MOVSI T,200000 + ANDCAM T,IMSOC6(I) ;CLEAR "ACTIVE AT PI LEVEL" BIT + JRST IMPOBA ;MAYBE TRY ANOTHER ONE + +;SENDING REST OF PARTIAL WORD (PI PTR NOT AT WORD BOUNDARY) +;A/ BITS LEFT IN WORD + +IMOB5A: SKIPA C,A ;36BIT GETS WHOLE WD +IMOB5B: HRREI C,-4(A) ;32BIT GETS 4 LESS + MOVNI J,-36.(A) ;# BITS SHIFT TO LEFT JUSTIFY + HRRZ D,TT + CAIN D,@IMSMPP(I) ;IF WHOLE REST OF BUFFER IS IN THIS WORD + JRST [ LDB D,[360600,,IMSMPP(I)] + SUB A,D ;A := NUMBER OF BITS TO SEND + MOVE C,(TT) ;ALIGN BITS TO BE SENT IN LEFT OF WORD + LSH C,(J) + MOVEM C,(TT) + MOVE C,A + JRST IMOB0F ] ;RE-ALIGN POINTERS TO WORD BOUNDARY + CAMLE C,IMSOC7(I) ;SKIP IF WILL FIT IN ALLOC + JRST IMOB6 ;MUST SEND BYTES NOT LEFT JUST IN WD, AND MORE TO RIGHT + MOVE D,(TT) ;GET WORD + LSH D,(J) ;LEFT JUSTIFY + MOVEM D,(TT) + MOVE D,TT + HLL D,IMSBFE(I) ;ADVANCE PI POINTER TO END OF THIS WORD + JRST IMOB0A ;BUILD HDR & SEND + +;SEND MIDDLE PART OF WORD. BECAUSE OF SMALL ALLOCATES, THE LEFT END OF THE +; WORD WAS SENT AND ALSO THERE IS NOT ENOUGH ALLOCATE TO SEND THE REST +; OF THE ONE WORD. THIS MIGHT NEVER OCCUR EXCEPT FOR 8 BIT BYTES. +;MUST MOVE GOOD BITS TO LEFT END OF WORD, WITHOUT DISTURBING BITS TO THE RIGHT + +IMOB6: MOVE C,IMSOC7(I) ;CAN ONLY SEND ALLOC BITS + SUB A,C ;POS OF LO BIT TO PICK UP + DPB A,[360600,,TT] ;POS IN BYTE PTR + MOVE D,TT ;SAVE ADVANCED PI PNTR + DPB C,[300600,,TT] ;STORE AS SIZE OF BYTE + LDB R,TT ;GET BYTE + MOVNI A,-36.(C) ;POS OF LO BIT TO STORE + DPB A,[360600,,TT] ;POS IN B PTR + DPB R,TT ;STORE BYTE AWAY + JRST IMOB0A ;SEND THE BYTE(S) + +OVHMTR UUO ;YET MORE RANDOM UUOS diff --git a/src/system/net.32 b/src/system/net.32 new file mode 100755 index 00000000..a8793d9b --- /dev/null +++ b/src/system/net.32 @@ -0,0 +1,501 @@ +;; For ITS network stuff, the following parameters are defined: +; +; NETP - General network code (net independent, both CHAOS, NCP, TCP, etc) +; INETP - Internet Protocol code. Must have IMPP or some other device. +; NCPP - Include NCP code (IMPP must be on) +; TCPP - Include TCP code (INETP must be on) + +; CHAOSP - Include CHAOS net code +; - other CHAOS stuff, all independent of internet stuff. + +NE%UNT==:<1_32.> ; Escape bit indicating non-Internet address +NW$BYT==:301400 ; Byte pointer to network number (approx!) +NE%STR==:<1_33.> ; Escape bit indicating string-type address + +DEFINE HOSTN A,B,C,D +.RADIX 10.,<<<<+B>_8>+C>_8>+D,!TERMIN + +; HOSTS3 full word network # values for certain networks + +NW%CHS==:> +NW%ARP==:<12_24.> +NW%LCS==:<22_24.> +NW%AI==:HOSTN 128,52,0,0 + +DEFINE GETNET AC,(ADDR) ; Macro to extract net number +IFNB [ADDR] MOVE AC,ADDR + TLNN AC,(17_32.) ; Check for non-Internet type addrs + TLNN AC,(1_31.) ; Internet address, see if class A net + TDZA AC,[77,,-1] ; Unternet or class A, zap low 3 octets + TLNN AC,(1_30.) ; Class B or C, see which. + TRZA AC,177777 ; Class B network, zap low 2 octets + TRZ AC,377 ; Class C net, only zap 1 low octet +TERMIN + +;;; Misc defs +CALL== +RET== +CALRET== + + OVHMTR NET + +IFN IMPP,[ ; ARPAnet IMP interface code +IFN KAIMP,[ +$INSRT IMPOLD +] +IFN KSIMP,[ +$INSRT IMP +] +] + + OVHMTR NET + +IFN NCPP,[ ; Old Arpanet NCP protocol code +$INSRT NCP +] + OVHMTR NET + +IFN INETP,[ ; Internet Protocol code +$INSRT INET +] + + OVHMTR NET + +IFN TCPP,[ ; Transmission Control Protocol code +$INSRT TCP +] + + OVHMTR UUO + +IFN CHAOSP,[ ; CHAOSnet interface and protocol code +$INSRT CHAOS +] + OVHMTR UUO + +SUBTTL General Network System Calls + +; .CALL NETRFC - Get a pending Request For Connection for a specific network +; Arg 1 - SIXBIT name of network +; Arg 2 - optional network-dependent arg +; (for CHAOS, points to packet buffer) +; Val 1 - network-dependent value +; For TCP and ARPNCP, this is ,, +; Control bits: + %NQREF==:1 ; Arg 2 is previously returned identifier, + ; refuse connection and flush from queue. + +NETRFC: MOVE C,CTLBTS(U) ; Set up control bits in C +IFN TCPP,[ + CAMN A,[SIXBIT /TCP/] + JRST TCPRQ +] +IFN CHAOSP,[ + CAMN A,[SIXBIT /CHAOS/] + JRST [ TRNE C,%NQREF ; If refusing conn, + JRST OPNL12 ; Ignore, can't handle yet. "Mode not avail" + CAIGE W,2 ; Must have a 2nd arg + JRST OPNL30 ; "Too few args" + MOVE A,B ; Fake out old CHAOSQ call + JRST CHAOSQ] +] +IFN NCPP,[ ; NOP for now +; CAMN A,[SIXBIT /ARPNCP/] +; JRST IMPRQ +] + JRST OPNL33 ; No match, say "meaningless args". + +; .CALL NETBLK - Wait for net channel state to change, or time out. +; Arg 1 - Channel (comes in R) +; Arg 2 - Undesired state +; Arg 3 - Optional timeout (as in .SLEEP), written back unless immediate +; Val 1 - New state +; Val 2 - Time left + +NETBLK: HRRZ T,(R) ; Get IOCHNM RH = device index + HLRZ I,(R) ; Get LH = often connection index +IFN NCPP,[ + CAIL T,NETDUI + CAILE T,NETDBO + CAIA + JRST [MOVE T,[HRRZ A,IMSOC4] + JRST NETBLI] +] ;NCPP +IFN CHAOSP,[ + CAIE T,CHAIDN + CAIN T,CHAODN + JRST [MOVE T,[HRRZ A,CHSSTA] + JRST NETBLI] +] ;CHAOSP +IFN TCPP,[ + CAIN T,TCPDUI + JRST [ MOVE T,[HLRZ A,XBSTAU] + JRST NETBLI] + CAIN T,TCPDUO + JRST [ MOVE T,[HRRZ A,XBSTAU] + JRST NETBLI] +] ;TCP + JRST OPNL34 ; Not a net chan, say "Wrong Type Device". + + +; T/ Instruction to XCT (not indexed) to get state in A +; Entry at NETBLI adds (I) to the instruction. + +NETBLI: ADDI T,(I) ; Provide "index" for instruction. +NETBL0: CAIGE W,3 + JRST [ HRLOI D,377777 ; No time given, use infinity + JRST NETBL4 ] + TLNE C,1000 ; Skip if pointer rather than immediate + JRST [ HRRZ D,C ; Get immediate time + ADD D,TIME + JRST NETBL4 ] + XCTR XRW,[MOVES D,(C)] ; Get time, check writeability + JUMPGE D,[ MOVNS D ; Relative time, make negative absolute + SUB D,TIME + JRST .+1 ] + UMOVEM D,(C) ; Store back absolute time + MOVNS D ; Make positive +NETBL4: MOVEM D,AC0S+D(U) ; Save absolute time to wait until + MOVEM B,AC0S+B(U) ; Save undesired state + PUSHJ P,NETBL2 ; Skip if state change or timeout + PUSHJ P,UFLS + MOVE B,D + SUB B,TIME ; How much used? + XCT T ; Return new state + JRST POPJ1 + +NETBL2: XCT T ; Get current state + CAME A,AC0S+B(U) ; Skip if still match + JRST POPJ1 + MOVE A,AC0S+D(U) ; Timeout time + CAMG A,TIME + AOS (P) + POPJ P, + +SUBTTL Utilities - CVTH2A, CVTH3A + + +; CVH2NA - Convert network host address in A to HOSTS2 format. +; A/ net address (any format) +; Returns A + +CVH2NA: PUSH P,B + LDB B,[301400,,A] ; Get high 12 bits of net address + CAIGE B,70 ; If less than lowest HOSTS2-fmt value + JUMPN B,CVH2N3 ; then must be HOSTS3, go convert. + CAIL B,1000 ; If any of high 3 bits set, + JRST CVH2N3 ; then it's a HOSTS3 strange-fmt number. + JUMPN B,CVH2N2 + CAILE A,377 ; Zero network, so must be ARPA net + JRST CVH2N1 ; Not just 8 bits, just add net number. + + ; Old-style 8-bit Arpanet host number + LSHC A,-6. + ROT B,6. + DPB B,[112000,,A] +CVH2N1: TLO A,(12_33) + JRST POPBJ + + ; Probably HOSTS2 format number +CVH2N2: JRST POPBJ ; For now, that's good enough. + + ; HOSTS3 format number, convert it. +CVH2N3: CAIN B,12 ; Arpa net? + JRST [ LSHC A,-16. + ANDI A,377 + ROT B,16. + DPB B,[112000,,A] + TLO A,(12_33) + JRST POPBJ] + CAIN B,7+ ; Chaos net? + JRST [ ANDI A,177777 ; Yup, fix it up. + TLO A,(7_33) + JRST POPBJ] + CAIN B,22 ; LCS net? + JRST [ LSHC A,-8. + ANDI A,-1 + LSH A,2 + LSHC A,8. + TLO A,(22_33) + JRST POPBJ] + + ; Not a known net, but try to do something plausible. + ANDCM A,[-1_24.] ; Preserve low 24 bits + DPB B,[331100,,A] ; put net # into HOSTS2 field. + POP P,B + RET + +; CVH3NA - Convert network host address in A to HOSTS3 (Internet) format. +; A/ net address (any format) +; Returns A + +CVH3NA: PUSH P,B + LDB B,[301400,,A] ; Get high 12 bits of net address + CAIGE B,70 ; If less than lowest HOSTS2 value, + JUMPN B,CVH3N3 ; it's already HOSTS3 format! (unless zero) + CAIL B,1000 ; If any of high 3 bits were set, + JRST CVH3N3 ; it must be a HOSTS3 strange-fmt addr. + JUMPN B,CVH3N2 ; If not zero, then must assume HOSTS2 fmt. + + ; Old-format 8-bit Arpanet host number, or HOSTS2 with zero net. + CAILE A,377 + JRST CVH3N6 ; If greater than 8 bits, assume HOSTS2, zero net. + LSHC A,-6 ; Put 10 bits spacing between host/imp #s. + LSH B,-<2+8.> + LSHC A,<2+8.+6> + TLO A,(12_24.) ; and add ARPA network number. + JRST CVH3N3 + + ; HOSTS2 format number +CVH3N2: TRZE B,7 ; Zap low 3 bits to ensure correct comparison + JRST CVH3N5 ; If any were set, can't be Chaosnet. + CAIN B,7_3 ; Chaos net? + JRST [ ANDI A,177777 ; Yes, kill all but bottom 16 bits + TLO A,(NE%UNT+<7_24.>) ; Add Chaos net # + JRST CVH3N3] +CVH3N5: CAIN B,12_3 ; Arpa net? +CVH3N6: JRST [ LSHC A,-9. + ANDI A,177777 + ROT B,9. + DPB B,[201000,,A] + TLO A,(12_24.) + JRST CVH3N3] + CAIN B,22_3 ; LCS net? + JRST [ LSHC A,-8. + LSH A,-2 + ANDI A,377 + LSHC A,-8. + TLO A,(22_24.) + JRST CVH3N3] + + ; No match, assume it's HOSTS3. + +CVH3N3: POP P,B + RET + +;.CALL STYNET +;ARG 1 - STY CHANNEL +;ARG 2 - NET INPUT CHANNEL TO CONNECT STY OUTPUT TO, OR -1 TO DISCONNECT +;ARG 3 - NET OUTPUT CHANNEL TO CONNECT STY INPUT TO +;ARG 4 - CHARS TO SEND WHEN OUTPUT .RESET HAPPENS ON STY'S TTY +; UP TO 3 8-BIT CHARACTERS, LEFT JUSTIFIED. + +NSTYNT: TLNN R,%CLSST + JRST OPNL34 ;1ST ARG NOT A STY CHANNEL. + HLRZ I,(R) ;GET TTY # OF STY + HRRES B ;ALLOW IMMEDIATE -1 + JUMPGE B,NSTYN2 ;JUMP IF CONNECTING. + PUSHJ P,NSTYN0 ;DISCONNECT + JRST OPNL41 ;WASN'T CONNECTED + JRST POPJ1 + +;VARIOUS ROUTINES CALL HERE WITH THE TTY# OF A STY IN I, TO DISCONNECT THE +; STY FROM THE NETWORK. NOTE THIS ROUTINE MUST NOT CHANGE U AND MUST NOT +; LSWCLR, SINCE IT COULD BE CALLED FROM IODCL VIA STYCLS OR NETCLS. + +NSTYN0: MOVSI B,%SSNET ;DISCONNECTING BOTH SIDES. + CONO PI,NETOFF + TDNN B,STYSTS-NFSTTY(I) + POPJ P, ;THIS STY NOT CONNECTED? + ANDCAB B,STYSTS-NFSTTY(I) ;MARK AS NO LONGER CONNECTED + MOVE C,STYNTL-NFSTTY(I) ;REMOVE THIS STY FROM ACTIVATION LIST + MOVEI D,STYNTA-STYNTL+NFSTTY +NSTYN1: CAMN I,STYNTL-NFSTTY(D) ;FIND THE STY THAT POINTS TO THIS ONE, + MOVEM C,STYNTL-NFSTTY(D) ;AND PATCH US OUT OF THE LIST. + SKIPE D,STYNTL-NFSTTY(D) ;SEARCH WHOLE LIST TILL FIND WHO POINTS TO US. + JRST NSTYN1 + SETOB C,STYNTL-NFSTTY(I) + EXCH C,STYNTI-NFSTTY(I) ;MARK THIS STY AS HAVING NO CONNECTION, GET SOCKET INDICES +IFN CHAOSP,[ + TLNE B,%SSCHA + JRST [ MOVSI B,%SSCHA ;DISCONNECT FROM CHAOS NET + ANDCAM B,STYSTS-NFSTTY(I) + MOVSI B,%CFSTY + TDNN B,CHSSTA(C) + JRST 4,. ;CHAOS DOESN'T THINK IT WAS CONNECTED? + ANDCAM B,CHSSTA(C) + JRST NETOJ1 ] +];CHAOSP +IFN TCPP,[ + TLNE B,%SSTCP + JRST [ MOVSI B,%SSTCP ; Disconnect from TCP connection + ANDCAM B,STYSTS-NFSTTY(I) ; Flush STY's "connect" bit + MOVSI B,(XB%STY) + TDNN B,XBUSER(C) ; Make sure TCP thinks connected + BUG ; It isn't?? + ANDCAM B,XBUSER(C) + JRST NETOJ1] +] ;TCPP +IFN NCPP,[ + MOVE B,[40000,,777] + TDNN B,IMSOC5(C) + JRST 4,. ;SOCKET DOESN'T THINK IT WAS CONNECTED? + ANDCAM B,IMSOC5(C) ;AND MARK SOCKETS WE WERE CONNECTED TO AS DISCONNECTED + MOVSS C + TDNN B,IMSOC5(C) + JRST 4,. ;SOCKET DOESN'T THINK IT WAS CONNECTED? + ANDCAM B,IMSOC5(C) + JRST NETOJ1 +] ;NCPP +.ELSE BUG + +; Here to set up STY connection. + +NSTYN2: MOVE Q,I ;SAVE TTY # OF STY + MOVEI E,1 + MOVE A,B ;DECODE THE NETWORK INPUT CHANNEL + JSP T,CHNDCD + HRRZ A,(R) +IFN CHAOSP,[ + CAIE A,CHAIDN + CAIN A,CHAODN + JRST [ HLRZ I,(R) ;CONNECT TO CHAOS NET + CONO PI,NETOFF + MOVSI B,%CFSTY + TDNE B,CHSSTA(I) + JRST OPNL23 ;ALREADY CONNECTED, FILE LOCKED + MOVSI C,%SSNET+%SSCHA + TDNE C,STYSTS-NFSTTY(Q) + JRST OPNL23 ;ALREADY CONNECTED, FILE LOCKED + IORM B,CHSSTA(I) ;OK, HOOK UP + DPB Q,[$CFTTN,,CHSSTA(I)] + JRST NSTYN3 ] +];CHAOSP +IFN TCPP,[ + CAIE A,TCPDUI + CAIN A,TCPDUO + JRST [HLRZ I,(R) ; Connect to TCP, get TCB index + CONO PI,NETOFF + MOVSI B,(XB%STY) + TDNE B,XBUSER(I) + JRST OPNL23 ; TCB Already connected, say "File Locked" + MOVSI C,%SSNET+%SSTCP + TDNE C,STYSTS-NFSTTY(Q) + JRST OPNL23 ; STY already connected, say "File Locked" + DPB Q,[XB$STY (I)] ; Store TTY # to connect TCB. + JRST NSTYN3] +] ;TCPP +IFN NCPP,[ + JSP T,NETCHK ;TEST LEGALITY; OPNL IF LOSES + TDNE E,IMSOC2(I) + JRST OPNL2 ;WRONG DIRECTION IF IT'S AN OUTPUT CHANNEL + MOVE B,I ;SAVE INPUT IMSOC INDEX + MOVE A,C ;DECODE OUTPUT CHANNEL + JSP T,CHNDCD + JSP T,NETCHK + TDNN E,IMSOC2(I) + JRST OPNL2 ;WRONG DIRECTION IF INPUT SOCKET + CONO PI,NETOFF + MOVE E,[40000,,777] + TDNN E,IMSOC5(B) ;ERROR IF EITHER CHANNEL ALREADY CONNECTED + TDNE E,IMSOC5(I) + JRST OPNL23 ;"FILE LOCKED" + MOVSI C,%SSNET + TDNE C,STYSTS-NFSTTY(Q) + JRST OPNL23 ;SIMILAR ERROR IF STY ALREADY CONNECTED + HRR E,Q ;GET 40000,,TTY # + IORM E,IMSOC5(I) + IORM E,IMSOC5(B) ;MARK SOCKETS AS CONNECTED +] ;NCPP + +NSTYN3: SKIPGE STYNTL-NFSTTY(Q) ;HALT IF STY'S VARS ARE NOT CORRECT FOR A + SKIPL STYNTI-NFSTTY(Q) ;NON-CONNECTED STY. + JRST 4,. + IORM C,STYSTS-NFSTTY(Q) ;ALL ERROR CAUGHT, SO MARK STY CONNECTED. + HRL B,I ;PUT INPUT IMSOC IDX,, OUTPUT IMSOC IDX + MOVSM B,STYNTI-NFSTTY(Q) ;INTO THE STY + TRZ D,7777 ;STORE THE OUTPUT RESET CHARACTERS - AT MOST 3 + MOVEM D,STYORC-NFSTTY(Q) + + ;ACTIVATE IN CASE HAS UNREAD INPUT +IFN NCPP,[ + TLNN C,%SSCHA+%SSTCP + PUSHJ P,IMPUIN +] ;NCPP +IFN CHAOSP,[ + TLNE C,%SSCHA + PUSHJ P,CHINTI +];CHAOSP +IFN TCPP,[ + TLNE C,%SSTCP + PUSHJ P,TCPUII +] ;TCPP + JRST NETOJ1 + +SUBTTL Clock interrupt level code + +; NETCLK - Slow net clock. Called at clock level every 1/2 sec. +; Can clobber all ACs + +NETCLK: +IFN CHAOSP, PUSHJ P,CHACLK ; Run Chaos net 1/2-second clock +IFN TCPP, PUSHJ P,TCPCLK ; Run TCP 1/2-sec clock + SETCMB A,NETCL1 ; Flip the 1 sec switch + JUMPE A,CPOPJ ; Return unless time for 1-sec clock +IFN INETP,CALL IPFCLK ; Run IP reassembly timeout every 1 sec + RET +EBLK +NETCL1: 0 ; Flip-flop to get 1-sec ticks +BBLK + +; STYNTC - Called at clock level every 1/60 sec to process all +; necessary transfers of data between STYs and associated +; net connections + +STYNTC: CONO PI,NETOFF + SKIPN I,STYNTA ;GET HEAD OF ACTIVATE LIST + JRST NETONJ ;EMPTY + SETZM STYNTA ;COPY LIST IN CASE A STY IS PUT BACK ON + CONO PI,NETON +STYNT7: MOVE A,STYNTL-NFSTTY(I) ;GET NEXT ON LIST + MOVEM A,STYNTB ;SAVE FOR NEXT TIME AROUND LOOP + SETOM STYNTL-NFSTTY(I) ;THIS ONE IS NO LONGER ON ACTIVATE LIST + MOVE A,STYSTS-NFSTTY(I) + TLNN A,%SSNET + JRST 4,. ;STY CLAIMS NOT TO BE CONNECTED?? + MOVE R,I ;SAVE TTY # + +IFN CHAOSP,[ + TLNE A,%SSCHA + JRST STYCHA ;CONNECTED TO CHAOS NET +];CHAOSP +IFN TCPP,[ + TLNE A,%SSTCP + JRST STYTCP +] ;TCPP +IFN NCPP,[ + JRST STYNCP +];NCPP + +STYNT8: SKIPE I,STYNTB ;GET NEXT STY FROM COPIED ACTIVATION LIST + JRST STYNT7 + POPJ P, + +;SUBROUTINE TO STANDARDIZE HOST NUMBER, OPNL25 IF NO GOOD +;PROCESSES HOST NUMBER IN T, MUNGS H, CALLED BY JSP J,STDHST +STDHST: +IFN 1,[ + EXCH A,T + CALL CVH3NA ; Convert # to HOSTS3 fmt + EXCH A,T + LDB H,[301400,,T] ; Get high 12 bits (net #) + CAIE H,12 ; Should be ARPA net + JRST OPNL25 + TDZ T,[NW%ARP+<377_8.>] ; Flush the net # and logical host field + JRST (J) +] ;IFN 1 +IFN 0,[ + LDB H,[331000,,T] ;GET NETWORK-NUMBER FIELD + CAIE H,12 ;ONLY 12 OR 0 IS ACCEPTABLE + JUMPN H,OPNL25 + TDNE T,[400600,,400] ;MAKE SURE OTHER RANDOM BITS AREN'T ON + JRST OPNL25 + TLZ T,777000 ;CLEAR NETWORK NUMBER + JUMPE T,OPNL25 ;0 IS NOT ACCEPTABLE + CAIL T,400 ;SKIP IF OLD-STYLE HOST NUMBER + JRST (J) + LDB H,[060200,,T] ;GET HOST FIELD + ANDI T,77 ;GET IMP FIELD + EXCH H,T + DPB H,[112000,,T] ;RECOMBINE + JRST (J) +] ;IFN 0 diff --git a/src/system/ni1010.defs2 b/src/system/ni1010.defs2 new file mode 100755 index 00000000..8ecde7eb --- /dev/null +++ b/src/system/ni1010.defs2 @@ -0,0 +1,98 @@ +;;; -*- Mode: Midas -*- +.AUXIL + +;;; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + +; Junk for Interlan NI1010A Unibus Ethernet Interface + +;Interrupt information +DEFSYM %ILVEC==300 ;Input side interrupt vector (non-standard) + ;Output side assumed to be %LHVEC+4 +DEFSYM %ILPRI==5 ;Interrupt priority (should be 6, but + ; hard to change to anything but 4!) + +DEFSYM %ILBAS==764000 ;Base of NI1010A Registers in UB space + +;Unibus Registers +DEFSYM %ILCSR=:%ILBAS ;Control and Status Register +DEFSYM %ILBAR=:%ILBAS+2 ;Buffer Address Register +DEFSYM %ILBCR=:%ILBAS+4 ;Byte COunt Register + +;Bitz +;CSR bits +DEFSYM %ILEUA==:140000 ;Extended UB address field +DEFSYM %ILCMD==:37400 ;Command Function Code +DEFSYM %ILCD==:200 ;Command Done +DEFSYM %ILCIE==:100 ;Command Interrupt Enable +DEFSYM %ILRD==:40 ;Receive DMA done +DEFSYM %ILRIE==:20 ;Receive Interrupt Enable +DEFSYM %ILSTS==:17 ;Command Status Code + +;Commands (in %ILCMD field of CSR) +DEFSYM %ILSML==400 ;Module Loopback (through interface) +DEFSYM %ILSIL==1000 ;Set Internal Loopback +DEFSYM %ILCLM==1400 ;Clear loopback mode +DEFSYM %ILSPR==2000 ;Promiscuous Receive Mode +DEFSYM %ILCPR==2400 ;Clear Promiscuous Receive Mode +DEFSYM %ILSRE==3000 ;Set Receive-on-error bit +DEFSYM %ILCRE==3400 ;Clear Receive-on-error bit +DEFSYM %ILOFL==4000 ;Go Offline +DEFSYM %ILONL==4400 ;Go Online +DEFSYM %ILROD==5000 ;Run onboard diagnostics +DEFSYM %ILSIS==6000 ;Set Insert-source-address mode +DEFSYM %ILCIS==7000 ;Clear Insert-source-address mode +DEFSYM %ILDPA==7400 ;Set physical address to default +DEFSYM %ILSRM==10000 ;Receive all multicast packets +DEFSYM %ILCRM==10400 ;Clear Receive all multicast packets +DEFSYM %ILRRS==14000 ;Report and reset statistics +DEFSYM %ILRCD==14400 ;Report Collision Delay Times +DEFSYM %ILRCV==20000 ;Supply Receive Buffer +DEFSYM %ILLXD==24000 ;Load Transmit Data +DEFSYM %ILLXS==24400 ;Load Transmit Data and Send +DEFSYM %ILLGA==25000 ;Load Group Addreses +DEFSYM %ILDGA==25400 ;Delete Group Adresses +DEFSYM %ILLPA==26000 +DEFSYM %ILFRQ==30000 ;Flush Receive BAR/BCR Queue +DEFSYM %ILRST==37400 ;Reset + +;Error codes. Found in %ILSTS field of CSR +DEFSYM %ILEOK==0 ;Success +DEFSYM %ILERT==1 ;Success, with retries +DEFSYM %ILEBC==2 ;Illegal Command +DEFSYM %ILEIC==3 ;Invalid Command +DEFSYM %ILERE==4 ;Receiver Error +DEFSYM %ILEBB==5 ;Buffer Size Too Big +DEFSYM %ILEFS==6 ;Frams Size Too Small +DEFSYM %ILEEC==10 ;Excessive Collisions +DEFSYM %ILEBA==12 ;Buffer Not Word Aligned +DEFSYM %ILENX==17 ;Non-eXistant Memory + +;Diagnostic codes. Results from %ILROD command +DEFSYM %ILDOK==0 ;No Problem +DEFSYM %ILDCE==1 ;ROM/RAM Checksum Error +DEFSYM %ILDDE==2 ;DMA Circuitry Failed +DEFSYM %ILDXE==3 ;Transmit Circuitry Failed +DEFSYM %ILDRE==4 ;Receive Circuitry Failed +DEFSYM %ILDLE==5 ;Loopback checks failed + +;Frame status bits, returned in frame status byte +; at the top of each received packet. +DEFSYM %ILFCE==1 ;CRC Error in packet +DEFSYM %ILFAE==2 ;Alignment Error +DEFSYM %ILFFL==4 ;1+ frames lost just before + +IFN $$TEMP,EXPUNG DEFSYM + \ No newline at end of file diff --git a/src/system/nmtape.30 b/src/system/nmtape.30 new file mode 100755 index 00000000..7011a974 --- /dev/null +++ b/src/system/nmtape.30 @@ -0,0 +1,2432 @@ +;******************************** +;** +;** TO BE DONE: +;** +;** RECORDS LONGER THAN 1K +;** AUTOMATIC DETERMINATION OF DENSITY AND RECORD LENGTH WHEN READING +;** ALLOW CLOSE WHEN TAPE HAS BEEN TAKEN OFF +;** BE MORE FORGIVING OF CONTROLLER LOSSAGE +;** PASS .MTAPE TO JOB DEVICE +;** HAVE AN IGNORE ERRORS SWITCH +;** THIS HORRIBLE BLETCHEROUS IOT CODE SHOULD BE REDESIGNED +;** +;******************************** + +;Do not be deceived by the TM10 conditionals. This file is only good +; for a TM03/RH11 on a KS10. See MTAPE for anything else. Barf. + +IFE TM10A+TM10B+TM03S,.ERR NO MAGTAPE CONTROLLER TYPE SELECTED +IFN TM10A,INFORM IO BUSS MAG TAPE,1 +IFN TM10B,INFORM DATA CHANNEL MAG TAPE,1 +IFN TM03S,INFORM RH11/TM03 MAG TAPE,1 + +IFN TM10P,[ +$INSRT TM10 +] +IFN TM03S,[ +$INSRT TM03S +] +$INSRT T20MAC + +MSCBL==8 ;Command buffer length +MGQDLL==10. ;PI level PDL length +IF2 IFN MNUMB-140600, .ERR IMPLICIT DEPENDENCY ON MNUMB +MSEOFP==210100 ;High bit of MNUMB in MEMBLT is EOF flag +MSCHN==140500 ;Other 5 bits of MNUMB is drive number + +MTXP==410300,, ;BP to set/get transport number from IOCHNM +MUNITF==170300 ;BP to set/get unit field in MTC CONI + +IFN TM10P,[ +;Tape controller commands +MNOPIN==10000 ;NOP and interrupt when idle +MWRITE==4000 ;Write data +MW3IN==14000 ;Write data and long EOR gap +MSPRR==7000 ;Space in reverse direction +MREAD==2000 ;Read data +MSPFR==6000 ;Space in forward direction +MSPFF==16000 ;Space forward to EOF +MSPRF==17000 ;Space reverse to EOF +MREWND==1000 ;Rewind +MRWNDD==11000 ;Rewind and unload +MWEOF==5000 ;Write EOF mark +] + +MGNRTY==10. ;Number of retries on read + +;Modes in OPEN call +; +%MMOUT==1,,0 ;Open for output, 0=>input +%MMBLK==2,,0 ;Block mode, 0=>unit mode +%MMIMG==4,,0 ;Image mode, 0=>Ascii +%MMCNK==10,,0 ;"Chunk" mode, 0=>stream mode +%MMNSE==20,,0 ;No skip to EOF on close, 0=>do skip +%MMEP==40,,0 ;Even parity, 0=>odd +%MMDEN==300,,0 ;Density select + ; 00=> "Default" - 1600 for KS/TU77 + ; 01=> 800 BPI + ; 10=> 1600 BPI + ; 11=> 6250 BPI +%MM32B==400,,0 ;"IBM" mode, write 8-bit bytes from LH 32 bits + ; 0=> core dump +%MMRSZ==7000,,0 ;Record Size + ; Ranging binarily from 0=>1024. to 7=>8. bytes + + +EBLK + +SUBTTL MAG TAPE STORAGE AREA + +MGVTC: 0 ;Scratch word for virgin tape check +MGJDTI: 0 ;"Wait for job done" time out value +MGNWRD: 0 ;Number of words read in a PI level read +MGTBZY: -1 ;Flag to get interrupt started +MGSFTI: 0 ;Software interrupt in progress +MGUNIT: -1 ;Unit expecting interrupt +MGWCW: 0 ;"Wait for control word written" flag +LMIOWD: 0 ;Last MIOWD + +MSRAC: BLOCK NMTCS ;Transport software status flags + %MA==1,,525252 + %MAEOF==400000 ;4.9 EOF seen on read - must be 4.9 + %MAETR==200000 ;4.8 EOT on internal read + %MAETW==100000 ;4.7 EOT on write + %MAERR==040000 ;4.6 PI level got an error + %MARCE==020000 ;4.5 Read compare error + %MACTH==014000 ;4.4 Core allocator says stop + ;4.3 " (WHY 2 BITS?) + %MASTP==002000 ;4.2 Stop read ahead + %MANWT==001000 ;4.1 Nothing written on tape yet + %MAEFA==000400 ;3.9 EOF seen on read-ahead, user hasn't seen + %MAESO==000200 ;3.8 EOF read since open + %MAMSO==000100 ;3.7 Tape moved since first open + %MAREW==000040 ;3.6 "Tape is rewinding" flag + %MARAC==000020 ;3.5 Read active flag + %MAMOL==000010 ;3.4 Transport on line + %MAWSW==000004 ;3.3 Wants software (timing) interrupts +MGERRC: BLOCK NMTCS ;Error count +MTCEFW: BLOCK NMTCS ;Number of EOF's written at close +MGEOFR: BLOCK NMTCS ;Number of EOF's since last read +MTPSAV: BLOCK NMTCS ;Storage to restore P on EOF +MSCMDC: REPEAT NMTCS,0 ;Number of commands in command list +MGSPCD: BLOCK NMTCS ;Spacing operation command +MGSCNT: BLOCK NMTCS ;Spacing operation count +MGEOTT: BLOCK NMTCS ;Timeout for detecting virgin tape +MSBUFP: REPEAT NMTCS,0 ;Mag tape MP<->PI buffer queue in,,out +MSNBOL: BLOCK NMTCS ;Number of buffers on list +MSCRW: BLOCK NMTCS ;R/W flag, -1=>output 0=>input +MSMPRC: BLOCK NMTCS ;Words left in buffer +MSMPRP: BLOCK NMTCS ;Next word in buffer +MTMDN: REPEAT NMTCS,-1 ;Block active at MP +MGCABN: REPEAT NMTCS,-1 ;Buffer active at PI level +MTUSE: REPEAT NMTCS,-1 ;Number of channels open on this transport +MTUSR: REPEAT NMTCS,-1 ;User index of transport user +MTBLKS: BLOCK NMTCS ;If write, buffer size + ;If read, size of last record read +MTMFNC: BLOCK NMTCS ;.MTAPE function storage +MTMCNT: BLOCK NMTCS ;.MTAPE count +MTMTAP: BLOCK NMTCS ;MTAPE call word + +MGCMTS: BLOCK NMTCS ;PI level status info (CONI MTS or similar) +MGCMTC: BLOCK NMTCS ;PI level controller info (CONI MTC or similar) + + IFN TM10P,[ +MTCONO: REPEAT NMTCS,\.RPCNT_17+20 ;Prototype CONO word for each transport + ] + IFN TM03S,[ +MTSELW: BLOCK NMTCS ;Select word (TC reg val) for each transport + MTSELM==3777 ;density/format/parity/unit bits mask +MTWTFC: BLOCK NMTCS ;-10 word count to tape frame conversion factor + ] + +;Build table of QDL (PI level stack) pointers +MGQDLP: REPEAT NMTCS,-MGQDLL,,CONC MGQD,\.RPCNT,-1 + +;Built storage for command lists and PI level stacks +REPEAT NMTCS,[ + CONC MSCB,\.RPCNT,: + BLOCK MSCBL ;Space for command list + MGRCV ;Fake "command", causes list to wrap around + + MGNCMD ;Function on botton of Q PDL, gets new command + CONC MGQD,\.RPCNT,: + BLOCK MGQDLL ;Space for PI level stack + + IFE .RPCNT,MSLCTB==.-MSCB0 ;Length of each table +] + +;Build table of pointers for adding commands to command list +MTCMBP: REPEAT NMTCS,-MSCBL-1,,CONC MSCB,\.RPCNT,-1 + +;Build table of bytepointers for removing commands from command list +MGCMBP: REPEAT NMTCS,4400,,CONC MSCB,\.RPCNT,-1 + +;It is depressing to discover that the DUMP program sucks these directly +; out of the running ITS. If you change what's in here fix DUMP too. + +MGEMTC: 0 ;CONI MTC, at last error +MGEMTS: 0 ;CONI MTS, at last error + +IFE TM10B,[ +MIOWD: BLOCK 2 ;Channel program +] +IFN TM10A,[ +MGDBRK: 0 + CONO MTS,1 + JRST 12,@MGDBRK +];TM10A + +BBLK + + +;Random Macros + +;Enqueue and Dequeue buffers from the lists used to pass buffers between +; main program and PI level. Assumes W has a valid transport number... + +DEFINE MTENQB REG,TEMP=TT + SKIPG MSNBOL(W) ;;Any buffers on list already? + IFSKP. + HLRZ TEMP,MSBUFP(W) ;;Yes, get old tail pointer + DPB REG,[MLO,,MEMBLT(TEMP)] ;;Add new one onto end of list + ELSE. + HRRM REG,MSBUFP(W) ;;No, make new buffer head of list + ENDIF. + HRLM REG,MSBUFP(W) ;;New buffer is tail in any event + SETZM TEMP + DPB TEMP,[MLO,,MEMBLT(REG)] ;;Indicate end of list + AOS MSNBOL(W) ;;Increment count of buffers on list +TERMIN + +DEFINE MTDEQB REG,TEMP=TT + HRRZ REG,MSBUFP(W) ;;Get head of buffer list + HLRZ TEMP,MSBUFP(W) ;;Get tail + CAMN REG,TEMP ;;Tail == head? + IFSKP. + LDB TEMP,[MLO,,MEMBLT(REG)] ;;No, get next buffer on list + HRRM TEMP,MSBUFP(W) ;;Make it the new head of list + ELSE. + SETZM MSBUFP(W) ;;Only one buffer, list is now empty + ENDIF. + SOS MSNBOL(W) ;;Decrement count of buffers on list +TERMIN + +IFN TM03S,[ +;Macros for testing various status bits as set up by MGGXPT and friends +IRP OP,,[NN,NE,NA,O,OE,ON,OA,Z,ZE,ZN,ZA,C,CE,CN,CA] + DEFINE TT!OP REG,#MSK + ...TSF==0 + IFSE REG,CS1,[ + TL!OP I,MSK + ...TSF==-1 + ] + IFSE REG,CS2,[ + TR!OP I,MSK + ...TSF==-1 + ] + IFSE REG,FS,[ + TL!OP J,MSK + ...TSF==-1 + ] + IFSE REG,ERR,[ + TR!OP J,MSK + ...TSF==-1 + ] + IFE ...TSF,.ERR Invalid register name REG given in TTxxx macro + TERMIN +TERMIN +];IFN TM03S + SUBTTL MAG TAPE OPEN ROUTINE + +; C/ MODE,,DEV +; D/ MODE (ROT 1) 4.9=1=>OUTPUT +; I/ DEVICE NUMBER +; R/ IOCHNM WORD POINTER + +MAGTO: SKIPL W,I ;Get device + CAIL W,NMTCS ;Too big? + JRST OPNL1 ;No such device + MOVSI T,%MAREW + TDNE T,MSRAC(W) ;Rewinding? + PUSHJ P,UFLS ;Yes, wait for completion + CONO PI,CLKOFF ;Don't want transport status changed under me + SKIPL MTUSE(W) ;See if we are the first opener + IFSKP. ;First opener. Initialize database for device + SETZM MSBUFP(W) ;Indicate no buffers on chain + SETZM MSNBOL(W) ;Another way of saying above + SETZM MSMPRC(W) ;Buffer words remaining + SETZM MSMPRP(W) ;Pointer to buffers + SETOM MTMDN(W) ;No buffer at MP level + SETOM MGCABN(W) ;No buffer owned by PI code + SETZM MSRAC(W) ;Initialize transport software status word + MOVEI A,2 + MOVEM A,MTCEFW(W) ;Number of EOF's written + MOVSI A,%MANWT + IORM A,MSRAC(W) ;Indicate nothing written on tape + ELSE. ;Not first opener. Check legality of this open + CAME U,MTUSR(W) ;Same user as previous open? + JRST OPNL10 ;Different user, report error + MOVE B,D ;Check direction of open + EQV B,MSCRW(W) ;Same as previous direction? + SKIPL B ;Yes, OK + JRST OPNL2 ;No, wrong direction + ENDIF. + MOVEM U,MTUSR(W) ;Store user + SETZM MSCRW(W) ;Indicate read until found to be otherwise + TLNE C,1 ;Read or write? + SETOM MSCRW(W) ;Indicate write + AOS MTUSE(W) ;Indicate 1 more user + PUSHJ P,SOSSET + MTUSE(W) ;SOS if PCLSR'd + CONO PI,CLKON ;Let um (em?) get me (who's em?) + PUSHJ P,MTSTAT ;Get transport status in standard form + MOVE A,MSRAC(W) + TLNE A,%MAERR ;PI error means device not there + JRST MTODNP ;Go report error +IFN TM03S,[ + TTNN FS,%TMSFP ;Formatter present? + JRST MTODNP ;No, can't win + TTNN FS,%TMSOL ;Slave on line? + JRST MTODOL ;No, lose +] +IFN TM10P,[ + TXNN J,%T1STH ;Transport hung, by chance? + JRST MTOW1 ;No, proceed + TXNN J,%T1SRW ;OK if rewinding + JRST OPNL7 ;Device not working +] +MTOW1: SKIPN MSCRW(W) ;Writing? + JRST MTOW2 ;No... +IFN TM10P,TXNE J,%T1SWL ;Yes. Write locked? +IFN TM03S,TTNE FS,%TMSWL + JRST OPNL26 ;Yes, device writelocked error +IFN TM10P, TXNN J,%T1SET ;At EOT? +IFN TM03S, TTNN FS,%TMSET + JRST MTOW2 ;No + MOVSI A,%MAETW+%MAERR ;If write and EOT, make .IOT give IOC error, + ; but let open win + IORM A,MSRAC(W) + +MTOW2: TXNE C,%MMDEN ;Density specified explicitly? + JRST MTOW3 ;Yes, go check for validity +IFN TM10P,MOVEI A,1 ;No, pick one. Use 800 for TM10 +IFN TM03S,MOVEI A,2 ;Use 1600 for TM03 + DPB A,[.BP %MMDEN,C] ;Set value + JRST MTOW4 ;Done and assumed correct + +MTOW3: LDB A,[.BP %MMDEN,C] ;Get density from open +IFN TM10P,[ + CAIE A,1 ;800 is the only currently OK speed for TM10 + JRST OPNL12 + IFN 0,[ +;You need something like this if you arrange to allow non-800 TM10 speeds + TXNN C,%MM32B ;32-bit compatible mode requested? + JRST MTOW4 ;No, core dump + CAIN A,1 ;Density specified as 800? + JRST MTOW4 ;Yes, we can do that + JRST OPNL12 ;32-bit and not 800BPI, controller can't do it + ] +];IFN TM10P +IFN TM03S,[ + CAIN A,3 ;Specified 6250? + JRST OPNL12 ;Yep, loser. Else OK +] + +;Here on successful open. +; Set up CONO or select word, IOCHNM word, blocksize +; +MTOW4: PUSHJ P,LSWDEL ;Release MTUSE switch +IFN TM10P,[ + MOVEI A,MTCCHN_3 ;Start building CONO word. Set control PI level +IFN TM10A,TRO A,1 ;Add in data PI level for non-DF10 controller + LDB B,[.BP %MMDEN,C] ;Get density from open + CAIE B,1 ;800 BPI + BUG INFO,[ILLEGAL TM10 TAPE SPEED SETTING, USING 800BPI] + MOVEI B,%T1D80 ; Yep. + DPB B,[.BP %T1CDS,A] ;Set density field of CONO word + TXNN C,%MM32B ;32-bit mode specified? + TXO A,%T1CCD ;No, set core dump mode in CONO + TXNN C,%MMEP ;User wants even parity? + TXO A,%T1COP ;No, set odd parity + DPB W,[.BP %T1CNU,A] ;Set unit number field of CONO + MOVEM A,MTCONO(W) ;Save assembled CONO word +];IFN TM10P +IFN TM03S,[ + MOVE A,W ;Get unit number being initialized + TXNN C,%MM32B ;User asked for industry compatible? + IFSKP. ;Yes... + MOVEI B,4 ;Set word-to-frame conversion factor + MOVEM B,MTWTFC(W) + MOVEI B,%TMFIC ;Set mode in budding select word + ELSE. ;Core dump... + MOVEI B,5 ; takes 5 tape frames per word + MOVEM B,MTWTFC + MOVEI B,%TMFCD ;Set CD format in select word + ENDIF. + DPB B,[.BP %TMTFS,A] ;Set format in select word + TXNE C,%MMEP ;User wants even parity? + TXO A,%TMTEP ;Yes, set even parity flag + LDB B,[.BP %MMDEN,C] ;Get density from open + CAIE B,1 ;800 BPI specified? + SKIPA B,[%TMD16] ;Anything else, use 16 + MOVEI B,%TMD08 ;800, use that + DPB B,[.BP %TMTDS,A] ;Set density in select word + MOVEM A,MTSELW(W) ;Set select word for this unit +];IFN TM03S + LDB B,[.BP %MMRSZ,C] ;Get record size from open call + TRC B,7 ;Convert to power of two + MOVEI A,10 ;Minimum record size is 10 (8.) words + LSH A,(B) ;Blocksize = minimum * 2^power + MOVEM A,MTBLKS(W) ;Save blocksize in words + LDB A,[.BP <%MMBLK\%MMIMG>,C] + ;Use unit/block and ascii/image bits as index + HLR C,MTOPTB(A) ;Get input dispatch routine from table + TLNE D,400000 ;Remember D? Skip if user opened in input mode + HRR C,MTOPTB(A) ;OK, get output dispatch routine instead + MOVEM C,(R) ;Save routine in IOCHNM word + DPB W,[MTXP(R)] ;Set transport number in IOCHNM word + JRST POPJ1 ;Skip return means success + +;Here if device is not present +MTODNP: SETZM MSRAC(W) ;Too bad. Clear status word and report error + JRST OPNL1 + +;Here if device off line +MTODOL: SETZM MSRAC(W) + JRST OPNL7 + +;Table of I/O routines +; +MTOPTB: MTUAIX,,MTUAOX ;Unit Ascii + MTBIX,,MTBOX ;Block Ascii + MTUIIX,,MTUIOX ;Unit Image + MTBIX,,MTBOX ;Block Image + + + +SUBTTL MAG TAPE CLOSE ROUTINES + +;MTOCL - CLOSE TAPE OPEN FOR OUTPUT + +MTOCL: LDB W,[MTXP(R)] ;Set up transport number + SOSL MTUSE(W) ;Decrement transport use counter + POPJ P, ;Not only channel open, all done + AOS MTUSE(W) ;Consistant state in case PCLSR'd + MOVSI A,%MAERR + TDNE A,MSRAC(W) ;See if error has occurred + PUSHJ P,MTOCL3 ;Yes, clean up a few things + + SKIPL MTMDN(W) ;Is there a partially processed buffer? + PUSHJ P,MTWBFD ;Yes, write it to tape + + MOVEI B,MGMEOT ;Queue a "Write EOT" command to PI level + PUSHJ P,MTCMD + SKIPLE MSCMDC(W) + PUSHJ P,UFLS ;Wait till done. + MOVEI A,1 + MOVEM A,MGEOFR(W) + SKIPGE MTMDN(W) ;Active buffer at MP level? + IFSKP. + MOVE A,MTMDN(W) + BUG PAUSE,[MT: MP BUF REMAINS AT CLOSE],OCT,A + PUSHJ P,MEMR + ENDIF. + SKIPGE MGCABN(W) ;Active buffer at PI level? + IFSKP. + MOVE A,MGCABN(W) + BUG PAUSE,[MT: PI BUF REMAINS AT CLOSE],OCT,A + PUSHJ P,MEMR + ENDIF. + SKIPN MSNBOL(W) ;Any buffers on buffer queue? + IFSKP. + BUG PAUSE,[MT:],DEC,MSNBOL(W),[BFRS QUEUED AT CLOSE] + PUSHJ P,MTCBFF + ENDIF. + SETOM MTUSE(W) ;Nobody is using this transport + SETOM MTUSR(W) ;No user associated with this transport + SETZM MSRAC(W) ;reset transport software status word + POPJ P, + +MTOCL3: SKIPL A,MTMDN(W) ;Have a buffer active at MP level? + PUSHJ P,MEMR ;Flush it if so + SETOM MTMDN(W) + SETZM MSMPRC(W) ;Say no words left in current buffer + POPJ P, + +;Close routine for MT open for input + +MTICL: LDB W,[MTXP(R)] ;Set up channel data pointer + SOSL MTUSE(W) ;Last user? + POPJ P, ;No, nothing to do + AOS MTUSE(W) ;Yes, save state for possible PCLSR + MOVEI T,1 ;This crock is because we want to allow + CAMGE T,MSCMDC(W) ; one outstanding command if rewinding + PUSHJ P,UFLS ;Wait till one or less outstanding command + MOVE T,MSRAC(W) ;Get transport software status + TLNE T,%MAREW ;Is it rewinding? + IFSKP. + SKIPLE MSCMDC(W) ;No, wait till no outstanding commands + PUSHJ P,UFLS + ENDIF. + SKIPGE MGCABN(W) ;Any PI-level buffers left? + IFSKP. + MOVE A,MGCABN(W) + BUG PAUSE,[MT: PI INPUT BUF LEFT AT CLOSE],OCT,A + PUSHJ P, MEMR + ENDIF. + PUSHJ P,MTRBD ;Release any MP-level buffers + SETOM MTUSR(W) ;Reset user identifier + PUSHJ P,MTCBFF ;Free some buffers ?whose+++ + SOS MTUSE(W) ;Decrement use count + MOVE T,MSRAC(W) ;Get transport software status again + TLNE T,%MAREW ;Are we rewinding? + JRST MTICL2 ;Yes, don't have to skip to EOF + MOVSI A,(%MMNSE) + TDNE A,(R) ;Check if user wants skip to EOF + JRST MTICL2 ;No, forget it + MOVSI A,%MAMSO + TDNN A,MSRAC(W) ;Has tape moved at all since open? + JRST MTICL2 ;No... + SKIPE MGEOFR(W) ; + JRST MTICL2 ;Note that this disposes of a read-ahead EOF. + PUSHJ P,MTSTAT +IFN TM10P,[ + MOVE B,MGCMTS(W) + TXNE B,%T1SBT ;BOT? + JRST MTICL2 +] +IFN TM03S,[ + TTNN FS,%TMSOL ;Still online? + JRST MTICL2 ;No, can't very well skip to EOF + TTNE FS,%TMSBT + JRST MTICL2 +] + MOVEI B,MGSPFF ;Space forward to end of file + PUSHJ P,MTCMD + SKIPLE MSCMDC(W) ;Wait till command done + PUSHJ P,UFLS + +MTICL2: MOVSI T,%MAREW + ANDM T,MSRAC(W) ;Clear all software status except rewinding + POPJ P, ;Done + +;Free a chain of IO buffers pointed to by MSBUFP(W) +; Count of buffers is in MSNBOL(W) +; +MTCBFF: SKIPN MSNBOL(W) ;Any buffers on chain? + POPJ P, ;No, fine + DO. + HRRZ A,MSBUFP(W) ;Yes, get pointer + LDB T,[MLO,,MEMBLT(A)] ;Get pointer to next buffer + HRRM T,MSBUFP(W) ;Write that in chain header + PUSHJ P,MEMR ;Return buffer to IO pool + SOSLE MSNBOL(W) ;Any more to do? + JRST TOP. ;Yes, loop back for more + ENDDO. + SETZM MSBUFP(W) ;Zero buffer list pointer + POPJ P, + + + +SUBTTL MAG TAPE INPUT .IOT ROUTINES + + SKIPA B,[SIOKT] +MTUAI: MOVEI B,CHRKTI ;Unit ASCII input + MOVE E,[440700,,5] + JRST MTREAD + + SKIPA B,[SIOKT] +MTUII: MOVEI B,CHRKTI ;Unit image input + MOVE E,[444400,,1] + JRST MTREAD + +MTBI: MOVE E,[444400,,1] ;Block input + MOVEI B,BLKT + +MTREAD: LDB W,[MTXP(R)] ;W <= Transport number + PUSHJ P,MTIECK ;Check for tape errors first + MOVEM P,MTPSAV(W) ;Save P for EOF return + JSP B,(B) ;IO Routine. BLKT,CHRKT,SIOKT + MSMPRP(W) ;Pointer to next word + MSMPRC(W) ;Count of words remaining + SETZ MTRBG ;Get new buffer (SETZ for CHRKT return on EOF) + MTRBD ;Discard buffer + JRST 4,. ;Unused + PUSHJ P,MTRBFW ;Code to wait for new buffer from PI level + +;Get a new buffer for I/O code. +; This routine assumes that there is a buffer ready to get +; (i.e. MTRBFW was called) +; +MTRBG: SKIPG MSNBOL(W) ;Any buffers on list? + JRST MTRBG3 ;No, must be error or EOF + CONO PI,UTCOFF ;Stop I/O for a bit + MTDEQB TT,A ;Dequeue buffer into TT using A as temp + MOVEM TT,MTMDN(W) ;Remember buffer active at MP level + CONO PI,UTCON ;Turn I/O back on + LDB J,[MWC,,MEMBLT(TT)] ;Get word count from buffer + MOVEM J,MTBLKS(W) ;Save for .MTAPE 13 + LSH TT,10. ;Convert buffer number into address + JRST SIOBGX ;TT/address, J/word count /E unchanged + +;Here if no buffer ready, error or EOF assumed +; +MTRBG3: SKIPL MSRAC(W) .SEE %MAEOF ;EOF flag set in transport status? + IFSKP. + MOVSI T,%MAEFA ;The EOF is now no longer read-ahead + ANDCAM T,MSRAC(W) ;So remember that fact + JRST POPJ2 ;Double skip to tell I/O code about EOF + ENDIF. + PUSHJ P,MTIECK ;Not EOF. Check for error conditions + BUG HALT,[TAPE READ BUFFER VANISHED] ;No error, shoulda been a buffer + +;MAG TAPE READ BUFFER DISCARD ROUTINE +MTRBD: SKIPGE A,MTMDN(W) ;Have an active MP buffer? + JRST MOVTWJ ;Set up T for buffer wait, return + CONO PI,UTCOFF ;Stop IO for a bit + SETOM MTMDN(W) ;No active MP buffer + SETZM MSMPRC(W) ;No data in nonexistant buffer + LDB TT,[MSEOFP,,MEMBLT(A)] ;Get EOF flag from PI level + PUSHJ P,MGMEMR ;Return buffer, enable UTC + JUMPN TT, [ MOVSI A,%MAEOF ;EOF seen? + IORM A,MSRAC(W) ;Record EOF in software status + JRST .+1 ] +MOVTWJ: MOVE T,W ;T gets transport number for bfr wait UFLS + POPJ P, ;Also MTRBG, MTRBFW rely on this setting T + + +;MAG TAPE READ WAIT FOR DATA ROUTINE +; Called under a UFLS by system IO code to wait for data to arrive. +; Note T, not W, has transport number. T must be set up by some +; previous routine +; +MTRBFW: MOVE TT,MSRAC(T) ;Get software status of transport + TLNN TT,%MAEOF\%MAERR ;PI code reports EOF or error? + SKIPLE MSNBOL(T) ;Or are any buffers available for reading? + JRST POPJ1 ;SOme interesting condition, unhang + TLNE TT,%MARAC ;Have we asked for a tape read yet? + POPJ P, ;Yes, nothing to do but wait, wait, wait + PUSH P,W ;This being done under a UFLS. only T good + PUSH P,B + MOVE W,T ;Set up transport number in usual place + MOVEI B,MGREAD ;What we want the PI level to do + MOVEI T,MSCBL ;Make sure that there is room in command list + CAMG T,MSCMDC(W) ;If there is room, + IFSKP. ; we will request a read operation + MOVSI TT,%MARAC + IORM TT,MSRAC(W) ;Read is active now, or will be shortly + PUSHJ P,MTCMD1 ;Queue up command request for PI level + ENDIF. ;If no room for command, all we can do is wait + MOVE T,W ;Fix up T for UFLS + POP P,B ;Clean up everything else + POP P,W + POPJ P, + +SUBTTL MAG TAPE OUTPUT .IOT ROUTINES + + SKIPA B,[SIOKT] +MTUAO: MOVEI B,CHRKT ;Unit ASCII output + MOVE E,[440700,,5] + JRST MTWRIT + + SKIPA B,[SIOKT] +MTUIO: MOVEI B,CHRKT ;Unit image output + MOVE E,[444400,,1] + JRST MTWRIT + +MTBO: MOVE E,[444400,,1] ;Block output + MOVEI B,BLKT + +MTWRIT: LDB W,[MTXP(R)] ;Get transport number + PUSHJ P,MTIECK ;Check for tape errors first + HRLZI A,%MAETW + TDNE A,MSRAC(W) ;PI code think it hit EOT? + JRST IOCER9 ;Yep, go lose + JSP B,(B) + SETZ MSMPRP(W) ;Pointer to next word + MSMPRC(W) ;Count + SETZ MTWBFG ;Get new buffer + MTWBFD ;Write out buffer to tape + JRST 4,. + TRNA ;No wait for buffer routine needed + +;MAG TAPE WRITE - BUFFER GET ROUTINE + +MTWBFG: PUSHJ P,MTIECK ;Check for tape errors + PUSHJ P,TCALL ;Turn off UTC + JRST IOMQ ;Try to get buffer + POPJ P, ;Return noskip if no buffers available + MOVEM A,MTMDN(W) ;Store active buffer number + MOVEI T,MUMGB + DPB T,[MUR,,MEMBLT(A)] ;Tell world that it is a mag tape buffer + DPB W,[MSCHN,,MEMBLT(A)] ;Store channel number in buffer header + SETZM TT + DPB A,[121000,,TT] ;Convert block number in A to address in TT + MOVE J,MTBLKS(W) ;Get block size of write + JRST SIOBGX + +;MAG TAPE WRITE - BUFFER FINISHED ROUTINE +; General IO code has filled a buffer or otherwise finished with it. +; Queue the buffer for writing if there is anything in it. + +MTWBFD: PUSHJ P,MTIECK ;Check for tape errors + SKIPGE A,MTMDN(W) ;Have an active buffer? + POPJ P, ;No, nothing to do + MOVEI T,MSCBL ;See if there is any room in command list + CAMG T,MSCMDC(W) + PUSHJ P,UFLS ;Wait for room in command list + MOVE T,MTBLKS(W) ;Get blocksize we are writing + SUB T,MSMPRC(W) ;Subtract number of words remaining in buffer + CONO PI,UTCOFF ;Lock up while frobbing buffer lists + SETOM MTMDN(W) ;Clear active buffer + SETZM MSMPRC(W) ;Clear free word in buffer count + JUMPE T,MEMR ;Nothing in buffer, just return block + DPB T,[MWC,,MEMBLT(A)] ;Store word count + MTENQB A ;Queue buffer on to-PI list + CONO PI,UTCON ;Finished mucking with buffer list + PUSH P,B + MOVEI B,MGWRIT ;Issue a write request to PI level + PUSHJ P,MTCMD + MOVSI B,%MANWT + ANDCAM B,MSRAC(W) ;Note that we have written something to tape + SETZM MTCEFW(W) ;Note no EOF's written at end of tape + JRST POPBJ ;Restore B and return + +SUBTTL MTCMD - GIVE COMMAND TO PI LEVEL + +;PUSHJ P,MTCMD + ;RH(W) has transport number + ;RH(B) has address of PI level routine to execute + +MTCMD: MOVEI T,MSCBL ;Pending command list length + CAMG T,MSCMDC(W) ;Count of commands currently in list + PUSHJ P,UFLS ;Wait for room in pending command list + CONO PI,UTCOFF ;Grab machine, keep count accurate +MTCMD1: MOVE T,MTCMBP(W) ;Get pointer to next slot in command list + AOBJN T,MTCMD2 ;Increment slot and check for wraparound + SUB T,[MSCBL,,MSCBL] ;Reached end of list, ring it +MTCMD2: MOVEM B,(T) ;Store new command + MOVEM T,MTCMBP(W) ;Store new pointer + AOS MSCMDC(W) ;Indicate one more command in list + JRST MSTRTR ;Go start up PI routine + +SUBTTL MTIECK - CHECK FOR IOC ERROR + +;PUSHJ P,MTIECK + ;Returns +1 if no error + ;Gives IOC error to user if error - never returns. + +MTIECK: PUSH P,A + MOVE A,MSRAC(W) ;Get transport software status + TLNN A,%MAERR ;PI level report an error? + JRST POPAJ ;No, all is OK + SKIPLE MSCMDC(W) ;Wait for PI level to finish cleaning up + PUSHJ P,UFLS ; before throwing away buffers + SKIPL A,MTMDN(W) ;Have an active MP-level buffer? + PUSHJ P,MEMR ;Yes, throw it away + SETOM MTMDN(W) ;No active MP buffer + SETZM MSMPRP(W) ;No place to get/put next character + SETZM MSMPRC(W) ;No room to do it anyway + PUSHJ P,MTCBFF ;Free any buffers waiting for MP processing + POP P,A + MOVE T,MGCMTS(W) ;Get transport status data from PI level +IFN TM10P,[ + TRNE T,%T1STH\%T1SIO ;Transport hung or illegal operation? + JRST IOCER1 ;Yes, report device error + TRNE T,%T1SPE\%T1SRC\%T1SRL\%T1SDL\%T1SBT ;Gruesome errors + JRST IOCER3 ;Report irrecoverable data error + TRNE T,%T1SET ;(Real) End of Tape? + JRST IOCER9 ;Device Full error +];IFN TM10P +IFN TM03S,[ + MOVE I,MGCMTC(W) ;Get controller transport status from PI level + MOVE J,MGCMTS(W) + TTNE CS1,%TM1MP ;Control bus parity error? + JRST IOCER1 + TTNN CS1,%TM1TE ;Transfer error? Could be TM03 or RH11 + IFSKP. + TTNE CS2,%TM2DL\%TM2UP\%TM2NF\%TM2NM\%TM2PE\%TM2MT\%TM2MP + JRST IOCER1 ;Non-data errors + TTNN FS,%TMSES ;Formatter error? + IFSKP. + TTNE ERR,%TMEUS\%TMECT\%TMENX\%TMEMD\%TMEFS\%TMEMC\%TMERM\%TMEIR\%TMEIF + JRST IOCER1 ;Fatal formatter errors + TTNE ERR,%TMECE\%TMECS\%TMEFC\%TMENG\%TMEFL\%TMEIC + JRST IOCER3 ;Non-recoverable data errors + ENDIF. + ENDIF. + TTNE FS,%TMSET ;End of tape? + JRST IOCER9 +];IFN TM03S + MOVE A,MGEOFR(W) ;Check for logical EOT + CAIL A,2 ;Read two EOF's since last record? + JRST IOCER9 ;Yes, report EOT + JRST IOCER3 ;No, give irrecoverable data error for now + +SUBTTL MAG TAPE .STATUS ROUTINE +;Building a status word in D. +;Routine sets: +; 1.7-1.9 open modes +; 2.3 BOT +; 2.4 EOT +; 2.5 9 track (0 = 7 track) +; 2.6 IBM mode (0 = coredump) +; 2.7 Transport idle (no pending command) +; 2.8 EOF (last thing seen was a tape mark) +; +STAMTC: +;Open modes + LDB W,[MTXP(R)] ;Get transport number + DPB A,[60300,,D] ;Open mode + PUSHJ P,MTSTAT ;Get tape status from transport +;EOT? + LDB A,[.BP %MAETW_22,MSRAC(W)] ;EOT on write + LDB B,[.BP %MAETR_22,MSRAC(W)] ;EOT on read + IOR A,B + DPB B,[140100,,D] ;Tape at EOT? +IFN TM10P,[ +;7 or 9 track drive? + LDB A,[20100,,J] ;Get 7/9 track bit + TRC A,1 + DPB A,[150100,,D] ;7 or 9 track drive + .ERR Missing TM10 .STATUS code at STAMTC +] +IFN TM03S,[ +;A bunch of new stuff. BOT? + SETZ A, + TTNE FS,%TMSBT ;Transport is at BOT? + SETO A, + DPB A,[130100,,D] ;BOT. +;7 or 9 track drive? + SETOM A ;TM03 is always 9-track + DPB A,[150100,,D] ;7 or 9 track drive +;Core dump or 32 bit mode? + MOVE A,MTWTFC(W) ;Get word to frame conversion. 4 or 5 + TRC A,1 ;Flip last bit. Last bit now on iff 32bit mode + DPB A,[160100,,D] ;Sorry. +;Formatter busy? + SETO A, + SKIPLE MSCMDC(W) ;Idle if no pending commands + SETZ A, + DPB A,[170100,,D] +;EOF last thing seen? + SETZ A, + TTNE FS,%TMSTM ;Last thing seen was a tape mark? + SETO A, + DPB A,[200100,,D] ;EOF. +];IFN TM03S + POPJ P, + +;RCHST ROUTINE FOR MAG TAPE + +RCHMGT: HLRZ E,(R) ;Get open mode from IOCHNM word + LDB J,[MTXP(R)] ;Get the mag tape drive number + MOVSI J,'MT0(J) ;Return that drive's device name + TRZ E,(.BM MTXP) ;Clear drive # field in OPEN modes + JRST POPJ1 ;Skip so that J overrides built-in device name + + +SUBTTL MAG TAPE PI LEVEL + +;Request magtape interrupt from MP-level software +; Must be called with I/O interrupts off (CONO PI,UTCOFF) +; This is called every 1/2 second by the ITS slow clock routine +; +MSTRTR: SETZM MGTBZY ;No busy tapes, flag software interrupt + CONO PI,MTCRQ ;Request interrupt on magtape channel + CONO PI,UTCON ;Reenable IO interrupt system + POPJ P, ;That is all + +;Handle tape interrupt requested by software or other nonspecific cause +; Get here via non-vectored MTCCHN interrupt on the KS +; +MGSBRK: AOS MGTBZY ;Note interrupt level is busy + SETOM MGSFTI ;Note software interrupt in progress + MOVEI B,NMTCS-1 ;Loop over all transports + SKIPG MSCMDC(B) ;Any commands in command list? +MGSBK1: SOJGE B,.-1 ;No, try next transport + SKIPGE B ;Found command or finished scan. Which? + JRST MGSBK2 ;Finished scanning. Go check other things + MOVE W,B ;Have a command. Set up transport number + PUSH P,B ;Save B over call to command routine + MOVSI B,%MACTH + TDNN B,MSRAC(W) ;Core allocator saying go away? + PUSHJ P,MGXGO ;No, go start requested routine + POP P,B ;Restore transport count + JRST MGSBK1 ;Loop back for another transport + +MGSBK2: SETZM MGSFTI ;Clear software interrupt flag + JRST MGEX ;That's all for now +;This probably should check for lost IE bits on TM03 + +;Handle interrupt caused by specific hardware conditions +; Get here via vectored interrupt on the KS +; + +IFN TM10P,[ +; A - result of CONI MTC, +; C - result of CONI MTS, +; +MGHBRK: SKIPGE W,MGUNIT ;Get unit we are expecting interrupt on + JRST MGUBRK ;None? Probably MP level bailed out. Punt. + LDB B,[MUNITF,,A] ;Get unit that controller is squacking about + CAME W,B ;Same unit? + BUG HALT,[MT PI CODE LOST TRANSPORT] + MOVE J,C + PUSH P,[MGEX] ;Cause POPJ P, in handler to dismiss interrupt +IFN TM10B,[ + TXNE C,%T1SCP\%T1SNM\%T1SDP ;Check for DF10 errors + JRST MGERR ;Yes, go to error routine +];TM10B + TXNE C,%T1SIO ;Illegal operation error? + JRST MGERR ;Yes, go to error routine + JRST MGXGO ;No, go handle interrupt + +;Here to unbreak on unexpected hardware interrupt +; +MGUBRK: LDB W,[MUNITF,,A] ;Who's the loser, anyway + MOVE B,MTCONO(W) ;Get prototype CONO word for that transport + CONO MTC,(B) ;Select offending unit + CONO MTS,31 ;Clear interrupt, DF10, stop any op in progress + JRST MGEX ;Go dismiss interrupt +];IFN TM10P + +IFN TM03S,[ +;Check for active unit. If none, go directly to inactive slave +;polling code. If active unit,check that controller is talking about +;this unit, then jump to its routine (MGXGO). When that finishes, +;see if controller is still showing attention, and check status +;of other transports if so. +; +;Well, almost. + + EBLK +MGHBRK: 0 + BBLK + JSR UTCSAV ;Save AC,s set up interrupt P PDL + AOS MGTBZY ;Note interrupt level is alive + SKIPGE W,MGUNIT ;Some transport waiting for an interrupt? + JRST MGNOUW ;Nope, either Slave Status Change or lossage + IORDI B,%TMTC ;Get transport the TM03 is thinking about + ANDI B,7 + CAME B,W ;Same as the one we were waiting for? + BUG HALT,[MT PI CODE LOST TRANSPORT] + PUSHJ P,MGXGO ;Go jump into this unit's handler + +MGNOUW: +IFN NMTCS-1,[ +.ERR Missing multi-transport code at MGNOUW! +If more than one unit, have to see if this is an interrupt caused by a +SSC (slave status change), and if so poll all the inactive units and +update their software status (rewinding, on/off line, etc.) With only +one transport we currently avoid this by keeping the unit active +(MGUNIT set) as long as it is doing *anything*, and giving it all the +hardware interrupts. See rewind code, too. +];IFN NMTCS-1 + JRST MGEX ;Go dismiss interrupt +];IFN TM03S + +;Interrupt level control flow +; +; Each transport maintains the current state of its PI-level action +; routines on a seperate (per-transport) PDL with its SP in Q. This +; allows you to save the current state, dismiss the interrupt, and +; resume where you left off when the next interrupt for this transport +; arrives. +; +; Subroutine linkage between routines handling a per-drive PI-level +; action is with PUSHJ Q,xxx and POPJ Q, +; +; The MP level queues commands for the PI level to process on a per- +; transport queue at MGSBx (x=unit number) +; +; Ths general interrupt code transfers to the per-drive actions by +; jumping to MGXGO, which will load Q from the saved state of the +; current drive and start up whatever it finds there. This may be +; the MGNCMD routine, which will start a new command, or it may be +; the middle of an in-progress PI-level command handler. +; +; PI-level action routines can relinquish control in several ways: +; +; PUSHJ Q, CPOPJ will dismiss the current interrupt, arranging for +; control to return to the instruction following the PUSHJ when the +; next interrupt for this unit occurs. +; +; JRST MGOVER will dismiss the current interrupt, arranging for the +; currently executing subroutine to be restarted "from the top" when +; the next interrupt for this unit occurs. +; +; A simple POPJ P, will dismiss the current interrupt, arranging for +; the routine that called this one to be started at the point immediately +; after the call when the next interrupt comes in. This is generally not +; useful except from first-level action routines, where a POPJ P, will +; indicate that you have finished handling the current command and cause +; the next interrupt to fetch and start execution of a new command from the +; queued command list by transferring to MGNCMD. Got that? + +;Transfer control to whatever the per-transport code wants to do. +; +MGXGO: MOVE Q,MGQDLP(W) ;Getsaved Q PDL pointer for current transport + PUSHJ P,QPOPJ ;"Return" to whatever is on top of Q PDL, + ; arranging for POPJ P, to return to here + + MOVEM Q,MGQDLP(W) ;Save current Q PDL for next time + POPJ P, ;Return, dismissing this interrupt + +;Dismiss interrupt, arranging for next interrupt to restart routine +; we are currently executing (rather than either continuing here or +; starting a new command) +; +MGOVER: +IFN TM10P,[ + CONSZ MTS,%T1STH\%T1SIO\%T1SCE ;Tape hung/ill op/DF10 error, + JRST MGERR ; go handle error condition +] + SOS (Q) ;Decrement address at top of Q PDL, now + ; points to PUSHJ Q, instruction so + ; that we will get called again from MGXGO + ; at next interrupt dispatch + POPJ P, ;Return to P PDL caller, dismissing interrupt + + +;This routine is always the last "command" in a transport command list +; Wraps the command list BP around the the beginning of the list, +; then gets and executes the next command. +; +MGRCV: MOVNI A,MSCBL+1 ;Get negative length of command list + ADDM A,MGCMBP(W) ;Wrap command extraction pointer back to start +MGNCM1: ILDB B,MGCMBP(W) ;Get new command from list + JRST (B) ;And jump to it + +;This code is always the first (bottom) thing in a transport's Q PDL +; It is therefore executed whenever MGXGO transfers control to the +; Q PDL and there is no command in progress. +; +MGNCMD: AOBJN Q,MGNCM1 ;Got here w/ POPJ Q,. Fake PUSHJ to restore Q, + ; then go get the next command + + BUG ;Q PDL pointer clobbered + +QPOPJ1: AOS (Q) +QPOPJ: POPJ Q, + + +;WAIT FOR JOB DONE BIT TO SET +; Called from PI-level command routines to wait for end of command. +; Called with PUSHJ Q,MGWTJD +; +; Returns +1 to caller if unusual termination +; +2 to caller if operation terminated normally +; +; I,J contain tape status: +; On TM10, I=CONI MTC, +; J=CONI MTS +; On TM03S, I=%TMCS1,,%TMCS2 (controller status), +; J=%TMFS,,%TMERR (formatter status) + +IFN TM10P,[ +MGWTJD: CONI MTS,J ;Get transport status + TXNE J,%T1STH\%T1SIO ;Transport hung or Illegal operation? + JRST MGERR ;Yes, job-done isn't ever going to get set +MGWJD1: CONI MTS,J ;Get status again + SKIPN MGJDTI ;Is there a time out set? + IFSKP. + MOVE T,TIME ;Yes, check it. Get current time + CAML T,MGJDTI ;Smaller than specified timeout time? + JRST MGERR ;No, lose + ENDIF. + TXNN J,%T1SJD ;JOB-DONE bit set? + JRST MGOVER ;No, we want to wait for it + CONI MTS,J ;Job Done. Get status + CONI MTC,I ;Get CONI MTC + MOVEM J,MGCMTS(W) ;Save for MP level + MOVEM I,MGCMTC(W) +IFN TM10B,[ + SKIPE MGWCW ;Want to wait for control word? + PUSHJ Q,MGWCWC ;Check to see if it is written + SETZM MGWCW ;Clear wait-for-control-word request flag +] + CONO MTS,30 ;Clear channel conditions + MOVE B,MTCONO(W) + CONO MTC,(B) ;Release mtc, clear job done bit +IFN TM10B,[ + TXNE J,%T1SCP\%T1SNM\%T1SDP ;Check for channel errors + POPJ Q, ;Channel error, return nonskip +] + TXNE J,%T1STH\%T1SIO\%T1SPE\%T1SRC%\T1SRL\%T1SDL\%T1SBT + POPJ Q, ;Random other things, not necessarily errors + JRST QPOPJ1 ;Success +];IFN TM10P +IFN TM03S,[ +MGWTJD: +MGWJD1: IORDI T,%TMCS1 ;Get controller status + TXNN T,%TM1GO ;Go bit still set? + JRST MGWJD2 ;No, command is finished. Go check errors + SKIPE T,MGJDTI ;Is there a time out set? Get it if so. + CAML T,TIME ;Past timeout time + JRST MGOVER ;No timeout or not timed out yet, go wait + JRST MGERR ;Timed out. Go check transport + +;Here if action has terminated. Set up status bits before returning +MGWJD2: HRLZ I,T ;%TMCS1,,? + IORDI T,%TMCS2 + HRR I,T ;I = %TMCS1,,%TMCS2 + IORDI J,%TMERR + IORDI T,%TMFS + HRL J,T ;J = %TMFS,,%TMERR - I,J now in standard form + MOVEM J,MGCMTS(W) ;Save for MP level + MOVEM I,MGCMTC(W) + TTNE CS1,%TM1MP ;Massbus control parity error + JRST MGERR ;Who knows what the transport is doing + TTNN CS1,%TM1TE ;Controller error? + TTNE FS,%TMSES ;Formatter error? + POPJ Q, ;Yes, return +1 for closer examination + JRST QPOPJ1 ;Success +];IFN TM03S + +;Select the transport given by W +; Returns +1 with transport selected, status in I,J +; May dismiss and wait for a while first +; +MGGXPT: +IFN TM10P,[ + CONSO MTS,%T1SNU ;Can controller select new unit right now? + JRST MGOVER ;No, wait for it + MOVE T,TIME + ADDI T,10.*30. ;Time out in 10. seconds + MOVEM T,MGJDTI ;Set up job-done timeout + MOVEM W,MGUNIT ;Note unit waiting for hardware interrupt + MOVE B,MTCONO(W) ;Get CONO word for new unit + CONO MTC,MNOPIN(B) ;NOP, but interrupt when new drive is ready + PUSHJ Q,MGWJD1 ;Wait for job done + JFCL ;Ignore any errors + SETZM MGJDTI ;No more timeout + SETOM MGUNIT ;Not waiting any more + POPJ Q, ;Return to caller +];IFN TM10P +IFN TM03S,[ + IORDI T,%TMFS ;Get current formatter status + TXNN T,%TMSES\%TMSSC ;Showing error or slave status change? + IFSKP. ;Yes, clear errors before going ahead + IOWRI W,%TMTC ;Select slave + MOVEI A,10. ;Try 10 times to clear drive + MOVEI B,%TMCLR + DO. + IOWRI B,%TMCS1 ;Write drive clear command + IORDI T,%TMFS ;Get status + TXNN T,%TMSES ;Still have error + JRST ENDLP. ;No, done + SOJG A,TOP. ;Retry up to 10 times + JRST MGERR ;Else give up + ENDDO. + ENDIF. + MOVE T,MTSELW(W) ;Get desired settings + IOWRI T,%TMTC ;Tell TM03 + MOVEI T,%TMNOP ;You may need this to set status values + IOWRI T,%TMCS1 ; but I'm not really sure + IORDI T,%TMCS1 + PUSHJ Q,MGWJD2 ;Go set status registers appropriately + JFCL ;Maybe should check non-existant slave? + POPJ Q, +];IFN TM03S + +;MGERR - HANDLE TAPE ERROR +; +;Called from PI level command routines which detect a tape or controller error +; Flags error in software status word, records error status in MGExxx. +; Flushes command in progress by resetting Q PDL to base. +; Flushes commands in PI-level command queue by resetting queue pointers. +; Flushes any buffers which might be queued for writing. +; Returns to P PDL, to wait for new commands. + +MGERR: +IFN TM10P,[ + CONI MTS,MGEMTS ;Get transport status for MP level analysis + CONI MTC,MGEMTC +] +IFN TM03S,[ + IORDI T,%TMCS1 ;Get controller and transport status into + HRLM T,MGEMTC ; standard form + IORDI T,%TMCS2 + HRRM T,MGEMTC + IORDI T,%TMFS + HRLM T,MGEMTS + IORDI T,%TMERR + HRRM T,MGEMTS + MOVE I,MGEMTC ;Get status to standard place for macros + MOVE J,MGEMTS +];IFN TM03S + MOVSI T,%MARAC ;Read not active, for sure + ANDCAM T,MSRAC(W) + SETZM MSCMDC(W) ;No commands active + SETOM MGUNIT ;Clear unit wait flag + SETZM MGJDTI ;No job-done timeout +IFN TM10B,[ + TXNE J,%T1SCP\%T1SNM\%T1SDP ;Channel error? + BUG PAUSE,[MTAPE: CHANNEL ERROR, STATUS=],OCT,J,[MICWA+1=],OCT,MICWA+1,[MIOWD=],OCT,MIOWD +];TM10B +IFN TM03S,[ + .ERR UBA errors? More gentle cleanup? + TTNE CS1,%TM1MP\%TM1TE ;Cbus parity or transfer error? + TTNE FS,%TMSES ;And no formatter error? + SKIPA ;Yes and yes (no) (what?). Controller error + BUG INFO,[MTAPE: RH11 ERROR, STATUS=],OCT,MGEMTC,[TM STATUS=],OCT,MGEMTS + TTNE FS,%TMSES ;Formatter error? + BUG INFO,[MTAPE: FORMATTER ERROR, STATUS=],OCT,MGEMTS + PUSHJ P,TMINIC ;Go reinit controller +];IFN TM03S + SKIPL A,MGCABN(W) ;Any buffers owned by PI routines? + PUSHJ P,IMEMR ;Yes, give them back to system + SETOM MGCABN(W) ;No PI buffer any more + HRLZI B,%MAERR ;Flag error detected by PI level + IORM B,MSRAC(W) ;Store in transport status word + MOVE Q,[-MGQDLL,,MGQD0-1];Reset Q PDL to base of this unit's stack, + MOVE T,MSLCTB ; thus flushing whatever command is in progress + IMUL T,W ;Find offset to base of Q PDL for this unit + ADD Q,T ;Add to prototype unit 0 QDP pointer, + PUSH P,Q ; and save it away + MOVE Q,[-MSCBL-1,,MSCB0-1] ;Get command list input pointer + ADD Q,T ;Offset it to this unit's command queue, + MOVEM Q,MTCMBP(W) ;And save it as new MP (input) queue pointer + MOVE Q,[4400,,MSCB0-1] ;Get new command list output pointer + ADD Q,T ;Offset correctly for this unit, + MOVEM Q,MGCMBP(W) ;And save as PI (output) command queue pointer + MOVSI B,%MAREW ;Does initting xport stop TM03 rewind? + ANDCAM B,MSRAC(W) ;Say not rewinding + SKIPN MSCRW(W) ;If reading, + JRST POPQJ ; we're done. Restore Q and exit + SKIPN MSNBOL(W) ;Writing. Any buffers on list? + JRST POPQJ ;No, restore Q and exit + DO. ;Here to free buffers on IO list + HRRZ A,MSBUFP(W) ;Get buffer pointer from head of chain + LDB T,[MLO,,MEMBLT(A)] ;Get back pointer (next buffer) + HRRM T,MSBUFP(W) ;Make next buffer head of chain + PUSHJ P,IMEMR ;Free current buffer + SOSLE MSNBOL(W) ;Decrement count, check for more + JRST TOP. ;More, loop back + ENDDO. + SETZM MSBUFP(W) ;Mark list as empty + JRST POPQJ ;Restore Q and return + +IFN TM10B,[ +;Wait for control word to get written +; +MGWCWC: SKIPE MICWA+1 ;Control word written? + POPJ Q, ;Yes, return to caller + CONO MTS,4 ;No, tell DF10 to write it +MGWCW1: SKIPE MICWA+1 ;Written yet? + JRST MGWCW2 ;Good, done + PUSHJ Q,CPOPJ ;Not written. Dismiss interrupt and wait + JRST MGWCW1 ;We're back. See if written yet. + +MGWCW2: MOVE I,MGCMTC(W) + MOVE J,MGCMTS(W) ;Restore status + TLO J,10 ;Set control word written + POPJ Q, ;Return to caller +];IFN TM10B + +IFN TM10A,[ +MGDCSI: SKIPA A,[BLKI MTC,MIOWD] +MGDCSO: MOVE A,[BLKO MTC,MIOWD] + MOVEM A,MAGLOC + MOVE A,[JSR MGDBRK] + MOVEM A,MAGLOC+1 + POPJ Q, +];IFN TM10A + +IFN TM03S,[ +;Note this one's called on P PDL +TMINIC: IORDI A,%TMTC ;Get TC reg value + ANDI A,MTSELM ;Keep interesting bits only + IORDI B,%TMCS2 ;Get CS2 + ANDI B,7 ;Keep selected "drive" (TM03) number only + MOVEI T,%TM2CC + IOWRI T,%TMCS2 ;Clear controller logic + IOWRI B,%TMCS2 ;Reselect TM03 + IOWRI A,%TMTC ;Reselect transport + MOVX T,%TMCLR ;Do a formatter clear command + IOWRI T,%TMCS1 + POPJ P, +];IFN TM03S + + +SUBTTL MAG TAPE PI LEVEL WRITE + +MGWRIT: PUSHJ Q,MGGXPT ;Select desired transport +IFN TM10P,[ + TXNE J,%T1STH\%T1SRW\%T1SWL ;Write locked, hung or rewinding? + JRST MGERR ;Not a good thing +] +IFN TM03S,[ + TTNE FS,%TMSFR ;Formatter ready? + TTNN FS,%TMSOL ;Transport on line? + JRST MGERR ;No or no, can't do operation + TTNE FS,%TMSWL ;Transport write locked? + JRST MGERR ;Shouldn't happen, we checked at open. +] + MOVSI A,%MACTH + TDNE A,MSRAC(W) ;Core alloc want quit temporarly? + JRST [ PUSHJ Q,CPOPJ ;OK, wait a while + JRST MGWRIT ] ;Then go back and try again + MOVEM W,MGUNIT ;Set unit + HRREI B,-MGNRTY ;Number of retries + MOVEM B,MGERRC(W) ;Store error count + MTDEQB A ;Get buffer to write off list + MOVEM A,MGCABN(W) ;Note this buffer active at PI + LDB B,[MWC,,MEMBLT(A)] ;Get word count from buffer + MOVNS B ;B -> -COUNT + HRLZS B ;B -> -COUNT,,0 +IFN KL10P,LSH B,4 ;Shift if KL10 data channel +IFN KL10P,MOVE R,A ;Save core page number for cache sweep +IFE TM03S,[ ;TM03S IOWD is -COUNT,,ITS PAGE + LSH A,10. ;Convert buffer number to memory address + SUBI A,1 ;Address - 1 +] + HRRM A,B ;B -> -COUNT,,ADDRESS-1; an IO word +IFN TM10B,DATAO MTS,[MICWA] ;Tell DF10 where IO channel program is +IFN TM10A,PUSHJ Q,MGDCSO ; + MOVEM B,MIOWD ;Put IO word where controller looks + MOVEM B,LMIOWD ;Remember what we're about to do +IFN TM10P,SETZM MIOWD+1 ;Stop after one operation +IFN KL10P,[ + PUSHJ P,CSHSWP ;Unload buffer from cache into core + CAI +] +MGWRT2: +IFN TM10P,[ + MOVE B,MTCONO(W) ;Get prototype CONO word + CONO MTC,MWRITE(B) ;Perform WRITE operation +] +IFN TM03S,[ + HLRE A,MIOWD ;Get PDP10 word count + ASH A,1 ; * 2 + IOWRI A,%TMWC ; = number of unibus words to transfer + HLRE A,MIOWD ;Get PDP10 word count again + IMUL A,MTWTFC(W) ;Convert to tape frame count + IOWRI A,%TMFC ;Set tape frames to write + HRRZ A,MIOWD ;Get ITS page to transfer to + LSH A,1 ;Convert ITS pg # to DEC pg # + TXO A,%UQVAL ;Valid mapping, I should hope + IOWRI A,UBAPAG+IUTPG_1 ;Set up first half of UBA mapping + TXO A,1 ;Next DEC page number + IOWRI A,UBAPAG+IUTPG_1+1 ;Set second half of UBA mapping + MOVEI A,IUTPG_14 ;Unibus address to DMA to + IOWRI A,%TMBA ;Tell controller + MOVX A,%TM1IE\%TMWRT ;Write, enable interrupts + IOWRI A,%TMCS1 ;Start controller +] + PUSHJ Q,MGWTJD ;Wait for job done + JRST MGWERR ;Error, go attempt to repair + +;Here if tape written OK +MGWRT3: MOVE A,MGCABN(W) ;Get buffer number + HRLZI B,%MAETW+%MAERR ;End of tape check +IFN TM10P,TXNE J,%T1SET ;Controller says we're at EOT? +IFN TM03S,TTNE FS,%TMSET + IORM B,MSRAC(W) ;Tell MP + LDB T,[MUR,,MEMBLT(A)] ;Get buffer flavor from buffer + CAIE T,MUMGB ;Still a magtape buffer? + BUG HALT,[MT BUF CHANGED INTO SOME OTHER KIND??] + SETOM MGCABN(W) ;No buffer active at PI anymore + PUSHJ P,IMEMR ;Return buffer to system + MOVSI A,%MAMSO ;Note tape has moved since open + IORM A,MSRAC(W) + ;JRST MGCMDR ;Falls through + +;General exit routine for most PI-level command handlers +; Check command queue for more commands. +; If no further commands, dismiss interrupt. +; If further commands queued, wait for this one to finish, then fetch +; and begin processing of next command. +; +MGCMDR: SOS MSCMDC(W) ;Decrement command count + SETOM MGUNIT ;Reset active unit + SKIPG MSCMDC(W) ;Any more commands? + JRST MGCMR1 ;No. Go see about other units +IFN TM10P,[ + MOVE B,MTCONO(W) + CONO MTC,MNOPIN(B) ;Tell controller to interupt when unit ready + MOVEM W,MGUNIT ;Set up unit number again for MGWTJD + PUSHJ Q,MGWTJD ;Go wait for unit to finish current command + JRST MGERR ;Oops + SETOM MGUNIT ;No unit waiting any more +];IFN TM10P + POPJ Q, ;Return on Q PDL. Most likely this will + ; transfer control to MGNCMD routine at + ; base of PDL, which will fetch and execute + ; next command. + +MGCMR1: +IFN NMTCS-1,[ +;Ought to check other transports for commands to start. +; For now, will get started by 1/2 second timeout, if nothing else. + .ERR Unfinished multi-transport code at MGCMR1 +];IFN NMTCS-1 + POPJ P, ;No more, return on P to dismiss interrupt + + + +;CONTROLLER DETECTED ERROR ON WRITE OPERATION +; Retry, or give up, or write some blank tape and then try again, +; depending on the type of error. +; +MGWERR: +IFN TM10P,[ +IFN TM10B,SETZM MIOWD ;Seems to do one record anyway +IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD ;Specify one record to space back cmd. +] + TXNE J,%T1STH\%T1SRW\%T1SIO\%T1SET\%T1SWL ;Bad types of errors + JRST MGERR ;OK, give up + AOSL MGERRC(W) ;Still retrying? + JRST MGERR ;No, give up + MOVE B,MTCONO(W) + CONO MTC,MSPRR(B) ;Space reverse one record + PUSHJ Q,MGWTJD ;Wait for job done + JRST MGERR ;Error + MOVE B,LMIOWD ;Get last operation's IOWD + MOVEM B,MIOWD ;We're going to try it again + MOVE B,MTCONO(W) ;Get prototype CONO + CONO MTC,14000(B) ;Write with extended EOR gap + PUSHJ Q,MGWTJD ;Wait for completion + JRST MGWBT ;Lost again, retry some more + JRST MGWRT3 ;Worked, return to normal write sequence +];IFN TM10P +IFN TM03S,[ + TTNE ERR,%TMERM\%TMEUS\%TMEFS\%TMEIR\%TMEIF\%TMEMC\%TMECT\%TMENX\%TMEOI + JRST MGERR ;Fatal errors + TTNN FS,%TMSOL ;On line? + JRST MGERR ;This isn't so good either + TTNE ERR,%TMEFC\%TMENG\%TMEMD\%TMEIC\%TMECE\%TMECS\%TMEFL + JRST MGWER1 ;Error which retrying might fix + +;Formatter seems happy. Check channel status before returning +; Currently this only catches the case where there was an RH11 error +; but no TM03 error, and thus should always end up jumping to MGERR. +; Formatter errors on which it might be OK to get here are %TMECE, +; %TMECS, %TMEFL, but someone needs to test this... + TTNE CS1,%TM1TE ;Transfer error? + TTNE FS,%TMSES ;And not formatter error? + CAIA + JRST MGERR ;Just lose for now + BUG INFO,[MT: ACCEPTING QUESTIONABLE WRITE OPERATION] + JRST MGWRT3 + +;Retry errors +MGWER1: AOSL MGERRC(W) ;Still retrying? + JRST MGERR ;No, give up + BUG INFO,[MT: RETRYING WRITE OPERATION] + PUSHJ P,TMINIC ;Hit controller with hammer + MOVEI B,1 + MOVEM B,MGSPCD(W) ;1 record + PUSHJ Q,MGSPCR ;Reselect transport space back a record + TTNE FS,%TMSTM ;Stopped on EOF? + SOSGE MGEOFR(W) ;Yes, one less EOF in front of us + SETZM MGEOFR(W) ;But never less than zero + PUSHJ P,TMINIC ;Hit controller with hammer again + PUSHJ Q,MGGXPT ;Set up transport again + MOVEI B,%TMER3\%TM1IE + IOWRI B,%TMCS1 ;Erase a few inches of tape + PUSHJ Q,MGWTJD ;Wait for job done + JRST MGERR ;Can't get anything right... + MOVE B,LMIOWD ;Get last operation's IOWD + MOVEM B,MIOWD ;We're going to try it again + JRST MGWRT2 ;Go back to write code and retry operation +];IFN TM03S + + +SUBTTL MAG TAPE PI LEVEL READ + +MGREAD: PUSHJ Q,MGGXPT ;Select desired transport +MGRD0: +IFN TM10P,[ + TXNE J,%T1STH\%T1SRW\%T1SET ;Unit hung, rewinding, or EOT + JRST MGERR ;Seems so, report error +] +IFN TM03S,[ + TTNE FS,%TMSFR ;Formatter ready? + TTNN FS,%TMSOL ;Transport on line + JRST MGERR ;No or no, can't do operation +] + MOVE B,MGEOFR(W) ;EOF's seen since last read + CAIL B,2 ;Apparent logical EOT? + JRST MGERR ;Yes, can't read anything + SKIPE MSCRW(W) ;Make sure open for reading + BUG HALT,[MT: CHN NOT OPEN FOR READING] + MOVSI B,%MACTH ;Core allocator wants to wait? + TDNN B,MSRAC(W) ;Check in status word + PUSHJ P,IOMQ ;No, get a buffer + JRST [PUSHJ Q,CPOPJ ;Wanted to wait some or failed, + JRST MGREAD ] ; wait a while, then start over + MOVEM A,MGCABN(W) ;Note active buffer at PI level + MOVEI B,MUMGB + DPB B,[MUR,,MEMBLT(A)] ;Note buffer belongs to mag tape code + MOVEM W,MGUNIT ;Set active unit number + HRREI B,-MGNRTY ;Number of retries + MOVEM B,MGERRC(W) ;Store error count +IFN KL10P, MOVE R,A ;Get page for cache flush routine +IFE TM03S,[ ;TM03S IOWD is -COUNT,,ITS PAGE + LSH A,10. ;Convert buffer number to memory address + SUBI A,1 ;address-1 +] +IFE KL10P,HRLI B,-2000 ;Get count half of IOWD +IFN KL10P,HRLI B,-2000_4 ;The KL is, of course, different + HRR B,A ;-count,,address-1 + MOVEM B,LMIOWD ;Remember IOWD for possible retry +IFN TM10B,[ + DATAO MTS,[MICWA] ;Tell DF10 where the channel program is + SETZM MICWA+1 ;Stop after one operation +] +IFN TM10A,PUSHJ Q,MGDCSI +IFN TM10P,SETZM MIOWD+1 +MGRD1: MOVEM B,MIOWD ;Save IOWD where channel expects it + MOVEI B,2000 ;Assume for now that the record has 2K words + MOVEM B,MGNWRD ;Set up word count +IFN KL10P,[ + PUSHJ P,CSHSWP ;Ensure no residue of this page in cache + CAIA +] +IFN KS10P,CLRCSH ;KS needs cache invalidated on read +IFN TM10P,[ + MOVE B,MTCONO(W) ;Get prototype CONO word + CONO MTC,MREAD(B) ;Issue READ command +] +IFN TM03S,[ + HLRE A,MIOWD ;Get PDP10 word count + ASH A,1 ; * 2 + IOWRI A,%TMWC ; = number of unibus words to transfer + SETZ A, ;Set FC to zero + IOWRI A,%TMFC ;Set tape frames to write + HRRZ A,MIOWD ;Get ITS page to transfer to + LSH A,1 ;Convert ITS pg # to DEC pg # + TXO A,%UQVAL + IOWRI A,UBAPAG+IUTPG_1 ;Set up first half of UBA mapping + TXO A,1 ;Next DEC page number + IOWRI A,UBAPAG+IUTPG_1+1 ;Set second half of UBA mapping + MOVEI A,IUTPG_14 ;Unibus address for DMA + IOWRI A,%TMBA ;Tell controller + MOVX A,%TM1IE\%TMRDF ;Read forward, enable interrupts + IOWRI A,%TMCS1 ;Start controller +];IFN TM03S +IFN TM10B,SETOM MGWCW ;Tell MGWTJD to wait for control word written + PUSHJ Q,MGWTJD ;Wait for command to complete + JRST MGRERR ;Error, go do something. May be retry, correct + ; MGNWRD if frame count error, or give up +IFN TM03S,[ +;Get true record size for TM03, which doesn't give a FC error on READ +MGRD1A: TTNE FS,%TMSTM ;Read a tape mark? + JRST [ SETZM MGNWRD ;Read a tape mark. No data, just EOF + JRST MGRD2 ] + IORDI A,%TMFC ;Get record size in tape frames + ADD A,MTWTFC(W) ;Round up to PDP10 words. + SUBI A,1 ;Add frames_per_word - 1 + IDIV A,MTWTFC(W) ;Get record size in PDP10 words + MOVEM A,MGNWRD +];IFN TM03S +;Here if OK or error handler has fixed things up +MGRD2: MOVE A,MGCABN(W) ;Get buffer we just wrote + SETOM MGCABN(W) ;No buffer active at PI level + MTENQB A ;Queue buffer up for MP level + MOVE B,MGNWRD ;Get number of words we read + DPB B,[MWC,,MEMBLT(A)] ;Set number of words in buffer +IFN TM10P,TXNE J,%T1SEF ;Read an EOF? +IFN TM03S,TTNE FS,%TMSTM ; i.e. a tape mark? + IFSKP. + SETZM MGEOFR(W) ;No. Note no EOFs read since last record + ELSE. + MOVSI B,%MAESO+%MAEFA ;EOF seen since open, EOF read ahead + IORM B,MSRAC(W) ;Note this in transport status word + SETO B, + DPB B,[MSEOFP,,MEMBLT(A)] ;Set EOF flag in this buffer + AOS A,MGEOFR(W) ;Count EOFs + CAIL A,2 ;Enough for EOT? + JRST MGRD4 ;Logical EOT, space back over it + ENDIF. + MOVSI A,%MAMSO + IORB A,MSRAC(W) ;Note tape movement +IFN TM10P,TXNE J,%T1SET ;Real EOT reached? +IFN TM03S,TTNE FS,%TMSET + JRST MGRD3 + MOVE C,MSNBOL(W) ;Get count of buffers on list +IFN TM10P,TXNN J,%T1SEF ;EOF? +IFN TM03S,TTNN FS,%TMSTM + +; CAIL C,6 ; or read ahead six records? + JFCL ;Or just for the hell of it + + JRST MGRD5 ;Yes, stop reading + TLNN A,%MASTP ;Somebody request we stop? + JRST MGRD0 ;No, go back and read another record + ;Yes, fall through to terminate read +;Here to terminate read command +; +MGRD5: MOVSI A,%MASTP+%MARAC ;Clear read active, any read stop request + ANDCAM A,MSRAC(W) + JRST MGCMDR ;Go to standard command return routine + +;Controller saw a real EOT +; +MGRD3: DPB B,[MSEOFP,,MEMBLT(A)] ;Fake EOF + DPB B,[420100,,MSRAC(W)] .SEE %MAETR ;Indicate EOT on read + JRST MGRD5 ;Terminate read + +;Here if logical EOT (two EOF's in a row) +; Back up till between the two EOF's +; +MGRD4: MOVSI A,%MAESO+%MARAC+%MASTP ;SECOND EOF, LOGICAL EOT + ANDCAM A,MSRAC(W) + JRST MGSPRF ;Space reverse one file + +;Error detected on read. +; Analyze error, retry read if it might help +; +MGRERR: +IFN TM10P,[ + IFN TM10B,[ + TXNE J,%T1SCP\%T1SNM\%T1SDP + JRST MGERR ;Channel error, forget it + ] + TXNE J,%T1STH\%T1SRW\%T1SIO\%T1SRC ;Hard error? + JRST MGERR ;Yes, abandon read + TXNE J,%T1SPE\%T1SDL%T1SBT ;Parity, data-late, or bad tape? + JRST MGMRT ;Yes, a read retry might fix it + TXNN J,%T1SRL ;Record length error? + JRST MGERR ;No, who knows what is going on + +;Here if record length error. Adjust MGNWRD to reflect data actually read +; +IFN TM10B,HRRZ A,MICWA+1 +IFN TM10A,HRRZ A,MIOWD ;Get final control word + HRRZ B,LMIOWD ;Get original IOWD + SUB A,B ;Calculate words read +IFN TM10B,SOS A ;Channel funnyness + CAIE A,1 ;Length of 1 may just be EOF indication + IFSKP. + TXNE J,%T1SEF\%T1SET ;1 word, EOF? EOT? + SETZM A ;Yes, zero length record, just carries MSEOFP + ENDIF. + MOVEM A,MGNWRD ;Save new record length + JRST MGRD2 ;Go process as potentially correctly read data +];IFN TM10P +IFN TM03S,[ + TTNE ERR,%TMERM\%TMEUS\%TMEFS\%TMEIR\%TMEIF\%TMEMC\%TMECT\%TMENX + JRST MGERR ;Fatal errors + TTNN FS,%TMSOL ;On line? + JRST MGERR ;This isn't so good either + TTZ ERR,%TMEFC\%TMENG ;Ignore NSG, Frame count error + TTNE FS,%TMSPE ;Phase encoded (1600BPI) mode? + TTZ ERR,%TMECE\%TMECS ;If so, ignore errors hardware already fixed + TTZN ERR,%TMECE\%TMECS\%TMEFC\%TMENG\%TMEFL\%TMEMD\%TMEIC ;Retryable? + JRST MGRER1 ;Nothing retrying will help + TTNE FS,%TMSTM ;Tape mark? + JRST MGRER2 ;Yes, no point in retrying + JRST MGMRT ;OK, go retry read + +;Formatter seems happy. Check channel status before returning +MGRER1: TTNE ERR,177777 ;Sanity check. Shouldn't be any errors left + JRST MGERR + TTNE CS1,%TM1TE ;Transfer error? + TTNE FS,%TMSES ;And not formatter error? + CAIA + JRST MGERR ;Just lose for now +MGRER2: JRST MGRD1A + +];IFN TM03S + + +;Retry a read operation +; +MGMRT: AOSL MGERRC(W) ;Still retrying? + JRST MGERR ;No, give up +IFN TM10P,[ + IFN TM10B,SETZM MIOWD + IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + ] + MOVEM A,MIOWD ;One record + PUSHJ Q,MGDCSO + MOVE B,MTCONO(W) + CONO MTC,MSPRR(B) ;Back up one record + PUSHJ Q,MGWTJD ;Wait till done + JRST MGERR ;No errors allowed + IFN TM10A,PUSHJ Q,MGDCSI ;Put back PI 1 BLKI +];IFN TM10P +IFN TM03S,[ +;This could be more refined + PUSHJ P,TMINIC ;Hit controller with hammer + PUSHJ Q,MGGXPT ;Set up transport again + SETO A, + IOWRI A,%TMFC ;1 record + MOVEI A,%TM1IE\%TMSPR ;Space backwards command + IOWRI A,%TMCS1 ;Do it + PUSHJ Q,MGWTJD ;Wait till finished + JRST MGERR ;Give up if error +];IFN TM03S + MOVE B,LMIOWD ;Get IOWD from last command + JRST MGRD1 ;Try operation again + + +SUBTTL MAG TAPE PI LEVEL SPACING COMMANDS +;Space forward and space reverse are completely under conditionals + +IFN TM03S,[ + +;Space forward MGSPCD(W) records +MGSPCF: PUSHJ Q,MGGXPT ;Acquire transport + TTNE FS,%TMSFR ;Formatter ready? + TTNN FS,%TMSOL ;Transport on line + JRST MGERR ;No or no, can't do operation + MOVEM W,MGUNIT ;Note active transport + MOVN A,MGSPCD(W) ;Get -count + IOWRI A,%TMFC ;Tell controller + MOVEI A,%TMSPF ;Get command + TXO A,%TM1IE ;Turn on interrupts + IOWRI A,%TMCS1 ;Start controller + PUSHJ Q,MGWTJD ;Wait till command completes + IFNSK. ;Error? + TTNE CS1,%TM1MP ;Control parity err? + JRST MGERR ;Yes, nothing else valid + TTNE FS,%TMSES ;Formatter errors? + IFSKP. + PUSHJ P, TMINIC ;No formatter errors, ignore RH errors + ELSE. + TTNN ERR,%TMEFC ;Frame count error? + JRST MGERR ;Nope, must be important + PUSHJ P,TMINIC + ENDIF. + ENDIF. + POPJ Q, + +;Space forward record +MGSPFR: MOVEI B,1 ;Do one record + MOVEM B,MGSPCD(W) ;Set count + MOVSI B,%MAMSO ;Note this command causes tape movement + IORM B,MSRAC(W) ;Set in transport software status + PUSHJ Q,MGSPCF ;Do spacing op + TTNN FS,%TMSTM + SETZB B,MGEOFR(W) ;Count EOFs since last record. None here + TTNE FS,%TMSTM + AOS B,MGEOFR(W) ;Saw one. + CAIL B,2 ;Saw two? + JRST MGSPRR ;Back up over last one... + JRST MGCMDR ;Clean up and leave + +;Space forward file +MGSPFF: MOVSI B,%MAESO ;See if tape has already read ahead to EOF + TDZE B,MSRAC(W) + JRST MGCMDR ;EOF already read during the read, done + MOVEI B,1 ;Do one record + MOVEM B,MGSPCD(W) ;Set count + MOVSI B,%MAMSO ;Note this command causes tape movement + IORM B,MSRAC(W) ;Set in transport software status + PUSHJ Q,MGSPCF ;Space forward one record + TTNN FS,%TMSTM + IFSKP. ;Saw a TM + AOS B,MGEOFR(W) ;Saw one. + CAIL B,2 ;Saw two? + JRST MGSPRR ;Yes, back up over last one, and leave + JRST MGCMDR ;No, OK, but we're done + ENDIF. + SETZB B,MGEOFR(W) ;No tape mark, reset count of EOFs seen +MGSPF1: MOVEM B,MGSPCD(W) ;Set count to 0 (B zero from above) + PUSHJ Q,MGSPCF ;Do it + TTNE FS,%TMSTM ;Saw a EOF? + IFSKP. ;No.. + TTNE FS,%TMSET ;Saw an EOT? + JRST MGERR ;Really shouldn't happen + JRST MGSPF1 ;Else go look for TM again + ENDIF. + AOS MGEOFR(W) ;Saw one. + JRST MGCMDR ;EOF read. done + +;Space reverse MGSPCD(W) records +MGSPCR: PUSHJ Q,MGGXPT ;Set up transport and get status + TTNE FS,%TMSFR ;Formatter ready? + TTNN FS,%TMSOL ;Transport on line + JRST MGERR ;No or no, can't do operation + TTNE FS,%TMSBT ;At BOT? + POPJ Q, + MOVEM W,MGUNIT ;Save selected transport + MOVN A,MGSPCD(W) ;Get -count + IOWRI A,%TMFC ;Tell controller + MOVEI A,%TMSPR ;Space Reverse command + TXO A,%TM1IE ;Turn on interrupts + IOWRI A,%TMCS1 ;Start controller + PUSHJ Q,MGWTJD ;Wait till command completes + IFNSK. ;Error? + TTNE CS1,%TM1MP ;Control parity err? + JRST MGERR ;Yes, nothing else valid + TTNE FS,%TMSES + IFSKP. + PUSHJ P,TMINIC + ELSE. + TTNN ERR,%TMEFC ;Frame count error? + JRST MGERR ;Nope, must be important + PUSHJ P,TMINIC + ENDIF. + ENDIF. + POPJ Q, + +;Space reverse one record +MGSPRR: MOVEI B,1 + MOVEM B,MGSPCD(W) ;1 record + MOVSI B,%MAMSO ;Note this command causes tape movement + IORM B,MSRAC(W) ;Set in transport software status + PUSHJ Q,MGSPCR + TTNE FS,%TMSTM ;Stopped on EOF? + SOSGE MGEOFR(W) ;Yes, one less EOF in front of us + SETZM MGEOFR(W) ;But never less than zero + JRST MGCMDR ;Leave through general exit + +;Space reverse fill +MGSPRF: MOVSI B,%MAESO ;See if tape has already read ahead to EOF + TDNN B,MSRAC(W) + JRST MGSPR2 ;No, we can just do command +MGSPR1: MOVEI B,1 + MOVEM B,MGSPCD(W) + PUSHJ Q,MGSPCR ;Skip back 1 record, should backup over EOF + TTNN FS,%TMSTM ;Tape mark seen? + JRST MGSPR1 ;Well, apparently not + MOVSI B,%MAESO + ANDCAM B,MSRAC(W) ;Turn off EOF-read-ahead flag +MGSPR2: SETZ B, + MOVEM B,MGSPCD(W) ;Space backwards the maximum number of records + PUSHJ Q,MGSPCR ;Do it + TTNN FS,%TMSBT ;BOT? + TTNE FS,%TMSTM ;Tape mark seen? + JRST MGCMDR ;Yes or Yes, all done + JRST MGSPR2 ;No, go back and try to find one. + +];End TM03S way back + + ;Rewind commands +; +MGRWND: +IFN TM10P,MOVEI B,MREWND ;Normal rewind +IFN TM03S,MOVEI B,%TMREW + CAIA +MGRWDM: +IFN TM10P, MOVEI B,MRWNDD ;Rewind and dismount +IFN TM03S, MOVEI B,%TMUNL + MOVEM B,MGSPCD(W) ;Set up command + PUSHJ Q,MGRWD1 ;Call action routine + JRST MGCMDR + +;Action routine for rewind commands +MGRWD1: PUSHJ Q,MGGXPT +IFN TM03S,[ + TTNE FS,%TMSFR ;Formatter ready? + TTNN FS,%TMSOL ;Transport on line + JRST MGERR ;No or no, can't do operation +] + MOVEM W,MGUNIT + MOVE B,MGSPCD(W) ;Get desired command +IFN TM10P,[ + ADD B,MTCONO(W) + CONO MTC,(B) +] +IFN TM03S,[ + TXO B,%TM1IE + IOWRI B,%TMCS1 +] + PUSHJ Q,MGWTJD ;Start controller and wait till done + IFNSK. + TTNE FS,%TMSES + JRST MGERR ;Oops. + ENDIF. + SETZM MGEOFR(W) ;Seen no EOFs since last record + +;Here after rewind command has started. +; Two possibilities: Tape is rewound already, or controller is finished +; but tape is still rewinding. +IFN TM10P,[ +MGRWD2: TXNN J,%T1SRW ;Slave still rewinding tape? + JRST MGRWD3 ;No, at BOT + PUSHJ Q,CPOPJ ;Wait some. + CONI MTS,J ;Get status again + MOVEM J,MGCMTS(W) ;Update in memory + JRST MGRWD2 ;Go see if we're done yet. + +;Here when tape has rewound +MGRWD3: MOVE T,TIME ;Wait 1 second more + ADDI T,30. ;This is an attempt to fix a hardware bug + MOVEM T,MGJDTI +MGRWD4: MOVE T,TIME + CAML T,MGJDTI ;Check time + JRST MGRWD5 ;Finished waiting, go clean up + PUSHJ Q,CPOPJ ;No, wait some more + JRST MGRWD4 + +MGRWD5: MOVSI A,%MAMSO+%MAREW + ANDCAM A,MSRAC(W) ;Say not rewinding, hasn't moved + SETZM MGJDTI ;Clear timeout + POPJ Q, +];IFN TM10P +IFN TM03S,[ +;This could be a lot smarter; should dismiss the command completely +; after rewind is started, and just scan for rewinding transports +; when a SSC interrupt is received. This change is also necessary +; to make multiple slaves work right; currently the rewinding unit +; holds active unit (MGUNIT) until the rewind is completed. +MGRWD2: TTNN FS,%TMSPP ;Transport still rewinding? + JRST MGRWD3 ;No, go finish up + PUSHJ Q,CPOPJ ;Dismiss interrupt, wait a while + PUSHJ Q,MGGXPT ;Get right slave, set up status + JRST MGRWD2 + +MGRWD3: MOVSI A,%MAMSO+%MAREW + ANDCAM A,MSRAC(W) ;Say not rewinding, hasn't moved + POPJ Q, +];IFN TM03S + +;SKIP TO LOGICAL EOT +; +MGSEOT: PUSHJ Q,MGGXPT ;Get transport +IFN TM10P,[ + TXNE J,%T1STH\%T1SRW ;Hung or rewinding? + JRST MGERR +] +IFN TM03S,[ + TTNE FS,%TMSFR ;Formatter ready? + TTNN FS,%TMSOL ;Transport on line + JRST MGERR ;No or no, can't do operation +] + MOVEM W,MGUNIT ;Set active unit +IFN TM10P,TXNE J,%T1SBT ;BOT? +IFN TM03S,TTNE FS,%TMSBT + JRST MGVTCK ;Yep, do virgin tape check + +;Not at BOT +; Do we have enough CONDITIONALS yet? +MGNVT: +IFN TM10P,[ + MOVE B,MTCONO(W) ;Get CONO word + IFN TM10A,[ + PUSHJ Q,MGDCSO + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD ;Tell it to move one record + ] + IFN TM10B,SETZM MIOWD + CONO MTC,MSPRR(B) ;Space reverse first +];IFN TM10P +IFN TM03S,[ + SETO B, ;Space backwards one record + IOWRI B,%TMFC + MOVEI B,%TMSPR\%TM1IE + IOWRI B,%TMCS1 +];IFN TM03S + PUSHJ Q,MGWTJD ;Wait till done + IFNSK. + TTNE FS,%TMSES + JRST MGERR + ENDIF. + SETZM MGEOFR(W) + AOS MGEOFR(W) ;Claim to have seen one EOF +MGEOT2: +IFN TM10P,[ + MOVE B,MTCONO(W) + CONO MTC,MSPFF(B) ;Skip forward to EOF + PUSHJ Q,MGWTJD + JRST MGERR +] +IFN TM03S,[ + AOS MSCMDC(W) ;Kludge so MGSPFF will return here. + PUSHJ Q,MGSPFF ;Space forward file +] + MOVSI B,%MAETR ;See if we hit real EOT +IFN TM10P, TXNE J,%T1SET +IFN TM03S, TTNE FS,%TMSET + IORM B,MSRAC(W) ;Yep, tell MP +IFN TM10P,[ + MOVE B,MTCONO(W) + IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD ;One record + ] + IFN TM10B,SETZM MIOWD + CONO MTC,MSPFR(B) ;Space forward one record +] +IFN TM03S,[ + SETO B, + IOWRI B,%TMFC + MOVEI B,%TMSPF\%TM1IE + IOWRI B,%TMCS1 +] + PUSHJ Q,MGWTJD + IFNSK. + TTNE FS,%TMSES + JRST MGERR + ENDIF. + MOVSI B,%MAETR ;Check for real EOT again +IFN TM10P,TXNE J,%T1SET +IFN TM03S,TTNE FS,%TMSET + IORM B,MSRAC(W) +IFN TM10P,TXNN J,%T1SEF ;Is this another EOF? +IFN TM03S,TTNN FS,%TMSTM ;(i.e. a tape mark) + JRST MGEOT2 ;No, not at logical EOT. Go try again +IFN TM10P,[ + MOVE B,MTCONO(W) ;Yes, at logical EOT, Back up over 1 EOF + CONO MTC,MSPRF(B) ;Space back one file +] +IFN TM03S,[ + SETO B, + IOWRI B,%TMFC + MOVEI B,%TMSPR\%TM1IE + IOWRI B,%TMCS1 +] + PUSHJ Q,MGWTJD + IFNSK. + TTNE FS,%TMSES + JRST MGERR + ENDIF. + MOVSI B,%MAEOF+%MAETR ;Tell MP at EOF, EOT + IORM B,MSRAC(W) + JRST MGCMDR + +;Check for virgin tape +MGVTCK: MOVE T,TIME + ADDI T,60. ;Set a two second timeout + MOVEM T,MGEOTT(W) ; before we must see an EOT +IFN TM10P,[ + IFN TM10B,[ + SETZM MIOWD + DATAO MTS,[MICWA] + ] + IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] + MOVEM A,MIOWD + PUSHJ Q,MGDCSO + ] + MOVE B,MTCONO(W) + CONO MTC,MREAD(B) ;Read record. will time out if no EOF marks +MGVTC1: CONI MTS,J + MOVEM J,MGCMTS(W) + TXNE J,%T1SJD ;Job done? + JRST MGNVT ;Yep, not virgin tape + TXNE J,%T1STH\%T1SIO ;Transport hung or illegal operation? + JRST MGERR ;Yes, give up + MOVE T,MGEOTT(W) ;Get the timeout value + CAMG T,TIME ;Time up? + JRST MGVT ;Yes, it's a new tape + PUSHJ Q,CPOPJ ;Wait a while + JRST MGVTC1 ;Go back and check again +];IFN TM10P +IFN TM03S,[ + SETO B, + IOWRI B,%TMFC ;Do one record + MOVEI B,%TMSPF\%TM1IE ;Space forward command + IOWRI B,%TMCS1 + +MGVTC1: IORDI T,%TMCS1 ;Get status + TXNN T,%TM1GO ;Still going? + IFSKP. ;Yep. + MOVE T,MGEOTT(W) ;Get the timeout value + CAMG T,TIME ;Time up? + JRST MGVT ;Yes, it's a new tape + PUSHJ Q,CPOPJ ;Wait a while + JRST MGVTC1 ;Go back and check again + ENDIF. + TXNE T,%TM1TE\%TM1MP ;Controller error? + JRST MGERR ;Yes, bad + IORDI T,%TMFS ;Get formatter status + TXNE T,%TMSES ;Formatter error? + JRST MGNVT ;No error, not a new tape + IORDI T,%TMERR ;Get formatter error register + TXNE T,%TMEFC ;Frame Count error? + JRST MGNVT ;Yes, that is probably an OK tape + JRST MGERR ;Not FC, must be a real problem +];IFN TM03S + +;Virgin tape. Abort operation in progress, rewind tape +MGVT: +IFN TM10P,[ + MOVE B,MTCONO(W) + CONO MTS,31 ;Clear controller + CONO MTC,MNOPIN(B) ;Start new command to clear things out + PUSHJ Q,MGWTJD + JFCL ;Ignore errors +] +IFN TM03S,[ + PUSHJ P,TMINIC +] +IFN TM10P,MOVEI B,MREWND ;Do a rewind +IFN TM03S,MOVEI B,%TMREW + MOVEM B,MGSPCD(W) + PUSHJ Q,MGRWD1 + SETZM MGEOFR(W) ;No EOFs seen + AOS MGEOFR(W) ;??? + JRST MGCMDR ;Done + +;Write EOT mark (two EOF's) on tape +; +MGMEOT: PUSHJ Q,MGGXPT +IFN TM10P,[ + TXNE J,%T1STH\%T1SRW\%T1SWL ;Hung, rewinding, or write locked... + JRST MGERR +] +IFN TM03S,[ + TTNE FS,%TMSFR ;Formatter ready? + TTNN FS,%TMSOL ;Transport on line + JRST MGERR ;No or no, can't do operation + TTNE FS,%TMSWL ;Transport write locked? + JRST MGERR ;Shouldn't happen, we checked at open. +];IFN TM03S + MOVEM W,MGUNIT ;Note active unit + SKIPE MTCEFW(W) ;Check # of EOF's already written + IFSKP. ;None. Need to write two + AOS MSCMDC(W) ;Kludge so MGWEOF will return here. + AOS MTCEFW(W) ;Increment EOF count + PUSHJ Q,MGWEOF ;Write an EOF + ENDIF. + MOVE A,MTCEFW(W) ;Get EOF count + SOSLE A ;Check for at least two EOF's written + IFSKP. ;No, need one more on tape + AOS MSCMDC(W) ;Again, force MGWEOF to return + AOS MTCEFW(W) ;Incr EOF count + PUSHJ Q,MGWEOF ;Write EOF + ENDIF. + MOVE A,MSRAC(W) ;Get transport software status + TLNE A,%MANWT ;Are we supposed to back up over last EOF? + IFSKP. + AOS MSCMDC(W) ;Yes. Force MGSPRF to return, then... + PUSHJ Q,MGSPRF ; ...do space reverse file command + ENDIF. + MOVSI A,%MANWT ;Note what we've done + IORM A,MSRAC(W) + JRST MGCMDR ;Leave through general exit routine + +;Write one EOF mark on tape +; +MGWEOF: PUSHJ Q,MGGXPT ;Set up transport for IO +IFN TM10P,[ + TXNE J,%T1STH\%T1SRW\%T1SWL ;Hung, rewinding, or write locked... + JRST MGERR ; ..lose +] +IFN TM03S,[ + TTNE FS,%TMSFR ;Formatter ready? + TTNN FS,%TMSOL ;Transport on line + JRST MGERR ;No or no, can't do operation + TTNE FS,%TMSWL ;Transport write locked? + JRST MGERR ;Shouldn't happen, we checked at open. +] + MOVEM W,MGUNIT ;Remember active unit +IFN TM10P,[ + MOVE B,MTCONO(W) ;Get CONO word for this unit + CONO MTC,MWEOF(B) ;Execute Write EOF function +] +IFN TM03S,[ + MOVEI B,%TM1IE\%TMWTM ;Write tape mark, enable interrupts + IOWRI B,%TMCS1 ;Do it +] + PUSHJ Q,MGWTJD ;Wait around till command is complete + IFNSK. + TTNE FS,%TMSES + JRST MGERR + ENDIF. + MOVSI A,%MAMSO + IORM A,MSRAC(W) ;Note tape movement in software status + JRST MGCMDR ;Return through general exit routine + +;Get transport and controller status +; +MGSTAT: PUSHJ Q,MGGXPT + JRST MGCMDR + +;Write some blank space +; +MGW3IN: PUSHJ Q,MGGXPT +IFN TM10P,[ + TXNE J,%T1STH\%T1SRW\%T1SWL ;Hung, rewinding, or write locked... + JRST MGERR +] +IFN TM03S,[ + TTNE FS,%TMSFR ;Formatter ready? + TTNN FS,%TMSOL ;Transport on line + JRST MGERR ;No or no, can't do operation + TTNE FS,%TMSWL ;Transport write locked? + JRST MGERR ;Shouldn't happen, we checked at open. +];IFN TM03S + MOVEM W,MGUNIT ;Note active transport +IFN TM10P,[ +;TM10 can't just write blank space, it has to write blank space followed +; by a data record + IFN TM10B,[ + SETZM MIOWD ;Tell TM10 to write 1-word record + DATAO MTS,[MICWA] + ] + IFN TM10A,[ + MOVE A,[-1,,MGVTC-1] ;1-word record + MOVEM A,MIOWD + PUSHJ Q,MGDCSO + ] + MOVE B,MTCONO(W) + CONO MTC,MW3IN(B) ;Write date record preceeded by 3-in gap +];IFN TM10P +IFN TM03S,[ + MOVEI B,%TM1IE\%TMER3 ;Erase 3 inches command, enable interrupts + IOWRI B,%TMCS1 ;Do it +];IFN TM03S + PUSHJ Q,MGWTJD ;Wait... + JFCL ;Ignore errors (really should check kind) +IFN TM10P,JRST MGSPRR ;Now space record reverse over the bogus record +IFN TM03S,JRST MGCMDR ;TM03 does it right + + +SUBTTL .MTAPE UUO + +;.MTAPE AC, +; AC/ CHNM,,COMMAND +; COMMAND/ COUNT,,FUNCTION + +;Called with J/ AC field from UUO + +AMTAPE: XCTR XR,[HLRZ R,(J)] ;Get IO channel from user + TRNE R,-NIOCHN ;Legal channel? + JRST ILUUO ;Lose + HRRZM R,UUAC(U) ;Cause errors to report on the correct channel + ADDI R,IOCHNM(U) ;Form IOCHNM pointer + HRRZ A,(R) ; A: CLSTB/IOTTB index + CAIL A,MTUAIX ; Min index for tape + CAILE A,MTBOX ; Max + POPJ P, ; Laconic error reportage. + LDB W,[MTXP(R)] ;Get transport number + CAME U,MTUSR(W) ;Same user? + POPJ P, ;No, give up + UMOVE A,(J) ;Get Channel,,Command from user + MOVEM A,MTMTAP(W) ;Save it + HRRZS A ;Get user address of Count,,Function word + PUSHJ P,MTIECK ;Check transport for error states + UMOVE A,(A) ;Get Count,,Function from user + HRRZM A,MTMFNC(W) ;Store function + HLREM A,MTMCNT(W) ; and count + SKIPN MTMCNT(W) ;Count of zero always means one, for + AOS MTMCNT(W) ; compatibility with the old code. + HRRZS A ;Just Function + CAIL A,NMTAPC ;Command in range? + POPJ P, ;No... + AOS (P) ;Command OK, skip return + JRST @MTAPDT(A) ;Go do command + +MTAPDT: MTHANG ;0 Hang till tape motion done + MTRWND ;1 Rewind + MTRWDM ;2 Rewind and dismount + MTWEOR ;3 Write EOR if appropriate + MTW3IN ;4 Write 3 inches of blank tape + MTWEOF ;5 Write EOF + MTSPR ;6 Space records + MTSPF ;7 Space files + MTSPEOT ;10 Space to EOT + MTSTOP ;11 Abort all operations immediately + MTSBKS ;12 Set block size (to COUNT) + MTRBKS ;13 Read block size (to AC) +IFN 0,[ + MTRTSW ;14 Read Transport Information (to AC) + MTRTEW ;15 Read Tape Error Word (to AC) +] +NMTAPC==.-MTAPDT + +;Set block size for write +; +MTSBKS: MOVE A,MTMCNT(W) ;Desired blocksize + CAIL A,4 ;Check reasonableness + CAILE A,2000 + SOSA (P) ;Fail if too big or too small + MOVEM A,MTBLKS(W) ;OK, change write-buffer size + POPJ P, + +;Read current write blocksize +; +MTRBKS: MOVE A,MTBLKS(W) ;Get current write block size + JRST APTUAJ ;Return it + +;Hang until all motion finished +; +MTHANG: SKIPLE MSCMDC(W) ;Check count of queued commands + PUSHJ P,UFLS ;Wait if there are any + JRST MTIECK ;Done, check for errors and return + +;Rewind, Rewind and dismount +; +MTRWND: SKIPA B,[MGRWND] ;Get "REWIND" PI level command +MTRWDM: MOVEI B,MGRWDM ; or "REWIND and DISMOUNT" if appropriate + SKIPE MSCRW(W) ;Writing? + JRST MTSOSP ;Yes, error. Go undo skip rtn and exit + MOVSI A,%MAREW ;Note rewinding in software status + IORM A,MSRAC(W) + JRST MTCMD ;Go queue command for PI level + + +;"Write End of Record" +; This is really the FORCE system call, or should be. +; +MTWEOR: SKIPG MTMDN(W) ;MP level have an active buffer? + POPJ P, ;No, nothing to do + SKIPE MSCRW(W) ;Writing? + JRST MTWBFD ;Yes, go write buffer to tape +MTSOSP: SOS (P) ;Not writing, error. Undo skip return + POPJ P, ;Return + +;Write EOF +; +MTWEOF: SKIPN MSCRW(W) ;Writing? + JRST MTSOSP ;No, can't write EOF. Take error exit + PUSHJ P,MTWEOR ;Flush current buffer, if any + MOVEI B,MGWEOF ;Get PI level EOF routine + AOS MTCEFW(W) ;Increment count of EOF's written + MOVSI TT,%MANWT ;Flag something written on tape + ANDCAM TT,MSRAC(W) + JRST MTCMD ;Queue MGWEOF command for PI level + +;Write blank tape +; +MTW3IN: SKIPN MSCRW(W) ;Error if tape not open for write + JRST MTSOSP + MOVEI B,MGW3IN ;Get PI level command + SETZM MTCEFW(W) ;No EOF's since last record + MOVSI TT,%MANWT + ANDCAM TT,MSRAC(W) ;Note written something to tape + JRST MTCMD ;Go queue command for PI + +;Space records, +=forward, -=back +; +MTSPR: SKIPE MSCRW(W) ;Not allowed if writing + JRST MTSOSP + PUSHJ P,MTFLRA ;Flush read-ahead, find out how far off we are + ADD B,C ;Get records tape is ahead of user (EOF=record) + MOVNS B ;Subtract this from user's request + ADDB B,MTMCNT(W) ;Adjust count + JUMPE B,CPOPJ ;If count is now zero, we are done +MTSPR1: PUSHJ P,MTCNTR ;Update user's copy in case PCLSR + JUMPG B,MTSPFR ;Space forward + MOVEI B,MGSPRR ;Get SPACE REVERSE command + PUSHJ P,MTCMD ;Queue it + AOSGE B,MTMCNT(W) ;Increment count, check if done + JRST MTSPR1 ;More + POPJ P, ;No more + +MTSPFR: MOVEI B,MGSPFR ;Get SPACE FORWARD command + PUSHJ P,MTCMD ;Queue it + SOSLE B,MTMCNT(W) ;Decr count, check if done + JRST MTSPR1 ;More + POPJ P, + +;This routine flushes readahead. Call before doing a spacing operation +; this doesn't actually undo the effect on the drive of the read-ahead. +; It does make sure that read-ahead's effect can't change, then returns +; in B the number of records ahead (non-negative) and in C the number of +; EOF's ahead (0 or 1). If called twice it will return zero the second +; time. Be sure to update your parameters. +; +MTFLRA: PUSHJ P,MTCNTR ;Make sure user space is writable first + MOVSI B,%MASTP + MOVSI T,%MARAC + IORM B,MSRAC(W) ;Tell PI-level read routine to stop reading + TDNE T,MSRAC(W) ;Wait until PI level actually stops + PUSHJ P,UFLS + ANDCAM B,MSRAC(W) ;Turn off %MASTP, things are now quiet + SKIPLE MSCMDC(W) ;Make sure PI level is completely inactive + PUSHJ P,UFLS ;Wait if necessary + MOVE B,MSNBOL(W) ;Get # bufs on read list (='s # records ahead) + LDB C,[.BP (%MAEFA),MSRAC(W)] ;1 if EOF read ahead + MOVSI T,%MAEFA ;Clear read-ahead EOF + ANDCAM T,MSRAC(W) + JRST MTCBFF ;Go flush read-ahead buffers + +;Space files, + = forward, - = back +MTSPF: SKIPE MSCRW(W) ;Not allowed if writing + JRST MTSOSP + PUSHJ P,MTFLRA ;Flush read-ahead + MOVN B,C ;Number of files tape is ahead of user + ADDB B,MTMCNT(W) ;Adjust desired count + JUMPE B,CPOPJ ;If now zero we are done +MTSPF1: PUSHJ P,MTCNTR ;Update user's count in case of PCLSR + JUMPG B,MTSPFF ;Go do forward if needed + MOVEI B,MGSPRF ;Get space reverse file command + PUSHJ P,MTCMD ;Queue it + AOSGE B,MTMCNT(W) ;Done? + JRST MTSPF1 ;Nope + POPJ P, + +MTSPFF: MOVEI B,MGSPFF ;Get space forward file command + PUSHJ P,MTCMD ;Do it + SOSLE B,MTMCNT(W) ;Count down + JRST MTSPF1 ; till done + POPJ P, + +;Update user's FUNCTION,,COUNT word in case he's PCLSR'd +; +MTCNTR: HRRZ A,MTMTAP(W) + MOVE T,MTMFNC(W) + HRL T,MTMCNT(W) + XCTR XW,[MOVEM T,(A)] + POPJ P, + +;Get Controller status words to I,J +; +MTSTAT: SKIPLE MSCMDC(W) ;Wait till commands queued to PI level are done + PUSHJ P,UFLS + MOVEI B,MGSTAT ;GET STATUS command + PUSHJ P,MTCMD ;Give to PI + SKIPLE MSCMDC(W) ;Wait till done + PUSHJ P,UFLS + MOVE I,MGCMTC(W) + MOVE J,MGCMTS(W) + POPJ P, + +;Go to EOT +; +MTSPEOT:MOVEI B,MGSEOT ;Get SPACE-TO-LOGICAL-EOT command + JRST MTCMD ;Queue it. Note read-ahead doesn't matter here + +;Stop whatever we are doing right now +; Very brute-force - throws away all pending commands, read-ahead buffers, etc. +; +MTSTOP: CONO PI,UTCOFF ;We are going to mess with buffer lists + SETZM MSCMDC(W) ;Poof, no more commands + MOVE Q,[-MGQDLL,,MGQD0-1] ;Reset Q PDL pointer to base of stack + MOVE T,MSLCTB + IMUL T,W + ADD Q,T + MOVEM Q,MGQDLP(W) + MOVE Q,[-MSCBL-1,,MSCB0-1] ;Reset command queue input pointer + ADD Q,T + MOVEM Q,MTCMBP(W) + MOVE Q,[4400,,MSCB0-1] ;Reset command queue output pointer + ADD Q,T + MOVEM Q,MGCMBP(W) + SKIPL A,MTMDN(W) ;Buffer active at MP level? + PUSHJ P,IMEMR ;Yes, release it + SETOM MTMDN(W) ;No buffer active at MP level + SETZM MSMPRP(W) ;Zero MP pointer into current buffer + SETZM MSMPRC(W) ;Zero count of available words in buffer + PUSHJ P,MTCBFF ;Flush any buffers queued for PI level + CAME W,MGUNIT ;Is interrupt level waiting for this unit? + JRST UTCONJ ;No, all set + SETOM MGUNIT ;Yes, say no unit waiting for interrupt. + ;(Makes interrupt go away w/out doing anything) +IFN TM10P,[ + CONI MTC,I ;See what drive controller thinks it's using + LDB B,[MUNITF,,I] + CAME W,B ;Same as the drive we're clearing? + JRST UTCONJ ;If not same unit, don't do anything + MOVE B,MTCONO(W) ;Yes, abort operation in progress + CONO MTS,31 ;Stop the tape + CONO MTC,(B) ;Clear interupts +];IFN TM10P +IFN TM03S,[ + IORDI B,%TMTC + ANDI B,7 ;Get selected transport + CAME W,B ;Same? + JRST UTCONJ + PUSHJ P,TMINIC ;Yes, go reinit controller +];IFN TM03S + SKIPGE A,MGCABN(W) ;Any buffers active at PI level? + JRST UTCONJ ;No + PUSHJ P,IMEMR ;Yes, return buffer to system + SETOM MGCABN(W) ;Say no buffer active at PI level + JRST UTCONJ ;Leave + + + + diff --git a/src/system/rh10.defs26 b/src/system/rh10.defs26 new file mode 100755 index 00000000..15f68e27 --- /dev/null +++ b/src/system/rh10.defs26 @@ -0,0 +1,230 @@ +.AUXIL + +;ALLOW USER TO USE SYMBOLS IN OTHER WAYS IF HE WISHES. +;BUT NORMALLY, DEFSYM FOO==BAR DOES FOO==BAR WITH ERROR CHECK. + +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ + $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` +] +.ISTOP +TERMIN TERMIN + +IFLE .MLLIT,.ERR .MLLIT MUST BE 1; SETTING IT TO 1. +.MLLIT==1 +$$TEMP==1 +];IF Not DEFined DEFSYM +.ELSE $$TEMP==0 + + +;DISK PHYSICAL PARAMETERS (RH10 CONTROLLER) + +DEFSYM NCYLS==406. ;# CYLINDERS NORMALLY USED +DEFSYM XCYLS==411.-NCYLS ;# CYLINDERS FOR SPARES, HACKS, ETC. +DEFSYM NHEDS==19. ;# TRACKS/CYLINDER +DEFSYM NSECS==20. ;# SECTORS/TRACK +DEFSYM SECBLK==8 ;# SECTORS/BLOCK +DEFSYM NBLKSC==NHEDS*NSECS/SECBLK ;# BLOCKS/CYLINDER +DEFSYM NBLKS==NCYLS*NBLKSC ;# BLOCKS NORMALLY USED +DEFSYM XBLKS==XCYLS*NBLKSC ;# BLOCKS FOR HACKS +DEFSYM TBLKS==NBLKS+XBLKS ;TOTAL BLOCKS + +DEFSYM NTUTBL==2 ;2 BLOCKS PER TUT +DEFSYM DECADE==NBLKSC ;NUMBER OF BLOCKS TO ALLOCATE AT A TIME + ;QSWAPA AND QLASTB MUST BE MULTIPLES OF THIS. + ;DECADE SIZE = CYLINDER SIZE FOR KLFEDR'S SAKE +DEFSYM DSK=270 ;I/O DEVICE NUMBER OF RH10 + +;CONI - LEFT HALF (ERROR BITS ONLY) + +DEFSYM %HID22==4000,, ;4.3 1=>22-BIT DATA CHANNEL, 0=>18-BIT +DEFSYM %HIILF==400,, ;3.9 ILLEGAL FUNCTION CODE IN CONTROL REGISTER +DEFSYM %HISDE==200,, ;3.8 SELECTED DRIVE PREVIOUS ERROR NOT RESET +DEFSYM %HIDPE==4,, ;3.3 CHANNEL DATA PARITY ERROR +DEFSYM %HICPE==2,, ;3.2 CHANNEL CONTROL WORD PARITY ERROR +DEFSYM %HINXM==1,, ;3.1 CHANNEL NXM ERROR + +;CONI - RIGHT HALF + +DEFSYM %HIBPE==400000 ;2.9 DATA BUSS PARITY ERROR +DEFSYM %HIEXC==200000 ;2.8 "EXCEPTION" IN DRIVE DURING DATA TRANSFER +DEFSYM %HICER==100000 ;2.7 CHANNEL ERROR (OR OF 3 BITS IN LH) +DEFSYM %HICWW==040000 ;2.6 CONTROL WORD HAS BEEN WRITTEN +DEFSYM %HIOVR==020000 ;2.5 OVER-RUN (MEMORY DATA LATE) +DEFSYM %HIDRE==010000 ;2.4 DRIVE RESPONSE ERROR - NO RESPONSE FROM DRIVE +DEFSYM %HIILC==004000 ;2.3 ILLEGAL COMMAND OR REGISTER ACCESS ERROR +DEFSYM %HIPWR==002000 ;2.2 POWER FAIL +DEFSYM %HICOV==000200 ;1.8 CONTROL BUS OVER-RUN +DEFSYM %HIRAE==000100 ;1.7 REGISTER ACCESS ERROR (ONLY IF INTR ENB) +DEFSYM %HIATN==000040 ;1.6 ATTENTION (INTERRUPTS) +DEFSYM %HIBSY==000020 ;1.5 CONTROL BUSY WITH DATA TRANSFER +DEFSYM %HIDON==000010 ;1.4 DATA TRANSFER DONE, NORMAL OR ERROR + ;1.1-1.3 PIA AS USUAL +DEFSYM %HIERR==736300 ;CONI ERROR BITS + +;CONO + + ;2.7-2.9 CLEAR CORRESPONDING ERROR BITS +DEFSYM %HOWCW==040000 ;2.6 WRITE CONTROL WORD + ;2.3-2.5 CLEAR CORRESPONDING ERROR BITS +DEFSYM %HORST==002000 ;2.2 RESET THE CONTROLLER + ;1.8 CLEARS CORRESPONDING ERROR BIT +DEFSYM %HORAE==000100 ;1.7 ENABLE RAE TO INTERRUPT +DEFSYM %HOATN==000040 ;1.6 ENABLE ATTENTION TO INTERRUPT +DEFSYM %HOSTP==000020 ;1.5 STOP DATA TRANSFER, CLR BSY, SET DONE + ;1.4 CLEARS CORRESP BIT (DONE) + ;1.1-1.3 SET PIA +DEFSYM %HOCLR==734210 ;CONO TO CLEAR ALL ERROR BITS + +;CONTROLLER REGISTER NUMBERS (LH OF DATAO) + +DEFSYM %HRLOD==1_13 ;4.3 BIT TO SAY "LOAD SELECTED REGISTER" +DEFSYM %HRCTL==40_14 ;CONTROL REGISTER +DEFSYM $HCDRV==.BP <7,,> ;3.1-3.3 DRIVE SELECT FIELD +DEFSYM $HCICWA==.BP 077700 ;1.7-2.6 INITIAL CONTROL WORD ADDR + ;AS USUAL, 1.7 IS REALLY THE WRITE EVEN PARITY BIT + ;1.1-1.6 FUNCTION CODE (%HMxxx) AND GO BIT +DEFSYM %HRBUF==50_14 ;DATA BUFFER REGISTER (MAINTENANCE) +DEFSYM %HRIAD==44_14 ;INTERRUPT ADDRESS REGISTER + ;3.2 1=>KI-10 MODE, 0=>KA-10 MODE + ;1.1-1.9 9-BIT VECTOR ADDRESS (KI) +DEFSYM %HRRAE==54_14 ;REGISTER ACCESS ERROR REGISTER + ;DATAI 1.1-1.8 RAE DRIVE 0-7 + ;DATAO 1.1-1.8 CLEAR THAT BIT +DEFSYM %HRCBF==74_14 ;CHANNEL BUFFER + +;COMMANDS +; COMMANDS THAT DO I/O ARE PUT IN %HRCTL ALONG WITH $HCICWA +; OTHER COMMANDS ARE STORED INTO %HRDCL +; IN EITHER CASE $HCDRV SAYS WHICH DRIVE + +DEFSYM %HMNOP==0 ;NO OPERATION +DEFSYM %HMUNL==3 ;UNLOAD (DOES PACK FLY OFF?) +DEFSYM %HMREC==7 ;RECALIBRATE +DEFSYM %HMCLR==11 ;DRIVE CLEAR (RESET ERRORS ETC.) +DEFSYM %HMRLS==13 ;DRIVE RELEASE (DUAL PORT) +DEFSYM %HMSRC==31 ;SEARCH (FOR R.P.S.) +DEFSYM %HMWCH==51 ;WRITE CHECK -- DOESN'T WORK (DEC BRAIN DAMAGE) +DEFSYM %HMWCF==53 ;WRITE CHECK FORMAT (HEADER AND DATA) -- DOESN'T WORK +DEFSYM %HMWRT==61 ;WRITE DATA +DEFSYM %HMWHD==63 ;WRITE HEADER AND DATA (FORMAT THE PACK) +DEFSYM %HMRED==71 ;READ DATA +DEFSYM %HMRHD==73 ;READ HEADER AND DATA +DEFSYM %HMSEK==5 ;SEEK TO CYLINDER +DEFSYM %HMOFS==15 ;OFFSET HEADS SLIGHTLY +DEFSYM %HMCEN==17 ;RETURN HEADS TO CENTERLINE +DEFSYM %HMACK==23 ;ACKNOWLEDGE MOUNTING OF PACK (REQUIRED BEFORE I/O) +DEFSYM %HMRDP==21 ;"READ-IN PRESET" + +;STANDARD FIELDS IN DRIVE REGISTERS + + ;3.1-3.3 DRIVE NUMBER ($HCDRV) +DEFSYM %HDCBT==002000 ;4.2 CONTROL BUS TIMEOUT +DEFSYM %HDPAR==001000 ;4.1 MASS BUS CONTROL PARITY ERROR +DEFSYM %HDDLT==000400 ;3.9 DATA LATE (NEED 3 US BETWEEN DATAO AND DATAI) +DEFSYM %HDILC==000200 ;3.8 ILLEGAL COMMAND +DEFSYM %HDERR==003600 ;ALL BITS FOR ERRORS IN TALKING TO DRIVE + ;DRIVE-DEPENDENT DATA IS IN LOW 16 BITS (1.1-2.7) + +;DRIVE REGISTERS (NUMBER IN LH OF DATAO) + +DEFSYM %HRDCL==0_14 ;DRIVE CONTROL REGISTER + ;1.1-1.6 COMMAND (%HMxxx) 1.1=GO BIT +DEFSYM %HCDVA==1_11. ;2.3 DRIVE AVAILABLE + +DEFSYM %HRSTS==1_14 ;STATUS REGISTER + ;1.1-1.6 BITS ON DURING HEAD LOAD SEQUENCE +DEFSYM %HSVV==100 ;1.7 VOLUME VALID. SET BY %HMACK, CLEARED BY + ; DRIVE TURN ON. 0 => PACK MAY HAVE BEEN CHANGED +DEFSYM %HSRDY==200 ;1.8 DRIVE READY +DEFSYM %HSDPR==400 ;1.9 "DRIVE PRESET" = CONNECTED TO THIS CONTROLLER +DEFSYM %HSPGM==1000 ;2.1 "PROGRAMMABLE" = EITHER CTRLR CAN CONNECT +DEFSYM %HSLST==2000 ;2.2 LAST SECTOR TRANSFERRED +DEFSYM %HSWRL==4000 ;2.3 WRITE LOCK +DEFSYM %HSMOL==10000 ;2.4 MEDIUM ON-LINE +DEFSYM %HSPIP==20000 ;2.5 POSITIONING IN PROGRESS +DEFSYM %HSERR==40000 ;2.6 BIT ON %HRER1, %HRER2, OR %HRER3 +DEFSYM %HSATN==100000 ;2.7 ATTENTION - ERROR, POSITIONING COMPLETE, + ; STARTUP COMPLETE, OR DRIVE AVAILABLE + +DEFSYM %HRER1==2_14 ;ERROR REGISTER 1 + ;GENERALLY THESE BITS ARE ONLY RESET BY %HMCLR + ;1.1 ILLEGAL COMMAND IN %HRDCL + ;1.2 ATTEMPT TO ACCESS NON-EXISTENT DRIVE REGISTER + ;1.3 ATTEMPT TO WRITE IN DRIVE REGISTER WHILE DRIVE BUSY + ;1.4 PARITY ERROR ON MASSBUS + ;1.5 FORMAT ERROR (PACK & CPU NOT BOTH 16- OR BOTH 18-BIT) + ;1.6 WRITE CLOCK FAIL +DEFSYM %H1ECH==100 ;1.7 ECC HARD ERROR (NOT 11-BIT BURST) + ;1.8 HEADER COMPARE ERROR + ;1.9 HEADER CRC ERROR + ;2.1 ADDRESS OVERFLOW + ;2.2 INVALID ADDRESS +DEFSYM %H1WLK==4000 ;2.3 ATTEMPT TO WRITE WHILE WRITE-LOCKED + ;2.4 DRIVE TIMING ERROR. MAY DE-FORMAT THE TRACK. + ;2.5 OPERATION NOT COMPLETE (3 REVS NO ACTION) + ;2.6 DRIVE UNSAFE - WRITE LOCK OR FIELD SERVICE +DEFSYM %H1ECC==100000 ;2.7 DATA CHECK, ECC COMPUTATION INITIATED +DEFSYM %H1SOF==110730 ;SOFT ERRORS + +DEFSYM %HRMNT==3_14 ;MAINTENANCE REGISTER (SEE RP04 MAINT MANUAL) + +DEFSYM %HRATN==4_14 ;ATTENTION SUMMARY REGISTER (NOT REALLY PER-DRIVE) + ;1.1-1.8 %HSATN DRIVES 0-7 + ;CLEARED BY ACCESSING DRIVE OR WRITING A 1 + +DEFSYM %HRADR==5_14 ;DESIRED SECTOR/TRACK ADDRESS +DEFSYM $HATRK==.BP 17400 ;TRACK 0-22 OCTAL +DEFSYM $HASEC==.BP 37 ;SECTOR 0-23 OCTAL (128 WORDS EACH) + ;NOTE THESE FIELDS ARE 8-BITS EACH + +DEFSYM %HRLAH==7_14 ;LOOK AHEAD (READ ONLY) + ;NUMBER OF 64'THS OF A SECTOR + +DEFSYM %HRTYP==6_14 ;DRIVE TYPE (RO) + ;1.1-1.9 DRIVE TYPE NUMBER (20 FOR "RP04") + ;2.3 DUAL-PORT DRIVE + ;2.5 MOVING HEAD + ;2.6 TAPE + ;2.7 NOT BLOCK ADDRESSED + +DEFSYM %HRSER==10_14 ;DRIVE SERIAL NUMBER (RO) + +DEFSYM %HROFS==11_14 ;HEAD OFFSET + ;1.1-1.8 OFFSET CODE + ;1.9-2.7 MISC CRUFTIES + +DEFSYM %HRCYL==12_14 ;DESIRED CYLINDER ADDRESS + ; 0 TO 410 DECIMAL + +DEFSYM %HRCCY==13_14 ;CURRENT CYLINDER ADDRESS + +DEFSYM %HRER2==14_14 ;ERROR REGISTER 2 + ;MISC UNSAFE CONDITIONS IN DRIVE + +DEFSYM %HRER3==15_14 ;ERROR REGISTER 3 + ;1.1-1.7 MORE MISC UNSAFES IN DRIVE +DEFSYM %H3SKI==40000 ;2.6 SEEK INCOMPLETE +DEFSYM %H3OFC==100000 ;2.7 OFF CYLINDER + +DEFSYM %HRPOS==16_14 ;ECC POSITION + ;LOCATION OF ERROR BURST WITHIN SECTOR + +DEFSYM %HRPAT==17_14 ;ECC PATTERN + ;11-BIT ERROR BURST + +;DF10-C CHANNEL DEFINITIONS (22-BIT- (KI-) MODE) + +DEFSYM $DFCAD==002600,, ;CURRENT ADDRESS - 1 (IN CONTROL WORD) +DEFSYM $DFWC==261600,, ;- WORD COUNT (IN CONTROL WORD) +DEFSYM $DFLAD==002600,, ;LAST DATA ADDRESS (IN STORED CONTROL WD) +DEFSYM $DFCWA==261600,, ;LAST CONTROL WORD ADDRESS (IN STORED CONTROL WORD) + + + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/rh11.defs48 b/src/system/rh11.defs48 new file mode 100755 index 00000000..f3d1b631 --- /dev/null +++ b/src/system/rh11.defs48 @@ -0,0 +1,289 @@ +; -*- Midas -*- +.AUXIL + +; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + +; For now, must have a disk type defined to get the correct register +; definitions. + +IFNDEF RP06P,RP06P==0 +IFNDEF RP07P,RP07P==0 +IFNDEF RM03P,RM03P==0 +IFNDEF RM80P,RM80P==0 + +IFN RP06P+RP07P+RM03P+RM80P-1,.FATAL Only one disk type allowed in RH11 DEFS + + +;;; Disk RH11 Interrupt vector: +DEFSYM PHVEC==254 ; Interrupts occur on level 6 + ; (high priority) on UBA #1. + +;;; Disk RH11 Unibus register addresses: + +DEFSYM %HRCS1=:776700 ;CTRL AND STATUS 1. + DEFSYM %HXSC== 1_15. ; Special Condition + DEFSYM %HXTRE==1_14. ; Transfer Error + DEFSYM %HXMCP==1_13. ; Mass I/O Control Bus Parity Error + DEFSYM %HXDVA==1_11. ; Drive Available + DEFSYM %HXPSE==1_10. ; Port Select + DEFSYM %HXA17==1_9. ; UB Address Extension Bit 17 + DEFSYM %HXA16==1_8. ; UB Address Extension Bit 16 + DEFSYM %HXRDY==1_7. ; Ready + DEFSYM %HXIE== 1_6. ; Interrupt Enable + DEFSYM $HXCMD==.BP 77 ; Bits 1-5 specify commands. + DEFSYM %HXGO== 1_0. ; GO bit + +;;; Commands with bit 0 (GO) included: + +DEFSYM %HMNOP==0 ; No Operation +DEFSYM %HMUNL==3 ; Unload ("Standby" -- the pack doesn't fly off). +DEFSYM %HMREC==7 ; Recalibrate +DEFSYM %HMCLR==11 ; Drive clear (reset errors etc.) +DEFSYM %HMRLS==13 ; Drive release (dual port) +DEFSYM %HMSRC==31 ; Search (for r.p.s.) +DEFSYM %HMWCH==51 ; Write Check (?doesn't work) +DEFSYM %HMWCF==53 ; Write Check Format, Header and Data (?doesn't work) +DEFSYM %HMWRT==61 ; Write Data +DEFSYM %HMRED==71 ; Read Data +DEFSYM %HMWHD==63 ; Write Header And Data (format the pack) +DEFSYM %HMRHD==73 ; Read Header and Data +IFN RP07P,[ +DEFSYM %HMWTD==65 ; Write Track Descriptor +DEFSYM %HMRTD==75 ; Read Track Descriptor +] +DEFSYM %HMSEK==5 ; Seek to Cylinder +DEFSYM %HMOFS==15 ; Offset Heads Slightly + ; Just sets %HSOFS on RP07 +DEFSYM %HMCEN==17 ; Return Heads To Centerline + ; Just clears %HSOFS on RP07 +DEFSYM %HMACK==23 ; Acknowledge mounting of pack (required before I/O) + ; No-op on RP07 +DEFSYM %HMRDP==21 ; Read-In Preset + +DEFSYM %HRWC=:776702 ;WORD COUNT. + +DEFSYM %HRBA=:776704 ;UNIBUS ADDRESS. + +DEFSYM %HRADR=:776706 ;DESIRED ADDRESS. + DEFSYM $HATRK==.BP 37400 ; Track + DEFSYM $HASEC==.BP 00177 ; Sector + ;; These are the sizes on the RP07 -- other drives are smaller. + ;; This is OK, as most places calculate this as Track_8+Sector + +DEFSYM %HRCS2=:776710 ;CTRL AND STATUS 2. + DEFSYM %HYDLT==1_15. ; Data Late + DEFSYM %HYWCE==1_14. ; Write Check Error + DEFSYM %HYPE== 1_13. ; Parity Error + DEFSYM %HYNED==1_12. ; Non-existant Drive + DEFSYM %HYNEM==1_11. ; %HRBA is NXM during DMA + DEFSYM %HYPGE==1_10. ; Program Error + DEFSYM %HYMXF==1_9. ; Missed Transfer + DEFSYM %HYMDP==1_8. ; Mass Data Bus Parity Error + DEFSYM %HYOR== 1_7. ; Output Ready (for Silo buffer diag.) + DEFSYM %HYIR== 1_6. ; Input Ready (for Silo buffer diag.) + DEFSYM %HYCLR==1_5. ; Controller Clear + DEFSYM %HYPAT==1_4. ; Parity Test + DEFSYM %HYBAI==1_3. ; Unibus Address Increment Inhibit + DEFSYM $HYDSK==.BP 7 ; Bits 2-0 are the Unit Select. + +DEFSYM %HRSTS=:776712 ;DRIVE STATUS. + DEFSYM %HSATN==1_15. ; Attention Active + DEFSYM %HSERR==1_14. ; Error + DEFSYM %HSPIP==1_13. ; Positioning In Progress + DEFSYM %HSMOL==1_12. ; Medium On-Line + DEFSYM %HSWRL==1_11. ; Write Locked + DEFSYM %HSLST==1_10. ; Last Sector Transferred + DEFSYM %HSPGM==1_9. ; Programmable + DEFSYM %HSDPR==1_8. ; Drive Present + DEFSYM %HSRDY==1_7. ; Drive Ready + DEFSYM %HSVV== 1_6. ; Volume Valid +; These are RP04-only bits in %HRSTS +; DEFSYM %HSDE1==1_5. ; Difference Equals 1 +; DEFSYM %HSL64==1_4. ; Difference Less Than 64 +; DEFSYM %HSGRV==1_3. ; Go Reverse +; DEFSYM %HSDIG==1_2. ; Drive To Inner Guard Band +; DEFSYM %HSF20==1_1. ; Drive Forward 20in/sec +; DEFSYM %HSF5== 1_0. ; Drive Forward 5in/sec +IFN RP07P,[ + DEFSYM %HSILS==1_2. ; Interleaved Sectors + DEFSYM %HSWRN==1_1. ; Early Warning + DEFSYM %HSOFS==1_0. ; Offset Mode +] + +DEFSYM %HRER1=:776714 ;ERROR 1. + DEFSYM %H1ECC==1_15. ; Data Check + DEFSYM %H1UNS==1_14. ; Unsafe + DEFSYM %H1OPI==1_13. ; Operation Incomplete + DEFSYM %H1DTE==1_12. ; Drive Timing Error + DEFSYM %H1WLK==1_11. ; Write Lock Error + DEFSYM %H1IAE==1_10. ; Invalid Address Error + DEFSYM %H1AOE==1_9. ; Address Overflow Error + DEFSYM %H1CRC==1_8. ; Header CRC Error + DEFSYM %H1HCE==1_7. ; Header Compare Error + DEFSYM %H1ECH==1_6. ; ECC Hard Error + DEFSYM %H1WCF==1_5. ; Write Clock Fail + DEFSYM %H1FER==1_4. ; Format Error + DEFSYM %H1PAR==1_3. ; Parity Error + DEFSYM %H1RMR==1_2. ; Register Modification Refused + DEFSYM %H1ILR==1_1. ; Illegal Register + DEFSYM %H1ILF==1_0. ; Illegal Function + +DEFSYM %HRATN=:776716 ;ATTENTION SUMMARY. + ; Each bit 7-0 corresponds to a drive asserting ATA. + +DEFSYM %HRLAH=:776720 ;LOOK AHEAD. + ; 2.2 - 1.7 Sector Count. + ; 1.6 - 1.5 Encoded Extension Field. + +DEFSYM %HRBUF=:776722 ;DATA BUFFER. + +DEFSYM %HRMNT=:776724 ;MAINTENANCE. + +DEFSYM %HRTYP=:776726 ;DRIVE TYPE. + ; 2.7 NOT BLOCK ADDRESSED + ; 2.6 TAPE + ; 2.5 Moving Head (better be a 1!!) + ; 2.3 Drive Request Required + ; 1.9 - 1.1 Drive Type Number: + ; RP04 = 20, RP05 = 21, + ; RP06 = 22, RM03 = 24, + ; RM80 = 26, RP07 = 42 + +DEFSYM %HRSER=:776730 ;SERIAL NUMBER. + +DEFSYM %HROFS=:776732 ;OFFSET. + ; 2.9-2.8 Unused + ; 2.7 Sign Change (RP06 only) + ; 2.7 Command Modifier (RP07 only) + ; Must be set before %HMWHD, %HMWTD or %HMRTD + ; 2.6 Move Track Descriptor (RP07 only) + ; 0 = 128. bit track descriptor + ; 1 = 344. bit track descriptor + ; 2.4 Format Bit (1=16, 0=18) + ; 2.3 ECC Inhibit + ; 2.2 Header Compare Inhibit + ; 2.1 Skip Sector Inhibit (RM 16bit only) + ; 1.9 Unused + ; + ; 1.8 - 1.1 Unused on RP07 + ; RP07 doesn't support offsets + ; + ; RP06 Offsets + ; 1.8 - 1.1 Offset Info + ; +400 u" 00010000 + ; -400 u" 10010000 + ; +800 u" 00100000 + ; -800 u" 10100000 + ; +1200 u" 00110000 + ; -1200 u" 10110000 + ; Centerline 00000000 + ; + ; RMxx Offsets + ; 1.1-1.7 Unused + ; 1.8 Offset Direction + ; 0 - Away from spindle + ; 1 - Towards spindle + +DEFSYM %HRCYL=:776734 ;DESIRED CYLINDER. + +IFN RP06P,[ + +DEFSYM %HRCCY=:776736 ;CURRENT CYLINDER. + +DEFSYM %HRER2=:776740 ;ERROR 2. + DEFSYM %H2NHS==1_10. ; No Head Selection + DEFSYM %H2WRU==1_8. ; Write Ready Unsafe + +DEFSYM %HRER3=:776742 ;ERROR 3. + DEFSYM %H3OFC==1_15. ; Off Cylinder + DEFSYM %H3SKI==1_14. ; Seek Incomplete (also sets UNS+ATA+PIP+RDY) + DEFSYM %H3DCL==1_6. ; DC power low (or perhaps AC?) + DEFSYM %H3ACL==1_5. ; AC power low (or perhaps DC?) + ; (the documentation is confused about + ; which is which.) + +];RP06P + +IFN RP07P,[ + +DEFSYM %HRCCY=:776736 ;CURRENT CYLINDER. + +DEFSYM %HRER2=:776740 ;ERROR 2. + DEFSYM %H2PRG==1_15. ; Program Error + DEFSYM %H2CRM==1_14. ; Control ROM parity error + DEFSYM %H2H88==1_13. ; 8080 in drive is hung + ;; DEC unimaginatively calls the following three bits + ;; READ/WRITE UNSAFE 1, 2 and 3. + DEFSYM %H2WU3==1_12. ; Write current when no write in progress + DEFSYM %H2WU2==1_11. ; More than one head selected + DEFSYM %H2WU1==1_10. ; No write transitions during a write + DEFSYM %H2WOV==1_9. ; Write Overrun + DEFSYM %H2WRU==1_8. ; Write Ready Unsafe + DEFSYM $H2COD==.BP 377 ; Error Code + ;; Error codes are: + ;; 012 Seek operation too long. + ;; 013 Guard band detected during seek operation. + ;; 014 Seek operation overshoot. + ;; 104 Guard band detection failure during recalibrate operation. + ;; 105 Reference gap or guard band pattern detection failure during + ;; recalibrate operation. + ;; 106 Seek error during recalibrate operation. + ;; 112 Heads have attempted to land on guard band during recalibrate + ;; operation. + +DEFSYM %HRER3=:776742 ;ERROR 3. + DEFSYM %H3BDS==1_15. ; Bad Sector + DEFSYM %H3SKI==1_14. ; Seek Incomplete (see error code in ER2) + DEFSYM %H3DSE==1_13. ; Defect Skip Error + DEFSYM %H3WCF==1_12. ; Write Current Failure + DEFSYM %H3LCF==1_11. ; Logic Control Failure + DEFSYM %H3LBC==1_10. ; Loss of Bit Clock + DEFSYM %H3LCE==1_9. ; Loss of Cylinder Error + DEFSYM %H3X88==1_8. ; 8080 in drive failed to respond to a command + DEFSYM %H3DCK==1_7. ; Device Check + DEFSYM %H3WHD==1_6. ; Index Unsafe (Bad %HMWHD) + DEFSYM %H3DCL==1_5. ; DC Low voltage + DEFSYM %H3SDF==1_4. ; Serdes Data (data buffer timing) Failure + DEFSYM %H3PAR==1_3. ; Data Parity Error during write operation + DEFSYM %H3SYB==1_2. ; Sync Byte error + DEFSYM %H3SYC==1_1. ; Sync Clock failure + DEFSYM %H3RTM==1_0. ; Run timeout + +];RP07P + +IFN RM03P\RM80P,[ +; RM has no Current Cylinder Register, the Error 2 Register is +; in a different place with different bits, and there is no +; Error 3 register + +DEFSYM %HRER2=:776742 ;ERROR 2. + DEFSYM %H2BSE==1_15. ; Bad Sector (sector marked bad on disk) + DEFSYM %H2SKI==1_14. ; Seek Incomplete (also sets UNS+ATA+PIP+RDY) + DEFSYM %H2OPE==1_13. ; Drive address plug was removed + DEFSYM %H2IVC==1_12. ; Invalid Command (really drive not valid) + DEFSYM %H2LSC==1_11. ; LSC Sucks + DEFSYM %H2LBC==1_10. ; Loss of Bitcheck (hardware lossage) + DEFSYM %H2DVC==1_7 ; Device Check (generic hardware lossage) + DEFSYM %H2SSE==1_5 ; Skip Sector found (can't happen in 18bit) + DEFSYM %H2DPE==1_3 ; Data Parity Error in controller + +];RM03P\RM80P + +DEFSYM %HRPOS=:776744 ;ECC POSITION. + +DEFSYM %HRPAT=:776746 ;ECC PATTERN. + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/rm03.defs5 b/src/system/rm03.defs5 new file mode 100755 index 00000000..2704e416 --- /dev/null +++ b/src/system/rm03.defs5 @@ -0,0 +1,41 @@ +; -*- Midas -*- +.AUXIL + +; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + +; Disk Physical Parameters for RM03 + +DEFSYM NCYLS==820. ; # CYLINDERS NORMALLY USED +DEFSYM XCYLS==823.-NCYLS ; # EXTRA CYLINDERS FOR SPARES, HACKS, ETC. +DEFSYM NHEDS==5 ; # TRACKS/CYLINDER +DEFSYM NSECS==30. ; # SECTORS/TRK +DEFSYM SECBLK==8 ; # SECTORS/BLOCK +DEFSYM NBLKSC==NHEDS*NSECS/SECBLK ; # BLKS/CYL +DEFSYM NBLKS==NCYLS*NBLKSC ; TOTAL # REG BLKS +DEFSYM XBLKS==XCYLS*NBLKSC ; # XTRA BLKS +DEFSYM TBLKS==NBLKS+XBLKS ; TOTAL BLKS + +; TUTs are 3 bits per disk block, or 12*1024=12288 disk blocks per TUT +; block. TBLKS works out to be 14814, so it takes 2 blocks to TUT an +; RM03. This leaves plenty of room for the extra words at the beginning of +; the TUT. +DEFSYM NTUTBL==2 ; 2 BLOCKS PER TUT + +; Allocate whole cylinders at a time. +DEFSYM DECADE==NBLKSC ; NUMBER OF BLOCKS TO ALLOCATE AT A TIME. + ; QSWAPA AND QLASTB MUST BE MULTIPLES OF THIS. + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/rm80.defs4 b/src/system/rm80.defs4 new file mode 100755 index 00000000..14b354c9 --- /dev/null +++ b/src/system/rm80.defs4 @@ -0,0 +1,45 @@ +; -*- Midas -*- +.AUXIL + +; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + +; Disk Physical Parameters for RM80 + +; The RM80 actually has 561 cylinders, but it appears that the onboard +; microprocessor diagnostics may scribble on the last two cylinders, so +; we just leave them out of this. + +DEFSYM NCYLS==556. ; # CYLINDERS NORMALLY USED +DEFSYM XCYLS==559.-NCYLS ; # EXTRA CYLINDERS FOR SPARES, HACKS, ETC. +DEFSYM NHEDS==14. ; # TRACKS/CYLINDER +DEFSYM NSECS==30. ; # SECTORS/TRK +DEFSYM SECBLK==8 ; # SECTORS/BLOCK +DEFSYM NBLKSC==NHEDS*NSECS/SECBLK ; # BLKS/CYL +DEFSYM NBLKS==NCYLS*NBLKSC ; TOTAL # REG BLKS +DEFSYM XBLKS==XCYLS*NBLKSC ; # XTRA BLKS +DEFSYM TBLKS==NBLKS+XBLKS ; TOTAL BLKS + +; TUTs are 3 bits per disk block, or 12*1024=12288 disk blocks per TUT +; block. TBLKS works out to be 29172, so it takes 3 blocks to TUT an +; RM80. This leaves plenty of room for the extra words at the beginning of +; the TUT. +DEFSYM NTUTBL==3 ; 3 BLOCKS PER TUT + +; Allocate whole cylinders at a time. +DEFSYM DECADE==NBLKSC ; NUMBER OF BLOCKS TO ALLOCATE AT A TIME. + ; QSWAPA AND QLASTB MUST BE MULTIPLES OF THIS. + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/rp06.defs1 b/src/system/rp06.defs1 new file mode 100755 index 00000000..11dd4dac --- /dev/null +++ b/src/system/rp06.defs1 @@ -0,0 +1,41 @@ +; -*- Midas -*- +.AUXIL + +; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + +; Disk Physical Parameters for RP06 + +DEFSYM NCYLS==812. ; # CYLINDERS NORMALLY USED +DEFSYM XCYLS==815.-NCYLS ; # EXTRA CYLINDERS FOR SPARES, HACKS, ETC. +DEFSYM NHEDS==19. ; # TRACKS/CYLINDER +DEFSYM NSECS==20. ; # SECTORS/TRK +DEFSYM SECBLK==8 ; # SECTORS/BLOCK +DEFSYM NBLKSC==NHEDS*NSECS/SECBLK ; # BLKS/CYL +DEFSYM NBLKS==NCYLS*NBLKSC ; TOTAL # REG BLKS +DEFSYM XBLKS==XCYLS*NBLKSC ; # XTRA BLKS +DEFSYM TBLKS==NBLKS+XBLKS ; TOTAL BLKS + +; TUTs are 3 bits per disk block, or 12*1024=12288 disk blocks per TUT +; block. TBLKS works out to be 38305, so it takes a little more than 3 +; blocks to TUT an RP06. This leaves plenty of room for the extra words at +; the beginning of the TUT. +DEFSYM NTUTBL==4 ; 4 BLOCKS PER TUT + +; Allocate whole cylinders at a time. +DEFSYM DECADE==NBLKSC ; NUMBER OF BLOCKS TO ALLOCATE AT A TIME. + ; QSWAPA AND QLASTB MUST BE MULTIPLES OF THIS. + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/rp07.defs1 b/src/system/rp07.defs1 new file mode 100755 index 00000000..222a2a64 --- /dev/null +++ b/src/system/rp07.defs1 @@ -0,0 +1,41 @@ +; -*- Midas -*- +.AUXIL + +; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + +; Disk Physical Parameters for RP07 + +DEFSYM NCYLS==627. ; # CYLINDERS NORMALLY USED +DEFSYM XCYLS==630.-NCYLS ; # EXTRA CYLINDERS FOR SPARES, HACKS, ETC. +DEFSYM NHEDS==32. ; # TRACKS/CYLINDER +DEFSYM NSECS==43. ; # SECTORS/TRK +DEFSYM SECBLK==8 ; # SECTORS/BLOCK +DEFSYM NBLKSC==NHEDS*NSECS/SECBLK ; # BLKS/CYL +DEFSYM NBLKS==NCYLS*NBLKSC ; TOTAL # REG BLKS +DEFSYM XBLKS==XCYLS*NBLKSC ; # XTRA BLKS +DEFSYM TBLKS==NBLKS+XBLKS ; TOTAL BLKS + +; TUTs are 3 bits per disk block, or 12*1024=12288 disk blocks per TUT +; block. TBLKS works out to be 108360, so it takes 9 blocks to TUT an +; RP07. This leaves plenty of room for the extra words at the beginning of +; the TUT. +DEFSYM NTUTBL==9 ; 9 BLOCKS PER TUT + +; Allocate whole cylinders at a time. +DEFSYM DECADE==NBLKSC ; NUMBER OF BLOCKS TO ALLOCATE AT A TIME. + ; QSWAPA AND QLASTB MUST BE MULTIPLES OF THIS. + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/rp10.defs16 b/src/system/rp10.defs16 new file mode 100755 index 00000000..c5e0de32 --- /dev/null +++ b/src/system/rp10.defs16 @@ -0,0 +1,106 @@ +.AUXIL + +IFNDEF DEFSYM,[ ;ALLOW USER TO USE SYMBOLS IN OTHER WAYS IF HE WISHES. + ;BUT NORMALLY, DEFSYM FOO==BAR DOES FOO==BAR WITH ERROR CHECK. +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ + $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` +] +.ISTOP +TERMIN TERMIN + +IFLE .MLLIT,.ERR .MLLIT MUST BE 1; SETTING IT TO 1. +.MLLIT==1 +$$TEMP==1 +] +.ELSE $$TEMP==0 + + +;DISK PHYSICAL PARAMETERS + +DEFSYM NCYLS==200. ;# CYLINDERS NORMALLY USED (RP02) +DEFSYM MCYLS==400. ;# CYLINDERS NORMALLY USED (RP03) +DEFSYM XCYLS==3 ;# EXTRA CYLINDERS FOR SPARES, HACKS, ETC. +DEFSYM NHEDS==20. ;# TRACKS/CYLINDER +DEFSYM NSECS==10. ;# SECTORS/TRK +DEFSYM SECBLK==8 ;# SECTORS/BLOCK +DEFSYM NBLKSC==NHEDS*NSECS/SECBLK ;# BLKS/CYL +DEFSYM NBLKS==NCYLS*NBLKSC ;TOTAL # REG BLKS (RP02) +DEFSYM MBLKS==MCYLS*NBLKSC ;TOTAL # REG BLKS (RP03) +DEFSYM XBLKS==XCYLS*NBLKSC ;# XTRA BLKS +DEFSYM TBLKS==MBLKS+XBLKS ;TOTAL BLKS + +DEFSYM NTUTBL==1 ;1 BLOCK PER TUT +DEFSYM DECADE==20. ;NUMBER OF BLOCKS TO ALLOCATE AT A TIME + ;QSWAPA AND QLASTB MUST BE MULTIPLES OF THIS +DEFSYM DPC==250 ;I/O DEVICE NUMBER + +;DISK COMMANDS + +DEFSYM DREADC==000000,, ;READ DATA +DEFSYM DWRITC==100000,, ;WRITE DATA + ;OP CODE 2 UNUSED +DEFSYM DWRITH==300000,, ;WRITE HEADER AND DATA (FORMAT PACK) +DEFSYM DSEEKC==400000,, ;POSITION HEADS +DEFSYM DEASEC==500000,, ;CLEAR ATTENTIONS +DEFSYM DNOOPC==600000,, ;SELECT DRIVE +DEFSYM DRCALC==700000,, ;RECALIBRATE DRIVE + +;BYTE POINTERS FOR ABOVE COMMANDS + +DEFSYM DUNFLD==360300,, ;UNIT FIELD (ALL COMMANDS) +DEFSYM DCYL==261000,, ;CYLINDER FIELD (READ,WRIT,WRITH,SEEK) +DEFSYM DCYLXB==200100,, ;EXTRA BIT OF CYLINDER FIELD FOR RP03 +DEFSYM DSURF==210500,, ;SURFACE FIELD (READ,WRIT,WRITH) +DEFSYM DSECT==140400,, ;SECTOR FIELD (READ,WRIT,WRITH) + + ;DATAI FIELDS + + +DEFSYM DUNFLI==410300,, ;UNIT FIELD +DEFSYM DCYLI==311000,, ;CYLINDER FIELD +DEFSYM DCYLXI==130100,, ;EXTRA BIT OF CYLINDER FIELD + +DEFSYM SKINC==100,, ;SEEK INCOMPLETE +DEFSYM ONCYL==40,, ;ON CYLINDER +DEFSYM ONLINE==20,, ;ON LINE +DEFSYM FUNSAF==10,, ;FILE UNSAFE +DEFSYM NSCHDR==4,, ;NO SUCH DRIVE +DEFSYM RDONLY==2,, ;READ ONLY +DEFSYM NOWRIH==1, ;WRITE HEADER LOCKOUT + +DEFSYM RP03BT==2000 ;SELECTED DRIVE IS AN RP03 +DEFSYM SECTI==140500,, + +DEFSYM ALLATT==776 + +;CONO INFORMATION + +DEFSYM DCLEAR==175710 ;CLEAR ALL ERROR CONDITIONS + + +;CONI INFORMATION + +DEFSYM PARER== 4000 +DEFSYM SRCER== 40000 +DEFSYM HRDER==130000 +DEFSYM PROER==402300 +DEFSYM WRTER== 1000 +DEFSYM ALLER==577300 +DEFSYM DONE==10 +DEFSYM BUSY==20 + +;DF10 CHANNEL INFORMATION + +DEFSYM $DFCAD==002600,, ;CURRENT ADDRESS - 1 (IN CONTROL WORD) + ;ALSO BITS 4.7-4.9 HAVE 1'S COMPLEMENT OF MA 3.1-3.3 +DEFSYM $DFWC==261600,, ;- WORD COUNT (IN CONTROL WORD) +DEFSYM $DFLAD==002600,, ;LAST DATA ADDRESS (IN STORED CONTROL WD) +DEFSYM $DFCWA==261600,, ;LAST CONTROL WORD ADDRESS (IN STORED CONTROL WORD) + + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/salv.311 b/src/system/salv.311 new file mode 100755 index 00000000..0b55c2d9 --- /dev/null +++ b/src/system/salv.311 @@ -0,0 +1,6685 @@ +;;; -*- Mode:MIDAS -*- +.SEE COPY ;COPY BLOCK TO BLOCK +.SEE DUP ;DUPLICATE ENTIRE DISC PACK +.SEE TRAN ;LOAD FROM MAG TAPE UNIT 5 +.SEE UCOP ;COPY UDIRS FROM DRIVE TO DRIVE +.SEE ZAP ;ZERO DIR BLOCKS, WRITE OUT EMPTY TUT,MFD, WRITE READIN BLOCK +.SEE SPKID ;SET PACK ID IN TUT +.SEE DSKTST ;SIMPLE DISK TEST (WRITE THEN READ) +.SEE SEKTST ;DISK TEST WHICH SEEKS BACK AND FORTH (DOES NO WRITING) +.SEE MARK ;FORMAT PACK +.SEE MARK69 ;FINISH FORMATTING PACK +.SEE MFDR ;TRY TO RECONSTRUCT MFD FROM USER DIRS +.SEE CHKR ;SALVAGER +.SEE GOGO ;SALVAGER - (AUTO FOR ALL DRIVES) +.SEE GETSTS ;GET CONTROLLER AND CURRENT DRIVE STATUS +.SEE RDHEAD ;READ HEADER FROM TRACK +.SEE LISTF ;PRINT USER DIRECTORY ON LPTR +.SEE UNLOCK ;TEST & UNLOCK A BLOCK +.SEE REMAP ;REMAP PACK #S AND FIX UFDS + +.SEE PUNCH ;VARIABLE TO BE SET NON-ZERO IF COPYING OF TTY OUTPUT TO PAPER TAPE IS WANTED +.SEE HCRASH ;VARIABLE TO BE SET NON-ZERO IF DUP'ING A DISK AFTER HEAD CRASH +.SEE NOQUES ;IF NON-ZERO, NO QUESTIONS IN GOGOX MODE +.SEE FERRS ;COUNT OF CORRECTABLE ERRORS +.SEE CERRS ;COUNT OF ECC-CORRECTED ERRORS (RP04 ONLY) +.SEE DUPRER ;COUNT OF BLOCKS THAT COULDN'T BE READ IN `DUP' +.SEE DUPWER ;COUNT OF BLOCKS THAT COULDN'T BE WRITTEN IN `DUP' + +IF1, TITLE SALVATION +IF2,[ PRINTX/SALVATION / + .TYO6 .FNAM2 + PRINTX/ +/] + +DEFINE SUBTTL A/ +TERMIN + +;AC'S + +ZR=0 +A=1 +B=2 +C=3 +D=4 +N=5 +I=6 +Q=7 +H=10 +TT=11 +T=12 +W=13 +U=14 +J=15 +K=16 +P=17 + +SUBTTL CONFIGURATION + +DEFINE IFCE A,B +IFE SIXBIT/A/-SIXBIT/B/,TERMIN ;SUBSTITUTE FOR IFSE THAT IGNORES CASE + +;OPTIONS + +IF1,[ +PRINTX /Run under time-sharing? / +.TTYMAC TS + IRPS Z,,[YES Y AYE DA JA] + IFCE Z,TS,{ + ITS==1 + IRPS ZZ,,[DC10P RP10P RH10P OLPTP NLPTP TTLPTP KL10P] + ZZ==0 + TERMIN + .ISTOP + } + TERMIN +TERMIN + +IFNDEF ITS,[ ;run stand alone +ITS==0 +PRINTX /Which machine? / +.TTYMAC MCHN + IFCE MCHN,AIKA,[ + FIRSPK==1 ;first pack that must be mounted in gogo mode + LASTPK==5 ;last pack that must be mounted in gogo mode + NUDSL==440. + DC10P==1 + RP10P==0 + RH10P==0 + T300P==0 + KL10P==0 + OLPTP==0 ;R.I.P. + NLPTP==0 + TTLPTP==0 + TCMXH==55. + LIGHTS==4 ;PI + ];AIKA + IFCE MCHN,ML,[ + FIRSPK==2 + LASTPK==3 + NUDSL==250. + DC10P==0 + RP10P==1 + RH10P==0 + T300P==0 + KL10P==0 + OLPTP==0 + NLPTP==0 ;rest in pieces + TTLPTP==0 + TCMXH==55. + LIGHTS==4 ;PI + ];ML + IFCE MCHN,DM,[ + FIRSPK==17. + LASTPK==21. + NUDSL==200. + DC10P==0 + RP10P==1 + RH10P==0 + T300P==0 + KL10P==0 + OLPTP==0 + NLPTP==0 + TTLPTP==100 + TCMXH==55. + LIGHTS==4 ;PI + ];DM + IFCE MCHN,MC,[ + SA==105*2000 ; MC system is big, need to push SALV higher. + FIRSPK==0 + LASTPK==1 + NUDSL==500. + DC10P==0 + RP10P==0 + RH10P==1 + T300P==3 ;UNIT 3 IS FIRST T-300 UNIT + KL10P==1 + OLPTP==0 + NLPTP==0 + TTLPTP==0 ;NO LPT AT ALL + TCMXH==100. ;LA36 + LIGHTS==500 ;KL-UDGE + NDRIVE==6 ;8 DOESN'T FIT IN 128K + NUNITS==6 + ];KL +TERMIN +IFNDEF FIRSPK, .FATAL UNKNOWN MACHINE "MCHN" +];IFNDEF ITS + +;Formerly we knew number of units, now these are set to maximum and at run +; time we find out which units are present and on-line with the right packs. +IFNDEF NDRIVE, NDRIVE==8 ;# physical units +IFNDEF NUNITS, NUNITS==8 ;# virtual units + +IFE NUNITS-NDRIVE,[ ;Hack for virtual units in pre-Calcomp AI-KA system. + DEFINE UNTMES A/ + TYPE A + TERMIN +] +IFN NUNITS-NDRIVE,[ + DEFINE UNTMES A/ + DEFINE ZZQ UNIT + TYPE A + TERMIN + ZZQ [VIRTUAL UNIT] + TERMIN +] + +;MACROS FOR CONDITIONALIZATION + +DEFINE TS +IFN ITS!TERMIN + +DEFINE NTS +IFE ITS!TERMIN + +DEFINE DC +IFN DC10P!TERMIN + +DEFINE RP +IFN RP10P!TERMIN + +DEFINE RH +IFN RH10P!TERMIN + +DEFINE KA +IFE KL10P!TERMIN + +DEFINE KL +IFN KL10P!TERMIN + +DEFINE INSIRP I,[X] +IRPS Z,,X + I,Z +TERMIN +TERMIN + +DEFINE INFORM A,B,C,D,E,F,G +PRINTX \A!B!C!D!E!F!G +\ +TERMIN + +DEFINE CONC A,B +A!B!TERMIN + +DEFINE STRA C/ + MOVE A,[440700,,[ASCIZ \C\]] +TERMIN + +DEFINE LPR B/ + JSR LOUTST + [ASCIZ \B\] +TERMIN + +DEFINE TYPE TXT/ + JSR TOUTST + [ASCIZ \TXT\] +TERMIN + +TS INFORM Runs under time-sharing on any machine +DC INFORM Systems Concepts disk control +RP INFORM DEC RP10 disk control +RH INFORM DEC RH10 disk control + INFORM Number of drives=,\ndrives +; INFORM Number of virtual units=,\nunits +KA INFORM KA-10 +KL INFORM KL-10 +IFN OLPTP, INFORM Old LPT Interface +IFN NLPTP, INFORM New LPT Interface +IFN TTLPTP, INFORM LPT on MTY line number ,\TTLPTP&77 +TS, T300P==0 +IFN T300P, INFORM Support for Trident T-300 via PDP-11 +];IF1 + +MEMSIZ==1000000 +IFNDEF SA,SA==100*2000 + +NLPT=464 ;device code of ML lpt +MTY==400 ;device code of scanner + +APR==0 +PI==4 +KA, TTY==120 +KA, PTP==100 +IFN T300P, DLB==60 ;DL-10 +.ALSO DLC==64 + +X=PUSHJ P, + +NTS,[ LOC SA + JRST GOGO ;make easy to start from ITS core load +SALVRT: 0 ;system may JSR here + JRST SALVAG +];NTS + +;DISK PHYSICAL PARAMETERS + +DC,[ + .INSRT SYSTEM;DC10 > +] +RP,[ + .INSRT SYSTEM;RP10 > +] +RH,[ + .INSRT SYSTEM;RH10 > +] +TS, NTUTBL==4 ;MAXIMUM NUMBER OF BLOCKS PER TUT ON ANY ITS + +;FILE SYSTEM PARAMETERS + +.INSRT SYSTEM;FSDEFS > + +IFN T300P,[ + + ;DL10 COMMUNICATIONS AREA IN NON-ENCACHED LOW CORE +DL10AR==500 ;ACTUAL STORAGE LAYOUT DEFINED IN ITS AND IN T300 DEFS + + .INSRT SYSTEM;T300 > +MXTUTB==NTUTB1 ;MAXIMUM OF NTUTBL AND NTUTB1 +];T300P +.ELSE MXTUTB==NTUTBL + +DC,[ +DEFINE QCOPY A,B +DCOPY A(-_2&37774)!TERMIN +];DC + +;DEFINE CHANNEL PROGRAM AREA + +NTS,[ +KL,[ + .INSRT SYSTEM;EPT > + +ZZ==. + LOC EPTDDT + JRST MEMSIZ-4000 ;FOR 'DDT' COMMAND IN KLDCP +LOC ZZ + +PAG==10 +..D010==0 +SWPIA=701440,,0 +SWPUO=701740,,0 +SWPIO=701640,,0 +SWPUA=701540,,0 +];KL +KA,[ +SLVICWA=20 +SLVIOWD=22 +];KA +];NTS + +TS,[ +TYIC==1 +TYOC==2 +LPTC==3 +QIN==4 +] + +IF2,[ +TS,[ NBLKS==10000. ;FAKE + TBLKS==10000. ;FAKE + MFDBLK==-1 ;JUST TO AVOID UNDEF SYM ERROR, VALUE NEVER USED +; TUTBLK==-1 ;.. +];TS +];IF2 + +SUBTTL COPY BLOCK TO BLOCK + +NTS,[ + +COPY: JSR INIT + PUSHJ P,CRR + UNTMES COPY BLOCK FROM UNIT # + PUSHJ P,NTYI + JRST COPY + CAIL A,NUNITS + JRST COPY + MOVEM A,FROM + MOVE I,A + PUSHJ P,RESET +CP1: PUSHJ P,CRR + TYPE BLOCK # + PUSHJ P,OTYI + CAIL A,TBLKS + JRST CP1 + MOVEM A,FMBLK +CP2: PUSHJ P,CRR + UNTMES ONTO UNIT # + PUSHJ P,NTYI + JRST CP2 + CAIL A,NUNITS + JRST CP2 + MOVEM A,TOU + MOVE I,A + PUSHJ P,RESET + PUSHJ P,CRR +CP3: TYPE BLOCK # + PUSHJ P,OTYI + PUSHJ P,CRR + CAIL A,TBLKS + JRST CP3 + MOVEM A,TOBLK + MOVEI A,TUT + MOVE J,FMBLK + MOVE I,FROM + PUSHJ P,READ + JUMPL T,CPERR +COPYB: MOVEI A,TUT ;HANDY PLACE FOR A BREAKPOINT + MOVE J,TOBLK + PUSHJ P,WRITT + JRST DDT + +DTYI: MOVEI B,0 ;DECIMAL TYPEIN +DTYI1: X NTYI + JRST DTYI2 + IMULI B,10. + ADD B,A + JRST DTYI1 + +DTYI2: MOVE A,B + POPJ P, + +OTYI: MOVEI B,0 ;OCTAL TYPEIN +OTYI1: X NTYI + JRST DTYI2 + LSH B,3 + ADD B,A + JRST OTYI1 + +CPERR: TYPE READ ERROR + X CRR + JRST DDT + + SUBTTL TEST AND UNLOCK SOME BLOCKS + +UNLOCK: JSR INIT + X CRR + UNTMES UNLOCK BLOCKS ON UNIT # + X NTYI + JRST UNLOCK + CAIL A,NUNITS + JRST UNLOCK + MOVEM A,FROM + MOVE I,A + X RESET +UNLK1: X CRR + TYPE BLOCK # + X OTYI + PUSHJ P,UNLOCB + JFCL + JRST UNLK1 ;USE ^Z TO GET OUT + +;UNLOCK A BLOCK, NUMBER IN A, UNIT IN FROM + +UNLOCB: INSIRP PUSH P,[J K Q D B TT] + MOVE J,A + MOVEM J,FMBLK + SETZM CYLBUF ;ZERO OUT IN CASE CAN'T READ + MOVE A,[CYLBUF,,CYLBUF+1] + BLT A,CYLBUF+4000-1 + MOVE I,FROM + MOVEI A,CYLBUF + PUSHJ P,READ + JUMPGE T,UNLK2 + TYPE READ ERROR + X CRR + X GSTS + TYPE PROCEED? + X Y.OR.N + JRST UNLOCX +UNLK2: MOVE A,[RXWDS,,WXWDS] + BLT A,WXWDS+4-1 + MOVEI A,CYLBUF + X WRITE + JUMPL T,WRERR + MOVEI A,CYLBUF+2000 + X READ + JUMPL T,[TYPE READ-BACK ERROR + X CRR + X GSTS + JRST UNLOCX] + MOVSI T,-2000 +UNLK3: MOVE TT,CYLBUF(T) + CAME TT,CYLBUF+2000(T) + JRST [ TYPE READ-BACK COMPARE ERROR + X CRR + JRST UNLOCX] + AOBJN T,UNLK3 + + MOVEI A,TUT + X RDTUT + JUMPL T,CPERR + MOVE J,FMBLK + MOVEI B,TUT + X TUTPNT + JUMPE J,[ TYPE CAN'T ACCESS TUT + X CRR + JRST UNLOCX ] + MOVEI B,1 ;SAFEST ... NEXT SALVAGE WILL PUT CORRECT VALUE + DPB B,J + MOVEI A,TUT + X WRTUT + JUMPL T,WRERR + AOS -6(P) ;WINNING, SKIP RETURN +UNLOCX: INSIRP POP P,[TT B D Q K J] + POPJ P, + +WRERR: TYPE WRITE ERROR + JRST CRDDT + +SUBTTL DUP - COPY ENTIRE PACK + +DUP1A: PUSHJ P,CRR +DUP1: UNTMES FROM UNIT # + PUSHJ P,NTYI + JRST DUP1A + CAIL A,NUNITS + JRST DUP1A + MOVE I,A + PUSHJ P,RESET +DUP2: MOVEM A,FROM +TO: PUSHJ P,CRR + UNTMES ONTO UNIT # + PUSHJ P,NTYI + JRST TO + CAIL A,NUNITS + JRST TO + MOVEM A,TOU + X CRR + UNTMES COPY FROM UNIT # + MOVE A,FROM + X DPT + UNTMES ONTO UNIT # + MOVE A,TOU + X DPT + TYPE , OK? + X Y.OR.N + JRST DDT + MOVE I,TOU + PUSHJ P,RESET + POPJ P, + +DUP: JSR INIT + SETZM USRDS' + SETZM USWRTS' + SETZM DUPRER + SETZM DUPWER +RH, SETZM CERRS + TYPE DUPLICATE DISK + PUSHJ P,DUP1 + MOVE I,FROM +DC, MOVE A,QTRAN(I) +DC, DPB A,[DUNFLD CYLRIR] +RP, MOVE I,TOU +.ELSE [ MOVE A,PKNUM(I) + MOVE I,TOU + CAME A,PKNUM(I) + JRST DUPLUZ +]DC, MOVE A,QTRAN(I) +DC, DPB A,[DUNFLD CYLRIW] + MOVEI J,NCYLS+XCYLS-1 ;DETERMINE HOW MANY CYLINDERS THIS DRIVE +RP,[ MOVSI A,(DNOOPC) + DPB I,[DUNFLD A] ;SELECT DESTINATION DRIVE + DATAO DPC,A + DATAI DPC,B + MOVE I,FROM + DPB I,[DUNFLD A] ;SELECT SOURCE DRIVE + DATAO DPC,A + DATAI DPC,A + XOR A,B + TRNE A,2000 + JRST [ TYPE CAN'T COPY RP02 TO RP03 OR VICE VERSA + JRST CRDDT ] + TRNE B,2000 + MOVEI J,MCYLS+XCYLS-1 ;DRIVES ARE RP03S, MORE CYLINDERS TO COPY +];RP +IFN T300P,[ + CAIL I,T300P + JRST T3DUP ;HAVE TO DO IT THE SLOW WAY + MOVE I,FROM + CAIL I,T300P + JRST [ TYPE CAN ONLY GO T-300 TO T-300 + JRST CRDDT ] +];T300P + MOVEI A,CYLBUF +DLUP: MOVE I,FROM + PUSHJ P,READCY + JUMPL T,DLUP1 ;LOST, TRY BLOCK AT A TIME + MOVE I,TOU + PUSHJ P,WRITCY + JUMPL T,DLUP1 +DLUP2: SOJGE J,DLUP +DC, MOVEI T,CYLRIR ;COPY READ-IN BLOCK +DC, PUSHJ P,RW0 +RH,[ SKIPN A,CERRS + JRST DDT + X TDPT + TYPE ECC-CORRECTED ERRORS. + JRST CRDDT +] +.ELSE JRST DDT + +DUPLUZ: TYPE PACK # DFRS + PUSHJ P,CRR + JRST DDT + +IFN T300P,[ +T3DUP: MOVE I,FROM + CAIGE I,T300P + JRST [ TYPE CAN ONLY GO T-300 TO T-300 + JRST CRDDT ] + TYPE THIS WILL TAKE A WHILE... + X CRR + MOVEI J,NBLKS1+XBLKS1-1 +T3DUP1: MOVEI A,CYLBUF + MOVE I,FROM + X READ + JUMPL T,CPERR + MOVE I,TOU + X WRITE + JUMPL T,WRERR + SOJGE J,T3DUP1 + JRST CRDDT +];T300P + +IFE RH10P,[ ;BLOCK AT A TIME +DLUP1: PUSH P,J + IMULI J,NBLKSC + CLEARM DLUPT +DLUP3: MOVE I,FROM + MOVEI A,CYLBUF + PUSHJ P,READ + JUMPL T,DLUPE1 + MOVE I,[RXWDS,,WXWDS] +DLUPEW: BLT I,WXWDS+4-1 + PUSHJ P,WRITT + JUMPL T,DLUPE2 +DLUPEX: AOS TT,DLUPT + CAIGE TT,NBLKSC + AOJA J,DLUP3 + POP P,J + JRST DLUP2 +] +RH,[ ;SECTOR AT A TIME ON RP04 SO GET EXTRA SECTORS +DLUP1: MOVEI T,NHEDS*NSECS + MOVEM T,DLUPT +DLUP3: SOS W,DLUPT ;NEXT SECTOR (GOING BACKWARDS THROUGH CYLINDER) + IDIVI W,NSECS ;TRACK IN W, SECTOR IN U + LSH W,8 + IOR W,U + HRL W,J ;NOW W HAS DISK ADDRESS + MOVEM W,RHPGA + MOVE U,[-200,,CYLBUF-1] + MOVEM U,RHIOW + MOVE I,FROM + MOVEI TT,%HMRED + MOVEM TT,RHCMD + PUSHJ P,RW1 + JUMPL T,DLUPE1 +DLUPEW: MOVE I,TOU + MOVEI TT,%HMWRT + MOVEM TT,RHCMD + PUSHJ P,RW1 + JUMPL T,DLUPE2 +DLUPEX: SKIPE DLUPT + JRST DLUP3 + JRST DLUP2 +];RH + +DLUPT: 0 + +DLUPE1: AOS DUPRER + SKIPE HCRASH + JRST DLUPE4 ;SPEED IS OF THE ESSENCE, DON'T TYPE ANYTHING + TYPE Read error on block # + PUSHJ P,DLUPE3 +DLUPE4: SETZM CYLBUF ;COULDN'T READ THE BLOCK, SUBSTITUTE ALL ZEROS + MOVE A,[CYLBUF,,CYLBUF+1] + BLT A,CYLBUF+2000-1 + MOVE I,[DLUPE5,,WXWDS] ;WITH SPECIAL EXTRA WORDS + JRST DLUPEW ;RESUME DLUP AT WRITE + +DLUPE3: MOVE A,I + X DPT + MOVEI A,"- + X TYO +IFE RH10P, MOVE A,J +IFN RH10P,[ + HLRZ A,RHPGA ;CYLINDER + IMULI A,NBLKSC + LDB W,[101000,,RHPGA] ;HEAD + IMULI W,NSECS + LDB U,[001000,,RHPGA] ;SECTOR + ADD W,U + IDIVI W,SECBLK + ADD A,W ;INACCURATE IF UNUSED SECTOR AT END OF CYLINDER +];RH10P + PUSHJ P,DPT + PUSHJ P,CRR + JRST GSTS ;HARDWARE STATUS + +DLUPE2: AOS DUPWER + SKIPE HCRASH + JRST DLUPEX ;SPEED IS OF THE ESSENCE, DON'T TYPE ANYTHING + TYPE Write error on block # + PUSHJ P,DLUPE3 + JRST DLUPEX + +;SUITABLE EXTRA WORDS FOR BLOCKS THAT COULDN'T BE READ + +DLUPE5: 0 ;WORD COUNT=2000, LAST BLOCK=0 + SIXBIT /??????/ ;DUMMY DIRECTORY + SIXBIT /(DISK)/ + SIXBIT/LOSSAG/ + +DC,[ SUBTTL CYLINDER I/O, DC10 +READCY: SKIPA T,[DREADC+DUNENB] ;READ CONTINUOUS +WRITCY: MOVSI T,(DWRITC+DUNENB) ;WRITE CONTINUOUS + MOVE TT,QTRAN(I) + DPB TT,[DUNFLD T] + MOVE TT,J + SKIPGE QTRAN(I) + ADDI TT,NCYLS+XCYLS + DPB TT,[DCYL T] + DPB TT,[DCYL CYLCM3] +CYL1: SKIPLE TT,PKNUM(I) + JRST CYL2 + PUSH P,T + PUSHJ P,RESET + POP P,T + JRST CYL1 + +CYL2: CAIL J,NCYLS + MOVEI TT,0 + DPB TT,[DPKID T] + DPB TT,[DPKID CYLCM3] + MOVEM T,CYLCOM + DPB A,[DCCA CYLCM1] + DPB A,[DCCA CYLCM2] + MOVEI T,CYLCOM +RW0: HRRM T,DGO + JRST RW1 ;TRY TRANSFER UNTIL SUCCEEDS + +CYLCOM: 0 + DALU+DLDBWC+DLLB -2004*NBLKSC(3) ;LOAD WORD COUNT WITH -2004*NO. OF BLOCKS/CYL +CYLCM1: DCOPY . +CYLCM3: DRCC ;READ COMPARE CONTINUOUS + DALU+DLDBWC+DLLB -2004*NBLKSC(3) +CYLCM2: DCCOMP . + DHLT + +CYLRIR: DREAD+DUNENB + DCOPY CYLBUF(-LRIBLK_2&37774) +CYLRIW: DWRITE+DUNENB + DCOPY CYLBUF(-LRIBLK_2&37774) + DHLT +];DC + +RP,[ SUBTTL CYLINDER I/O, RP10 & RH10 CONTROLS + +;RP10 CYLINDER I/O ALWAYS SUCCEEDS. IF PROBLEMS OCCUR, GOES SECTOR +;AT A TIME, TYPING OUT WHAT IS GOING ON, ZEROING SECTORS THAT CAN'T BE READ, +;THEN RETURNS CLAIMING TO HAVE WON. +READCY: SKIPA T,DRD +WRITCY: MOVE T,DWR + MOVEM T,RPIOOP + MOVEM J,RPIOCY + SETZM RPIOHD + SETZM RPIOSC + MOVEM A,RPAOBJ + MOVNI T,NBLKSC*2000 + HRLM T,RPAOBJ +RPCY0: PUSHJ P,RPIO + JUMPGE T,CPOPJ ;WON +IFN 0,[ ;I DON'T THINK THIS CODE WORKS + SKIPE HCRASH + POPJ P, + MOVE T,RPIOOP + CAMN T,DWR + JRST [ TYPE WRITE ERROR ON BLOCK + JRST .+3 ] + TYPE READ ERROR ON BLOCK + PUSH P,A + PUSH P,B + MOVE A,I + X DPT + TYPE - + MOVE A,RPIOHD + IMULI A,NSECS + ADD A,RPIOSC + IDIVI A,SECBLK + MOVE B,RPIOCY + IMULI B,NBLKSC + ADD A,B + X DPT + X CRR + POP P,B + POP P,A + PUSHJ P,GSTS ;EXPLAIN WHAT HAPPENED TO THIS SECTOR + MOVE T,RPIOOP ;IF READ, ZERO THE BUFFER + HRLZ TT,RPAOBJ ;IF WAS REALLY IN SECTOR AT A TIME MODE + CAMN T,DRD + CAIE TT,-200 + JRST RPCY1 + MOVE TT,RPAOBJ + SETZM (TT) + HRLZ T,TT + HRRI T,1(TT) + BLT T,177(TT) +RPCY1: AOS T,RPIOSC ;ADVANCE TO NEXT SECTOR + CAIGE T,NSECS + JRST RPCY2 + SETZM RPIOSC + AOS T,RPIOHD + CAIL T,NHEDS + POPJ P, ;MUST BE DONE +RPCY2: MOVE T,[200,,200] + ADDB T,RPAOBJ + JUMPL T,RPCY0 ;GO DO THE REST OF THE CYLINDER +];IFN 0 + POPJ P, ;HMM, MUST BE DONE +];RP + +RH,[ ;CYLINDER I/O, RH10 CONTROL + +READCY: SKIPA TT,[%HMRED] +WRITCY: MOVEI TT,%HMWRT +IFN T300P,[ + CAIL I,T300P + JRST 4,. ;NOT CODED YET + SETZM T3IOP +];T300P + MOVEM TT,RHCMD + HRLZM J,RHPGA ;SET ADDRESS TO START OF CYLINDER + MOVEI T,-1(A) ;SET UP IOWD TO TRANSFER WHOLE CYLINDER + HRLI T,-200*NHEDS*NSECS ;- NUMBER OF WORDS TO TRANSFER + MOVEM T,RHIOW + JRST RW1 +];RH + +SUBTTL TRAN - LOAD FROM MAG TAPE + +MAGOP: AOSE ITAPE + JRST MTR1 + HRROI A,MAGHD + PUSHJ P,MREAD + MOVE A,MAGHD + TRNE A,-1 + JRST MBDTHD + CAMGE A,[-LTHBLK,,] + JRST MBDTHD + ADD A,[1,,THBLK+1] + PUSHJ P,MREAD + TYPE TAPE # + HLRZ A,THTPN + PUSHJ P,TDPT + PUSHJ P,CRR + +MTR1: HRROI A,MAGHD + PUSHJ P,MREAD + JUMPE T,CPOPJ ;EOF + MOVE A,MAGHD + TRNE A,-1 + JRST MBADHD + CAMGE A,[-LMHBLK,,0] + JRST MBADHD + ADD A,[1,,MHBLK+1] + PUSHJ P,MREAD + SETZM LNKFLG + HLRZ B,MHPKN + JUMPE B,POPJ1 ;NOT A LINK + SETOM LNKFLG + MOVE A,[-3,,LNKNM1] ;READ LINK INFO + PUSHJ P,MREAD + JRST POPJ1 + +MBADHD: LPR BAD HEADER + PUSHJ P,LCRR + PUSHJ P,IGFIL + JRST MTR1 + +MBDTHD: TYPE BAD TAPE HEADER + JRST CRDDT + +TRAN: PUSHJ P,REW +TRAN1: JSR INIT + PUSHJ P,CRR + MOVEI I,0 +TRAN2: SKIPGE QACT(I) + PUSHJ P,RESET + CAIGE I,NUNITS-1 + AOJA I,TRAN2 + MOVEI A,5 ;READS FROM TAPE UNIT 5 + PUSHJ P,DUP2 + MOVEI A,TUT + MOVE I,TOU + PUSHJ P,RDTUT + JUMPL T,READC + MOVEI A,MFD + MOVE J,MFDBK + PUSHJ P,READT + +TNAML: PUSHJ P,MAGOP + JRST MREOT + MOVE A,MHFN1 ;DON'T RELOAD DIRECTORIES! + MOVE B,MHFN2 + CAMN A,[SIXBIT/.FILE./] + CAME B,[SIXBIT/(DIR)/] + CAIA + JRST TIGNF + CAMN A,[SIXBIT/M.F.D./] + CAME B,[SIXBIT/(FILE)/] + SKIPA A,MHSNM + JRST TIGNF + PUSHJ P,SIXLPT + PUSHJ P,LSPAC + MOVE A,MHFN1 + PUSHJ P,SIXLPT + PUSHJ P,LSPAC + MOVE A,MHFN2 + PUSHJ P,SIXLPT + PUSHJ P,LSPAC + CLEARM FERRS + MOVE B,MHSNM + MOVE A,MFD+MDNAMP + SETZM IBLK +TMLKP: CAIL A,2000 + JRST TNEWU + SKIPN C,MFD+MNUNAM(A) + JRST TMLKZ + CAMN B,C + JRST TOLDU +TMLKL: ADDI A,LMNBLK + JRST TMLKP + +TMLKZ: MOVEM A,IBLK + JRST TMLKL + +TOLDU: HRREI J,-2000(A) ;CONVERT MFD INDEX TO BLOCK NO + ASH J,-1 + ADD J,NUDS + MOVEM J,UFDTA + MOVEI A,NUSRD + PUSHJ P,READT + CAME B,NUSRD+UDNAME + JRST 4,. + JRST TOLDUR + +TNEWU: MOVE A,[NUSRD,,NUSRD+1] + SETZM NUSRD + BLT A,NUSRD+1777 + MOVEM B,NUSRD+UDNAME + MOVEI A,2000 + MOVEM A,NUSRD+UDNAMP + SKIPE A,IBLK + JRST .+3 + MOVNI A,LMNBLK + ADDB A,MFD+MDNAMP + MOVEM B,MFD+MNUNAM(A) + HRREI J,-2000(A) ;CONVERT MFD INDEX TO BLOCK NO + ASH J,-1 + ADD J,NUDS + MOVEM J,UFDTA +TOLDUR: + MOVE B,MHFN1 + MOVE C,MHFN2 + MOVE A,NUSRD+UDNAMP + SETZM IBLK +TULKP: CAIL A,2000 + JRST TNEWF + MOVSI T,UNCDEL + TDNE T,NUSRD+UNRNDM(A) + JRST TULKD + SKIPN T,NUSRD+UNFN1(A) + JRST TULKZ + CAME B,T + JRST TULKL + CAMN C,NUSRD+UNFN2(A) + JRST TOLDF +TULKL: ADDI A,LUNBLK + JRST TULKP + +TULKZ: SKIPN NUSRD+UNFN2(A) +TULKD: MOVEM A,IBLK + JRST TULKL + +TOLDF: LPR EXISTS + PUSHJ P,LCRR +TIGNF: PUSHJ P,IGFIL + JRST TNAML + +IGFIL: MOVE A,[-2000,,FDBUF] + PUSHJ P,MREAD + SKIPN EOUF + JRST IGFIL + CLEARM EOUF + POPJ P, + +TNEWF: SKIPE A,IBLK + JRST TNEWCK + MOVNI A,LUNBLK + ADDB A,NUSRD+UDNAMP +TNEWCR: MOVE T,NUSRD+UDESCP + IDIVI T,6 + CAIL T,-UDDESC(A) + JRST 4,. + MOVEM B,NUSRD+UNFN1(A) + MOVEM C,NUSRD+UNFN2(A) +DC, MOVEM B,WXWDS+XWFN1 +DC, MOVEM C,WXWDS+XWFN2 + MOVE B,NUSRD+UDNAME +DC, MOVEM B,WXWDS+XWSYSN +DC, SETZM WXWDS+XWBWC + MOVE B,NUSRD+UDESCP + DPB B,[UNDSCP NUSRD+UNRNDM(A)] + MOVE B,MHDATE + MOVEM B,NUSRD+UNDATE(A) + SETOM NUSRD+UNREF(A) + MOVE B,TUT+QPKNUM + DPB B,[UNPKN NUSRD+UNRNDM(A)] + MOVEI A,NUSRD+UNRNDM(A) + HRLI A,(UNWRDC) + MOVEM A,TRNDEP' ;DPB WC OF LAST BLOCK LATER + SETZM CBYT' + SETZM OBLKS' + SETZM IBLK' + SETZM LBLK' + SKIPE LNKFLG + JRST TRNLNK ;JUMP IF APPENDING LINK +TBLKL: +TBLKL1: MOVE A,[-2000,,FDBUF] + PUSHJ P,MREAD + JUMPE T,TBLKL2 +DC, DPB T,[XWAWC WXWDS+XWBWC] + DPB T,TRNDEP ;STORE WORD COUNT IN DIRECTORY + MOVE T,LBLK +DC, DPB T,[XWBLK WXWDS+XWBWC] + AOS IBLK + PUSHJ P,WRBLK +TBLKL2: SKIPN EOUF + JRST TBLKL + SETZM EOUF + JRST TBDON + +TNEWCK: SKIPN NUSRD+UNFN1(A) + SKIPE NUSRD+UNFN2(A) + JRST 4,. + JRST TNEWCR + +TBDON: PUSHJ P,EBYT + MOVEI J,UDWPH + SKIPN LBLK + PUSHJ P,BYDEP +TBDON1: MOVEI J,0 + PUSHJ P,BYDEP + JRST TMDON + +TRNLNK: MOVE A,LNKSNM + PUSHJ P,TRNLK1 + MOVE A,LNKNM1 + PUSHJ P,TRNLK1 + MOVE A,LNKNM2 + PUSHJ P,TRNLK1 + JRST TBDON1 + +TRNLK1: MOVE K,A + MOVEI A,6 +TRNLK2: MOVEI J,0 + LSHC J,6 + JUMPE J,TRNLK4 + CAIE J,': + CAIN J,'; + JRST [ PUSH P,J + MOVEI J,': + PUSHJ P,BYDEP + POP P,J + JRST .+1 ] + PUSHJ P,BYDEP + SOJG A,TRNLK2 + POPJ P, + +TRNLK4: MOVEI J,'; + JRST BYDEP + +READFN: SKIPA I,FROM +READT: MOVE I,TOU + PUSHJ P,READ +READC: JUMPL T,[JRST 4,.] + POPJ P, + +WRBLK: MOVE J,TUT+QTUTP + AOS TUT+QTUTP + CAML J,TUT+QLASTB + JRST WRLUZ + MOVEM J,LBLK + SETZM TUTLUZ + MOVEI B,TUT + PUSHJ P,TUTPNT + LDB B,J + JUMPN B,WRBLK + MOVEI B,1 + DPB B,J + MOVE J,LBLK + MOVEI A,FDBUF + PUSHJ P,WRITT + SUB J,OBLKS + ADDM J,OBLKS + CAIN J,1 + JRST WRBC + PUSHJ P,EBYT + CAIG J,UDWPH-UDTKMX + JRST WRBS + MOVE J,OBLKS + LSHC J,-NXLBYT*6 + MOVEI U,NXLBYT+1 + ADDI J,UDWPH+1 +WRBL: PUSHJ P,BYDEP + LSHC J,6 + SOJG U,WRBL + POPJ P, + +WRLUZ: SETCMB J,TUTLUZ' + JUMPE J,WRLUZ1 + MOVE J,TUT+QSWAPA + CAMGE J,TUT+QFRSTB + MOVE J,TUT+QFRSTB + MOVEM J,TUT+QTUTP + JRST WRBLK + +WRLUZ1: TYPE DISK FULL + SKIPN NOLPT + X LCRR + JRST CRDDT + +WRBS: ADDI J,UDTKMX-1 +BYDEP: MOVE T,NUSRD+UDESCP + AOS NUSRD+UDESCP + IDIVI T,6 + ADDI T,UDDESC + CAML T,NUSRD+UDNAMP + JRST 4,. + ADDI T,NUSRD + HLL T,QBTBL(W) + DPB J,T + POPJ P, + +WRBC: AOS J,CBYT + CAIGE J,UDTKMX + POPJ P, +EBYT: PUSH P,J + SKIPN J,CBYT + JRST POPJJ + PUSHJ P,BYDEP + SETZM CBYT +POPJJ: POP P,J + POPJ P, + + +TMDON: MOVE J,[WXWDS,,WXWDS+1] + SETZM WXWDS + BLT J,WXWDS+3 + MOVE A,TUT+QTUTP + IDIVI A,NBLKSC + IMULI A,NBLKSC + MOVEM A,TUT+QTUTP + MOVEI A,TUT + MOVE I,TOU + PUSHJ P,WRTUT + MOVEI I,0 +TMDON2: SKIPL QACT(I) + JRST TMDON1 + MOVE J,MFDBK + MOVEI A,MFD + PUSHJ P,WRITE + MOVE J,UFDTA + MOVEI A,NUSRD + PUSHJ P,WRITE +TMDON1: CAIGE I,NUNITS-1 + AOJA I,TMDON2 + SKIPN FERRS + LPR OK + PUSHJ P,LCRR + JRST TNAML + +SUBTTL UCOP - COPY DIRECTORIES FROM DRIVE TO DRIVE + +UCOP: JSR INIT + TYPE COPY DIRS + PUSHJ P,DUP1 + MOVEI A,D0 + MOVE J,MFDBK + PUSHJ P,READFN + PUSHJ P,WRITT + MOVEI Q,2000 +UCOPL: SUBI Q,LMNBLK + CAMGE Q,D0+MDNAMP + JRST DDT + SKIPN B,D0(Q) + JRST UCOPL + HRREI J,-2000(Q) ;CONVERT MFD INDEX TO BLOCK NO + ASH J,-1 + ADD J,NUDS + MOVEI A,OUSRD + PUSHJ P,READFN + CAME B,OUSRD+UDNAME + JRST 4,. + PUSHJ P,WRITT + JUMPL T,WRERR + JRST UCOPL + +SUBTTL SPKID - SET PACK ID IN TUT + +SPKID: JSR INIT + CAIA +SPKID0: X CRR + UNTMES SET PACK ID ON UNIT # + X NTYI + JRST SPKID0 + CAIL A,NUNITS + JRST SPKID0 + X CRR + MOVE I,A + PUSHJ P,RESET + MOVEI A,TUT + PUSHJ P,RDTUT + JUMPL T,ZAPLUZ + TYPE PACK NO= + MOVE A,TUT+QPKNUM + X TDPT + TYPE , CHANGE ID FROM + MOVE A,TUT+QPAKID + X T6B + TYPE TO + X SIXIN + X CRR + JUMPE B,ZAPLUZ + MOVEM B,TUT+QPAKID + MOVEI A,TUT + PUSHJ P,WRTUT + JUMPL T,ZAPLUZ + JRST DDT + SUBTTL REMAP - REASSIGN PACK#S AND FIX UFDS + +REMAPP: REPEAT 40, -1 ;INDEX BY PACK #. LH=NEW PACK #, RH=DISK ADDR OFFSET + +REMAP: JSR INIT + UNTMES REMAP THE COPY OF THE UFDS ON UNIT # + PUSHJ P,NTYI + JRST REMAP + X CRR + CAIL A,NUNITS + JRST REMAP + MOVE I,A + MOVEI A,MFD ;GET MFD + MOVE J,MFDBK + PUSHJ P,READ + JUMPL T,ACTUE3 + MOVE Q,MFD+MDNAMP +REMAP1: CAIL Q,2000 ;NEXT UFD + JRST CRDDT + SKIPN B,MFD+MNUNAM(Q) + JRST REMAP9 + MOVEM B,USRNAM + MOVE J,Q + SUBI J,2000 + IDIVI J,LMNBLK + ADD J,NUDS ;UFD BLOCK NUMBER + MOVEI A,OUSRD + PUSHJ P,READ + JUMPL T,CPERR + CAME B,OUSRD+UDNAME + JRST CPERR + MOVE K,OUSRD+UDNAMP +REMAP2: CAIL K,2000 ;NEXT FILE + JRST REMAP6 + MOVSI C,UNLINK + TDNE C,UNRNDM+OUSRD(K) + JRST REMAP5 ;DON'T MANGLE LINKS + LDB C,[UNDSCP UNRNDM+OUSRD(K)] + IDIVI C,UFDBPW + HLL C,QBTBLI(D) + ADDI C,UDDESC+OUSRD ;C HAS DESC POINTER + LDB D,[UNPKN UNRNDM+OUSRD(K)] ;D HAS PK # + SKIPGE A,REMAPP(D) ;GET MAPPING + JRST 4,. ;LOSER FORGOT TO PATCH IT IN + HLRZ D,A ;GET NEW PACK # + DPB D,[UNPKN UNRNDM+OUSRD(K)] ;CHANGE IT + HRRE D,A ;D HAS BLOCK # OFFSET +REMAP3: MOVE H,C + ILDB A,C ;GET DESC + JUMPE A,REMAP5 ;EOF + CAIG A,UDWPH + JRST REMAP3 ;DOESN'T DEPEND ON ABS DISK ADDRESSES + ANDI A,37 ;MASK OUT LOAD-ADDR-BIT +REPEAT NXLBYT,[ + LSH A,UFDBYT + ILDB B,C + ADD A,B +] + ADD A,D ;RELOCATE THE ADDRESS + REPEAT 6,JFCL ;PATCH AREA + MOVE C,H ;GET BACK B.P. TO START OF LOAD-ADDR DESCRIPTOR + MOVE H,[_36+UFDBYT_30+A] +REPEAT NXLBYT+1,[ + ILDB B,H +IFE .RPCNT, ADDI B,40 + IDPB B,C +] + JRST REMAP3 + +REMAP5: ADDI K,LUNBLK + JRST REMAP2 + +REMAP6: MOVEI A,OUSRD + PUSHJ P,WRITE + JUMPL T,WRERR +REMAP9: ADDI Q,LMNBLK + JRST REMAP1 + +SUBTTL ZAP - ZERO DIR BLOCKS, WRITE EMPTY TUT & MFD + +ZAP: JSR INIT + X CRR + UNTMES INIT DIRS ON UNIT # + PUSHJ P,NTYI + JRST ZAP + CAIL A,NUNITS + JRST ZAP + PUSHJ P,CRR + MOVEM A,TOU + MOVE I,A +RP,[ TYPE PACK NO = + X DTYI ;IF RP, NO PK # IN HARDWARE, GET IT FROM HUMAN + X CRR + MOVEM A,PKNUM(I) +] PUSHJ P,RESET ;IF DC OR RH, WILL USE PACK # FROM HARDWARE + MOVE A,[WXWDS-1,,WXWDS] + BLT A,WXWDS+3 + SETZM MFD ;INIT ALL BLOCKS TO ZERO + MOVE A,[MFD,,MFD+1] + BLT A,MFD+1777 + MOVN J,NUDS ;GET AOBJN PTR TO UFD BLOCKS + HRLZ J,J +KL, ADD J,[2,,2] ;PROTECT KLDCP? + MOVEI A,MFD +ZAPL: PUSHJ P,WRITE + JUMPL T,ZAPLUZ + AOBJN J,ZAPL + +DC,[ CONO DC0,DCCSET+DCDENB + DATAO DC0,[DJMP DZAP] + CONSZ DC0,DSSACT + JUMPA .-1 + CONSO DC0,DSSERR +];DC + JRST MARK69 + +ZAPLUZ: TYPE LOSE + JRST CRDDT + +DC,[ +DZAP: DWRITE ;ZERO READ-IN BLOCK + DCSKIP (-LRIBLK_2&37774) + DHLT +];DC + + SUBTTL SIMPLE DISK TESTS + +;THIS ONE JUST WRITES A SINGLE BLOCK, READS IT BACK, AND CHECKS THAT IT'S THE SAME. +DSKTST: JSR INIT + SETOM HCRASH ;DON'T DO ERROR RETRY + TYPE TEST UNIT # + X NTYI + JRST DSKTST + X CRR + CAIL A,NUNITS + JRST DSKTST + MOVE I,A + TYPE GOT A SCRATCH PACK ON UNIT # + X TOPT + TYPE ? + X Y.OR.N + JRST CRDDT +DSKTS0: X RESET + MOVEI J,NBLKSC*15. ;RANDOMLY USE CYLINDER 15. + MOVSI A,-2000 + MOVEI B,1 ;FIRST PART OF PATTERN IS FLOATING 1S +DSKT0A: MOVEM B,D0(A) + LSH B,1 + SKIPE B + AOBJN A,DSKT0A + HRROI B,-2 ;NEXT IS FLOATING 0S +DSKT0B: MOVEM B,D0(A) + JUMPGE B,DSKT0C + LSH B,1 + AOS B + AOBJN A,DSKT0B +DSKT0C: MOVEM A,D0(A) ;REST IS AN ADDRESS PATTERN + AOBJN A,DSKT0C + MOVEI A,D0 + X WRITE + JUMPL T,WRERR +DSKTS1: MOVEI A,D1 + X READ + PUSHJ P,TYIPSE + MOVSI B,-2000 +DSKT1A: MOVE A,D1(B) + CAMN A,D0(B) +DSKTS2: AOBJN B,DSKT1A + JUMP DSKTS4 ;CHANGE TO JUMPA FOR NO TYPEOUT + JUMPGE B,DSKTS3 ;JUMP IF COMPARED ALL + HRRZ A,B + X TOPT + TYPE / + MOVE A,D0(B) + X THWO + X TSPAC + MOVE A,D1(B) + X THWO + X TSPAC + MOVE A,D0(B) + XOR A,D1(B) + X THWO + X CRR + JRST DSKTS2 + +DSKTS3: JUMPGE T,DSKTS1 ;AFTER PRINTING COMPARISON, IF DISK NOTICED ERROR + X GSTS ; ALSO PRINT THAT + JRST DSKTS1 + +DSKTS4: DATAO LIGHTS,[0] + JUMPGE B,DSKTS1 + MOVE A,B + XOR A,CYLBUF(B) + DATAO LIGHTS,A + JRST DSKTS2 + +;SEEK TEST. THIS LOOPS OVER ALL HEADS, AND OPTIONALLY LOOPS OVER DIFFERENT +; LENGTH SEEKS. IT DOESN'T WRITE, BUT IS A TEST OF SEEKING AND SEARCHING. +;SETOM HCRASH IF YOU WANT TO DO NO ERROR RETRIES ON READ/SEARCH ERRORS +;(SEEK INCOMPLETES WILL ALWAYS BE RETRIED.) + +SEKTST: JSR INIT + TYPE SEEK TEST UNIT # + X NTYI + JRST SEKTST + X CRR + CAIL A,NUNITS + JRST SEKTST + MOVE I,A + X RESET + TYPE ALWAYS DO FULL LENGTH SEEKS? + SETZM SEKINC + MOVEI A,10.*NBLKSC + X Y.OR.N + MOVEM A,SEKINC' ;IF NO, DO DECREASING LENGTH SEEKS +SEKTS0: +RP,[ + MOVSI A,(DNOOPC) ;DETERMINE HOW MANY CYLINDERS THIS DRIVE + DPB I,[DUNFLD A] + DATAO DPC,A + DATAI DPC,B + MOVEI A,*NBLKSC ;RP02 + TRNE B,2000 + MOVEI A,*NBLKSC ;RP03 +];RP +.ELSE MOVEI A,*NBLKSC +IFN T300P,[ + CAIL I,T300P + MOVEI A,*NBLKC1 ;T-300 +];T300P + MOVEM A,SEKCY2' + SETZM SEKCY1' +SEKTS1: SETZM SEKHDN' ;RESET HEAD +SEKTS2: MOVE J,SEKCY1 ;BLOCK ADDRESS OF OUTER CYLINDER + ADD J,SEKHDN ;SELECT A BLOCK ON THE DESIRED HEAD + MOVEI A,CYLBUF + X READ ;READ IT + SKIPGE T +SEKTS3: X GSTS ;JFCL THIS IF YOU DON'T WANT ERROR MESSAGES + MOVE J,SEKCY2 ;BLOCK ADDRESS OF INNER CYLINDER + ADD J,SEKHDN ;SELECT SAME HEAD + MOVEI A,CYLBUF + X READ + SKIPGE T + XCT SEKTS3 + PUSHJ P,TYIPSE + MOVEI J,NSECS/SECBLK ;ADVANCE TO NEXT HEAD + ADDB J,SEKHDN + CAIGE J,NBLKSC ;SKIP IF TOUCHED ALL HEADS + JRST SEKTS2 + MOVN B,SEKINC ;YES, CHANGE CYLINDERS + ADDB B,SEKCY2 + MOVE C,SEKINC + ADDB C,SEKCY1 + CAMG C,B + JRST SEKTS1 + JRST SEKTS0 ;RECYCLE + +THWO: PUSH P,A + PUSH P,B + TLNN A,-1 + JRST THWO1 + HLRZS A + X TOPT + TYPE ,, + HRRZ A,-1(P) +THWO1: X TOPT + POP P,B + POP P,A + POPJ P, + DC,[ + SUBTTL DC-10 PACK FORMATTING +MARK: JSR INIT + X CRR + UNTMES FORMAT PACK ON UNIT # + PUSHJ P,NTYI + JRST MARK + CAIL A,NUNITS + JRST MARK + PUSHJ P,CRR + HRRZ TT,QTRAN(A) + CONO DC1,(TT) ;SETUP DRIVE # FOR LATENCY TIMER + MOVEM A,TOU + MOVE I,A + PUSHJ P,RECAL + CONSO DC1,DFUNSF\DOFFL + JRST MARK1 + TYPE DRIVE OK? + JRST CRDDT + +MARK1: MOVE A,[DSPC+DSCWIM+DSWIDX+DSWNUL] + MOVEM A,CYLBUF + MOVEI D,CYLBUF+1 + PUSHJ P,RDLAT ;READ LATENCY TIMER + JUMPE A,.-1 +MARK1A: CONI DC1,A + CONI DC1,C + LDB A,[DSLAT A] + LDB C,[DSLAT C] + CAME A,C + JRST MARK1A + JUMPN A,[MOVE B,A + JRST MARK1A] +IFN 0,[ ;THIS HARDWARE HAS BEEN BROKEN FOR YEARS + PUSH P,B + MOVE A,B + IDIVI A,10. ;NO. OF MILLISECONDS + PUSH P,B + PUSHJ P,TDPT + MOVEI A,". + PUSHJ P,TYO + POP P,A + ADDI A,"0 + PUSHJ P,TYO + TYPE MILLISECONDS ROTATION TIME + PUSHJ P,CRR + POP P,B + CAIGE B,254. ;LIKELY JUST NO INDEX ON THIS PACK + JRST MARK1B + TYPE TOO DAMN LONG TO BE CREDIBLE, USING 24.5 MS. + PUSHJ P,CRR +];IFN 0 + MOVEI B,245. +MARK1B: IMULI B,1000 ;CONVERT TO NUMBER OF BITS/TRACK + IDIVI B,36. ;NO. OF WORDS PER SECTOR + AOJ B, + MOVEM B,MAXT' + SETZ A, + PUSHJ P,STOBLK ;ENOUGH ONES TO WIPE OUT THIS TRACK + MOVE J,MAXT + IDIVI J,NSECS + CAIL K,NSECS/2 + AOJ J, ;INTER-SECTOR GAP LENGTH + SUBI J,3+3+7+3011 ;HEADER CODE+HEADER DATA+"ONES"+BLOCK+CHECKSUM + MOVEI Q,NSECS +MARK1C: MOVEI B,(D) + HRLI B,HBLK ;SETUP COPYS FOR HEADER PREAMBLE,DATA,POSTAMBLE + ADDI D,3 + BLT B,-1(D) + MOVNI B,-NSECS(Q) + IMULI B,3 + ADDI B,DHEDR + HRRM B,-2(D) ;POINT COPY TO THIS SECTORS ENCODED DATA + MOVEI B,103. ;103 BLOCKS OF 10 ZEROS (ENCODED) + MOVE A,[QCOPY EZERS,15.,] + PUSHJ P,STBLK + SOJLE Q,MARK1D + MOVE B,J ;ENOUGH ONES TO FILL OUT REMAINING PART OF SECTOR + PUSHJ P,STOBLK + JRST MARK1C + +;SETUP STUFF FOR POSSIBLY WRITING READIN BLOCK +MARK1D: MOVE A,[QCOPY EONES,3,] + MOVEM A,(D) + AOJ D, + MOVSI A,(DOPR+DOHXFR) + MOVEM A,(D) + MOVEM D,RIWP' + ADDI D,2 + MOVE B,J + SUBI B,3+3+7+LRIBLK*3/2+3 ;HEADER+LRIBLK+CHECKSUM + LSH B,-1 + SUBI B,3*3 + PUSHJ P,STOBLK + MOVEI B,(D) + HRLI B,WRTRI + ADDI D,5 + BLT B,-1(D) + MOVSI A,(DJMP) ;PATCH JUMP AROUND RIBLK CODE, WILL BE CLOBBERED FOR BLOCK 0 ONLY + ADDI A,(D) + MOVE B,RIWP + MOVEM A,1(B) + MOVEI B,(D) + MOVEM B,ENDP' + AOS ENDP + HRLI B,RCBLK + ADDI D,5 + BLT B,-1(D) + MOVEI B,-3(D) ;PATCH AOJN .-1 ADDRESS + HRRM B,-2(D) + TYPE PACK NO = + PUSHJ P,DTYI + PUSHJ P,CRR + MOVE I,TOU + MOVEM A,PKNUM(I) + MOVE I,[440300,,RIHEDR] ;ENCODE READIN HEADER + PUSHJ P,ENCI + MOVEI I,RIHED0 + PUSHJ P,HCOMP + MOVEI J,/NSECS-1 + MOVEM J,TRKN' + ;SO FAR +;WRITE IMAGE COMMAND - (START AT SECTOR PULSE) +;COPY ;ENOUGH TO WIPE OUT FULL TRACK +;(THEN FOR EACH SECTOR): + +;HEADER PREAMBLE +; ONES FOLLWED BY SINGLE ZERO +; 8 BYTES OF 10101 +; TWO 28 BIT HEADER WORDS +; A SERIES OF ONES FOLLWED BY 01 +;ENCODED ZEROS FOR DATA BLOCK (2004) WORDS + 2 WORDS CHECKSUM +;ENOUGH ENCODED ONES TO FILL OUT REST OF SECTOR (EXCEPT ON LAST SECTOR) + +;AFTER LAST SECTOR +;A FEW ONES +; NORMALLY: FOR BLOCK 0: +;RIWP: HANG FOR END OF TRANSFER WRITE ONES +; JUMP AROUND WRITE READIN WRITE ONES +; READIN HEADER PREAMBLE +; READIN HEADER +; READIN HEADER POSTAMBLE +; READIN BLOCK +; ONES TO PAD OUT REST OF TRACK +; DALU SETUP CONTROL COUNTER +;ENDP: READ COMPARE COMMAND +; COPY 4 WORDS ZEROS +; AOJN CC,.-1 +; HALT + +MARK2: MOVEI K,5 + MOVEM K,NTRYS' + SETZM DHED0 + CAIL J,NBLKS/NSECS + JRST MARK2C + MOVE I,TOU + MOVE A,PKNUM(I) + DPB A,[DPKID DHED0] ;PACK ID FOR HEADER + DPB A,[DPKID @ENDP] ;PACK ID FOR READ-COMPARE COMMAND + JUMPN J,MARK2C + MOVE B,RIWP + MOVE A,[QCOPY EONES,3,] + MOVEM A,(B) + MOVEM A,1(B) +MARK2C: IDIVI J,NHEDS + PUSH P,J + MOVE W,TOU + SKIPGE QTRAN(W) + ADDI J,NCYLS+XCYLS ;OFFSET IF DOUBLE SIZE PHYSICAL PACK +IRP A,,[CYLBUF,@ENDP,DHED0] ;SETUP INITIAL WRITE-IMAGE COMMAND + DPB J,[DCYL A] ; " READ-COMPARE COMMAND + DPB K,[DSURF A] ; " HEADER WORD +TERMIN + POP P,J ;VIRTUAL CYLINDER # + MOVEI W,0 + DPB W,[DHNXAD DHED1] + MOVEI W,1 ;END OF TRACK + CAIN K,NHEDS-1 + MOVEI W,2 ;END OF CYLINDER + CAIE J,NCYLS-1 + CAIN J,NCYLS+XCYLS-1 + TRO W,1 ;END OF DISK + MOVE I,[440300,,DHEDR] + PUSHJ P,ENCI + MOVEI I,DHED0 + MOVEI Q,NSECS +MARK2B: CAIN Q,1 ;PUT IN INCREMENT CODE + DPB W,[DHNXAD DHED1] + PUSHJ P,HCOMP ;ENCODE HEADERS + AOS DHED0 + SOJG Q,MARK2B +MARK2A: CONO DC0,DCCSET\DCDENB + DATAO DC0,[DJMP CYLBUF] + MOVE A,[DWLUP,,14] + BLT A,16 + JRST 14 ;WAIT IN AC'S FOR DISC, THEN FALL THRU +MARK2D: CONSO DC0,DSSERR + JRST MARK4 + CONSZ DC1,DCPERR\DNXM\DDOBSY + JRST MARK3A + CONSZ DC1,DPROT + JRST MARK3B + CONSZ DC1,DOFFL\DFUNSF + JRST MARK3C + CONSO DC1,DWTHER\DCKSER\DOVRRN\DRCER\DRLNER + JRST MARK3D +MTROV: SOSLE NTRYS + JRST MARK2A + CONSZ DC1,DOVRRN + JRST MARK3A + TYPE DISK BAD + JRST CRDDT + +DWLUP: CONSZ DC0,DSSACT + JRST 14 + JRST MARK2D + +MARK3A: TYPE MACHINE LOSSAGE + JRST CRDDT + +MARK3B: TYPE NOT WRT ENABLED + JRST CRDDT + +MARK3C: TYPE DRIVE LOSSAGE + JRST CRDDT + +MARK3D: TYPE CONTROLLER LOSSAGE + JRST CRDDT + +MARK4: SOSL J,TRKN + JRST MARK2 +];DC + +;INITIALIZE MFD AND TUT +; TOU AND PKNUM+n MUST BE ALREADY SET UP + +MARK69: MOVE I,TOU + X MFDINN + TYPE SWAPPING ALLOC = + PUSHJ P,OTYI + PUSHJ P,CRR + X TUTINI + MOVE A,PKNUM(I) + MOVEM A,TUT+QPKNUM + TYPE PACK # = + X TDPT + X CRR + TYPE PACK ID = + PUSHJ P,6TYI + PUSHJ P,CRR + MOVEM B,TUT+QPAKID + MOVEI A,MFD + MOVE J,MFDBK + PUSHJ P,WRITT + JUMPL T,WRERR + MOVE A,TUT+QSWAPA ;SET UP FREE SPACE POINTER + CAMGE A,NUDS + MOVE A,NUDS + ADDI A,NBLKSC-1 ;JUST IN CASE QSWAPA NOT ON CYLINDER BOUNDARY + IDIVI A,NBLKSC + IMULI A,NBLKSC + MOVEM A,TUT+QTUTP + MOVEI A,TUT + PUSHJ P,WRTUT + JUMPL T,WRERR + JRST DDT + +6TYI: MOVE C,[440600,,B] + MOVEI B,0 +6TYL: PUSHJ P,TYI + SUBI A,40 + JUMPLE A,CPOPJ + TLNE C,770000 + IDPB A,C + JRST 6TYL + DC,[ +HCOMP: SETOM HPAR' + MOVEI J,(I) + HRLI J,-2 +HCOMP1: MOVEI B,14. + MOVE A,(J) + XORM A,HPAR + LSH A,-2 + SOJG B,.-2 + AOBJN J,HCOMP1 + + MOVE B,(I) + PUSHJ P,ENCH + MOVE B,HPAR + ANDI B,3 + LSH B,20. + XORB B,1(I) + PUSHJ P,ENCH + MOVSI B,770000 +HCOMP2: TDNN B,DSKBP + POPJ P, + PUSHJ P,ENCDO + JRST HCOMP2 + +ENCO: SKIPA A,C1 +ENCZ: MOVEI A,0 +ENC: ANDI A,1 + HRRZ T,ENCS' + JRST @ENCT(T) + +ENCT: ENC1 + ENC2 + ENC1 + ENCZ2 + +ENCDO: SKIPA A,[3] +ENCDZ: MOVEI A,0 +ENCD: ANDI A,3 + HRRZ T,ENCS + JRST @ENCDT(T) + +ENCDT: ENC2A + [JRST 4,.] + ENCZ2A + [JRST 4,.] + +ENC1: HRLM A,ENCS +ENC1A: AOS ENCS + POPJ P, + +ENC2: ROT A,-1 + HLR A,ENCS + ROT A,2 + JRST ENC2B +ENC2A: LSH A,1 + AOS ENCS +ENC2B: JUMPE A,ENC1A +C1: TRO A,1 + IDPB A,DSKBP' +ENC3: SETZM ENCS + POPJ P, + +ENCZ2: ROT A,-1 + HLR A,ENCS + JRST .+2 +ENCZ2A: ROT A,-1 + ASH A,2 + TRO A,2 + IDPB A,DSKBP + ROT A,2 + TRO A,5 + IDPB A,DSKBP + JRST ENC3 + +ENCH: LSH B,36.-28. + SKIPA C,[14.] +ENCW: MOVEI C,18. + LSHC A,2 + PUSHJ P,ENCD + SOJG C,.-2 + POPJ P, + +ENCI: MOVEM I,DSKBP + SETZM ENCS + POPJ P, + +RDLAT: CONI DC1,A ;READ LATENCY TIMER INTO A + LDB A,[DSLAT A] +RDLAT2: MOVEM A,T + CONI DC1,A + LDB A,[DSLAT A] + CAME A,T + JRST RDLAT2 + POPJ P, + +STBLK: MOVEM A,(D) ;STORE C(A) IN B WORDS AT D + SOJLE B,[AOJA D,CPOPJ] + HRLI D,1(D) + ADDI B,1(D) + MOVS D,D + EXCH B,D + BLT B,-1(D) + POPJ P, + +STOBLK: MOVE A,[QCOPY EONES,LOBLK,] + IDIVI B,LOBLK + JUMPE B,STOBL3 ;LESS THAN ONE BLOCK NEEDED?? + JUMPE C,STOBL2 + CAIL C,3 + JRST STOBL2 + SOJ B, + ADDI C,LOBLK +STOBL2: PUSHJ P,STBLK +STOBL3: CAIGE C,3 + MOVEI C,3 + MOVNI C,(C) + DPB C,[DCWC A] + MOVEM A,(D) + AOJA D,CPOPJ + +HBLK: QCOPY PREAMB,3, ;NORMAL HEADER + QCOPY .,3, + QCOPY POSTMB,7, + +WRTRI: QCOPY PREAMB,3, ;READIN HEADER, DATA BLOCK + QCOPY RIHEDR,3, + QCOPY POSTMB,7, + QCOPY EZERS,, + QCOPY EONES,3, + +RCBLK: DALU+DLCC+DLLB -401*NSECS(3) ;READ COMPARE "LOOP" FOR DATA WORDS + DRCC + QCOPY ZERS,4 + DJMP+DAOJNC . + DHLT + +LOBLK==60 + +DHED0: 0 +DHED1: -2004&37777 +DHEDR: BLOCK 3*NSECS + + +RIHED0: 0 +RIHED1: -LRIBLK&37777 +RIHEDR: BLOCK 3 + +EZERS: REPEAT LRIBLK*3/2+3,252525252525 + +EONES: REPEAT LOBLK+3,-1 + +PREAMB: -1 ;ONES + -26 ;ONES...0.1010 + 655326553265 ;1.10101.10101.10101.10101.10101.10101.10101 + +POSTMB: REPEAT 6,-1 ;ONES...01 + -3 + +ZERS: BLOCK 4 +];DC + +RH,[ + SUBTTL RH-10 PACK FORMATTING + +MARK: JSR INIT + SETZM CERRS +KL,[ SWPUA ;TURN THE CACHE OFF + CONSZ APR,200000 + JRST .-1 + CONI PAG,A + TRZ A,600000 + CONO PAG,(A) +];KL + X CRR + UNTMES FORMAT PACK ON UNIT # + X NTYI + JRST MARK + CAIL A,NUNITS + JRST MARK + X CRR + MOVE I,A + MOVEM I,TOU + SETOM MARKF + PUSHJ P,RESET + SETZM MARKF + TYPE ARE YOU SURE YOU WANT TO FORMAT PACK ON DRIVE # + X TOPT + TYPE ? + X TYI + X CRR + CAIE A,"Y + JRST DDT + TYPE PACK NO = + PUSHJ P,DTYI + PUSHJ P,CRR + MOVEM A,PKNUM(I) + MOVSI A,%HRSER ;GET DRIVE SERIAL NUMBER + PUSHJ P,RHGET + JRST RHMKER + HRLZ D,A + TLZ D,600000 ;FIRST "KEY" WORD IS SERIAL NO OF DRIVE FORMATTED ON + HRR D,PKNUM(I) ;SECOND "KEY" WORD IS I.T.S. PACK NUMBER + SETZB A,B ;GENERATE PATTERN FOR SURFACE +RHFMP1: MOVEM B,CYLBUF(A) ;CYL 0 TRACK 0 SECTOR (B) IS FIRST HEADER WORD + MOVEM D,CYLBUF+1(A) ;PUT DRIVE SERIAL NUMBER IN 3.1-4.7 OF HDR WD 2 + ADDI A,2 + SETZB C,H ;FILL SECTOR WITH WORST CASE PATTERN +RHFMP2: MOVE T,RHWC(H) + MOVEM T,CYLBUF(A) + AOS H + CAIL H,RHWCL + MOVEI H,0 + AOS A + CAIGE C,200-1 + AOJA C,RHFMP2 + CAIGE B,NSECS-1 ;DO NEXT SECTOR + AOJA B,RHFMP1 + CAIE A,202*NSECS + JRST 4,. ;WRONG AMOUNT OF CRUFT GENERATED + MOVE A,[-202*NSECS_4,,CYLBUF-1] ;SET UP IOWD + MOVEM A,SLVIOWD + SETZM SLVIOWD+1 + MOVEI A,SLVIOWD + MOVEM A,SLVICWA + JRST RHFMT0 ;GO FORMAT + +RHWC: 726666666676 ;RP04 10-MODE WORST CASE PATTERN + 555555555753 + 333333337266 + 666666765555 + 555557533333 + 333372666666 + 667655555555 + 573333333333 +RHWCL==.-RHWC + +RHMKER: TYPE DISK ERROR + X CRR + PUSHJ P,GSTS + JRST DDT + +RHFMT0: MOVEI J,NCYLS+XCYLS +RHFMT1: SOJL J,RHFMT4 ;LOOP ON CYLINDERS + MOVEI K,NHEDS +RHFMT2: SOJL K,RHFMT1 ;LOOP ON SURFACES + MOVEI B,NSECS ;ADJUST THE HEADER WORDS + MOVEI C,0 +RHFMT3: DPB J,[221100,,CYLBUF(C)] + DPB K,[100500,,CYLBUF(C)] + ADDI C,202 + SOJG B,RHFMT3 + MOVSI A,%HRADR ;SET UP ADDRESS IN DRIVE + DPB K,[$HATRK A] + PUSHJ P,RHSET + JRST RHMKER + MOVSI A,%HRCYL ;LEAVE CYLINDER NUMBER IN RH10 "DIB" LIGHTS + HRR A,J + PUSHJ P,RHSET + JRST RHMKER + SETZM SLVICWA+1 + MOVSI A,%HRCTL ;SET UP WRITE HEADERS AND DATA COMMAND + HRRI A,%HMWHD + MOVEI B,SLVICWA + DPB B,[$HCICWA A] + PUSHJ P,RHSET + JRST RHMKER + CONSO DSK,%HIDONE + JRST .-1 + CONSZ DSK,%HIERR + JRST RHMKER + JRST RHFMT2 + +RHFMT4: TYPE FORMATTING COMPLETE, VERIFICATION BEGINS + X CRR + MOVEI J,NCYLS+XCYLS-1 +RHFMT5: MOVEI A,CYLBUF + PUSHJ P,READCY + JUMPGE T,RHFMT6 + TYPE CYLINDER + MOVE A,J + X TOPT + TYPE IN ERROR + X CRR + X GSTS + X CRR + JRST RHFMT9 + +RHFMT6: SETZB A,H ;VERIFY DATA. RELIES ON SECTOR SIZE BEING +RHFMT7: MOVE B,CYLBUF(A) ; A MULTIPLE OF RHWCL + CAME B,RHWC(H) + PUSHJ P,RHFMT8 + ADDI H,1 + CAIL H,RHWCL + MOVEI H,0 + CAIGE A,200*NSECS + AOJA A,RHFMT7 +RHFMT9: SOJGE J,RHFMT5 + SKIPN A,CERRS + JRST RHFMTX + X TDPT + TYPE ECC-CORRECTED ERRORS DURING VERIFICATION. +RHFMTX: X CRR + JRST MARK69 ;HARDWARE FORMATTED, DO SOFTWARE + +RHFMT8: PUSH P,A + TYPE WORD + X TOPT + TYPE OF CYLINDER + MOVE A,J + X TOPT + TYPE CORRECT + MOVE A,RHWC(H) + X TOPT + TYPE ACTUAL + MOVE A,B + X TOPT + X CRR + JRST POPAJ +];RH + +RP,[ + SUBTTL RP-10 PACK FORMATTING + +MARK: JSR INIT +KL,[ SWPUA ;TURN THE CACHE OFF + CONSZ APR,200000 + JRST .-1 + CONI PAG,A + TRZ A,600000 + CONO PAG,(A) +];KL + X CRR + UNTMES FORMAT PACK ON UNIT # + X NTYI + JRST MARK + CAIL A,NUNITS + JRST MARK + X CRR + MOVE I,A + MOVEM I,TOU + SETOM MARKF + PUSHJ P,RESET + SETZM MARKF + MOVSI A,(DNOOPC) ;DETERMINE TYPE OF DRIVE + DPB I,[DUNFLD A] + DATAO DPC,A + DATAI DPC,A + MOVEI B,"2 + MOVEI C,NCYLS+XCYLS + TRNN A,2000 + JRST .+3 + MOVEI B,"3 + MOVEI C,MCYLS+XCYLS + MOVEM C,LAST + TLNE A,1 + JRST [ TYPE WRITE HEADER LOCKOUT SWITCH IS ON + JRST CRDDT ] + TYPE ARE YOU SURE YOU WANT TO FORMAT PACK ON RP0 + MOVE A,B + X TYO + TYPE # + MOVE A,I + X TOPT + TYPE ? + X TYI + X CRR + CAIE A,"Y + JRST DDT + TYPE PACK NO = + PUSHJ P,DTYI + PUSHJ P,CRR + MOVEM A,PKNUM(I) + SETZB A,B ;GENERATE TEMPLATE TRACK +RPFMP1: MOVEI T,31. ;SYNC ZONE OF 30 ZERO WORDS + SETZM CYLBUF(A) + AOS A + SOJG T,.-2 + AOS CYLBUF-1(A) ;AND ONE WORD CONTAINING 1 IN BIT 35 + MOVEM B,CYLBUF(A) ;THEN ADDRESS WORD +REPEAT 4,SETZM CYLBUF+1+.RPCNT(A) ;THEN ADDR PARITY WORD AND 3 ZERO WORDS SYNC + ADDI A,5 + MOVE T,RPWC ;THEN 128 DATA WORDS OF WORST CASE PATTERN + MOVEM T,CYLBUF(A) + MOVSI T,CYLBUF(A) + HRRI T,CYLBUF+1(A) + BLT T,CYLBUF+177(A) + ADDI A,200 + CAIGE B,NSECS-1 ;DO NEXT SECTOR + AOJA B,RPFMP1 + CAIE A,244*NSECS + JRST 4,. ;WRONG AMOUNT OF CRUFT GENERATED + MOVE A,[-244*NSECS,,CYLBUF-1] ;SET UP IOWD + MOVEM A,SLVIOWD + SETZM SLVIOWD+1 + MOVEI A,SLVIOWD + MOVEM A,SLVICWA + JRST RPFMT0 ;GO FORMAT + +RPMKER: TYPE DISK ERROR + X CRR + PUSHJ P,GSTS + JRST DDT + +RPFMT0: MOVE J,LAST ;HIGHEST CYLINDER # + 1 +RPFMT1: SOJL J,RPFMT4 ;LOOP ON CYLINDERS + MOVEI K,NHEDS +RPFMT2: SOJL K,RPFMT1 ;LOOP ON SURFACES + MOVEI B,NSECS ;ADJUST THE HEADER WORDS + MOVEI C,0 +RPFMT3: DPB J,[121100,,CYLBUF+37(C)] + DPB K,[050500,,CYLBUF+37(C)] + MOVE D,CYLBUF+37(C) ;COMPUTE HEADER PARITY WORD + MOVEI T,36. + MOVSI TT,(SETZ) ;ODD PARITY +RPFMTP: TRNE D,1 + TLC TT,(SETZ) + ROT D,1 + SOJG T,RPFMTP + MOVEM TT,CYLBUF+40(C) + ADDI C,244 + SOJG B,RPFMT3 + MOVSI A,300000 ;WRITE FORMAT + ADDI A,SLVICWA + DPB J,[DCYL A] + ROT J,-8 ;EXTRA BIT FOR RP03 + DPB J,[DCYLXB A] + ROT J,8 + DPB K,[DSURF A] + DPB I,[DUNFLD A] + MOVEM J,RPIOCY + PUSHJ P,SEEK + JRST RPMKER + DATAO DPC,A + CONSO DPC,DONE + JRST .-1 + CONSZ DPC,ALLER + JRST RPMKER + JRST RPFMT2 + +RPFMT4: TYPE FORMATTING COMPLETE, VERIFICATION BEGINS + X CRR + SOS J,LAST +RPFMT5: MOVEI A,CYLBUF + PUSHJ P,READCY + JUMPGE T,RPFMT6 + TYPE CYLINDER + MOVE A,J + X TOPT + TYPE DOESN'T READ -- GIVING UP ON IT. + X CRR + X GSTS + X CRR + JRST RPFMT9 + +RPFMT6: SETZB A,H ;VERIFY DATA. + MOVE D,RPWC + LSH D,1 ;CONTROL DROPS ONE BIT DURING WRITE FORMAT +RPFMT7: MOVE B,CYLBUF(A) + CAME B,D + PUSHJ P,RPFMT8 + CAIGE A,200*NSECS + AOJA A,RPFMT7 +RPFMT9: SOJGE J,RPFMT5 + X CRR + JRST MARK69 ;HARDWARE FORMATTED, DO SOFTWARE + +RPFMT8: PUSH P,A + TYPE WORD + X TOPT + TYPE OF CYLINDER + MOVE A,J + X TOPT + TYPE CORRECT + MOVE A,RPWC + X TOPT + TYPE ACTUAL + MOVE A,B + X TOPT + X CRR + JRST POPAJ + +RPWC: 714533,,462556 ;WORST CASE PATTERN +];RP +CONSTA +];NTS + NTS,[ +SUBTTL MFDR - RECONSTRUCT MFD FROM UFDS + +MFDR: MOVEI P,PDL + PUSHJ P,CRR ;RECONSTRUCT MFD BY GETTING NAMES FROM UFD'S + UNTMES RECONSTRUCT MFD FROM UNIT # + PUSHJ P,NTYI + JRST MFDR + MOVE I,A + PUSHJ P,MFDINN + SETOM IMNFLG + MOVEI J,0 +MFDR1: MOVEI A,TUT + PUSHJ P,READ + JUMPL T,MFDRL + MOVE B,TUT+UDESCP ;LOOK LIKE LEGIT UFD? + TLNE B,-1 + JRST MRUFDL ;SHOULD BE F.S. PNTR + CAIL B,<2000.-11.>*6 + JRST MRUFDL + MOVE B,TUT+UDNAMP + SKIPE TUT+UDNAME ;USER NAME + TLNE B,-1 + JRST MRUFDL ;PNTR TO BEG OF NAME AREA + MOVEI B,(J) ;CONVERT BLOCK NO TO MFD INDEX + SUB B,NUDS + LSH B,1 + ADDI B,2000 + MOVE C,TUT+UDNAME ;USER NAME + MOVEM C,MFD(B) + AOSN IMNFLG + MOVEM B,MFD+MDNAMP + JRST MRUFDW + + +MFDRL: JRST 4,.+1 +MRUFDL: JFCL +MRUFDW: + ADDI J,1 + CAMGE J,NUDS + JRST MFDR1 + TYPE WRITE? + PUSHJ P,TYI + CAIE A,"Y + JRST DDT +MFDWR: MOVEI A,MFD + MOVE J,MFDBK + PUSHJ P,WRITE + JRST DDT +];NTS + +IMNFLG: 0 + +SUBTTL INITIALIZE MFD + +MFDINN: CLEARM MFD + MOVE A,[MFD,,MFD+1] + BLT A,MFD+1777 + MOVE A,[SIXBIT /M.F.D./] + MOVEM A,MFD+MDCHK + MOVE A,NUDS + MOVEM A,MFD+MDNUDS + MOVEI A,2000 + MOVEM A,MFD+MDNAMP + POPJ P, + +SUBTTL INITIALIZE TUT + +;DRIVE NUMBER IN I, SWAPPING ALLOC IN A + +TUTINI: CLEARM TUT + MOVE B,[TUT,,TUT+1] + BLT B,TUT+<2000*MXTUTB>-1 + MOVEM A,TUT+QSWAPA + MOVE K,A + CAMGE K,NUDS + MOVE K,NUDS ;K HAS BASE OF FILE AREA + MOVEI J,NBLKS ;DETERMINE HOW MANY BLOCKS THIS DRIVE +RP,[ MOVSI A,(DNOOPC) + DPB I,[DUNFLD A] ;SELECT DRIVE + DATAO DPC,A + DATAI DPC,A + TRNE A,2000 + MOVEI J,MBLKS ;RP03 HAS MORE BLOCKS +];RP +IFN T300P,[ + CAIL I,T300P + MOVEI J,NBLKS1 +];T300P + MOVEM J,TUT+QLASTB ;LAST REGULAR BLOCK IS LAST TUT'ED +IFN T300P,[ + MOVEI A,<2000*NTUTBL-LTIBLK>*TUTEPW + CAIL I,T300P + MOVEI A,<2000*NTUTB1-LTIBLK>*TUTEPW + SUB J,A +];T300P +.ELSE SUBI J,<2000*NTUTBL-LTIBLK>*TUTEPW ;SUBTRACT MAX NUMBER OF TUTABLE BLOCKS + CAMLE J,K ;IS THERE ROOM FOR ALL OF FILE AREA? + JRST 4,. ;NOPE + SKIPGE J + MOVEI J,0 + MOVEM J,TUT+QFRSTB + MOVEI A,TUT +TUTFIL: MOVEI K,TUTLK ;ENTER HERE FROM SALV1, A -> TUT + MOVSI D,440000+TUTBYT_6 + ADDI D,LTIBLK(A) + MOVE B,NUDS + SUB B,QFRSTB(A) + JUMPLE B,TUTI1A +TUTI1: IDPB K,D ;MARK OUT USER DIR AREA + SOJG B,TUTI1 + +TUTI1A: MOVEI B,(A) + MOVSI D,-LSBTAB +TUTI2: SKIPGE J,SBTAB(D) + JRST TUTI3 ;NOT REALLY THERE + PUSHJ P,TUTPNT + MOVEI K,TUTLK + DPB K,J ;MARK OUT BLOCK +TUTI3: AOBJN D,TUTI2 + MOVE D,NTBL(I) ;MARK OUT TUT (SIZE VARIES) +TUTI4: MOVE J,MFDBK + SUB J,D + PUSHJ P,TUTPNT + MOVEI K,TUTLK + DPB K,J + SOJG D,TUTI4 + POPJ P, + +;TUTPNT - ROUTINE TO ACCESS THE TUT +; CALL WITH BLOCK NUMBER IN J, POINTER TO TUT IN B +; RETURNS WITH BYTE POINTER IN J (0 IF BLOCK NOT TUT'ED) +; K IS CLOBBERED +; +;TUTPNN - SAME BUT CALL WITH DISK NUMBER IN I, CLOBBERS B TO NEW TUT ADDR +; +;TUTPNO - SAME BUT CALL WITH DISK NUMBER IN I, CLOBBERS B TO OLD TUT ADDR + +TUTPNN: SKIPA B,QNTUTO(I) + +TUTPNO: MOVE B,QOTUTO(I) + +TUTPNT: CAMGE J,QLASTB(B) + CAMGE J,QFRSTB(B) + TDZA J,J + CAIA + POPJ P, ;BLOCK NOT TUT'ED, RETURN J=0 + SKIPGE QPKNUM(B) + JRST [ TYPE OLD FORMAT TUT? + JRST ERRDDT ] + SUB J,QFRSTB(B) + IDIVI J,TUTEPW + HLL J,QTTBL(K) + ADDI J,LTIBLK(B) + POPJ P, + SUBTTL MAIN SALVAGER + +GOGO: JRST GOGO0 ;VECTOR OF MYSTERIES +SALVAG: JRST GOGO1 ;(IN CASE UP CREEK WITHOUT SYMBOL TABLE) +CHKR: JRST CHKR0 +NTS,[ + JFCL LPBUST ;-> LPT BUSTED FLAG + JFCL NOQUES ;-> NO QUESTIONS FLAG + JFCL GOODUN ;-> ONLY ROUTINE THAT KNOWS WHICH ARE "RIGHT" PACKS + JFCL GETSTS ;-> ROUTINE TO TYPEOUT CURRENT DISK STATUS + JFCL DSKTST ;-> SIMPLE READ/WRITE TEST + JFCL SEKTST ;-> SIMPLE SEEK TEST (READ ONLY) + JFCL DUP ;-> DISK COPYING ROUTINE + JFCL HCRASH ;-> AS FAST AS POSSIBLE FLAG +];NTS + +GOGO1: JSR INIT + SETOM NOQUES ;IF STARTED BY BEG$G IN ITS, BE FAST. + JRST GOGO2 ;(NO ROUTINE TYPEOUT) + +GOGO0: JSR INIT +GOGO2: SETOM GOGOX ;AUTOMATIC MODE + TYPE SALVAGER. + MOVE A,[.FNAM2] + X T6B + X CRR + MOVEI A,NUNITS-1 + SETOM QACT(A) ;ALL UNITS ACTIVE + SOJGE A,.-1 + PUSHJ P,ACTUN ;ACTIVATE ALL UNITS THAT ARE ON-LINE + PUSHJ P,GOODUN ;MAKE SURE ALL PACKS THAT SHOULD BE MOUNTED ARE + MOVEM I,MDSK ;FIRST ACTIVE UNIT IS DSK TO GET MFD FROM + MOVEM I,UDSK ;.. DSK TO GET UFD'S FROM + PUSHJ P,DRPHAS ;VERIFY THAT DIRECTORIES ON ALL PACKS ARE IN PHASE + SETZM CKFLSW ;DON'T CHECK ALL BLOCKS + JRST SALV1 + +CHKR0: JSR INIT ;ASK QUESTIONS MODE + TYPE SALVAGER. + MOVE A,[.FNAM2] + PUSHJ P,T6B + PUSHJ P,CRR + MOVEI A,NUNITS-1 + SETZM QACT(A) + SOJGE A,.-1 + TYPE ACTIVE UNITS ARE: +CHKR1: PUSHJ P,NTYI + JRST CHKR2 + CAIGE A,NUNITS + SETOM QACT(A) + JRST CHKR1 + +CHKR2: PUSHJ P,CRR + PUSHJ P,ACTUN +CHKR3: UNTMES USE MFD FROM UNIT: + PUSHJ P,NTYI + JRST CHKR3 + CAIGE A,NUNITS + SKIPN QACT(A) + JRST CHKR3 + MOVEM A,MDSK + PUSHJ P,CRR + PUSHJ P,DRPHAS ;VERIFY THAT DIRECTORIES ON ALL PACKS ARE IN PHASE + SETZM CKFLSW + SETZM CKFIX +DC, TYPE CHECK FILES FOR CLOBBERED BLOCKS? +.ELSE TYPE READ ALL BLOCKS OF ALL FILES? + PUSHJ P,TYI + CAIN A,"Y + SETOB A,CKFLSW + PUSHJ P,CRR + JUMPGE A,CHKR4 +DC,[ TYPE FIX POINTERS THEN? + SETOM CKFIX + X Y.OR.N + SETZM CKFIX +];DC +CHKR4: UNTMES GET USR DIRS FROM UNIT: + PUSHJ P,NTYI + JRST CHKR4 + CAIGE A,NUNITS + SKIPN QACT(A) + JRST CHKR4 + PUSHJ P,CRR + MOVEM A,UDSK + JRST SALV1 + +ACTUN: MOVEI C,NUNITS-1 +ACTUN2: SKIPN QACT(C) + JRST ACTUN1 + MOVE I,C + PUSHJ P,RESET + SKIPN QACT(C) ;STILL THERE? + JRST ACTUN1 + MOVE I,C + MOVE A,QOTUTO(I) + PUSHJ P,RDTUT + JUMPL T,ACTUE1 + MOVE I,QOTUTO(C) + MOVE A,QPKNUM(I) + ANDI A,37 + MOVEM A,QPKN(C) + SKIPE NOQUES + JRST ACTUN1 + TYPE UNIT # + MOVE A,C + PUSHJ P,DPT + TYPE ID IS + MOVE A,QPAKID(I) + PUSHJ P,T6B + TYPE PK # + MOVE A,QPKNUM(I) + PUSHJ P,TDPT +IFN DC10P+RH10P,[ + MOVE A,PKNUM(C) + CAMN A,QPKNUM(I) + JRST ACTUN4 +IFN T300P,[ + CAIL C,T300P + JRST ACTUN4 ;PKNUM NOT REALLY SET UP +];T300P + TYPE (HARDWARE SAYS + PUSHJ P,TDPT + TYPE ) +ACTUN4: ] + SKIPN A,QTRSRV(I) + JRST ACTUN5 + CAMN A,[-1] + JRST [ TYPE (RESERVED) + JRST ACTUN5 ] + PUSHJ P,TSPAC + PUSHJ P,SIXTYP + TYPE : +ACTUN5: PUSHJ P,CRR +ACTUN1: SOJGE C,ACTUN2 + SETOM ACTIVE + POPJ P, + +ACTUE1: TYPE Error reading TUT block + PUSHJ P,CRR + PUSHJ P,GSTS + JRST ERRDDT + +ACTUE3: TYPE Error reading MFD block + PUSHJ P,CRR + PUSHJ P,GSTS + JRST ERRDDT +ACTIVE: 0 ;-1 IF ALREADY HAVE RESET DRIVES + +;MAKE SURE ALL NECESSARY PACKS ARE MOUNTED +GOODUN: +NTS,[ MOVEI A,FIRSPK ;AND RETURN MASTER DISK # IN I +GOODN1: MOVEI C,NUNITS-1 +GOODN2: SKIPE QACT(C) + CAME A,QPKN(C) + SOJGE C,GOODN2 + JUMPL C,GOODN3 ;THIS PACK MISSING + CAIGE A,LASTPK + AOJA A,GOODN1 + MOVEI A,LASTPK-FIRSPK+1 ;NUMBER OF PRIMARY PACKS + MOVEI C,NUNITS-1 ;SCAN FOR SECONDARY PACKS +GOODN4: SKIPN QACT(C) + JRST GOODN5 + MOVE B,QOTUTO(C) + SKIPE B,QTRSRV(B) + CAMN B,[-1] + JRST GOODN5 + ADDI A,1 ;THIS SECONDARY PACK IS OK TO HAVE MOUNTED +GOODN5: SOJGE C,GOODN4 +];NTS + MOVEI C,NUNITS-1 ;AND FIND MASTER DISK (LOWEST NUMBERED ACTIVE UNIT) + SKIPE QACT(C) ;ALSO COMPUTE GOOD PACKS - ALL PACKS IN A + JRST [ MOVE I,C + SOJA A,.+1 ] + SOJGE C,.-2 +NTS, JUMPGE A,CPOPJ +NTS, TYPE EXTRA PACKS MOUNTED. +NTS, JRST ERRDDT +TS, POPJ P, + +GOODN3: TYPE PACK # + X TDPT + TYPE NOT MOUNTED + JRST ERRDDT + +TS, DRPHAS: POPJ P, +NTS,[ +;CHECK THAT DIRECTORIES ARE IN PHASE ON ALL PACKS +DRPHAS: MOVEI I,NUNITS-1 +DRPHS1: SKIPN QACT(I) ;FIRST, GET ALL THE MFDS + JRST DRPHS2 + MOVE J,MFDBK + MOVE A,QNTUTO(I) + PUSHJ P,READ + JUMPL T,ACTUE3 +DRPHS2: SOJGE I,DRPHS1 + MOVE I,MDSK ;GET MASTER DISK'S ASCENDING DIRECTORY NUMBER + MOVE A,@QNTUTO(I) .SEE MDNUM + MOVE B,A + SUBI B,1 + MOVEI I,NUNITS-1 ;SEE IF ALL OTHERS ARE THE SAME, OR AT MOST 1 LESS +DRPHS3: SKIPE QACT(I) + JRST [ CAMG B,@QNTUTO(I) .SEE MDNUM + CAMGE A,@QNTUTO(I) .SEE MDNUM + JRST DRPHS6 + JRST .+1 ] + SOJGE I,DRPHS3 + POPJ P, + +DRPHS6: TYPE DIRECTORIES OUT OF PHASE. + X CRR + MOVEI I,0 +DRPHS4: SKIPN QACT(I) + JRST DRPHS5 + UNTMES UNIT # + HRRZ A,I + X TOPT + TYPE PACK # + MOVE A,QPKN(I) + X TDPT + TYPE , MDNUM= + MOVE A,@QNTUTO(I) .SEE MDNUM + X TOPT + X CRR +DRPHS5: CAIGE I,NUNITS-1 + AOJA I,DRPHS4 + TYPE VERIFY THAT THE PROPER PACKS ARE MOUNTED. IF YOU AREN'T SURE, + X CRR + TYPE GET HELP. IF THEY ARE PROPER, AND ONE IS JUST COMING ON-LINE + X CRR + TYPE AFTER BEING OFF FOR A WHILE, YOU WILL HAVE TO UCOP TO IT. + SKIPE GOGOX + JRST ERRDDT + JRST CRR +];NTS + +SALV1: SETZM MFDWRT ;-1 IF MFD MODIFIED (DIRECTORIES DELETED) + SETZM SHARED + MOVEI I,NUNITS-1 +SALV2: SKIPN QACT(I) + JRST SALV3 + HRRZ B,QNTUTO(I) ;ZERO OUT NEW TUT + HRL B,B + SETZM (B) + MOVE A,B + AOS B + BLT B,2000*MXTUTB-1(A) + HRRZ B,QNTUTO(I) ;COPY RANDOM INFO FROM OLD TUT TO NEW + HRL B,QOTUTO(I) + MOVE A,B + BLT A,LTIBLK-1(B) + HRRZ A,QNTUTO(I) + PUSHJ P,TUTFIL ;FILL IN BLOCKS AREA OF TUT +SALV3: SOJGE I,SALV2 + MOVE I,MDSK + MOVEI A,MFD + MOVE J,MFDBK + PUSHJ P,READ + JUMPL T,ACTUE3 + MOVE A,MFD+MDNUDS + CAME A,NUDS + JRST [ TYPE Wrong NUDSL version = + X TDPT + JRST ERRDDT] + MOVE A,MFD+MDCHK + CAME A,[SIXBIT /M.F.D./] + JRST [ TYPE MFD check word garbaged? + X T6B + X CRR + SKIPN GOGOX + X CONTIN + JRST ERRDDT + JRST .+1] + MOVE Q,MFD+MDNAMP + ADDI Q,MFD +MFDLUP: CAIL Q,MFD+2000 + JRST MFDFIN + SKIPN A,MNUNAM(Q) + JRST MFDLU1 + PUSHJ P,USRLUP + SKIPN LFILES + PUSHJ P,DELUSR +MFDLU1: ADDI Q,LMNBLK + JRST MFDLUP + +DELUSR: MOVE A,MNUNAM(Q) + CAMN A,[SIXBIT /.LPTR./] + POPJ P, + PUSHJ P,T6B + TYPE ; NO FILES, USER DIRECTORY DELETED + PUSHJ P,CRR + SETZM MNUNAM(Q) + SETOM MFDWRT + POPJ P, + +USRLUP: MOVEM A,USRNAM + SETZM UFDLOS + SETZM UFDSEE ;-1 IF ANY ERROR OCCURS, PRINT WHOLE UFD + SETZM LFILES + MOVE J,Q + SUBI J,MFD+2000 ;MAP MFD ENTRY INTO UFD BLOCK + IDIVI J,LMNBLK ; -Nth USER DIRECTORY + ADD J,NUDS ;END OF USER DIR AREA - N + PUSH P,Q + PUSH P,UDSK ;SAVE UFD DISK, MIGHT CHANGE IF UFD IS BAD + MOVEM J,DBLK + MOVE I,UDSK +USRLU1: MOVEI A,OUSRD ;COME BACK TO HERE ON TRY NEXT DRIVE + PUSHJ P,READ + JUMPL T,USRLE2 + MOVE Q,OUSRD+UDNAME + CAME Q,USRNAM + JSR USRLE4 + MOVE Q,[OUSRD,,NUSRD] + BLT Q,NUSRD+1777 ;COPY OLD FOR GARBAGE CHECK + MOVEI Q,2000-LUNBLK+OUSRD + MOVEI J,OUSRD + ADD J,UDNAMP(J) ;LOWEST FILE NAME BLOCK + CAIG J,OUSRD+2000 + CAIGE J,OUSRD+UDDESC + JRST USRLE3 ;NAME POINTER OUTSIDE BLOCK! (try next drive) + MOVE T,OUSRD+UDESCP + IDIVI T,6 + ADDI T,OUSRD+UDDESC + CAML T,J + JRST USRLE7 ;NAME AND DESCRIPTOR AREAS OVERLAP (try next drive) + PUSH P,J ; FILE NAME POINTER + +;PER FILE LOOP +DIRL1: CAMGE Q,J + JRST USRFIN + SETOM FILEER ; PRINT FILE NAME ONLY ON FIRST ERROR + SETZM BADFIL ; SET IF BAD RETRIEVAL DISCOVERED + MOVEM Q,LASTQ + SKIPN A,UNFN1(Q) + SKIPE UNFN2(Q) + CAIA + JRST DIRLUP + AOS LFILES + LDB C,[UNPKN UNRNDM(Q)] + LDB A,[UNDSCP UNRNDM(Q)] + CAML A,OUSRD+UDESCP + JRST DIRLE1 ;POINTS OUTSIDE DESC AREA (ignore) + IDIVI A,6 + ADDI A,OUSRD+UDDESC + HLL A,QBTBLI(B) + TLNE A,400000 + SUB A,[440000,,1] + MOVEI ZR,0 + LDB B,A + JUMPN B,DIRLE2 ;NOT PRECEEDED BY ZERO (ignore) +DIRL2: MOVE N,A + MOVEI J,0 + ILDB B,A + JUMPE B,DIRLE3 ;POINTS TO ZERO (ignore) +DIRL3: MOVE TT,UNRNDM(Q) + TLNE TT,UNLINK + JRST LINK + SETZM NOTUT + PUSHJ P,FINDPK ;FIND WHICH PACK + SKIPL C + SKIPN QACT(C) + SETOM NOTUT ;FILE ON UNMOUNTED PACK, DON'T HACK TUT + MOVEM C,FUNIT + SETZM LSTBLK + SETZM ADRSET +TRLUP: MOVE TT,N + ADDI TT,NUSRD-OUSRD + IDPB ZR,TT + ILDB B,N + JUMPE B,DIRLUP + CAIN B,UDWPH ; WRITE PLACE HOLDER, OR NULL FILE + JRST TRLUP + CAIL B,UDWPH + JRST LOAD + CAILE B,UDTKMX + JRST SKIPF + JRST TLUP + +TLUP: AOS Q +TLUP1: MOVE A,Q + SKIPN ADRSET + JRST DIRLE4 ;NO STARTING BLOCK (ignore untill jmp) + SKIPE NOTUT ;IF NOT ON ACTIVE UNIT, SKIP FILE + JRST CKFL3 + MOVE D,QOTUTO(C) + CAML A,QLASTB(D) + JRST DIRLE5 ;BLOCK OFF DSK (ignore block) + CAMGE A,QFRSTB(D) + JRST DIRLE5 + CAMGE A,NUDS + JRST DIRLE6 ;POINTS TO UFDS (ignore block) +CKFL2A: MOVSI D,-LSBTAB + CAMN A,SBTAB(D) + JRST DIRLE6 ;SPECIAL BLOCK + AOBJN D,.-2 + MOVE D,MFDBK + SUB D,NTBL(C) + CAML A,D + CAMLE A,MFDBK + CAIA + JRST DIRLE6 ;TUT +NTS,[ SKIPGE CKFLSW + PUSHJ P,CKFL +];NTS + MOVEM Q,LSTBLK + SKIPN NOTUT + SKIPN ADRSET + JRST CKFL3 + MOVE D,J ;SEE IF BLOCK LOCKED + SUBI D,NTUT0-OTUT0 ;(LOCK BYTES NOT IN NEW TUT YET) + ILDB D,D + CAIN D,TUTLK + PUSHJ P,DIRLEB + ILDB D,J + SKIPE D + JSR DIRLE7 ;SHARED BLOCK + CAIGE D,TUTMNY + AOS D + DPB D,J + MOVE K,J + SUBI K,NTUT0-OTUT0 + LDB D,K + JUMPE D,DIRLE9 +CKFL3: SOJG B,TLUP + JRST TRLUP + +OLDFIL: SETOM UFDSEE ;PRINT WHOLE UFD LATER + AOSE FILEER + JRST CKFL2A + TYPE !!! Over-writing user-directory area block + MOVE A,Q + X DPT + TYPE , BY + X PNTNAM + JRST CKFL2A + + +CKFL: PUSH P,J + PUSH P,I + SETOM XWDSEE + MOVE J,A + MOVEI A,FDBUF + MOVE I,C + PUSHJ P,READ +CKFLBP: JUMPL T,CKFLE1 +CKFL4: +DC,[ MOVE A,RXWDS+XWSYSN + CAME A,USRNAM + JRST CKFLE2 +CKFL5: LDB A,[XWBLK RXWDS] + CAME A,LSTBLK + JRST CKFL6 +CKFL6A: SKIPE CKFIX ;FIX ERRORS? + SKIPGE XWDSEE ;ANY ERRORS? + JRST CKFL7 + LDB A,[XWAWC RXWDS] + DPB A,[XWAWC WXWDS] + MOVE A,LSTBLK + DPB A,[XWBLK WXWDS] + MOVE A,USRNAM + MOVEM A,WXWDS+XWSYSN + MOVE Q,LASTQ + MOVE A,UNFN1(Q) + MOVEM A,WXWDS+XWFN1 + MOVE A,UNFN2(Q) + MOVEM A,WXWDS+XWFN2 + MOVEI A,FDBUF + PUSHJ P,WRITE + MOVEI A,FDBUF + PUSHJ P,READ + JUMPL T,CKFLE1 + LPR RETRIEVAL NOW: + PUSHJ P,LPTXWD + SETOM XWDSEE + JRST CKFL4 +];DC +CKFL7: POP P,I + POP P,J + POPJ P, + +CKFLE1: PUSHJ P,PNTNAM + TYPE ERROR READING BLOCK +CKFLE3: MOVE A,J + PUSHJ P,DPT + PUSHJ P,CRR + PUSHJ P,PNTXWD + PUSHJ P,GSTS + JRST CKFL4 +DC,[ +CKFLE2: JRST CKFL6A ;JFCL THIS IF YOU HATE ARCHIVES + AOS BADFIL + PUSHJ P,LPTNAM + X LTAB + X LPTXWD + X LTAB + LPR Retrieval User-name differs + LDB A,[XWBLK RXWDS] + CAMN A,LSTBLK + JRST [ X LCRR + JRST CKFL6A] + LPR , + JRST CKFLE4 + +CKFL6: JRST CKFL6A ;JFCL THIS IF YOU HATE ARCHIVES + AOS BADFIL + PUSHJ P,LPTNAM + X LTAB + X LPTXWD + X LTAB +CKFLE4: LPR Chain pointer wrong, Last block= + MOVE A,LSTBLK + PUSHJ P,LOPT + PUSHJ P,LCRR + JRST CKFL6A +];DC + +LOAD: SETOM ADRSET ;B HAS BYTE WHERE UDWPH < BYTE <=77 + ANDCMI B,20 ;DM FUNNY BITS + MOVEI J,-UDWPH-1(B) + MOVEI K,NXLBYT +LOAD1: MOVE TT,N + ADDI TT,NUSRD-OUSRD + IDPB ZR,TT + ILDB B,N + LSH J,6 + ADD J,B + SOJG K,LOAD1 + MOVE Q,J + SKIPE NOTUT + JRST LOAD2 ;THIS DRIVE NOT ACTIVE + MOVE I,C + PUSHJ P,TUTPNN ;GET POINTER TO NEW TUT + ADD J,[TUTBYT_14,,] ;BACK UP FOR ILDB +LOAD2: MOVEI B,1 + JRST TLUP1 + +SKIPF: SUBI B,UDTKMX + IBP J + AOS Q + SOJG B,.-2 + MOVEI B,1 + JRST TLUP + +LINK: MOVE TT,N + ADDI TT,NUSRD-OUSRD + PUSHJ P,LTYPE + JRST DIRLEC + PUSHJ P,LTYPE + JRST DIRLEC + PUSHJ P,LTYPE + JRST DIRLUP + ILDB B,N + JUMPE B,DIRLUP + JRST DIRLE8 ;LINK NOT FOLLOWED BY ZERO (ignore) + +LTYPE: MOVEI B,6 +LTYPE2: IDPB ZR,TT + ILDB A,N + JUMPE A,CPOPJ ;NON SKIP RETURN IF FOLLOWED BY ZERO + CAIN A,': + JRST [ ILDB A,N + IDPB ZR,TT + JRST LTYPE3] + CAIE A,'; +LTYPE3: SOJG B,LTYPE2 + JRST POPJ1 ;SKIP RETURN IF ENDS NATURALLY + +DIRLUP: SKIPN BADFIL + JRST DIRLP1 + TYPE BAD RETRIEVAL: + X PNTNAM +DIRLP1: MOVE Q,LASTQ + MOVE J,(P) + MOVSI A,UNMARK + ANDCAM A,UNRNDM(Q) + SUBI Q,LUNBLK + JRST DIRL1 + +FINDPK: PUSH P,B ;MAP PACK NUMBER IN C, TO UNIT NUMBER + MOVEI B,NUNITS-1 + CAMN C,QPKN(B) + JRST FINDP1 + SOJGE B,.-2 + SETOM C + POP P,B + POPJ P, + +FINDP1: HRRZ C,B + POP P,B + POPJ P, + +USRLE2: TYPE USR DIRECTORY READ ERROR + SETOM FLAG' ;HARDWARE ERROR +USRL2A: PUSHJ P,TSPAC + MOVE A,USRNAM + PUSHJ P,SIXTYP + MOVEI A,"; + PUSHJ P,TYO + PUSHJ P,CRR + SKIPE FLAG + PUSHJ P,GSTS ;PRINT CONTROLLER STATUS + SKIPE GOGOX + JRST ERRDDT + TYPE TRY NEXT DRIVE? + PUSHJ P,TYI + CAIE A,"Y + JRST CRDDT + PUSHJ P,CRR + MOVE I,UDSK +USRL2B: AOS I + CAIL I,NUNITS + SUBI I,NUNITS + SKIPN QACT(I) + JRST USRL2B + MOVEM I,UDSK ;WILL GET POPED BEFORE NEXT USER + SETOM UFDLOS ;CAUSE DIR TO BE WRITTEN ON ALL DRIVES + MOVE J,DBLK + JRST USRLU1 + +USRLE3: TYPE User directory name-pointer scrambled + SETZM FLAG + JRST USRL2A + +USRLE7: TYPE Name area, descriptor area overlap + SETZM FLAG + JRST USRL2A + +USRLE4: 0 ;USR NAME IN DIR DIFFERS + TYPE USER NAME IN DIRECTORY DIFFERS + PUSHJ P,TSPAC + MOVE A,USRNAM + PUSHJ P,T6B + TYPE ; BLOCK + MOVE A,DBLK + X DPT + UNTMES , UNIT + MOVE A,I + PUSHJ P,DPT + TYPE , DIR HAS + X TSPAC + MOVE A,OUSRD+UDNAME + X T6B + PUSHJ P,CRR + SKIPE GOGOX + JRST ERRDDT + TYPE CORRECT IT? (MFD ENTRY TAKEN AS GOOD) + PUSHJ P,TYI + X CRR + CAIE A,"Y + JRST ERRDDT + MOVE A,USRNAM + MOVEM A,OUSRD+UDNAME + MOVEI A,OUSRD + PUSHJ P,WRITE + JRST @USRLE4 + +USRLE5: SETOM UFDSEE + SKIPN GARBF + PUSHJ P,PGARBF + LPR , POINTER= + MOVE A,Q + PUSHJ P,LOPT + LPR , GARBAGE IS + MOVE A,NUSRD(Q) + ANDCAM A,OUSRD(Q) ;CLEAR OUT THE GARBAGE + PUSHJ P,LOPT + PUSHJ P,LCRR + AOJA Q,GARB6 + +PGARBF: LPR GARBAGE IN FREE AREA + PUSHJ P,LCRR + MOVE A,USRNAM + PUSHJ P,L6B + LPR ; Block # + MOVE A,DBLK + PUSHJ P,LOPT + PUSHJ P,LCRR + SKIPE GOGOX + JRST ERRDDT + SETOM UFDLOS + SETOM GARBF + POPJ P, + +USRLE6: SETOM UFDSEE + SKIPN EXGARB + PUSHJ P,PEXGAR + MOVE A,J + PUSHJ P,LOPT + PUSHJ P,LSPAC + MOVE A,B + PUSHJ P,LOPT + PUSHJ P,LCRR + MOVE TT,Q + SUBI TT,NUSRD-OUSRD + DPB ZR,TT + JRST GARB3 + +PEXGAR: LPR EXTRA GARBAGE IN UFD + PUSHJ P,LCRR + MOVE A,USRNAM + PUSHJ P,L6B + LPR ; Block # + MOVE A,DBLK + PUSHJ P,LOPT + PUSHJ P,LCRR + SKIPE GOGOX + JRST ERRDDT + SETOM UFDLOS + SETOM EXGARB + POPJ P, + + +PNTNAM: PUSH P,NOLPT + SETOM NOLPT + X LPTNAM + POP P,NOLPT + POPJ P, + +LPTNAM: PUSH P,A ;DIRLE5 ETC. + MOVE A,USRNAM + PUSHJ P,L6B + MOVEI A,"; + PUSHJ P,LTYO + CAIA +LPTFIL: PUSH P,A ;AVOID PDL SCREWAGE + PUSH P,B + PUSH P,C + MOVE B,LASTQ + MOVE A,UNFN1 (B) + PUSHJ P,L6B + PUSHJ P,LSPAC + MOVE A,UNFN2(B) + PUSHJ P,L6B + LDB C,[UNPKN UNRNDM(B)] + LPR PACK + MOVE A,C + X LDPT + X FINDPK ;FIND PACK FILE IS ON + JUMPL C,LPTFI1 + LPR , UNIT # + MOVE A,C + X LDPT +LPTFI1: PUSHJ P,LCRR + INSIRP POP P,[C B A] + POPJ P, + +PNTXWD: PUSH P,NOLPT + SETOM NOLPT + X LPTXWD + POP P,NOLPT + POPJ P, + +LPTXWD: +DC,[ + PUSH P,A + LPR Extra words: Block # + MOVE A,UNIT + X LDPT + MOVEI A,"- + X LTYO + MOVE A,BLK + X LOPT + X LSPAC + MOVE A,RXWDS+XWSYSN + PUSHJ P,L6B + MOVEI A,"; + PUSHJ P,LTYO + MOVE A,RXWDS+XWFN1 + PUSHJ P,L6B + PUSHJ P,LSPAC + MOVE A,RXWDS+XWFN2 + PUSHJ P,L6B + LPR , Chain pointer= + LDB A,[XWBLK RXWDS] + PUSHJ P,LOPT + LPR , active wd cnt= + LDB A,[XWAWC RXWDS] + PUSHJ P,LOPT + PUSHJ P,LCRR + POP P,A +];DC + SETZM XWDSEE .SEE CKFL6A + POPJ P, + DIRLE1: PUSHJ P,LPTNAM + LPR DESC POINTS OUT OF DESC AREA + PUSHJ P,LCRR + SKIPE GOGOX + JRST ERRDDT + SETOM UFDSEE + JRST DIRLUP + +DIRLE2: PUSHJ P,LPTNAM + LPR FILE NOT PRECEEDED BY ZERO + PUSHJ P,LCRR + SKIPE GOGOX + JRST ERRDDT + SETOM UFDSEE + JRST DIRL2 + +DIRLE3: PUSHJ P,LPTNAM + LPR FILE POINTS TO ZERO + PUSHJ P,LCRR + SKIPE GOGOX + JRST ERRDDT + SETOM UFDSEE + JRST DIRL3 + +DIRLE4: PUSHJ P,LPTNAM + LPR STARTING ADDRESS NOT SET +DIRL4A: X LCRR + SKIPE GOGOX + JRST ERRDDT + SETOM UFDSEE + JRST CKFL3 + +DIRLE5: PUSHJ P,LPTNAM + LPR BLOCK POINTS OFF DSK + X LOPT + JRST DIRL4A + +DIRLE6: PUSHJ P,LPTNAM + LPR BLOCK IN RESERVED AREA + X LOPT + JRST DIRL4A + +DIRLE7: 0 + PUSHJ P,LPTNAM + LPR SHARES BLOCK WITH SOME OTHER FILE + X LCRR + AOS SHARED ;SHARED BLOCK FLAG +; SKIPN NOLPT +; SETOM UFDSEE + SETZM SALVRT ;NO AUTOMATIC SYS START + JRST @DIRLE7 + +DIRLEC: PUSHJ P,LPTNAM + LPR LINK NOT THREE NAMES + JRST DIRLED + +DIRLE8: PUSHJ P,LPTNAM + LPR LINK NOT FOLLOWED BY A ZERO +DIRLED: PUSHJ P,LCRR + SKIPE GOGOX + JRST ERRDDT + SETOM UFDSEE + JRST DIRLUP + +DIRLE9: SKIPE NOQUES + JRST CKFL3 + LPR FILE UNPROTECTED IN OLD TUT - + X LPTNAM + LPR Block + MOVE A,Q + X LOPT + X LCRR + JRST CKFL3 + +DIRLEB: PUSHJ P,LPTNAM + LPR FILE CONTAINS LOCKED BLOCK + MOVE A,Q + X LOPT + SETZM SALVRT ;NO AUTO SYS STARTUP + JRST LCRR + +USRFIN: CLEARM GARBF + CLEARM EXGARB + CLEARB ZR,J + MOVE Q,[440600,,NUSRD+UDDESC] +GARB2: CAML J,OUSRD+UDESCP + JRST USRFN2 +GARB4: ILDB B,Q + JUMPN B,USRLE6 ;GARBAGE IN DESCRIPTOR AREA (clear out) +GARB3: AOJA J,GARB2 + +USRFN2: TLNE Q,770000 + JRST GARB4 + MOVEI Q,-NUSRD+1(Q) ;FIRST WORD ABOVE DESCRIPTOR AREA +GARB6: CAML Q,NUSRD+UDNAMP + JRST GARB5 + SKIPN NUSRD(Q) + AOJA Q,GARB6 + JRST USRLE5 ;GARBAGE IN NAME AREA (clear out) + +GARB5: SKIPE UFDSEE + PUSHJ P,UFDPR + SKIPN UFDLOS + JRST USRFN5 + SKIPE NOQUES + JRST GARB5A + TYPE UFD NEEDS UPDATE - WRITE? + X Y.OR.N + JRST USRFN5 +GARB5A: MOVEI A,OUSRD + MOVEI I,NUNITS-1 + MOVE J,DBLK +GARB7: SKIPE QACT(I) + PUSHJ P,WRITE + SOJGE I,GARB7 +USRFN5: POP P,J + POP P,UDSK + POP P,Q + POPJ P, + + +SUBTTL LISTF - DUMP OUT USER DIRECTORY +LISTF: JSR INIT + SKIPL ACTIVE ;ALREADY DID RESET + X ACTUN + X CRR + TYPE USER?= + X SIXIN + X CRR + JUMPE B,DDT + MOVEI I,NUNITS-1 + SETOM FUNIT +LISTF3: SKIPN QACT(I) + JRST LISTF2 + MOVEM I,FUNIT + MOVE A,QNTUTO(I) + PUSHJ P,RDTUT + JUMPL T,[TYPE ERROR READING TUT # + MOVE A,I + X DPT + X CRR + X GSTS + X CONTIN + JRST DDT + JRST .+1] +LISTF2: SOJGE I,LISTF3 + MOVEM B,USRNAM + MOVEI A,MFD + MOVE J,MFDBK + SKIPGE I,FUNIT ;USE FIRST ACTIVE UNIT + JRST LISTF4 ;NO DISKS ACTIVE?? + X READ + JUMPL T,[TYPE ERROR READING MFD + X CRR + X GSTS + X CONTIN + JRST DDT + JRST .+1] + MOVE D,USRNAM + MOVE Q,MFD+MDNAMP +LISTF1: CAIL Q,2000 + JRST [ TYPE USER NOT FOUND - + MOVE A,D + X T6B + JRST CRDDT] + CAME D,MFD(Q) + JRST [ ADDI Q,LMNBLK + JRST LISTF1] + SUBI Q,2000 + IDIVI Q,LMNBLK + HRRZ J,Q + ADD J,NUDS + MOVEM J,DBLK + MOVE I,FUNIT ;USE FIRST ACTIVE UNIT + MOVEI A,OUSRD + X READ + JUMPL T,[TYPE ERROR READING USER DIRECTORY + X CRR + X GSTS + X CONTIN + JRST CRDDT + JRST .+1] + X USEE0 + JRST CRDDT + +CONTIN: TYPE CONTINUE? + X TYI + X CRR + CAIN A,"Y + AOS (P) + POPJ P, + +LISTF4: TYPE NO ACTIVE UNIT TO GET DIR FROM + JRST CRDDT + +UFDPR: SETZM SALVRT ;NO AUTO SYS STARTUP + SKIPN NOLPT + JRST [ TYPE Errors in directory + MOVE A,OUSRD+UDNAME + X T6B + X CRR + JRST .+1 ] +USEE0: MOVE Q,OUSRD+UDNAME + PUSHJ P,LFORM + LPR USER DIRECTORY: + MOVE A,Q + X L6B + MOVEI A,"; + X LTYO + X LCRR + MOVEI J,OUSRD + ADD J,UDNAMP(J) + CAIG J,OUSRD+2000 + CAIGE J,OUSRD+UDDESC + JRST [ LPR UFD NAME AREA POINTER OUT OF RANGE + JRST USEEF ] + MOVE T,OUSRD+UDESCP + IDIVI T,6 + ADDI T,OUSRD+UDDESC + CAML T,J + JRST [ LPR DESCRIPTOR FREE POINTER OVERLAPS NAME AREA + JRST USEEF ] + MOVEM J,LAST + MOVEI Q,OUSRD+2000-LUNBLK +USEE1: CAMGE Q,LAST ;PER FILE LOOP + JRST USEEF + MOVEM Q,LASTQ + SKIPN A,UNFN1(Q) + SKIPE UNFN2(Q) + CAIA + JRST USEELP + X LPTFIL + LDB C,[UNPKN UNRNDM(Q)] + X FINDPK + MOVEM C,FUNIT ;KLUDGE KLUDGE (LOOKS AT TUTS) + LDB A,[UNDSCP UNRNDM(Q)] + CAML A,OUSRD+UDESCP + JRST [ LPR FILE DESCRIPTOR POINTER POINTS OUTSIDE DESCRIPTOR AREA + JRST USEELY ] + IDIVI A,6 + ADDI A,OUSRD+UDDESC + HLL A,QBTBLI(B) + TLNE A,400000 + SUB A,[440000,,1] + LDB B,A + X LTAB + X USBYTE + LPR (INITIAL ZERO) + JUMPN B,[ LPR - IS NOT PRESENT + JRST USEELY ] + X LCRR +USEE2: MOVE N,A + MOVEI J,0 + ILDB B,A ;PEEK AT NEXT BYTE + JUMPE B,[X USBYTE + LPR (FIRST BYTE SHOULD BE NON-ZERO) + JRST USEELY] ;SHOULD BE NON-ZERO + LDB A,[UNDSCP UNRNDM(Q)] + X LOPT ;SHOW DESC ADDR BEFORE FIRST DESC BYTE +USEE3: MOVE TT,UNRNDM(Q) + TLNE TT,UNLINK + JRST USLINK + ;FALLS THROUGH + SETZM ADRSET +USLUP: ILDB B,N + X LTAB + X USBYTE + JUMPE B,[LPR (STOP) + X LCRR + JRST USEELP] + CAIN B,UDWPH + JRST [ LPR (WRITE-PLACE-HOLDER) + X LCRR + JRST USLUP] + CAIL B,UDWPH + JRST USLOAD + CAILE B,UDTKMX + JRST USSKIP + LPR (TAKE-N BLOCKS) +USLP1: AOS Q +USLP2: MOVE A,Q + X LOPT + X LSPAC + SKIPGE TT,FUNIT + JRST USLP3 ;PACK NOT MOUNTED + MOVE TT,QOTUTO(TT) + CAMGE Q,QLASTB(TT) + SKIPN ADRSET + JRST USLPE ;BAD BLOCK + ILDB TT,J ;TUT ENTRY + CAMGE Q,NUDS + JRST USLPE + MOVSI D,-LSBTAB + CAMN Q,SBTAB(D) + JRST USLPE + AOBJN D,.-2 + MOVE A,FUNIT + MOVE D,MFDBK + SUB D,NTBL(A) + CAML Q,MFDBK + CAMLE Q,D + CAIA + JRST USLPE ;OVERLAPS TUT OR MFD + + SKIPL FUNIT ;FILE NOT ON ACTIVE UNIT + CAIN TT,1 + JRST USLP3 + LPR ?? TUT= + MOVE A,TT + X LDPT + LPR ?? +USLP3: SOJG B,USLP1 + X LCRR + JRST USLUP +USLPE: LPR ?? BAD BLOCK # ?? + JRST USLP3 + +USEELP: MOVE Q,LASTQ + SUBI Q,LUNBLK + JRST USEE1 + +USLOAD: SETOM ADRSET + ANDCMI B,20 ;DM FUNNY BITS + MOVEI J,-UDWPH-1(B) + MOVEI K,NXLBYT +USLOD1: ILDB B,N + X USBYTE + LSH J,6 + ADD J,B + SOJG K,USLOD1 + MOVE Q,J + SKIPGE I,FUNIT + TDZA J,J ;NO TUT + PUSHJ P,TUTPNO ;GET POINTER TO OLD TUT + ADD J,[TUTBYT_14,,] ;BACK UP FOR ILDB + LPR (JUMP + MOVE A,Q + X LOPT + LPR ) + MOVEI B,1 + JRST USLP2 + +USSKIP: SUBI B,UDTKMX + LPR (SKIP + MOVE A,B + X LOPT + LPR ) + IBP J + AOS Q + SOJG B,.-2 + MOVEI B,1 + JRST USLP1 + +USLINK: X LTAB + LPR (LINK) + X USLINP + JRST USLIN3 + MOVEI A,"; + X LTYO + X USLINP + JRST USLIN3 + X LSPAC + X USLINP + ADD N,[060000,,] ;ENDS WITH ZERO, RE-READ THE ZERO BYTE + X LCRR + ILDB B,N + X LTAB + X USBYTE + LPR (ZERO) + JUMPE B,USLIN4 + LPR ?? NO END ZERO ?? +USLIN4: X LCRR + JRST USEELP + +USLIN3: LPR ?? ENDS EARLY ?? + JRST USLIN4 + +USLINP: MOVEI B,6 +USLIN2: ILDB A,N + JUMPE A,CPOPJ ;NON SKIP RETURN IF FOLLOWED BY ZERO + CAIN A,'; + JRST POPJ1 ;SKIP RETURN IF ENDS NATURALLY + CAIN A,': ;QUOTE CHAR + ILDB A,N + ADDI A,40 + X LTYO + SOJG B,USLIN2 + JRST POPJ1 ;SKIP RETURN IF ENDS NATURALLY + +USBYTE: PUSH P,A + PUSH P,B + LDB A,[30300,,(P)] + ADDI A,"0 + X LTYO + LDB A,[300,,(P)] + ADDI A,"0 + X LTYO + X LSPAC + POP P,B + POP P,A + POPJ P, + +USEELY: X LCRR +USSELP: MOVE Q,LASTQ + SUBI Q,LUNBLK + JRST USEE1 + +USEEF: X LCRR + X LFORM + POPJ P, + +SUBTTL MAIN SALVAGER - WRITE MFD & TUT + +MFDFIN: MOVEI I,0 +MFDFN0: SKIPE QACT(I) + PUSHJ P,TUTCMP + CAIGE I,NUNITS-1 + AOJA I,MFDFN0 + SKIPN MFDWRT + JRST SHARCK ;MFD DIDN'T HAVE ANY CHANGES +MFDWR0: SKIPE NOQUES + JRST MFDWR1 + TYPE WRITE OUT CHANGES IN MFD? + X Y.OR.N + JRST SHARCK +MFDWR1: MOVE J,MFDBK + MOVEI I,NUNITS-1 +MFDWR2: MOVEI A,MFD + SKIPE T,QACT(I) + PUSHJ P,WRITE + JUMPGE T,MFDWR3 + PUSHJ P,GSTS ;ERROR WRITING MFD + SKIPN GOGOX + JRST MFDWR0 + JRST ERRDDT + +MFDWR3: SOJGE I,MFDWR2 + JRST SHARCK + +TUTCMP: SETZM TUTDFR ;FIRST SEE IF ANY DIFFERENCES + SETZM TTDFPS + SETZM NLKBKS' + SETZM TUTCHG ;MAKE SUMMARY TABLE OF DIFFERENCES + MOVE Q,[TUTCHG,,TUTCHG+1] + BLT Q,TUTCHG+-1 + MOVE Q,QTTBLI + HRR Q,QNTUTO(I) ;NEW B.P. + ADDI Q,LTIBLK + MOVE J,Q + HRR J,QOTUTO(I) ;OLD B.P. + MOVE TT,QFRSTB(J) ;BLOCK NUMBER + MOVE B,QLASTB(J) + SOS B + MOVEM B,TUTHIB' ;HIGHEST BLOCK # + ADDI J,LTIBLK +TUTC1: ILDB B,Q + ILDB D,J + CAMN B,D + JRST TUTC2 + CAIN D,TUTLK + JRST [ MOVE B,D ;IF LOCKED, STAY LOCKED + DPB B,Q + AOS NLKBKS ;COUNT BLOCKS LOCKED DUE TO DISK ERRORS + SKIPN GOGOX + PUSHJ P,LCKRPT ;IN CHKR MODE, REPORT LOCKED BLOCKS + JRST TUTC2 ] + PUSHJ P,TUTC4 +TUTC2: CAMGE TT,TUTHIB + AOJA TT,TUTC1 + SKIPN NOQUES + SKIPN A,NLKBKS + JRST TUTC3 + X TDPT + UNTMES LOCKED BLOCKS ON UNIT # + HRRZ A,I + X DPT + X CRR +TUTC3: SKIPN TUTDFR + POPJ P, ;NO DIFFERENCES THIS TUT + JRST TUTCM0 ;DIFFERENCES, GO HANDLE + +TUTC4: IMULI B,TUTMAX + ADD B,D + MOVE T,QOTUTO(I) ;DON'T LIST TUT CHANGES IN SWAPPING AREA + CAML TT,NUDS + CAML TT,QSWAPA(T) + AOS TUTCHG(B) + AOS TUTDFR + POPJ P, + +TUTCM0: SKIPE NOQUES ;HERE WHEN TUT HAS DIFFERENCES + JRST TUTCM3 ;IF NO QUESTIONS, JUST WRITE + MOVEI A,TUTMAX*TUTMAX-1 ;SEE IF ANY TUT DIFFERENCES NOT IN SWAPPING AREA + SKIPN TUTCHG(A) + SOJGE A,.-1 + JUMPL A,TUTCM4 ;NONE, GO ASK IF SHOULD WRITE + SETZM LINPOS ;OTHERWISE, SUMMARIZE TUT DIFFERENCES + TYPE TUT # + HRRZ A,I + X DPT + MOVEI B,TUTMAX-1 +TUTSM1: MOVEI D,TUTMAX-1 +TUTSM2: MOVE A,B + IMULI A,TUTMAX + ADD A,D + SKIPN A,TUTCHG(A) + JRST TUTSM3 + X TSPAC + X TDPT + X TSPAC + MOVE A,B + X DPT + TYPE _ + MOVE A,D + X DPT + MOVE A,LINPOS + CAIGE A,60. + JRST TUTSM3 + X CRR + SETZM LINPOS +TUTSM3: SOJGE D,TUTSM2 + SOJGE B,TUTSM1 + TYPE , PRINT? + X Y.OR.N + JRST TUTCM4 + +;HERE TO PRINT OUT THE TUT + + SETZM TUTDFR + MOVE Q,QTTBLI + HRR Q,QNTUTO(I) ;NEW B.P. + ADDI Q,LTIBLK + MOVE J,Q + HRR J,QOTUTO(I) ;OLD B.P. + MOVE TT,QFRSTB(J) ;BLOCK NUMBER + MOVE B,QLASTB(J) + SOS B + MOVEM B,TUTHIB' ;HIGHEST BLOCK # + ADDI J,LTIBLK +TUTCM1: ILDB B,Q + ILDB D,J + CAME B,D + JRST TUTDF1 +TUTCM2: CAMGE TT,TUTHIB + AOJA TT,TUTCM1 + + SKIPE TTDFPS + X LCRR + X LFORM ;SOMETHING PRINTED, ADVANCE LPT PAPER +TUTCM4: TYPE TUT # + HRRZ A,I + X DPT + TYPE NEEDS UPDATING - WRITE? + X Y.OR.N + POPJ P, +TUTCM3: + MOVE A,QNTUTO(I) + PUSHJ P,WRTUT + JUMPGE T,CPOPJ + PUSHJ P,GSTS ;ERROR WRITING TUT + SKIPN GOGOX + JRST TUTCM4 + JRST ERRDDT + +TUTMAX=1_TUTBYT + +TUTCHG: BLOCK TUTMAX*TUTMAX + +TUTDF1: MOVE T,QOTUTO(I) + CAML TT,NUDS + CAML TT,QSWAPA(T) + CAIA + JRST TUTCM2 ;IN SWAPPING AREA, IGNORE + PUSHJ P,NEWOLD + PUSH P,[TUTCM2] + AOSL TTDFPS + JRST TUTDF7 ;NO MORE ROOM ON LINE + MOVEI A,40 ;PRINT MULTIPLE FROBS PER LINE + PUSHJ P,LPTR ;SO THE LINE PRINTER WILL GO FASTER + JRST LPTR + +NEWOLD: SKIPN TUTDFR + PUSHJ P,TUTTYP + MOVE A,TT + PUSHJ P,LOPT + PUSHJ P,LSPAC + MOVE A,B + PUSHJ P,LOPT + MOVEI A,"_ + PUSHJ P,LPTR + MOVE A,D + JRST LOPT + +TUTTYP: SETOM TUTDFR + PUSHJ P,LCRR + LPR TUT DIFFERENCES FOR DRIVE # + HRRZ A,I + PUSHJ P,LOPT +TUTDF7: MOVNI A,5 ;START NEW LINE, ROOM FOR 5 BLOCKS IF TTY + SKIPN NOLPT + MOVNI A,9 ;OR 9 IF LPT + MOVEM A,TTDFPS + JRST LCRR + +LCKRPT: TYPE LOCKED BLOCK + HRRZ A,I + X TDPT + MOVEI A,"- + X TYO + MOVE A,TT + X TOPT + X CRR + POPJ P, + +SUBTTL TRACK DOWN SHARED BLOCKS + +SHARCK: SKIPN SHARED + JRST CRDDT ;NO SHARED TRACKS, WE ARE DONE + TYPE SHARED BLOCKS + PUSHJ P,LCRR + LPR LOOKING FOR SHARED BLOCKS + PUSHJ P,LCRR + MOVE I,MDSK + MOVEI A,MFD + MOVE J,MFDBK + PUSHJ P,READ + JUMPL T,ACTUE3 + MOVE Q,MFD+MDNAMP + ADDI Q,MFD +SMFDLP: CAIL Q,MFD+2000 + JRST SHRCKF ;DONE + SKIPN A,MNUNAM(Q) + JRST SMFDL1 + PUSHJ P,SUSRLP +SMFDL1: ADDI Q,LMNBLK + JRST SMFDLP + +SHRCKF: SKIPN GOGOX + JRST CRDDT + JRST ERRDDT + +SUSRLP: HRREI J,-MFD-2000(Q) ;CONVERT MFD INDEX TO BLOCK NUMBER + ASH J,-1 + ADD J,NUDS + MOVEM A,USRNAM + PUSH P,Q + MOVE I,UDSK + PUSH P,UDSK +SUSRL1: MOVEI A,OUSRD + PUSHJ P,READ + JUMPL T,SUSRE2 + MOVEI Q,2000-LUNBLK+OUSRD + MOVEI J,OUSRD + ADD J,UDNAMP(J) + PUSH P,J +SDIRL1: CAMGE Q,J + JRST SUSRFN + MOVEM Q,LASTQ + SKIPE A,UNFN1(Q) + JRST .+3 + SKIPN UNFN2(Q) + JRST SDIRLP + LDB C,[UNPKN UNRNDM(Q)] + LDB A,[UNDSCP UNRNDM(Q)] + IDIVI A,6 + ADDI A,OUSRD+UDDESC + HLL A,QBTBLI(B) + TLNE A,400000 + SUB A,[440000,,1] +SDIRL2: MOVE N,A + MOVEI J,0 + ILDB B,A +SDIRL3: MOVE TT,UNRNDM(Q) + TLNE TT,UNLINK + JRST SDIRLP + PUSHJ P,FINDPK + SKIPL C + SKIPN QACT(C) + JRST SDIRLP + CAIG B,UDWPH ; A LOAD FIRST THING + JRST SDIRLP + +STRLUP: ILDB B,N + JUMPE B,SDIRLP + CAIN B,UDWPH + JRST STRLUP + CAIL B,UDWPH + JRST SLOAD + CAILE B,UDTKMX + JRST SSKIPF + JRST STLUP + +STLUP: AOS Q +STLUP1: ILDB D,J + CAIE D,1 + PUSHJ P,SPNT + SOJG B,STLUP + JRST STRLUP + +SLOAD: ANDCMI B,20 ;DM FUNNY BIT + MOVEI J,-UDWPH-1(B) + MOVEI K,NXLBYT +SLOAD1: ILDB B,N + LSH J,6 + ADD J,B + SOJG K,SLOAD1 + MOVE Q,J + MOVE I,C + PUSHJ P,TUTPNN ;GET PNTR TO TUT + ADD J,[TUTBYT_14,,] ;COMPENSATE FOR ILDB + MOVEI B,1 + JRST STLUP1 + +SSKIPF: SUBI B,UDTKMX + IBP J + AOS Q + SOJG B,.-2 + MOVEI B,1 + JRST STLUP + +SPNT: MOVE A,USRNAM + PUSHJ P,L6B + MOVEI A,"; + PUSHJ P,LTYO + EXCH Q,LASTQ + MOVE A,UNFN1(Q) + PUSHJ P,L6B + PUSHJ P,LSPAC + MOVE A,UNFN2(Q) + PUSHJ P,L6B + PUSHJ P,LSPAC + HRRZ A,C + PUSHJ P,LDPT + MOVEI A,"- + PUSHJ P,LTYO + MOVE A,LASTQ + PUSHJ P,LOPT + LPR , TUT= + MOVE A,D + X LDPT + PUSHJ P,LCRR + EXCH Q,LASTQ + POPJ P, + +SUSRE2: TYPE USER DIRECTORY PARITY ERROR + PUSHJ P,TSPAC + TYPE BLOCK # + MOVEM J,DBLK + MOVE A,J + PUSHJ P,DPT + UNTMES UNIT # + MOVE A,I + PUSHJ P,DPT + PUSHJ P,CRR + PUSHJ P,GSTS + SKIPE GOGOX + JRST ERRDDT + TYPE TRY NEXT DRIVE? + X Y.OR.N + JRST ERRDDT + MOVE I,UDSK +SUSR2B: AOS I + CAIL I,NUNITS + SUBI I,NUNITS + SKIPN QACT(I) + JRST SUSR2B + MOVEM I,UDSK + MOVE J,DBLK + JRST SUSRL1 + +SUSRFN: POP P,J + POP P,UDSK + POP P,Q + POPJ P, + +SDIRLP: MOVE Q,LASTQ + SUBI Q,LUNBLK + MOVE J,(P) + JRST SDIRL1 + +POPBAJ: POP P,B +POPAJ: POP P,A + POPJ P, + +SUBTTL INITIALIZATION + +INIT: 0 + MOVEI P,PDL +NTS,[ KA,[ + CONO 675550 ;RESET APR + CONO PI,710000 ;RESET PI + MOVE TT,[JSR UUOHLT] ;HALT ON UUO + SKIPN 41 + MOVEM TT,41 + MOVEI A,SA ;MAKE SURE ALL NECESSARY MEMORY IS PRESENT +INIT0: MOVE B,(A) + CONSZ 10000 + JRST [ TYPE NXM IN SALV MEM + JRST ERRDDT ] + ADDI A,2000 + CAIGE A,THEEND + JRST INIT0 +];KA +KL,[ + SETZM DTEOPR ;BTB IF QUIT OUT AND RESTART + CONO APR,267760 ;I/O RESET, CLEAR + DISABLE ALL FLAGS + CONO PI,010000 ;CLEAR P.I. SYSTEM + CONSZ PAG,400000 + JRST .+4 ;JUMP IF CACHE LOOK ENABLE + SWPIA ;IF CACHE OFF, INVALIDATE IT BEFORE TURNING ON + CONSZ APR,200000 + JRST .-1 + MOVEI TT,SALVPF ;SET TO HALT ON PAGE FAIL (E.G. PARITY ERROR) + MOVEM TT,PFNPC + CONO PAG,600000+EPT/1000 ;SET UP EPT, ENABLE CACHE, DISABLE PAGING AND TRAPS + DATAO PAG,[100000,,400000+EPT/1000] ;UPT=EPT + MOVEI TT,UUOHLT + SKIPN EPT+430 ;HALT ON KERNEL UUO + MOVEM TT,EPT+430 + MOVEI A,SA ;MAKE SURE ALL NECESSARY MEMORY IS PRESENT +INIT0: MOVE B,(A) + CONSZ 2000 + JRST [ TYPE NXM IN SALV MEM + JRST ERRDDT ] + ADDI A,1000 + CAIGE A,THEEND + JRST INIT0 +RH, CONI DSK,TT +RH, TLNN TT,(%HID22) +RH, JRST [ TYPE DF10 IN KA MODE?? +RH, JRST ERRDDT ] +IFN T300P,[ ;TURN ON DL10 TO ACCESS T-300 + CONO DLC,400000 ;MR CLR + CONO DLB,1 ;TURN OFF EXCESS LIGHTS + CONO DLB,2 ;.. + CONO DLB,3 ;.. + CONO DLB,DL10AR ;64 WORDS FOR PDP11 #0 AT DL10AR + DATAO DLC,[200001,,] ;KA INTERRUPT MODE + CONO DLC,100020 ;ENB PDP11 PORT #0 NO INTERRUPTS +];T300P +];KL +DC, SETZM ENCS +RH, SETZM MARKF +RP,[ DATAI DPC,A + TLNN A,NOWRIH + JRST [ TYPE [WRITE HEADERS ENABLED] + X CRR + JRST .+1 ] +];RP + SETOM DRIVE ;ALL DRIVES ASSUMED TO BE ON-LINE + MOVE A,[DRIVE,,DRIVE+1] + BLT A,DRIVE+NDRIVE-1 + MOVEI A,SLVIOWD ;SET UP CHANNEL PROGRAM AREA + MOVEM A,SLVICWA + SETZM SLVIOWD+1 + SETZM SLVICWA+1 +];NTS + SETZM GOGOX + SETZM NOQUES + MOVEI A,NUNITS-1 + SETOM QPKN(A) ;TUT NOT IN YET + SOJGE A,.-1 +TS,[ + .OPEN TYIC,[SIXBIT / $TTY/] + .VALUE + .OPEN TYOC,[SIXBIT / !TTY/] + .VALUE + .CORE _-10.+1 + .VALUE + MOVE A,[SQUOZE 0,NQS] + .EVAL A, + .VALUE + MOVEM A,NQS + MOVE A,[SQUOZE 0,QACT] + .EVAL A, + .VALUE + MOVEM A,SQACT + MOVE A,[SQUOZE 0,NUDSL] + .EVAL A, + .VALUE + MOVEM A,NUDS + MOVE A,[SQUOZE 0,MFDBLK] + .EVAL A, + .VALUE + MOVEM A,MFDBK + MOVE B,[SQUOZE 0,NTUTBL] + .EVAL B, + .VALUE + MOVEI C,NUNITS-1 + MOVEM B,NTBL(C) + SOJGE C,.-1 + CAILE B,MXTUTB + .VALUE ;NOT ASSEMBLED FOR BIG ENOUGH TUTS + MOVE B,[SQUOZE 0,T300P] ;NEED KLUDGES FOR 2 SIZES OF TUT + .EVAL B, + MOVEI B,0 + JUMPE B,INI03 + MOVE C,[SQUOZE 0,NTUTB1] + .EVAL C, + .VALUE + CAILE C,MXTUTB + .VALUE ;TOO BIG + MOVEM C,NTBL(B) + CAIGE B,NUNITS-1 + AOJA B,.-2 +INI03: MOVE A,[SQUOZE 0,NBLKS] + .EVAL A, + .VALUE + MOVEM A,SNBLKS + SUBI A,1 + MOVEM A,SNBLKS-1 +];TS + + ;BRING UP THE LPT + + SETOM NOLPT ;ASSUME THE WORST + SKIPE LPBUST + JRST LPTDWN + SETOM LPFRST' ;FLAG LPT NOT USED YET + +TS,[ TYPE WANT LPT? + PUSHJ P,TYI + X CRR + SETOM LPBUST ;ASK ONLY ONCE + CAIN A,"Y + .OPEN LPTC,[.UAO,,'LPT] + JRST LPTDWN + SETZM NOLPT + SETZM LPBUST +];TS +;DROPS THROUGH + ;DROPS IN +NTS,[ +IFN OLPTP,[ ;BRING UP AI-KA LPT +LPTUP3: CONO LPT,10 + DATAO LPT,[440] + MOVEI A,200000 +LPTUP1: SOJLE A,LPTUP2 + CONSZ LPT,10 + JRST LPTUP1 + SETZM NOLPT + JRST LPTDWN +];IFN OLPTP + +IFN NLPTP,[ ;BRING UP ML LPT +LPTUP3: SETOM LPTBFC + MOVE A,[<.BYTE 7 ? 15 ? 15 ? 15 ? 15 ? 15>] + MOVEM A,LPTBUF + CONO NLPT,200 + CONO NLPT,1000 ;IMAGE MODE + DATAO NLPT,[23*2] ;MOTOR ON + + MOVEI A,200000 ;1 SECOND +LPTUP1: SOJLE A,LPTUP2 + CONSO NLPT,100 ;IS IT ON? + JRST LPTUP1 + SETZM NOLPT ;WELL, YES + CONO NLPT,200 + CONO NLPT,100 ;SET OUTPUT DONE + JRST LPTDWN ;ITS UP +];IFN NLPTP + +IFN TTLPTP,[ ;BRING UP LPT ATTACHED VIA MTY +LPTUP3: MOVEI A,200000 +LPTUP1: SOJLE A,LPTUP2 + CONI MTY,B + TRNN B,40 ;ANY INPUT? + JRST LPTUP1 + LDB B,[140500,,B] + DATAI MTY,C + CAIE B,TTLPTP&77 + JRST LPTUP1 ;NOT FROM LPT + + SETZM NOLPT ;IS FROM LPT -> WIN + MOVEI B,TTLPTP_14 ;LINE NUMBER IN RIGHT PLACE + CONO MTY,10(B) ;SET OUTPUT DONE + JRST LPTDWN +];IFN TTLPTP + +IFN OLPTP+NLPTP+TTLPTP,[ + ;ROUTINE TO ASK IF UP +LPTUP2: TYPE LPT DOWN (Y OR N) +IFN OLPTP, TYPE [MAYBE NEEDS RESET BUTTON PUSHED] + PUSHJ P,TYI + X CRR + CAIN A,"Y + JRST LPTUP4 + CAIN A,"N + JRST LPTUP3 ;"N", CHECK IT AGAIN + JRST LPTUP2 + +LPTUP4: SETOM LPBUST +];IFN OLPTP+NLPTP+TTLPTP +];NTS + +LPTDWN: JRST @INIT + +NTS,[ +UUOHLT: +KA, 0 + JRST 4,. ;HERE IF UUO IN STAND-ALONE MODE (ELSE HALT IN ITS) +];NTS + +SUBTTL LPT & TTY I/O + +LDPT: PUSH P,A + PUSH P,B + JUMPGE A,LDPT0 + MOVEI A,"- + PUSHJ P,LTYO + MOVN A,-1(P) +LDPT0: PUSHJ P,LDPT1 + JRST POPBAJ + +LDPT1: IDIVI A,10. + HRLM B,(P) + SKIPE A + PUSHJ P,LDPT1 + JRST LDPT2 + +LOPT: PUSH P,A + PUSH P,B + PUSHJ P,LOPT1 + JRST POPBAJ + +LOPT1: LSHC A,-35. ;IN CASE NEGATIVE + LSH B,-1 + DIVI A,8 + HRLM B,(P) + SKIPE A + PUSHJ P,LOPT1 +LDPT2: HLRZ A,(P) + ADDI A,"0 +;DROPS IN +LTYO: +LPTR: +LPTR1: SKIPE NOLPT + JRST TYLPT ;TYPE ON TTY INSTEAD + + PUSH P,A + AOSE LPFRST + JRST LPTR2 + TYPE (INFO ON LPT) + X CRR +LPTR2: + +IFN OLPTP,[ +OLP1: CAIN A,12 ;SUPPRESS LF, MAKE CR=CR-LF + JRST POPAJ + CAIN A,15 + JRST [ CONO LPT,10 + MOVEI A,440 + JRST .+1] + CAIN A,14 + MOVEI A,441 + CAIN A,33 + MOVEI A,"$ + CAIL A,"a + CAILE A,"z + CAIA + SUBI A,40 ;LOWER CASE -> UPPER CASE + SUBI A,40 + PUSH P,B + HRLZI B,2 ;3 SECOND TIMEOUT + CONSZ LPT,10 + SOJG B,.-1 + JUMPLE B,OLP2 +OLP3: DATAO LPT,A + JRST POPBAJ + +OLP2: X CRR + TYPE HIT RESET BUTTON ON LPT + X CRR + HRLZI B,15 ;20 SECOND TIMEOUT + CONSZ LPT,10 + SOJG B,.-1 + JUMPLE B,OLP2 + JRST OLP3 +];IFN OLPTP + +TS,[ .IOT LPTC,A + JRST POPAJ +];TS + +IFN NLPTP,[ ;SEND CHARACTER TO NLPT + PUSH P,B + SOSLE LPTBFC ;MORE TO GO + JRST LPTR0 ;YES +LPTR01: MOVEI B,5 ;NO, NEW WORD + MOVEM B,LPTBFC + MOVE B,[440700,,LPTBUF] + MOVEM B,LPTBFP + MOVEI B,-1 ;TIMEOUT FOR DEAD LPT + CONSO NLPT,100 + SOJG B,.-1 + DATAO NLPT,LPTBUF + +LPTR0: IDPB A,LPTBFP ;BUFFER 5 AT A TIME + CAIL A,12 + CAILE A,14 ;LF OR FF, FORCE BUFFER NOW + JRST POPBAJ + MOVEI A,15 +LPTR00: SOSG LPTBFC + JRST LPTR01 + IDPB A,LPTBFP + JRST LPTR00 + + ;NLPT BUFFERING CRUFT +LPTBUF: -1 ;5 CHAR LPT BUFFER +LPTBFC: 5 ;COUNT OF CHARS LEFT IN BUF +LPTBFP: @. ;BYTE POINTER INTO LPT BUFFER + +LPTFIN: SKIPL LPFRST ;DO NOTHING IF NEVER OUTPUT TO LPT + SKIPGE NOLPT ;WAS LPT INIT'ED? + POPJ P, ;NO, DON'T HANG + MOVE A, [<.BYTE 7 ? 15 ? 14 ? 15 ? 15 ? 15>] + MOVEI B, 15 +LPTFN0: SOSG LPTBFC + JRST LPTFN1 + IDPB B, LPTBFP + JRST LPTFN0 + +LPTFN1: CONSO NLPT,100 ;WAIT FOR THAT TO HAPPEN + JRST .-1 + DATAO NLPT, LPTBUF + CONSO NLPT,100 ;WAIT FOR THAT TO HAPPEN + JRST .-1 + DATAO NLPT, A + POPJ P, +];IFN NLPTP + +IFN TTLPTP,[ +; call with ascii char in A +; saves and restores all AC's + + ANDI A,177 ;MASK TO 7 BIT ASCII + CAIGE A,40 ;SKIP IF NOT CTL CHAR + CAIN A,14 ;SKIP IF NOT FF + JRST LPTOP ;PRINT LITERALLY FF, GRAPHICS + CAIN A,15 ;SKIP IF NOT CR + JRST LPCR ;JUMP TO CR ROUT + CAIN A,12 ;SKIP IF NOT LF + JRST LPLF ;JUMP TO LF ROUT + CAIN A,11 ;SKIP IF NOT TAB + JRST LPTAB ;JUMP TO TAB ROUT + MOVEI A,"^ ;HERE FOR RANDOM CTL CHAR + PUSHJ P,LPTO ;PUT OUT ^FOO + MOVE A,(P) ;RETREIVE CHAR + ADDI A,100 ;MAKE IT A 'LETTER' +LPTOP: PUSHJ P,LPTO + JRST POPAJ + +LPCR: SKIPE LPTPOS ;SKIP IF STILL AT LEFT MARGIN + PUSHJ P,LPTO ;ELSE PUT OUT CR + SETZM LPTPOS ;MARK 'AT LEFT MARGIN' + SETOM LPCRLF ;MARK LF AFTER CR + MOVEI A,12 ;LF + JRST LPTOP ;OUTPUT IT + +LPLF: AOSE LPCRLF ;SKIP IF THIS LF AFTER CR + JRST LPTOP ;ELSE PUT IT OUT + JRST POPAJ + +LPTAB: MOVEI A,40 ;SPACES FOR TAB + PUSHJ P,LPTO + MOVE A,LPTPOS ;CHECK POS + TRNE A,7 ;SKIP IF POS = 0 MOD 8 + JRST LPTAB ;ELSE PUT ANOTHER SPACE + JRST POPAJ + +LPTO: CAIL A,40 ;SKIP FOR CTL CHAR NOT COUNTED + AOS LPTPOS ;COUNT CHAR + PUSH P,A + PUSH P,B + MOVEI A,-1 ;TIMER FOR FLAG +LPWAIT: SOJLE A,LPTOUT + CONI MTY,B ;GET STATUS + TRNE B,40 ;SKIP IF NO INPUT FLAG + JRST FLSINP ;ELSE JUMP TO FLUSH INPUT + TRNN B,10 ;SKIP IF OUTPUT FLAG + JRST LPWAIT ;ELSE LOOP + LDB B,[140500,,B] ;GET SUBDEV # + CAIE B,TTLPTP&77 ;SKIP IF THIS IS LPT # + JRST FLSOUT ;ELSE FLUSH +LPTOUT: MOVEI B,TTLPTP_14 ;GET LPT NO IN SUBDEV POSITION + CONO MTY,(B) ;SELECT SUBDEV + POP P,B ;RESTORE AC + MOVE A,(P) ;GET CHAR + LSH A,35 ;PUT IN FUNNY POSITION + DATAO MTY,A ;PUT OUT 1 CHAR + JRST POPAJ + +FLSINP: DATAI MTY,B ;READ INPUT + JRST LPWAIT ;AND IGNORE + +FLSOUT: LSH B,14 ;SHIFT TO SELECT + CONO MTY,200(B) ;RESET FLAG, IT'S NOT LPT + JRST LPWAIT + +LPTPOS: 0 ;PRINT POSITION FROM LEFT MARGIN +LPCRLF: 0 ;# CHARS AFTER LAST CR, -1 IF TO IGNORE LF +];IFN TTLPTP + +TYLPT: CAIN A,14 + JRST CRR ;NO FF ON TTY + JRST TYO + +SIXTYP: +T6B: PUSH P,B ;OUTPUT SIXBIT IN A + PUSH P,A + LSHC A,-36. +T6B1: LSHC A,6 + ADDI A,40 + PUSHJ P,TYO + MOVEI A,0 + JUMPN B,T6B1 + POP P,A +POPBJ: POP P,B + POPJ P, + +SIXLPT: +L6B: PUSH P,B ;OUTPUT SIXBIT IN A + PUSH P,A + MOVE B,[440600,,(P)] ;ALWAYS OUTPUTS SIX COLUMNS +L6B1: ILDB A,B ;CAN YOU GUESS WHY? WIN A KEWPIE DOLL! + ADDI A,40 + PUSHJ P,LPTR + TLNE B,770000 + JRST L6B1 + POP P,A + POP P,B + POPJ P, + +SLPT: PUSH P,B + MOVE B,A +SL1: ILDB A,B + JUMPE A,POPBJ + PUSHJ P,LPTR + JRST SL1 + +DPT: +TOPT: PUSH P,A + PUSH P,B + MOVEI B,8 + MOVEM B,ORADIX + PUSHJ P,TDPT1 + JRST POPBAJ + +TDPT: PUSH P,A + PUSH P,B + MOVEI B,10. + MOVEM B,ORADIX' + PUSHJ P,TDPT1 + JRST POPBAJ + +TDPT1: LSHC A,-35. ;IN CASE NEGATIVE + LSH B,-1 + DIV A,ORADIX + HRLM B,(P) + SKIPE A + PUSHJ P,TDPT1 + HLRZ A,(P) + ADDI A,"0 + JRST TYO + +LTAB: +IFN OLPTP,[ + PUSHJ P,LSPAC ;OLD LPT LACKS TABS + PUSHJ P,LSPAC + PUSHJ P,LSPAC + JRST LSPAC +];IFN OLPTP + +.ELSE [ PUSH P,A + MOVEI A,11 ;NLPT HAS HARDWARE TABS + JRST L1 +];ELSE + +LCRR: PUSH P,A + MOVEI A,15 + PUSHJ P,LPTR + MOVEI A,12 + PUSHJ P,LPTR + JRST POPAJ + +LSPAC: PUSH P,A + MOVEI A,40 +L1: PUSHJ P,LPTR + POP P,A + POPJ P, + +LFORM: PUSH P,A + MOVEI A,14 + PUSHJ P,LPTR + JRST POPAJ + +LOUTST: 0 + PUSH P,A + PUSH P,B + HRRZ B,@LOUTST + HRLI B,440700 +LOUT2: ILDB A,B + JUMPE A,LOUT1 + X LPTR + JRST LOUT2 + +LOUT1: POP P,B + POP P,A + AOS LOUTST + JRST 2,@LOUTST + +TOUTST: 0 + PUSH P,A + PUSH P,B + HRRZ B,@TOUTST + PUSHJ P,OUTSTR + AOS TOUTST + POP P,B + POP P,A + JRST 2,@TOUTST + +OUTSTR: HRLI B,440700 +OUTST1: ILDB A,B + JUMPE A,CPOPJ + PUSHJ P,TYO + JRST OUTST1 + +ERRDDT: PUSHJ P,CRR + TYPE *** ERROR *** SYSTEM MAY NOT BE BROUGHT BACK UP +CRDDTE: NTS, SETZM SALVRT ;CAN'T RETURN TO SYSTEM +CRDDT: PUSHJ P,CRR + +DDT: +NTS,[ +IFN NLPTP, PUSHJ P,LPTFIN ;UNBUFFER LINE PRINTER + SKIPE SALVRT + JRST @SALVRT + TYPE DDT + SKIPN MEMSIZ-4000 + JRST 4,. ;NO DDT LOADED? + JRST MEMSIZ-4000 +];NTS +TS,[ .VALUE [ASCIZ\:DDT +\] + JRST DDT +];TS + +CRR: PUSH P,A + PUSHJ P,CRR1 + SETZM LINPOS' + JRST POPAJ + +CRR1: MOVEI A,15 + PUSHJ P,TYO + MOVEI A,12 + JRST TYO + +TSPAC: PUSH P,A + MOVEI A,40 + X TYO + JRST POPAJ + +TYO: +TS, .IOT TYOC,A +NTS,[ +KA,[ + CONSZ TTY,20 + JRST .-1 + DATAO TTY,A + SKIPN PUNCH + JRST TYO0 + CONSZ PTP,20 ;WAIT FOR NOT BUSY + JRST .-1 + DATAO PTP,A +TYO0: +];KA +KL,[ + PUSH P,A + ANDI A,177 + PUSHJ P,DTEXIO + POP P,A +];KL +];NTS + AOS LINPOS + POPJ P, + +KL,[ ;DTE20 COMMUNICATION ROUTINE ... COPIED FROM DEC "SUBRTN" PROGRAM + +DTEXIO: SETZM DTEFLG + MOVEM A,DTECMD + SETZM DTEF11 + CONO DTE,%DBL11 + SKIPN DTEFLG + JRST .-1 + SETZM DTEFLG + MOVE A,DTEF11 + POPJ P, +];KL + +NTYI: PUSHJ P,TYI ;INPUT DIGIT, SKIP IF WIN + CAIL A,"0 + CAILE A,"9 + POPJ P, + SUBI A,"0 +POPJ1: AOS (P) + POPJ P, + +SIXIN: PUSH P,C +SIXI1: MOVE C,[440600,,B] + SETZ B, +SIXIL: X TYI + CAIL A,140 + JRST [ TYPE XXX + JRST SIXI1] + CAIG A,40 + JRST SIXIX + CAIN A,"; + JRST SIXIL + SUBI A,40 + TLNE C,770000 + IDPB A,C + JRST SIXIL + +SIXIX: POP P,C + POPJ P, + +TYI: ;INPUT CHAR INTO A +TS, .IOT TYIC,A +NTS,[ +KA,[ + CONSO TTY,40 + JRST .-1 + DATAI TTY,A +];KA +KL,[ + MOVEI A,3400 ;"DDT MODE" INPUT + PUSHJ P,DTEXIO + JUMPE A,.-2 +];KL +];NTS + ANDI A,177 + CAIL A,"a ;MIGHT NOT BE KSR-35 + CAILE A,"z + CAIA + SUBI A,40 + CAIN A,^Z + JRST CRDDTE + JRST TYO + +;RETURN TO DDT IF CHARACTER TYPED +TYIPSE: PUSHJ P,TYIP + POPJ P, + PUSHJ P,TYI + JRST DDT + +;SKIP IF INPUT AVAILABLE +TYIP: PUSH P,A +TS,[ .LISTEN A, + SKIPE A +];TS +NTS,[ +KA, CONSZ TTY,40 +KL,[ MOVEI A,3400 + PUSHJ P,DTEXIO + SKIPE A +];KL +];NTS + AOS -1(P) + POP P,A + POPJ P, + +Y.OR.N: PUSH P,A ;YES OR NO, SKIP IF YES +YORN1: X TYI + X CRR + CAIE A,"Y + CAIN A,"N + JRST YORN2 + TYPE (Y OR N) + JRST YORN1 ;TELETYPE KEYBOARD LOSSAGE? + +YORN2: CAIN A,"Y + AOS -1(P) + JRST POPAJ + +SUBTTL MAG TAPE I/O + +NTS,[ MTC==340 ;MAG TAPE CHANNEL FOR FUNCTIONS + MTS==344 ;MAG TAPE CHANNEL FOR STOPPING AND STATUS + +;SHIFTS FOR FIELDS IN CONO MTC, + UNITNO==15. + PARITY==14. + CDUMP==13. + FUNC==9. + DENSTY==6. + + 800BPI==2 + + MAGCOM=5_+1_+800BPI_+1_ + +;FUNCTIONS + NOOP1=0_+MAGCOM ;CLEAR INTERRUPT FLAGS + NOOP2=10_+MAGCOM ;INTERRUPT WHEN TRANSPORT IDLE + REWIND=1_+MAGCOM ;REWIND + REED=2_+MAGCOM ;READ + SPACR=7_+MAGCOM ;SPACE REVERSE + +;FLAGS + JOBDON==100 + DATREQ==1 + EOFF==10000 + EOTF==4000 +;NOTE - TM10B HAS DATA PIA (CONI MTC, 1.1-1.3) STUCK AT 7 + +REW: CLEARM EOFCNT + CLEARM MAGBFP + CLEARM SHORTL + CONO MTC,NOOP1 ;CLEAR INTERRRUPT FLAGS + CONO MTC,REWIND ;INITIATE REWIND + CONSO MTS,JOBDON ;WAIT FOR REWIND TO BEGIN + JRST .-1 + CONO MTC,NOOP2 ;SET JOB DONE WHEN TRANSPORT IDLE + CONSO MTS,JOBDON ;WAIT FOR JOB DONE + JRST .-1 + SETOM ITAPE + POPJ P, ;REWIND DONE +ITAPE: 0 + +MREAD: MOVEI T,0 + PUSH P,B +MREAD7: SKIPGE B,MAGBFP + JRST MREAD5 + SKIPN EOFLG + JRST MREAD1 + SETZM EOFLG + SETOM EOUF + JRST POPBJ + +MREAD1: MOVEI B,10. + MOVEM B,MTRYS +MERR2: MOVE B,[-2000,,MAGBUF] + MOVEM B,MAGBFP + SETZM SLVIOWD + CONO MTC,NOOP1 ;CLEAR FLAGS + CONSO MTC,7 ;IS THIS A TM10B? + JRST MREADA ;NO +KA, MOVE B,[-2000,,MAGBUF-1] ;YES SET UP CHANNEL PROGRAM +KL, MOVE B,[-2000_4,,MAGBUF-1] + MOVEM B,SLVIOWD + SETZM SLVICWA+1 + SETZM SLVIOWD+1 + DATAO MTS,[SLVICWA] +KL,[ SWPUA ;UNLOAD THE CACHE + PUSH P,A + MOVE A,[CONSZ APR,200000] + MOVE B,[JRST A] + MOVE C,[POPJ P,] + PUSHJ P,A + POP P,A +] +MREADA: CONO MTC,REED +MREAD2: CONSO MTS,DATREQ+EOFF+JOBDON+EOTF ;WAIT FOR NEXT DATA REQUEST + JRST .-1 + MOVEI C,20. + SOJG C,. + CONI MTS,C + TRNE C,EOTF + JRST MREOT + TRNN C,JOBDON + JRST MREAD3 + TRNN C,EOFF + JRST MREAD6 + AOS EOFCNT + SETOM EOFLG + CLEARM SHORTL + JRST MREAD9 + +MREAD6: SETOM SHORTL +MREAD9: CONSZ MTC,7 ;SKIP IF TM10A + JRST MREADB + HLLZS B + MOVNS B + ADDM B,MAGBFP + JRST MREAD4 + +MREADB: HRRZ B,SLVICWA+1 + JUMPE B,.-1 + MOVNI B,1-MAGBUF(B) + SKIPE EOFLG + MOVSI B,0 ;EOF MARK => NO WORDS READ + HRLM B,MAGBFP + JRST MREAD4 + +MREAD3: TRNE C,DATREQ + CONSZ MTC,7 ;SKIP IF TM10A + JRST MREAD2 ;TM10B OR NO DATA REQUEST + DATAI MTC,(B) + SKIPE SHORTL + JRST 4,. + AOBJN B,MREAD2 +MREAD4: CONO MTS,1 + CONSO MTS,JOBDON + JRST .-1 + CONSZ MTS,440000 ;X HUNG + ILL OP + JRST 4,MERR +MREAD8: CONSO MTS,20600 + JRST MREAD7 +MERR: SOSG MTRYS + JRST MERR1 + SETZM SLVIOWD +KL,[ SWPUO 0 + CONSZ APR,200000 + JRST .-1 +] + CONO MTC,NOOP1 + CONO MTC,SPACR + CONSZ MTC,7 ;SKIP IF TM10A + JRST .+4 + CONSO MTS,DATREQ + JRST .-1 + DATAO MTC, + CONO MTS,1 + CONSO MTS,JOBDON + JRST .-1 + JRST MERR2 + +MERR1: AOS FERRS ;IGNORE ERR + JRST MREAD7 + +MREAD5: HLRE C,B + CAMG B,A + HLRE C,A + HRLZS B + HRR B,A + MOVNS C + HRLS C + ADDI C,-1(A) + BLT B,(C) + HLRS C + ADD A,C + ADDM C,MAGBFP + ADDI T,(C) + JUMPGE A,POPBJ + JRST MREAD7 + +MREOT: CONO MTS,1 ;STOP TAPE IF STILL MOVING + CONO MTC,NOOP1 + LPR EOT + X LCRR + JRST DDT +];NTS + +SUBTTL TYPE CONTROLLER AND DRIVE STATUS +TS,[ +GSTS: POPJ P, +];TS + +DC,[ +GETSTS: MOVEI P,PDL + PUSH P,[DDT] +GSTS: INSIRP PUSH P,[A B C D T] + CONI DC0,D + MOVEI C,DC0STS + TYPE CONTROLLER STATUS: + PUSHJ P,TYPSTS + CONI DC1,D + MOVEI C,DC1STS + PUSHJ P,TYPSTS + CONO DC0,DCCSET+DCDENB + DATAO DC0,[DJMP GETUNT] + CONSZ DC0,DSSACT + JRST .-1 + TYPE CURRENT UNIT= + LDB A,[DUNFLD GOTUNT] + DPB A,[DUNFLD STOSTS] + PUSHJ P,TDPT + TYPE ,DRIVE STATUS: + PUSHJ P,CRR + DATAO DC0,[DJMP STOSTS] + CONSZ DC0,DSSACT + JRST .-1 + MOVE D,STATUS + LSH D,-15. + MOVEI C,DRVSTS + PUSHJ P,TYPSTS + TYPE CYLINDER= + LDB A,[101100,,STATUS] + PUSHJ P,TOPT + PUSHJ P,CRR + INSIRP POP P,[T D C B A] + POPJ P, + +TYPSTS: SETOM FIRST' +TYPST1: SKIPN B,(C) + JRST CRR + HLRZ T,B ;FLAGS TO TEST + TDNN D,T + AOJA C,TYPST1 + MOVEI A,", + AOSE FIRST + PUSHJ P,TYO + MOVE A,LINPOS + CAILE A,TCMXH + PUSHJ P,CRR + PUSHJ P,OUTSTR + AOJA C,TYPST1 + ;DC +DEFINE STS A,B/ +A,,[ASCIZ \B\] +TERMIN + +DC0STS: STS 4000,ERROR-FLG + STS 1000,ATTENTION + STS 200,RUN + STS 100,ACTIVE + 0 + +DC1STS: STS 4000,INTERNAL-PARITY-ERROR + STS 2000,RECORD-LENGTH + STS 1000,READ-COMPARE + STS 400,OVERRUN + STS 200,CHECKSUM/DECODER + STS 100,BARK!! + STS 40,FILE-UNSAFE/SEEK-INCOMPLETE/END-OF-DISC + STS 20,OFF-LINE/MULTIPLE-SELECT + STS 10,RDG-KEY/PROTECT/READONLY + STS 4,DATAO-WHILE-BUSY + STS 2,NON-EX-MEM + STS 1,CORE-PARITY-ERROR + 0 + +DRVSTS: STS 4,UNIT-SELECTED + STS 10,ON-LINE + STS 20,READY + STS 40,SEEK-INCOMPLETE + STS 100,READ-ONLY + STS 200,UNSAFE + STS 400,WRITE-CURRENT-SENSED(?) + 0 + +GETUNT: DJSR .+1 +GOTUNT: 0 + DHLT + +STOSTS: DSDRST+DUNENB STATUS(74) + DHLT +STATUS: 0 +];DC + +RP,[ +GETSTS: MOVEI P,PDL + PUSH P,[DDT] +GSTS: INSIRP PUSH P,[A B C D T] + TYPE DISK STATUS: + CONI DPC,D + MOVEI C,CNLSTS + TLNE D,-1 + PUSHJ P,TYPSTS + MOVSS D + MOVEI C,CNISTS + PUSHJ P,TYPSTS + DATAI DPC,D + TLC D,1 ;REVERSE SENSE OF WRITE HEADER LOCKOUT SWITCH + MOVEI C,DTISTS + PUSHJ P,TYPSTS + TYPE CURRENT UNIT= + LDB A,[DUNFLI D] + PUSHJ P,TDPT + TYPE , CYLINDER= + LDB A,[DCYLI D] + TRNE D,.BM DCYLXI + ADDI A,400 + PUSHJ P,TOPT + TYPE , LAST ADDRESSED CYL= + MOVE A,RPIOCY + X TOPT + TYPE , SURF= + MOVE A,RPIOHD + X TOPT + TYPE , SEC= + MOVE A,RPIOSC + X TOPT + PUSHJ P,CRR + INSIRP POP P,[T D C B A] + POPJ P, + +TYPSTS: SETOM FIRST' +TYPST1: SKIPN B,(C) + JRST CRR + HLLZ T,B ;FLAGS TO TEST + TDNN D,T + AOJA C,TYPST1 + MOVEI A,", + AOSE FIRST + PUSHJ P,TYO + MOVE A,LINPOS + CAILE A,TCMXH + PUSHJ P,CRR + PUSHJ P,OUTSTR + AOJA C,TYPST1 + + ;RP +DEFINE STS A,B/ +A,,[ASCIZ \B\] +TERMIN + +; CONI STATUS TABLE (RH) + +CNISTS: STS 400000,SEARCH DONE + STS 200000,END OF CYLINDER + STS 100000,POWER FAILURE + STS 040000,SEARCH ERROR + STS 020000,OVERRUN + STS 010000,NXM + STS 002000,DRIVE NOT READY + STS 001000,WRITE PROTECT + STS 000400,DATAO WHEN BUSY + STS 000200,SECTOR ADDRESS ERROR + STS 000100,SURFACE ADDRESS ERROR + STS 000020,BUSY + STS 000010,DONE + 0 + +; CONI STATUS TABLE (LH) + +CNLSTS: STS 000010,CONTROL WORD PARITY ERROR + STS 000004,SECTOR PARITY ERROR + STS 000002,MEMORY WORD PARITY ERROR + STS 000001,DISK WORD PARITY ERROR + 0 + +; DATAI STATUS TABLE (LH) + +DTISTS: STS 000100,SEEK INCOMPLETE + STS 000040,ON CYLINDER + STS 000020,DISK ON-LINE + STS 000010,FILE UNSAFE + STS 000004,NON EXISTENT DRIVE + STS 000002,DRIVE IS READ-ONLY + STS 000001,WRITE HEADER LOCKOUT OFF!! + 0 +];RP + +RH,[ +GETSTS: MOVEI P,PDL + PUSH P,[DDT] +GSTS: +IFN T300P,[ + SKIPE T3IOP + JRST T3STS ;LAST OPERATION WAS REALLY TO T-300 +];T300P + INSIRP PUSH P,[A B C D T I K] + TYPE CONTROLLER STATUS: + CONI DSK,D + MOVEI C,CNLSTS + TLNE D,-1 + PUSHJ P,TYPSTS + MOVSS D + MOVEI C,CNISTS + PUSHJ P,TYPSTS + TYPE CURRENT REGISTER: + DATAI DSK,D + PUSHJ P,TYPRGN + MOVE A,D + PUSHJ P,TOPT ;TYPE REG NO, STATUS, AND CONTENTS IN OCTAL + JUMPL D,GSTS0 ;DO FOLLOWING ONLY FOR DRIVE REGS + MOVEI A,", + PUSHJ P,TYO + MOVEI C,DIBSTS + PUSHJ P,TYPSTS + CAIA ;DON'T GIVE BLANK LINE +GSTS0: PUSHJ P,CRR + TYPE CURRENT DRIVE= + LDB A,[$HCDRV D] + PUSHJ P,TDPT + PUSHJ P,CRR + MOVEI I,NUNITS-1 ;CONVERT BACK TO VIRTUAL UNIT + CAME A,QTRAN(I) ;TO MAKE RHGET HAPPY + SOJGE I,.-1 + JUMPL I,GSTS3 ;FOO!! ADDRESSING NON EXISTENT DRIVE + + MOVSI K,-LGSTSR ;DISPLAY DRIVE REGS SPEC'ED IN TABLE +GSTS1: MOVE D,GSTSRT(K) + PUSHJ P,TYPRGN ;TYPE REG NAME + HRRZ C,D ;C -> STATUS BIT TABLE + HLLZ A,D ;A := REG NUMBER + PUSHJ P,RHGET ;GET CONTENTS OF REG + JRST GSTSER ;?? + PUSHJ P,TOPT ;GIVE CONTENTS IN OCTAL + PUSHJ P,TSPAC + MOVS D,A ;AND SYMBOLICLY + PUSHJ P,TYPSTS + AOBJN K,GSTS1 +GSTS3: INSIRP POP P,[K I T D C B A] + POPJ P, + +GSTSER: TYPE BARF: + MOVE D,A + MOVEI C,DIBSTS + PUSHJ P,TYPSTS + JRST GSTS3 ;DON'T TRY ANY MORE REGS + +TYPSTS: SETOM FIRST' +TYPST1: SKIPN B,(C) + JRST CRR + HLLZ T,B ;FLAGS TO TEST + TDNN D,T + AOJA C,TYPST1 + MOVEI A,", + AOSE FIRST + PUSHJ P,TYO + MOVE A,LINPOS + CAILE A,TCMXH + PUSHJ P,CRR + PUSHJ P,OUTSTR + AOJA C,TYPST1 + +TYPRGN: LDB A,[360600,,D] ;TYPE NAME OF REGISTER ADDRESSED BY D + ROT A,-1 + MOVE B,RHRGTB(A) + JUMPL A,.+2 + MOVSS B + PUSHJ P,OUTSTR + MOVEI A,"= + JRST TYO + +;TABLE OF DRIVE REGISTERS THAT NEED TO BE DISPLAYED +; LH = REG ADDR, RH = STATUS BITS TABLE ADDR + +GSTSRT: %HRDCL,,[0] + %HRSTS,,STSSTS + %HRCYL,,[0] + %HRCCY,,[0] + %HRADR,,[0] + %HROFS,,OFSSTS + %HRER1,,ER1STS + %HRER2,,ER2STS + %HRER3,,ER3STS +LGSTSR==.-GSTSRT + ;RH +DEFINE STS A,B/ +A,,[ASCIZ \B\] ? TERMIN + +; CONI STATUS (LH) + +CNLSTS: STS 400000,AR FULL + STS 200000,CB FULL + STS 040000,CC INH + STS 020000,CHANNEL ACTIVE + STS 010000,CHANNEL PULSE + STS 004000,22-BIT CHANNEL + STS 000400,CXR ILL FUNC + STS 000200,CXR DRIVE ACCESS ERR + STS 000004,MEMORY PARITY + STS 000002,CONTROL WORD PARITY + STS 000001,NXM + 0 + +; CONI STATUS (RH) + +CNISTS: STS 400000,DATA BUS PARITY + STS 200000,DRIVE EXCEPTION + STS 100000,CHANNEL ERROR + STS 020000,CHANNEL OVERRUN + STS 010000,DRIVE RESPONSE ERR + STS 004000,CXR ILL CMD + STS 002000,CXR POWER FAIL + STS 000200,CONTROL BUS OVERRUN + STS 000100,RAE INTR + STS 000040,ATTN INTR + STS 000020,BUSY + STS 000010,DONE + 0 + +; REGISTERS + +ZZ==-1 +XX==0 +YY==0 +DEFINE REG N,T/ +IFLE N-ZZ, .ERR REG OUT OF ORDER +REPEAT N-ZZ-1, REGH [ASCIZ\????\] + REGH [ASCIZ\T\] +TERMIN + +DEFINE REGH [A] +ZZ==ZZ+1 +IFE XX, YY==A +IFN XX, YY,,A +XX==1-XX +TERMIN + +RHRGTB: REG 0,DRV CTL + REG 1,DRV STATUS + REG 2,DRV ER1 + REG 3,DRV MAINT + REG 4,ATTENTION + REG 5,DRV TRACK-SECTOR + REG 6,DRV TYPE + REG 7,DRV LOOK-AHEAD + REG 10,DRV SERIAL NO + REG 11,DRV OFFSET + REG 12,DRV DESIRED CYL + REG 13,DRV CURRENT CYL + REG 14,DRV ER2 + REG 15,DRV ER3 + REG 16,DRV ECC POS + REG 17,DRV ECC PAT + REG 40,CONTROL + REG 44,INTR ADDR + REG 50,DATA BUFFER + REG 54,RAE STATUS + REG 74,CHANNEL BUFFER + REG 100,FOO +LOC RHRGTB+40 +EXPUNGE REG,REGH,XX,YY,ZZ + +; BITS IN DIB REGISTER + +DIBSTS: STS 004000,CTL-TO-DRIVE + STS 002000,CTL BUS TIMEOUT + STS 001000,CTL BUS PARITY + STS 000400,DIB DATA LATE + STS 000200,DIB ILL CMD + 0 + +; DRIVE STATUS REGISTER + +STSSTS: STS 1,FWD 5 IPS + STS 2,FWD 20 IPS + STS 4,INNER GUARD BAND + STS 10,GO REVERSE + STS 20,DIFF < 64 + STS 40,DIFF = 1 + STS 100,VOLUME VALID + STS 200,DRIVE READY + STS 400,CONN THIS CTRLR + STS 2000,LAST SECTOR XFERD + STS 4000,WRITE LOCK + STS 10000,MEDIUM ONLINE + STS 20000,POSITIONING IN PROGRESS + STS 40000,ERR + STS 100000,ATTENTION + 0 + +; DRIVE ERROR REGISTER 1 + +ER1STS: STS 1,ILL FUNC + STS 2,ILL REG + STS 4,REG MOD REFUSE + STS 10,BUS PARITY ERR + STS 20,PACK FORMAT ERR + STS 40,WRITE CLOCK FAIL + STS 100,ECC HARD ERR + STS 200,HEADER WRONG + STS 400,HEADER CRC ERR + STS 1000,ADDR OVERFLOW + STS 2000,INVALID ADDR + STS 4000,WRITE LOCK ERR + STS 10000,DRV TIMING ERR + STS 20000,OP NOT COMPLETE + STS 40000,UNSAFE + STS 100000,DATA CHECK + 0 + +; DRIVE ERROR REGISTER 2 + +ER2STS: STS 1,WRITE CURRENT UNSAFE + STS 2,CURRENT SINK FAILURE + STS 4,WRITE SELECT UNSAFE + STS 10,CURRENT SWITCH UNSAFE + STS 20,MOTOR SEQUENCE ERR + STS 40,TRANSITIONS DET FAIL + STS 100,TRANSITIONS UNSAFE + STS 200,"UNSAFE EXCEPT R/W" + STS 400,WRITE READY UNSAFE + STS 1000,MULTIPLE HEAD SELECT + STS 2000,NO HEAD SELECT + STS 4000,INDEX ERROR + STS 10000,30 VOLT UNSAFE + STS 20000,PHASE LK OSC UNSAFE + STS 100000,AC UNSAFE + 0 + +; DRIVE ERROR REGISTER 3 + +ER3STS: STS 1,PACK SPEED UNSAFE + STS 2,VELOCITY UNSAFE + STS 10,UNSAFE EXCEPT R/W + STS 40,AC LOW + STS 100,DC LOW + STS 40000,SEEK INCOMPLETE + STS 100000,OFF CYLINDER + 0 + +; DRIVE OFFSET REGISTER + +OFSSTS: STS 2000,HDR COMPARE INH + STS 4000,ECC INHIBIT + STS 10000,PDP-11 FORMAT + 0 +];RH + +IFN T300P,[ +;PRINT STATUS OF T300 (ERROR FROM LAST COMMAND) +;LATER THIS WILL BE INTEGRATED INTO GSTS +T300ST: MOVEI P,PDL + PUSH P,[DDT] +T3STS: INSIRP PUSH P,[A B C D T I K] + TYPE T-300 AND 2561 STATUS: + SKIPN D,DSCFLT + JRST T3STS2 + TRNN D,%DFRST+%DFCQE+%DFNXM+%DFPAR + JRST T3STS1 + MOVEI C,[ STS %DFRST,CONTROLLER POWER-CYCLED AND RESET + STS %DFCQE,COMMAND-QUEUE ERROR + STS %DFNXM,RQB NXM + STS %DFPAR,RQB PARITY ERROR + 0 ] + MOVSS D ;TYPSTS WANTS BITS IN LEFT HALF + PUSHJ P,TYPSTS + TYPE , PDP-11 ERROR ADDRESS= + LDB A,[000200,,DSCFLT] + LSH A,16. + IOR A,DSCSTS + PUSHJ P,TOPT +T3STS9: PUSHJ P,CRR + JRST GSTS3 + +;FAULT CODE +T3STS1: CAILE D,17 + JRST [ TYPE ILLEGAL FAULT CODE= + MOVE A,D + PUSHJ P,TOPT + JRST T3STS9 ] + MOVE B,(D)[ [ASCIZ/FAULT CODE 0?/] + [ASCIZ/DRIVE NOT READY/] + [ASCIZ/ILLEGAL HEAD OR SECTOR/] + [ASCIZ/SEEK TIMEOUT/] + [ASCIZ/DISK STATUS BAD AFTER ON-CYLINDER (FAULT CODE 4)/] + [ASCIZ/TIME OUT WRITING SECTOR ID (FAULT CODE 5)/] + [ASCIZ/FIFO ERROR IN FORMAT WRITE (FAULT CODE 6)/] + [ASCIZ/WRITE TIMEOUT (FAULT CODE 7)/] + [ASCIZ/SEEK TIMEOUT (FAULT CODE 10)/] + [ASCIZ/HEADS NOT LOADED/] + [ASCIZ/READ TIMEOUT (FAULT CODE 12)/] + [ASCIZ/INDEX TIMEOUT (FAULT CODE 13)/] + [ASCIZ/SECTOR TIMEOUT (FAULT CODE 14)/] + [ASCIZ/FAULT CODE 15?/] + [ASCIZ/DMA TIMEOUT (FAULT CODE 16)/] + [ASCIZ/DMA TIMEOUT IN ECC (FAULT CODE 17)/] ] + PUSHJ P,OUTSTR + PUSHJ P,CRR +;COMMAND OK, CHECK ORDINARY ERROR STATUS +T3STS2: MOVE D,DSCSTS + MOVEI C,[ STS %DSRTR,COMMAND WAS RETRIED + STS %DSECH,UNCORRECTABLE DATA ERROR + STS %DSECC,CORRECTED DATA ERROR + STS %DSIDE,ID ERROR + STS %DSHCE,HEADER COMPARE ERROR + STS %DSPRT,WRITE-PROTECTED SECTOR + STS %DSALT,ALTERNATE-SECTOR FLAG + STS %DSOVR,OVERRUN + STS %DSSKE,SEEK ERROR + STS %DSOFL,DRIVE OFF-LINE OR FAULT + STS %DSFLT,DRIVE FAULT + STS %DSNXM,PDP11 MEMORY NXM + STS %DSPAR,PDP11 MEMORY PARITY ERROR + STS %DSSFL,SYSTEM FAULT + STS %DSWLK,DRIVE WRITE-LOCKED + 0 ] + MOVSS D ;TYPSTS WANTS D IN LEFT HALF + PUSHJ P,TYPSTS + PUSHJ P,CRR ;NOW SHOW DISK COMMAND AND ADDRESS + TYPE DISK COMMAND: + MOVE A,DSCCMD + PUSHJ P,TOPT + PUSHJ P,TSPAC + MOVEI B,[ASCIZ/(UNKNOWN?)/] + CAIN A,%DMSNS + MOVEI B,[ASCIZ/(SENSE)/] + CAIN A,%DMTST + MOVEI B,[ASCIZ/(DIAGNOSTICS)/] + CAIN A,%DMREC + MOVEI B,[ASCIZ/(RECALIBRATE)/] + CAIN A,%DMSEK + MOVEI B,[ASCIZ/(SEEK)/] + CAIN A,%DMWRT + MOVEI B,[ASCIZ/(WRITE)/] + TRNE A,%DMRED + JRST [ CAIG A,%DMRED+10 + MOVE B,(A)[ [ASCIZ/(READ)/] + [ASCIZ/(READ EARLY-DATA-STROBE)/] + [ASCIZ/(READ LATE-DATA-STROBE)/] + [ASCIZ/(READ POSITIVE-CYLINDER-OFFSET)/] + [ASCIZ/(READ NEGATIVE-CYLINDER-OFFSET)/] + [ASCIZ/(READ EARLY-DATA-STROBE POSITIVE-CYLINDER-OFFSET)/] + [ASCIZ/(READ EARLY-DATA-STROBE NEGATIVE-CYLINDER-OFFSET)/] + [ASCIZ/(READ LATE-DATA-STROBE POSITIVE-CYLINDER-OFFSET)/] + [ASCIZ/(READ LATE-DATA-STROBE NEGATIVE-CYLINDER-OFFSET)/] + ]-%DMRED + JRST .+1 ] + PUSHJ P,OUTSTR + TYPE , DRIVE= + MOVE A,DSCDRV + PUSHJ P,TOPT + TYPE , CYL= + MOVE A,DSCCYL + PUSHJ P,TOPT + TYPE , HEAD= + MOVE A,DSCHED + PUSHJ P,TOPT + TYPE , SEC= + MOVE A,DSCSEC + PUSHJ P,TOPT + JRST T3STS9 +];T300P + +SUBTTL READ & TYPE OUT HEADERS + +DC,[ ;FOR NOW, DC10 ONLY +RDHDHD==20 ;2WORDS PER SEC, MANY SECS + +RDHEAD: JSR INIT ;READ ALL HEADERS ON A TRACK + PUSHJ P,CRR + UNTMES UNIT= + PUSHJ P,GETNUM + JRST RDHEAD + CAIL A,NUNITS + JRST RDHEAD + MOVEM A,TOU + MOVE I,A + PUSHJ P,RESET +RDHD1: TYPE CYL= + PUSHJ P,GETNUM + JRST DDT + CAIL A,NCYLS+XCYLS + JRST RDHD1 + SKIPGE QTRAN(I) + ADDI A,NCYLS+XCYLS + DPB A,[DCYL READHD] + TYPE SURF= + PUSHJ P,GETNUM + SETZ A, + CAIL A,NHEDS + JRST RDHD1 + DPB A,[DSURF READHD] + DATAO DC0,[DJMP READHD] + CONSZ DC0,DSSACT + JRST .-1 + CONSZ DC0,DSSERR + JRST [ TYPE ERROR--- + JRST GETSTS] + SETOM SECT0' + SETOM FIRST + SETZ T, +RDHD2: MOVE D,HEADBF(T) + TLZ D,777000 + CAMN D,SECT0 + JRST RDHD1 ;GONE AROUND ONCE + AOSN FIRST + MOVEM D,SECT0 + TYPE PKID= + LDB A,[DPKID HEADBF(T)] + PUSHJ P,TOPT + PUSHJ P,TCOMMA + MOVE D,HEADBF(T) + PUSHJ P,TYPLOC + PUSHJ P,CRR + MOVE A,HEADBF+1(T) + TLNE A,1000 ;INDIRECT BIT OF HEADER + JRST [ MOVEI A,"@ + PUSHJ P,TYO + MOVE D,HEADBF+1(T) + PUSHJ P,TYPLOC + JRST RDHD6] + TYPE LENGTH= + MOVN A,HEADBF+1(T) + LDB A,[1600,,A] ;LENGTH FIELD + PUSHJ P,TOPT + LDB A,[270200,,HEADBF+1(T)] ;ANY NEXT-ADDRESS CODE? + JUMPE A,RDHD3 + MOVE B,NXTADR(A) + PUSHJ P,OUTSTR +RDHD3: MOVE A,HEADBF+1(T) + TLNE A,200 + JRST [ MOVEI B,[ASCIZ /,WRITE PROTECT/] + PUSHJ P,OUTSTR + JRST .+1] +RDHD6: SETO C, ;PARITY + HRLI T,-2 +RDHD4: MOVEI D,14. + MOVE A,HEADBF(T) + XORM A,C + LSH A,-2 + SOJG D,.-2 + AOBJN T,RDHD4 + TRNN C,3 ;BOTH ODD? + JRST RDHD5 + MOVEI B,[ASCIZ /,BAD PARITY!!/] + PUSHJ P,OUTSTR +RDHD5: PUSHJ P,CRR + CAIL T,RDHDHD*NSECS + JRST RDHD1 + JRST RDHD2 + +READHD: DSPC+DSWIDX+DSWNUL+DSCRHD ;WAIT FOR INDEX, THENREAD HEADERS + QCOPY HEADBF,RDHDHD*NSECS + DHLT + +HEADBF: BLOCK RDHDHD*NSECS + +TCOMMA: MOVEI A,", + JRST TYO + +NXTADR: 0 + [ASCIZ /,END-OF-TRACK/] + [ASCIZ /,END-OF-CYLINDER/] + [ASCIZ /,END-OF-DISC/] + +TYPLOC: TYPE CYL= + LDB A,[DCYL D] + PUSHJ P,TOPT + TYPE ,SURF= + LDB A,[DSURF D] + PUSHJ P,TOPT + TYPE ,SECT= + LDB A,[DSECT D] + JRST TOPT + +GETNUM: SETZ C, + SETOM FIRST +GETNM1: PUSHJ P,TYI + CAIL A,"0 + CAILE A,"9 + JRST [ MOVE A,C + SKIPL FIRST + AOS (P) + JRST CRR] + AOS FIRST + IMULI C,10 + ADDI C,-"0(A) + JRST GETNM1 +];DC + +SUBTTL DRIVE RESET + +NTS,[ +DC,[ +RECAL: CONO DC0,DCCSET+DCDENB + MOVE T,QTRAN(I) + SKIPL DRIVE(T) ;SKIP IF DRIVE NOT KNOWN TO BE DEAD ALREADY + JRST [ SETZM QACT(I) + POPJ P,] + DPB T,[DUNFLD DRST] + DPB T,[DUNFLD STOSTS] + DATAO DC0,[DJMP STOSTS] + CONSZ DC0,DSSACT + JRST .-1 + MOVE T,STATUS + TDNN T,[DDSONL] ;ON LINE + JRST OFFL1 + DATAO DC0,DRST + CONSO DC0,DSSATT + JRST .-1 + CONSO DC1,20 ;OFF LINE OR MULTIPLE SELECT + POPJ P, +OFFL1: SETZM QACT(I) + SKIPE GOGOX + POPJ P, ;IN GOGO MODE, WILL CHECK FOR RIGHT PACKS MOUNTED + TYPE Drive off line # + PUSH P,A + HRRZ A,QTRAN(I) + SETZM DRIVE(A) + PUSHJ P,DPT + POP P,A + PUSHJ P,CRR + POPJ P, +];DC + +RP,[ +RESET: PUSH P,A + CONSZ DPC,BUSY + JRST .-1 + DATAO DPC,[DEASEC 776] + DPB I,[DUNFLD DRST] + DATAO DPC,DRST +RESET0: DATAI DPC,T + TLNE T,20 + JRST RESET1 + SKIPE GOGOX + JRST RESET9 ;IN GOGO MODE, WILL CHECK FOR RIGHT PACKS MOUNTED + TYPE OFF LINE # + MOVE A,I + PUSHJ P,DPT + PUSHJ P,CRR + JRST RESET9 + +RESET1: TLNN T,4 + JRST RESET2 + SKIPE GOGOX + JRST RESET9 ;IN GOGO MODE, WILL CHECK FOR RIGHT PACKS MOUNTED + TYPE NO SUCH DRIVE # + MOVE A,I + PUSHJ P,DPT + PUSHJ P,LCRR + JRST RESET9 + +RESET2: TRNN T,776 + JRST RESET0 + DATAO DPC,[DEASEC 776] + JRST POPAJ + +RESET9: SETZM QACT(I) ;THIS DRIVE LOST + JRST POPAJ + +DRST: DRCALC +];RP + +DC,[ +RESET: PUSHJ P,RECAL + MOVE T,QTRAN(I) ;GET PACK ID FROM HARDWARE + DPB T,[DUNFLD GPKID] + MOVEI T,TUTCYL + SKIPGE QTRAN(I) + ADDI T,NCYLS+XCYLS + DPB T,[DCYL GPKID] + CONO DC0,DCCSET+DCDENB + DATAO DC0,[DJMP GPKID] + CONSZ DC0,DSSACT + JRST .-1 + LDB T,[DPKID RPKID] + MOVEM T,PKNUM(I) + POPJ P, + +DRST: DSPC+DSRCAL+DSWINF+DUNENB +GPKID: DSPC+DSCRHD+DSWNUL+DUNENB+TUTCYL_11.+TUTSRF_6+TUTSEC + DCOPY RPKID(37774) + DHLT +];DC +];NTS + +TS,[ +RESET: PUSH P,A + HRRZ A,QTRAN(I) + SKIPL DRIVE(A) + JRST OFFL2 + CAML I,NQS + JRST OFFL2 + HRRZ A,SQACT ;SYSTEM QACT TABLE + ADD A,I + MOVSS A + HRRI A,A + .GETLOC A, ;COPY SYSTEMS QACT + SKIPE A ;0 MEANS ON-LINE TO ITS + JRST OFFLIN + POP P,A + POPJ P, + + +OFFLIN: TYPE Drive off line # + HRRZ A,QTRAN(I) + SETZM DRIVE(A) + PUSHJ P,DPT + PUSHJ P,CRR +OFFL2: SETZM QACT(I) + POP P,A + POPJ P, +];TS + +NTS,[ +RH,[ +RESET: MOVE T,QTRAN(I) ;GET PHYS DRIVE +IFN T300P,[ + CAIL I,T300P + JRST T3RST +];T300P + SKIPL DRIVE(T) + JRST [ SETZM QACT(I) ;DRIVE ALREADY KNOWN TO BE DOWN + POPJ P, ] + PUSH P,A + MOVE A,[%HRDCL,,%HMCLR] ;CLEAR THE DRIVE + PUSHJ P,RHSET + JRST RESETL ;HMM, NO DRIVE + MOVE A,[%HRDCL,,%HMRDP] ;I SAID, "CLEAR THE DRIVE"! + PUSHJ P,RHSET + JRST RESETL + MOVE A,[%HROFS,,0] ;CLEAR THE FRIGGING DRIVE!!! + PUSHJ P,RHSET + JRST RESETL + MOVSI A,%HRTYP ;GET DRIVE TYPE + PUSHJ P,RHGET + JRST RESETL ;?? + TRNE A,140000 + JRST RESETL ;TAPE? + TRNN A,020000 + JRST RESETL ;FIXED HEADS? + MOVE A,[%HRDCL,,%HMACK] ;PACK ACKNOWLEDGE + PUSHJ P,RHSET + JRST RESETL + MOVSI A,%HRSTS + PUSHJ P,RHGET + JRST RESETL + TRNN A,%HSMOL + JRST RESET4 ;PACK NOT MOUNTED + MOVE A,[%HRDCL,,%HMREC] ;RECALIBRATE + PUSHJ P,RHSET + JRST RESETL + MOVEI B,80000. ;A LITTLE OVER 1/2 SEC +RESET0: MOVSI A,%HRSTS ;GET STATUS + PUSHJ P,RHGET + JRST RESETL ;DRIVE VANISHED? + TRNE A,%HSERR + JRST RESETL ;GOT ERROR RECALIBRATING? + TRC A,%HSVV+%HSMOL+%HSRDY ;CHECK FOR GOOD BITS + TRCE A,%HSVV+%HSMOL+%HSRDY + SOJG B,RESET0 ;BITS NOT ALL ON, WAIT MORE + JUMPG B,RESET5 ;WON. + ;TIMED OUT, FALL INTO RESETL + +RESETL: SETZM QACT(I) ;LOST + SKIPE GOGOX + JRST POPAJ ;IN GOGO MODE, WILL CHECK FOR RIGHT PACKS MOUNTED + CONSZ DSK,%HIDRE + JRST RESET1 + CONSZ DSK,%HIILC + JRST RESET2 + TYPE MISC ERROR DRIVE # + MOVEI A,GSTS ;CALL GSTS BEFORE RETURNING + EXCH A,(P) + PUSH P,A + JRST RESET3 + +RESET2: TYPE ILC OR RAE DRIVE # + JRST RESET3 + +RESET1: TYPE DRIVE NOT PRESENT # +RESET3: HRRZ A,QTRAN(I) + X DPT + X CRR + JRST POPAJ + +RESET4: SETZM QACT(I) + SKIPE GOGOX + JRST POPAJ ;IN GOGO MODE, WILL CHECK FOR RIGHT PACKS MOUNTED + TYPE DRIVE OFF LINE # + JRST RESET3 + +RESET5: SKIPE MARKF + JRST POPAJ ;PACK NOT FORMATTED YET + MOVSI A,%HRCYL + HRRI A,TUTCYL + PUSHJ P,RHSET + JRST RESETL + MOVSI A,%HRADR + PUSHJ P,RHSET + JRST RESETL + MOVE A,[-2_4,,SLVIOWD-1] + MOVEM A,SLVICWA + SETZM SLVICWA+1 +KL,[ SWPUO 0 + CONSZ APR,200000 + JRST .-1 +] + MOVE A,[%HRCTL,,SLVICWA_6+%HMRHD] + PUSHJ P,RHSET + JRST RESETL + CONSO DSK,%HIDONE + JRST .-1 + CONSZ DSK,%HIERR + JRST RESETL + HRRZ A,SLVIOWD+1 ;GET I.T.S. PACK NUMBER + MOVEM A,PKNUM(I) + JRST POPAJ +];RH + +IFN T300P,[ +T3RST: PUSH P,D + MOVEI D,%DMSNS ;FIRST, SENSE STATUS (RECALIBRATE HANGS IF + PUSHJ P,T3CMD ; DRIVE OFF LINE, AND TIMEOUT LEAVES 11 WEDGED) + JUMPL T,T3RSTL ;TIMEOUT, 11 MUST BE DOWN + TDNE T,[%DFRST,,%DSOFL+%DSSFL] + JRST T3RSTL ;DRIVE OFF-LINE, LEAVE IT ALONE + MOVEI D,%DMREC ;SEND A RECALIBRATE + PUSHJ P,T3CMD + JUMPN T,T3RSTL ;JUMP IF ERROR + SETOM PKNUM(I) ;PACK NUMBER NOT GOTTEN FROM HARDWARE! + POP P,D + POPJ P, + +T3RSTL: SETZM QACT(I) ;OFF LINE + POP P,D + SKIPN GOGOX + JRST T3STS + POPJ P, + +;DO COMMAND IN D ON DRIVE NUMBER IN I, RETURN STATUS IN T (0 IF OK) +;LH(T) GETS DSCFLT, RH(T) GETS DSCSTS +;YOU MUST SET UP DSCCYL, ETC. BEFORE CALLING +T3CMD: MOVEI T,2561 + MOVEM T,DSCCHK + MOVEM D,DSCCMD + MOVEI T,-T300P(I) + MOVEM T,DSCDRV + SETZM DSCDON +KL,[ SWPUO 0 ;UNLOAD PAGE 0 FROM THE CACHE + CONSZ APR,200000 + JRST .-1 +];KL + MOVEI T,1 + MOVEM T,DSCREQ +KL,[ SWPUO 0 ;UNLOAD PAGE 0 FROM THE CACHE + CONSZ APR,200000 ;AGAIN SO 11 WILL SEE DSCREQ ON IN INTERRUPT + JRST .-1 +];KL + CONO DLC,100040 ;INTERRUPT 11 + MOVEI T,60000. ;I THINK THIS TIMEOUT IS ABOUT 3 SECONDS + ;UNFORTUNATELY, THIS TIMEOUT DOESN'T WORK ANYWAY + ;REALLY, BECAUSE IF DRIVE 0 IS OFFLINE THE + ;CONTROLLER HANGS AND EXECUTES COMMANDS WRONG + ;AND OTHERWISE LOSES ITS ASS. +T3CMD1: +KL,[ SWPUO 0 ;UNLOAD PAGE 0 FROM THE CACHE + CONSZ APR,200000 ;AGAIN SO DSCDON GETS PICKED UP FROM MAIN MEMORY + JRST .-1 +];KL + SKIPN DSCDON + SOJG T,T3CMD1 + JUMPLE T,[ MOVSI T,(SETZ) ;SIGNAL TIMEOUT (DRIVE OFFLINE?) + POPJ P, ] ;DSCFLT & DSCSTS WILL SAY NON-ERROR + SETZM DSCDON + CONO DLC,10 ;11 IS TRYING TO INTERRUPT -10, TURN IT OFF + HRLZ T,DSCFLT + HRR T,DSCSTS + TRZE T,%DSRTR+%DSECC ;THESE ARE NOT ERRORS + AOS CERRS + POPJ P, +];T300P +];NTS + +SUBTTL READ & WRITE TUT + +;DISK NUMBER IN I, CORE ADDR IN A, ERROR RETURN HAS T NEGATIVE + +WRTUT: +TS, JRST SUCCESS +NTS,[ MOVE J,MFDBK + SUB J,NTBL(I) +WRTUT0: PUSHJ P,WRITE + JUMPL T,CPOPJ + ADDI A,2000 + ADDI J,1 + CAMGE J,MFDBK + JRST WRTUT0 + POPJ P, +];NTS + +RDTUT: +NTS,[ MOVE J,MFDBK + SUB J,NTBL(I) +RDTUT0: PUSHJ P,READ + JUMPL T,CPOPJ + ADDI A,2000 + ADDI J,1 + CAMGE J,MFDBK + JRST RDTUT0 + POPJ P, +];NTS +TS,[ TUTPAG==600000 ;READ TUT BY MAPPING IN ABS PAGE + MOVE T,NTBL(I) ;SIZE OF TUT ON THIS DRIVE + MOVE J,[SQUOZE 0,QTUTO] ;AND WHERE ARE THEY LOCATED? + .EVAL J, + .VALUE + PUSH P,A + PUSH P,I + ADD J,I ;-> -> FIRST BLOCK THIS TUT + MOVSS J + HRRI J,J + .GETLOC J, + HRRZS J + LSH J,-10. ;FIRST BLOCK# OF TUT + MOVN I,T + HRL J,I ;AOBJN PTR FOR BLOCKS OF THIS TUT +RDTUT1: .CALL [ SETZ + 'CORBLK + MOVEI 210000 ;READ ONLY + MOVEI -1 ;INTO SELF + MOVEI TUTPAG/2000 + MOVEI 400000 ;FROM SYSTEM + SETZI (J) ] + .VALUE + MOVSI I,TUTPAG + JRST RDTUT3 + +RDTUT3: HRRI I,(A) + BLT I,1777(A) ;COPY IN A BLOCK OF TUT + ADDI A,2000 + AOBJN J,RDTUT1 + POP P,I + POP P,A + SKIPGE QPKNUM(A) + .VALUE ;OLD FORMAT? + SKIPN QLASTB(A) + .VALUE ;OLDER FORMAT? + JRST SUCCESS +];TS + +SUBTTL DISK I/O + +WRITT: MOVE I,TOU +WRITE: HRRZM J,LBLK' +TS,[ HRRZ TT,I + CAML TT,NQS + .VALUE + HRRZ TT,J + CAIGE TT,TBLKS + SKIPGE TT + .VALUE + JRST SUCCESS +];TS +DC,[ SKIPA T,[DWR] +READ: MOVEI T,DRD ;A/ CORE LOCN, I/ DRIVE J/TRACK # + HRRM T,DGO + HRRZM J,BLK + MOVEM I,UNIT + HRRZ TT,I + CAIL TT,NUNITS + JRST 4,. + HRRZ TT,J + CAIGE TT,TBLKS + SKIPGE TT + JRST 4,. + MOVE TT,QTRAN(I) ;GET PHYSICAL DRIVE # + DPB TT,[DUNFLD (T)] + DPB A,[DCCA 1(T)] + DPB A,[DCCA 4(T)] + HRRZ TT,J + CAIL TT,NBLKS+XBLKS + JRST 4,. + IDIVI TT,NSECS + DPB T,[DSECT @DGO] + IDIVI TT,NHEDS + DPB T,[DSURF @DGO] + MOVE T,TT + SKIPGE QTRAN(I) + ADDI T,NCYLS+XCYLS ;MAP INTO 2ND HALF OF CALCOMP + DPB T,[DCYL @DGO] + MOVE T,PKNUM(I) + CAIL TT,NCYLS + MOVEI T,0 + DPB T,[DPKID @DGO] + HRRZ TT,DGO + MOVE T,(TT) + TLZ T,340000 ;CHANGE TO READ COMPARE + MOVEM T,3(TT) +RW1: MOVEI T,30. + SKIPE HCRASH + MOVEI T,0 ;SPEED IS OF THE ESSENCE - TRY ONLY ONCE +RW2: CONO DC0,DCCSET\DCDENB + DATAO DC0,DGO + MOVSI TT,3 ;WAIT AT MOST 3 SECONDS + CONSZ DC0,DSSACT + SOJGE TT,.-1 + JUMPL TT,[ PUSH P,T + X RECAL + POP P,T + JRST .+2 ] + CONSZ DC0,DSSERR + SOJGE T,RW2 + SKIPGE T + AOS FERRS + POPJ P, + +DGO: DJMP . + +DRD: DREAD+DUNENB + DCOPY .(-2000_2&37774) + DCOPY RXWDS(-4_2&37774) + DRC + DCCOMP .(-2000_2&37774) + DCCOMP RXWDS (-4_2&37774) + DHLT + +DWR: DWRITE+DUNENB + DCOPY .(-2000_2&37774) + DCOPY WXWDS(-4_2&37774) + DRC + DCCOMP .(-2000_2&37774) + DCCOMP WXWDS(-4_2&37774) + DHLT +];DC + +TS,[ +READ: HRRZ TT,I + CAIL TT,NUNITS + .VALUE + HRRZ TT,J + CAMN TT,MFDBK + JRST [ .OPEN QIN,[.BII,,'DSK + SIXBIT /M.F.D./ + SIXBIT /(FILE)/] + .VALUE + JRST RDIN] + CAML TT,NUDS + .VALUE ;SOME RANDOM DISK BLOCK + .SUSET [.SSNAM,,USRNAM] + .OPEN QIN,[.BII,,'DSK + SIXBIT /.FILE./ + SIXBIT /(DIR)/] + .VALUE +RDIN: HRLI A,-2000 + .IOT QIN,A + .CLOSE QIN, +SUCCES: MOVEI T,30. + POPJ P, +];TS + RP,[ ;RP10 I/O - FALL IN FROM WRITE + SKIPA T,DWR +READ: MOVE T,DRD + MOVEM T,RPIOOP + HRRZ TT,J + CAIL TT,MBLKS+XBLKS + JRST 4,. + IMULI TT,SECBLK + IDIVI TT,NSECS + MOVEM T,RPIOSC + IDIVI TT,NHEDS + MOVEM T,RPIOHD + MOVEM TT,RPIOCY + MOVEM A,RPAOBJ + MOVNI T,2000 + HRLM T,RPAOBJ + JRST RPIO ;DO IT + +DRD: DREADC+SLVICWA+5000 ;DISABLE PARITY ERROR STOPS +DWR: DWRITC+SLVICWA + +;VARIABLES SET UP TO CONTROL TRANSFER +;WHEN AN ERROR OCCURS, IT GOES INTO SECTOR AT A TIME MODE, AND +;THESE VARIABLES ARE STEPPED ALONG TO REFLECT THAT. +RPAOBJ: 0 ;AOBJN POINTER TO WORDS TO BE TRANSFERRED +RPIOCY: 0 ;CYLINDER TO START AT +RPIOHD: 0 ;HEAD TO START AT +RPIOSC: 0 ;SECTOR TO START AT +RPIOOP: 0 ;COMMAND WORD. SLVICWA ALREADY ADDED IN +;UNIT IS IN I + +;HIGH-LEVEL I/O ROUTINE. TRIES TO DO IT ALL AT ONCE, +;IF THAT LOSES TWICE TRIES IT A SECTOR AT A TIME. +;IF HCRASH IS SET, TRY ONLY ONCE. +;SMASHES T, TT. RETURNS T NEGATIVE IF ERROR. +RPIO: PUSH P,A + SETZM SLVIOWD+1 + MOVE T,RPAOBJ + SOS T + MOVEM T,SLVIOWD + PUSHJ P,RPXIO ;TRY IT + JRST RPIO1 + MOVEI T,102 ;WON + JRST RPIO9 + +RPIO1: SETOM T + SKIPE HCRASH + JRST RPIO9 ;GIVE UP IF HCRASH + PUSHJ P,RPRCAL ;RECALIBRATE, THEN + PUSHJ P,RPXIO ;TRY IT AGAIN + JRST RPIO2 + MOVEI T,101 ;WON +RPIO9: SKIPGE T + AOS FERRS + POP P,A + POPJ P, + +;SECTOR AT A TIME MODE +RPIO2: MOVEI T,100 + SKIPL TT,RPAOBJ + JRST RPIO9 ;TRANSFER EXHAUSTED, WON + SOS TT + HRLI TT,-200 + MOVEM TT,SLVIOWD + MOVEI T,10. ;TRY THIS SECTOR 10 TIMES + PUSHJ P,RPXIO + SOJGE T,.-1 + JUMPL T,RPIO9 ;GIVE UP + MOVE T,[200,,200] ;ADVANCE TO NEXT SECTOR + ADDM T,RPAOBJ + AOS T,RPIOSC + CAIGE T,NSECS + JRST RPIO2 + SETZM RPIOSC + AOS T,RPIOHD + CAIGE T,NHEDS + JRST RPIO2 + SKIPL RPAOBJ + JRST RPIO2 + JRST 4,. ;CYLINDER OVERFLOW? + +;LOW-LEVEL IO, JUST DO THE OPERATION SPECIFIED IN THE VARIABLES. +;CLOBBER A,TT. +;SKIP IF SUCCESS. +RPXIO: MOVEI TT,SLVIOWD ;SET UP DF10 COMMAND + HRRZM TT,SLVICWA + SETZM SLVICWA+1 + PUSH P,T + PUSHJ P,SEEK ;MAKE SURE AT DESIRED CYLINDER + JRST POPTJ ;SEEK FAILED + POP P,T + MOVE A,RPIOOP ;SET UP RP10 DATAO + DPB I,[DUNFLD A] + MOVE TT,RPIOCY + DPB TT,[DCYL A] + LSH TT,-8 ;FOR RP03 + DPB TT,[DCYLXB A] + MOVE TT,RPIOHD + DPB TT,[DSURF A] + MOVE TT,RPIOSC + DPB TT,[DSECT A] + CONO DPC,DCLEAR + SKIPN HCRASH ;IF HCRASH, MAY BE MONITORING SOMETHING IN LIGHTS? + DATAO LIGHTS,A + DATAO DPC,A ;ISSUE COMMAND + CONSO DPC,DONE ;AWAIT DONE + JRST .-1 + CONSZ DPC,ALLER ;SKIP-RETURN UNLESS ERROR + POPJ P, + HLRO TT,RPAOBJ ;SEEMS SUCCESSFUL, CHECK THE CHANNEL CONTROL WORD STORED + HRRZ A,RPAOBJ + SUB A,TT ;SUPPOSED END OF TRANSFER + HRRZ TT,SLVICWA+1 + CAIE A,1(TT) +DF10FK: POPJ P, ;CHANNEL TRYING TO FUCK YOU OVER + JRST POPJ1 + +;RECALIBRATE UNIT IN I, SMASHES T,TT +RPRCAL: CONO DPC,DCLEAR + MOVE T,[DEASEC 776] + DPB I,[DUNFLD T] ;LEAVE PROPER UNIT SELECTED FOR GETSTS + DATAO DPC,T ;CLEAR ATTNS + DPB I,[DUNFLD DRST] + DATAO DPC,DRST +RPRCL1: DATAI DPC,TT + TLNN TT,(ONLINE) + POPJ P, ;OFF LINE + TLNE TT,(NSCHDR) + POPJ P, ;NO SUCH DRIVE + TRNN TT,776 + JRST RPRCL1 ;AWAIT ATTENTION + DATAO DPC,T ;GOT ATTENTION, CLEAR IT +RPRCL2: TLNE TT,(ONCYL+SKINC) + POPJ P, ;DONE + DATAI DPC,TT + JRST RPRCL2 ;ON CYLINDER SOMETIMES TAKES A WHILE TO SET + +;SEEK TO CYLINDER IN RPIOCY ON UNIT I, SMASHES T,TT, SKIPS ON SUCCESS. +SEEK: MOVEI TT,10. + MOVEM TT,SEEKC +SEEK1: CONSZ DPC,BUSY + JRST .-1 + DATAO DPC,[DEASEC 776] + MOVSI TT,(DSEEKC) + DPB I,[DUNFLD TT] + MOVE T,RPIOCY + DPB T,[DCYL TT] + LSH T,-8 ;FOR RP03 + DPB T,[DCYLXB TT] + SKIPN HCRASH + DATAO LIGHTS,TT + CONO DPC,DCLEAR + DATAO DPC,TT + MOVE T,[DEASEC 776] + DPB I,[DUNFLD T] ;LEAVE PROPER UNIT SELECTED FOR GETSTS + PUSHJ P,RPRCL1 ;AWAIT COMPLETION + TLNE TT,(ONCYL) ;SUCCEED IF ON CYLINDER + JRST POPJ1 + SOSGE T,SEEKC ;COUNT FAILURES + POPJ P, ;GIVE UP + PUSHJ P,RPRCAL ;RECALIBRATE + JRST SEEK1 ;AND TRY AGAIN +];RP + RH,[ ;RH10 I/O - FALL IN FROM WRITE + +;ENTER WITH: A ADDRESS, J BLOCK NUMBER, I VIRTUAL UNIT +.SEE RHCMD ;VARIABLES CONTROLLING WHAT GOES ON HERE +;INSIDE RW2 TT GENERALLY HAS THE DISK COMMAND AND T HAS THE RETRY COUNT +;ONLY T AND TT CLOBBERED +;ON RETURN T MINUS IF ERROR + + SKIPA TT,[%HMWRT] +READ: MOVEI TT,%HMRED +IFN T300P,[ + CAIL I,T300P + JRST T3IO + SETZM T3IOP +];T300P + MOVEM TT,RHCMD + HRRZ TT,J + CAIL TT,TBLKS + JRST 4,. + IDIVI TT,NBLKSC ;TT:=CYLINDER, T:=BLOCKS INTO CYLINDER + HRLZM TT,RHPGA ;SAVE CYLINDER + MOVE TT,T ;GET BLOCKS INTO CYLINDER + IMULI TT,SECBLK ;SECTORS INTO CYLINDER + IDIVI TT,NSECS ;TT:=HEAD, T:=SECTOR + LSH TT,8 ;FORM ADDRESS WORD + IOR TT,T + HRRM TT,RHPGA ;COMPLETE THE ADDRESS + MOVEI T,-1(A) ;SET UP IOWD TO TRANSFER ONE BLOCK + HRLI T,-2000 + MOVEM T,RHIOW +;ENTER HERE WITH RHCMD, RHIOW, AND RHPGA SET UP. I HAS UNIT#. +RW1: MOVEI T,5 ;INIT LOSAGE COUNT + PUSHJ P,RW2 ;TRY + JRST RW7 ;FAILED +;HERE TO RETURN. T SAYS WHETHER WINNING OR LOSING. +RW5: MOVE A,[%HRDCL,,%HMCEN] ;RETURN TO CENTER-LINE IF NECESSARY + AOSN OFFSTF + PUSHJ P,RHSET + JFCL + SKIPGE T + AOS FERRS + MOVE A,RHIOW ;RESTORE A + MOVEI A,1(A) + POPJ P, + +;HERE IF LOSING. +RW7: SKIPE HCRASH + JRST RWL0 ;SPEED IS OF THE ESSENCE, TRY ONLY ONCE + PUSHJ P,RW2 ;HMM, TRY AGAIN + JRST RWLOSS ;STILL LOSING, COGITATE + JRST RW5 ;WINNING NOW + +RWLOSS: MOVSI A,%HROFS ;ATTACK OFFSET REGISTER + HRR A,OFFSTB(T) ;SET APPROPRIATE OFFSET VALUE + SETOM OFFSTF' ;REMEMBER TO RETURN TO CENTERLINE LATER + PUSHJ P,RHSET + JRST RWL0 ;WHAT?? + MOVE A,[%HRDCL,,%HMOFS] + PUSHJ P,RHSET + JRST RWL0 + MOVEI A,20000. ;WAIT 10 MS OR SO FOR GOOD LUCK + SOJG A,. + PUSHJ P,RW2 ;TRY IT NOW + SOJGE T,RWLOSS ;LOSE, TRY WITH DIFFERENT OFFSET + JUMPGE T,RW5 ;WON, SO TAKE WIN RETURN +RWL0: SETO T, ;COMPLETE LOSS, RETURN NOW + JRST RW5 + +OFFSTB: 260 + 60 + 240 + 40 + 220 + 20 + ;RH10 I/O ROUTINE PROPER +;FIRST STEP IS TO SET UP CHANNEL COMMAND LIST +RW2: MOVE TT,RHIOW ;SET UP ADDRESSES + MOVEM TT,RHTIOW + MOVE TT,RHPGA + MOVEM TT,RHTPGA +;RE-ENTER HERE AFTER ECC ERROR +RW2OVR: PUSH P,B + PUSH P,C + MOVE A,[-6,,SLVIOWD] ;POINTS TO WHERE CCWS WILL BE STORED + HLRO C,RHTIOW ;MINUS NUMBER OF WORDS TO TRANSFER + MOVNS C ;POSITIVE + HRRZ B,RHTIOW ;ADDRESS MINUS ONE +RW2CC1: MOVN TT,C ;WORDS TO TRANSFER IN THIS CCW + CAIL C,40000-200 ;WC IS ONLY A 14-BIT FIELD + MOVNI TT,40000-200 + MOVEM B,(A) ;STORE CA + DPB TT,[$DFWC (A)] ;STORE WC + ADD C,TT ;LESS WORDS TO DO + SUB B,TT ;ADVANCE ADDRESS + AOBJP A,[JRST 4,.] ;ADVANCE CCW PTR, HALT IF TOO BIG! + JUMPG C,RW2CC1 ;NEED MORE WORDS + SETZM (A) ;END CCW LIST + HRRZI A,SLVIOWD ;POINT CHANNEL AT IT + MOVEM A,SLVICWA + SETZM SLVICWA+1 ;INIT FOR CONTROL WORD WRITING + POP P,C + POP P,B + MOVEI A,SLVICWA ;BUILD DATAO CMD + MOVE TT,RHCMD + DPB A,[$HCICWA TT] + TLO TT,%HRCTL ;FILL OUT COMMAND WORD + ;NOW BEFORE GIVING COMMAND CHECK STATUS + CONSZ DSK,%HIBSY ;WAIT FOR DSK CONTROL + JRST .-1 + CONO DSK,%HOCLR ;CLEAR ANY LEFT-OVER ERROR INDICATORS +RW2A: MOVSI A,%HRSTS ;CHECK DRIVE STATUS + PUSHJ P,RHGET + JRST RW3 ;DRIVE VANISHED?? + TRNE A,%HSPIP ;WAIT FOR POSITIONING + JRST RW2A ;(MIGHT BE OFFSETTING HEADS?) + TRNE A,%HSERR ;ANY ERRORS IN DRIVE? + JRST RW6 ;YES, TRY TO RECOVER + TRC A,%HSVV+%HSMOL+%HSRDY ;CHECK FOR ALL READY BITS ON + TRCE A,%HSVV+%HSMOL+%HSRDY + JRST RW3 ;NOT READY?? + HLRZ A,RHTPGA ;SET CYLINDER + TLO A,%HRCYL + PUSHJ P,RHSET + JRST RW3 + HRRZ A,RHTPGA ;SET TRACK-SECTOR + TLO A,%HRADR + PUSHJ P,RHSET + JRST RW3 +KL,[ MOVE A,RHTIOW ;SWEEP THE CACHE + AOS A ;RH ADDRESS OF BUFFER, LH - # WDS + LSH A,-9. + TRZ A,777000 + TLO A,777000 ;A NOW HAS AOBJN PTR TO PAGES +RWSWP3: TRNE TT,10 ;SWEEP ONE PAGE + SWPIO (A) ;IF READING, INVALIDATE + TRNN TT,10 + SWPUO (A) ;IF WRITING, UNLOAD + CONSZ APR,200000 ;WAIT UNTIL SWEEPER WAKES + JRST .-1 + AOBJN A,RWSWP3 + SWPUO 0 ;STORE CHANNEL PROGRAM IN CORE + CONSZ APR,200000 + JRST .-1 +];KL +;DROPS THROUGH + ;DROPS IN +RWGO: MOVE A,TT ;ISSUE I/O COMMAND + PUSHJ P,RHSET + JRST RW3 + CONSO DSK,%HIDONE ;WAIT FOR COMPLETION + JRST .-1 + MOVSI A,%HRSTS ;CHECK DISK STATUS, ERRORS DON'T ALWAYS SHOW UP IN CONI + PUSHJ P,RHGET + JRST RW3 + TRNN A,%HSERR + CONSZ DSK,%HIERR + CAIA + JRST POPJ1 ;NO ERROR, SKIP RETURN FROM RW2 +;FOLLOWING TWO LINES CAUSE ECC NOT TO WORK +; CONSO DSK,%HIEXC +; POPJ P, ;NOT DRIVE EXCEPTION, PROBABLY CORRIGIBLE BY RETRY + TRNN A,%HSERR ;ANYTHING IN ERR REGS? + JRST RW3 ;FOO, WHAT IS GOING ON?? + MOVSI A,%HRER2 ;MAKE SURE NO UNSAFES + PUSHJ P,RHGET + JRST RW3 + JUMPN A,RW3 + MOVSI A,%HRER3 + PUSHJ P,RHGET + JRST RW3 + JUMPN A,RW3 + MOVSI A,%HRER1 ;GET ERROR1 REG + PUSHJ P,RHGET + JRST RW3 + TRNE A,077067 ;GROSS ERROR? + JRST RW3 ;YES, ABORT + TRZE A,100000 ;SEE IF CORRECTABLE DATA ERROR + JUMPE A,RWECC ;YES, GO FIX IT + POPJ P, ;ERROR, BUT RETRY MAY WIN + +RW6: MOVE A,[%HRDCL,,%HMCLR] ;ERROR IN DRIVE, TRY CLEARING + PUSHJ P,RHSET + JRST RW3 + MOVSI A,%HRSTS + PUSHJ P,RHGET + JRST RW3 + TRNN A,%HSERR + JRST RW2A ;WON + ;LOST, FALL INTO RW3 + +RW3: POP P,(P) ;UNCORRECTABLE ERROR, RW FAILS + JRST RWL0 + +;ERROR CORRECTION CODE -- TAKEN FROM MAINDEC-10-DDRPF +; THAT CODE HAD NO HOPE WHATSOEVER OF WORKING. RETAKEN FROM ITS. +; THAT CODE DIDN'T WORK EITHER. TAKEN FROM NEWER ITS. + +RWECC: TRNN TT,10 ;SKIP IF READ + POPJ P, ;RETRY IF WRITE + INSIRP PUSH P,[B W U J K H] + DW1==W ;FIRST WORD IN ERROR + DW2==U ;SECOND WORD IN ERROR + EP1==J ;FIRST WORD OF ERROR PATTERN + EP2==K ;SECOND WORD OF ERROR PATTERN + ADR==H ;ADDRESS OF LOSING WORDS + ;B ;SO CAN DIVIDE A + SKIPN A,SLVICWA+1 ;GET ADDRESS OF LAST WORD TRANSFERRED + JRST 4,.-1 ;CHANNEL SHOULD HAVE STORED CONTROL WORD + SOS ADR,A ;LAST WORD TRANSFERRED (SUPPOSEDLY) + ANDI ADR,-200 ;IN ANY CASE, THIS MAKES ADR -> START OF SECTOR + HRRZ A,RHTIOW ;ADR-1 OF START OF TRANSFER + SUBM ADR,A + SOS B,A ;NUMBER OF WORDS SUCCESSFULLY TRANSFERRED + MOVEM B,RHSUCC ;SAVE + HLRO K,RHTIOW + MOVNS K + CAIL B,0 ;CHECK FOR CHANNEL LYING + CAILE B,-200(K) + JRST RWECC3 ;FRAUD, TRANSFERRED NEGATIVE OR TOO MANY WORDS + MOVSI A,%HRPOS ;GET ERROR POSITION + PUSHJ P,RHGET + JRST RWECC3 + SOJL A,RWECC3 ;WHICH IS OFF BY 1. IF ZERO, LOSE. + IDIVI A,36. ;CONVERT TO WORD AND BIT + ADD ADR,A + MOVS DW1,(ADR) ;FETCH THE TWO LOSING WORDS + MOVS DW2,1(ADR) + MOVSI A,%HRPAT ;GET ERROR PATTERN + PUSHJ P,RHGET + JRST RWECC3 + MOVE EP1,A + SETZ EP2, + ROTC EP1,(B) ;ALIGN IT + XOR DW1,EP1 ;FIX THE ERRONEOUS BITS + XOR DW2,EP2 +RWECCB: ;SET BREAK HERE IF DON'T TRUST... + MOVSM DW1,(ADR) ;PUT CORRECTED DATA BACK + MOVSM DW2,1(ADR) + INSIRP POP P,[H K J U W] + + AOS CERRS ;COUNT NUMBER OF TIMES ECC DONE + MOVEI A,%HMCLR ;CLEAR THE ECC-ERROR CONDITION + PUSHJ P,RHSET + JFCL + MOVEI A,200 ;ALLOW FOR THE SECTOR WE CORRECTED + ADDB A,RHSUCC ;GET BACK NUMBER OF WORDS TRANSFERRED + IDIVI A,200 ;NUMBER OF SECTORS TRANSFERRED INCLUDING CORRECTED ONE + LDB B,[$HASEC RHTPGA] ;UPDATE DISK ADDRESS + ADD A,B + IDIVI A,NSECS + DPB B,[$HASEC RHTPGA] + LDB B,[$HATRK RHTPGA] + ADD A,B + DPB A,[$HATRK RHTPGA] ;NO NEED TO IDIVI A,NHEDS SINCE ALL XFERS WITHIN CYLINDER + MOVE A,RHSUCC ;NOW ADVANCE CCW + HRL A,A + ADDB A,RHTIOW + POP P,B + TLNE A,-1 + JRST RW2OVR ;NOT EXHAUSTED, CONTINUE DISK XFER + JRST POPJ1 ;ECC IN LAST SECTOR OF XFER, XFER COMPLETED SUCCESSFULLY + +RWECC3: INSIRP POP P,[H K J U W B] + JRST RW3 + +;ROUTINES TO ACCESS RH10 CONTROLLER AND DRIVE REGISTERS +;CALL WITH +; I UNIT NUMBER +; A REGISTER NUMBER IN LH +; NON-SKIP RETURN IF RAE ERROR +; SKIP RETURN IF WIN +;CLOBBERS ONLY A + +;SET REGISTER. TAKES DATA TO GO IN REGISTER IN RH OF A +;CLOBBERS A (PROBABLY) + +RHSET: TLOA A,%HRLOD ;TELL HARDWARE IS SET INSTEAD OF GET + ;AND FALL INTO RHGET + +;GET REGISTER. RETURNS 16 BITS RIGHT-JUSTIFIED IN A + +RHGET: TLZ A,%HRLOD + TLO A,(I) ;INSERT PHYS DRV NO + DATAO DSK,A ;TELL RH10 TO FETCH REGISTER + MOVEM A,RHLAST' ;SAVE FOR REBUGGING + MOVEI A,4 ;ENSURE 3 USEC DELAY BEFORE DATAI + SOJG A,. ;TO ALLOW MASSBUS TRANSACTION TO COMPLETE + DATAI DSK,A ;GET REG CONTENTS AND FLAGS + TLNE A,%HDERR ;ERROR? + JRST RHRAE ;YES, GO REPORT + ANDI A,177777 ;MASK TO 16 BITS + AOS (P) ;AND TAKE SUCCESS RETURN + POPJ P, + +RHRAE: MOVSI A,%HRRAE+%HRLOD(I) + DATAO DSK,A ;CLEAR RAE REGISTER IN CONTROLLER + POPJ P, ;AND TAKE NON-SKIP RETURN + +;DISK ROUTINE VARIABLES + +RHCMD: 0 ;%HMRED OR %HMWRT +RHIOW: 0 ;IOWD -NWDS,,ADR-1 FOR TRANSFER +RHTIOW: 0 ;TEMPORARY IOWD FOR CONTINUING FROM ECC +RHPGA: 0 ;DISK ADDRESS CYL,,HED_8+SEC +RHTPGA: 0 ;TEMPORARY DISK ADDRESS FOR CONTINUING FROM ECC +RHSUCC: 0 ;NUMBER OF WORDS SUCCESSFULLY TRANSFERRED BEFORE ECC +];RH + +IFN T300P,[ ;T-300 I/O - FALL IN FROM WRITE + +;ENTER WITH: A ADDRESS, J BLOCK NUMBER, I VIRTUAL UNIT +; TT %HMWRT OR %HMRED +;ONLY T AND TT CLOBBERED +;ON RETURN T MINUS IF ERROR + +T3IO: INSIRP PUSH P,[A B C D] + SETOM T3IOP' + CAIE TT,%HMRED ;GET READ OR WRITE COMMAND + SKIPA D,[%DMWRT] + MOVEI D,%DMRED +T3IO1: HRRZ A,J ;GUBBISH IN LH + IDIVI A,NBLKC1 ;A CYLINDER, B BLOCK WITHIN CYLINDER + MOVEM A,DSCCYL + IMULI B,SECBL1 ;B SECTOR WITHIN CYLINDER + IDIVI B,NSECS1 ;B HEAD, C SECTOR + MOVEM B,DSCHED + MOVEM C,DSCSEC + MOVE B,-3(P) ;ORIGINAL ADDRESS + HRLI B,730000 ;12-BIT BYTES, START WITH FIRST BYTE IN WORD + MOVE C,[-4,,DSCPNT] ;SET UP BYTE POINTERS + MOVEM B,(C) + ADDI B,400 + AOBJN C,.-2 +KL,[ SWPUA ;DUMP EVERYTHING OUT OF CACHE + CONSZ APR,200000 + JRST .-1 +];KL + PUSHJ P,T3CMD ;PERFORM THE OPERATION + JUMPE T,T3IO2 ;RETURN IF SUCCESS + MOVE A,T ;SEE IF ERROR MAY BE RECOVERABLE + TRZ A,%DSECH+%DSIDE+%DSHCE + JUMPN A,T3IO3 ;IF IRRECOVERABLE + TRNE D,%DMRED ;OR IF NOT A READ COMMAND + CAIN D,%DMRED+10 ;OR IF TRIED ALL RECOVERY FEATURES +T3IO3: TLOA T,(SETZ) ;ENSURE T NEGATIVE TO INDICATE ERROR + AOJA D,T3IO1 ;OTHERWISE RETRY USING NEXT ERROR RECOVERY FEATURE +T3IO2: INSIRP POP P,[D C B A] + POPJ P, +];T300P + +SUBTTL MISCELLANEOUS VARIABLES + +KL,SALVPF: JRST 4,. ;COME HERE IF PAGE FAIL IN SALVAGER + +CONSTANTS +VARIABLES + +POPTJ: POP P,T +CPOPJ: POPJ P, + +THBLK: -LTHBLK,,0 +THTPN: 0 ;TAPE #,,REEL # IN THIS DUMP +THDATE: 0 ;TAPE CREATION DATE +THTYPE: 0 ;0=>RANDOM >0 => FULL <0 => INCR +LTHBLK==.-THBLK + +MHBLK: -LMHBLK,,0 ;FILE HEADER BLOCK +MHSNM: 0 ;SYS NAME +MHFN1: 0 ;FN1 +MHFN2: 0 ;FN2 +MHPKN: 0 ;PACK # +MHDATE: 0 ;CREATION DATE +LMHBLK==.-MHBLK +LNKFLG: 0 ;NONZERO => RELOADING LINK +LNKNM1: 0 ;LINK FN1 +LNKNM2: 0 ;LINK FN2 +LNKSNM: 0 ;LINK SNAME +MAGHD: 0 +EOTFLG: 0 +EOFCNT: 0 +EOUF: 0 +SHORTL: 0 +MTRYS: 0 +MAGBFP: 0 +EOFLG: 0 + +FROM: 0 +TOU: 0 + +SBTAB: -1 ;FOR PATCHING + -1 + -1 + -1 +MFDBK: MFDBLK ;SPECIAL RESERVED BLKS + ;TUT USED TO BE HERE, BUT NO LONGER +LSBTAB==.-SBTAB + +;THIS IS AN ARRAY INDEXED BY UNIT GIVING THE NUMBER +;OF BLOCKS IN THE TUT ON THAT UNIT. +;THESE BLOCKS ARE ALWAYS RIGHT BEFORE THE MFD. +NTBL: +IFE T300P, REPEAT NUNITS, NTUTBL +IFN T300P,[ + REPEAT T300P, NTUTBL + REPEAT NUNITS-T300P, NTUTB1 +];T300P + +RXWDS: BLOCK 4 ;THE EXTRA WORDS + + 0 ;FOR BLT +WXWDS: BLOCK 4 + +NOLPT: 0 ;-1 FOR NO LPT +LPBUST: -1 ;-1 LPT IS BUSTED DON'T KEEP ASKING +PUNCH: 0 ;SET TO -1 WITH DDT IF COPY TTY OUTPUT TO PUNCH +HCRASH: 0 ;SET TO -1 WITH DDT IF EMERGENCY DUP AFTER HEAD CRASH + ;SACRAFICE EVERYTHING FOR SPEED SINCE PACK IS BEING SCRAPED BY HEADS +NUDS: NTS,[NUDSL]+0 ;NUMBER OF USER DIRECTORY BLOCKS +ADRSET: 0 ;ADDRESS SET +FMBLK: 0 ;FROM BLOCK +TOBLK: 0 ;TO BLOCK +LFRMSW: 0 +SEEKC: 0 +SHARED: 0 ;NUMBER OF SHARED BLOCKS +GOGOX: 0 ;-1 FOR AUTOMATIC MODE +NOQUES: 0 ;-1 TO ASK NO QUESTIONS (ONLY EFFECTIVE IN GOGOX MODE) +MDSK: 0 ;DISK TO GET MFD FROM +UDSK: 0 ;DSK TO GET UFD'S FROM +CKFLSW: 0 ;CHECK FILES FOR CLOBBERED BLOCKS +MFDWRT: 0 ;MFD CHANGED +TUTDFR: 0 ;FLAG TO SHOW TUT CHANGED +TTDFPS: 0 ;COUNT FROBS PER LINE WHEN PRINTING TUT +LFILES: 0 ;NUMBER OF FILES IN DIRECTORY +USRNAM: 0 ;M.F.D. USR NAME +UFDLOS: 0 ;SOME GARBAGE IN UFD +UFDSEE: 0 ; -1 IF A STRANGE UFD, PRINT WHOLE THING +FILEPK: 0 ; PACK FILE IS ON +LAST: 0 ; LAST FILE IN UFD +DBLK: 0 ;STORAGE FOR DIRECTORY NUMBER +FILEER: 0 ;ERROR IN FILE +BADFIL: 0 ; BLOCKS IN FILE WITH RETRIEVAL ERRORS +XWDSEE: 0 ; -1 IF HAVENT TYPED EXTRA WORDS YET +LASTQ: 0 ;STORAGE FOR Q +NOTUT: 0 ;TUT NOT ACTIVE FOR THIS FILE +LSTBLK: 0 ;LAST BLOCK STORAGE +BLK: 0 ; LAST BLOCK READ OR WRITTEN FROM +CKFIX: 0 ; -1 IF AUTO FIX RETRIEVAL POINTERS +UNIT: 0 ; UNIT " +FUNIT: 0 ; UNIT FILE IS ON, -1 IF PACK NOT MOUNTED +FERRS: 0 ;TRANSFER ERRORS +CERRS: 0 ;ERRORS CORRECTED BY ECC LOGIC +DUPRER: 0 ;DUP READ ERROR COUNT +DUPWER: 0 ;DUP WRITE ERROR COUNT +UFDTA: 0 +GARBF: 0 ;GARBAGE IN FREE AREA +EXGARB: 0 ;EXTRA GARBAGE IN UFD +MARKF: 0 ;MARKING PACK + +PDL: BLOCK 200 +QBTBLI: 440600,, +QBTBL: 360600,, + 300600,, + 220600,, + 140600,, + 60600,, + 600,, + +QTRAN: +DC,[ 0 ;RH IS PHYSICAL DRIVE + 1 ;4.9 BIT MEANS SECOND HALF + 2 ;(NO LONGER DOES ANYTHING, NOW THAT MEMOWRECKS HAVE BEEN + 3 ; FLUSHED, BUT KEEP AROUND IN CASE EVER NEEDED AGAIN.) + 4 + 5 + 6 + 7 +];DC +.ELSE REPEAT NDRIVE, .RPCNT ;OTHERWISE NOTHING SPECIAL + +IFN .-QTRAN-NUNITS,.ERR BARF AT QTRAN!! + +QTTBLI: REPEAT 36./TUTBYT+1, 440000+TUTBYT_6-TUTBYT_12.*.RPCNT,, +QTTBL=QTTBLI+1 + +TS, NQS: 0 ;SYSTEMS NUMBER OF DRIVES +TS, SQACT: 0 ;LOCATION OF QACT IN SYSTEM +TS, SALVRT: 0 ;DUMMY + + NBLKS-1 ;SNBLKS-1 +SNBLKS: NBLKS ;SYSTEM NBLKS (INIT'ED IN TS) +DRIVE: REPEAT NDRIVE,-1 ;-1 IF DRIVE ON LINE +QACT: REPEAT NUNITS,-1 ;-1 IF UNIT ACTIVE +QPKN: REPEAT NUNITS,-1 ;PACK NUMBER ACCORDING TO TUT +PKNUM: BLOCK NUNITS ;PACK NUMBER ACCORDING TO HARDWARE + +RPKID: 0 + +IRP A,,[OTUT,NTUT] +Q!A!O: REPEAT NUNITS,CONC A,\.RPCNT, +TERMIN + +PAT: +PATCH: BLOCK 100 + +LOC <.+1777>&776000 +CYLBUF: +OUSRD: BLOCK 2000 +NUSRD: BLOCK 2000 +FDBUF: BLOCK 2000 +MFD: BLOCK 2000 +MAGBUF: BLOCK 2000 +IRPS A,,OTUT NTUT +REPEAT NUNITS,CONC A,\.RPCNT,: BLOCK 2000*MXTUTB +TERMIN +D0==OTUT0 +D1==OTUT1 +TUT=NTUT0 +RH, CYLSIZ==200*NHEDS*NSECS +RP, CYLSIZ==NBLKSC*2000 +DC, CYLSIZ==NBLKSC*2004 +NTS, IFL .-CYLBUF-CYLSIZ,LOC CYLBUF+CYLSIZ +THEEND: +CONSTANTS +VARIABLES +IFN .-THEEND, .ERR CRUFT AFTER THEEND + +INFORM HIGHEST USED = ,\THEEND + +IFG THEEND-400000, .ERR TOO MOBY (MUST FIT IN 128K TO AVOID HOLE IF SOME MEM DOWN) +;This error check doesn't really matter for MC much, since memory has +;to be switched out in 128K increments, which means that the system +;can't work with any holes in the low 256K. + +IF2, NTS, KL, PAG=- + +TS, END DDT ;ALWAYS STARTED BY G +NTS,END ;DON'T CLOBBER I.T.S. START ADDR WHEN LOADED TOGETHER diff --git a/src/system/sysjob.117 b/src/system/sysjob.117 new file mode 100755 index 00000000..76e0b705 --- /dev/null +++ b/src/system/sysjob.117 @@ -0,0 +1,2796 @@ +; -*-MIDAS-*- + +SUBTTL DEMON JOB INTERFACE ROUTINES + ;GIVE STUFF TO DEMON JOB RUNNING IN USER MODE, WHICH THEN OUTPUTS + ;STUFF IN ITS OWN FORMAT TO THE DISK + ;COMMUNICATION IS VIA DMNBUF (BUFFER) AND POINTERS, + ;DEMON JOB FINDS IT BY LOOKING UP SYSTEM SYMS + + ;USAGE: + ;ROUTINES MUST BE CALLED WITH CLK OFF OR IN PROGRESS + ;FIRST CALL DMNP TO SET UP D AS "PDL POINTER" INTO DMNBF + ;DMNPSH ADR ;PUSH ADR INTO DMNBF (ASSEMBLES INTO A PUSH) + ;FIRST WORD PUSHED SHOULD HAVE ENTRY TYPE DESCRIPTOR IN HIGH SIX BITS + + ;ENTRY TYPE DESCRIPTORS: +DMNELI==10000 ;LOGIN (DMNPLI) +DMNELO==20000 ;LOGOUT (DMNPLO) + ;^ ADD MORE AS NEEDED, NEED NOT BE SYMBOLIC BUT PLEASE COMMENT THEM HERE FOR XREF + + ;DMNRS ;NORMALLIZE POINTER (DUE TO STANDARD LENGTH ENTRY IN TABLE) + ;ASSEMBLES INTO ONE STORAGE WORD + ;THEN CALL (PUSHJ) DMNRT WHICH STORES BACK D + ;ALL DMNPSH'S SHOULD BE ASSEMBLED BEFORE DMNRT; + ;ALL ROUTINES SHOULD BE BETWEEN THIS PAGE AND DMNBUF + +;DMNSZ (# ENTRIES IN DMNBF) DEFINED EARLY IN SYSTEM ENGLISH SO CAN BE CHANGED EASILY + +DMNFMT==2 ;ASCENDING FORMAT NUMBER, SHOULD BE INCREMENTED EACH TIME + ;A CHANGE IS MADE REQUIRING CHANGE IN CODING EITHER OF DEMON JOB + ;OR OF PROGRAMS READING ITS OUTPUT +;DMNFNT 1 -> 2 9/71 SWAPIN RQ INCLUDED W/LOGOUT + +DMNBAC==0 ;DMNPSH COUNTER, AFTER FIRST TIME GETS RE-INITIALIZED TO DMNBLM + +DEFINE DMNPSH ADR + DMNBAC==DMNBAC+1 + PUSH D,ADR +TERMIN + +IF1,DMNBEL==0 ;BECOMES LENGTH PER ENTRY IN DMNBF + +DEFINE DMNRS + ADDI D,DMNBEL-DMNBAC +IF1,IFG DMNBAC-DMNBEL,DMNBEL==DMNBAC +DMNBAC==DMNBLM +TERMIN + + ;PUSHJ P,DMNP ;SET UP D FOR DMNPSH'S INTO DMNBF + +DMNP: MOVE D,DMNBFP ;GET POINTER + CAIL D,DMNBFE-1 ;AT END OF BUFFER? + MOVEI D,DMNBF-1 ;YES, RE-INITIALIZE + AOS DMNBC ;INDICATE ENTRY ABOUT TO BE FILLED, SO DEMON KNOWS IF IT LOST +DMNP0: ;DMNP0 MAY BE CALLED IN USER MODE FROM DEMON JOB + DMNPSH TIME ;FIRST WORD IN BUFFER ALWAYS TIME OF ENTRY + ;^ MAYBE ADD MORE STANDARD PUSHES HERE + POPJ P, + +DMNBLM==DMNBAC ;NUMBER OF INITIAL WORDS PUSHED + + ;PUSHJ P,DMNRT (BUT USUALLY JRST DMNRT FOR RETURN) + ;DMNBF ENTRY COMPLETED, STORE BACK POINTERS + +DMNRT: TLZ D,-1 ;CLEAR OUT LEFT HALF OF POINTER + CAIL D,DMNBFE ;AFTER END OF BUFFER? + JRST 4,.+1 ;DMNBF POINTER INCREMENTED INCORRECTLY SOMEWHERE ALONG THE LINE + ;PROBABLY PROGRAMMER FORGOT TO DO DMNRS; CODING AFTER DMNBF MIGHT BE CLOBBERED + AOS DMNBD ;ENTRY COMPLETE, GIVE IT TO DEMON JOB + MOVEM D,DMNBFP + POPJ P, + + ;NOW FOR INDIVIDUAL ROUTINES + + ;LOGIN + +DMNPLI: PUSHJ P,DMNP ;SET UP + HRLI U,DMNELI ;INDICATE LOGIN + ;PUT FOLLOWING INTO DMNBF: + DMNPSH U ;INDEX OF USER BEING LOGGED IN + TLZ U,-1 + DMNPSH UNAME(U) ;UNAME + DMNPSH JNAME(U) ;JNAME + DMNPSH TRMNAM(U) ;TERMINAL NAME + DMNPSH XUNAME(U) + DMNRS ;THAT'S ALL + JRST DMNRT + + ;LOGOUT + +DMNPLO: PUSHJ P,DMNP ;SET UP D + PUSHJ P,LOGUSE ;GET TREE'S USAGE IN T AND TT + HRLI U,DMNELO ;INDICATE LOGOUT + ;PUT FOLLOWING IN DMNBF FOR DEMON JOB TO DUMP OUT ON DISK: + DMNPSH U ;INDEX OF USER BEING LOGGED OUT + TLZ U,-1 + DMNPSH UNAME(U) ;UNAME OF USER + DMNPSH JNAME(U) ;JNAME + DMNPSH TT ;TIME USED, IN 4.069 USEC UNITS + DMNPSH T ;# SWAPIN REQUESTS (THESE VALID SINCE LOGUSE ALREADY CALLED) + ;^ ADD MORE HERE + ADDM TT,LOUTIM ;COUNT UP TOTAL TIME USED BY ALL LOSERS + DMNRS + JRST DMNRT + +DMNPL0==CPOPJ ;DMNPL0 MAY BE CALLED FROM DEMON JOB IN USER MODE + ;IT IS NO LONGER POSSIBLE TO MAKE THIS WORK RIGHT, + ;SO WE JUST RETURN. PFTHMG DRAGON SHOULD BE FIXED. + +EBLK + ;DEMON VARIABLES, MUST FOLLOW CODING + ;USE CARE IN REDEFINING SYMBOLS ON THIS PAGE; DEMON JOB RUNNING IN USER MODE + ;LOOKS AT SOME OF THEM, EXCEPT AS INDICATED + +DMNBF: BLOCK DMNBEL*DMNSZ ;BUFFER +DMNBFE:: + +DMNBC: 0 ;ENTRY COUNT, INCREMENTED JUST BEFORE ENTRY ADDED TO DMNBF (USED BY DEMON) +DMNBD: 0 ;ENTRY COUNT, INCREMENTED JUST AFTER " " " +DMNBFP: DMNBF-1 ;POINTER INTO BUFFER, HAS ADR OF LAST WORD WRITTEN (NOT USED BY DEMON) +VSCLAU: 0 .SEE VSCLA1 ;LAST JOB TREE ACCOUNTING UPDATE DONE FOR + ;NO MORE CODING ALLOWED AFTER THIS POINT + +DEFINE DMNPSH A +INFORM DMNPSH AT .,\. +TERMIN + +DEFINE DMNRS +INFORM DMNRS AT .,\. +TERMIN + +BBLK + +SUBTTL "SYSTEM" JOBS + +IFN TPLP,[ +TPLI==11 ;PSEUDO LPT IN +PRTO==12 ;REAL LPT OUT +] +IFN DEMON,TPLI==11 ;FOR DEMON HACKER +IFN DEMON,TEMPC==16 ;FOR TESTING WHETHER DEMON FILE EXISTS. +STYOC==17 ;OUTPUT " + +;CODE FROM ICLR TO SCOR EXECUTED ONLY ONCE (SEE BEG) +ICLR: MOVE A,[GO,,GO+1] ;PICK UP BLT POINTER (COPY EXCH WORD INTO NEXT) + SETZM GO ;CLEAR FIRST WORD + BLT A,IEND ;CLEAR OUT INITIALIZING CODE (IN AREA TO BE USER VAR BLOCKS) + SKIPL CORRQ ;SKIP IF CORE RQ FOR SYSTEM'S SPACE PROCESSED + PUSHJ P,UFLS ;WAIT AS NECESSARY + PUSHJ P,SYSCOP ;"OPEN" SYSTEM CONSOLE CHANNEL +IFN CCLKP,[ + JRST .+3 ;JFCL FOR CHESS CLK MODE + PUSHJ P,CLQAD1 + CCLKB +];CCLKP +IFN IMPP,[ + MOVE A,TIME + MOVEM A,LNETIM + PUSHJ P,IMPINI +];IMPP + MOVEI A,IINTIC + MOVEM A,IINCNT +SCOR: MOVE P,SYSPDP + MOVE U,USER + CONO PI,CLKON + MOVE A,TIME + ADDI A,30.*60.*5 ;5 MINUTES BEFORE SHUTDOWN? + SKIPLE SHUTDN + CAMG A,SHUTDN + JRST .+3 + SKIPN SUSRS + JRST SYSOUT ;JUMP IF SYS DYING & NO ONE LOGGED IN + MOVE T,[.HANG] + MOVEM T,FORTY ;TELL PEEK WHAT OUR UFLS REALLY IS. + MOVE T,TIME + MOVEM T,SYSITM + SKIPN SUPCOR ;SKIP IF ANY BITS ON IN SUPCOR + PUSHJ P,UFLS ;HANG TILL A BIT ON +;SYS JOB IS HUNG IF SYSITM IS 30 SEC OLD AND PC ISN'T SCOR1. +SCOR1: MOVSI A,(SETZ) + MOVEI B,0 +SYSDP1: TDNE A,SUPCOR + JRST SYSDP2 +SYSDP3: LSH A,-1 + JUMPE A,SCOR + AOJA B,SYSDP1 + +SYSDP2: SKIPGE SYSDTB(B) ;SKIP UNLESS 4.9 BIT OF ENTRY ON + ANDCAM A,SUPCOR ;4.9 ON, CLEAR SUPCOR BIT + LDB C,[370200,,SYSDTB(B)] + TRNE C,2 ;IF ROUTINE IS GOING TO USE TTY, + PUSHJ P,WARMTTY ;THEN WARM IT UP FOR IT + TRNE C,1 + PUSHJ P,DINGTTY + LDB T,[420100,,SYSDTB(B)] ;GET 4.8 BIT + JUMPE T,@SYSDTB(B) ;IF 4.8 BIT = 0, JUMP TO ROUTINE + PUSH P,A ;4.8 .NE. 0, SAVE A + PUSH P,B ;SAVE B + PUSHJ P,@SYSDTB(B) ;CALL ROUTINE + POP P,B ;RESTORE B + POP P,A ;RESTORE A + LDB T,[410100,,SYSDTB(B)] ;GET 4.7 BIT + JUMPE T,SYSDP3 ;IF ZERO RETURN TO LOOP + ANDCAM A,SUPCOR ;NON-ZERO, CLEAR SUPCOR BIT + JRST SYSDP3 ;LOOP + +SUBTTL SUPCOR DISPATCH TABLE + +;DISPATCH TABLE FOR BITS IN SUPCOR +;4.9 = 1 TO CLEAR SUPCOR BIT BEFORE DISPATCHING +;4.8 = 0, JRST TO ROUTINE ; = 1, PUSHJ +;4.7 = 1 TO CLEAR SUPCOR BIT AFTER (ONLY USEFUL IF PUSHJ) +;4.6 WARM UP TELETYPE BEFORE CALL +;4.5 DING BEFORE CALL + +SCL==1,,525252 ;BIT TYPEOUT MASK FOR SUPCOR +SCR==525252 ; .. + +SYSDTB: +SCLEX==400000 ? 300000,,SYSEX ;INCREASE USER-VAR BLOCK SPACE. +SCLSHD==200000 ? 340000,,SYSSHD ;HANDLE .SHUTDN - PRINT "GOING DOWN" MESSAGES. +SCLOUT==100000 ? 400000,,SYSOUT ;TIME FOR SYSTEM TO GO DOWN. +IFE KS10P,[ 660000,,SYSCK5 ;CHECK FOR DEVICES GIVING SPURIOUS INTERRUPTS. + SCLCK5==040000] +IFN KS10P, 400000,,SYSDP3 +SCLDAT==020000 ? 600000,,DATIME ;CONTINUE TRYING TO DETERMINE DATE AND TIME. +SCLPAR==010000 ? 360000,,PARTYP ;PRINT "PARITY ERROR..." +SCLSET==004000 ? 340000,,SYSSET ;DEPOSIT IN SYSTEM (.SETLOC). +SCLIMP==002000 ? 600000,,SYSIMU ;PRINT "NETWORK UP ..." +SCLWRT==001000 ? 340000,,SYSWRT ;PRINT WRITING-ON-SYS: MESSAGE. +SCLLGI==000400 ? 340000,,SYSLGI ;PRINT LOGIN MESSAGE. +SCLDEC==000200 ? 300000,,SYSDEC ;DECREASE USER-VAR SPACE. +SCLVSK==000100 ? 600000,,VSCLK ;VERY SLOW (2 MINUTE) CLOCK. +SCLGUN==000040 ? 600000,,SYSGUN ;FLUSH TREES THAT ARE TRYING TO LOG OUT. +SCLNET==000020 ? 460000,,SYSNET ;BRING NCP DOWN AND UP. +IFN DEMON,[ 600000,,DEMCHK ;RUN ANY DEMONS WHICH NEED IT. + SCLDMN==000010] +IFE DEMON, 400000,,SYSDP3 +SCLNXM==000004 ? 360000,,NXMTYP ;PRINT "NON-EX MEM ERROR ..." +IFE KA10P,[ +SCLBPF==000002 ? 360000,,BPFTYP ;BAD PAGE FAIL +].ELSE 400000,,SYSDP3 +SCLIDK==000001 ? 600000,,ISYS ;DISK IS INITIALIZED +SCRTPP==400000 ? 600000,,TPLPRT ;TRANSFER DATA TO LPT (FROM TPL) +SCRTPC==200000 ? 600000,,VSCL6 ;SEE IF ANY FILES HAVE BEEN SPOOLED. + 400000,,SYSDP3 +SCRHNG==040000 ? 600000,,SYSDIL ;DIALUP LINE CONNECT OR DISCONNECT +SCRDET==020000 ? 600000,,SYSDT ;DETACH TOP-LEVEL JOBS WITH INTERRUPTS. +SCRCFM==010000 ? 600000,,SYSCFM ;PRINT CONSOLE FREE MSGS +SCRMSG==004000 ? 640000,,SYSMPR ;PRINT RANDOM SYSTEM MESSAG + REPEAT 5,400000,,SYSDP3 ;CAN BE SET BY USER (.SUPSET) +IFN N11TYS,[ 600000,,VWHO ;UPDATE WHO LINES (40) + SCRWHO==000040] +.ELSE 400000,,SYSDP3 +IFN N11TYS,[ 640000,,SYS11D ;TV 11 GONE DOWN (20) + SCR11D==000020] +.ELSE 400000,,SYSDP3 +IFN N11TYS,[ 640000,,SYS11U ;TV 11 COME UP, INIT IT (10) + SCR11U==000010] +.ELSE 400000,,SYSDP3 +IFE DEMON, 400000,,SYSDP3 ;(4) +IFN DEMON,[ 600000,,DMNOFF + SCRDMF==000004] +SCRTPF==000002 ? 300000,,TPLOFF ;BLOCK TPL. +SCRCKS==000001 ? 600000,,SYSCKS ;PERFORM CHECKSUMMING + +IFN .-SYSDTB-36.,.ERR SYS JOB DISPATCH + +SUBTTL DM DAEMON OVERSEER + +IFN DEMON,[ +DEMCHK: PUSHJ P,SYSDEX ;HANDLE REQUESTS TO KNOW WHETHER A FILE + ;EXISTS TO BE SIGNALLED AS A DEMON. + PUSHJ P,LSWTL ;SYSTEM JOB SIEZES DEMON TABLE SWITCH WITH UTCOFF + 400000,,DEMSW + MOVE B,DMLSEX + CAMN B,[-DMLNG,,0] ;IF AT BEGINNING OF TABLE SET FLAG + TDZA D,D + SETOM D +DMSCN9: SKIPE TT,DMTTBL(B) + SKIPE DMTTBL+1(B) ;ONLY PAY ATTENTION IF NOT DOWN + JRST DMSCN1 ;AND GUY THERE + MOVE T,DMTTBL+2(B) + HRRE C,T + TLNE T,-1 + JRST DMSCN3 + JUMPLE C,DMSC10 +DMSCN0: SKIPG DMNFLG + JRST DMSC11 ;IF FLAG SET CAN'T LOAD EM + CAME TT,[SIXBIT /UNSPOO/] + JRST DMSCN4 ;DON'T BOTHER WITH TPL STUFF, IF NOT TPL + SKIPGE TPLFLG + JRST DMSC10 ;REMOVE FROM WORLD + JRST DMSCN4 + +DMSCN4: HLRM T,DMTTBL+3(B) ;SET UP IMPLICIT REQUEST + CONO PI,UTCON ;ATTEMPT LOAD HERE + MOVE T,DMTTBL(B) + MOVEM T,DMOBLK+2 ;CHECK TO SEE IF FILE EXITS + .IOPUSH TPLI, + .OPEN TPLI,DMOBLK ;DON'T WORRY CAN'T PCLSR + JRST DMSCN5 ;OPEN FAILURE + .IOPOP TPLI, ;GET BACK STUFF + HRROI T,DMTTBL(B) + PUSHJ P,NUJBST ;TRY TO LOAD + JRST DMSCN6 ;COME BACK LATER, NO ENTRY FOR THIS GUY. +DMSCN8: ADD B,[DMTLL,,DMTLL] + SKIPL B + MOVSI B,-DMLNG + MOVEM B,DMLSEX ;FIX UP TABLE +DMSCN7: MOVSI B,SCLDMN + IORM B,SUPCOP ;IF MORE REQUESTS, RUN AGAIN IN 1 SECOND. + SOSLE REQCNT ;NO MORE REQUESTS => + JRST LSWPOP + SETZM REQCNT + ANDCAM B,SUPCOP ;DON'T RUN AGAIN. + ANDCAM B,SUPCOR ;THEN CLEAR OUT SUPCOR BIT + JRST LSWPOP + + +DMSCN5: .IOPOP TPLI, ;FILE DOESN'T EXIST + CONO PI,UTCOFF +DMSC10: PUSHJ P,DEMMRV ;REMOVE DEAMON + JRST DMSCN8 ;AND REQUEST + +DMSCN3: JUMPG C,DMSCN0 ;LOAD + JRST DMSCN1 + +DMSCN2: CONO PI,UTCON ;CONTINUE AROUND LOOP + ADD B,[DMTLL,,DMTLL] +DMSCN6: MOVEM B,DMLSEX + JRST LSWPOP ;COME BACK LATTER WITHOUT FLUSHING REQ + +DMSCN1: ADD B,[DMTLL,,DMTLL] ;ADD ON VAL + JUMPL B,DMSCN9 ;CONTINUE AROUND LOOP + MOVSI B,-DMLNG + MOVEM B,DMLSEX + JUMPE D,UTOLKJ +DMSC11: SETZM REQCNT ;IF RAN THROUGH WHOLE TABLE WITHOUT ANY PROCESS + CONO PI,UTCON + JRST DMSCN7 ;FLUSH ALL REQUESTS AND RETURN + +DMNOFF: MOVNS TT,DMNFLG + JUMPLE TT,DMNOF1 ;DEAMONS OFF + PUSHJ P,LSWTL + DEMSW +DMNOF3: SKIPE DMTTBL(B) + SKIPE DMTTBL+1(B) + JRST DMNOF2 + AOS REQCNT +DMNOF2: ADD B,[DMTLL,,DMTLL] + JUMPL B,DMNOF3 + MOVSI B,SCLDMN + IORM B,SUPCOR + JRST LSWPOP + +DMNOF1: MOVSI B,SCLDMN + ANDCAM B,SUPCOR + SETZM REQCNT ;ZERO COUNT + POPJ P, + +;CALL HERE TO HANDLE ALL JOBS THAT ARE WAITING IN .DEMSIG TO +;BE TOLD WHETHER A PURPORTED DEMON REALLY EXISTS. GIVE THEM +;THEIR ANSWERS AND START THEM UP AGAIN. +SYSDEX: SETZ A, + MOVEI C,'SYS + MOVE D,['ATSIGN] +SYSDE1: CONO PI,CLKOFF + SKIPN SRN3(A) ;THIS JOB'S ALREADY BEEN SERVICED?^ + SKIPN UNAME(A) ;OR DOESN'T REALLY EXIST? + JRST SYSDE3 + MOVE B,UPC(A) ;IS IT WAITING FOR SERVICE FROM US? + XORI B,ADEMS1 ;MUST BE IN EXEC MODE AT THE RIGHT PLACE. + TDNE B,[%PCUSR,,-1] + JRST SYSDE3 + MOVE E,AC0S+A(A) ;GET THE FN2 IT WANTS TO CHECK. + CONO PI,CLKON + SETZ T, ;T GETS 0 IFF FILE CAN BE OPENED. + .OPEN TEMPC,C + CAIA + JRST SYSDE2 + LDB T,[220600,,IOCHST+TEMPC] + SKIPN T + MOVEI T,%ENSFL +SYSDE2: .CLOSE TEMPC, + CONO PI,CLKOFF + SKIPN UNAME(A) ;SEE IF JOB IS STILL WAITING FOR SERVICE + JRST SYSDE3 ;SO IT ISN'T CLOBBERED IF IT GOT AN + MOVE B,UPC(A) ;INTERRUPT AND IS DOING SOMETHING ELSE. + XORI B,ADEMS1 + TDNN B,[%PCUSR,,-1] + CAME E,AC0S+A(A) + JRST SYSDE3 + MOVEM T,AC0S+T(A) ;GIVE THE JOB ITS ANSWER IN T, AND + SETOM SRN3(A) ;TELL THE JOB IT HAS BEEN SERVED. +SYSDE3: CONO PI,CLKON + ADDI A,LUBLK + CAMGE A,USRHI + JRST SYSDE1 + POPJ P, +];DEMON + +SUBTTL VERY SLOW CLOCK + +;SUBROUTINES CALLED BY THE VERY SLOW CLOCK. + +;CHECK FOR DEMON REQUESTS WHOSE TIME HAS COME. +IFN DEMON,[ +VSCLDM: PUSHJ P,LSWTL + DEMSW + MOVSI B,-DMLNG +VSCLD2: SKIPG DMTTBL+3(B) ;IF SPECIFIC ENTRY IS < = O, IGNORE + JRST VSCLD1 + SOSE DMTTBL+3(B) + JRST VSCLD1 + HLRZ T,DMTTBL+2(B) ;SIGNAL DEAMON + MOVEM T,DMTTBL+3(B) + MOVE A,DMTTBL(B) + PUSHJ P,DEMSIG ;SIGNAL REQUEST FOR THIS GUY + BUG ;ENTRY IN TABLE NOT FOUND EVEN THOUGH NON ZERO TIME +VSCLD1: ADD B,[DMTLL,,DMTLL] + JUMPL B,VSCLD2 + JRST LSWPOP +] + +;CHECK FOR CLOBBERED TEN-11 INTERFACE CONTROL PAGE WORDS, +;AND RESET THEM TO THEIR CORRECT SETTINGS. +IFN TEN11P,[ +T11CK: SKIPE TEN11F + POPJ P, + MOVSI I,-256. +T11CKL: MOVE A,T11MP(I) + CAMN A,[-1] + MOVEI A,0 ;HARDWARE SHOULD BE 0 ON CONFLICT PAGE + TLZ A,174000 ;USAGE COUNT + MOVE B,400000+T11CP*2000(I) + CAME A,B + JRST T11ERR +T11CL1: AOBJN I,T11CKL + POPJ P, + +T11ERR: AOS T11ERC + MOVEM A,400000+T11CP*2000(I) + MOVEM A,T11CCN + MOVEM B,T11WCN + MOVEM I,T11PG + JRST T11CL1 +] + +;VERY SLOW CLOCK (EVERY 2 MIN). SIGNALLED BY SCLVSK, SET BY A CLOCK-QUEUE ENTRY. +;CALLS THE ULTRA-SLOW CLOCK (EVERY 2 HOURS) WHEN IT'S TIME. + +VSCLK:;JSP E,CHECK ;CHECK FOR CLOBBERED DEVICES (WOULD BE NICE, BUT BUGS...) +IFN DEMON,PUSHJ P,VSCLDM ;DEAMON SLOW CLOCK BREAK ROUTINE +IFN TEN11P,PUSHJ P,T11CK + MOVE U,VSCLAU ;ACCOUNTING UPDATE, FIND A JOB TREE +VSCLA1: ADDI U,LUBLK + CAML U,USRHI + MOVEI U,0 + SKIPE UNAME(U) + SKIPL SUPPRO(U) + JRST VSCLA1 + HRLO TT,UNAME(U) + AOJE TT,VSCLA1 ;DON'T IF NOT LOGGED IN YET + MOVEM U,VSCLAU + CONO PI,CLKOFF + PUSHJ P,LOGUPD + PUSHJ P,DMNPLI + CONO PI,CLKON + MOVE U,USER + SKIPLE CTLCNT ;Time to print date on console log? + JRST VSCLA2 ; No. + PUSHJ P,GLPDTM ;Yes - get localized pdtime. + JRST VSCLA2 ; Can't print time if we don't know it. + PUSHJ P,WARMTTY ;Warm up tty, newline. + PUSHJ P,DATIM6 ;Print what time it is now. + MOVEI TT,CTLMAX ;Restart countdown of lines printed. + MOVEM TT,CTLCNT +VSCLA2: PUSHJ P,VSCOLD ;CHECK FOR OLD DETACHED TREES TO BE KILLED + PUSHJ P,TTTMNT ;TURN OFF MOTORS OF IDLE TERMINETS. +VSCL7: SETOM UFDFLF ;CAUSE CORE JOB TO TRY TO FLUSH 2311 UFDS + AOS NCORRQ + MOVSI I,-NCLCH ;LOOK FOR UNOPEND CORE LINK BUFFERS THAT HAVE BEEN + PUSHJ P,SWTL ;AROUND FOR MORE THAN 2 MINUTES + CLOSW +VSCLCL: SKIPE CLSYN(I) ;SKIP IF VARS UNUSED + SKIPL A,CLUSR(I) + JRST VSCLC2 + AOJN A,VSCLC2 ;JUMP IF OPEN + MOVE TT,CLRAC(I) + TLOE TT,200000 + JRST VSCLCR ;BIT ALREADY ON, BUFFER OLD + MOVEM TT,CLRAC(I) +VSCLC2: AOBJN I,VSCLCL ;LOOP FOR ALL SETS OF VARIABLES + PUSHJ P,LSWPOP ;RELEASE SWITCH + + MOVE A,UTTBF ;IF MANY 200-WORD BUFFERS ARE FREE, + CAIGE A,8 + JRST .+3 + SETOM UTBFLF ;HAVE THE CORE JOB FLUSH THEM + AOS NCORRQ + +IFN IMPP,[ + SKIPGE IMPUP ;SKIP IF IMP UP, OR PERMANENTLY DOWN + PUSHJ P,SYSIMU ;TRY TO BRING IT UP +];IMPP +IFN TPLP,PUSHJ P,VSCL6 ;MAYBE START PRINTING FROM .LPTR. +IFN NLPTP,[ + SKIPL NLUSR ;IF LPT ISN'T IN USE, + JRST VSCNL1 + AOS TT,NLFREE ;KEEP TRACK OF HOW LONG THAT'S BEEN SO. + SOJN TT,VSCNL1 ;IF TRUE FOR >=2 VSCLK INTREVALS (4 MIN) + CONO NLPT,1000 ;TURN LPT MOTOR OFF: 1ST PUT LPT IN IMAGE MODE + DATAO NLPT,[.BYTE 7 ? 24 ? 177 ? 177 ? 177 ? 177] ;THEN TURN OFF. +VSCNL1:] + SOSLE IINCNT + POPJ P, + +;IT'S TIME FOR THE ULTRA-SLOW CLOCK + MOVEI A,IINTIC ;GET HERE EVERY TWO HOURS OR SO + MOVEM A,IINCNT + PUSHJ P,GLPDTM + POPJ P, ;TIME NOT KNOWN + PUSHJ P,WARMTTY + JRST DATIM6 ;TIME KNOWN, TELL SYSTEM CONSOLE + +VSCLCR: HRRZ A,TT + PUSHJ P,BRTN ;RETURN BUFFER + SETZM CLSYN(I) ;FREE VARIABLES + JRST VSCLC2 + +;CHECK FOR TREES WITH BUMRTL SET THAT HAVE NOT RUN FOR +;A WHOLE HOUR, AND GUN THEM. +VSCOLD: SETZB U,J + CONO PI,CLKOFF + MOVSI B,BUMRTL + MOVSI C,BULGOS + MOVE A,TIME + SUBI A,60.*60.*30. ;1 HOUR AGO +VSCOL0: SKIPE UNAME(J) + TDNN B,APRC(J) + JRST VSCOL1 ;JOB NON EX OR DOSN'T HAVE BUMRTL + SKIPGE SUPPRO(J) ;NO GOOD IF NOT TOP LEVEL. + TDNE C,APRC(J) ;IGNORE JOBS THAT ARE ALREADY LOGGING OUT. + JRST VSCOL1 + CAML A,LUBTM(J) ;NOT RUNNING AND HASN'T RUN FOR 1 HOUR => GUN. + JRST VSCOL2 +VSCOL1: ADDI J,LUBLK ;KEEP LOOKING TILL FIND JOB THAT NEEDS GUNING. + CAMGE J,USRHI + JRST VSCOL0 + JRST CLKONJ ;NO TREES NEED TO BE GUNNED. + +VSCOL2: MOVEI I,[ASCIZ /KILLED HOUR-OLD DETACHED JOB, # /] + PUSHJ P,SYSJEX ;PRINT MESSAGE AFTER CALLING ALOGO6 + PUSHJ P,ALOGO6 + JRST VSCOLD ;LOOK FOR ANOTHER TREE TO GUN. + +; MOVEI I,[ASCIZ/DID FOO TO JOB # /] +; PUSHJ P,SYSJEX +; PUSHJ P,FOO +;DOES FOO TO THE JOB WITH IDX IN J, AND PRINTS A SYSTEM MSG. +;FOO WILL FIND THE USR IDX IN A AND J. IT IS OK TO ENTER +;SYSJEX WITH CLOCK OFF BUT FOO MUST TURN IT ON. +SYSJEX: HRRZS A,J + PUSH P,JNAME(A) + PUSH P,UNAME(A) + PUSH P,A ;SAVE ALL THE INFO WE NEED FOR THE MESSAGE. + PUSH P,I + XCT @-4(P) ;DO "FOO" + JFCL ;LET FOO SKIP. + AOS -4(P) ;SKIP OVER THE PUSHJ TO FOO. + PUSHJ P,WARMTTY + HRRZ I,(P) + PUSHJ P,SYSSP ;PRINT THE STRING IN I + POP P,I + HLRZS I + SKIPE I + PUSHJ P,(I) ;IF LH(I) WAS NONZERO, CALL THAT PRINT ROUTINE + POP P,A + IDIVI A,LUBLK + PUSHJ P,SYSOPT ;PRINT THE JOB # + MOVEI I,[ASCIZ /, USR:/] + PUSHJ P,SYSSP + POP P,A + PUSHJ P,SYSIXP ;PRINT UNAME, AND SPACE + PUSHJ P,STYOS + POP P,A + PUSHJ P,SYSIXP ;PRINT JNAME + JRST SYSTCR ;SPACE, TIME AND CR. + +SUBTTL TPL + +VSCL6: ;CHECK TPL: SEE IF LPT FREE AND ANY FILE TO PRINT. +IFN UNSPLP,[ + PUSHJ P,LSWTL + DEMSW + MOVE A,[SIXBIT /UNSPOO/] + PUSHJ P,DEMSIG + JRST LSWPOP ;REQUEST FAILED, TOO BAD + JRST LSWPOP +] + +IFE TPLP,POPJ P, +IFN TPLP,[ + MOVEI A,SCRTPP ;ALSO ENTER HERE FOR TPL CHECK + TDNE A,SUPCOR ;SKIP IF NOT ALREADY PRINTING FILE + POPJ P, + IFG LPTP-1,[ + SKIPE TPLSWP + JRST VSCL6A + SKIPLE NLPTBR + SKIPL LPTUSR + POPJ P, +VSCL6B: + ] + IFLE LPTP-1,[ + SKIPL LPTUSR + POPJ P, + ] + IFG OLPTP-NLPTP,[ + MOVEI A,132. + CAMLE A,LPTCC + POPJ P, + ] + IFG NLPTP-OLPTP,[ + CONSO NLPT,207 + SKIPG NLPTBR + POPJ P, ;.OPEN OF LPT WOULD HANG + ] + MOVEI A,SCRTPF + TDNE A,SUPCOR ;BLOCKED + POPJ P, + .OPEN TPLI,[SIXBIT / TPL.FILE.(DIR)/] ;MAKE SURE FILE DIR IN CORE + JRST VSCLX1 + MOVEI B,2 +VSCL2: .IOT TPLI,A + CAIE A,^C + CAIN A,12 + SOJG B,VSCL2 + JUMPN B,VSCL2 + SETOB I,C + SETZM TPLFN1 + SETZM TPLFN2 + MOVEI B,TPLFN1 + HRLI B,440600 +VSCL2A: .IOT TPLI,A + CAIN A,"* + JUMPL I,VSCL4 + CAIE A,^C + CAIN A,14 + JRST VSCLX1 + CAIN A,40 + JUMPL I,VSCL2A ;IGNORE SPACES BEFORE THE PACK NUMBER. + CAIN I,3 ;AFTER 4 CHARS STARTING WITH BEGINNING OF PACK NUMBER + JRST VSCL2E ;COMES THE START OF THE FN1. + CAIN A,"L + MOVEI C,0 ;INDICATE LINK + AOJA I,VSCL2A ;FIRST NON SPACE CRUFTY + +IFG LPTP-1,[ +VSCL6A: MOVEI A,132. + CAMG A,LPTCC + SKIPL OLPUSR + POPJ P, + JRST VSCL6B +] + +VSCL2E: MOVEI TT,6 +VSCL2B: SUBI A,40 + IDPB A,B + .IOT TPLI,A + SOJG TT,VSCL2B + MOVE B,[440600,,TPLFN2] +VSCL2C: .IOT TPLI,A + SUBI A,40 + IDPB A,B + TLNE B,770000 + JRST VSCL2C + .IOPUSH TPLI, + .OPEN TPLI,TPLFN + JRST VSCLL1 ;TRY AGAIN + .IOPOP PRTO, + .CLOSE PRTO, +IFN NLPTP,[ +IFN OLPTP,[ + SKIPE TPLSWP + JRST VSCL3A +] + CONSZ NLPT,207 + JRST VSCLX1 + MOVEI T,LPTBSZ + CAMN T,NLPTBR ;SKIP ON OPEN WOULD HANG + .OPEN PRTO,[3,,(SIXBIT /LPT/)] + JRST VSCLX1 +IFN OLPTP,[ + JRST VSCL3B +VSCL3A: +]] +IFN OLPTP,[ + MOVEI A,132. + CAMG A,LPTCC ;SKIP IF .OPEN WOULD HANG +IFN NLPTP,.OPEN PRTO,[3,,'OLP] +.ELSE .OPEN PRTO,[3,,(SIXBIT /LPT/)] + JRST VSCLX1 +VSCL3B: +] + MOVEI A,SCRTPP + IORM A,SUPCOR ;PRINT THIS FILE + IORM A,SUPCOP ;PRINT MORE EVERY SECOND. + JRST TPLPRT + +VSCLL1: .IOPOP TPLI, + JUMPL C,VSCLX1 + MOVEI B,1 ;LINK THAT DIDN'T EXIST + JRST VSCL2 +] + +IFN TPLP,[ +;COME HERE TO TRANSFER SOME CHARS FROM DSK TO LPT, +;ASSUMING BOTH CHNLS ALREADY OPEN. +TPLPRT: +IFN NLPTP,[ +IFN OLPTP,[ + SKIPE TPLSWP + JRST TPLPR3 +] + MOVEI A,TPLBSZ + CAMLE A,NLPTBR + POPJ P, +IFN OLPTP,[ + JRST TPLPR5 +TPLPR3: +]] +IFN OLPTP,[ + MOVEI A,10.*TPLBSZ ;LEAVE SPACE FOR CHARS THAT TAKE MORE THAN 1 CHAR + CAMLE A,LPTCC + POPJ P, +TPLPR5: +] + MOVE A,[-TPLBSZ,,TPLBUF] ;"UN-RELOCATE" + .IOT TPLI,A + MOVE B,A + MOVNI A,-TPLBUF(A) + HRLZS A + JUMPE A,TPLPR1 ;JUMP ON END OF FILE + HRRI A,TPLBUF + .IOT PRTO,A + JUMPL B,TPLPR1 ;LAST BUFFER-FULL PRINTED + JRST TPLPRT + +TPLPR4: CLEARM TPLFN3 + .FDELE TPLFN ;DELETE FILE JUST PRINTED + JFCL + MOVEI A,SCRTPP + ANDCAM A,SUPCOP ;DON'T NEED TO CALL TPLPRT EVERY SECOND. + ANDCAM A,SUPCOR +VSCLX1: .CLOSE PRTO, + .CLOSE TPLI, + POPJ P, + +VSCL4: .IOT TPLI,A + CAIN A,14 + JRST VSCLX1 + CAIN A,12 + JRST VSCL2A + JRST VSCL4 + +TPLPR1: PUSHJ P,TPLPR4 + JRST VSCL6 +] +.ELSE TPLPRT==CPOPJ + +;HANDLE A USER'S REQUEST TO "BLOCK THE TPL" +IFN TPLP,[ +;IF SYS JOB IS SPOOLING, JUST THROW AWAY CURRENT FILE. +TPLOFF: MOVEI A,SCRTPP + TDZN A,SUPCOP + POPJ P, ;NOTHING HAPPENING + PUSHJ P,WARMTTY + .RESET PRTO, + PUSHJ P,TPLPR4 + MOVE A,[SIXBIT /TPLOFF/] + PUSHJ P,SYSIXP + JRST SYSTCR +] + +IFE TPLP+UNSPLP,TPLOFF==CPOPJ + +IFN UNSPLP,[ +TPLOFF: MOVNS B,TPLFLG + JUMPG B,VSCL6 ;IF NOW RUNNING GIVE REQ + MOVSI B,-DMLNG +TPLOF1: SKIPE C,DMTTBL(B) + SKIPG D,DMTTBL+1(B) ;USER INDEX -0 IF NOT YET LOADED + JRST TPLOF2 + CAME C,[SIXBIT /UNSPOO/] + JRST TPLOF2 + PUSH P,U + MOVE U,D + PUSHJ P,ALOGOUT ;DOES ONE USTOP FOR YOU + POP P,U + JRST TPLOF3 + +TPLOF2: ADD B,[DMTLL,,DMTLL] + JUMPL B,TPLOF1 +TPLOF3: PUSHJ P,WARMTTY + MOVE A,[SIXBIT /TPLOFF/ ] + PUSHJ P,SYSIXP + JRST SYSTCR +] + +SUBTTL WHO LINES + +IFN N11TYS,[ +;PDP11 COMM AREA (SYSTEM WIDE) +;STARTS AT PDP11 ADDRESS 40 +;PNTR TO TT11HD +;PNTR TO POINTA +;I/O VERSION # +;SORCE FILE VERSION # +;--PDP10 WD BOARDARY-- 0 , INITED +; 0 , GODOWN + +;AT POINTA: +; ADDR OF SYSTEM WHO-LINE VARS +; ADDR OF 10-11 COMMAND BUFFER +; TENWHO , 0 ;PDP10 SETS TO TELL PDP11 TO UPDATE WHO-LINES +; MAXTV , 0 ;MAXTV = # TV'S 11 IS SET UP TO HANDLE +; NF11TY , 0 ;10 TELLS 11 WHAT TTY # OF 1ST BUFFER IS. + +;PDP11 CONSOLE VARS +; EVEN PDP11 WORD ODD PDP11 WORD +;TT11HD - CHAIN OF ACTIVE INPUT BUFFERS 0 +; PNTR TO OUTPUT BUFFER CHNL 0 VIDEO BUFFER,KBD # (377 IF NONE) +; " CHNL 1 " +;... +; OUTPUT BFR EMPTY NOTIFY RQ FLAG TO FREE CHNL +;... +; PNTR TO WHO LINE BLOCK FREE + +;THE 11 HAS COME UP, SO INIT COMMUNICATION VARIABLES AND START USING IT +SYS11U: SKIPG TT11P + POPJ P, + LDB A,[$11AD0,,TT11HA] ;GET PDP10 ADDRESS OF INPUT-BFR-CHAIN PTR + CAIL A,NTTPG*2000 + BUG HALT,[GARBAGE POINTER IN TV-11 MEMORY] + ADDI A,TT11LO + CONO PI,TTYOFF + MOVEM A,TT11HD ;SAVE IT FOR CLOCK LVL TO CHECK. + LDB C,[$11WD0,,TT11HA+1] ;GET PDP11 IO VERSION #. + MOVEI B,12. ;OLD TV PROGRAMS HANDLE 12. BUFFERS + LDB T,[$11AD1,,TT11HA] ;GET ADDR OF POINTA + CAIL C,3 ;VERSION 3 AND UP TV PGM HAS MAXTV - READ IT + LDB B,[$11WD0,,TT11LO+2(T)] + MOVEM B,TT1111 ;THAT'S HOW MANY TV'S THE 11 THINKS TERE ARE + CAIL B,N11TYS + MOVEI B,N11TYS ;MIN OF THAT AND # TEN THINKS THERE ARE + MOVEM B,TT11RL + MOVEI B,NF11TY + CAIL C,3 ;VERSION 3 TV PGM AND UP WANTS NF11TY + DPB B,[$11WD0,,TT11LO+3(T)] + HRLZ I,TT11RL ;GET AOBJN -> TV'S BOTH 10 AND 11 WILL HANDLE. + MOVNS I +VSCL7C: LDB B,[$11AD0,,1(A)] ;GET DPY BUFFER ADRESS FOR THIS TTY + ADDI B,TT11LO+2 ;CONVERT TO PDP10 ADDRESS. + HRLI B,040000+TT11BY_6 ;GET BP TO ILDB 1ST DATA WORD. + MOVEM B,NF11TY+TOBBP(I) ;PNTR TO BEG OF OUTPUT BUFFER + LDB C,[$11AD0,,(B)] ;GET # BYTES IN DATA AREA + ADDI B,(C) ;GET BP TO LAST WORD IN AREA + MOVEM B,NF11TY+TOBEP(I) + MOVEM B,NF11TY+TOIP(I) + ADDI A,1 + AOBJN I,VSCL7C + MOVEM C,TT11OL ;REMEMBER LENGTH OF OUTPUT BUFFERS. + SETOM TT11P ;TV TTYS NOW UP. + CONO PI,TTYON + MOVE A,[-N11TYS,,NF11TY] + MOVSI B,%TACFM ;NOW SAY ALL PDP11 TTYS NEED + ANDCAM B,TTYSTA(A) ;CONSOLE FREE MESSAGES, + AOBJN A,.-1 + MOVEI A,SCRCFM + IORM A,SUPCOR ;TELL SYS JOB TO PRINT THEM. + PUSHJ P,CLQAD1 ;ADD WHO LINE BLOCK TO CLOCK QUEUE IF NOT THERE + WHOCLB + MOVEI I,[ASCIZ /TV 11 IS UP -/] + JRST SYSSTD ;STRING,SPACE TIME AND DATE THEN CR +] + +IFN N11TYS,[ + +$INSRT WHOVAR + +;UPDATE WHO-LINE VARIABLES. +VWHO: SKIPL TT11P ;DON'T SCREW UP IF PDP11 ISN'T UP. + POPJ P, + MOVE A,TT11HD + HRLZ A,TT11RL + MOVNS A + HRR A,TT11HD ;-<# TV'S BEING USED>,,
+ ADD A,TT1111 + ADD A,TT1111 ;NOW RH -> 2 11-WDS BEFORE PTR TO WHOLINE VARS OF 1ST TV +VWHO1: LDB B,[$11AD0,,1(A)] ;GET WHO LINE VAR PDP11-ADDR, SHIFTED 2. + ADDI B,TT11LO ;CONVERT TO PDP10 ADDRESS. + CONO PI,TTYOFF + MOVE TT,WHJOB(B) ;JOB # (SHIFTED 4+16.) + MOVE C,WHMODE(B) ;MODE (SHIFTED 4+16.) + JUMPG C,VWHO3 + CONO PI,TTYON + JUMPL C,VWHO2 ;MODE < 0 => NO WHOLINE. + HLRE I,A ;GET -<# TIMES REMAINING THRU LOOP> + ADD I,TT11RL + HRRZ TT,TTYSTS+NF11TY(I) ;MODE 0, USE JOB WHICH HAS THE TTY. + MOVE Q,TT + IDIVI Q,LUBLK + LSH Q,4.+16. + MOVEM Q,WHJOB(B) +;FOR OTHER MODES, COME BACK HERE, WITH USER IDX IN TT. +VWHO3R: CONO PI,CLKOFF + MOVE C,UNAME(TT) + HLLZM C,WHUNAM(B) + HRLZM C,WHUNM2(B) ;STORE THE JOB'S UNAME + MOVE C,JNAME(TT) + HLLZM C,WHJNAM(B) + HRLZM C,WHJNM2(B) ;AND JNAME. + MOVE C,USYSNM(TT) + HLLZM C,WHSNAM(B) + HRLZM C,WHSNM2(B) ;AND SNAME. + MOVE C,[SIXBIT /STOP/] + SKIPE USTP(TT) ;AND "STATUS": IF NOT RUNNABLE, "STOP". + JRST VWHO4 + MOVE C,[SIXBIT /RUN/] ;IF NOT WAITING, "RUN". + SKIPN FLSINS(TT) + JRST VWHO4A + MOVE C,[SIXBIT /PAGE/] ;DETECT WAITING FOR PAGE. + MOVE Q,USWST(TT) + TLNE Q,200000 + JRST VWHO4 + JRST VWHO4B + +VWHO4A: MOVE E,UPC(TT) ;JOB RUNNING: USER MODE? + TLNE E,%PCUSR ;IF SO, STATUS IS "RUN" (C ALREADY SET UP) + JRST VWHO4 +VWHO4B: MOVE E,SV40(TT) ;ELSE DECODE SYSTEM CALL TO GET STATUS. + HLRZ Q,E + CAIN Q,(.CALL) + JRST VWHO4D ;SYMBOLIC SYSTEM CALL. + TRZ Q,17_5 + MOVE I,OPTION(TT) + TLNN I,%OPDEC + JRST VWHO4E + CAIE Q,40_9 + CAIN Q,41_9 + JRST VWHO4F + CAIN Q,47_9 + JRST VWHO4F +VWHO4E: CAIN Q,(.IOT) ;.IOT => DECODE DEVICE IN USE. + JRST VWHOI1 + CAIN Q,(.OPER) + JRST VWHOO1 ;.OPER => DECODE ADDRESS FIELD. + CAIN Q,(.CALL) + JRST VWHOC1 ;.CALL BUT NOT SYMBOLIC => DECODE AC FIELD. + LSH Q,-9 + CAIL Q,40 + CAIL Q,40+NUUOSX +VWHO4F: SKIPA C,[SIXBIT /UUO/] ;UNRECOGNIZED UUO. + MOVE C,UUOSXB-40(Q) ;ELSE GET SIXBIT NAME OF UUO. + JRST VWHO4C + +;A SYMBOLIC SYSTEM CALL IS IN PROGRESS. +VWHO4D: MOVE C,LSCALL(TT) ;USE SYSTEM CALL NAME AS STATUS + CAME C,[SIXBIT /SIOT/] + CAMN C,[SIXBIT /IOT/] + JRST VWHOI2 ;BUT IF IT'S "IOT", DECODE DEVICE TYPE. +VWHO4C: SKIPE FLSINS(TT) + JRST VWHO4 + LSH C,-6 + TLO C,'+_12. ;STICK "+" ON FRONT IF RUNNING IN SYSTEM +;DROPS THROUGH ;(NOT IF IN USER MODE, OR IF HUNG). + ;DROPS IN +;COME HERE WITH STATUS AS SIXBIT IN C. +VWHO4: +IFE SWPWSP, SKIPL USWSCD(TT) ;SKIP IF SWAP-BLOCKED +IFN SWPWSP,[ MOVE Q,USWST(TT) + TLNN Q,%SWSB +] + JRST .+3 + LSH C,-6 + TLO C,(SIXBIT/>/) + HLLZM C,WHSTAT(B) + HRLZM C,WHSTA2(B) + MOVEI C,WHJ%RT(B) + HRLI C,442000 + MOVE Q,JTMU(TT) ;COMPUTE % RUN TIME FROM SCHEDULER PRIORITY. + MULI Q,100. + DIV Q,[2.^6] + IDPB Q,C + MOVE Q,UTRNTM(TT) + IDIVI Q,25000. + IDPB Q,C ;JOB RUNTIME IN .1 SEC UNITS. + MOVE Q,NMPGS(TT) + MOVE I,NSWPGS(TT) + SUBM Q,I + IDPB I,C ;JOB # REAL PAGES. + IDPB Q,C ;JOB # VIRTUAL PAGES. +;HANDLE THE USER-SPECIFIED FIELDS IN THE WHOLINE. + MOVE Q,UWHO1(TT) + ANDCMI Q,17 + MOVEM Q,1(C) ;STORE JOB'S WHOLINE FLAGS. + MOVE Q,UWHO2(TT) + HLLZM Q,2(C) ;STORE FIRST USER WHO VAR + HRLZM Q,3(C) + MOVE Q,UWHO3(TT) + HLLZM Q,4(C) ;STORE SECOND USER WHO VAR + HRLZM Q,5(C) +VWHO2: CONO PI,CLKON + AOBJN A,VWHO1 + JRST VWSYS + +VWHOO1: HRRZ Q,E ;JOB EXECUTING .OPER. + CAIL Q,MXOPR + SKIPA C,[SIXBIT/UUO/] + MOVE C,OPRSXB(Q) ;GET .OPER NAME AS STATUS + JRST VWHO4C + +VWHOI2: SKIPL Q,UUAC(TT) ;NEW SYS CALL IOT + JRST VWHO4C ;GETTING ARGUMENTS, UUAC NOT SET UP YET + MOVE I,C ;SAVE NAME IN I + JRST VWHOI4 + +VWHOI1: LDB Q,[270400,,E] ;.IOT + SETZ I, +VWHOI4: ADDI Q,IOCHNM(TT) ;Q HAS IOCHNM WORD ADDR FOR CHANNEL. + MOVE Q,(Q) ;GET IOCHNM WORD CONTENTS (RH INDEXES TABLES) + HLRZ C,Q + HLL Q,IOTTB(Q) ;LH GETS BITS SAYING DIRECTION, BLOCK VS UNIT. + HLL C,CLSTB(Q) + TLNE C,%CLSJ ;IF JOB DEVICE + JRST [ MOVE C,JBDEV(C) ;GET NAME OF SIMULATED DEVICE + JRST VWHOI6 ] + HLLZ C,DCHSTB(Q) ;C GETS DEVICE NAME (LEFT-JUST SIXBIT) + JUMPL C,VWHOI6 ;JUMP IF NORMAL 3-CHARACTER NAME + MOVSS C ;NO, IS ADDRESS OF 6-CHARACTER NAME + MOVE C,(C) +VWHOI6: SETZ D, ;EVENTUALLY MAKE STATUS BE 9 CHARS, NOT 6? + MOVE E,[360600,,C] + ILDB J,E ;FIND FIRST SPACE IN THAT DEVICE NAME + JUMPN J,.-1 + JUMPGE Q,VWHOI3 .SEE %IOTBK ;IF BLOCK MODE, PUT A "B" THERE. + MOVEI J,'B + DPB J,E + IBP E +VWHOI3: CAME I,[SIXBIT /SIOT/] + JRST VWHOI5 + MOVEI J,'S + DPB J,E + IBP E +VWHOI5: MOVEI J,'O ;FOLLOW WITH "O" OR "I" SAYING DIRECTION. + TLNN Q,%IOTOT + MOVEI J,'I + DPB J,E + JRST VWHO4C ;COMPLETED STATUS LOOKS LIKE "TTYBO". + +VWHOC1: LDB Q,[270400,,E] ;.CALL: GET AC FIELD, + MOVE C,CALSXB(Q) ;GIVE SIXBIT NAME OF .CALL. + JRST VWHO4C + +;MODE ISN'T 0: FIGURE OUT WHICH JOB TO DISPLAY WHO-LINE FOR, +;AND GO TO VWHO3R WITH JOB'S IDX IN TT. COME HERE WITH TTYCHN OFF. +VWHO3: LSH TT,-16.-4 ;WHAT JOB WAS LAST DISPLAY DONE FOR? + IMULI TT,LUBLK + CAMGE TT,USRHI + SKIPN D,UNAME(TT) + JRST VWHO3B ;JOB WE WERE LOOKING AT HAS VANISHED. + TLNE C,<-4>_<16.+4-18.> + JRST VWHO3B ;THIS TTY IS GETTING SYSTEM WHO-LINE. + TLNN C,2_<16.+4-18.> + JRST VWHO3E ;WANT SAME JOB AS LAST TIME. + +;MODE 2 OR 3: COME HERE TO SEARCH FOR DESIRED JOB. +VWHO3A: MOVSI E,1_<16.+4-18.> + MOVEM E,WHMODE(B) ;SWITCH TO MODE 1. + MOVEI E,MAXJ+5 ;DON'T LOOP FOREVER +VWHO3D: ADDI TT,LUBLK ;ADVANCE TO NEXT JOB UP OR DOWN. + TLNE C,1_<16.+4-18.> + SUBI TT,2*LUBLK + SKIPGE TT ;WRAP AROUND IF NEC GOING DOWN. + ADD TT,USRHI + CAML TT,USRHI ;WRAP AROUND IF NEC. GOING UP. + MOVEI TT,0 + CAMN D,UNAME(TT) ;BELONGS TO SOMEONE ELSE => KEEP GOING. + JRST VWHO3C ;BELONGS TO THIS USER => STOP. + SOJG E,VWHO3D ;KEEP LOOKING BUT DON'T LOOP IF NO JOB TO BE FOUND. +VWHO3B: SETZM WHSTAT(B) ;NO JOB TO BE FOUND. + CONO PI,TTYON + JRST VWHO2 + +VWHO3C: MOVE Q,TT ;DESIRED JOB FOUND: SET UP FOR MODE 1 + IDIVI Q,LUBLK ;LOOKING AT THIS JOB. + LSH Q,16.+4 + MOVEM Q,WHJOB(B) +VWHO3E: CONO PI,TTYON + JRST VWHO3R + + +;USER WHO LIES UPDATED; NOW UPDATE SYSTEM WHO LINE VARS. +VWSYS: LDB A,[$11AD1,,TT11HA] + LDB B,[$11AD0,,TT11LO(A)] + ADD B,[$11WD1,,TT11LO] ;FIRST WORD OF BLOCK SET BY 11 + MOVEI C,SRI + IDPB C,B ;ITS VERSION#. + MOVEI C,2 + MOVEI E,0 +IFN SWPWSP, MOVSI TT,%SWSB + MOVEI Q,2*LUBLK +VWSYS2: CAML Q,USRHI ;COUNT # JOBS. + JRST VWSYS1 + SKIPN UNAME(Q) + JRST VWSYS3 + AOS C ;C GETS # JOBS, + SKIPE USTP(Q) + JRST VWSYS3 +IFE SWPWSP, SKIPGE USWSCD(Q) +IFN SWPWSP, TDNE TT,USWST(Q) + AOS E ;E GETS NUMBER OF ACTIVE SWAPPED BLOCKED JOBS +VWSYS3: ADDI Q,LUBLK + JRST VWSYS2 + +VWSYS1: IDPB C,B ;TOTAL # JOBS + MOVE D,MMPCNT + IDPB D,B ;TOTAL MEM (= TOTAL # PAGES, COUNTING SHARED PAGES ONLY ONCE). + MOVE C,RNABLU + SUBI C,1 + IDPB C,B ;RUNNABLE USERS + IDPB E,B ;# SWAP-BLOCKED JOBS + MOVE TT,NPGWTU + IDPB TT,B ;# WAITING FOR PAGE. + MOVE C,TRUMM ;TOTAL RUNNABLE USER MEMORY + IDPB C,B + MOVEI C,0 + MOVE TT,USRHI ;COUNT PAGES AVAILABLE FOR USE OR ACTUALLY USED FOR USER MEM + ADDI TT,USRSTG+1777 + LSH TT,-10. +VWSYS5: LDB D,[MUR,,MEMBLT(TT)] + CAIE D,MURUSR + CAIN D,MUFR + AOS C ;FREE OR USER MEM. + CAIGE TT,TSYSM-1 + AOJA TT,VWSYS5 + IDPB C,B ;TOTAL MEM AVAIL FOR USERS + HLRZ C,QDATE + IDPB C,B + MOVE C,SYSDBG + IDPB C,B + AOS B ;SKIP A WHOLE WORD FOR TIME OF DAY + MOVEI D,(B) ;SAVE ADDRESS FOR BELOW + MOVE C,SUSRS ;# LOGGED IN USERS. + IDPB C,B + MOVEI E,10000. ;FAIR SHARE IN % + IDIV E,SLOADU ;BASHES TT + IDPB E,B + MOVE C,TIMOFF ;TIME OF DAY IN .5 SEC UNITS. + LSH C,4 + MOVEM C,(D) ;DEPOSITING TIME OF DAY TRIGGERS WHO-LINE UPDATE + POPJ P, ; BY THE PDP-11, SO DEPOSIT IT LAST + +] ;END IFN N11TYS + +SUBTTL EXPAND/CONTRACT USER VARIABLES AREA + +SYSEX: PUSHJ P,SCOREX + POPJ P, + MOVE A,TIME + MOVEM A,SCITM + POPJ P, + +SYSDEC: MOVE A,TIME ;TRY TO DECREASE CORE RESERVED FOR USER VARIABLES + SUB A,SCITM + CAIG A,50. + POPJ P, ;TOO SOON SINCE GOT MORE CORE + CONO PI,CLKOFF + MOVE A,USRHI + SUBI A,LUBLK + SKIPN UNAME(A) + JRST .-2 + ADDI A,LUBLK + MOVEM A,USRHI ;USRHI=> HIGHEST USER+L + ADDI A,USRSTG + ADDI A,1777 + SETOM SJCFF ;INHIBIT ALLOCATION WHILE HUSRAD IS CHANGING + CONO PI,CLKON + MOVEI U,0 ;FOR ACORE + LSHC A,-10.-36. ;MOVE INTO B AS WELL + PUSHJ P,ACORE + BUG ;LOST FLUSHING CORE? + CLEARM SJCFF + POPJ P, + +SCOREX: LDB B,[121000,,HUSRAD] ;EXTEND CORE FOR USER VARIABLES AT TOP OF SYSTEM + ADDI B,1 + CAILE B,LIOBLK + MOVEI B,LIOBLK ;TRYING TO GET TOO BIG, DON'T + MOVEI U,0 + JRST ACORE + +SUBTTL LOGGER OUT + +;THIS ROUTINE AWAKENED BY .LOGOUT, .GUN, ETC. +;SEARCH FOR TREES THAT ARE LOGGING OUT AND READY TO BE FLUSHED +;(IE HAVE BULGO SET) AND FLUSH THEM, PRINTING LOGOUT MESSAGE IF APPRO. +SYSGUN: SETZ U, +SYSGU0: MOVE T,APRC(U) + TLNE T,BULGO ;IS THIS JOB READY TO BE FLUSHED? + SKIPN UNAME(U) + JRST SYSGU1 +IFN NUNITS,[ + SKIPGE TTYTBL(U) ;IF CONSOLE-CONTROLLED, FLUSH UTAPE ASSIGNMENTS + JRST SYSGU2 + MOVSI I,-NUNITS + MOVE A,UNAME(U) + CAMN A,UTASS+1(I) + SETZM UTASS+1(I) + AOBJN I,.-2 +SYSGU2: ] + HLRO B,UNAME(U) + AOJE B,SYSGU3 ;IF THIS TREE COUNTS AS A LOGGED-IN USER, + SKIPL TTYTBL(U) + SOS SUSRS ;DECREMENT COUNT OF SUCH. +SYSGU3: CONO PI,CLKOFF + PUSHJ P,DMNPLO ;UPDATE TREE'S USAGE AND INFORM DEMON JOB + MOVEM TT,TRUNTM(U) ;SAVE RUN TIME FOR LOGOUT MSG + CONO PI,CLKON + SKIPGE A,TTYTBL(U) + JRST SYSGU4 ;IF TREE HAS CONSOLE, + SKIPE TTNTO(A) + BUG + PUSHJ P,TTYLO1 ;FREE IT. + CAMN U,EPDL(U) ;UNLESS GUNNED DOWN, + SKIPN SUPPLG ;MAY NOT WANT TO BOTHER PRINTING MESSAGE ON SYS CONSOLE + SKIPGE DEDTIM + JRST SYSGU4 ;IF LOGGED OUT BECAUSE SYS DOWN, SPARE THE LOGOUT MSG + PUSHJ P,WARMTTY + MOVEI I,[ASCIZ / LOGOUT /] + PUSHJ P,SYSSP + MOVE A,UNAME(U) + PUSHJ P,SYSIXP ;UNAME. + PUSHJ P,STYOS ;SPACE. + HRRZ A,TTYTBL(U) + PUSHJ P,SYSOPT ;TTY #. + PUSHJ P,SYSTCR + ;VALUE PRINTED IS WRONG, AND HARD TO FIX, SO FOLLOWING CODE HAS BEEN FLUSHED. + ;THE REASON IT'S WRONG IS BECAUSE TIME ALREADY SENT TO THE DAEMON IS NOT INCLUDED. + ;MOVEI I,[ASCIZ / TUSED= /] + ;PUSHJ P,SYSSP + ;MOVE A,TRUNTM(U) + ;MULI A,4069. + ;DIVI A,1000. + ;PUSHJ P,SYSDPC + ;MOVEI I,[ASCIZ / USECS/] + ;PUSHJ P,SYSSTD + CAMN U,EPDL(U) ;WAS LOGGED OUT BY SELF? + JRST SYSGU4 + MOVEI I,[ASCIZ / ^^ GUNNED DOWN BY /] + PUSHJ P,SYSSP + MOVE A,SRN4(U) + PUSHJ P,SYSIXP ;UNAME OF GUNNER. + MOVE A,SRN5(U) + PUSHJ P,SYSSIX ;SPACE, AND JNAME OF GUNNER. + PUSHJ P,SYSTCR ;CRLF. +;MESSAGES PRINTED IF NECESSARY. +SYSGU4: SETZ R, + PUSHJ P,ZUSER ;COMPLETELY ELIMINATE THE JOB. + CONO PI,CLKON +SYSGU1: ADDI U,LUBLK + CAMGE U,USRHI + JRST SYSGU0 + SETZ U, + POPJ P, + +;DETACH ANY TREES WHOSE TOP-LEVEL JOBS HAD FATAL INTS + +SYSDT: SETZB U,J + PUSHJ P,SWTL + TREESW + CONO PI,CLKOFF + MOVSI B,BUSRC + MOVSI T,BULGOS+400000 +SYSDT0: SKIPN UNAME(J) + JRST SYSDT1 + SKIPGE SUPPRO(J) ;LOOK FOR TOP-LEVEL + TDNE T,APRC(J) ;IGNORE JOBS ALREADY DISOWNED, OR LOGGING OUT. + JRST SYSDT1 + TDNE B,USTP(J) ;THAT HAS BEEN STOPPED AS BY SUPERIOR + JRST SYSDT2 +SYSDT1: ADDI J,LUBLK + CAMGE J,USRHI + JRST SYSDT0 + JRST CLKOPJ ;NO MORE SUCH JOBS, DONE; LSWPOP AND CLKON. + +;FOUND A TOP LEVEL JOB NEEDING TO BE DETACHED. +SYSDT2: PUSH P,J + MOVE T,OPTION(J) + TLNE T,%OPLKF + JRST [ IDIVI J,LUBLK ;BASHES R + .CALL [SETZ ? 'UNLOCK ? SETZI %JSNUM(J)] ;UNLOCK THE LOCKS + BUG + MOVE J,(P) + JRST .+1 ] + CONO PI,CLKOFF ;IODCSS MIGHT HAVE TURNED IT ON + SKIPL E,JBI(J) ;NOTE CLKOFF IN EFFECT WHILE HACKING JOB DEVICE STUFF + SKIPGE JBCG(E) + JRST SYSDTA + MOVE A,JBCUI(E) ;JOB DEVICE, GIVE IOCER1 OR OPNL7 + LDB T,[000400,,JBSTS(E)] + CAIE T,1 + JRST [ MOVSI T,7_5 ;NON IOT, UNHANG CREATOR SO WILL SEE OPNL7 + MOVEM T,JBSTS(E) + MOVE T,FLSINS(A) + CAMN T,JBFLS + SETZM FLSINS(A) + JRST SYSDTA ] + MOVEI B,1 ;IOT GIVE IOCER1 + MOVS H,E + PUSHJ P,NSTIOC + JFCL +SYSDTA: POP P,J + SETZ U, + MOVE I,[SYSDT8,,[ASCIZ/TOP LEVEL INTERRUPT /]] + PUSHJ P,SYSJEX + PUSHJ P,SYSDT7 + JRST SYSDT + +SYSDT8: MOVE A,-1(P) ;USER INDEX + MOVE A,PIRQC(A) ;TOP LEVEL INTERRUPT BITS + PUSHJ P,SYSFWP +SYSDT9: MOVEI I,[ASCIZ/ DETACHED JOB # /] + JRST SYSSP + +;JOB IN J SHOULD BE DETACHED, AND GUNNED AFTER AN HOUR, +; OR RIGHT AWAY IF NOT LOGGED IN +SYSDT4: HLRE B,UNAME(J) + AOJE B,SYSDT5 ;NOT LOGGED IN => KILL + HRLI I,SYSDT9 + PUSHJ P,SYSJEX + PUSHJ P,SYSDT3 + POPJ P, + +SYSDT5: HRLI I,[MOVEI I,[ASCIZ / KILLED JOB # /] + JRST SYSSP] + PUSHJ P,SYSJEX + PUSHJ P,SYSDT6 + POPJ P, + +SYSDT6: PUSHJ P,SYSDT3 ;FIRST DETACH (LEAVES USER INDEX OF TOP LEVEL JOB IN A). + JRST ALOGO6 ;THEN LOG OUT. SINCE DETACHED, NO ADDITIONAL MSG FROM SYSGUN. + +;CALL WITH CLOCK OFF TO DETACH THE JOB WITH IDX IN A AND J. +;ASSUME JOB'S BULGOS HAS BEEN CHECKED, AND TREESW LOCKED. +;TURNS CLOCK BACK ON AND DOES A LSWCLR +SYSDT7: TDZA B,B ;HERE TO LEAVE AROUND +SYSDT3: MOVEI B,10 ;HERE TO SET BUMRTL WHEN WE DETACH + PUSHJ P,SOSSET + DIELOK(A) + AOS DIELOK(A) + CONO PI,CLKON + MOVEM B,CTLBTS(U) + PUSHJ P,NDETA0 + BUG + POPJ P, + +IFN NDLTYS+NETYS,[ + +;HANDLE DIAL-UP LINE CONNECTS OR DISCONNECTS ON DL-10 AND DTE20. + +SYSDIL: +IFN NDLTYS,[ + SKIPN A,DL10CL + JRST SYSDL2 ;THERE'S NONE TO PROCESS? + SETZM DL10CL ;FREE THE VAR FOR THE PDP11 + PUSHJ P,SYSDL0 +SYSDL2: ];NDLTYS +IFN NETYS,[ + SKIPGE A,DTEHNG + JRST SYSDL3 + SETOM DTEHNG + PUSHJ P,SYSDL0 +SYSDL3: +];NETYS + POPJ P, + +SYSDL0: LDB I,[.BP 77,A] ;GET OUT THE TTY NUMBER + CAIL I,NCT + POPJ P, + TRNE A,-100 + JRST SYSDL1 ;IT'S A CONNECT + PUSHJ P,SWTL ;IT'S A DISCONNECT + TREESW + MOVE J,TTYSTS(I) ;DETACH THE TREE ON THAT TTY. + JUMPL J,LSWPOP ;THERE'S NO TREE. + TLNN J,%TSCNS + JRST LSWPOP ;TTY IS OPEN AS A DEVICE. + MOVE I,APRC(J) + TLNE I,BULGOS ;GIVE UP IF TREE LOGGING OUT. + JRST LSWPOP + MOVE U,USER + MOVEI I,[ASCIZ /DIALUP LINE DISCONNECTED,/] + JRST SYSDT4 + +;ON A CONNECT, SNARF THE LINE SPEEDS DETERMINED BY THE PDP11. +SYSDL1: LDB B,[.BP 7000,A] + DPB B,[$TTISP,,TTYTYP(I)] + LDB B,[.BP 700,A] + DPB B,[$TTOSP,,TTYTYP(I)] + PUSHJ P,NCNSSP ;SET UP INITIAL TTY TYPE AS PRINTING, ACCORDING TO SPEED + MOVEI B,20 ;DON'T ASSUME TTY IS AT LEFT MARGIN + MOVEM B,TTYIHP(I) + MOVEM B,TPHP(TT) + MOVEM B,TPHP+TPLEN(TT) + POPJ P, +];NDLTYS+NETYS +.ELSE SYSDIL==CPOPJ + +IFN N11TYS,[ +SYS11D: MOVEI I,[ASCIZ /TV 11 WENT DOWN --/] + PUSHJ P,SYSSTD ;STRING, SPACE, TIME AND CR + SETZM TT11P ;IN CASE SCR11D WAS SET BY A USER, AND HE DIDN'T HACK THIS. + MOVEI A,TT11HD+1 + MOVEM A,TT11HD ;PREVENT TT11IN FROM BEING CALLED ANY MORE. +SYS11G: PUSHJ P,SWTL ;PREPARE FOR DOING DETACHES + TREESW + MOVE I,[-N11TYS,,NF11TY] +SYS11F: SKIPGE J,TTYSTS(I) ;DETACH ALL 11TV TREES. + JRST SYS11E ;THIS 11TV NOT IN USE + TLNN J,%TSCNS + JRST SYS11P ;THIS 11TV IN USE AS A DEVICE, DON'T DETACH BUT DO PCLSR + MOVE T,APRC(J) + TLNE T,BULGOS + JRST SYS11E ;DON'T DETACH TREES THAT ARE LOGGING OUT. + MOVE U,USER + MOVEI I,[ASCIZ / .../] + PUSHJ P,SYSDT4 ;DETACH OR KILL JOB W/ # IN J, AND PRINT MESSAGE. + JRST SYS11G ;TREESW NOW UNLOCKED; MUST RE-LOCK. + +SYS11P: HRRZ A,J ;PCLSR THE NAME DRAGON + PUSHJ P,NJRPCL + PUSHJ P,NJUPCL ;AND DROP INTO SYS11E + +SYS11E: AOBJN I,SYS11F + PUSHJ P,LSWPOP ;TREESW NOT NEEDED IF NOTHING TO DETACH. + MOVSI T,-MXVBN ;FLUSH VIDEO BUFFER ASSIGNMENTS. + SETOM VBAST(T) + AOBJN T,.-1 + MOVEI T,0 +SYS11V: CAML T,USRHI + POPJ P, + SETZM NVDBA(T) + SETOM TVCREG(T) ;FLUSH TV BUFFER NUMBERS IN CREGS + ADDI T,LUBLK + JRST SYS11V + +TVBNCL: PUSH P,T ;"DEASSIGN" TVVBN(U) AND CLEAR IT ON SCREEN IF NECC + SKIPN TEN11F + SKIPL TT11P + JRST TVBNC1 + SKIPL T,TVVBN(U) + CAME U,USER + JRST TVBNC1 + PUSH P,400000+TTR10*2000 + MOVEM T,400000+TTR10*2000 + MOVE T,TVBLAD + CLEARM 400000+TTR0*2000(T) + POP P,400000+TTR10*2000 +TVBNC1: SETOM TVVBN(U) + JRST POPTJ +];N11TYS + +;PRINT CONSOLE FREE MSGS ON ALL TTYS THAT NEED IT. +;NOTE THAT THERE ARE LOWER CASE MESSAGES ON THIS PAGE. +.SEE TTYLO1 ;THIS RTN SIGNALLED WHEN A TTY BECOMES FREE. +SYSCFM: CLEARM IOCHNM+STYOC ;REUSE SYSTEM CONSOLE CHANNEL +SYSCF0: MOVEI A,0 +SYSCF1: CAIL A,NCT + JRST SYSCOP ;DONE, SWITCH SYSCON CHANNEL BACK TO SYSCON + SKIPGE B,TTYSTA(A) .SEE %TACFM + AOJA A,SYSCF1 + TLNE B,%TANJS + TLZ B,%TACTZ ;%TANJS MEANS A FAILED ^Z - FORGET ABOUT THAT ^Z. + MOVEM B,TTYSTA(A) + SKIPGE TTYSTS(A) .SEE %TSFRE + TLNE B,%TACTZ + AOJA A,SYSCF1 ;IN PROCESS OF LOADING TREE FOR THIS CONSOLE + HRLZ T,A + ADD T,[%TJDIS+%TJMOR,,TYODN] + MOVEM T,IOCHNM+STYOC ;"OPEN" A CHANNEL TO THAT TTY. + SKIPGE SHUTDN + PUSHJ P,SYSTS1 ;IF SHUTDOWN AND A DISPLAY, CLEAR THE SCREEN + MOVEI I,[ASCIZ / +Top level interrupt, tree detached +/] + MOVSI B,%TCDET ;IF TTY FREE DUE TO DETACH FOR TOP LEVEL INT, + TDNE B,TTYCOM(A) + PUSHJ P,SYSSP .SEE NDETAC ;SAY SO. + ANDCAM B,TTYCOM(A) + MOVSI B,%TANJS + ANDCA B,TTYSTA(A) + EXCH B,TTYSTA(A) ;CLEAR BIT, SAVE OLD VALUE + PUSH P,A + XCT DWNMSG + SKIPGE SHUTDN + JRST SYSCF2 ;SYSTEM IS DOWN, SAY SO + XCT SCMESG + CAMN A,SYSCN + JRST SYSCF2 ;SYSTEM JOB USING THIS CONSOLE, SAY SO + SRITYP [ System fully loaded. Console ] + TLNN B,%TANJS + SRITYP [ Console ] + PUSHJ P,SYSSP +IFN N11TYS, CAIE A,NF11TY ;ON ALL FREE PDP11-TV CONSOLES + PUSHJ P,SYSOPT + MOVEI I,[ASCIZ / Free./] + PUSHJ P,SYSSTD + XCT DMESSG + SKIPE SYSDBG +SYSCF2: PUSHJ P,SYSSTD ;SAY "SYS BEING DEBUGGED" IF NEC. + SKIPLE SHUTDN + PUSHJ P,SYSSHM ;SAY "SYS GOING DOWN" IF NEC. + POP P,A + MOVSI B,%TACFM ;TTY NO LONGER NEEDS CONSOLE FREE MSG. + IORM B,TTYSTA(A) +IFN N11TYS,PUSHJ P,TTYLO2 ;TELL THE PDP11 THIS TTY IS FREE + SETZM IOCHNM+STYOC + JRST SYSCF0 + +SUBTTL SHUTDOWN + +;HANDLE .SHUTDN - PRINT "GOING DOWN" MSGS, ETC. +SYSSHD: LDB D,[221700,,SHUTLK+1] + PUSHJ P,SWTL + SHUTLK + MOVEI I,SYSSHM + TLO I,40 + PUSH P,D + PUSHJ P,SYALCP + POP P,D + IMULI D,LUBLK + SKIPE D ;SKIP IF LEFT FROM >5 MIN PRINT OUT + SKIPN A,UNAME(D) + JRST LSWPOP + MOVEI I,[ASCIZ /CULPRIT = /] + PUSHJ P,SYSSP + PUSHJ P,SYSSIX + MOVE A,JNAME(D) + PUSHJ P,SYSSIX + PUSHJ P,SYSTCR + JRST LSWPOP + +;GOING DOWN, WHAT A SHAME +SYSSHM: SRITYP [GOING DOWN IN ] + SKIPG SHUTDN + SRITYP [REVIVED] + PUSHJ P,SYSSP + SKIPG B,SHUTDN + JRST SYSSHN + SUB B,TIME + IDIVI B,30. ;CONVERT TO SECONDS + PUSHJ P,RTIME ;CONVERT TO SIXBIT + MOVE B,A + PUSHJ P,SYSTCD +SYSSHN: MOVEI I,[.ASCII /. /] + JRST SYSSTD + +;AND COME HERE WHEN TIME FOR SYS TO GO DOWN. +;MARK THE SYSTEM "DOWN", START FLAPPING TAPES AND DISKS, +;GUN ALL USERS, ETC. COMPLETION OF GOING DOWN IS DETECTED AT +;SLOW CLOCK LEVEL ("COFFIN"). +SYSOUT: PUSHJ P,CLQDEL + DEDBLK + SETOM DEDTIM ;PREVENT ^Z'S + .FDELE [SIXBIT/ SYSDOWN MAIL/ ? 0 ? 0] + JFCL + MOVEI U,LUBLK*2 +SYSCK3: SKIPGE SUPPRO(U) ;LOOK FOR ALL TOP-LEVEL JOBS. + SKIPN UNAME(U) + JRST SYSCK4 + MOVE T,USTP(U) + TLNE T,BUSRC + JRST SYSCK1 + MOVE T,OPTION(U) ;IS THIS JOB AN EXCEPTION? + TLNE T,%OPLIV + JRST SYSCK4 ;YES, LET IT LOG ITSELF OUT +SYSCK1: PUSHJ P,ALOGOUT ;LOG IT OUT (TELLS IT TO PREPARE ITSELF, SIGNAL SYSGUN) +SYSCK4: ADDI U,LUBLK + CAMGE U,USRHI + JRST SYSCK3 + SETZ U, +DWNMSG: SRITYP [NOT IN OPERATION] + PUSHJ P,SYALCP ;TYPE OUT ON FREE CONSOLES +IFN TPLP, MOVEI A,SCRTPF ;TPLOFF +IFN TPLP, IORM A,SUPCOR +IFN UNSPLP,[ SKIPG TPLFLG + JRST SYSCK0 + MOVEI A,SCRTPF + IORM A,SUPCOR +SYSCK0: +] MOVE I,QACTB + IORM I,QMDRO + MOVSI A,-NQS +SYSCK7: MOVE I,DCHBT(A) + SKIPN QACT(A) + IORM I,QTUTO(A) + AOBJN A,SYSCK7 +IFN NUNITS,[ + MOVEI A,1 +SYSUDM: SKIPL UDIRO(A) + .UDISMT A, ;DISMOUNT TAPES + CAIGE A,NUNITS + AOJA A,SYSUDM +] + MOVE T,TIME + MOVEM T,DTHTIM + SETOM SHUTDN + PUSHJ P,TTTMNT ;TURN OFF ALL TERMINET MOTORS + JRST SCOR + +SUBTTL SYSTEM CHECKS +;CHECK FOR DEVICES THAT LOSE THE PIA, DEVICES THAT INTERRUPT SPURIOUSLY, +;CLOBBERD LOCATIONS IN MEMORY. + +IFE KS10P,[ ; KS has no devices to speak of... + +SYSCK5: MOVSI A,-128. +SYSC51: SKIPL B,DCHNTC(A) +SYSC5A: AOBJN A,SYSC51 + JUMPGE A,CPOPJ + TLNN B,300000 + JRST SYSC5A + PUSH P,A + TLZE B,200000 + JRST SYSC52 + PUSHJ P,SYSC5S + JRST SYSC53 +SYSC52: PUSHJ P,SYSC5C +SYSC53: POP P,A + MOVSI B,300000 + ANDCAM B,DCHNTC(A) + JRST SYSC5A + +SYSC5C: PUSHJ P,SYSC5B + MOVEI I,[ASCIZ / CLOBBERED/] + JRST SYSSTD + +SYSC5S: PUSHJ P,SYSC5B + MOVEI I,[ASCIZ / SUSPECTED OF INTERRUPTING ON CHANNEL /] + PUSHJ P,SYSSP + LDB T,[360300,,DCHNTC(A)] + PUSHJ P,SYSSOP + JRST SYSTCR + +SYSSOP: PUSH P,A + PUSH P,B + MOVE A,T + PUSHJ P,SYSOPT + JRST POPBAJ + +SYSC5B: MOVEI I,[ASCIZ /DEVICE /] + PUSHJ P,SYSSP + HRRZ T,A + LSH T,2 + PUSHJ P,SYSSOP + MOVEI I,[ASCIZ / (CONI= /] + PUSHJ P,SYSSP + HRRZ T,DCHNTC(A) + PUSHJ P,SYSSOP + MOVEI I,[ASCIZ /) /] + JRST SYSSP + +] ;IFE KS10P + +SYSCKS: HRRZ T,UPDBR1 ;CHECK FOR CLOBBERED DBRS + HRRZ TT,UPDBR2 + CAIN T,UPGMP + CAIE TT,UPGMP+100 + BUG HALT,[PAGER DATA CLOBBERED. MAY BE DEC-TTL LEVEL CONVERTERS LOSING.] +;DROPS THROUGH + ;DROPS IN + MOVE A,SYSCKP + MOVE B,(A) + MOVEI C,(B) + EQV C,(B) + AOBJN B,.-1 + CAME C,CKSUMS-TSTB(A) + JRST SYSKS2 + AOBJN A,SYSKS1 +SYSKS3: MOVE A,[-LTSTB,,TSTB] +SYSKS1: MOVEM A,SYSCKP + POPJ P, + +SYSKS2: EXCH C,CKSUMS-TSTB(A) + XOR C,CKSUMS-TSTB(A) ;SAVE XOR + PUSHJ P,WARMTTY + PUSHJ P,DINGTTY + MOVEI I,[ASCIZ /SYSTEM CLOBBERED BETWEEN /] + PUSHJ P,SYSSP + HRRZ A,(A) + PUSHJ P,SYSOPT + MOVEI I,[ASCIZ / AND /] + PUSHJ P,SYSSP + MOVE B,SYSCKP + HLRE A,(B) + SETCMM A ;OFFSET BY ONE + ADD A,(B) + HRRZS A + PUSHJ P,SYSOPT + MOVEI I,[ASCIZ / XOR= /] + PUSHJ P,SYSSP + MOVE A,C + PUSHJ P,SYSFWP + MOVEI I,[ASCIZ / !/] + PUSHJ P,SYSSTD + CLEARM TCKXOR ;TRY TO DETERMINE EXACT ADR AND PREV CONTENTS + MOVE A,[TCKXOR,,TCKXOR+1] + BLT A,TCKXOR+35. + MOVE A,[-LTSTB,,TSTB] +SYSKS6: MOVE B,(A) +SYSKS5: MOVE C,(B) +REPEAT 36.,[IFL .RPCNT-18.,TLNE C,400000_<-.RPCNT> +IFGE .RPCNT-18.,TRNE C,400000_<18.-.RPCNT> + XORM B,TCKXOR+.RPCNT + ] + AOBJN B,SYSKS5 + AOBJN A,SYSKS6 + MOVSI D,-36. +SYSKS7: MOVE A,TCKXOR(D) ;UPDATE CKXORS TBL AND FILL TCKXOR TBL WITH POSSIBLE ADRS + EXCH A,CKXORS(D) + XOR A,CKXORS(D) + HRRZM A,TCKXOR(D) + AOBJN D,SYSKS7 + PUSHJ P,STYOT ;INDENT LINE + MOVSI D,-36. + MOVSI E,400000 ;CURRENT BIT + CLEARB I,J ;COUNT OF #'S PRINTED, CLOBBERED WD +SYSKS8: SKIPE A,TCKXOR(D) + AOJA J,SYSKS9 ;INCR COUNT OF ADRS PRINTED +SYSKT2: LSH E,-1 + AOBJN D,SYSKS8 + SOJN J,SYSKT1 ;MORE THAN 1 ADR CLOBBERD SO CANT PRINT PREV CONTENTS + MOVEI T,"= + PUSHJ P,STYO + MOVE A,I ;PRINT CONTENTS PRIOR TO CLOBBERAGE + XOR A,(R) ;XOR CURRENT CONTENTS + PUSHJ P,SYSFWP + MOVEI T,"- + PUSHJ P,STYO + MOVEI T,"> + PUSHJ P,STYO + MOVE A,(R) + PUSHJ P,SYSFWP ;CURRENT CONTENTS +SYSKT1: PUSHJ P,SYSCRF + JRST SYSKS3 + +SCKX1: PUSH P,T ;UPDATE CKXORS TO REFLECT CHANGING WD IN T IN ADR IN Q + MOVSI C,-36. +SCKX2: SKIPGE T + XORM Q,CKXORS(C) + LSH T,1 + AOBJN C,SCKX2 + JRST POPTJ + +SYSKS9: PUSHJ P,SYSOPT + PUSHJ P,STYOS + MOVE R,TCKXOR(D) ;CLEAR DUP ENTRIES + MOVE T,D + MOVE Q,E ;ALSO LEAVE LAST ADR IN R (IN CASE ITS ONLY ADR) +SYSKT3: CAME R,TCKXOR(T) + JRST SYSKT4 + CLEARM TCKXOR(T) + XORM Q,I +SYSKT4: LSH Q,-1 + AOBJN T,SYSKT3 + JRST SYSKT2 + +SUBTTL SUPPORT ROUTINES FOR BUG MACRO + +;NOTE: THESE REPLACE THE SYSMSG ROUTINE THAT USED TO BE HERE + +;ENTRY POINTS +BUGCHK: PUSH P,TT + MOVE TT,SYSMPT ;HOW MANY MESSAGES BEHIND? + SUB TT,SYSMPU + CAIGE TT,<8_SYSMLNG>-8 + SKIPE SYSDBG + JRST BUGPSE+1 ;TREAT AS BUGPSE IF BUFFER FULL OR SYSDBG + CAIA +BUGINF: PUSH P,TT + PUSHJ P,SYSMS0 ;HAND MESSAGE TO SYSTEM JOB TO BE PRINTED + JRST POPTTJ ;CONTINUE TRAPPED ROUTINE + +BUGPSE: PUSH P,TT + PUSHJ P,SYSMS0 ;COPY MESSAGE INTO SYSTEM JOB BUFFER + JSP TT,BUGDD0 ;PRINT MESSAGE AND GO TO DDT + ASCIZ/PAUSE. FIND A WIZARD, CONSIDER TAKING A CRASH DUMP, +OR TYPE P TO ATTEMPT TO REVIVE THE SYSTEM./ + +BUGDDT: PUSH P,TT + PUSHJ P,SYSMS0 ;COPY MESSAGE INTO SYSTEM JOB BUFFER + JSP TT,BUGDD0 ;PRINT MESSAGE AND GO TO DDT + ASCIZ/DDT. TYPE P TO CONTINUE./ + +BUGNIL: PUSH P,TT + JRST BUGHL1 ;NO MESSAGE, JUST GO STRAIGHT TO DDT. + +BUGAWF: 0 ;JSR HERE WHEN AWFUL THINGS HAVE HAPPENED + CONO PI,PIOFF ;BETTER DO THIS AS SOON AS POSSIBLE + MOVEM P,BUGACS+P ;SAVE P AND GET A PDL TO USE + MOVE P,BUGPDL + PUSH P,BUGAWF ;SIMULATE PUSHJ P,BUGHLT +BUGHLT: PUSH P,TT + PUSHJ P,SYSMS0 ;COPY MESSAGE INTO SYSTEM JOB BUFFER +BUGHL1: JSP TT,BUGDD0 ;PRINT MESSAGE AND GO TO DDT + ASCIZ/HALT. FIND A WIZARD OR CONSIDER TAKING A CRASH DUMP. +THE SYSTEM HAS CRASHED AND CANNOT BE REVIVED WITHOUT EXPERT ATTENTION. +IF YOU CAN'T FIND HELP, RELOAD THE SYSTEM./ + +;ROUTINE TO PICK UP THE DATA OUT OF THE BUG TABLE, EVALUATE THE +;ARGUMENTS, AND DUMP THE RESULTS INTO THE SYSMSG BUFFER TO BE +;PRINTED LATER. THE THIRD THING DOWN ON THE STACK IS THE PC+1 +;AT WHICH THE BUG WAS DETECTED. TT IS THE ONLY SMASHABLE REGISTER. +SYSMS0: MOVEI TT,8 ;8 WORDS IN ENTRY + ADDB TT,SYSMPT ;UPDATE STORING POINTER + ANDI TT,8_SYSMLNG-1 ;MASK TO BUFFER INDEX + ADDI TT,SYSMBF + PUSH P,TT ;SAVE PTR + PUSH P,A ;NOW LOCATE BUG TABLE ENTRY + PUSH P,B + MOVE A,TIME ;STASH TIME IN EXTRA WORD OF ENTRY + MOVEM A,7(TT) + MOVEI B,BUGTAB +SYSMS1: HRRZ A,(B) + CAIN A,@-5(P) + JRST SYSMS2 ;PC MATCHES + HLRZ A,(B) ;ADVANCE TO NEXT ENTRY + ADD B,A + JUMPN A,SYSMS1 + JRST 4,. ;NOT IN TABLE?? MACROS MUST BE SCHROD + +SYSMS2: HLRZ A,(B) + ADDI TT,-2(A) + EXCH TT,-2(P) ;TT START OF ENTRY, -2(P) END + MOVE A,TT + HRLI A,1(B) ;COPY BITS,,STRING AND ARG POINTERS + BLT A,@-2(P) + POP P,B + POP P,A + SUBM TT,(P) ;(P) GETS -NARGS + SKIPE (P) ;IN CASE NO ARGS +SYSMS3: PUSH TT,@1(TT) ;EVALUATE ARGUMENT POINTERS + AOSGE (P) + JRST SYSMS3 + MOVEI TT,SCRMSG ;BIT FOR MSG PRINT + IORM TT,SUPCOP ;TRY EVERY SECOND TO PRINT SOME MSGS + IORM TT,SUPCOR ;FIRST ATTEMPT RIGHT AWAY. + JRST POP1J ;RETURN TO BUGINF OR WHEREVER + +;CALL HERE TO PRINT THE MESSAGES OUT OF THE BUFFER +;A HAS SCRMSG +SYSMPR: MOVE TT,SYSMPT ;LAST MESSAGE IN + CAMG TT,SYSMPU ;LAST MESSAGE OUT + JRST [ ANDCAM A,SUPCOP ;CAUGHT UP + POPJ P, ] + SUBI TT,8_SYSMLNG + CAMLE TT,SYSMPU + JRST [ MOVE A,TT ;BEHIND BY MORE THAN SIZE OF BUFFER + SUB A,SYSMPU + MOVEM TT,SYSMPU + LSH A,-3 ;NUMBER OF MESSAGES LOST + PUSHJ P,DINGTTY + PUSHJ P,SYSDPT + MOVEI I,[ASCIZ/ SYS MSGS LOST/] + PUSHJ P,SYSSTD + JRST .+1 ] + MOVEI TT,8 + ADDB TT,SYSMPU + ANDI TT,8_SYSMLNG-1 + ADDI TT,SYSMBF + PUSHJ P,DINGTTY + HLLZ D,(TT) ;GET MODE FLAGS + HRRZ I,(TT) ;GET ASCIZ MSG + HRLI I,440700 +SYSMP0: ILDB T,I + JUMPE T,SYSMP1 + CAIGE T,10 + JRST SYSMP3 + PUSHJ P,STYO + JRST SYSMP0 + +SYSMP1: PUSHJ P,STYOS ;SPACE AND OUTPUT REMAINING ARGS + PUSHJ P,SYSMP2 + JRST SYSTCR ;END WITH TIME, POPJ + JRST SYSMP1 + +SYSMP3: PUSH P,T ;OUTPUT THIS MANY ARGS +SYSMP4: PUSHJ P,SYSMP2 + JFCL + PUSHJ P,STYOS + SOSLE (P) + JRST SYSMP4 + SUB P,[1,,1] + JRST SYSMP0 + +SYSMP2: MOVEI C,0 + LSHC C,3 ;GET A BYTE + JUMPE C,CPOPJ ;NO MORE ARGS TO PRINT + PUSH P,I + MOVE A,1(TT) + PUSHJ P,@SYSMTB(C) + POP P,I + AOJA TT,POPJ1 + +;DISPATCH TABLE FOR SYSTEM MESSAGE PRINTER + +SYSMTB: JRST 4,. ;0 CHECKED FOR END + SYSFWP ;1 FULL WORD OCTAL + SYSDPT ;2 FULL WD DECIMAL + SYSDPC ;3 " WITH COMMAS + SYSCRF ;4 DO CR + CPOPJ ;5 ? + SYSIXP ;6 SIXBIT + [MOVE I,A ;7 ASCIZ + JRST SYSSP] + +;ROUTINE FOR BUGS THAT NEED TO HALT INTO DDT +BUGDD0: HRLI TT,440700 + CONO PI,PIOFF ;PREVENT INTERFERENCE, AND HACK STYO + MOVEM TT,T00POS ;SAVE ADDRESS OF MESSAGE TEMPORARILY + POP P,TT ;RESTORE TT AT TIME OF BUG + POP P,BUGPC ;ADDRESS+1 OF BUG + SKIPE BUGAWF + MOVE P,BUGACS+P ;CORRECT P AT TIME OF BUG + SETZM BUGAWF ;CLEAR FLAG FOR NEXT BUG IN CASE REVIVED + CONI PI,BUGPI ; SAVE PI STATUS + CONI BUGAPR ; SAVE APR STATE +IFE KA10P,[ + CONI PAG,BUGEBR ; SAVE EBR, UBR, ETC + DATAI PAG,BUGUBR +] ;IFE KA10P + SPM BUGPGM ; SAVE PAGER STATE + MOVEM 17,BUGACS+17 ;SAVE ACS + MOVEI 17,BUGACS + BLT 17,BUGACS+16 + MOVE P,BUGPDL ;USE THIS PDL FOR TYPING OUT + PUSH P,T00POS ;RECOVER ASCIZ STRING FOR FLAVOR OF BUG + PUSHJ P,SYSCRF ;CARRIAGE RETURN +BUGDD1: MOVEI A,SCRMSG + PUSHJ P,SYSMPR ;DUMP SYSMSG BUFFER +IFN KA10P,[ + CONSZ TTY,40 ;PUNT IF CHARACTER TYPED + JRST BUGDD2 +] ;KA10P +IFN KL10P,[ + SETZM DTEFLG + MOVEI A,%DTTYI + MOVEM A,DTECMD + CONO DTE,%DBL11 + SKIPN DTEFLG + JRST .-1 + SKIPE DTEF11 ;INPUT TYPED? + JRST BUGDD2 ;YES, PUNT +] ;KL10P +IFN KS10P,[ + SKIPE 8CTYIN ; Any input available? + JRST BUGDD2 ; Yes: Punt. +] ;KS10P + MOVE TT,SYSMPT ;LAST MESSAGE IN + CAMLE TT,SYSMPU ;LAST MESSAGE OUT + JRST BUGDD1 +BUGDD2: MOVE A-1,BUGPI ;CHECK FOR PI IN PROGRESS + ANDI A-1,77400 + LSH A-1,20. + JFFO A-1,[ MOVEI I,[ASCIZ/PI LEVEL /] + PUSHJ P,SYSSP + PUSHJ P,SYSDPT + PUSHJ P,STYOS + JRST .+1 ] + MOVEI I,[ASCIZ/BUG/] + PUSHJ P,SYSSP + POP P,I ;PAUSE OR HALT MESSAGE + SKIPN SYSDBG ;PUNT LONG-WINDED MESSAGE IF DEBUGGING + PUSHJ P,SYSSP + MOVEI I,[ASCIZ/ +YOU ARE NOW IN DDT./] + PUSHJ P,SYSSP + MOVEI TT,[ASCIZ|BUGPC/Q-2/|] + HRLI TT,440700 + MOVEM TT,777777 ;TELL DDT TO EXAMINE BUGHLT ADDRESS + MOVE TT,BUGPC ;ARRANGE FOR P TO JUMP THERE + MOVEM TT,@DDT-6 ;IN OLDER DDT WILL JUST CLOBBER AC0 + MOVSI 17,BUGACS ;RESTORE ACS + BLT 17,17 + CONO PI,PION + JRST DDT + +EBLK + +;DATA AREAS POINTERS AND BUFFER FOR SYS MSG PRINTER + +CTLMAX==55. ;Number of lines after which we should print the date. +CTLCNT: 0 ;Keeps track of number of lines printed on console. + +SYSMPT: 0 ;POINTER TO MESSAGE MOST RECENTLY INSERTED +SYSMPU: 0 ;POINTER TO MESSAGE MOST RECENTLY PRINTED + ;(MUST TAKE MODULO LENGTH OF TABLE, AND ADD OFFSET OF BEGIN OF TABLE) +IFNDEF SYSMLNG,SYSMLNG==5 ;LOG(2) OF # ENTRIES (5=>32) + +SYSMBF: BLOCK 8_SYSMLNG ;8 WDS PER ENTRY: BITS,,STRING, 6 ARGS, TIME + +BUGPC: 0 ;RESTART PC FROM BUG +BUGPI: 0 ; CONI PI,BUGPI +BUGAPR: 0 ; CONI APR,BUGAPR +IFE KA10P,[ +BUGEBR: 0 ; CONI PAG,BUGEBR +BUGUBR: 0 ; DATAI PAG,BUGUBR +];IFE KA10P +IFN 0,[ ;UPGML/UPGMLE not defined yet... +BUGPGM: BLOCK UPGMLE-UPGML ; SPM BUGPGM +] +BUGPGM: BLOCK 8 ;KLUDGE +BUGACS: BLOCK 20 ;AC SAVE AREA FOR BUGDD0 +BUGPDL: -20,,. + BLOCK 20 +T00POS: 0 ;TTY00 HORIZONTAL POSITION + +BBLK + +SUBTTL .SETLOC ROUTINE (DOCUMENT THEN DOES IT) + +SYSSET: MOVE A,SETSLC ;LOCATION TO BE MODIFIED + TLNN A,-1 ;SKIP IF ALREADY DONE + SKIPA C,SETSLQ ;NEW VAL IN SETSLQ + SKIPA C,(A) ;NEW VAL IN LOC + SKIPA D,A ;OLD VAL IN @A + MOVEI D,SETSLQ ;OLD VAL IN SETSLQ + PUSHJ P,SYSSCT ;PRINT OUT DDT-TYPE SEQUENCE + MOVE A,SETSU ;GET USET NAME + PUSHJ P,STYOT ;TYPE OUT A TAB + MOVEI B,0 + PUSHJ P,SYSIXP ;PRINT NAME OF GUILTY PARTY + PUSHJ P,SYSTCR ;STANDARD SYS CARRIAGE RETURN + SKIPGE SETSLC ;IF ALREADY MUNGED AT UUO LEVEL + POPJ P, ;THEN EXIT NOW + MOVE T,SETSLQ ;GET DESIRED VALUE +; SKIPL UMBTS +; JRST SYSSE8 ;DON'T HACK METABITS +; LMB Q,@SETSLC ;GET META BIT OF DESIRED LOCATION +; TRNE Q,1 ;IF 1 THEN HAVE TO MOMENTARILY CLEAR IT +; JRST SYSSE5 +SYSSE8: EXCH T,@SETSLC ;META BIT=0, CHANGE LOCATION +SYSSE6: MOVE Q,SETSLC ;GET ADR OF MUNGED LOC + MOVE A,[-LTSTB,,TSTB] +SYSSE1: MOVE B,(A) + CAIGE Q,(B) + JRST SYSSE3 + HLRE C,B + SETCMM C + ADD C,B + CAILE Q,(C) + JRST SYSSE3 + PUSHJ P,SCKX1 ;UPDATE CKXORS TBL TOO + EQV T,@SETSLC + EQVM T,CKSUMS-TSTB(A) + MOVE T,@SETSLC + PUSHJ P,SCKX1 ;UPDATE TO REFLECT NEW CONTENTS +SYSSE2: MOVSI A,SCLSET + ANDCAM A,SUPCOR + CAIE Q,SYSDBG ;IF NOT DEBUG SWITCH + POPJ P, ;EXIT + PUSHJ P,DBGINT ;SYSDBG STATE CHANGE, TELL ALL USERS + SKIPE SYSDBG + JUMPN T,CPOPJ +;SYSDBG CLEARED, GIVE "IN OPERATION" MESSAGE BY DROPPING INTO ISYS +;HERE WHEN SYSTEM IS UP AND DISKS HAVE BEEN INITIALIZED +;RE-ENTER HERE WHEN SYSDBG STATE CHANGED +ISYS: PUSHJ P,DATIME ;MAY BE ABLE TO FIND TIME IMMEDIATELY (ONCE MFD IN) + PUSHJ P,TTTMN2 ;MAKE SURE WE THINK THAT ALL TERMINET + ;MOTORS ARE OFF, SO WE'LL TRY TO TURN THEM ALL ON WHEN WE TYPE + ;"ITS IN OPERATION" ON THEM. + PUSHJ P,TTRSAL ;SEND %TDORS TO ALL SOFTWARE TTYS + SRITYP [IN OPERATION] + SKIPE SYSDBG ;IF SYS IN DEBUG MODE +DMESSG: SRITYP [BEING DEBUGGED] ;SET TO APPROP MSG + PUSHJ P,SYALCP ;PRINT ON ALL CONSOLES +SCMESG: SRITYP [SYSTEM JOB USING THIS CONSOLE.] + PUSHJ P,SYSSP ;PRINT ON SYS JOB CONSOLE + SKIPGE DMLLDF ;START DRAGON (DAEMON) IF WANTED + SKIPL DMON+1 ;AND NOT DONE ALREADY + POPJ P, + HRROI T,DMON + CONO PI,UTCOFF + PUSHJ P,NUJBST + BUG ;SHOULD BE ROOM IN REQUEST BUFFER + JRST UTCONJ + +SYSSE3: AOBJN A,SYSSE1 + JRST SYSSE2 + + ;SETLOC ROUTINE TO MODIFY LOCATION WITH META BIT = 1 + +;SYSSE5: MOVEI D,0 +; SMB D,@SETSLC +; EXCH T,@SETSLC +; SMB Q,@SETSLC +; JRST SYSSE6 + +SUBTTL MEMORY ERROR MESSAGES + +NXMTYP: MOVEI I,[ASCIZ /NON-EX MEM ERROR #/] + MOVEI TT,1 + JRST MEMTYP + +IFE KA10P,[ +BPFTYP: MOVEI I,[ASCIZ /PAGE FAIL ERROR #/] + MOVEI TT,2 + JRST MEMTYP +] ;IFE KA10P + +PARTYP: MOVEI I,[ASCIZ /PARITY ERROR #/] ;PARITY ERROR + MOVEI TT,0 +MEMTYP: PUSHJ P,SYSSP + MOVE A,PARERR(TT) + PUSHJ P,SYSOPT + MOVEI I,[ASCIZ /, PC = /] + PUSHJ P,SYSSP + MOVE A,PARPC(TT) + PUSHJ P,SYSFWP + MOVEI I,[ASCIZ /, JOB # /] + PUSHJ P,SYSSP + MOVE A,PARUSR(TT) + IDIVI A,LUBLK + PUSHJ P,SYSOPT + MOVEI I,[ASCIZ /, USR:/] + PUSHJ P,SYSSP + MOVE D,PARUSR(TT) + MOVE A,UNAME(D) + PUSHJ P,SYSSIX + PUSHJ P,STYOS + MOVE A,JNAME(D) + PUSHJ P,SYSSIX + JRST @.+1(TT) ;DISPATCH ON TYPE OF ERROR + PARTY2 ;PARITY + SYSTCR ;NXM +IFE KA10P,[ + BPFTY2 ;BPF + +BPFTY2: MOVEI I,[ASCIZ /, PFW = /] + PUSHJ P,SYSSP + MOVE A,BPFPFW + PUSHJ P,SYSFWP + JRST SYSTCR +] ;IFE KA10P + +PARTY2: PUSHJ P,SYSTCR +IFN KS10P,[ + MOVEI I,[ASCIZ /ERR ADDR = /] + PUSHJ P,SYSSP + MOVE T,PARERA ; Error address is all we collect on the KS. + PUSHJ P,SYSP + PUSHJ P,SYSCRF +] ;KS10P +IFN KL10P,[ + SKIPN PARRSN + JRST PARTP1 + MOVEI I,[ASCIZ /ERR ADDR = /] + PUSHJ P,SYSSP ;PAR ERR INT ALWAYS GIVES ERR ADDR + MOVE T,PARERA + JRST PARTP2 + +PARTP1: MOVEI I,[ASCIZ /PFW = /] + PUSHJ P,SYSSP ;PAR ERR TRAP GIVES PFW AND BAD DATA + MOVE T,PARPFW ;EVEN IF SCAN DOESN'T FIND PAR ERRS. + PUSHJ P,SYSP + MOVEI I,[ASCIZ /, BAD DATA = /] + PUSHJ P,SYSSP + MOVE T,PARWRD +PARTP2: PUSHJ P,SYSP + PUSHJ P,SYSCRF +] ;KL10P + SOSGE D,PARCNT + POPJ P, + JUMPE D,PARTP3 ;IF SCAN FOUND MORE THAT ONE PAR ERR, + ;PRINT AND'S AND OR'S OF DATA AND ADDRS. +IRP X,,[PARAAN,PARAOR,PARAND,PARIOR]Y,,[ADDR AND,ADDR IOR,DATA AND,DATA IOR] +IFE .IRPCNT&1, MOVEI I,[ASCIZ /Y = /] +.ELSE MOVEI I,[ASCIZ /, Y = /] + PUSHJ P,SYSSP + MOVE T,X + PUSHJ P,SYSP +IFN .IRPCNT&1, PUSHJ P,SYSCRF ;PRINT TWO ITEMS PER LINE. +TERMIN +PARTP3: MOVEI I,[ASCIZ /PARITY ERRORS: +/] + PUSHJ P,SYSSP +SYSPR1: PUSHJ P,STYOT ;TYPE TAB + MOVE A,PARADR(D) + PUSHJ P,SYSFWP + PUSHJ P,STYOT + MOVE A,PARCON(D) + PUSHJ P,SYSFWP + PUSHJ P,SYSCRF + SOJGE D,SYSPR1 + AOS D,PARCNT + MOVEI I,[ASCIZ/ .../] + CAIN D,MXPARS + PUSHJ P,SYSSP ;NOT ALL PARITY ERRORS WERE PRINTED + JRST SYSCRF + +SUBTTL LOGIN & MISCELLANEOUS MESSAGES + +SYSLGI: SKIPE SUPPLG + POPJ P, ;DON'T BOTHER PRINTING MESSAGE + HLRZ I,SLGIV+1 ;Message (CHUNAME, LOGIN, etc) + PUSHJ P,SYSSP + MOVEI TT,SLGIV ;.LOGIN + MOVE A,(TT) + CAMN A,[-1] + BUG + PUSHJ P,SYSG23 + SKIPE A,SLGIV+2 + PUSHJ P,SYSSIX + JRST SYSTCR + +SYSG23: PUSHJ P,SYSIXP + PUSHJ P,STYOS + HRRZ A,1(TT) ;PICK UP TTY NUM + JRST SYSOPT + +;PRINT A MESSAGE WHEN SOMEONE WRITES ON SYS. +SYSWRT: MOVE A,SWUNAM ;WRITE ON SYS DEVICE + PUSHJ P,SYSIXP + MOVE A,SWJNAM + PUSHJ P,SYSSIX + MOVE A,SWFN3 ;SNAME - SYS,SYS1, ... + PUSHJ P,SYSSIX + MOVE A,SWFN1 + PUSHJ P,SYSSIX + MOVE A,SWFN2 + PUSHJ P,SYSSIX + MOVE A,[SIXBIT /WRITE/] ;Assume luser was writing. + MOVE B,SWMOD ;Check opcode. + CAIN B,2 ;MLINK? + MOVE A,[SIXBIT /LINK/] ; Yup. + CAIN B,4 ;Maybe DELE/WO, RENAM/WO? + MOVE A,[SIXBIT /DELRNM/] ; Yah, hmmhmmm. +SYSWR3: PUSHJ P,SYSSIX + JRST SYSTCR + +SUBTTL DETERMINE AND PRINT THE DATE AND TIME + +EBLK +DATIME: JRST .+1 ;RH MODIFIED TO REFLECT PROGRESS +BBLK ;ROUTINE CALLED BY PUSHJ, + ;BIT SET EVERY SECOND FROM SUPCOP UNTIL + ;THE DATE IS KNOWN. + MOVSI T,40000 ;"MFD IN" BIT IN QMDRO + CONO PI,UTCOFF ;DISABLE INTERRUPTS + TDNE T,QMDRO ;SEE IF DIRECTORY IN + JRST UTCONJ ;NOT IN + ;MFD IN, GET CRUD FROM IT + MOVE A,QMDRO ;GET ORIGIN OF MFD + SKIPE B,MDYEAR(A) ;YEAR + MOVEM B,FYEAR + SKIPE C,MPDOFF(A) ;PDTIME OFFSET + MOVEM C,PDTIME + MOVEI C,DATIM0 + HRRM C,DATIME + JRST UTCONJ + +DATIM0: PUSHJ P,GLPDTM ;NOW SEE IF IT'S ALL THERE + JRST DATIM2 ;NOT ALL THERE, DOCUMENT WHAT'S MISSING + JRST DATIM6 ;ALL THERE, TYPE OUT AND CLEAR SUPCOR BIT + + ;NOT ALL THERE, DOCUMENT (TYPE OUT) WHAT IS MISSING + ;SHOULD NOT BE NECESSARY TO WARM UP TTY + +DATIM2: +IFN PDCLKP,[ + DATAI PDCLK,A ;SEE IF CLOCK ON + JUMPN A,DATIM3 ;JUMP IF CLOCK WINNING + MOVEI I,[ASCIZ /DECORIOLIS CLOCK HAS BEEN POWERED OFF, IF THE TIME +CANNOT BE DETERMINED FROM THE NETWORK, YOU MAY HAVE TO :PDSET +/] + MOVEI T,500. + SOJG T,. ;WAIT AND BE SURE + DATAI PDCLK,A ;GET DATAI AGAIN + JUMPN A,DATIM3 ;JUMP IF OK NOW + PUSHJ P,SYSSP ;COMPLAIN +] ;PDCLKP +IFN KS10P,[ + RDTIM A ; Clobbers B + TLC A,1729. ; "A most interesting number" + TLNN A,-1 ; If present, KS-10 clock still remembers the time. + JRST DATIM3 + MOVEI I,[ASCIZ /THE KS-10 CLOCK HAS BEEN RESET, IF THE TIME CANNOT +BE DETERMINED FROM THE NETWORK, YOU MAY HAVE TO :PDSET +/] + PUSHJ P,SYSSP ; Complain +] ;KS10P +DATIM8: +; HRROI T,CCTSS ;NOW PREPARE TO LOAD CTSS CALLER FROM SYS:@ CCTSS +; PUSHJ P,NUJBST ;DO A PSEUDO-CONTROL Z +; JRST DATIM7 +DATIM3: MOVEI C,0 ;COUNTER OF THINGS MISSING FROM MFD + MOVEI I,[ASCIZ /YEAR, /] + SKIPG FYEAR ;CHECK YEAR + PUSHJ P,[AOJA C,SYSSP] ;NOT IN, COMPLAIN +IFN PDCLKP\KS10P,[ + MOVEI I,[ASCIZ /PDTIME OFFSET, /] + SKIPN PDTIME + PUSHJ P,[AOJA C,SYSSP] ;PDTIME OFFSET NOT IN +] ;PDCLKP\KS10P + JUMPE C,DATIM4 ;SKIP FOLLOWING IF EVERYTHING ON DISK + MOVEI I,[ASCIZ /NOT ON DISK. +PLEASE SETLOC APPROPRIATELY. +/] + PUSHJ P,SYSSP +DATIM4: SKIPA T,[DATIM5];UPDATE DATIME TO WAIT FOR EVERYTHING TO BE THERE +DATIM7: MOVEI T,DATIM8 ;UPDATE DATIME TO WAIT FOR ABILITY TO DO + ; PSEUDO-CONTROL Z FOR CTSS CALLER + HRRM T,DATIME + POPJ P, + + ;WAIT FOR EVERYTHING TO BE THERE + ;THEN TYPE OUT "IT IS NOW...", ETC. + +DATIM5: PUSHJ P,GLPDTM ;CHECK IT + POPJ P, ;NOT ALL THERE YET + MOVEI T,DATIME+1 ;ALL THERE, RE-INITIALIZE DATIME + HRRM T,DATIME +DATIM6: MOVSI T,SCLDAT ;STOP CALLING DATIME EVERY SECOND + ANDCAM T,SUPCOP ;NOW THAT THE WORK IS DONE. + HRRZS TIMOFF ;START UP SLOW CLOCK REAL-TIME ROUTINE + SETZM RSWTIM ;Initialize the resource-warning timestamp. + PUSHJ P,WARMTT ;WARM UP TTY + PUSHJ P,RYEAR1 ;GET DAY OF WEEK IN RELEVANT FIELD OF E +SYSNWP: MOVEI I,[ASCIZ /IT IS NOW /] + PUSHJ P,SYSSP ;TYPE IT OUT + IDIVI A,SPD ;A HAS RESULT OF PUSHJ TO GLPDTM + PUSH P,A ;SAVE DAY OF YEAR + MOVE A,B ;GET # SECS SINCE MIDNIGHT IN A + IDIVI A,SPD/2 ;GET AM/PM BIT IN A, 12 HOUR TIME (SECS) IN B + PUSH P,[SIXBIT / AM PM/](A) ;REMEMBER WHAT HALF-DAY + CAIGE B,3600. ;USE 12:01 RATHER THAN 0:01 IN 12-HR TIME. + ADDI B,12.*3600. + PUSHJ P,RTIME ;CONVERT TIME TO SIXBIT + MOVE B,A + TLNN B,170000 ;IF LEADING DIGIT IS ZERO, + TLZ B,770000 ;THEN TURN IT INTO A BLANK + PUSHJ P,SYSTCD ;TYPE OUT TIME + POP P,B ;RESTORE AM OR PM WORD + PUSHJ P,SYS6 ;TYPE IT OUT + MOVE B,[SIXBIT / EST,/] + TLNE E,100000 ;DST BIT + HRLI B,(SIXBIT / ED/) ;DAYLIGHT SAVINGS TIME, TYPE OUT EDT INSTEAD OF EST + PUSHJ P,SYS6 ;TYPE IT OUT + PUSHJ P,STYOS ;TYPE A SPACE + LDB B,[320300,,E] ;GET DAY OF WEEK (0 => SUNDAY) + MOVE B,DOWTBL(B) ;MON, TUES, WEDNES, ETC. (IN SIXBIT) + PUSHJ P,SYS6 ;TYPE IT OUT + MOVEI I,[ASCIZ /DAY, /] ;FINISH ON DAY OF WEEK + PUSHJ P,SYSSP ;" " " + POP P,A ;RESTORE DAY OF YEAR + PUSHJ P,RDATE1 ;CALCULATE MONTH AND DAY + MOVE B,NMNTBL-1(B) ;GET SIXBIT FOR MONTH + PUSHJ P,SYS6 ;TYPE OUT MONTH + PUSHJ P,STYOS ;TYPE A SPACE + MOVE A,C ;GET DAY OF MONTH IN A + PUSHJ P,SYSDPT ;TYPE OUT IN DECIMAL + MOVEI T,", + PUSHJ P,STYO ;TYPE A COMMA + MOVEI A,(E) ;GET YEAR + PUSHJ P,SYSDPT ;TYPE IT OUT + JRST SYSCRF ;END WITH CRLF + + ;TABLE OF NAMES OF MONTHS (FIRST THREE LETTERS, IN SIXBIT) + +NMNTBL: MNIRP [SIXBIT /M/] + + ;TABLE OF SIXBIT NAMES FOR DAYS OF THE WEEK + ;(THE "DAY" ON THE END LEFT OFF) + +DOWTBL: IRPS D,,[SUN MON TUES WEDNES THURS FRI SATUR] + SIXBIT /D/ + TERMIN +IFN .-DOWTBL-7,.ERR BARF AT DOWTBL + +SUBTTL NETWORK UP/DOWN + +SYSNET: +IFE IMPP,JRST SCOR +IFN IMPP,[ + MOVE A,IMERCN ;Get error status + CAME A,[-1] ;--1 means IMP cycled by user + SKIPA I,[[ASCIZ /IMP CRASHED, STATUS=/]] + MOVEI I,[ASCIZ /IMP cycled by user at/] + PUSHJ P,SYSSP ;Print string + MOVE A,IMERCN ;Get IMP error code back + CAME A,[-1] + PUSHJ P,SYSFWP ;Print status if error + PUSHJ P,SYSTCR ;Time, CRLF + SETOM IMERCN ;Reset error status + MOVE A,LNETIM ;Last time net was initted + SUB A,TIME ;A will be positive if net was last + ADDI A,30.*30. ; initted less than 30 sec ago. + PUSH P,A ;Flag for SYSNT5. + means don't restart IMP + MOVNI A,2 ;Say we are coming up, but no PI action yet, + MOVEM A,IMPUP ; and prevent new net openers. IMPUP may + PUSHJ P,SYSNT5 ; not already be -1 if got here via LOCK/NET + JRST SCOR ;Reset net, then back to main loop + +;Reset net, and potentially restart IMP +; Try restarting if IMP ready and -1(P) is negative. +; +;IMPUP is -1 so no new opens can happen. + +SYSNT5: + ;PCLSR those users running in OPEN. + ; + MOVEI U,0 +IFN NCPP,[ + PUSHJ P,LSTSTP ;PCLSR all users in .OPEN + NETLST + MOVSI I,-IMPSTL +SYSNT2: SKIPL A,IMSOC1(I) + JRST SYSNT1 + HRRZS A + SKIPN UNAME(A) + JRST SYSNT1 + MOVE T,APRC(A) + TLNE T,BULGO ;Tree is being deleted anyway. + JRST SYSNT1 + PUSHJ P,IFSTOP ;Stop network user + PUSHJ P,CHSCAA + PUSHJ P,SYSNT3 ;Hack IOCHNM words of net user +SYSNT1: AOBJN I,SYSNT2 +];NCPP + + ;Disconnect all STYs from the network + ; + MOVEI I,NFSTTY+NSTTYS-1 +SYSNT6: + PUSHJ P,NSTYN0 + JFCL + CAILE I,NFSTTY + SOJA I,SYSNT6 + +IFN NCPP,[ + ;Clean up connections which were closing + ; + CONO PI,UTCOFF + MOVSI I,-IMPSTL +SYSNT7: SKIPL H,IMSOC1(I) + JRST SYSNT4 + PUSHJ P,IMPBRT ;RETURN BUFFER + TLNN H,200000 ;IN PROCESS OF CLOSING? + JRST SYSNT4 ;NO, IGNORE + SETZM IMSOC1(I) ;FLUSH SOCKET + SOS IMNCS ;DECREASE COUNT OF CLOSES IN PROCESS +SYSNT4: AOBJN I,SYSNT7 ;LOOP THRU ALL SOCKETS + SKIPE IMNCS ;SKIP IF 0 MORE CLOSES + BUG PAUSE,DEC,IMNCS,[NET CHANNELS NOT CLOSED YET] + CONO PI,UTCON +];NCPP + + ;Maybe try to bring the IMP up again + ; + MOVEI U,0 + SKIPG -1(P) ;If last time down was < half minute ago, + CALL IMPCKR ; or IMP ready line is not set, + JRST LSWCLR ; then don't try to bring it up again + PUSHJ P,IMPINI +IFN NCPP,PUSHJ P,LSWCLR ;Restart old network users + PUSHJ P,WARMTTY + MOVEI I,[ASCIZ /IMP up again./] + JRST SYSSTD ;Print and return + +IFN NCPP,[ +SYSNT3: HRRZ C,(R) + CAIL C,NETDUI + CAILE C,NETDBO + POPJ P, ;NOT A NETWORK CHANNEL + HLRE C,(R) ;SOCKET MAP INDEX + JUMPL C,CPOPJ + HRROS (R) ;SET LH OF IOCHNM TO -1 + HRRZ C,R + SUBI C,IOCHNM(A) + CAIL C,20 + POPJ P, ;ON IOPDL + MOVE C,CHNBIT(C) + AND C,MSKST2(A) + IORM C,IFPIR(A) ;INTERRUPT USER + POPJ P, +];NCPP +];IMPP + +;Try to bring IMP up if desirable +SYSIMU: +IFE IMPP,POPJ P, ;No IMP, no work +IFN IMPP,[ + SKIPGE IMPTCU ;Already trying to come up? + POPJ P, ;Yes, no meddling needed + CALL IMPCKR ;Check if IMP ready line is now + JRST [ SETZM IMPTCU ;IMP not ready, we are down and not trying + POPJ P, ] ; to come up. Give up now + PUSH P,[-1] ;Force SYSNT5 to try and restart IMP if called + SKIPGE IMPUP ;Do this only if imp is temporarily down. + PUSHJ P,SYSNT5 ;Reset world, restart IMP + JRST POP1J ;Clean up and exit +];IMPP + +; PUSHJ P,LSTSTP +; LIST ;WHERE LIST/ +;STOPS ALL JOBS ON THE LIST, AND PUT THEM ON OUR LSWPR. +;LIST SHOULD BE LINKED THROUGH THE RH, AND EACH WORD IN THE LIST SHOULD BE +;IN THE USER VAR BLOCK OF SOME JOB. THAT JOB IS CONSIDERED TO BE ON THE LIST. +;0 IN THE RH MEANS NIL. +LSTSTP: MOVE T,@(P) ;POINTER TO FIRST ELEMENT OF LIST + CONO PI,CLKOFF + MOVE T,(T) +LSTST1: HRRZS T + SKIPN A,T ;ADDRESS OF LSWB BLOCK + JRST CLKOJ1 + MOVEI A,-USRSTG(A) + IDIVI A,LUBLK + IMULI A,LUBLK ;USER INDEX + PUSH P,(T) + PUSHJ P,IFSTOP ;STOP USER, ADDING HIS USTP TO OUR LSWPR + POP P,T + JRST LSTST1 + SUBTTL SYSTEM JOB TYPE-OUT ROUTINES + +;PRINT "/ <@D> " IN OCTAL. +;USED BY SYSSET. CLOBBERS A,B,T. +SYSSCT: HRRZS A + PUSHJ P,SYSOPT + MOVEI T,"/ + PUSHJ P,STYO + PUSHJ P,STYOT ;TAB + MOVE A,(D) ;GET CURRENT VALUE + PUSHJ P,SYSFWP + PUSHJ P,STYOT + MOVE A,C ;GET NEW VALUE + JRST SYSFWP + +;STRING <- I, SPACE, TIME AND CRLF. +;CLOBBERS A THRU E AND T. +SYSSTD: PUSHJ P,SYSSP + +;SPACE, TIME AND CRLF. +;CLOBBERS A THRU E AND T. +SYSTCR: PUSHJ P,SYSTPT + +;TYPE A CRLF. CLOBBERS T. +SYSCRF: SOS CTLCNT ;Countdown number of lines printed. + MOVEI T,15 + PUSHJ P,STYO + MOVEI T,12 + JRST STYO + +SYSTPT: PUSHJ P,STYOS ;TYPE SPACE, TIME + CONSZ PI,200 ;IF IN BUGDD0, MUSTN'T CALL GLPDTM + PUSHJ P,GLPDTM + POPJ P, ;TIME NOT KNOWN + IDIVI A,SPD + PUSHJ P,RTIME ;CONVERT TO SIXBIT. + MOVE B,A ;DROP INTO SYSTCD + +SYSTCD: LDB A,[301400,,B] + PUSHJ P,SYSTWR + LDB A,[141400,,B] + PUSHJ P,SYSTWR + MOVE I,[140600,,B] + JRST SYSIX2 + +;PREPARE FOR TYPING OUT A MESSAGE ON THE CONSOLE TTY. CALL HERE BEFORE +;STARTING TO TYPE A LINE, IF THERE IS A CHANCE THAT SYS JOB MIGHT JUST +;BE STARTING TO TYPE AFTER A PERIOD OF SILENCE. +WARMTTY:PUSHJ P,SYSCOP ;GET SYSTEM TTY READY TO USE + .IOT STYOC,[^P] ;ADVANCE TO FRESH LINE + .IOT STYOC,["A] +WARMT2: +IFN 1, POPJ P, +.ELSE [ MOVE T,SYSCN + MOVE T,TTLTM(T) ;DON'T DO THIS IF THERE'S BEEN ACTIVITY IN 2 MINUTES. + ADDI T,115.*30. + CAML T,TIME + POPJ P, + PUSH P,[[MOVEI T,^H + JRST WARMT1]] + SKIPA T,[175] ;WARM UP TELETYPE (ONLY ON AI-KA FOR NOW) +];END .ELSE +DINGTTY: SKIPA T,[^G] ;DING DING +WARMT1: PUSHJ P,.+1 + PUSHJ P,.+1 + JRST STYO + +;ROUTINE TO "OPEN" A CHANNEL TO THE SYSTEM CONSOLE +;IT'S DONE THIS WAY SO THAT THE CONSOLE CAN STILL BE +;USED AS A USER CONSOLE WHEN NECESSARY. SYSTEM JOB +;MESSAGES WILL JUST COME OUT FROM TIME TO TIME. + +SYSCOP: HRLZ T,SYSCN ;FAKE UP AN IOCHNM WORD + ADD T,[%TJDIS+%TJMOR,,TYODN] + SKIPGE SYSCN + MOVEI T,NLODN ;IF NO SYS TTY AVAIL, USE NUL DEVICE + MOVEM T,IOCHNM+STYOC + POPJ P, + +;TYPE OUT THE SIXBIT WORD IN B, QUIT WHEN WHAT IS LEFT IS BLANK +SYS6: JUMPE B,CPOPJ ;RETURN WHEN NOTHING LEFT + MOVEI A,0 ;INITIALIZE FOR LSH + LSHC A,6 ;SHIFT A CHARACTER IN + MOVEI T,40(A) ;CONVERT TO SIXBIT AND GET IN T + PUSHJ P,STYO ;TYPE OUT THE CHARACTER + JRST SYS6 ;LOOP BACK FOR NEXT CHARACTER + +;PRINT A MESSAGE ON ALL FREE CONSOLES. 40 SET IN LH(I) => IT IS ADDR OF ROUTINE; +;ELSE IT IS ADDR OF AN ASCIZ STRING TO BE TYPED FOLLOWED BY THE TIME AND A CRLF. +SYALCP: TLNN I,40 + HRLI I,440700 ;SYSTEM ALL CONSOLES PRINT + MOVEI A,0 +SYALC1: PUSHJ P,SYSTSU + AOJA A,SYALC3 + TLNE I,40 + JRST SYALC5 + MOVE Q,I ;SO NOT TO MUNG I UNTIL END +SYALC2: ILDB E,Q + JUMPE E,SYALC4 ;JUMP IF DONE + .IOT STYOC,E ;COPY CHARACTER + JRST SYALC2 ;GO GET NEXT CHARACTER + +SYALC5: PUSH P,I + PUSH P,A + PUSHJ P,(I) + POP P,A + POP P,I +SYALC6: MOVSI E,%TACFM + IORM E,TTYSTA(A) ;DONT NEED CONSOLE FREE MSG ANY MORE + AOS A ;INCREMENT CONSOLE NUMBER +SYALC3: CAIGE A,NCT+IFN N11TYS,[1-N11TYS] ;IF MORE CONSOLES LEFT, + JRST SYALC1 ;THEN PRINT OUT ON NEXT ONE + JRST SYSCOP ;FINALLY RE-OPEN SYSTEM CONSOLE. + +SYALC4: PUSH P,[SYALC6] ;PUT TIME AT END OF MESSAGE + PUSH P,A ;IF WE KNOW WHAT TIME IT IS + PUSH P,B + PUSHJ P,GLPDTM + JRST POPBAJ + PUSH P,I + IRPC A,,[ AT] + .IOT STYOC,["A] ;PUT TIME IN UP/DOWN MESSAGES + TERMIN + PUSHJ P,SYSTPT + POP P,I + JRST POPBAJ + +SYSTSU: CONO PI,TTYOFF + MOVE T,TTYSTA(A) + TLZN T,%TACFM + JRST TTYONJ ;IN USE OR WILL GET CONSOLE FREE MSG => DON'T HACK IT + MOVEM T,TTYSTA(A) + CONO PI,TTYON + AOS (P) ;TTY NEEDS HACKING, SO SKIP. + HRLZ T,A + ADD T,[%TJDIS+%TJMOR,,TYODN] + MOVEM T,IOCHNM+STYOC ;"OPEN" THE CHANNEL. +SYSTS1: MOVE T,TTYOPT(A) + TLNN T,%TOIML + TLNN T,%TOMVU + POPJ P, ;IMLAC OR PRINTING TTY, DON'T CLEAR. + MOVEI T,^P + PUSHJ P,STYO + MOVEI T,"C + JRST STYO + + ;SYSTEM JOB RADIX PRINT-OUT ROUTINES + ;FULL WORD (TWO HALFWORD) OCTAL: +SYSFWP: TLNN A,-1 ;IF LH=0, + JRST SYSOPT ;THEN PRINT ONLY RH + LSHC A,-18. + HLLM B,(P) + PUSHJ P,SYSOPT + HLRZ A,(P) + MOVEI T,", ;",," BETWEEN HALFWORDS + PUSHJ P,STYO + PUSHJ P,STYO + + ;OCTAL PRINTOUT, NO LEADING ZEROS, HALFWORD MAXIMUM +SYSOPT: IDIVI A,10 + JUMPE A,SYSRP1 + HRLM B,(P) + PUSHJ P,SYSOPT +SYSRP2: HLRZ B,(P) ;ENTRY POINT FROM DECIMAL TYPEOUT ROUTINE +SYSRP1: MOVEI T,"0(B) ;" " " + JRST STYO + + ;DECIMAL PRINTOUT, COMMAS EVERY 3 DIGITS, FULLWORD MAXIMUM +SYSDPC: MOVE 0,A ;ROUTINE EXPECTS ARGUMENT IN A, CLOBBERS 0, A(=0+1), B(=A+1) +SYSDP5: IDIVI 0,1000. ;GET LEAST SIGNIFICANT 3 DIGITS IN A + JUMPE 0,SYSDPT ;PRINT HIGH ORDER DIGITS WITHOUT LEADING ZEROES + HRLM A,(P) + PUSHJ P,SYSDP5 + HLRZ A,(P) + MOVEI T,", ;SINCE 3*N DIGITS LEFT TO BE TYPED, N>0, + PUSHJ P,STYO ;PRINT OUT A COMMA + MOVEI T,3 ;NUMBER OF DIGITS TO PRINT OUT + ;ROUTINE TO PRINT OUT AS MANY DECIMAL DIGITS AS SPECIFIED IN T +SYSLZP: IDIVI A,10. + SOJLE T,SYSRP1 + HRLM B,(P) + PUSHJ P,SYSLZP + JRST SYSRP2 + +;PRINT NUMBER IN A IN DECIMAL; CLOBBERS B, T. +SYSDPT: IDIVI A,10. + JUMPE A,SYSRP1 + HRLM B,(P) + PUSHJ P,SYSDPT + JRST SYSRP2 + +STYOQ: MOVEI T,"? ;TYPE OUT "?" + JRST STYO + +STYOT: SKIPA T,[11] ;TAB +STYOS: MOVEI T,40 ;TYPE OUT A SPACE +STYO: CONSO PI,200 ;PI ON? (SYSTEM UP) + JRST STYO1 + .IOT STYOC,T + POPJ P, + +;TYPE OUT DIRECTLY WHILE SYSTEM IS NOT RUNNING +STYO1: HRLM T,(P) + CAIN T,15 + SETZM T00POS + AOS T,T00POS + CAIL T,75. + PUSHJ P,SYSCRF + HLRZ T,(P) +IFN KA10P,[ + CONSZ TTY,20 + JRST .-1 + DATAO TTY,T +] ;KA10P +IFN KL10P,[ + SETZM DTEFLG + MOVEM T,DTECMD + CONO DTE,%DBL11 + SKIPN DTEFLG + JRST .-1 +] ;KL10P +IFN KS10P,[ + ANDI T,177 ; ASCII for the 8080 + IORI T,400 ; Means a character is present + MOVEM T,8CTYOT + CONI T + IORI T,80INT + CONO (T) ; punch 8080 + SKIPE 8CTYOT ; wait for completion + JRST .-1 + HLRZ T,(P) ; God knows who might look at T... +] ;KS10P + POPJ P, + +;PRINT WORD IN I AS 12. OCTAL DIGITS. CLOBBERS J,T. +SYSP: MOVE J,[440300,,I] + MOVE I,T +SYSP1: ILDB T,J + ADDI T,"0 + PUSHJ P,STYO + TLNE J,770000 + JRST SYSP1 + POPJ P, + +SYSSP: HRLI I,440700 ;ENTRY TO TYPE C(I) AS A POINTER TO ASCIZ +SYSSP2: ILDB T,I + JUMPE T,CPOPJ + PUSHJ P,STYO + JRST SYSSP2 + +SYSTWR: LSH A,30-18. + ADDI A,(SIXBIT / :/) + MOVE I,[220600,,A] + JRST SYSIX2 +SYSSIX: PUSHJ P,STYOS ;TYPE A SPACE AND FALL IN +SYSIXP: MOVE I,[440600,,A] ;ENTRY TO TYPE OUT C(A) AS SIXBIT +SYSIX2: ILDB T,I + ADDI T,40 + PUSHJ P,STYO + TLNN I,770000 + POPJ P, + JRST SYSIX2 diff --git a/src/system/t20mac.1 b/src/system/t20mac.1 new file mode 100755 index 00000000..b8616e2a --- /dev/null +++ b/src/system/t20mac.1 @@ -0,0 +1,345 @@ +;Random useful coding macros. GZ@OZ developed MACSYM.MID based on the +;Twenex monitor macro collection MACSYM.MAC - this is a non-Twenex-specific +;subset of that. + +;Stuff supported (will add more stuff as need arises): +; FLD(VAL,MSK) & BIT(n) & POINT SIZE,ADDR,OFFSET +; MOVX AC,MASK & TXxx AC,MASK & JXx AC,MASK,ADDR & LOAD/STOR AC,MASK,ADDR +; DO./ENDDO. macros (and related stuff) +; IFxxx/ANxxx macros +; SAVEACS [A,B,C,D] & SAVE. [LOC,LOC,LOC] + + +.KILL ..XX,..TXZ,..TXO,..TXC,..X0,..X1,..X2,..X3,TOP. +.XCREF ..XX,..TXZ,..TXO,..TXC,..X0,..X1,..X2,..X3 +.XCREF ..DX,..IX,..EX,.SAVX1,.SAVX2 + +IF2,.INEOF ;Don't bother if no code + +;.NSTGW ;No storage words in this part + +DEFINE FLD (VAL,MASK) +<.DPB ,<.BP ,>,0>TERMIN + +DEFINE BIT (N) +<1_<35.->>TERMIN + +DEFINE POINT SIZE=7,ADDR=0,COUNT=0 +RADIX 8+2 +..X1==SIZE +..X2==COUNT +RADIX 8 +..XX==<..X2-1>/<36./..X1> +..X2==..X2-..XX*<36./..X1> +<<<36.-<..X1*..X2>>_30.>+<..X1_24.>++..X1> +TERMIN + +;MOVX - LOAD AC WITH CONSTANT + +DEFINE MOVX AC,#MSK + IFE <-1,,0>&MSK,[MOVEI AC,MSK] + .ELSE [IFE <0,,-1>&MSK,[MOVSI AC,(MSK)] + .ELSE [IFE <<-1,,0>&MSK>-<-1,,0>,[HRROI AC,MSK] + .ELSE [IFE <<0,,-1>&MSK>-<0,,-1>,[HRLOI AC,(MSK&.LHALF)] + .ELSE [MOVE AC,[MSK]]]]] +TERMIN + +;TX - TEST MASK + +IRP OP,,[N,NA,OE,ON,OA,ZE,ZN,ZA,CE,CN,CA] + DEFINE TX!OP AC,#MSK + IFE <-1,,0>&MSK,[TR!OP AC,MSK] + .ELSE [IFE <0,,-1>&MSK,[TL!OP AC,(MSK)] + .ELSE [TD!OP AC,[MSK]]] + TERMIN +TERMIN + +IRP OP,,[N,E] + DEFINE TXN!OP AC,#MSK + IFE <-1,,0>&MSK,[TRN!OP AC,MSK] + .ELSE [IFE <0,,-1>&MSK,[TLN!OP AC,(MSK)] + .ELSE [IFE MSK+1,[CAI!OP AC,0] + .ELSE [TDN!OP AC,[MSK]]]] + TERMIN +TERMIN + +..TXZ==ANDI +..TXO==ORCMI +..TXC==EQVI +IRP OP,,[Z,O,C] + DEFINE TX!OP AC,#MSK + IFE <-1,,0>&MSK,[TR!OP AC,MSK] + .ELSE [IFE <0,,-1>&MSK,[TL!OP AC,(MSK)] + .ELSE [IFE <<-1,,0>&MSK>-<-1,,0>,[..TX!OP AC,-1#MSK] + .ELSE [TD!OP AC,[MSK]]]] + TERMIN +TERMIN + +EQUALS IORX,TXO +EQUALS XORX,TXC + +DEFINE ANDX AC,#MSK +TXZ AC,-1#MSK +TERMIN + + SUBTTL JX -- JUMP ON MASK + +;JXE -- JUMP IF MASKED BITS ARE EQUAL TO 0 +;JXN -- JUMP IF MASKED BITS ARE NOT EQUAL TO 0 +;JXO -- JUMP IF MASKED BITS ARE ALL ONES +;JXF -- JUMP IF MASKED BITS ARE NOT ALL ONES (FALSE) + +DEFINE JXE AC,#MSK,?ADR + IFE MSK-.MINFI,[JUMPGE AC,ADR] + .ELSE [IFE MSK+1,[JUMPE AC,ADR] + .ELSE [TXNN AC,MSK + JRST ADR]] +TERMIN + +DEFINE JXN AC,#MSK,?ADR + IFE MSK-.MINFI,[JUMPL AC,ADR] + .ELSE [IFE MSK+1,[JUMPN AC,ADR] + .ELSE [TXNE AC,MSK + JRST ADR]] +TERMIN + +DEFINE JXO AC,#MSK,?ADR + IFE <.LZ MSK,>+<.TZ MSK,>-35.,[JXN AC,MSK,ADR] + .ELSE [TXC AC,MSK + TXCN AC,MSK + JRST ADR] +TERMIN + +DEFINE JXF AC,#MSK,?ADR +IFE <.LZ MSK,>+<.TZ MSK,>-35.,[JXE AC,MSK,ADR] +.ELSE [TXC AC,MSK + TXCE AC,MSK + JRST ADR] +TERMIN + +;LOAD, STOR +DEFINE LOAD AC,#MSK,?LOCN + IFE MSK+1,[MOVE AC,LOCN] + .ELSE [IFE MSK-777777,[HRRZ AC,LOCN] + .ELSE [IFE MSK-<-1,,0>,[HLRZ AC,LOCN] + .ELSE [LDB AC,[.BP MSK,LOCN]]]] +TERMIN + +DEFINE STOR AC,#MSK,?LOCN + IFE MSK+1,[MOVEM AC,LOCN] + .ELSE [IFE MSK-777777,[HRRM AC,LOCN] + .ELSE [IFE MSK-<-1,,0>,[HRLM AC,LOCN] + .ELSE [DPB AC,[.BP MSK,LOCN]]]] +TERMIN + + SUBTTL BLOCK MACROS + +;MACROS TO PROVIDE SOME BLOCK HANDLING OF CODE + +;DO. - LOOP STRUCTURE, DECLARES TOP OF LOOP +; LOOP. - JUMPS TO TOP OF LOOP +; EXIT. - EXITS LOOP +; TOP. - TAG AT TOP OF LOOP FOR JUMPS, E.G. SOJG T4,TOP. +; ENDLP. - TAG AT END OF LOOP FOR JUMPS, E.G. SOJL T4,ENDLP. + +DEFINE DO. + ..DX +TERMIN + +DEFINE ..DX \%TGE,%SV1,%SV2,%SV3 + EQUALS %SV1,TOP. ? EQUALS %SV2,ENDDO. ? EQUALS %SV3,ENDLP. + .KILL %SV1 + TOP.==. + DEFINE ENDDO. + %TGE::EQUALS TOP.,%SV1 ? EQUALS ENDDO.,%SV2 ? EQUALS ENDLP.,%SV3 + .KILL %TGE + TERMIN + DEFINE ENDLP. +%TGE!!TERMIN +TERMIN + +DEFINE ENDDO. +.ERR ENDDO. outside loop +TERMIN +DEFINE ENDLP. +.ERR ENDLP. outside loop +TERMIN +TOP.==-1 + +DEFINE OD. +ENDDO.!TERMIN + +DEFINE LOOP. +JRST TOP.!TERMIN + +DEFINE EXIT. +JRST ENDLP.!TERMIN + + +;Conditionals + +DEFINE IFSKP. +..IX [JRST ] +TERMIN + +DEFINE IFNSK. +TRNA + ..IX [JRST ] +TERMIN + +DEFINE IFXN. AC,#MASK + IFE 1_35.-MASK,..IX [JUMPGE AC,] + .ELSE [IFE MASK+1,..IX [JUMPE AC,] + .ELSE [TXNN AC,MASK + ..IX [JRST ] + ]] +TERMIN + +DEFINE IFXE. AC,#MASK + IFE 1_35.-MASK,..IX [JUMPL AC,] + .ELSE [IFE MASK+1,..IX [JUMPN AC,] + .ELSE [TXNE AC,MASK + ..IX [JRST ] + ]] +TERMIN + +DEFINE IFE. AC +..IX [JUMPN AC,] +TERMIN + +DEFINE IFN. AC +..IX [JUMPE AC,] +TERMIN + +DEFINE IFG. AC +..IX [JUMPLE AC,] +TERMIN + +DEFINE IFGE. AC +..IX [JUMPL AC,] +TERMIN + +DEFINE IFLE. AC +..IX [JUMPG AC,] +TERMIN + +DEFINE IFL. AC +..IX [JUMPGE AC,] +TERMIN + +DEFINE ..IX OP,\%TAG,%SV1,%SV2 + OP!%TAG + EQUALS %SV1,..TG ? EQUALS %SV2,ENDIF. + DEFINE ..TG LBL + %TAG!!LBL!TERMIN + DEFINE ENDIF. + ..TG [::] + .KILL ..TG + EQUALS ..TG,%SV1 ? EQUALS ENDIF.,%SV2 + TERMIN +TERMIN + +DEFINE ELSE. +..EX +TERMIN + +DEFINE ..EX \%TAG + JRST %TAG + ..TG [::] + DEFINE ..TG LBL + %TAG!!LBL!TERMIN +TERMIN + +DEFINE ..TG LBL + .ERR Conditional construct outside a conditional +TERMIN + +DEFINE ENDIF. + .ERR ENDIF. outside a conditional +TERMIN + + +;GENERAL CASES WITHIN CONDITIONALS + +DEFINE ANSKP. + JRST ..TG +TERMIN + +DEFINE ANNSK. + TRNA + JRST ..TG +TERMIN + +DEFINE ANDXN. AC,#MASK +IFE 1_35.-MASK,JUMPGE AC,..TG +.ELSE [IFE MASK+1,JUMPE AC,..TG + .ELSE [TXNN AC,MASK + JRST ..TG + ]] +TERMIN + +DEFINE ANDXE. AC,#MASK +IFE 1_35.-MASK,JUMPL AC,..TG +.ELSE [IFE MASK+1,JUMPN AC,..TG + .ELSE [TXNE AC,MASK + JRST ..TG + ]] +TERMIN + +DEFINE ANDE. AC + JUMPN AC,..TG +TERMIN + +DEFINE ANDN. AC + JUMPE AC,..TG +TERMIN + +DEFINE ANDG. AC + JUMPLE AC,..TG +TERMIN + +DEFINE ANDGE. AC + JUMPL AC,..TG +TERMIN + +DEFINE ANDLE. AC + JUMPG AC,..TG +TERMIN + +DEFINE ANDL. AC + JUMPGE AC,..TG +TERMIN + + + +; SAVEAC [A,B,C] +; Supports +1/+2 returns. +; Unlike macro version, supports arbitrary locations (not just AC's) +; and doesn't clobber AC16. Assumes stack in P, though. + +DEFINE SAVEAC ACS + IRP AC,,[ACS] + PUSH P,AC + ..XX==.IRPCNT + TERMIN + .SAVX1 ..XX+1,[ACS] +TERMIN + +EQUALS SAVE.,SAVEAC ;Not in MACRO version... + +DEFINE .SAVX1 #N#,ACS + PUSH P,[[CAIA + AOS -N(P) + .SAVX2 [ACS] + POPJ P, + ]] +TERMIN + +DEFINE .SAVX2 ACS + IRP AC,REST,[ACS] + .SAVX2 [REST] + POP P,AC + .ISTOP + TERMIN +TERMIN + diff --git a/src/system/t300.defs7 b/src/system/t300.defs7 new file mode 100755 index 00000000..5819e4d5 --- /dev/null +++ b/src/system/t300.defs7 @@ -0,0 +1,92 @@ +.AUXIL + +;ALLOW USER TO USE SYMBOLS IN OTHER WAYS IF HE WISHES. +;BUT NORMALLY, DEFSYM FOO==BAR DOES FOO==BAR WITH ERROR CHECK. + +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ + $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` +] +.ISTOP +TERMIN TERMIN + +IFLE .MLLIT,.ERR .MLLIT MUST BE 1; SETTING IT TO 1. +.MLLIT==1 +$$TEMP==1 +];IF Not DEFined DEFSYM +.ELSE $$TEMP==0 + +;DISK PHYSICAL PARAMETERS (CENTURY DATA T-300 AND 2561 CONTROLLER) +;SINCE WE HAVE ALSO AN RH10 CONTROLLER, THESE ARE SUFFIXED WITH A 1 + +DEFSYM NCYLS1==812. ;# CYLINDERS NORMALLY USED +DEFSYM XCYLS1==815.-NCYLS1 ;# CYLINDERS FOR SPARES, HACKS, ETC. +DEFSYM NHEDS1==19. ;# TRACKS/CYLINDER +DEFSYM NSECS1==32. ;# SECTORS/TRACK (256. 16-BIT WORDS) +DEFSYM SECBL1==12. ;# SECTORS/BLOCK +DEFSYM NBLKC1==NHEDS1*NSECS1/SECBL1 ;# BLOCKS/CYLINDER +DEFSYM NBLKS1==NCYLS1*NBLKC1 ;# BLOCKS NORMALLY USED +DEFSYM XBLKS1==XCYLS1*NBLKC1 ;# BLOCKS FOR HACKS +DEFSYM TBLKS1==NBLKS1+XBLKS1 ;TOTAL BLOCKS + +DEFSYM NTUTB1==4 ;4 BLOCKS PER TUT HERE +DEFSYM TUTBL1==MFDBLK-NTUTB1 ;TUT ALSO STARTS AT A DIFFERENT PLACE + +;TAKE DECADE FROM RH1O DEFS +;DEFSYM DECADE==NBLKSC ;NUMBER OF BLOCKS TO ALLOCATE AT A TIME +; ;QSWAPA AND QLASTB MUST BE MULTIPLES OF THIS. +; ;DECADE SIZE = CYLINDER SIZE FOR KLFEDR'S SAKE + +;10/11 COMMUNICATION AREA IS 14. WORDS STARTING 48. WORDS INTO THE 64.-WORD DL10 AREA + +DEFSYM DSCCHK=DL10AR+60 ;MUST BE 2561 OCTAL +DEFSYM DSCREQ=DL10AR+61 ;SET NON-ZERO BY 10 TO SIGNAL REQUEST TO 11 +DEFSYM DSCDON=DL10AR+62 ;SET NON-ZERO BY 11 TO SIGNAL DONE TO 10 +DEFSYM DSCFLT=DL10AR+63 ;0 NO FAULT +DEFSYM %DFRST==100000 ;POWER CYCLED OR BROKEN, SO CONTROLLER WAS RESET +DEFSYM %DFCQE==10000 ;CONSISTENCY ERROR IN COMMAND QUEUE +DEFSYM %DFNXM==4000 ;NXM ERROR IN COMMAND QUEUE +DEFSYM %DFPAR==2000 ;PARITY ERROR IN COMMAND QUEUE + ; IF ONE OF THESE BITS IS ON, BITS 1-0 AND DSCSTS + ; ARE THE ERROR ADDRESS + ;BITS 7-0 SYSTEM FAULT CODE IF LEFT BYTE IS ZERO + ; SEE THE 2561 OEM MANUAL FOR MEANING OF FAULT CODES +DEFSYM DSCSTS=DL10AR+64 ;STATUS BITS AS FOLLOWS +DEFSYM %DSRTR==100000 ;COMMAND WAS RETRIED +DEFSYM %DSECH==40000 ;UNCORRECTABLE DATA ERROR (ECC HARD) +DEFSYM %DSECC==20000 ;CORRECTED DATA ERROR +DEFSYM %DSIDE==10000 ;ID ERROR +DEFSYM %DSHCE==4000 ;ADDRESS ERROR (HEADER COMPARE ERROR) +DEFSYM %DSPRT==2000 ;WRITE-PROTECT STATUS OF SECTOR (ABORTS WRITE COMMAND) +DEFSYM %DSALT==1000 ;ALTERNATE-SECTOR STATUS (ABORTS READ, WRITE, AND CHECK) +DEFSYM %DSOVR==400 ;FIFO OVER-RUN, NOT CORRECTED BY 1 RETRY +DEFSYM %DSSKE==200 ;SEEK ERROR FROM DRIVE +DEFSYM %DSOFL==100 ;DRIVE OFF-LINE OR FAULT +DEFSYM %DSFLT==20 ;DRIVE FAULT +DEFSYM %DSNXM==10 ;NXM ON PDP11 MEMORY +DEFSYM %DSPAR==4 ;PARITY ERROR IN PDP11 MEMORY +DEFSYM %DSSFL==2 ;SYSTEM FAULT, SEE LOW BYTE OF DSCFLT +DEFSYM %DSWLK==1 ;DRIVE WRITE-LOCKED, WRITE ABORTED + +DEFSYM DSCCMD=DL10AR+65 ;COMMAND CODE AS FOLLOWS +DEFSYM %DMSNS==2 ;SENSE DRIVE STATE. DSCSTS GETS CODE FOR DRIVE TYPE IN + ; BITS 14-8 (10 FOR T-300), AND %DSWLK, %DSFLT, %DSOFL, %DSSKE +DEFSYM %DMTST==3 ;TEST SPECIFIED DRIVE (RUNS DIAGNOSTICS) +DEFSYM %DMREC==4 ;RECALIBRATE +DEFSYM %DMSEK==5 ;SEEK +DEFSYM %DMWRT==6 ;WRITE DATA +DEFSYM %DMRED==20 ;READ DATA. ADD 1-10 FOR VARIOUS RECOVERY FEATURES AS + ; DOCUMENTED IN THE 2561 OEM MANUAL. + +DEFSYM DSCDRV=DL10AR+66 ;DRIVE NUMBER (0 IS FIRST DRIVE ON 11) +DEFSYM DSCCYL=DL10AR+67 ;CYLINDER NUMBER +DEFSYM DSCHED=DL10AR+70 ;HEAD NUMBER +DEFSYM DSCSEC=DL10AR+71 ;SECTOR NUMBER +DEFSYM DSCPNT=DL10AR+72 ;4 12-BIT BYTE POINTERS TO DATA TO TRANSFER + +IFN $$TEMP,EXPUNG DEFSYM diff --git a/src/system/tcp.275 b/src/system/tcp.275 new file mode 100755 index 00000000..51d3b16e --- /dev/null +++ b/src/system/tcp.275 @@ -0,0 +1,3629 @@ +; This file holds the modules for TCP. +comment | STUFF TO DO + +Incoming ACKs should prevent retrans from aborting connection, since +clearly it is still alive, just doesn't have room for our stuff (which +is possibly overflowing its window). + +Note Clark suggs on windowing/ACKing. + If input data seg doesnt have PUSH, don't send ACK, but set + a timeout for sending ACK. Send ACK when: + PUSH is seen + outgoing seg forced out (new or retrans) + timed out + +Output buffering stinks. If can't send buff due to too many segs, +then should be able to keep adding to present segment. + +Provide way for output IOT to specify URGENT, and +Handle URGENT when received on input. + +| + +SUBTTL TCP definitions + +%WYTCP==:7 ; Move to BITS later + +%MOD32==:740000 ; LH mask used for mod 32 arithmetic +%TCPMI==:5 ; Max # segments in input queue per connection +%TCPMO==:5 ; Max # segments in output queue per connection +%TCPDS==:536. ; Default max # bytes per segment (when no + ; knowledge of receiving host) +%TCPMS==:2048.-40. ; Maximum possible segment size we can support + ; This must be 7777 (octal) or less. +%TCPMB==:%TCPMI*%TCPMS ; Max # bytes of data in queue (a bit fictional) +%TCPMR==:20. ; Max # retransmit retries allowed +%TCPMQ==:20 ; Max # pending RFCs allowed +%TCPMP==:777 ; Max port # allowed for pending-RFC (SYN) conns + ; Note pending-RFCs used ONLY for job startups, + ; SYNs are not queued in general. + +; Defintions of TCP Segment Header fields. +%TCPHL==:5 ; # of 32-bit words in fixed part of TCP header + +TH%SRC==:777774,, ; 0 Source Port +TH%DST==: 3,,777760 ; 0 Destination Port +TH%SEQ==:777777,,777760 ; 1 Sequence Number +TH%ACK==:777777,,777760 ; 2 Acknowledgement Number +TH%THL==:740000,, ; 3 Data Offset (TCP Header Length in 32-bit wds) +TH%RES==: 37400,, ; 3 Reserved (should be 0) +TH%CTL==: 374,, ; 3 Control bits +TH%WND==: 3,,777760 ; 3 Window +TH%CKS==:777774,, ; 4 Checksum +TH%UP==: 3,,777760 ; 4 Urgent Pointer + ; 5 Start of Options/Data + +TH$SRC==:<.BP TH%SRC,0> +TH$DST==:<.BP TH%DST,0 > +TH$SEQ==:<.BP TH%SEQ,1> +TH$ACK==:<.BP TH%ACK,2> +TH$THL==:<.BP TH%THL,3> +TH$RES==:<.BP TH%RES,3> +TH$CTL==:<.BP TH%CTL,3> +TH$WND==:<.BP TH%WND,3> +TH$CKS==:<.BP TH%CKS,4> +TH$UP==: <.BP TH%UP, 4> +TH$OPT==:<441000,,5> ; An ILDB-type pointer to start of options. + + ; Control bit definitions (as located in full word) +TC%URG==:<200,,> ; Urgent Pointer significant +TC%ACK==:<100,,> ; Ack field significant +TC%PSH==:< 40,,> ; Push Function +TC%RST==:< 20,,> ; Reset connection +TC%SYN==:< 10,,> ; Synchronize sequence numbers +TC%FIN==:< 4,,> ; Finalize - no more data from sender + +; TCP Connection tables, normally indexed by I +; These correspond to what the TCP document (RFC-793) calls +; the "Transmission Control Block" parameters. +; A TCB is "in use" if either XBUSER or XBSTAT is non-zero. +; XBUSER is set if a user job has channels associated with the TCB. +; XBSTAT is set if TCP is dealing with the TCB. +; PI level will never touch any TCBs which have a zero XBSTAT, so it is +; safe for the MP level to hack a zero-XBSTAT TCB without using NETOFF. + +IFNDEF XBL,XBL==10. ; Allow this many TCP connections for now. + +EBLK ; General variables + +XBUSER: BLOCK XBL ; RH User index + XB%STY==:<770000,,> ; TTY # of STY connected to (0 if none) + XB%ICH==:<007700,,> ; Input channel #+1 (77=IOPUSHed) + XB%OCH==:<000077,,> ; Output channel #+1 (77=IOPUSHed) + XB$STY==:<.BP XB%STY,XBUSER> + XB$ICH==:<.BP XB%ICH,XBUSER> + XB$OCH==:<.BP XB%OCH,XBUSER> +XBSTAT: BLOCK XBL ; ,, + ; Connection flags (internal to ITS) + %XBMPL==:SETZ ; Current output segment locked at MP level (IOT) + ; This must be sign bit for SGNSET/PCLSR to work. + %XBCTL==:<374,,> ; Array of output request bits + IFN %XBCTL-TH%CTL,.ERR %XBCTL flags must be the same as TH%CTL!! + ; For all bits in %XBCTL the general meaning is + ; "Set this bit in next outgoing segment". If no bits + ; are set, output is sent every 2 sec, otherwise every + ; 1/2 sec. If %XBNOW is set, output is sent as soon + ; as something notices it. + %XBNOW==:<1,,> ; Send output segment ASAP (else 1/2 sec clock) + %XBACF==:<2,,> ; Our FIN has been ACKed + + %XBABT==:< 400,,> ; We're aborting. + %XBFIN==:<1000,,> ; FIN received for input, input queue will not + ; get any more additions. +; %XBWOK==:<100,,> ; State is OK for user to write (else get IOC err) +; %XBROK==:<200,,> ; State is OK for user to read (else get IOC err) + + ; Connection state, as in TCP document (RFC-793) + ; Some test/dispatch code depends on the fact that the first + ; 4 states have the values they do. + ; ** NOTE: These .XSzzz symbols are not advertised to users. + ; ** Maybe I'll rename them in here sometime. -- CSTACY 9/84 + .XSCLS==:0 ; Closed (must be zero) + .XSSYQ==:1 ; ADDITIONAL ITS STATE: Syn-Queued + .XSLSN==:2 ; Listen + .XSSYN==:3 ; Syn-Sent + .XSSYR==:4 ; Syn-Rcvd + .XSOPN==:5 ; Established (Open) + .XSFN1==:6 ; Fin-Wait-1 + .XSFN2==:7 ; Fin-Wait-2 + .XSCLW==:10 ; Close-Wait + .XSCLO==:11 ; Closing + .XSCLA==:12 ; Last-Ack + .XSTMW==:13 ; Time-Wait + .XSTOT==:14 ; Total # of states +XBSTAU: BLOCK XBL ; User Channel state ,, +XBCLSU: BLOCK XBL ; Close reason ,, + .XCNTO==:0 ; Never opened + .XCUSR==:1 ; Closed by user + .XCFRN==:2 ; Closed by foreign host + .XCRST==:3 ; Fgn host reset things + .XCDED==:4 ; Fgn host dead (apparently) + .XCINC==:5 ; Incomplete transmission (retrans timeout) + ; ==:6 ; Byte size mismatch - can't happen + .XCNCP==:7 ; Local TCP went down + .XCRFS==:10 ; Fgn host refused connection (valid RST + ; received in SYN-SENT state) + +XBPORT: BLOCK XBL ; <4 zero bits> + ; It is set up this way for fast lookup of + ; incoming segments. +XBHOST: BLOCK XBL ; Remote host (HOSTS3 format) +XBLCL: BLOCK XBL ; Local host (HOSTS3 format) +XBNADR: REPEAT XBL,-1 ; Net host address to give the device driver (-1 none) + +; MP Input - see TCPI for detailed description +XBITQH: BLOCK XBL ; Input Segment TCP queue header +XBINBS: BLOCK XBL ; Total # bytes in input queue +XBINPS: BLOCK XBL ; Total # segments in input queue +XBIBP: BLOCK XBL ; Main prog BP to input +XBIBC: BLOCK XBL ; # bytes available for this BP + +; MP Output - see TCPW for detailed description +XBOCOS: BLOCK XBL ; Current Output Segment pointer (0 if none) +XBOBP: BLOCK XBL ; Main prog BP into output segment +XBOBC: BLOCK XBL ; # bytes of room for this BP + +XBORTP: BLOCK XBL ; Retransmit parameters +XBORTQ: BLOCK XBL ; Retransmit queue header +XBORTL: BLOCK XBL ; Retransmit queue length (# of segments) +XBORTC: BLOCK XBL ; Retransmit count (1st msg on queue) +XBORTT: BLOCK XBL ; Retransmit timeout (1st msg on queue) + +; TCP Send Sequence Variables +XBSUNA: BLOCK XBL ; Send Unacknowledged +XBSNXT: BLOCK XBL ; Send Next +XBSWND: BLOCK XBL ; Send Window (offered window) +XBSAVW: BLOCK XBL ; Available window (between SNXT and SUNA+WND) +XBSUP: BLOCK XBL ; Send Urgent Pointer +XBSWL1: BLOCK XBL ; Segment Seq number used for last window update +XBSWL2: BLOCK XBL ; Segment Ack number used for last window update +XBSMSS: BLOCK XBL ; Max seg size that receiver can handle + +; TCP Receive Sequence Variables +XBRNXT: BLOCK XBL ; Receive Next +XBRWND: BLOCK XBL ; Receive Window +XBRUP: BLOCK XBL ; Receive Urgent Pointer +XBRMSS: BLOCK XBL ; Max seg size we are expecting/ have asked for + +BBLK + +NTSYNL: SIXBIT /TCP/ ; Start SYS;ATSIGN TCP for random SYNs. +EBLK + 0 ; Word for NUJBST etc to mung for above job starting + +TCPUP: -1 ; -1 to handle TCP stuff, 0 to turn off. +TCPUSW: 0 ; -1 to disable net conns from anyone but ourself (like NETUSW) + ; Perhaps eventually this should be the same as NETUSW. +TCPRQN: 0 ; # of things in SYN queue, to keep it small +TCPRQL: 0 ; Index of last SYN queued. +TCPCRI: 0 ; Counter used for gensymming local port #s +TISSLU: 0 ; Last ISS used +TISSC: 0 ; Counter to further uniquize ISS +TCPLCP: 0 ; Last TCB index allocated +TCPBSW: -1 ? 0 ; Lock switch for allocating TCB indices +TCPTMO: 4*30. ; Default timeout for retransmits (in 30'ths of sec) +BBLK + +; Macro to perform sequence-number range checking. +; Note all numbers are 32-bit positive integers, modulo 2**32. +; Use it like this: +; CMPSEQ ,,,,,, +; Left and Right are addrs of the range bounds. One of them +; must be an AC. +; Seqno must be an AC. +; LT and LE are the strings "<" and "=<". +; Lerr and Rerr are the places to JRST to if the left or +; right compares fail, respectively. Rerr can +; be omitted and will default to Lerr. +; e.g. +; CMPSEQ A,<,D,=<,XBSNXT(I),TSI30 +; NOTE CAREFULLY that only existence within a range is checked, +; and the bounds L,R of the range MUST be known to be L =< R! +; It does not work to use CMPSEQ for the degenerate case +; CMPSEQ A,<,B,<,B,ERR +; to see if A < B. + +DEFINE CMPSEQ (L),C1,S,C2,(R),(OUTV1),(OUTV2) + %%%CML==0 + %%%CMR==0 +IFSE [C1][<] %%%CML==CAMG +IFSE [C1][=<] %%%CML==CAMGE +IFSE [C2][<] %%%CMR==CAML +IFSE [C2][=<] %%%CMR==CAMLE +IFE %%%CML&%%%CMR, .ERR Seq compare has bad relational arg + %%%CMX==CAMLE +IFSE [C1][=<] %%%CMX==CAML + +IFGE L-20,IFGE R-20, .ERR Seq compare needs ACs + +IFL L-20,CAMLE L,R ; Skip if normal order, L =< R +.ELSE CAMGE R,L + JRST [ ; Reverse order, R < L. Check S < R & L < S + %%%CMR S,R ; Skipwin if S <(=) R + %%%CMX S,L ; Unusual test here, win if S >(~=) L + JRST .+5 ; If either wins, win completely! +IFB OUTV2, JRST OUTV1 +.ELSE CAML S,[020000,,] ? JRST OUTV1 ? JRST OUTV2 + ] + ; Normal order, L =< R + %%%CML S,L ; Skipwin if S >(=) L + JRST OUTV1 + %%%CMR S,R ; Skipwin if S <(=) R +IFB OUTV2, JRST OUTV1 +.ELSE JRST OUTV2 +TERMIN + +SUBTTL TCP Open system call + +; .CALL TCPOPN +; arg 1 - receive channel number +; arg 2 - transmit channel number +; arg 3 - local port # (-1 to gensym unique port #) +; arg 4 - foreign port # (-1 for wild) +; arg 5 - foreign host address (HOSTS3 fmt) (-1 for wild) +; arg 6 - Retransmission timeout (optional) + +;Control bits: +; - None needed for channels - they are opened as .UAI and .UAO +; automatically (no other modes possible). +; - 7 vs 8 bit ASCII transfers can be determined by user-space byte +; pointer used in SIOT. System buffers are always 8-bit bytes. +%NOLSN==:100 ; Listen mode +%NOBBI==:200 ; Use big buffer for input (not implemented yet) +%NOBBO==:400 ; Use big buffer for output (not implemented yet) +%NOWDA==:1000 ; Use word-align algorithm on transmit (not implemented yet) + +; Note a value of -1 for either the foreign port or host will imply +; that the call is a "listen". For the time being, either also implies +; the other, i.e. wild port means wild host and vice versa. This is +; because I havent figured out what the right thing to do is for the +; various combinations that could result otherwise. +; Word-align means that for the transmit side, all segments sent will +; have the data aligned so that the first byte, and every fourth byte +; after that, will start on a 32-bit word boundary. This should +; produce a noticeable speedup for transfers that involve large blocks +; of words rather than small amounts of miscellaneous text. +; For the latter, it only makes things worse, so is not the default. + +; Return is semi-immediate; the call may +; hang momentarily waiting for a free network buffer. (Have timeout? +; do a SKIPA SKIPA HANG to schedule, then fail if still none?) +; Use NETBLK +; to determine when the channels become open. For a non-listen call, +; there is an internal ITS timeout, but for listen the state can persist +; forever. + +TCPOPN: METER("TCP: syscal tcpopn") + MOVEI A,(A) + MOVEI B,(B) + CAIGE A,NIOCHN + CAIL B,NIOCHN + JRST OPNL14 ; Bad channel # argument + CAIN A,(B) + JRST OPNL33 ; Illegal to use same channel # for both + MOVEI J,(B) + HRLI J,(A) ; Save chan #s in J/ ,, + PUSH P,C + PUSH P,D + PUSH P,E + PUSH P,J + MOVEI R,(A) ; Close receive chan + ADDI R,IOCHNM(U) + PUSHJ P,CCLOSE ; Close whatever is already on channels. + HRRZ R,(P) ; Close xmit chan + ADDI R,IOCHNM(U) + PUSHJ P,CCLOSE + POP P,J + POP P,E + POP P,D + POP P,C + + HLRZM J,UUAC(U) ; Remember input channel # for errs. + SKIPN TCPUP ; If TCP disabled, + JRST OPNL7 ; Fail, "device not ready". + CALL SWTL ; Lock TCB assignment switch + TCPBSW + MOVE I,TCPLCP + SOJL I,TCPO2 +TCPO1: SKIPN XBUSER(I) ; Hunt for free TCB + SKIPE XBSTAT(I) ; Must be both closed and unassigned. + SOJGE I,TCPO1 + JUMPGE I,TCPO3 ; Jump if got one! +TCPO2: MOVEI I,XBL ; Hit beginning, wrap back to end + CAMN I,TCPLCP + JRST OPNL6 ; No free TCB's available + MOVEM I,TCPLCP ; Might as well make faster next time + SOJA I,TCPO1 + +TCPO3: MOVEM I,TCPLCP ; Save scan pointer for next time + JRST TCPO4 ; (This is here for patching. -CSTACY) + + ; Got an index, now see if we're going to do a LISTEN + ; or an active open. +TCPO4: SETZ W, ; Assume active + CAME C,[-1] ; Verify local port is OK + CAIG C,177777 + CAIA + JRST OPNL11 ; Complain "illegal file name" + CAMN D,[-1] + AOJA W,.+3 + CAILE D,177777 + JRST OPNL11 + CAMN E,[-1] + ADDI W,2 + ; W = 0 if no wildcards, =1 if port wild, =2 if host wild, =3 both. + MOVE B,CTLBTS(U) ; Get control bits for call + CAIE W, + TRO B,%NOLSN ; Set "Listen" bit if implied by args. +; Crock - if either is wild, ensure both are. + CAIE W, + SETOB D,E + + SETZ R, ; Say we have no buffer + TRNE B,%NOLSN ; Skip if not listening, doing active open. + JRST TCPO20 ; Listening, don't need buffer. + + ; No wild-cards, this is going to be an active open. We will need + ; a buffer to send the initial SYN, so let's get it now and get + ; all possible PCLSR'ing over with, before turning off the NET PI. + CALL PKTGFI ; Get a free packet, skip unless fail. + CAIA ; Didn't get, skip to schedule. + JRST TCPO15 ; Got it! + SKIPA + SKIPA ; Force a schedule + CALL UFLS + CALL PKTGFI ; Try again. If we fail again, net is full, + JRST OPNL6 ; so better just return "device full" err. +TCPO15: MOVEI R,(A) ; We have buffer! Fall through. + TRCPKT R,"TCPO15 Alloc to send initial SYN" + + ; Okay, nothing can stop us now from running through to completion. + ; We do all the following code with net interrupts OFF so that + ; (a) We can scan all TCBs for port/host conflicts and be + ; sure we checked everything right, + ; (b) Incoming segments at int level won't be confused by + ; an inconsistent state for this TCB. + ; (c) We can check the pending-RFC queue safely. +TCPO20: CONO PI,NETOFF ; Don't let PI level see dirty work. + CAMN C,[-1] + JRST [ CALL TCPPCR ; Assign unique TCP port # + ROT D,-16. ; Put fgn port in high 16 bits + DPB A,[.BP TH%DST,D] ; Deposit local port + JRST TCPO30] ; Note that since port is unique, no + ; possible conflict with existing, so skip chk. + ; Also, low 4 bits indicate wildness if set. + + ; Note that low 4 bits of XBPORT are set to indicate wildness. + ; This ensures that TCPIS won't find them, but TSISQ will. + ; Have specific local port, check to make sure it doesn't already + ; exist in TCB tables. + ROT D,-16. ; Get fgn port in high 16 bits + DPB C,[.BP TH%DST,D] ; Put together the ports word + MOVSI T,-XBL +TCPO22: CAMN D,XBPORT(T) ; Look for matching port set + SKIPN XBSTAT(T) ; which is in use + AOBJN T,TCPO22 + JUMPL T,TCPO91 ; Ugh, found match! Must fail... + + ; OK, D has our unique port set, and we're ready to set things up. +TCPO30: MOVEM D,XBPORT(I) ; Store port set + SKIPL A,E + CALL CVH3NA ; Make sure it's HOSTS3 format. + MOVEM A,XBHOST(I) ; Store foreign host + CALL IPBSLA ; Call IP for best local address + MOVEM A,XBLCL(I) + CALL TXBINI ; Initialize the TCB + CALL TCPMSS ; Set default MSS values. Reexamined when + ; foreign host known if this is a wild listen. + CALL TCPRWS ; Open a default receive window + HRRZM U,XBUSER(I) ; Make TCB/index in use + HLRZ A,J ; Get back saved rcv channel # + DPB A,[XB$ICH (I)] ; Deposit input channel + DPB J,[XB$OCH (I)] ; and output channel + MOVE B,[0101,,0] ; Increment both channel #'s by 1 + ADDM B,XBUSER(I) ; So can distinguish chan 0 from no chan. + HRLZ T,I ; Set up user's IOCHNM words + HRRI T,TCPDUI + ADDI A,IOCHNM(U) + MOVEM T,(A) ; Set up input chan ,,TCPDUI + HRRI T,TCPDUO + ADDI J,IOCHNM(U) + MOVEM T,(J) ; Set up output chan ,,TCPDUO + + ; Search pending-RFC queue to make sure we match up or reject + ; with stuff in there. + LDB B,[.BP TH%DST,XBPORT(I)] ; B gets local port # + SETO D, ; D is -1 for any PE ptr. + CALL TCPRQS ; Search queue, return index in A + JUMPL A,TCPO41 ; Ignore further RFC checks if nothing. + MOVEI C,(A) + HRRZ A,XBITQH(C) + CAIN A, + BUG HALT + HLRZ W,PK.IP(A) + HLRZ H,PK.TCP(A) + TRNE D,17 ; If we're "wild" accepting any request, + JRST TCPO35 ; Take it! + LDB B,[IP$SRC (W)] ; No, must try full match. + CAMN B,XBHOST(I) ; If hosts match + CAME D,TH$SRC(H) ; and ports match too + JRST TCPO40 ; (don't) + + ; Matching request!! + ; For now, we ignore the listen/active distinction here, and + ; always try to establish connection with the pending RFC. + ; So, can flush use of R for listen flag. Have to flush the + ; extra buffer if it was "active" open, though, since we can + ; just re-use the pending-RFC packet. +TCPO35: METER("TCP: Open matched pending RFC") + JUMPN R,TCPO36 + MOVEI Q,XBITQH(C) ; If don't already have buffer, + CALL PKQGF(PK.TCP) ; Get it from the queued SYN (C is idx to) + SKIPN R,A ; It had better have a buffer! + BUG HALT + TRCPKT R,"TCPO36 Queued SYN used to answer pending RFC rqst" +TCPO36: LDB B,[IP$SRC (W)] + MOVEM B,XBHOST(I) ; Set host address + LDB B,[IP$DST (W)] + MOVEM B,XBLCL(I) ; Use local address the other end wants + MOVE D,TH$SRC(H) + MOVEM D,XBPORT(I) ; And ports + CALL TCPMSS ; Find default segment sizes for connection + CALL TCPRWS ; Set up receive window + EXCH C,I ; C identifies slot of queued SYN. + CALL TSISQF ; Flush the SYN from queue! + MOVEI I,(C) + CALL TSILSX ; Invoke interrupt level SYN+ACK, re-uses + ; the packet and sets state and everything. + JRST TCPO80 ; OK, take win return. + + ; Request doesn't match, restore it and fall thru. +TCPO40: +; MOVEI Q,TCPRQH ; Thought we had something but didn't, +; CALL PKQPF(PK.TCP) ; so put back on queue. + + ; No matching request on pending-RFC queue. +TCPO41: CAIN R, ; Skip if handling active open + JRST [ MOVEI A,.XSLSN ; No, handling a listen. + JRST TCPO70] ; Just change state and we're done. + + ; Active open, must fire off initial SYN. + ; R has PE ptr to free packet to be used for the SYN. + CALL TCPISS ; Get initial sequence # + MOVEM A,XBSUNA(I) ; Set up sequence vars + MOVEM A,XBSNXT(I) + MOVSI T,(TC%SYN) ; Note no ACK in initial segment! + TRCPKT R,"TCPO41 Send initial SYN" + CALL TSOSSN ; Send SYN segment (clobber mucho ACs) + MOVEI A,.XSSYN ; Set state to SYN-SENT and fall thru. + +TCPO70: HRRM A,XBSTAT(I) ; Set state LISTEN or SYN-SENT. + CALL TCPUSI ; Change user state. +TCPO80: CONO PI,NETON + JRST LSWPJ1 ; Success return, unlock switch and skip. + + ; Port match failure, must back off and fail. +TCPO91: CONO PI,NETON ; No need to hide our shame + SKIPE A,R ; If we had a buffer, + CALL PKTRT ; return it to freelist. + JRST OPNL13 ; Say "file already exists". + +; TXBINI - Initialize TCB connection table entries for specific index. +; The things it doesn't touch are commented out below. +; I/ TCB index + +TXBINI: +; SETZM XBUSER(I) ; Set after +; SETZM XBSTAT(I) ; Set after + SETZM XBSTAU(I) + SETZM XBCLSU(I) +; SETZM XBPORT(I) ; Set prior +; SETZM XBHOST(I) ; Set prior +; SETZM XBLCL(I) + SETOM XBNADR(I) + + ; I/O vars + SKIPE XBITQH(I) + BUG CHECK,[TCP: Init TCB has input, I=],OCT,I,[list ],OCT,XBITQH(I) + SETZM XBITQH(I) + SETZM XBINBS(I) + SETZM XBINPS(I) + SETZM XBIBP(I) + SETZM XBIBC(I) + + SKIPE XBOCOS(I) + BUG CHECK,[TCP: Init TCB has output, I=],OCT,I,[list ],OCT,XBOCOS(I) + SETZM XBOCOS(I) + SETZM XBOBP(I) + SETZM XBOBC(I) + + ; Retransmit stuff + SETZM XBORTP(I) + SKIPE XBORTQ(I) + BUG CHECK,[TCP: Init TCB has retrans, I=],OCT,I,[list ],OCT,XBORTQ(I) + SETZM XBORTQ(I) + SETZM XBORTL(I) + SETZM XBORTC(I) + SETZM XBORTT(I) + + ; TCP Send Sequence Initialization + SETZM XBSUNA(I) + SETZM XBSNXT(I) + SETZM XBSWND(I) + SETZM XBSAVW(I) + SETZM XBSUP(I) + SETZM XBSWL1(I) + SETZM XBSWL2(I) +; SETZM XBSMSS(I) ; Set after + + ; TCP Receive Sequence Initialization + SETZM XBRNXT(I) + SETZM XBRUP(I) +; SETZM XBRMSS(I) ; Set after +; SETZM XBRWND(I) ; Set after + RET + +; TCPPCR - Port Create. Creates a unique local port #. +; Returns # in A. Current algorithm is very simple/dumb. +; Must only be called at MP level with NETOFF. +; Clobbers T,Q + +TCPPCR: PUSH P,B + MOVEI A,(U) ; Get user index + IDIVI A,LUBLK ; Find job # + AOS B,TCPCRI ; Bump and get new counter + ROT B,-8. ; Put low bits into high + LSHC A,8. ; Then shift them into port # + CALL TCPPLU ; See if this port unique or not. + JRST [ AOS TCPCRI ; If not, AOS stuff and keep going. + AOJA A,.-1] + POP P,B + RET + +; TCPPLU - Port Lookup. Skips if port # unique among local ports. +; A/ port # +; Clobbers T, Q. +; Returns .+1 if fail (number not unique) +; T/ idx of matching TCB + +TCPPLU: LSH A,4 ; Shift over for easier compare + MOVSI T,-XBL +TCPLU2: SKIPN Q,XBPORT(T) + JRST TCPLU3 + AND Q,[TH%DST] + CAMN A,Q + JRST TCPLU7 +TCPLU3: AOBJN T,TCPLU2 + AOS (P) +TCPLU7: LSH A,-4 + RET + +; TCPMSS - Determine and set max bytes per segment for TCB in I +; I/ TCB index. XBHOST should be set already. +; Bashes A, T +; Base maximum TCP segment sizes on size of largest datagram IP wants +; to send to destination. This sets the default sizes. We will tell +; the foreign side what we want (XBRMSS) with a TCP MSS option in the +; outgoing SYN. We will adjust what we send (XBSMSS) down if foreign +; side requests it with MSS opton in an incoming SYN. + +TCPMSS: MOVE A,XBHOST(I) ; Foreign address + CALL IPMTU ; IP datagram size to T + SUBI T,40. + MOVEM T,XBSMSS(I) ; Set default send and receive segment sizes + MOVEM T,XBRMSS(I) + RET + + +SUBTTL Other TCP device system call routines + +; Device name in DEVTAB, device code in DCHSTB, index in RSTB to some tables + +; OPEN - from DEVADR + +TCPO: JRST OPNL12 ; Say "mode not avail" + ; Save rest temporarily. + HLRS C + MOVSI A,(A) ; Save RH of FN1 in LH of IOCHNM + JSP Q,OPSLC7 + TCPDUI,,TCPDUO + TCPDBI,,TCPDBO + TCPDUI,,TCPDUO + TCPDBI,,TCPDBO + +; CLOSE - from CLSTB +; R/ addr of IOCHNM word + +TCPCLS: METER("TCP: syscal close") + HLRZ I,(R) ; Get TCB index from LH of IOCHNM + CAIL I,XBL ; Make sure it's reasonable + BUG HALT,[TCP: CLS idx bad] + HRRZ A,XBUSER(I) ; Verify user + CAIE A,(U) + BUG HALT,[TCP: CLS usr bad] + SETO D, ; See if input or output + HRRZ A,(R) + CAIN A,TCPDUO ; Output? + AOSA D + CAIN A,TCPDUI ; Input? + ADDI D,1 + CAIGE D, ; D/ 0 for input, 1 for output. + BUG ; IOCHNM value screwed up?? + LDB A,[XB$ICH (I)] ; Get input chan # according to TCB + LDB B,[XB$OCH (I)] ; Ditto output + MOVEI C,(R) + SUBI C,IOCHNM(U) ; Find channel # we're closing + ADDI C,1 ; Increment since TCB # is really #+1 + CAME C,A(D) ; Compare with channel # in TCB + BUG HALT,[TCP: Close chan not same as TCB chan] + JUMPN D,[MOVEI D,2 + CAIE A, + MOVEI D,3 + JRST TCPC06] + CAIE B, + IORI D,1 +TCPC06: + ; D is now a 2-bit channel status index. + ; Bit 1.2 is 0 for input, 1 for output. + ; Bit 1.1 is 0 if other channel is closed, 1 if it is still open. + SKIPN XBSTAT(I) ; Perhaps already gone? + JRST TCPCL8 ; Yeah, flush channel etc. + PUSH P,D + CONO PI,NETOFF ; Ensure that state doesn't change on us. + HRRZ J,XBSTAT(I) + CAIL J,.XSTOT + BUG HALT,[TCP: CLS state bad] + XCT TCPCXT(J) ; Invoke closure stuff appropriate for state + CONO PI,NETON ; TCB state hacking done, can re-enable ints. + POP P,D + + ; Remove links between user channel and TCB. If both channels + ; are gone, XBUSER is cleared completely. + ; The TCB is not necessarily closed at this point (XBSTAT zero) + ; but TCP will look after it independently to ensure it eventually + ; goes away. +TCPCL8: SETZ B, ; Get a zero + MOVEI T,.XCUSR ; Use this for "Close reason" if needed + TRNE D,2 ; Remember D bit 1.2 indicates output chan + JRST [ DPB B,[XB$OCH (I)] ; Yup, clear output chan. + CALL TCPUCO ; Set close reason if necessary + HRRZ A,XBOCOS(I) ; Does a COS buffer exist? + CAIN A, + JRST TCPCL9 ; Nope, nothing to flush. + CALL PKTRTA ; Aha, free it up. + SETZM XBOCOS(I) + SETZM XBOBP(I) + SETZM XBOBC(I) + JRST TCPCL9] + DPB B,[XB$ICH (I)] ; Clear input chan. + CALL TCPUCI ; Set close reason if need to. + CALL TXBIFL ; Flush input queue + +TCPCL9: TRNN D,1 ; Skip if other channel still there. + SETZM XBUSER(I) ; Else flush whole word incl user index! + TRNE D,1 ; If a channel is left, + CALL TCPUSI ; we may need to take interrupt on it. + LDB A,[XB$STY (I)] ; Was a STY connected to channel? + JUMPE A,CPOPJ ; Return if not. + MOVEI I,(A) ; Ugh, must disconnect it! Set up TTY # + CALL NSTYN0 ; Disconnect + JFCL + RET ; Return (CLOSE will clear IOCHNM/IOCHST) + +TCPCLE: BUG CHECK,[TCP: Illegal state in CLOSE, J=],OCT,J,[ D=],OCT,D + CALL TXBFLS ; Flush all of TCB but XBUSER + RET + +TCPCXT: OFFSET -. +.XSCLS:: CALL TXBFLS ; Closed already, but flush again to make sure +.XSSYQ:: CALL TCPCLE ; Syn-Queued - can't happen!! +.XSLSN:: CALL TXBFLS ; Listen - flush TCB, enter closed state. +.XSSYN:: CALL TXBFLS ; Syn-Sent - flush TCB, enter closed state. +.XSSYR:: XCT TCPCXT+.XSOPN ; Syn-Rcvd - handled same as OPEN below +.XSOPN:: XCT (D)[ ; Established (Open) + CALL TCPCLE ; In (only) - Can't happen + JFCL ; In (have Out) - Disconnect input + CALL TCPC30 ; Out (only) - Send FIN, enter FIN-WAIT-1 + CALL TCPC30] ; Out (have In) - " " " " +.XSFN1:: XCT (D)[ ; Fin-Wait-1 + JFCL ; In (only) - Disconnect input + CALL TCPCLE ; In (have Out) - Can't happen + CALL TCPCLE ; Out (only) - Can't happen + CALL TCPCLE] ; Out (have In) - Can't happen +.XSFN2:: XCT (D)[ ; Fin-Wait-2 + CALL TXBFLS ; In (only) - Flush, give up waiting + CALL TCPCLE ; In (have Out) - Can't happen + CALL TCPCLE ; Out (only) - Can't happen + CALL TCPCLE] ; Out (have In) - Can't happen +.XSCLW:: XCT (D)[ ; Close-Wait + CALL TCPCLE ; In (only) - Can't happen + JFCL ; In (have Out) - Disconnect input + CALL TCPC70 ; Out (only) - Send FIN, enter LAST-ACK + CALL TCPC70] ; Out (have In) - " " " " +.XSCLO:: XCT TCPCXT+.XSFN1 ; Closing - handled same as Fin-Wait-1 etc. +.XSCLA:: XCT TCPCXT+.XSFN1 ; Last-Ack - handled same as Fin-Wait-1 etc. +.XSTMW:: XCT TCPCXT+.XSFN1 ; Time-Wait - handled same as Fin-Wait-1 etc. +.XSTOT:: OFFSET 0 + + ; Closing output channel while in SYN-RCVD state. + ; Send a FIN and enter FIN-WAIT-1 state. +TCPC30: CALL TCPCLF + MOVEI J,.XSFN1 + JRST TCPC75 + + ; Closing output channel while in CLOSE-WAIT state. + ; Send a FIN and enter LAST-ACK state. +TCPC70: CALL TCPCLF + MOVEI J,.XSCLA +TCPC75: HRRM J,XBSTAT(I) + RET + +TCPCLF: MOVSI T,(TC%ACK+TC%FIN+%XBNOW) ; Tell TCP that output needs FIN and ACK. + JRST TCPOFR ; Go force out current buffer if any + +; TCPUC - Set "Reason-closed" states if not already set. +; T/ Reason to use, if none already exists. +; Clobbers Q +TCPUC: CALL TCPUCI +TCPUCO: HRRZ Q,XBCLSU(I) + CAIN Q, + HRRM T,XBCLSU(I) + RET +TCPUCI: HLRZ Q,XBCLSU(I) + CAIN Q, + HRLM T,XBCLSU(I) + RET + +; TXBFLS - Flush all info about a TCB from TCP viewpoint. +; Mostly consists of freeing up all buffers used, and then +; clearing out most other data cells of the TCB. +; Note that XBUSER and XBSTAU are not affected! +; TXBFLP - ditto but usable at PI level, it is careful not to smash +; things that MP level might be referencing. +; Clobbers A,T,Q +; TXBIFL - Flushes input queue +; TXBOFL - Flushes output queue (including retrans list!) + +TXBFLS: SETZM XBSTAT(I) + CALL TXBIFL + CALL TXBOFL + SETZM XBPORT(I) + SETZM XBHOST(I) + RET + +; TXBFLP - Things to be careful of: +; - swiping COS +; - flushing input queue (don't touch it) + +TXBFLP: CALL TXBOFL + SETZM XBSTAT(I) ; Say off-limits to PI level now. + SETZM XBPORT(I) + SETZM XBHOST(I) + LDB T,[XB$ICH (I)] ; See if input chan active + CAIN T, + CALL TXBIFL ; No input chan, so ensure input q flushed + CALL TCPUSI ; Alert user to mung + RET + +TXBIFL: SETZM XBINBS(I) + SETZM XBINPS(I) + SETZM XBIBP(I) + SETZM XBIBC(I) + MOVEI Q,XBITQH(I) + CALL PKPFLS + SKIPE XBITQH(I) + BUG CHECK,[TCP: Incompl input fls I=],OCT,I,[list ],OCT,XBITQH(I) + CALL TCPRWS ; Reset receive window. + RET + +TXBOFL: HRRZ A,XBOCOS(I) ; If current output seg exists, + CAIE A, + SKIPGE XBSTAT(I) ; and isn't locked by MP level, + CAIA + JRST [CALL PKTRTA ; then free it + SETZM XBOCOS(I) ; and clear the pointer. + SETZM XBOBP(I) + SETZM XBOBC(I) + JRST .+1] + SETZM XBORTT(I) + SETZM XBORTC(I) + MOVEI Q,XBORTQ(I) + CALL PKPFL ; Flush retrans list carefully. + SKIPE XBORTL(I) + BUG CHECK,[TCP: Incompl output fls, I=],OCT,I,[list ],OCT,XBORTQ(I) + MOVE A,XBSNXT(I) + MOVEM A,XBSUNA(I) ; Claim everything ACK'd. + SETZM XBSWND(I) ; Zero our send window. + SETZM XBSAVW(I) ; and available window + SETZM XBSUP(I) ; and urgent pointer. + RET + +PKPFLS: PUSH P,Q +PKPFL2: MOVE Q,(P) + CALL PKQGF(PK.TCP) + JUMPE A,POPQJ + CALL PKTRTA ; Should always be freeable. + JRST PKPFL2 + +; Ditto, but for flushing retransmit queue, which has to be special +; since packets are linked on IP output list as well as TCP list. +; Since we can't take packets off the IP output list here, we just set +; a flag telling output PI level to ignore the packet. + +PKPFL: PUSH P,Q +PKPFL3: MOVE Q,(P) + CALL PKQGF(PK.TCP) + JUMPE A,POPQJ + CONO PI,PIOFF + MOVE T,PK.FLG(A) ; Check packet flags + TLNN T,(%PKODN) ; Output done? + JRST [ TLO T,(%PKFLS) ; No, say to flush when hit it. + MOVEM T,PK.FLG(A) + CONO PI,PION + TRCPKT A,"PKPFL3 Packet not flushed" + JRST PKPFL4] + CONO PI,PION + CALL PKTRT +PKPFL4: SOSGE XBORTL(I) + BUG CHECK,[TCP: Retrans Q count err] + JRST PKPFL3 + +SUBTTL TCP Main Program Input + +; All TCP input segments for a connection are put on a queue that +; is headed at XBITQH. When this header is zero, there is no more +; input; if the %XBFIN flag is also set, the remote host has closed +; its transmit side and there will never be any more input. +; Segments are only added by PI level, at the end of the queue. +; Segments are only removed by MP level IOTs, at the start of the queue. +; (An incoming RST will of course flush the queue at PI level) + +; If XBIBP is non-zero, it points into the first segment on the input queue, +; and XBIBC is also valid; things are ready for MP IOTing. +; However, neither XBIBP nor XBIBC is meaningful if XBITQH is zero. + +; Input IOT - from IOTTB + SKIPA T,[SIOKT] ; Come here for SIOT entry +TCPI: MOVEI T,CHRKT + METER("TCP: syscal in") + HLRZ I,(R) ; Get TCB index + + ; Verify state, do misc setup for reading + MOVSI B,(XB%STY) + TDNE B,XBUSER(I) ; Can't IOT if direct-connected to STY. + JRST IOCR10 ; "Chan in illegal mode" + HLRZ B,XBSTAU(I) ; Just reading state, don't need NETOFF. + SKIPG TCPTBI(B) ; Ensure meta-state allows reading. + JRST [ HLRZ B,XBCLSU(I) ; Can't read, see if reason OK + CAIN B,.XCFRN ; Only OK reason is clean fgn close. + JRST UNIEOF ; Yeah, just return quietly. + JRST IOCR10] + + MOVE E,[441000,,4] ; 8-bit bytes, 4 to a word + MOVEI B,[ + XBIBP(I) ; Byte pointer + XBIBC(I) ; # bytes to read + TCPIBG ; Routine to get next buffer + TCPIBD ; Routine to discard buffer + 0 ; not used + TRNA ; Negative - TCPIBG and TCPIBD will do waiting. + ] + CALL (T) + CAIA + AOS (P) + SKIPG XBIBC(I) ; If count for this buffer reached zero, + CALL TCPIBD ; Flush it so XBITQH is valid indication of input avail + RET + +; TCPIBD - Discard input buffer, invoked by I/O. +; This is always called before TCPIBG is. + +TCPIBD: SKIPN XBIBP(I) ; Make sure something's there to discard. + RET ; Nope, gone or was never set up. + MOVEI Q,XBITQH(I) ; Point to TCP input queue header + CALL PKQGF(PK.TCP) ; Get first thing off queue, into A + CAIN A, ; Something better be there. + BUG HALT,[TCP: IOTI queue lost] + + ; Check BP just out of sheer paranoia. + HRRZ T,XBIBP(I) ; Find addr BP points to (maybe +1 actual) + HLRZ Q,PK.TCP(A) ; Get addr of TCP header + CAIL Q,(T) ; Header better be less than BP! + JRST TCPIB2 + TRZ Q,PKBSIZ-1 ; Get addr of start of buffer + CAILE T,PKBSIZ(Q) ; BP should be within or just past end. +TCPIB2: BUG HALT,[TCP: IOTI BP incons] + + ; Okay, end of paranoia, just flush the buffer. + LDB T,[PK$TDL (A)] ; Find # chars we read + MOVN T,T + ADDM T,XBINBS(I) ; Update # chars avail for input. + CALL PKTRT ; Return packet to freelist. + SOSGE T,XBINPS(I) ; Decrement count of segs on input queue + BUG CHECK,[TCP: Input Q count incons] + CAIL T,%TCPMI/2 ; If we are now handling past 50% input, + JRST [ MOVSI T,(TC%ACK) ; Make sure we send an ACK + IORM T,XBSTAT(I) ; so new rcv window is reported. + JRST .+1] + CONO PI,NETOFF + CALL TCPRWS ; Set new receive window + CALL TXBIST ; Get new input chan state + HRLM T,XBSTAU(I) ; Set it. Note interrupt is avoided here. + CONO PI,NETON + SETZM XBIBP(I) + SETZM XBIBC(I) + RET ; Always return with simple POPJ + +TCPRWS: MOVEI T,%TCPMI + SUB T,XBINPS(I) ; Find # segs we can still queue up + CAIGE T,1 ; If no full segs left, + TDZA T,T ; Zero the window, no more segs allowed + IMUL T,XBRMSS(I) ; Else will take N * MSS bytes +TCPRW3: MOVEM T,XBRWND(I) + RET + +IFN 0,[ + ; This code turns out to lose because the code at TCPIS only + ; checks XBRWND to see whether to compact input or not, and as + ; long as XBRWND is non-zero, stuff will always be added to queue, + ; using up all the packet buffers. + ; Basically it's a question of whether or not to allow more input, + ; up to limits of last queued buffer, if the queue has too many + ; buffers on it. Metering will show whether most other implementations + ; win or lose with our buffer-alloc type windowing. +TCPRW2: HLRZ Q,XBITQH(I) ; Find # chars room in last seg + LDB T,[PK$TDL (Q)] + LDB Q,[PK$TDO (Q)] + ADDI Q,(T) + MOVEI T,576. + SUBI T,(Q) + CAIGE T, + SETZ T, + MOVEM T,XBRWND(I) + RET +] + +; TCPIBG - Get new input buffer (invoked by I/O, after TCPIBD) +; Return .+1 if can't get new buffer, must wait (Never, we do waiting) +; Return .+2 if OK, new BP and count set up. +; Return .+3 if "EOF", transfer complete + +TCPIBG: SKIPE XBIBP(I) ; Shouldn't be anything already there. + BUG HALT,[TCP: IOTI buf incons] +TCPIB3: SKIPN A,XBITQH(I) ; See if anything in input queue + JRST TCPIB5 ; No, go handle EOF. + LDB T,[PK$TDL (A)] ; Find # bytes input for this segment + CAIN T, ; Something probably shd be there. + BUG HALT,[TCP: IOTI null seg] + MOVEM T,XBIBC(I) ; Store as new # bytes + LDB T,[PK$TDO (A)] ; Get offset from start of header + HLRZ Q,PK.TCP(A) ; Get addr of TCP header + ROT T,-2 ; Divide offset by 4 + ADDI Q,(T) ; Point to right word + LSH T,-34. ; Right-justify the low 2 bits + HRL Q,(T)[441000 ? 341000 ? 241000 ? 141000] ; Get right LH for BP + MOVEM Q,XBIBP(I) ; Now store BP! + JRST POPJ1 ; Say ready to go again... + + ; No input available. First check to see if there will ever + ; be any more (FIN seen?), then whether to return right away or + ; hang. +TCPIB5: CONO PI,NETOFF ; Avoid timing inconsistencies + SKIPE A,XBITQH(I) ; Check again + JRST [ CONO PI,NETON ; Got some?? + JRST TCPIB3] ; Try again. + SKIPN XBINPS(I) ; No, should also have no segments + SKIPE XBINBS(I) ; and no bytes + BUG HALT,[TCP: IOTI count incons] + MOVE A,XBRWND(I) ; Save value of rcv window + CALL TCPRWS ; Then reset the window + CAME A,XBRWND(I) ; Was previous value correct? + METER("TCP: RCV.WND out of synch") + MOVE T,XBSTAT(I) ; Get flags + CONO PI,NETON + TLNE T,(%XBFIN) ; FIN seen, and input queue empty? + JRST TCPIB6 ; Yes, true EOF now. + + MOVE T,CTLBTS(U) ; See if call had "don't-hang" bit set + TRNE T,10 + JRST TCPIB7 ; No, return EOF. + SKIPN XBITQH(I) ; Wait until input queue has something. + CALL UFLS + JRST TCPIBG ; Then call again. + +TCPIB6: +TCPIB7: CALL TCPUSI ; Adjust user state. + JRST POPJ2 ; and return "EOF" + + +SUBTTL TCP Main Program Output + +; Output IOT - from IOTTB +; Output segments are chained together from XBORTQ, which is +; the "retransmit queue". +; The queue only contains segments which occupy sequence space, since +; these are the only ones which require ACKs and possible retransmit. +; All others are sent directly to the IP output queue. +; While the transmit connection is open, +; Segments are only added by MP level IOTs, at the end of the queue. +; Segments are only removed by PI level ACKs, at the start of the queue. + +; Main program I/O is done into the "Current Output Segment", which is NOT +; on the retransmit queue. There are three variables related to this COS. +; XBOCOS - ,, +; XBOBP - BP into the COS, for MP IOT writing. +; XBOBC - Count of # bytes left that MP IOT can deposit into. +; Note that the maximum possible size of the buffer is kept in PK$TDL +; (TCP segment Data Length). For windowing reasons it may be necessary +; to restrict the amount of space actually used, thus the initial value +; of XBOBC may be less than PK$TDL. This is why the initial value is also +; copied into the RH of XBOCOS, so that when XBOBC counts out we know +; exactly how much of the buffer was actually used. It is possible for +; XBOBC to be increased by interrupt level window processing, in order +; to increase utilization of the buffer. +; States: +; If XBOCOS is zero, XBOBP and XBOBC must also be zero; there is +; no COS. +; If XBOCOS is non-zero (a current output seg exists), then: +; if LH(XBOCOS) is zero, the segment hasn't yet been written +; into, and needs to be set up. +; XBOBP and XBOBC should be zero! +; else the segment is set up for writing. XBOBP should be set! +; If XBOBC is zero it means the segment now contains +; LH(XBOCOS) bytes of data. If this number is less +; than PK$TDL (max possible seg data) then the count +; may be reset to allow further output into this +; segment, or it may simply be sent as is. +; +; The current segment is put on the retransmit queue (and IP output queue) +; when: +; PI level (eg clock) decides it's time to send an ACK or do a FORCE. +; MP level IOT fills up the segment completely. +; MP level FORCE or CLOSE is invoked. +; The current segment is locked down during MP IOT, to keep PI level +; from ripping it away (which would leave entrails dangling). +; PCLSR'ing will clear this lock. If TCP flushes the TCB at PI level +; for some reason, XBOCOS will be freed unless locked. XBOBC and XBOBP +; will still be cleared even if locked, so as to cause a call to TCPOBW +; which will notice the condition and free the COS itself. + + SKIPA A,[SIOKT] ; Come here for SIOT entry +TCPW: MOVEI A,CHRKT + METER("TCP: syscal out") + HLRZ I,(R) ; Get TCB index from IOCHNM wd + + ; Verify state, do misc setup for writing, lock segment. + CONO PI,NETOFF + HRRZ B,XBSTAU(I) ; Get output chan state + SKIPG TCPTBO(B) ; See if meta-state allows writing + JRST IOCR10 ; Can't, say "chan not open" (ugh) + MOVSI B,(XB%STY) + TDNE B,XBUSER(I) ; Also can't if direct-connected to STY. + JRST IOCR10 + MOVSI B,(%XBMPL) ; Set locked flag (must be sign bit!) + IORM B,XBSTAT(I) + CONO PI,NETON ; Okay, we've got it. + CALL SGNSET ; Set PCLSR routine to unlock flag. + XBSTAT(I) + SKIPN XBOCOS(I) ; If no COS there, + SETZM XBOBC(I) ; make SURE count is zapped so refill invoked. + MOVE E,[441000,,4] ; 8-bit bytes, 4 to a word + MOVEI B,[ + SETZ XBOBP(I) ; Output BP found here (sign sez is output) + XBOBC(I) ; # bytes of room remaining + TCPOBG ; Routine to get another buffer (not used) + TCPOBW ; Buffer full, routine to send it. + 0 ; Not used + TRNA] ; Negative - TCPOBG and TCPOBW will do waiting. + CALL (A) + CAIA + AOS (P) ; Pass on a skip return. + + ; User IOT is done, now unlock the segment. + ; We also check for wanting to do an immediate ACK and if needed + ; ship out the current buffer right now, without waiting + ; for the 1/2-sec clock to do it. + SKIPN A,XBSTAT(I) ; See if XBSTAT is still set + JRST IOCR10 ; No, take IOC error return! + CAIL A, ; It better still be locked! + BUG CHECK,[TCP: Output not locked] + CALL LSWPOP ; Clear the lock flag + TLNN A,(%XBNOW) ; Was "immediate-send" flag set? + RET ; Nope, can just return. + METER("TCP: TCPW exit force") + CONO PI,NETOFF + MOVSI T,(TC%PSH) ; Hmm, set up and shove out. + CALL TCPOFR ; and force out current output segment. + CONO PI,NETON + RET + +TCPOBG: BUG CHECK,[TCP: IOT called wrong rtn (TCPOBG)] + AOS (P) ; If proceeded, can still win. Make skip return + ; and drop through to TCPOBW. + +; TCPOBW - Write/Get output buffer, invoked by SIOKT/CHRKT when the +; buffer count (XBOBC) is zero. This routine can figure out +; whether it needs to ship out a full buffer, or get a new +; output buffer, or both. Always returns with XBOBP and +; XBOBC set up for additional output (otherwise it hangs and +; can be PCLSR'd) + +TCPOBW: SKIPE R,XBOCOS(I) ; Get PE ptr to COS + JRST [ HLRZ A,R ; Got a COS, see if already set up + JUMPN A,TCPOB5 ; Jump if so. + JRST TCPOB2] ; Else must set it up. + + ; No current segment, must get a new one. + HRRZ T,XBSTAU(I) ; First ensure output state is OK. + SKIPG TCPTBO(T) ; Skip if still OK to output. + JRST IOCR10 ; Blooie, say "Chan not open". + CALL PKTGF ; Get one, hang until we succeed. + MOVEI R,(A) ; Set up in std AC + TRCPKT R,"TCPOBW Alloc for IOT output buffer" + HRRZM R,XBOCOS(I) ; Store ptr + + ; Set up segment for IOT to deposit into. +TCPOB2: MOVEI T,%TCPMO ; Get max # segments allowed on queue + CAMG T,XBORTL(I) ; Hang until we have less than this. + CALL UFLS ; Note that conn closure will unhang too, + ; because it flushes output queue. + CALL TSOINI ; Initialize the segment (set up W, H) + LDB A,[PK$TDO (R)] ; Find offset data should start at. + TRNE A,3 + BUG HALT ; Should always start at wd boundary! + LSH A,-2 ; Find # words + ADDI A,(H) ; Add address of TCP header, + HRLI A,441000 ; and now we have our initial BP. + MOVEM A,XBOBP(I) ; Set it up. + LDB A,[PK$TDL (R)] ; Get max length avail in this segment + + ; Now have a fresh buffer and nothing else to wait for. + ; Freeze the world, make sure it's still OK to output, and find + ; out how big an output segment we can allow. +TCPOB4: CONO PI,NETOFF + HRRZ T,XBSTAU(I) ; Still OK to output? Check again. + SKIPG TCPTBO(T) + JRST [ MOVEI A,(R) ; Bah, must return buffer. + CALL PKTRTA + SETZM XBOCOS(I) + CONO PI,NETON + JRST IOCR10] ; Barf "Chan not open". + MOVEI T,(I) ; Get index in T for PCLSRing. + CALL TCPOB9 ; Check available window + JRST [ CONO PI,NETON ; Window too small, allow ints + CALL TCPOB9 + CALL UFLS + JRST TCPOB4] ; Big enough, go back and re-try stuff. + LDB Q,[PK$TDL (R)] ; Get max # bytes available + CAMLE Q,XBSAVW(I) ; Greater than window? + MOVE Q,XBSAVW(I) ; Yeah, truncate down to this size. + HRLM Q,XBOCOS(I) ; Store original # bytes in LH of XBOCOS + MOVEM Q,XBOBC(I) + CONO PI,NETON + RET ; Okay, all set up, return. + +TCPOB9: MOVE A,XBSWND(T) + LSH A,-2 ; Get 25% offered window + CAML A,XBSAVW(T) ; If 25% offered > avail window, + RET ; punt and wait for better stuff. + JRST POPJ1 + + ; Here when we were all set up, and output has used up all + ; of the buffer space initially available. Check to make sure + ; there isn't more we can fill out, and if not then fire off + ; the segment. +TCPOB5: HLRZ T,XBOCOS(I) ; Get # bytes we originally had + CONO PI,NETOFF ; Avoid magic changes in send window + CAML T,XBSAVW(I) + JRST TCPOB6 ; Send window same or smaller (!), send seg. + MOVE Q,XBSAVW(I) ; Send window is bigger! Get new size + LDB A,[PK$TDL (R)] ; Get max size + CAMLE A,Q + MOVEI A,(Q) ; Use minimum of max size and send window. + MOVEI Q,(A) ; Save result + SUBI A,(T) ; Find # more bytes we can hack + CAIG A, ; If there's no more, + JRST TCPOB6 ; Just send it off anyway. + HRLM Q,XBOCOS(I) ; Hurray, got more! Store new original # + MOVEM A,XBOBC(I) ; And set up new count + CONO PI,NETON + RET ; And return happily. + +TCPOB6: TRCPKT R,"TCPOB6 IOT Send" + CALL TCPOB7 + JRST TCPOBW + +TCPOB7: DPB T,[PK$TDL (R)] ; Okay, say this many bytes of data are in seg + PUSH P,B + PUSH P,C + PUSH P,E + MOVSI T,(TC%PSH) ; Ensure seg is pushed out. + IORM T,XBSTAT(I) + CALL TSOSND ; Send data segment (# bytes in PK.TCI) + ; This clobbers a lot of ACs! + SETZM XBOCOS(I) ; No current output segment now. + CONO PI,NETON + SETZM XBOBP(I) + SETZM XBOBC(I) + POP P,E + POP P,C + POP P,B + RET + +; TCPOFR - Force out partially-filled current output segment +; Must have NETOFF. +; Called by FORCE and CLOSE at MP level +; by TCPCLK at PI clock level +; Note that we try to never have stuff in the COS which would +; over-run our send window, by hanging in MP IOT. This will +; be slightly screwed up if the receiver suddenly decreases the window +; size, since this routine always sends the whole thing anyway, +; but it's probably OK (helps avoid SWS) +; I/ TCB index +; T/ additional flags to use (PUSH, URG, FIN) +; Clobbers R and everything that TSOSND does (a lot!) + +TCPOFR: MOVE A,XBSTAT(I) ; Get flags for connection + TLNE A,(%XBCTL) ; Wants anything added on? + IOR T,A ; Yes, OR the bits in. + JUMPL A,TCPOF6 ; If locked at MP level, don't send it! + SKIPN R,XBOCOS(I) ; See if current output seg exists + JRST TCPOF5 ; No, can't hack now. + HLRZ TT,R ; Get # bytes of original buffer size + JUMPE TT,TCPOF5 ; If none, nothing to hack. + SUB TT,XBOBC(I) ; Subtract # left, to get # bytes data + CAIG TT, + JRST [ SETZ TT, ; No data, see if a flag wants to be sent. + TLNN T,(TC%FIN+TC%ACK+TC%SYN) ; Any of these are impt. + JRST TCPOF9 ; Nope, do nothing. + JRST .+1] + DPB TT,[PK$TDL (R)] ; Store back # bytes of real data + AND T,[TH%CTL] ; Mask off the flags + IORM T,XBSTAT(I) ; Stuff in as requests + TRCPKT R,"TCPOFR Force send" + CALL TSOSND ; Send out the stuff + SETZM XBOCOS(I) + SETZM XBOBP(I) + SETZM XBOBC(I) +TCPOF9: RET + + ; No current output segment, so no data to send. Check, though, + ; to see if any flags need sending. +TCPOF5: TLNN T,(TC%SYN+TC%ACK+TC%FIN) + RET ; Nope, just return. + MOVE E,T ; They do! Save em against smashage + CALL PKTGFI ; Try to get a buffer (clobbers T,Q) + JRST TCPOF6 ; Ugh, failed, see about setting flags. + MOVEI R,(A) + TRCPKT R,"TCPOF5 Alloc and send flags only in TCPOFR" + MOVE T,E ; Restore flags + CALL TSOSNR ; Set up the packet and send it! + RET + + ; Can't get packet now, so set up the request flags for later hacking. + ; Also comes here when current output seg is locked at MP level. +TCPOF6: AND T,[%XBCTL] ; Clear out extraneous bits + TLO T,(%XBNOW) ; Ask to send stuff immediately + IORM T,XBSTAT(I) ; and set flags back. + RET + +; TCPOSB - Routine similar to TCPOBW, except that it doesn't hang, +; so that it is suitable for calling at PI level (by STYNTC esp) +; Returns .+1 if can't set up output buffer for writing. +; Returns .+2 if output buff is all set up, with non-zero XBOBC. + +TCPOSB: SKIPE R,XBOCOS(I) + JRST [ HLRZ A,R ; Have COS, see if already set up + JUMPN A,TCPOS5 ; Jump if so. + JRST TCPOS2] ; Else just set it up. + + ; No current segment, get a new one. + HRRZ T,XBSTAU(I) ; First ensure output state is OK. + SKIPG TCPTBO(T) ; Skip if still OK to output. + RET ; Blooie. + CALL PKTGFI ; Get one, skip if successful + RET ; Sigh... + MOVEI R,(A) ; Set up in std AC + TRCPKT R,"TCPOSB Alloc for STYNET output data" + HRRZM R,XBOCOS(I) ; Store ptr + + ; Set up segment for IOT to deposit into. +TCPOS2: MOVEI T,%TCPMO ; Get max # segments allowed on queue + CAMG T,XBORTL(I) ; Fail if we have more than this. + RET + CALL TSOINI ; Initialize the segment (set up W, H) + LDB A,[PK$TDO (R)] ; Find offset data should start at. + TRNE A,3 + BUG HALT ; Should always start at wd boundary! + LSH A,-2 ; Find # words + ADDI A,(H) ; Add address of TCP header, + HRLI A,441000 ; and now we have our initial BP. + MOVEM A,XBOBP(I) ; Set it up. + LDB A,[PK$TDL (R)] ; Get max length avail in this segment + + ; Now have a fresh buffer and nothing else to wait for. + ; Freeze the world, make sure it's still OK to output, and find + ; out how big an output segment we can allow. +TCPOS4: CONO PI,NETOFF + HRRZ T,XBSTAU(I) ; Still OK to output? Check again. + SKIPG TCPTBO(T) + JRST [ MOVEI A,(R) ; Bah, must return buffer. + CALL PKTRTA + SETZM XBOCOS(I) + CONO PI,NETON + RET] ; Barf "Chan not open". + MOVEI T,(I) ; Get index in T for testing (no PCLSR) + CALL TCPOB9 ; Check available window + JRST NETONJ ; Window too small, just return + + LDB Q,[PK$TDL (R)] ; Get max # bytes available + CAMLE Q,XBSAVW(I) ; Greater than window? + MOVE Q,XBSAVW(I) ; Yeah, truncate down to this size. + HRLM Q,XBOCOS(I) ; Store original # bytes in LH of XBOCOS + MOVEM Q,XBOBC(I) + CONO PI,NETON + AOS (P) + RET ; Okay, all set up, return. + + ; Here when we were all set up, and output has used up all + ; of the buffer space initially available. Check to make sure + ; there isn't more we can fill out, and if not then fire off + ; the segment. +TCPOS5: HLRZ T,XBOCOS(I) ; Get # bytes we originally had + CONO PI,NETOFF ; Avoid magic changes in send window + CAML T,XBSAVW(I) + JRST TCPOS6 ; Send window same or smaller (!), send seg. + MOVE Q,XBSAVW(I) ; Send window is bigger! Get new size + LDB A,[PK$TDL (R)] ; Get max size + CAMLE A,Q + MOVEI A,(Q) ; Use minimum of max size and send window. + MOVEI Q,(A) ; Save result + SUBI A,(T) ; Find # more bytes we can hack + CAIG A, ; If there's no more, + JRST TCPOS6 ; Just send it off anyway. + HRLM Q,XBOCOS(I) ; Hurray, got more! Store new original # + MOVEM A,XBOBC(I) ; And set up new count + CONO PI,NETON + AOS (P) + RET ; And return happily. + +TCPOS6: TRCPKT R,"TCPOS6 STYNET Send" + CALL TCPOB7 + JRST TCPOSB + +TCPBI: +TCPBO: RET ; No-ops, labels left in case want to use. + +; STATUS - from LH(DTSTB) +; Must return status in LH(D). Must not smash C,R. +; R/ addr of IOCHNM word + +TCPSTA: HLRZ I,(R) ; Get TCB index + SKIPN XBUSER(I) ; Probably an error if this is zero. + BUG CHECK,[TCP: STATUS on unused conn ],OCT,I + SETZ D, + SKIPN XBSTAT(I) + RET + HRRZ A,(R) ; Find whether input or output + CAIN A,TCPDUI + SKIPA T,[TXBIST] + MOVEI T,TXBOST + CALL (T) + DPB T,[140600,,D] + RET + + +TXBIST: HRRZ T,XBSTAT(I) + CAIL T,.XSTOT + BUG HALT + SKIPGE T,XBCTBI(T) ; Get conversion + JRST [ SKIPN XBITQH(I) ; Must test for input avail - any segs? + SKIPA T,(T) ; None avail, use standard + MOVE T,1(T) ; Have some waiting, use alternate state + RET] + RET +XBCTBI: OFFSET -. +.XSCLS:: SETZ [%NTCLS ? %NTCLI] ; 0 Closed +.XSSYQ:: 0 ; Technically this is an impossible state... +.XSLSN:: %NTLSN ; 1 Listen +.XSSYN:: %NTSYN ; 4 Syn-Sent +.XSSYR:: %NTSYR ; 2 Syn-Rcvd +.XSOPN:: SETZ [%NTOPN ? %NTINP] ; 5/11 Established (open) +.XSFN1:: SETZ [%NTOPN ? %NTINP] ; 7 Fin-Wait-1 +.XSFN2:: SETZ [%NTOPN ? %NTINP] ; 7 Fin-Wait-2 +.XSCLW:: SETZ [%NTCLU ? %NTCLI] ; 3/10 Close-Wait +.XSCLO:: SETZ [%NTCLS ? %NTCLI] ; 7/10 Closing +.XSCLA:: SETZ [%NTCLS ? %NTCLI] ; 7 Last-Ack +.XSTMW:: SETZ [%NTCLS ? %NTCLI] ; 7 Time-Wait +.XSTOT:: OFFSET 0 + + +TXBOST: HRRZ T,XBSTAT(I) + CAIL T,.XSTOT + BUG HALT + SKIPGE T,XBCTBO(T) ; Get conversion + JRST [ SKIPN XBORTQ(I) ; Must test for output queued + SKIPA T,(T) ; None, use standard + MOVE T,1(T) ; Have some output waiting, use alternate state + RET] + RET +XBCTBO: OFFSET -. +.XSCLS:: %NTCLS ; 0 Closed +.XSSYQ:: 0 ; Technically this is an impossible state... +.XSLSN:: %NTLSN ; 1 Listen +.XSSYN:: %NTSYN ; 4 Syn-Sent +.XSSYR:: %NTSYR ; 2 Syn-Rcvd +.XSOPN:: SETZ [%NTOPN ? %NTWRT] ; 5/6 Established (open) +.XSFN1:: %NTCLX ; 7 Fin-Wait-1 +.XSFN2:: %NTCLX ; 7 Fin-Wait-2 +.XSCLW:: SETZ [%NTOPN ? %NTWRT] ; 5/6 Close-Wait +.XSCLO:: %NTCLX ; 7 Closing +.XSCLA:: %NTCLX ; 7 Last-Ack +.XSTMW:: %NTCLX ; 7 Time-Wait +.XSTOT:: OFFSET 0 + + + +; WHYINT - from RH(DTSTB) +; Results are: +; A/ %WYTCP +; B/ +; C/ input - # bytes in input buff +; output - # bytes of room avail in output buff +; D/ Close reason (only valid if state %NTCLS) + +TCPWHY: HLRZ I,(R) ; Get TCB index + METER("TCP: syscal whyint") + CAIL I,XBL + BUG HALT,[TCP: WHY idx bad] + CALL TCPSTA + LDB B,[140600,,D] ; Get state for channel + HRRZ A,(R) ; Find whether input or output + CAIN A,TCPDUI + JRST [ HLRZ D,XBCLSU(I) ; Get input close reason + MOVSI C,(XB%STY) + TDNE C,XBUSER(I) ; No input avail if direct-conn to STY + JRST [ SETZ C, ? JRST TCPWH5] + SKIPLE C,XBINBS(I) + JRST TCPWH5 + SKIPN C,XBITQH(I) + JRST TCPWH5 + LDB C,[PK$TDL (C)] + JRST TCPWH5] + HRRZ D,XBCLSU(I) ; Get output close reason + SKIPN C,XBOBC(I) ; Get # bytes of room left in current pkt + JRST [ MOVEI C,%TCPMO ; If none, return total queue space instead + SUB C,XBORTL(I) + IMUL C,XBSMSS(I) + CAIG C, + SETZ C, + JRST .+1] +TCPWH5: MOVEI A,%WYTCP + JRST POPJ1 + + + +; RFNAME - from LH(DRFNTB) +; A/ LH of IOCHNM word for channel. + +TCPRCH: MOVEI I,(A) + LDB B,[.BP TH%DST,XBPORT(I)] + LDB C,[.BP TH%SRC,XBPORT(I)] + MOVE D,XBHOST(I) + MOVEI W,4 + POPJ P, + +; RFPNTR - from RH(DRFNTB) +TCPRFP: JRST OPNL34 + +; IOPUSH/POP - from LH(RSTBI) +TCPIOP: HRRZ T,R + SUBI T,IOCHNM(U) + CAIN I, + SKIPA T,[77] ; IOPUSH, use 77 + ADDI T,1 ; IOPOP, use chan+1 + HLRZ I,(R) ; Get TCB index + HRRZ B,(R) ; Get direction + CAIN B,TCPDUI ; as a BP to chan # + SKIPA B,[XB$ICH (I)] + MOVE B,[XB$OCH (I)] + DPB T,B ; Store new saved channel # + POPJ P, + +; RESET - from RH(RSTBI) +; This doesn't have to do anything for a while yet. +TCPRST: + POPJ P, + +; FORCE - from LH(DFRCTB) +; Should force out the TCP segment currently being written, +; and give it a good shove (ie PUSH). +; A/ LH of IOCHNM word, in RH. +; H/ IOCHNM word +; R/ ,, +TCPFRC: METER("TCP: syscal force") + HRRZ B,(R) ; This should be a TCP output channel. + CAIE B,TCPDUO ; If not output, must be input, so + JRST OPNL2 ; say "wrong direction". + HLRZ I,(R) ; Get TCB index + CAIL I,XBL ; Ensure validity + BUG HALT,[TCP: FRC bad idx] + + ; Ensure that state allows sending anything. + CONO PI,NETOFF ; So state doesn't change while we think. + HRRZ J,XBSTAT(I) + CAIE J,.XSOPN + CAIN J,.XSCLW + CAIA + JRST OPNL7 ; Bad state, say "device not ready". + + PUSH P,R + MOVSI T,(TC%PSH) ; Set PUSH flag (but not ACK, to avoid + ; forcing send of empty buffer) + CALL TCPOFR ; Force out! Clobber many ACs. + CONO PI,NETON + POP P,R + JRST POPJ1 + + +; FINISH - from RH(DFRCTB) +; We already know that R is OK since FORCE looked at it first. +; In fact, I is still set up. +; R/ addr of IOCHNM word + +TCPFIN: METER("TCP: syscal finish") + MOVSI T,(%XBNOW) + TDNE T,XBSTAT(I) ; Wait until this bit is off (XBOCOS put on Q) + CALL UFLS + SKIPE XBORTQ(I) ; Hang until retransmit queue is empty. + CALL UFLS + JRST POPJ1 + +SUBTTL TCP STY connection routines + +; STYTCP - invoked by STYNTC routine during 1/2 sec clock, for +; STYs connected to TCP channels. +; R/ TTY # + +STYTCP: MOVE I,STYNTI-NFSTTY(R) ; Get TCB index for connection + LDB TT,[XB$STY (I)] ; Verify that TCB thinks we're hooked up + CAIE TT,(R) + BUG ; It doesn't?? + + ; First, check for and transfer any input for the STY. + HLRZ T,XBSTAU(I) ; Get input state + SKIPG TCPTBI(T) ; Make sure we can do input. + JRST STYTC9 ; Nope, must disconnect. +STYTC1: SOSGE XBIBC(I) + JRST [ CALL TCPIBD ; Discard input buffer if any + HRRZ A,XBITQH(I) ; Any more input avail? + JUMPE A,STYTC5 ; No, done, check for output. + CALL TCPIBG ; Have some! Set it up. Shd never hang. + JFCL + JRST STYTC1] + ILDB A,XBIBP(I) ; Get the byte + TRNE A,200 ; Special char? + JRST [ AOS XBIBC(I) ; Ugh, must back up and get user's attention + MOVSI B,8._14 ; Back up both count and 8-bit byte pointer + ADDM B,XBIBP(I) ; by adding to P field of BP + JRST STYTC9] ; Go disconnect. + EXCH R,I ; I gets TTY #, R gets TCB index + PUSH P,R + PUSH P,I + CONO PI,TTYOFF + CALL NTYI5 ; Give the char to TTY input interrupt level + CONO PI,TTYON + POP P,R ; Note reverse order, so R gets TTY # + POP P,I ; and I gets TCB index again. + JRST STYTC1 ; Try for more input. + + ; Transfer chars from STY output to TCP connection +STYTC5: SKIPGE TTYOAC(R) ; Do we have any output? + JRST STYTC7 ; No, all's done, force out what we did. + HRRZ A,XBSTAU(I) ; Check output state + SKIPG TCPTBO(A) ; to verify that TCB is healthy. + JRST STYTC9 ; Ugh, go disconnect STY. + MOVSI A,(%XBMPL) + IORM A,XBSTAT(I) ; Lock COS against PI level snarfing + + SKIPE XBOCOS(I) + SKIPG E,XBOBC(I) ; Get # bytes room in output buff + JRST [ + ; Set up buffer, etc, possibly forcing out existing buff. + PUSH P,R + CALL TCPOSB ; Invoke special hang-less routine. + JRST [POP P,R ; If can't get any more room, jump to STYTC6 + JRST STYTC6] + POP P,R + SKIPG E,XBOBC(I) ; OK, should have bytes now. + BUG + JRST .+1] + SKIPN D,XBOBP(I) ; Get BP into buffer + BUG + EXCH R,I + CONO PI,TTYOFF + MOVEM D,DBBBP ; Set up buffer for TTY output interrupt level + MOVEM E,DBBCC + MOVEM E,DBBCC1 + PUSH P,R + SETOM TYPNTF + PUSHJ P,TYP ; Generate output + SETZM TYPNTF + POP P,R + EXCH R,I ; Restore I/ TCB #, R/ TTY # + MOVE D,DBBBP ; Advance pointers + MOVEM D,XBOBP(I) + MOVE E,DBBCC + SUB E,DBBCC1 ; Minus # chars output generated + CONO PI,TTYON + ADDM E,XBOBC(I) + JRST STYTC5 ; Check for more output + + ; No more output or we can't get more room, force out what + ; we've currently got. +STYTC6: CALL TCPUII ; Reactivate STY (expensive crock, but...) +STYTC7: MOVSI A,(%XBMPL) ; Unlock the COS + ANDCAM A,XBSTAT(I) + MOVSI T,(TC%PSH) ; PUSH this stuff + CALL TCPOFR ; Force out buffer + JRST STYNT8 ; Then go check other STYs. + + + ; Disconnect STY and get user's attention. Note this may be + ; buggy in that STY output has not yet been transferred to the + ; net by the time we get here, if we're here due to a 200 char. +STYTC9: PUSH P,I + MOVEI I,(R) ; Set up I/ TTY # + CALL NSTYN0 ; Disconnect it + BUG + POP P,I + CALL TCPUII ; Wake up the user program + JRST STYNT8 ; Go handle other STYs. + +IFN 0,[ +;CALLED AT CLOCK LEVEL FROM STYNTC WHEN A CHAOS STY IS ENCOUNTERED +;TTY NUMBER IN I & R +STYCHA: MOVE I,STYNTI-NFSTTY(R) ;GET CHAOS INDEX + MOVE TT,CHSSTA(I) + TLNN TT,%CFSTY + JRST 4,. ;CHAOS CONNECTION CLAIMS NOT BE CONNECTED? + JUMPL TT,STYCH9 .SEE %CFOFF ;OK TO USE? IF NOT, DISCONNECT + SKIPGE TTYOAC(R) ;ANY OUTPUT? + JRST STYCH1 ;NO, CHECK FOR INPUT + SKIPN D,CHSOBP(I) ;IF BUFFER ALLOCATED, USE IT + JRST [ SKIPG CHSNOS(I) ;OTHERWISE ALLOCATE ONE + JRST STYCH1 ;WINDOW FULL, WAIT UNTIL REACTIVATED + PUSHJ P,CHABGI + JRST STYCH3 ;NO CORE, WAIT ONE CLOCK TICK + MOVEI D,%CPKDT(A) + HRLI D,440800 + MOVEM D,CHSOBP(I) + MOVEI E,%CPMXC + MOVEM E,CHSOBC(I) + JRST .+3 ] + SKIPG E,CHSOBC(I) + JRST STYCH4 ;BUFFER FULL, FORCE IT + EXCH R,I ;I GETS TTY, R GETS CHAOS + CONO PI,TTYOFF + MOVEM D,DBBBP ;SET UP BUFFER FOR TTY OUTPUT INTERRUPT LEVEL + MOVEM E,DBBCC + MOVEM E,DBBCC1 + PUSH P,R + SETOM TYPNTF + PUSHJ P,TYP ;GENERATE OUTPUT + SETZM TYPNTF + POP P,R + EXCH R,I ;I GETS CHAOS, R GETS TTY + MOVE D,DBBBP ;ADVANCE POINTERS + MOVEM D,CHSOBP(I) + MOVE E,DBBCC + SUB E,DBBCC1 ;MINUS # CHARS OUTPUT GENERATED + CONO PI,TTYON + ADDM E,CHSOBC(I) +STYCH4: PUSHJ P,CHAFC1 ;FORCE THE BUFFER + JRST STYCHA ;CHECK FOR MORE OUTPUT + +STYCH3: PUSHJ P,CHINTI ;REACTIVATE SO WILL COME BACK ON NEXT CLOCK TICK +STYCH1: SOSGE CHSIBC(I) ;GET INPUT, IF ANY + JRST [ PUSHJ P,CHAIBD ;DISCARD EXHAUSTED INPUT BUFFER, IF ANY + HLRZ A,CHSIBF(I) + JUMPE A,STYNT8 ;NONE, RETURN TO STYNTC + LDB TT,[$CPKOP(A)] + CAIE TT,%CODAT + JRST STYCH9 ;RANDOM PACKET, DISCONNECT + PUSHJ P,CHPKIA ;ACKNOWLEDGE GOBBLING OF THIS PACKET + SOS CHSNBF(I) ;REMOVE BUFFER FROM RECEIVE LIST + MOVEI Q,CHSIBF(I) + PUSHJ P,CHAQGF + LDB E,[$CPKNB(A)] ;SET UP FOR BYTE STREAM INPUT + MOVEM E,CHSIBC(I) + MOVEI D,%CPKDT(A) + HRLI D,440800 + MOVEM D,CHSIBP(I) + JRST STYCH1 ] + ILDB A,CHSIBP(I) ;GET CHARACTER OF INPUT + TRNE A,200 + JRST [ AOS CHSIBC(I) ;WOOPS, SPECIAL CHARACTER, NEEDS USER ATTENTION + MOVSI A,8_14 ;SO PUT IT BACK AND DISCONNECT + ADDM A,CHSIBP(I) + JRST STYCH9 ] + EXCH R,I ;I GETS TTY, R GETS CHAOS + PUSH P,R + PUSH P,I + CONO PI,TTYOFF + PUSHJ P,NTYI5 ;GIVE CHARACTER TO TTY INPUT INTERRUPT LEVEL + CONO PI,TTYON + POP P,R + POP P,I ;I GETS CHAOS, R GETS TTY ((POP IN REVERSE ORDER)) + JRST STYCH1 ;TRY FOR MORE INPUT + +STYCH9: PUSH P,I + MOVE I,R ;I GETS TTY + PUSHJ P,NSTYN0 ;DISCONNECT THE STY + JRST 4,. + POP P,I ;I GETS CHAOS + PUSHJ P,CHINTI ;WAKE UP THE TELNET SERVER + JRST STYNT8 ;GO HANDLE OTHER STYS +] ;ifn 0 + +SUBTTL Other TCP system call functions + +; TCPRQ - Handle .CALL NETRFC, return port # of next pending +; request for connection (SYN). +; Perhaps return a uniquizer in LH, so know when see +; the same request again? + +TCPRQ: TRNE C,%NQREF ; Skip if just getting, not flushing. + JRST TCPRQ5 + METER("TCP: syscal netrfc get") + CONO PI,NETOFF ; In case a RST comes for it or something. +; MOVE I,TCPRQL ; Get last thing stored on queue + SETOB B,D ; Look for any match + CALL TCPRQS ; Search the queue... + JUMPL A,OPNL4 ; None, say "file not found". + MOVEI I,(A) + LDB A,[.BP TH%DST,XBPORT(I)] ; Get local port # for the SYN + HRLI A,(I) ; And put index in LH as uniquizer. + CONO PI,NETON + JRST POPJ1 + +TCPRQ2: BUG CHECK,[TCP: Pending SYN smashed!] + RET + + ; Refuse indicated connection. +TCPRQ5: METER("TCP: syscal netrfc ref") + CAIGE W,2 ; Must have 2 args + JRST OPNL30 ; "Too few args" + HLRE D,A ; Get identifier + HRRE B,A + CONO PI,NETOFF + CALL TCPRQS ; Search for the queued SYN + JUMPL A,OPNL4 + + ; Now must refuse connection. + MOVEI I,(A) + MOVEI Q,XBITQH(I) + CALL PKQGF(PK.TCP) ; Get queued SYN segment + SKIPN XBITQH(I) ; Should have been only one + SKIPG R,A ; and should have been one! + BUG HALT + CALL TXBFLS ; Flush the TCB. + SOSGE TCPRQN ; Decrement count of queued SYNs + BUG HALT + HLRZ W,PK.IP(R) ; Move all this setup somewhere modular. + HLRZ H,PK.TCP(R) + LDB TT,[PK$TDL (R)] + MOVE E,TH$CTL(H) + TLNE E,(TC%SYN) + ADDI TT,1 + TLNE E,(TC%FIN) + ADDI TT,1 + CALL TSISLR ; Respond to this req with RST+ACK + CONO PI,NETON + JRST POPJ1 + +; TCPRQS - Search pending-RFC queue. Must be called with NETOFF!! +; B/ local port # (-1 for any) +; D/ Index #, -1 for any (searches back from last one stored) +; Clobbers T,Q +; Returns +; A/ Index to matching SYN (-1 if no match) + +TCPRQS: JUMPGE D,TCPRQ7 + MOVE A,TCPRQL + MOVEI C,1 +TCPRQ6: HRRZ T,XBSTAT(A) ; See if right state + CAIN T,.XSSYQ + JRST [ LDB T,[.BP TH%DST,XBPORT(A)] + CAIL B, + CAMN T,B + RET + JRST .+1] + SOJGE A,TCPRQ6 + MOVEI A,XBL-1 + SOJGE C,TCPRQ6 +TCPRQ9: SETO A, + RET + +TCPRQ7: SKIPL A,D + CAIL D,XBL + JRST TCPRQ9 + HRRZ T,XBSTAT(A) ; Verify state + CAIE T,.XSSYQ + JRST TCPRQ9 + LDB T,[.BP TH%DST,XBPORT(A)] ; Got one! Get local port # + CAIL B, + CAIN T,(B) ; Must match given arg unless -1 + RET ; Won! + JRST TCPRQ9 + +ifn 0,[ +TCPRQS: MOVEI A,TCPRQH-PK.TCP +TCPRQ6: MOVEI Q,(A) ; Save ptr to prev node + HRRZ A,PK.TCP(A) ; Get ptr to next PE + JUMPE A,TCPRQ8 ; If not there, return 0 as error. + JUMPL D,TCPRQ7 + CAIE A,(D) ; See if identifier matches + JRST TCPRQ6 ; Jump if not. +TCPRQ7: HLRZ T,PK.TCP(A) ; Yes, verify port number + CAIN T, ; Ensure ptr to TCP header exists. + BUG HALT + LDB T,[TH$DST (T)] + CAIE T,(B) + JRST TCPRQ6 ; Nope, get next thing. + + ; Found it! Take off list, a bit tricky. + SOSGE TCPRQN ; Decrement count of entries + BUG HALT + MOVSI T,(%PQFL2) ; Clear the on-list flag for PK.TCP + ANDCAM T,PK.FLG(A) +IFN 2-PK.TCP,.ERR TCPRQS must fix %PQFL2 to match PK.TCP + HRRZ T,PK.TCP(A) ; Get its next-ptr + HRRM T,PK.TCP(Q) ; Store in node previous to this one. + JUMPN T,TCPRQ8 ; If wasn't last thing, all's well. + CAIN Q,TCPRQH-PK.TCP ; Last thing. If prev was actually hdr, + SETZ Q, ; must store zero. + HRLM Q,TCPRQH ; Set new "last" ptr in hdr. +TCPRQ8: + RET + +] ;ifn 0 + +; TSOINI - set up a raw PE for use as a TCP output segment. Means +; setting IP, TCP header pointers properly, so that all fields +; are contiguous. Note that PK.TCI is set to indicate XBSMSS(I) +; bytes of (available) data storage! +; Sets up PK.IP, PK.TCP, and PK.TCI. +; R/ PE ptr +; I/ TCB connection index (val put into PK.TCI) +; Returns with R, W, H pointing to PE, IP hdr, and TCP hdr. +; +; TSOINA - Ditto, but takes arg in A and only clobbers T (doesn't set W, H) + + +TSOINI: HRRZ W,PK.BUF(R) ; Get addr of buffer + HRLM W,PK.IP(R) ; Store as IP header addr + MOVEI H,(I) ; Set up TCI with all fields. + ANDI H,PK%TCB + IOR H,[<<%TCPHL*4>_<.TZ PK%TDO,>>] + MOVEM H,PK.TCI(R) ; + MOVE H,XBSMSS(I) ; Allow XBSMSS(I) bytes with assumed offset. + DPB H,[PK$TDL (R)] + MOVEI H,%TCPHL(W) ; For now, this will do. + HRLM H,PK.TCP(R) ; Store as TCP header addr + RET + +TSOINA: HRRZ T,PK.BUF(A) ; Get addr of buffer + HRLM T,PK.IP(A) ; Store as IP header addr + ADDI T,%TCPHL ; For now, this will do to get TCP hdr. + HRLM T,PK.TCP(A) ; Store as TCP header addr + MOVEI T,(I) ; Set up TCI with all fields. + ANDI T,PK%TCB + IOR T,[<<%TCPHL*4>_<.TZ PK%TDO,>>] + MOVEM T,PK.TCI(A) ; Set up index and header length fields + MOVE H,XBSMSS(I) ; Allow XBSMSS(I) bytes with assumed offset. + DPB H,[PK$TDL (R)] + RET + +; TCPUSI - TCP User State-change Interrupt. Called each time connection +; changes state (.XSnnn) or I/O queues start/end. Always tries +; to interrupt user, except for change %NTWRT->%NTOPN on output +; and %NTINP->%NTOPN on input. +; Moon: Interrupt when input rcvd and buff empty, or output full +; and becomes reasonably non-full. +; Clobbers T, Q + +TCPUSI: METER("TCP: tcpusi called") + CALL TXBIST ; Check input state + HLRZ Q,XBSTAU(I) + CAIE T,(Q) ; New state? + JRST TCPUS3 ; Yes, go handle. +TCPUS2: CALL TXBOST + HRRZ Q,XBSTAU(I) + CAIN T,(Q) + RET + + ; Output channel state change + ; Q/ old state, T/ new state (%NT values, not .XS) + HRRM T,XBSTAU(I) ; Store new state (old in Q) + CAIN Q,%NTOPN ; If was open + CAIE T,%NTWRT ; Changing to buff-full + CAIA + RET ; Then don't interrupt. + MOVE Q,TCPTBO(Q) + CAMN Q,TCPTBO(T) ; See if meta-state change + RET ; Nope, ignore. + LDB Q,[XB$OCH (I)] ; Yes, get channel # + METER("TCP: User O ints") + CALRET TCPUS5 + + ; Input channel state change +TCPUS3: HRLM T,XBSTAU(I) ; Store new state (old in Q) + CAIN Q,%NTINP ; If was input avail + CAIE T,%NTOPN ; Changing to plain open + CAIA + JRST TCPUS2 ; Then don't interrupt. + MOVE Q,TCPTBI(Q) + CAMN Q,TCPTBI(T) ; See if meta-state change + JRST TCPUS2 ; No + ; Drop thru to interrupt + + ; Give input channel interrupt +TCPUII: METER("TCP: User I ints") + LDB Q,[XB$STY (I)] ; See if hooked to STY + JUMPN Q,TCPUSS ; Jump to handle STY stuff if so. + LDB Q,[XB$ICH (I)] ; No, just get input chan + CALL TCPUS5 + JRST TCPUS2 + + ; Give interrupt to STY that TCB is connected to. + ; Q/ TTY # +TCPUSS: CONO PI,PIOFF ; Protect list hacking + SKIPL STYNTL-NFSTTY(Q) ; Don't put on list twice + JRST PIONJ + MOVE T,STYNTA ; Add to list + MOVEM T,STYNTL-NFSTTY(Q) + MOVEM Q,STYNTA + JRST PIONJ + + ; Interrupt on channel in Q. +TCPUS5: JUMPE Q,CPOPJ ; May be no channel there. + PUSH P,U + SKIPN U,XBUSER(I) + BUG HALT ; Jumpe above should catch this. + MOVSI T,(SETZ) + IORM T,PIRQC(U) + CAIN Q,77 ; If IOPUSH'ed, no interrupt. + JRST POPUJ + MOVE T,CHNBIT-1(Q) ; Q is -1 based. + AND T,MSKST2(U) + IORM T,IFPIR(U) + POP P,U + RET + + ; Input chan state type. Pos # means can read. + ; 0 is pre-open, 1 is open, 2 is input avail, -1 is post-open. +TCPTBI: OFFSET -. +%NTCLS:: 0 ; 0 CLS +%NTLSN:: 0 ; 1 LSN +%NTSYR:: 0 ; 2 RFC +%NTCLU:: -1 ; 3 RCL? +%NTSYN:: 0 ; 4 RFS +%NTOPN:: 1 ; 5 OPN +%NTWRT:: 1 ; 6 RFN +%NTCLX:: -1 ; 7 CLW +%NTCLI:: 1 ; 10 CLI +%NTINP:: 2 ; 11 INP + OFFSET 0 + + ; Output chan state type. Pos # means can write. + ; 0 is pre-open, 1 is open, 2 is buff full, -1 is post-open. +TCPTBO: OFFSET -. +%NTCLS:: 0 +%NTLSN:: 0 +%NTSYR:: 0 +%NTCLU:: 1 +%NTSYN:: 0 +%NTOPN:: 1 +%NTWRT:: 2 +%NTCLX:: -1 +%NTCLI:: 1 +%NTINP:: 1 + OFFSET 0 + + +SUBTTL TCP Input Interrupt Level + +; TCPIS - Process TCP Input Segment (PI level) +; R/ PE ptr to packet, not on any list. +; PK.BUF is set, ditto IP/TCP header pointers. +; W/ addr of IP header +; H/ addr of IP data (start of TCP header) +; J/ host-table index for address datagram received from. +; Can clobber all ACs except P, returns with POPJ. +; AC usage during incoming segment processing: +; R/ PE ptr to packet +; W/ addr of IP header +; H/ addr of TCP header +; I/ TCB index (if any) +; J/ TCB connection state +; TT/ # bytes of TCP data in segment +; E/ ,, +; D/ Segment Sequence no. +; Flags for RH of E +%TSISL==1 ; Seq starts to left of rcv.nxt +%TSISR==2 ; Seq starts to right of " ; if neither on, is = rcv.nxt +%TSIFL==4 ; Bad seq, flush after handling RST/ACK/URG + +TCPIS: METER("TCP: Segs rcvd") + SKIPN TCPUP ; Unless TCP claims to be up, + JRST TSIFL ; Throw it away, no TCP yet, sigh. + + ; First verify that this is a valid TCP segment, by + ; checksumming it (sigh!). TT gets total # bytes in TCP segment. + CALL THCKSI ; Get checksum in A for segment + LDB B,[TH$CKS (H)] ; Get segment's checksum + CAME A,B ; Should match. + JRST TSIF01 ; Failed, go bump err count and flush it. + LDB T,[TH$THL (H)] ; Find TCP header length in words + LSH T,2 ; Make it in octets + SUBI TT,(T) ; TT now has # octets of segment data. + + ; Contents of segment have been validated (more or less), + ; now set up convenient context values + ; PK.TCI contents + ; E/ Segment control flags (in LH) + ; TT/ SEG.LEN + HLLZ E,TH$CTL(H) ; Get word with segment control flags + DPB T,[PK$TDO (R)] ; Store offset of data (from THCKSI) + DPB TT,[PK$TDL (R)] ; Store length of data + TLNE E,(TC%SYN) ; Note that SYN counts in seg.len + ADDI TT,1 ; so allow for it + TLNE E,(TC%FIN) ; And do same thing for FIN. + ADDI TT,1 ; Either way, get SEG.LEN set up in TT. + + ; Then see if any TCB exists for this segment. + SKIPE A,TH$SRC(H) ; Get source/dest port word + SKIPN B,IP$SRC(W) ; Get source addr from IP header + JRST TSIF02 ; Flush anything with zero field. + LSH B,-4 ; Right-justify the addr + MOVSI I,-XBL +TSI02: CAMN A,XBPORT(I) ; Loop til we find it + CAME B,XBHOST(I) +TSI03: AOBJN I,TSI02 + JUMPL I,TSI05 ; Jump if found existing connection + JRST TSISQ ; Jump if no existing connection. + +TSI04: SKIPE XBSTAT(I) ; Found "closed" connection???? + JRST TSI02 ; LH must have crud still set, ignore for now + BUG CHECK,[TCP: Clsed TCB has active port/host] ; Shouldn't happen! + SETZM XBHOST(I) ; If continued, fix up. + JRST TSI02 + + ; Connection exists, TCB index now in I. + ; Set up a little more context (PK.TCI and J) +TSI05: DPB I,[PK$TCB (R)] ; Store TCB index in packet info + MOVEM J,XBNADR(I) ; Save host-table idx of addr this seg is from. + HRRZ J,XBSTAT(I) ; Get connection state + CAIL J,.XSTOT ; Highest possible state. + BUG HALT,[TCP: Bad conn state] + METER("TCP: IS all states") + XCT XSMTRS(J) ; Bump meter for each state + CAIG J,.XSSYN ; If it's CLS, SYQ, LSN or SYN-SENT + JRST @(J)[ ; then process specially. + TSI04 ; Closed??? + TSISQQ ; Syn-Queued? (Probably re-trans) + TSILS ; Listen + TSISS] ; Syn-sent + ; Drop through to perform general sequence-number checking. + + ; Check Sequence Number!!! + ; This code doesn't do two things: + ; 1) it doesn't keep around stuff that arrives to the + ; right of rcv.nxt. + ; 2) for situation where seg.seq number is valid, + ; (i.e. seq =< rcv.nxt) the code punts if + ; end of seg is out of window. It should simply + ; expand the window! + LDB D,[TH$SEQ (H)] ; Get sequence number + JUMPG TT,TSI10 ; Jump if data present. + JUMPL TT,TSIF03 ; No data. Jump if error (neg data!) + + ; No data in this segment, it is probably a simple ACK. + CAME D,XBRNXT(I) ; Seg.seq == snd.nxt (as expected?) + JRST TSI01 + METER("TCP: 0-len seg seq match") + JRST TSI20 ; Yep, seg is acceptable instantly! + +TSI01: SKIPN C,XBRWND(I) ; Have some receive window? + JRST TSI09 + ADD C,XBRNXT(I) ; Get nxt+wnd + TLZ C,%MOD32 ; all arith mod 32 + CMPSEQ XBRNXT(I),=<,D,<,C,TSI07,TSI08 + JRST TSI20 ; Within rcv window, buy it + +TSI07: METER("TCP: 0-len seg before rcv window") + JRST TSISNE + +TSI08: METER("TCP: 0-len seg after rcv window") + JRST TSISNE + + ; 0-data, 0-window, and SEG.SEQ != RCV.NXT +TSI09: METER("TCP: Ifl 0-len 0-window seqerr") + JRST TSISNE ; Sigh, flush it. + + ; Seq number check when data present. +TSI10: CAME D,XBRNXT(I) ; Is seq # what we expect (seq = nxt)? + JRST TSI11 + SKIPE C,XBRWND(I) ; Yes! And is our window open? + JRST TSI20 ; Yes! Fast dispatch! + + ; Data segment, with valid sequence number, but our window is + ; zero. See if there's some way we can avoid throwing away the + ; segment... if we can't take it then still must handle + ; ACK/URG/RST flags. For now, we really handle this at TSI70. +TSI12: METER("TCP: 0-wnd data seg") + JRST TSI20 + + ; Sequence # isn't exactly what we hoped for, see if the + ; segment overlaps a valid portion of sequence space. +TSI11: SKIPN C,XBRWND(I) ;#3: Get window, is it zero? + MOVEI C,512. ; If zero, substitute a dummy window. + + ; Both len>0 and wnd>0. + ADD C,XBRNXT(I) ; Get nxt+wnd + TLZ C,%MOD32 ; all arith mod 32 + ;#4a: nxt =< seq < nxt+wnd + CMPSEQ XBRNXT(I),=<,D,<,C,TSI13 ; Jump if fail this test, try 4b. + + ; Come here when sequence # is OK, but segment starts farther on + ; than we want, i.e. there is a "hole" between rcv.nxt and seg.seq. + ; Eventually we could keep this segment around, to speed up + ; throughput for nets that get packets out of order, but for + ; now we'll just flush it and force a retransmit. + METER("TCP: Iseg hole") + TRO E,%TSISR+%TSIFL ; Say starts to right, and flush later. + JRST TSI20 ; Go process RST/ACK/URG etc. + +TSIF12: METER("TCP: Ifl seq dup") ; Segment falls in prev rcvd data. + MOVE D,XBRNXT(I) ; Fake out, say seq # OK + TRO E,%TSIFL ; and don't process data. + JRST TSI20 ; Go handle RST/ACK/URG. + +TSIF13: METER("TCP: Ifl seq int err") ; Shouldn't ever happen, due to + JRST TSISNE ; right-bound check code above. +TSIF14: METER("TCP: Ifl seq old") + JRST TSISNE +TSIF15: METER("TCP: Ifl monster seg") ; Impossible error + JRST TSISNE + + ; Segment does not overlap window to right, so see if it + ; overlaps to left, i.e. sequence # falls within data we have + ; already received. +TSI13: MOVE A,XBRNXT(I) + SUBI A,%TCPMB ; Make a fictional lower bound + CAIGE A, + ADD A,[1_32.] ; Keep bound mod 2^32 + CMPSEQ A,=<,D,=<,XBRNXT(I),TSIF14,TSIF13 + + ; Yep, falls within received data. It's probably a duplicate + ; retransmitted segment; see if there's any new data on right side. + ; Note that we are not using XBRWND here, because as long as we + ; have a non-zero window we will always accept everything in the + ; segment. So we create another fictional bound to the right. + ADD A,[%TCPMB*2] ; Get back to other side of rcv.nxt + TLZ A,%MOD32 ; Keep mod 2^32 + MOVE C,D + ADDI C,-1(TT) ; Get seq+len-1 + TLZ C,%MOD32 + ;#4b: nxt =< seq+len-1 < nxt+wnd? + CMPSEQ XBRNXT(I),=<,C,=<,A,TSIF12,TSIF15 ; If fail this too, error. + + ; Aha, have some new data in spite of being overlapped with some + ; previously received data! Here, we + ; twiddle things so that it appears to start properly at + ; rcv.nxt. This is done without touching the segment contents + ; at all, just modifying the packet entry info. + METER("TCP: Iseg ovlap") + MOVE A,XBRNXT(I) ; Get rcv.nxt + CAMGE A,D ; Make sure it's greater than seg.seq + TLO A,(1_32.) ; Mod 2^32 screw, make it greater (add 33d bit) + SUB A,D ; Find # octets of sequence space diff + CAMLE A,TT ; Shouldn't be greater than seg.len!! + BUG CHECK,[TCP: Trim error] + SUBI TT,(A) + JUMPLE TT,TSIF12 ; If nothing left, drop this segment. + TLZE E,(TC%SYN) ; Clear SYN since it's at front. + SUBI A,1 ; If it was set, reduce cnt of actual data + LDB T,[PK$TDL (R)] ; that we're going to flush. Get cnt + SUBI T,(A) ; Decrement # valid data bytes in segment + DPB T,[PK$TDL (R)] ; Put back + LDB T,[PK$TDO (R)] ; Also adjust offset to valid data + ADDI T,(A) ; Increment to point at new data + DPB T,[PK$TDO (R)] ; Put back + MOVE D,XBRNXT(I) ; Now say seg.seq = rcv.nxt! + ; Segment sanitized, drop through. + SKIPN XBRWND(I) ; Only proceed if our window not zero. + JRST TSI12 ; It's zero! May have to flush it... + + ; Fall through to TSI20 for RST/ACK/URG processing. + + ; Now check RST +TSI20: TLNE E,(TC%RST) ; RST bit set? + JRST TSIRST ; Yeah, go process it. + + ; Now check security/precedence + JFCL ; ho ho ho + + ; Now check SYN bit +TSI40: TLNE E,(TC%SYN) ; SYN bit set? + JRST TSISYN ; Yeah, go process it (basically error) + + ; Now check ACK bit +TSI50: TLNN E,(TC%ACK) ; ACK bit set? + JRST TSIF50 ; No, error. Drop segment. + JRST @TSI51(J) ; Yes, dispatch depending on state. +TSI51: OFFSET -. +.XSCLS:: [JRST 4,TSI51] ; Closed +.XSSYQ:: [JRST 4,TSI51] ; ITS: Syn-Queued +.XSLSN:: [JRST 4,TSI51] ; Listen +.XSSYN:: [JRST 4,TSI51] ; Syn-Sent +.XSSYR:: TSI53 ; Syn-Rcvd +.XSOPN:: TSI54 ; Established (open) +.XSFN1:: TSI54 ; Fin-Wait-1 +.XSFN2:: TSI54 ; Fin-Wait-2 +.XSCLW:: TSI54 ; Close-Wait +.XSCLO:: TSI54 ; Closing +.XSCLA:: TSI54 ; Last-Ack +.XSTMW:: TSIATW ; Time-Wait +.XSTOT:: OFFSET 0 + + + ; SYN-RCVD state, handling ACK. +TSI53: LDB A,[TH$ACK (H)] ; Get ACK field + MOVE B,XBSUNA(I) ; Need one CMPSEQ arg in AC + ; Test: snd.una =< seg.ack =< snd.nxt + CMPSEQ B,=<,A,=<,XBSNXT(I),TSISRA ; Jump if fail + MOVEI J,.XSOPN ; ACK wins, we're now open! + HRRM J,XBSTAT(I) ; Set new state, fall through to handle. + CALL TCPUSI ; Adjust user state. + ; Must initialize SND.WL1, SND.WL2, and SND.WND. + ; Maybe later merge this with TSI55. + MOVEM A,XBSWL2(I) ; Yes! Update send window, set WL2 to ACK + MOVEM D,XBSWL1(I) ; and WL1 to SEQ + LDB B,[TH$WND (H)] + MOVEM B,XBSWND(I) ; and snd.WND to seg.WND. + MOVEM B,XBSAVW(I) ; and make avail window be same as send wind. + JRST TSI54X ; Skip repeating the ACK test. + + ; Handle ACK while in open state (also other receive-OK states) +TSI54: LDB A,[TH$ACK (H)] ; Get ACK field + MOVE B,XBSUNA(I) ; Need one CMPSEQ arg in AC + ; Test: snd.una =< seg.ack =< snd.nxt + ; If seg.ack < snd.una, go to TSI60 and ignore the ACK. + ; If seg.ack > snd.nxt, go to TSISAK to drop segment (ACKing) + CMPSEQ B,=<,A,=<,XBSNXT(I),TSI60,TSISAK ; Jump if fail + + ; ACK is fine. Update SND.UNA and clean up retransmit queue. +TSI54X: MOVEM A,XBSUNA(I) ; Update snd.una + + ; Must check retransmit queue slowly to find right place to flush, + ; if any. + ; Procedure is: (1) pull off 1st thing on queue. + ; (2) If the new 1st thing has a seq # =< snd.una, + ; then can flush what we pulled off, and try again. + ; (3) otherwise put it back on at front. +TSI54A: MOVE C,A ; Save ACK # in C +TSI54B: MOVEI Q,XBORTQ(I) ; Get pointer to retrans q + CALL PKQGF(PK.TCP) ; Get 1st thing on queue + JUMPE A,TSI54Z ; None left? Win! + TRCPKT A,"TSI54B Mabye flush from rexmit Q" + MOVE T,PK.FLG(A) ; Check packet flags, + TLNN T,(%PKODN) ; to make sure output was completed. + JRST TSI54Y ; Not done yet, so don't flush yet. + HRRZ B,XBORTQ(I) ; Get pointer to next thing + JUMPE B,[CAMN C,XBSNXT(I) ; No next thing, compare with snd.nxt + JRST TSI54D ; Equal, can flush! + JRST TSI54Y] ; If not equal, must have ack < snd.nxt + ; so previous segment can't be flushed. + HLRZ B,PK.TCP(B) ; Get addr of TCP hdr for 2nd queued segment + LDB B,[TH$SEQ (B)] ; Get sequence # for it +TSI54C: CMPSEQ B,=<,C,=<,XBSNXT(I),TSI54Y ; See if ACK comes after that # + + ; Hurray, matches or exceeds this seq #, + ; So we can flush the seg we pulled off! +TSI54D: TRCPKT A,"TSI54D Flushing from Q" + TLO T,(%PKFLS) ; Tell IP to forget it if queued + MOVEM T,PK.FLG(A) + CALL PKTRT ; Flush if not otherwise occupied +TSI54E: MOVE A,TIME ; Crock crock, set up new timeout. + ADD A,TCPTMO + MOVEM A,XBORTT(I) + SETZM XBORTC(I) ; Reset retry counts + SOSGE XBORTL(I) ; Decrement # segments on retrans q. + BUG HALT,[TCP: Retrans Q count error] + JRST TSI54B ; Keep going as long as we can. + +TSI54Y: MOVEI Q,XBORTQ(I) + CALL PKQPF(PK.TCP) ; Put back on front of queue +TSI54Z: MOVE A,C ; Restore ACK # to A. + + ; Now see if send window should be updated. + CAMN D,XBSWL1(I) ; Fast check first, WL1 = SEQ? + JRST TSI55C ; Yes, go check ACK then + MOVE T,XBSWL1(I) + ADDI T,-1 + TLZ T,%MOD32 + CMPSEQ XBSWL1(I),<,D,<,T,TSI56 ; Check if wl1 < seq < wl1+xxx + JRST TSI55 ; Yes, must update window. +TSI55C: MOVE T,XBSWL2(I) + ADDI T,-1 + TLZ T,%MOD32 + CMPSEQ XBSWL2(I),=<,A,=<,T,TSI56 ; Fall-thru win if snd.wl2 =< seg.ack + +TSI55: MOVEM A,XBSWL2(I) ; Yes! Update send window, set WL2 to ACK + MOVEM D,XBSWL1(I) ; and WL1 to SEQ + LDB B,[TH$WND (H)] + MOVEM B,XBSWND(I) ; and snd.WND to seg.WND. + ; Drop thru + + ; Either SND.UNA or SND.WND was probably updated, so lets update + ; SND.AVW also (available window). The following computes + ; WND - (NXT - UNA) and assumes UNA =< NXT. +TSI56: MOVE A,XBSNXT(I) + CAMGE A,XBSUNA(I) ; If need mod 32 wrap, + TLO A,(1_32.) ; wrap up the number that should be higher. + SUB A,XBSUNA(I) ; Find NXT-UNA (# bytes not yet acked) + CAIL A,0 + CAILE A,177777 ; Make simple check + BUG INFO,[TCP: Bad AVW calc, UNA=],OCT,XBSNXT(I),[NXT=],OCT,XBSUNA(I) + MOVE B,XBSWND(I) + SUBI B,(A) ; Find # bytes we can still send + CAIGE B, ; Make sure it's not negative! + SETZ B, + MOVEM B,XBSAVW(I) + + ; Done with ACK processing for OPEN state, see if must handle + ; idiosyncracies of other states. +TSI57: CAIN J,.XSOPN ; Skip other checks if state is OPEN (normal) + JRST TSI60 ; Go check for URG etc. + CAIN J,.XSCLW + JRST TSI80 + CAIN J,.XSFN1 + JRST [ SKIPE XBORTQ(I) ; If our FIN is ACK'd, enter FIN-WAIT-2 + JRST TSI60 ; Not yet. + MOVEI J,.XSFN2 ; Yes, FIN was ACKed, change state. + HRRM J,XBSTAT(I) + CALL TCPUSI ; Call this for any state change. + LDB T,[XB$ICH (I)] ; Do we have an input chan? + JUMPN T,TSI60 ; If so, CLOSE will handle the wrapup. + MOVE T,TIME ; No, must set timeout. + ADDI T,2*60.*30. ; Use 2*MSL + MOVEM T,XBORTT ; set timeout. + JRST TSI60] + CAIN J,.XSFN2 + JRST [ ; If retrans queue empty, transmit-chan CLOSE done. + JRST TSI60] + CAIN J,.XSCLO + JRST [ SKIPE XBORTQ(I) ; If our FIN is ACK'd, + JRST TSIF55 ; No-- flush the segment. + CALL TSITMW ; then enter TIME-WAIT state, start timeout. + JRST TSI80] ; Then go check for FIN, etc. + CAIN J,.XSCLA ; LAST-ACK waiting for ACK of our FIN. + JRST [ SKIPE XBORTQ(I) ; If our FIN has been ACK'd, + JRST TSIF56 ; No-- flush the segment. + METER("TCP: FIN acked in .XSCLA") + CALL TXBFLP ; Flush the TCB immediately, PI level + JRST TSIFL] ; then flush the segment. + BUG CHECK,[TCP: Bad ACK state] + + ; Check the URG bit. The only states which get to this + ; point are OPEN, FIN-WAIT-1, and FIN-WAIT-2. +TSI60: TLNN E,(TC%URG) ; Segment has urgent pointer set? + JRST TSI70 ; Nope, on to next step. + LDB A,[TH$UP (H)] ; Get SEG.UP (urgent ptr from segment) + + ; This is where URGENT should be handled!!!! + ; Drop through + + ; Finally process segment text! + ; Only states OPEN, FIN-WAIT-1 and FIN-WAIT-2 can get here. +TSI70: TRNE E,%TSIFL ; If segment being flushed after ACK/URG, + JRST TSIF70 ; flush it now! + + LDB A,[PK$TDL (R)] ; Find # bytes of real data in segment + JUMPLE A,TSI80 ; If none, no text processing. + + TLNE E,(TC%FIN) ; Check that # bytes data == seg.len + JRST [ CAIE A,-1(TT) ; Must allow for funny non-data FIN. + JRST TSI71 ; Nope + JRST TSI72] ; Yep + CAIE A,(TT) ; # bytes data should == seg.len +TSI71: BUG CHECK,[TCP: seglen error] +TSI72: SKIPE D,XBRWND(I) ; Note D used for flag, + JRST TSI75 ; and is non-zero if no compaction done. + + ; Our window is zero, and technically we should throw away the + ; data now that all RST/ACK/URG processing has been done. However, + ; we try to see if we can possibly do a little compaction, since + ; the overhead of doing this is a lot less than the overhead + ; of re-processing the re-transmitted segment! + MOVE A,XBINPS(I) ; Check length of input queue + CAIL A,2 ; Must be at least 2 + SKIPN XBITQH(I) + BUG CHECK,[TCP: Wind & Queue both 0] + + ; See if it's worth trying to compact the input seg into the + ; last one received (which hasn't yet been seen by MP level) + HLRZ A,XBITQH(I) ; Get ptr to last input seg on queue + LDB B,[PK$TDO (A)] ; Get offset to data in old seg + LDB C,[PK$TDL (A)] ; See how much data is there + LDB T,[PK$TDL (R)] ; Find # bytes in new segment + ADDI B,(C) ; Get offset to end of data + MOVEI D,(B) + ADDI D,(T) ; Get projected total offset + CAML D,XBRMSS(I) ; Crock method of ensuring enuf room. + JRST TSI17 ; Not enough, we lose. Lose. Lose. + + ; Win! We're gonna compact! + METER("TCP: Iseg cmpct") + ADDI C,(T) ; Get new # bytes for prev seg + DPB C,[PK$TDL (A)] ; Store it in advance. + HLRZ D,PK.TCP(A) ; Find addr of TCP header in prev seg + IDIVI B,4 + ADDI D,(B) ; Get addr for BP to end of data + HRL D,(C)[441000 ? 341000 ? 241000 ? 141000] ; Make LH + LDB B,[PK$TDO (R)] ; Get data offset for new segment + IDIVI B,4 + ADDI B,(H) ; Get addr for BP to start of new data + HRL B,(C)[441000 ? 341000 ? 241000 ? 141000] ; Make LH + ; B/ BP to new data + ; D/ BP to end of old data + ; T/ # bytes of new data + MOVEI A,(T) ; Save # added data in A +TSI74: ILDB C,B + IDPB C,D + SOJG T,TSI74 + SETZ D, ; Clear D to indicate compaction done. + JRST TSI75 + + ; Can't accept segment data, period. +TSI17: METER("TCP: Ifl 0-wnd") + JRST TSIFL ; Flush the seg, sob. + +TSI75: MOVEI B,(TT) + ADDB B,XBRNXT(I) ; Update rcv.nxt value by adding seg.len + TLZE B,%MOD32 + MOVEM B,XBRNXT(I) ; Updated! + LDB B,[XB$ICH (I)] ; See if we have an input channel # + JUMPE B,[METER("TCP: IS fl no chan") + JRST TSI78] ; No input channel, so just throw away. + MOVEI C,(A) ; Save # bytes data. + ADDM A,XBINBS(I) ; Add new bytes to # bytes in input queue + JUMPE D,TSI78 ; If compaction done, that's all... + SKIPE B,XBINPS(I) ; If no segments previously on queue, + MOVE B,XBIBC(I) ; or current input buff has zero cnt, + ; then will definitely interrupt user later. + AOS XBINPS(I) ; Bump # segments on queue + + ; Check to see how much to reduce window by. + ; Amount is in C (defaults to amount we just received) + CALL TCPRWS ; Set receive window + + ; Finally add segment to queue! + MOVEI A,(R) ; Set up pointer to packet/segment + MOVEI Q,XBITQH(I) ; Point to TCP input queue + CALL PKQPL(PK.TCP) ; Add to end of queue, using TCP links. + JUMPN B,TSI78 ; Check, jump unless had no input before + CALL TXBIST ; If none, then must definitely change state! + HRLM T,XBSTAU(I) ; + CALL TCPUII ; And always give an input-avail int! + + ; Now must send an ACK, or rather arrange for one to be + ; sent soon. FIN is also checked here, so as to bypass the + ; code which assumes that XBRNXT hasn't been updated (if we are + ; here, it certainly has!) +TSI78: MOVSI A,(TC%ACK) ; Set bit asking for ACK to be sent. + IORM A,XBSTAT(I) + TLNN E,(TC%FIN) ; Perform FIN-bit check + JRST TSI90 ; None, all done with segment! + JRST TSI82 ; FIN exists, handle it (bypass bump of XBRNXT) + + ; Lastly check the FIN bit. + ; Connection states which do not expect to receive data come here + ; directly from ACK processing. +TSI80: TRNE E,%TSIFL ; If duplicate segment being flushed after + JRST TSIF70 ; ACK/URG, flush it now! + TLNN E,(TC%FIN) + JRST TSI90 + CAIG J,.XSSYN + JRST TSIF80 ; Flush if CLOSED, LISTEN, SYN-SENT + + ; Advance RCV.NXT over the FIN + AOS A,XBRNXT(I) + TLZE A,%MOD32 + MOVEM A,XBRNXT(I) + + ; Rest of FIN processing, after processing new data in packet. + ; Ack FIN, update connection state, inform user. +TSI82: MOVSI A,(TC%ACK+%XBFIN) ; Set bit asking that ACK be sent, and FIN + IORM A,XBSTAT(I) ; was seen. + MOVEI T,.XCFRN ; Say foreign host closed input side. + CALL TCPUCI + + ; Now effect some state changes + CAIE J,.XSOPN ; If OPEN + CAIN J,.XSSYR ; or SYN-RCVD + JRST [MOVEI J,.XSCLW ; Change state to CLOSE-WAIT + JRST TSI85] + CAIN J,.XSFN1 + JRST [ SKIPN XBORTQ(I) ; If our FIN was ACK'd, + JRST TSI84 ; Go enter TIME-WAIT state + MOVEI J,.XSCLO ; Otherwise enter CLOSING state. + JRST TSI85] + CAIE J,.XSFN2 + CAIN J,.XSTMW + JRST TSI84 ; Go to TIME-WAIT + JRST TSI90 ; Any other states just do nothing. + +TSI84: CALL TSITMW ; Enter TIME-WAIT state, starting 2-MSL timeout + JRST TSI90 +TSI85: HRRM J,XBSTAT(I) ; Set new state and fall through. + CALL TCPUSI ; Set user state. + + ; Done. Finally decide whether to keep segment around or not. +TSI90: HLRZ A,XBITQH(I) ; Get ptr to last thing on input queue + CAIN A,(R) ; Same as current seg (ie it was queued?) + RET ; Yes, just return! + JRST TSIF90 ; Else drop through to flush the segment. + +XSMTRS: OFFSET -. +.XSCLS:: METER("TCP: state CLS") +.XSSYQ:: METER("TCP: state SYQ") +.XSLSN:: METER("TCP: state LSN") +.XSSYN:: METER("TCP: state SYN") +.XSSYR:: METER("TCP: state SYR") +.XSOPN:: METER("TCP: state OPN") +.XSFN1:: METER("TCP: state FN1") +.XSFN2:: METER("TCP: state FN2") +.XSCLW:: METER("TCP: state CLW") +.XSCLO:: METER("TCP: state CLO") +.XSCLA:: METER("TCP: state CLA") +.XSTMW:: METER("TCP: state TMW") +.XSTOT:: OFFSET 0 + + +TSIF01: METER("TCP: ISeg cksm errs ") + JRST TSIFL +TSIF02: METER("TCP: IS zero port/addr") + JRST TSIFL +TSIF03: METER("TCP: IS fl neg data") + JRST TSIFL +;TSIF10: ; Flush this later (retain til get new .METER LIST) + METER("TCP: IS fls Seq # err") + JRST TSIFL +TSIF50: METER("TCP: IS fls Seq no ACK ") + JRST TSIFL +TSIF55: METER("TCP: IS fls CLO & FIN not ACKed") + JRST TSIFL +TSIF56: METER("TCP: IS fls CLA & FIN not ACKed") + JRST TSIFL +TSIF70: METER("TCP: IS fls seqerr processed A/U/R") + JRST TSISNE ; Go respond with ACK +TSIF80: METER("TCP: IS fls FINchk state") + JRST TSIFL +TSIF2A: METER("TCP: IS fls random RST") + JRST TSIFL +TSIF2B: METER("TCP: IS fls Fresh SYN already on SYNQ") + JRST TSIFL + +TSIF90: METER("TCP: IS fls processed seg") + JRST TSIFL + + ; Come here to flush the datagram/segment and return. +TSIFL: METER("TCP: Isegs flushed") + MOVEI A,(R) + CALRET PKTRT + +; TSITMW - Routine to enter TIME-WAIT state. +; TSITM2 is entry point when already in that state. +; Clobbers T, Q +TSITMW: MOVEI J,.XSTMW + HRRM J,XBSTAT(I) + CALL TCPUSI ; Alert user if necessary. +TSITM2: SKIPE XBORTQ(I) ; Unless retransmit still hogs timeout + RET ; (if so, return) + MOVE T,TIME ; then set up 2-MSL timeout. + ADDI T,30.*2.*60. + MOVEM T,XBORTT(I) + RET + +; TSISNE - Sequence number error, segment not acceptable, +; return an ACK unless RST was set. + +TSISNE: METER("TCP: IS NE seqerr") + TLNE E,(TC%RST) + JRST TSIFL ; Flush segment if RST was set + + ; Send an immediate ACK without data, re-using the + ; packet/segment that R points to. +TSOACK: MOVSI T,(TC%ACK) ; Send an ACK immediately + TRCPKT R,"TSOACK return ACK in response to out-of-seq ACK" + CALL TSOSNR + RET + +; TSISQ - Jumped to from TCPIS when TCP segment is received that matches +; no existing connection. Check to see if it's a valid connection +; request. If so, +; (1) see if it matches any wild listens; if so, process. +; (2) see if it's OK to start up a server for it; if so, process. + +TSISQ: TLNE E,(TC%RST) ; If it has RST set, + JRST TSIF2A ; Go drop it quietly. + TLNE E,(TC%ACK) ; If ACK, can't be a valid request either + JRST TSISAR ; Go send a RST in response (with SEQ=SEG.ACK) + TLNN E,(TC%SYN) ; Anything else had better have a SYN + JRST TSISLR ; otherwise send RST with SEQ=0,ACK=SEQ+LEN + + ; Okay, we have a promising SYN. See if it matches any + ; "wild" listens. + METER("TCP: Fresh SYN") + LDB B,[TH$DST (H)] ; Get desired port # + LDB C,[TH$SRC (H)] ; Find port it's from + LDB D,[IP$SRC (W)] ; and host it's from. + MOVSI I,-XBL +TSISQ2: HRRZ J,XBSTAT(I) ; Get state for TCB + CAIE J,.XSLSN ; We're hunting for LISTEN +TSISQ3: AOBJN I,TSISQ2 + JUMPGE I,TSISQ5 ; Jump if no match. + LDB A,[.BP TH%DST,XBPORT(I)] ; Get our local port (never wild) + CAIE A,(B) ; It must match desired "dest port"! + JRST TSISQ3 ; Nope, doesn't want this one. + SKIPL XBHOST(I) ; Aha, very likely will match. Follow thru. + CAMN D,XBHOST(I) + CAIA + JRST TSISQ3 ; Host didn't match. + MOVE A,XBPORT(I) ; Check remote port field + TRNE A,17 ; Low 4 bits are non-zero if remote wild. + JRST TSISQ4 ; Won! + LDB A,[.BP TH%SRC,A] ; Not wild, see if it matches request. + CAIE A,(C) ; Compare our remote with its source. + JRST TSISQ3 ; No, no match here. + + ; Matched a wild listen! Must fill in various stuff. +TSISQ4: MOVEI A,17 + ANDCAM A,XBPORT(I) ; Clear wild bits + DPB C,[.BP TH%SRC,XBPORT(I)] ; Set remote port # + MOVEM D,XBHOST(I) ; Set remote host addr + LDB D,[IP$DST (W)] ; Set local address to whichever address other guy knows + MOVEM D,XBLCL(I) + DPB I,[PK$TCB (R)] ; Finish setting up context for dispatch + CALL TCPMSS ; Correct MSS values for specified foreign host + CALL TCPRWS ; Open up a receive window + JRST TSILS ; Go handle SYN rcvd for LISTEN. + + ; No outstanding listens. Check the port number, to + ; see if it's something we are likely to service. +TSISQ5: LDB A,[TH$DST (H)] ; Get destination port # + CAILE A,%TCPMP ; Fits max port # for RFC service? + JRST TSISLR ; Naw, barf about it (send RST). + + ; See if we're actually willing to start up a job... + LDB A,[IP$SRC (W)] ; See who it's from + JSP T,IPLCLH ; Ask IP if this is one of us + SKIPL TCPUSW ; It isn't, so make sure we're open for biz + CAIA + JRST TSISLR ; Sorry charlie (send RST) + + ; Okay, we'll take it as SYN-QUEUED! We know this is a new + ; request, otherwise it would have been matched at TSI02 and + ; dispatched to TSISQQ instead. + +ifn 0,[ + ; first see if it's already on the queue! + ; Note that we still have remote host # in D. + SKIPN Q,TCPRQH ; Get pointer to 1st item on queue + JRST TSISQ7 ; No queue, so not on. + MOVE B,TH$SRC(H) ; Get req's source/dest ports + MOVE D,IP$SRC(W) ; and its source addr +TSISQ6: HLRZ T,PK.TCP(Q) ; Get addr of TCP header from queue + HLRZ C,PK.IP(Q) ; and addr of IP header + CAIE T, + CAIN C, + BUG CHECK,[TCP: SYNQ smashed] + CAMN B,TH$SRC(T) ; Same ports? + CAME D,IP$SRC(C) ; Same host? + CAIA ; No + JRST TSIF2B ; Yes, assume SYN is a dup, ignore it. + HRRZ Q,PK.TCP(Q) ; Get next thing on pending queue + JUMPN Q,TSISQ6 + + ; Not on queue, let's try to add it. +TSISQ7: MOVE A,TCPRQN ; Find # of things on queue already + CAIL A,%TCPMQ ; Keep its length reasonable + JRST TSISQ8 ; Sigh, ran out. + HRROI T,NTSYNL ; OK, now try loading job up! + CALL NUJBST ; Queue request for job TCPRFC + JRST TSISLR ; Bah, no job slots or something! + MOVEI A,(R) ; It's on the way! Queue the SYN now. + MOVEI Q,TCPRQH + CALL PKQPL(PK.TCP) ; Add onto end of pending-RFC queue. +] ;ifn 0 + + MOVSI I,-XBL +TSISQ6: SKIPN XBUSER(I) + SKIPE XBSTAT(I) + AOBJN I,TSISQ6 + JUMPGE I,TSISQ8 ; Jump if no free slots. + CALL TXBINI ; Got one, might as well verify it's cleared. + MOVE A,TCPRQN ; Find # of things on queue already + CAIL A,XBL/2 ; Keep number reasonable + JRST TSISQ8 ; Sorry, too many. + HRROI T,NTSYNL ; Now see if we can load up handler job. + CALL NUJBST ; Do it + JRST TSISLR ; Ugh, couldn't start new job... + MOVEI J,.XSSYQ + MOVEM J,XBSTAT(I) ; Set state SYN-QUEUED + LDB A,[IP$SRC (W)] + MOVEM A,XBHOST(I) ; Set up host # + MOVE A,TH$SRC(H) ; and ports + ; Don't need to set XBLCL, won't be looked at + MOVEM A,XBPORT(I) ; That's all we need for now. + CALL TCPMSS ; Might as well keep these right even though + CALL TCPRWS ; this TCB will be flushed when conn opens. + MOVE A,TIME + ADDI A,10.*30. ; Let it stay queued for 10 seconds. + MOVEM A,XBORTT(I) + MOVEI Q,XBITQH(I) ; Put the segment on input queue for slot. + MOVEI A,(R) + CALL PKQPF(PK.TCP) + + HRRZM I,TCPRQL ; Save # of last SYN queued. + AOS TCPRQN ; And increment count of entries. + METER("TCP: Srvjob starts") + RET ; All done! + +TSISQ8: BUG INFO,[TCP: SYN queue full] + JRST TSISLR ; Sigh. + + +; TSISQQ - Come here when segment received that matches an +; existing port/host which is in SYN-QUEUED state. + +TSISQQ: TLNE E,(TC%RST) ; Is it an RST? + JRST [ CALL TSISQF ; Yeah, flush the queued SYN. + JRST TSIFL] ; and drop segment. + TLNE E,(TC%ACK) ; An ACK? That's illegal etc... + JRST [ CALL TSISQF ; Flush the queued SYN, + JRST TSISAR] ; and send a RST in response. + TLNN E,(TC%SYN) ; Anything else better be a SYN + JRST [ CALL TSISQF ; else send RST. + JRST TSISLR] + JRST TSIF2B ; Most likely a duplicate SYN, so just + ; flush it and return. + + ; Flush TCB for a queued SYN. +TSISQF: SETZM XBSTAT(I) + SETZM XBPORT(I) + SETZM XBHOST(I) + SETZM XBORTT(I) + SKIPE XBITQH(I) + CALL TXBIFL + SOSGE TCPRQN + BUG HALT + RET + + +; TSISAR - Respond to current segment by sending a RST with +; SEQ=SEG.ACK. Re-uses the current segment's packet buffer. +; R, W, H set up for PE, IP, and TCP. +; E has seg flags. May not be anything in I, so re-use fields +; from given packet! +; TSISAQ - like TSISAR but just drops segment if it has RST in it. +; TSISLR - like TSISAR, but SEQ=0, ACK=SEG.SEQ+SEG.LEN +; This is used when responding to segments without an ACK, i.e. +; initial SYNs. + +TSISLR: METER("TCP: times at TSISLR") + LDB A,[TH$SEQ (H)] ; Get SEQ. Assume TT still valid. + ADDI A,(TT) ; ACK=SEG.SEQ+SEG.LEN + LSH A,4 ; Left justify it. + SETZ D, ; SEQ=0 + MOVSI T,(TC%RST+TC%ACK) + JRST TSISA2 + +TSISAQ: TLNE E,(TC%RST) ; Here, if incoming seg was RST, + JRST TSIFL ; just ignore, don't respond. +TSISAR: METER("TCP: times at TSISAR") + MOVE D,TH$ACK(H) ; Use SEG.ACK for SEQ + MOVSI T,(TC%RST) + + ; Here, A, D, and T must be set up. +TSISA2: SETZ B, + LDB C,[TH$SRC (H)] ; Get source port + DPB C,[.BP TH%DST,B] ; Use as dest port + LDB C,[TH$DST (H)] ; Get dest + DPB C,[.BP TH%SRC,B] ; Use as... you guessed it. + PUSH P,IP$DST(W) ; Which of my addresses to claim to be from + MOVE C,IP$SRC(W) + +; A/ ACK field (left justified) +; B/ (left justified) +; C/ remote host (left justified) +; D/ SEQ field (left justified) +; R/ PE ptr to packet responding to +; T/ flags to use + + + SETZ I, + CALL TSOINI ; Initialize W,H,PK.IP(R),PK.TCP(R),PK.TCI(R) + ; Note everything in PK.TCI will be wrong. + MOVEM C,IP$DST(W) ; Store remote host + MOVEM B,TH$SRC(H) ; Store loc/rem ports + MOVEM D,TH$SEQ(H) ; Deposit new SEQ field + TLNN T,(TC%ACK) ; If sending an ACK + SETZ A, + MOVEM A,TH$ACK(H) ; Deposit ACK field. + TLO T,240000 ; Set IHL + MOVEM T,TH$CTL(H) ; Deposit segment flags + MOVEI A,5*4 + DPB A,[IP$TOL (W)] ; Say length just a std TCP header. + POP P,IP$SRC(W) + CALL THCKSM ; Figure TCP checksum + DPB A,[TH$CKS (H)] ; Deposit in + CALL IPKSND ; Put this buffer on IP output queue! + RET + + +; TSILS - Segment received for this connection while in LISTEN state. +; +TSILS: METER("TCP: Segs rcvd in LSN") + TLNE E,(TC%RST) ; Ignore any RSTs. + JRST TSIFL + TLNE E,(TC%ACK) ; ACKs are bad too. + JRST TSISAR ; Respond with a RST to them. + TLNN E,(TC%SYN) ; It should be a SYN. + JRST TSIFL ; If not, just flush. + + ; We've received a SYN that should be valid. Set up for + ; SYN-RCVD state. Note that we ignore security/precedence + ; except to remember it so our transmits look OK. + ; NOTE!!! TSILSX is an entry point from MP level TCPOPN call, + ; which is used to hook up a user OPEN to a matching SYN on + ; the pending-RFC queue! + METER("TCP: SYN in LSN") +TSILSX: LDB D,[TH$SEQ (H)] ; Get sequence number + LDB A,[TH$WND (H)] + MOVEM A,XBSWND(I) ; Initialize send window + MOVEM A,XBSAVW(I) ; and available window + MOVEM D,XBSWL1(I) ; Save seg.seq used for last window update + LDB A,[TH$ACK (H)] + MOVEM A,XBSWL2(I) ; Save seg.ack used for last window update + ADDI D,1 + TLZ D,%MOD32 ; Get seg.seq+1 + MOVEM D,XBRNXT(I) ; Store as initial RCV.NXT + CALL TCPISS ; Select a new ISS in A (Initial Send Seq#) + MOVEM A,XBSUNA(I) ; Set SND.UNA to ISS +; ADDI A,1 +; TLZ A,%MOD32 + MOVEM A,XBSNXT(I) ; And SND.NXT also; assume that process of + ; sending it will increment by 1. + + ; Check for TCP options at this point, and process if present + LDB A,[TH$THL (H)] ; TCP header length + CAILE A,%TCPHL ; If default, no options present + CALL TCPPIO ; Else, process input options + + ; Nasty business - put together and send a segment with + ; seq=ISS,ack=RCV.NXT,ctl=SYN+ACK. + ; For now we can assume that initial SYNs will never + ; contain text, and so we don't have to queue it up. + ; Alternatively can hope that remote site is clever about + ; retransmitting! + ; This is because if we don't need to keep received segment + ; around, can just re-use it. + MOVSI T,(TC%SYN+TC%ACK) + TRCPKT R,"TSISLX Reflecting incoming SYN with SYN" + CALL TSOSSN ; Fire off SYN. Sends MSS option too. + MOVEI J,.XSSYR ; Change state to SYN-RCVD. + HRRM J,XBSTAT(I) + CALL TCPUSI ; Set user state. + RET + +; TCPISS - Select new ISS, return in A + +TCPISS: MOVE A,TIME + LSH A,13. +TCPIS2: TLZ A,%MOD32 + CAMN A,TISSLU ; Same as last used? + JRST [ AOS A,TISSC + ANDI A,17 + LSH A,9. + ADD A,TISSLU + JRST TCPIS2] ; Jump to mask off and test again. + MOVEM A,TISSLU + RET + +; TCPPIO - Process TCP options from incoming segment. +; This is only checked for SYN segments because the only interesting +; option (Max Segment Size) is only sent with SYN segments +; +; R/ Pkt buffer +; I/ TCB Index +; H/ TCP Header +; A/ TCP header size in 32-bit words + +TCPPIO: SUBI A,%TCPHL + LSH A,2 ; Options length in bytes + MOVE B,[TH$OPT (H)] ; BP to start of options +TCPPIL: SKIPG A ; Anything left? + RET ; Nope, done + ILDB C,B ; Get option type + CAIL C,TCPPIS ; In range? + RET ; Have to give up if unknown option + JRST @TCPPIT(C) + +TCPPIT: TCPPI0 + TCPPI1 + TCPPI2 +TCPPIS==.-TCPPIT + + ;End of option list +TCPPI0: RET + + ;NOP +TCPPI1: SOJA A,TCPPIL ; Decrement length and loop + + ;Max Seg Size TYPE ? LENGTH ? MSB ? LSB +TCPPI2: ILDB C,B ; Get length + SUB A,C ; Count it + ILDB C,B ; Get 16-bit quantity, updating B + LSH C,8. + ILDB D,B + ADD C,D ; Now contains foreign MSS request + CAMGE C,XBSMSS(I) ; Don't exceed our own limits! + MOVEM C,XBSMSS(I) ; Set new value in TCB + JRST TCPPIL + + +; TSISS - Segment received while in SYN-SENT state. +; Note that being in this state implies that there is one +; segment on the retransmit queue, which must be the initial SYN +; that we sent. + +TSISS: METER("TCP: Segs rcvd in SYN-SENT") + LDB D,[TH$SEQ (H)] ; Get SEG.SEQ + TLNN E,(TC%ACK) ; Has an ACK? + JRST TSISS2 ; Nope, it better be RST or SYN. + + ; See if our SYN has been ACKed. Since we only send SYNs + ; without data, this just means a test for SEG.ACK = SND.NXT. + LDB B,[TH$ACK (H)] ; Have ACK. Get ack field + CAME B,XBSNXT(I) ; It should ACK our initial SYN + JRST TSISAQ ; If not, send a RST. +; MOVE A,XBSUNA(I) ; snd.una =< seg.ack =< snd.nxt ? +; CMPSEQ A,=<,B,=<,XBSNXT(I),TSISAQ ; If not good, send RST. + +TSISS2: TLNE E,(TC%RST) ; Check for RST + JRST [ TLNN E,(TC%ACK) ; Ugh, have RST. Did we also get good ACK? + JRST TSIFL ; No, can just flush this segment. + MOVEI T,.XCRFS ; Yeah, our SYN is being refused, so + CALL TCPUC ; say this is close-reason. + JRST TSIRST] ; Then must go abort connection. + + ; Here we get to check security/precedence. Hurray. + ; We should just copy the seg values, so as to fake sender out. + + ; Now finally check the SYN bit! + TLNN E,(TC%SYN) ; Must be set + JRST TSIFL ; Neither RST nor SYN? Flush it. + + ; It's a SYN. Update our send params from its values. + ; We will either send an ACK or another SYN; in both cases the + ; SYN segment currently on the retransmit queue should be flushed. + MOVEI Q,XBORTQ(I) ; Point to retrans q + CALL PKQGF(PK.TCP) ; Pluck off 1st thing + SOSN XBORTL(I) ; Verify none left on queue + CAIN A, ; and something was there! + BUG CHECK,[TCP: SYN-SENT retrans Q bad] + JUMPE A,TSISS3 ; Just for robustness + TRCPKT A,"TSISS2 Flushing our SYN from rexmit Q" + MOVE T,PK.FLG(A) + TLO T,%PKFLS ; Tell IP to flush packet if seen + MOVEM T,PK.FLG(A) + CALL PKTRT ; Flush SYN packet if not otherwise busy + SETZM XBORTT(I) ; and flush timeout. + +TSISS3: LDB A,[TH$WND (H)] + MOVEM A,XBSWND(I) ; Initialize send window + MOVEM A,XBSAVW(I) ; and available window + MOVEM D,XBSWL1(I) ; Save seg.seq used for last window update + LDB A,[TH$ACK (H)] + MOVEM A,XBSWL2(I) ; Save seg.ack used for last window update + ADDI D,1 + TLZ D,%MOD32 + MOVEM D,XBRNXT(I) ; Set RCV.NXT to SEQ+1 + + ; Process segment options in case sender specified MSS + LDB A,[TH$THL (H)] ; TCP header length + CAILE A,%TCPHL ; If default, no options present + CALL TCPPIO ; Else, process input options + + TLNN E,(TC%ACK) + JRST TSISS4 + LDB A,[TH$ACK (H)] ; If ACK also present, (known acceptable) + MOVEM A,XBSUNA(I) ; Set SND.UNA to SEG.ACK. + + ; Here must test if SND.UNA > ISS (our SYN has been ACKed). + ; But this was already checked just before TSISS2. + MOVSI T,(TC%ACK) ; Hurray, we're open! Must ACK the SYN + TRCPKT R,"TSISS3 ACK SYN to open conn" + CALL TSOSNR ; (Re-using its segment) + MOVEI J,.XSOPN ; Hurray, we're open now! + HRRM J,XBSTAT(I) + CALL TCPUSI ; Update user state + RET + + ; Our SYN not ACKed yet, so enter SYN-RCVD state. +TSISS4: + ; Must go send seq=ISS,ack=RCV.NXT,ctl=SYN+ACK + LDB D,[TH$SEQ (H)] ; Get sequence number + ADDI D,1 + TLZ D,%MOD32 ; Get seg.seq+1 + MOVEM D,XBRNXT(I) ; Store as initial RCV.NXT + SOSGE A,XBSUNA(I) ; Set SND.UNA to ISS + JRST [ MOVEI A,1 + MOVEM A,XBSUNA(I) + JRST .+1] + MOVEM A,XBSNXT(I) ; And SND.NXT also; assume that process of + ; sending it will increment by 1. + MOVSI T,(TC%SYN+TC%ACK) + TRCPKT R,"TSISS4 ACK and re-SYN SYN-SENT conn" + CALL TSOSSN ; Fire off SYN/ACK with MSS option included. + MOVEI J,.XSSYR ; Change state to SYN-RCVD. + HRRM J,XBSTAT(I) + CALL TCPUSI ; Set user state. + RET + +; TSIRST - valid RST segment received (not in LISTEN). +; Basically must flush the connection, signal user, etc. + +TSIRST: METER("TCP: Valid RSTs") + CALL TXBFLP ; Flush the TCB immediately, PI level + MOVEI T,.XCRST ; Say fgn host reset stuff + CALL TCPUC ; as "close reason" + CALRET TSIFL ; Flush segment. + +; TSISYN - SYN segment received. +; If in window, error - send a RST and close things up. +; If not in window, return an ACK as for TSISNE. + +TSISYN: METER("TCP: Random SYN") + + CALRET TSIFL + +; TSISRA - Bad ACK seen while in SYN-RCVD state, +; send a RST. + +TSISRA: METER("TCP: Bad ACK in SYR") + CALRET TSIFL + +; TSISAK - Received ACK for something not yet seen, send ACK and +; drop segment. +TSISAK: METER("TCP: ACK for nxm") + CALRET TSIFL + +; TSIATW - Received ACK while in TIME-WAIT state. This should be +; a re-transmit of the remote FIN. ACK it, and restart +; 2-MSL timeout. + +TSIATW: METER("TCP: ACK in .XSTMW") + MOVSI T,(TC%ACK) + TRCPKT R,"TSIATW ACK send in TIME-WAIT" + CALL TSOSNR ; Send simple ACK in response. + JRST TSITM2 ; and restart 2-MSL timeout. + +SUBTTL TCP Send output segment + +; Send TCP output segment. +; Send output (usually data) segment, for connection indexed by I. +; Note this differs from TSISAR etc. which don't have any active connection, +; thus no valid I. As much context as possible is taken from the +; TCB tables indexed by I. +; In particular, the %XBCTL flags are examined to see if anything should +; be added to the outgoing segment, other than what was requested in the +; call. + +; Sequence space variables are updated. +; The following possibilities are independently possible: +; Re-using packet / using fresh packet +; Uses seq space (must retrans) / no seq space used +; +; TSOSND - send output segment while connection established +; R/ PE ptr to packet, +; PK.BUF, PK.IP and PK.TCP must be set. +; If these were not initialized by TSOINI so as to get +; the right offsets, you will probably lose. +; PK.TCI should have the # bytes of data and offset. +; I/ TCB index +; Clobbers A,B,C,D,E,W,H,Q,T,TT + +; TSOSNR - Just sends a data-less "reply" type segment using +; TCB's sequence space vars. Seq=snd.nxt, ack=rcv.nxt, etc. +; R/ PE ptr to packet (packet will be smashed and re-used) +; I/ TCB index +; T/ flags to use (Neither ACK nor %XBCTL will be added automatically!) + +; Clobbers A,B,C,D,E,W,H,Q,T,TT + +TSOSNR: CALL TSOINI ; Initialize (sets up W,H PK.IP,PK.TCP,PK.TCI) + SETZ TT, ; Say zero bytes of real data + DPB TT,[PK$TDL (R)] ; and make sure packet entry reflects this. + JRST TSOSN ; Jump in to do it. + + +; TSOSSN - Send an initial SYN segment. No data, but add a TCP +; MSS option set from XBRMSS(I), and using TCB's sequence space +; vars. Seq=snd.nxt, ack=rcv.nxt, etc. +; R/ PE ptr to packet (packet will be smashed and re-used) +; I/ TCB index +; T/ flags to use (None, including SYN, will be added automatically) + +; Clobbers A,B,C,D,E,W,H,Q,T,TT + +TSOSSN: CALL TSOINI ; Initialize (sets up W,H PK.IP,PK.TCP,PK.TCI) + MOVE TT,XBRMSS(I) ; Max seg size we would like + LSH TT,4 ; 32-bit option + IOR TT,TSOMSO ; Add in type and length fields of option + MOVEM TT,TH$OPT(H) ; Write it. Damn well better be first option. + LDB TT,[PK$TDO (R)] ; Get current TCP header size + ADDI TT,4 ; Adding 4-byte option + DPB TT,[PK$TDO (R)] + SETZ TT, ; Say zero bytes of real data + DPB TT,[PK$TDL (R)] ; and make sure packet entry reflects this. + JRST TSOSN ; Jump in to do it. + +TSOMSO: .BYTE 8 ? 2 ? 4 ? 0 ? 0 ? .BYTE ; Option 2, length 4, two data words + +TSOSND: MOVSI T,(TC%ACK) ; Simple data segment + IOR T,XBSTAT(I) ; Plus whatever is being requested. + HLRZ W,PK.IP(R) ; Get ptr to IP header + HLRZ H,PK.TCP(R) ; and TCP header + LDB TT,[PK$TDL (R)] ; Get # bytes of data +; LDB A,[PK$TDO (R)] ; Get offset of data +; ADDI TT,(A) ; Now have # bytes past std hdr length. + +; TSOSN - Entry point if W, H, and TT already set up. +; I/ TCB index +; T/ flags for segment +; R/ PE ptr (PK.BUF, PK.IP, PK.TCP, PK.TCI must all be set) +; W/ IP header ptr +; H/ TCP header ptr +; TT/ # bytes of data (real data, not including header or SYN/FIN) +; Clobbers A,B,C,D,E,TT,T,Q and updates various TCB data. + +; This code assumes TT is the bytes of DATA only. +; Must store the out-of-TCP info in the IP header field, so that +; the checksum and IPKSND routines will find it there. +; This info consists of: +; IP$SRC - Source address +; IP$DST - Dest address +; IP$TOL - TCP segment length including header +; IP$PTC - Protocol number (needn't set, assumes %PTCTC always) + +TSOSN: METER("TCP: Out segs") + AND T,[TH%CTL] ; Ensure non-flag bits are flushed. + MOVE A,T + ANDCAB A,XBSTAT(I) ; Turn off these request bits + TLNE A,(TH%CTL) ; Any request bits left? + JRST TSOSN2 ; Yeah, can't turn off "now" bit. + MOVSI A,(%XBNOW) ; Satisfied everything, so flush + ANDCAM A,XBSTAT(I) ; the send-immediately bit. + +TSOSN2: LDB A,[PK$TDO (R)] ; Bytes of header + ADDI A,(TT) ; Add bytes of data + DPB A,[IP$TOL (W)] ; Store in IP length field + MOVE A,XBLCL(I) + LSH A,4 + MOVEM A,IP$SRC(W) ; Set source host + MOVE A,XBHOST(I) + LSH A,4 + MOVEM A,IP$DST(W) ; Set dest host + + ; Out-of-TCP info set up, now build the real TCP header. + LDB A,[.BP TH%DST,XBPORT(I)] ; Get port sending from (local) + DPB A,[TH$SRC (H)] + LDB A,[.BP TH%SRC,XBPORT(I)] ; Get port to send to + DPB A,[TH$DST (H)] + MOVE A,XBSNXT(I) ; Get sequence number to use + LSH A,4 + MOVEM A,TH$SEQ(H) ; Set SEQ field + TLNN T,(TC%ACK) ; Check flags, sending ACK? + TDZA A,A ; If not, use zero field anyway. + MOVE A,XBRNXT(I) ; Get ack number to use + LSH A,4 + MOVEM A,TH$ACK(H) ; Set ACK field + + SKIPE A,XBSUP(I) ; Urgent data being sent? + JRST [ TLO T,(TC%URG) ; Yes! Say urgent pointer signif + METER("TCP: Urgent dgms") + MOVNI B,(TT) + ADDB B,XBSUP(I) ; Adjust pointer as result of data sent + CAIGE B, + SETZM XBSUP(I) + LSH A,4 + JRST .+1] + MOVEM A,TH$UP(H) ; Set urgent pointer if any + + MOVE A,XBRWND(I) ; Get our current receive window + LSH A,4 + IOR A,T ; Add in caller's flags + LDB B,[PK$TDO (R)] ; Header length in bytes + LSH B,-2 ; TCP wants length in 32-bit words + DPB B,[<.BP TH%THL,A>] + MOVEM A,TH$THL(H) ; Store header len, flags, window + + PUSH P,TT ; Goddam checksum clobberage + CALL THCKSM ; Now figure out checksum + POP P,TT + DPB A,[TH$CKS (H)] + + ; TCP header set up. Now update our TCB connection vars to + ; account for the stuff we're sending. + TLNE T,(TC%SYN) ; Now find new seq # (SND.NXT) + ADDI TT,1 ; SYN counts as 1 octet + TLNE T,(TC%FIN) ; So does a FIN + ADDI TT,1 + JUMPLE TT,TSOSN8 ; If not actually using seq space, skip + ; a bunch of update/retrans stuff. + + ; We're using up some sequence space! Must update avail window, + ; and put the segment on retransmit queue. + MOVE A,XBSAVW(I) ; Must update avail send window + SUBI A,(TT) + CAIGE A, ; If window becomes negative, + SETZ A, ; keep it at zero. + MOVEM A,XBSAVW(I) + ADD TT,XBSNXT(I) ; Get new SND.NXT + TLZ TT,%MOD32 + MOVEM TT,XBSNXT(I) + SKIPN XBORTT(I) ; Retrans timeout already set? + JRST [ MOVE A,TIME + ADD A,TCPTMO ; Make it 5 sec for now. + MOVEM A,XBORTT(I) + SETZM XBORTC(I) ; Clear count of retries. + JRST .+1] + TRCPKT R,"TSOSND Pkt w/seq space added to retransmit queue" + MOVEI A,(R) ; Arg to PKQPL, A/ PE ptr + MOVEI Q,XBORTQ(I) ; Arg to PKQPL, Q/ queue hdr ptr + CALL PKQPL(PK.TCP) ; Put on TCP retrans queue + AOS XBORTL(I) ; Bump count of segs on queue + +TSOSN8: CALL IPKSND ; Put on IP output queue + RET + +SUBTTL TCP Retransmit and Timeout + +Comment | + The following things in TCP need some sort of timeout: + Retransmit output segment if not ACKed (removed) within RT sec + Timeout to abort connection if retransmission fails for UT sec + Timeout to ACK incoming data (ie avoid ACKing immediately, + wait for more output or input). + Timeout during TIME-WAIT to flush connection. +| + +; TCPCLK - This routine is called by 1/2-sec "slow" clock. What it has to do +; is scan all active TCB's for the following conditions: +; (1) Retransmit timeout has expired, must resend something. +; or TIME-WAIT timeout has expired. +; (2) An ACK must be sent, either by sending the current output +; buffer, or by generating an ACK without data. + +EBLK +TCLKRC: 0 ; Count of segs compacted in pass over a retrans Q +BBLK + +TCPCLK: SKIPN TCPUP ; Do nothing if turned off. + RET + MOVSI I,-XBL + CONO PI,NETOFF + SKIPA A,TIME +TCLK05: SKIPA A,TIME + +TCLK10: SKIPN B,XBSTAT(I) + JRST TCLK15 + SKIPE C,XBORTT(I) + CAMG A,C + CAIA + JRST TCLK20 ; Retrans timeout +TCLK12: TLNE B,(TH%CTL+%XBNOW) ; Any flags set? + JRST TCLK50 ; Wants ACK sent +TCLK15: AOBJN I,TCLK10 + CONO PI,NETON + RET +TCLK16: MOVE A,TIME + AOBJN I,TCLK10 + CONO PI,NETON + RET + + ; Come here for timeout of some sort. +TCLK20: SKIPE XBORTQ(I) ; If a retrans queue exists, + JRST TCLK22 ; then assume it was a retrans timeout. + MOVEI C,(B) ; No retrans Q, probably a TIME-WAIT one? + CAIN C,.XSTMW ; State TIME-WAIT? + JRST [ METER("TCP: Time-Wait timeout") + CALL TXBFLP ; Flush the TCB completely, PI level + JRST TCLK16] + CAIN C,.XSSYQ ; State SYN-QUEUED? + JRST [ METER("TCP: SYQ timeout") + CALL TSISQF ; Flush the queued SYN. + JRST TCLK16] + CAIN C,.XSFN2 ; State FIN-WAIT-2? + JRST TCLK21 + METER("TCP: Random timeout") ; Sigh. + SETZM XBORTT(I) ; Flush whatever it was. + JRST TCLK16 + +TCLK21: METER("TCP: FN2 timeout") + CALL TXBFLP ; Flush the TCB completely, PI level + SKIPE XBUSER(I) ; Shouldn't still have anything open. + BUG CHECK,[TCP: FN2 timo with active user] + JRST TCLK16 + +TCLK22: METER("TCP: Retrans") + AOS C,XBORTC(I) ; Retrans timeout. Send it again. + SKIPE D,XBORTP(I) ; Has user set any retrans params? + JRST [ JRST TCLK25] ; Yes! For now, non-Z means skip abort check. + CAILE C,%TCPMR ; Tried too many times? + JRST TCLK80 ; Ugh, abort the connection! + SKIPN R,XBORTQ(I) + JRST [ SETZM XBORTT(I) ; If nothing on queue, + JRST TCLK12] ; just reset the timeout to nothing. + SKIPGE A,PK.FLG(R) ; Ensure that packet isn't being output now + JRST TCLK25 ; Still being output?? Reset timeout. + ; Note that we don't check to see whether segment has already + ; been transmitted, on the theory that compaction is going to + ; pay off anyway. + HLRZ W,PK.IP(R) + HLRZ H,PK.TCP(R) + SETZM TCLKRC ; Clear compaction count. + + ; Looks like we have to retransmit. Try to compact up as much + ; stuff as possible into a single segment; this gets a bit + ; hairy. Note that we compact as much as we can, ignoring the + ; %PKPIL and %PKODN bits (except for setting the appropriate flush + ; flags). + TRCPKT R,"TCLK30 Segment being retransmitted" +TCLK30: HRRZ J,PK.TCP(R) ; Get pointer to succeeding segment + JUMPE J,TCLK39 ; If none following, can't compact (ignore + ; possibility of adding XBOCOS for now) + LDB B,[PK$TDO (R)] ; Get 1st offset + LDB C,[PK$TDL (R)] ; Get 1st length + LDB T,[PK$TDL (J)] ; Get 2nd length + ADDI B,(C) ; Find offset to end of 1st data + MOVEI D,(B) + ADDI D,(T) ; Find total length after compaction + CAILE D,576.-<5*4> ; Hack hack hack! Limit to 556. so std + ; IP datagram is limited to 576. + JRST TCLK39 ; If too big, don't compact. + + ; Compact two segments into one! + ; R/ 1st seg D/ offset to end of data + ; J/ 2nd seg T/ len of 2nd data + METER("TCP: Retrans compact") + TRCPKT J,"TCLK30 Segment being compacted into previous seg for rexmit" + ADDI C,(T) ; Get new # bytes for 1st seg + DPB C,[PK$TDL (R)] ; Store it in advance. +; HLRZ D,PK.TCP(R) ; Find addr of TCP header in 1st seg + MOVEI D,(H) + IDIVI B,4 + ADDI D,(B) ; Get addr for BP to end of data + HRL D,(C)[441000 ? 341000 ? 241000 ? 141000] ; Make LH + LDB B,[PK$TDO (J)] ; Get data offset for 2nd seg + IDIVI B,4 + HLRZ A,PK.TCP(J) ; Get addr for BP to start of 2nd data + ADDI B,(A) + HRL B,(C)[441000 ? 341000 ? 241000 ? 141000] ; Make LH + ; B/ BP to 2nd data + ; D/ BP to end of 1st data + ; T/ # bytes of 2nd data + LDB A,[IP$TOL (W)] ; Get current length of whole datagram + ADDI A,(T) ; Increment by length of added stuff + DPB A,[IP$TOL (W)] ; Store back + ADDI A,3 + LSH A,-2 + HRLM A,PK.BUF(R) ; Set up new count of # words in datagram. +TCLK32: ILDB C,B + IDPB C,D + SOJG T,TCLK32 + + ; Data copied over, now update flags and stuff. + HLRZ D,PK.TCP(J) + MOVE A,TH$CTL(D) ; Get flags for 2nd seg + AND A,[TH%CTL] ; Mask off just flags + IORM A,TH$CTL(H) ; Add them to flags for 1st seg + TLNE A,(TC%URG) ; If URGENT bit set, + JRST [ LDB B,[TH$UP (D)] ; Get pointer from 2nd seg + LDB C,[PK$TDL (R)] ; Sigh, get new len of 1st seg + ADDI B,(C) ; Adjust for bytes in front + LDB C,[PK$TDL (J)] ; But have to subtract length + SUBI B,(C) ; of 2nd seg (already in 1st len) + DPB B,[TH$UP (H)] ; Store ptr back in 1st seg + JRST .+1] + + ; Compaction done! Now have to remove 2nd seg from queue. + HRRZ B,PK.TCP(J) ; Get pointer to 3rd seg + HRRM B,PK.TCP(R) ; Point 1st at it + CAIN B, ; If 2nd was the last one, + HRLM R,XBORTQ(I) ; must update "last" ptr in queue header. + MOVE A,PK.FLG(J) ; Get flags +IFN PK.TCP-2,.ERR %PQFL flag must match PK.TCP + TLZ A,(%PQFL2) ; Say it's off the TCP list, to allow + ; flushing from IP queue. + TLO A,(%PKFLS) ; In fact, require it + MOVEM A,PK.FLG(J) ; Store flags back + JUMPGE A,[MOVEI A,(J) ; If not locked by PI output, + TRCPKT A,"TCLK32 Seg flushed from rexmit by compaction" + CALL PKTRT ; try to flush it now. + JRST .+1] + SOSGE XBORTL(I) ; Decrement count of retrans queue segs + BUG HALT + AOS TCLKRC ; Bump count of recompacts done + JRST TCLK30 ; OK, try to recompact next seg! + + ; Note one possible problem with following code; although + ; the segment being re-trans'd is given latest poop (ACK, WND), + ; the ones following are not. This is usually OK as we assume + ; that following segs have actually been sent out, but if it + ; happens that they HAVEN'T (i.e. %PKODN not set) then their + ; info is going to be a little out of date. This shouldn't + ; screw things too much, however. +TCLK39: MOVE D,XBRNXT(I) ; Get latest ACK value + LSH D,4 + MOVEM D,TH$ACK(H) ; Set it + MOVE D,XBRWND(I) ; And latest window + DPB D,[TH$WND (H)] + CALL THCKSI ; Compute checksum for it (note not THCKSM) + DPB A,[TH$CKS (H)] + SKIPE TCLKRC ; Was any recompaction done? + CALL IPKHD2 ; Yes, must recompute IP header (checksum etc) + MOVE A,PK.FLG(R) + TLNN A,(%PKODN) ; Has segment already been tried once? + JRST [ ; No, don't put on output queue twice!! + TRCPKT R,"TCLK39 Rexmit skipped because seg not yet output" + METER("TCP: Pretrans compact") + JRST TCLK25] + TLO A,(%PKRTR) ; Set flag saying this is a retransmit + MOVEM A,PK.FLG(R) + MOVEI A,(R) + CALL IPKSNQ ; Put back on IP output queue + ; Note PK.BUF shd still be set up right. +TCLK25: MOVE A,TIME + HRRZ B,XBORTP(I) ; If RH set, use it for new timeout. + CAIN B, + MOVE B,TCPTMO ; Use timeout default. + ADD B,A + MOVEM B,XBORTT(I) + JRST TCLK79 + + ; Here when need to send an ACK. First see if we can + ; make use of existing output buffer. +TCLK50: METER("TCP: slow ACKs") + TLNE B,(TC%SYN+TC%RST) + BUG CHECK,[TCP: SYN or RST set in XBSTAT clock req] + SKIPE R,XBOCOS(I) ; Ensure there is one. + TLNE B,(%XBMPL) ; and that it isn't locked. + JRST TCLK60 ; Sigh, can't use it. + + ; There is an output buffer, and it's not locked, so use that + ; to send stuff out! + TRCPKT R,"TCLK50 COS used to send clock level ACK" + MOVSI T,(TC%PSH) + CALL TCPOFR ; Force it out. + JRST TCLK16 + + ; Come here when we have to generate a new segment for ACK. +TCLK60: TLNN B,(%XBNOW) ; Insisting that we ACK? + JRST TCLK65 ; No, can semi-punt. + CALL PKTGFI ; Get buffer + JRST TCLK65 ; and forget about ACKing if we cant get one + METER("TCP: Clk ACK") + MOVEI R,(A) + MOVE T,B ; Use request flags in segment. + TRCPKT R,"TCLK60 Alloc and send ACK from clock level" + CALL TSOSNR ; Send a simple ACK + JRST TCLK16 + +TCLK65: MOVSI A,(%XBNOW) ; No, so just set insist flag + IORM A,XBSTAT(I) ; and wait a bit longer. + JRST TCLK16 + +TCLK79: + JRST TCLK16 + + ; Abort the connection, timed out. +TCLK80: METER("TCP: Timeout abort") + CALL TXBFLP ; This is pretty drastic... flush, PI level. + MOVEI T,.XCINC ; Say "incomplete transmission" + CALL TCPUC ; as close reason. + JRST TCLK16 + +TCLK90: CONO PI,NETON + RET + + +; Checksum cruft. + +; THCKSM - Figures TCP segment checksum, IP$TOL has TCP segment length. +; THCKSI - Figures TCP segment checksum, IP$TOL has IP header plus TCP seg. +; W/ addr of IP header +; H/ addr of TCP header +; Note that the following out-of-TCP values are looked up +; from the IP header in order to compute sum for the "pseudo header". +; IP$SRC - source host +; IP$DST - dest host +; IP$TOL - # octets in TCP segment (plus IP header) +; Finally, +; %PTCTC - Assumed value +; +; Clobbers B,C,D,E +; Returns +; A/ checksum +; TT/ Total # bytes in TCP segment + +THCKSM: TDZA C,C ; Compute as if IHL=0 +THCKSI: MOVNI C,5*4 + ; First compute pseudo header + LDB A,[IP$SRC (W)] ; Source addr + LDB B,[IP$DST (W)] ; Dest addr + ADD A,B + ADDI A,%PTCTC ; Add TCP protocol number + LDB TT,[IP$TOL (W)] ; Get total length in octets + JUMPE C,THCKS2 + LDB B,[IP$IHL (W)] ; Find IP header length in 32-bit wds + LSH B,2 ; mult by 4 to get # octets + SUBI TT,(B) ; Find # octets of IP data (TCP segment) +THCKS2: ADDI A,(TT) ; Add in. + MOVEI C,-<5*4>(TT) ; Get # bytes in segment after 1st 5 wds + + ; Done with pseudo header (not folded yet, though). + LDB B,[044000,,0(H)] ; Get wd 0 (src/dest) + ADD A,B + LDB B,[TH$SEQ (H)] ; Get wd 1 (seqno) + ADD A,B + LDB B,[TH$ACK (H)] ; wd 2 + ADD A,B + LDB B,[044000,,3(H)] ; wd 3 + ADD A,B + LDB B,[TH$UP (H)] ; wd 4 (part of) + ADDI A,(B) + + LSHC A,-16. + LSH B,-<16.+4> + ADDI A,(B) ; Now have it folded up. + JUMPLE C,THCKS7 ; If nothing more, can leave now. + MOVEI E,5(H) + HRLI E,442000 ; Set up 16-bit byte ptr to options/data + LSHC C,-1 + JUMPLE C,THCKS6 +THCKS5: ILDB B,E + ADDI A,(B) + SOJG C,THCKS5 +THCKS6: JUMPL D,[ ; Jump if odd byte left. + ILDB B,E ; get it + ANDCMI B,377 ; mask off low (unused) byte. + ADDI A,(B) + JRST .+1] +%CKMSK==<-1#177777> ; Mask for stuff above 16 bits +THCKS7: TDNE A,[%CKMSK] ; If any carries, add them in. + JRST [ LDB B,[.BP %CKMSK,A] + TDZ A,[%CKMSK] + ADD A,B + JRST THCKS7] + ANDCAI A,177777 ; Complement sum and mask off. + RET + + +MTRCOD ; Last stuff -- expand meter tables. +TRCCOD ; Expand trace tables diff --git a/src/system/tcpbuf.58 b/src/system/tcpbuf.58 new file mode 100755 index 00000000..e761cc90 --- /dev/null +++ b/src/system/tcpbuf.58 @@ -0,0 +1,575 @@ +COMMENT | + +Notes on TCP input and output buffers + +Ideally the TCP segment queues should be logically separate from the IP +datagram queues, but for efficiency it should be possible to have them +both together. + +Input buffers are expected to be lists of datagrams/segments. +This is reasonably simple, since pointers (in known places) can just be +set up to the data (whereever it is in the datagram/segment). +There is a problem with allocation/windows in this scheme, since it +is possible to run out of datagram buffers before running out of window, +if the remote site becomes cretinous about it and sends only a few +bytes per dgram very fast. But in that case re-transmission can just +force it to buffer up its output, so that future dgrams will be somewhat +more filled, so it is probably OK. If this does become a screw, can +add code to do compaction at clock level. + +Output buffers are a little more uncertain. Could have simple +circular buffer, with appropriate pointers set up so that IMP output +message is read directly from the buffer (same as NCP). Alternatively +could have queue of segments/datagrams all ready to go. Guess I'd +like to try doing the latter, to keep things "simple" by minimizing +the number of kinds of things floating around. + +Problem with putting output datagram together: can't always predict +ahead of time how big the leaders are going to be! Especially true +for IP level, which TCP is not supposed to know too much about. Thus +if not careful, it could happen that output is put into a segment too +close to the start of the buffer, so that there is not enough room for +the TCP and IP headers to fit in. Have to look at this; may need to +give up notion of keeping all the packet internals nicely contiguous. +Maximum IP header length is set at 60 bytes (15 words). The maximum +TCP header length is also 15 words. +Looking at the currently defined options, it seems unlikely that ITS +will use any of them, and if so, they can be predicted fairly easily on +a per-connection basis, so things should work out okay. Note that +the IP level can always simply fragment stuff if it really wants to be +that complex. + +It would be nice to be able to keep track of stuff which is on the +device (IMP) output queue but hasn't yet gone out, in order to add +last-minute bits (like ACK) or even some more data. Idea: output "queue" +is just a list of TCP connections that need attention, so can always +go in and mung stuff (even change mind about outputting) just by playing +with connection flags/lists. This is basically how NCP does it. + +Re packet buffer design: + Somewhat more hypothetical is the notion of keeping a "usage +count" for each buffer, so that pointers from the packet table entries +can point to several different buffers and not just one. When a usage +count hits zero, put the buffer on the freelist. Actually this is not +really needed for the case of a table entry pointing to more than one +buffer, but it IS needed for the case of more than one table entry +pointing to the same buffer. This might happen, for example, if +an internet bypass were set up so that datagrams going to ourselves +were simply vectored directly to the input queues. But for the +time being, it probably isn't too outrageous to simply re-copy the +datagram in question. (Also better emulates a fake network device). + +Suggest that lists point directly to themselves rather than +to start of entry; this allows low-level list routines to be used +on all lists. The higher-level routines of course have to know what +offsets to use for a specific list. Alternatively provide different routines +for each offset needed, and equate references to the appropriate routine +for each use. (This is what I'm trying at the moment, hence the IRPS) + +May want to use format ,, where is the addr +of the initial pointer (not initial node). This allows backtracking +to figure out what TCP connection or IP queue a packet belongs to. +Brute force approach is to simply have another word for the TCB index, etc. + +If this stuff is general enough it could be used for CHAOS packets also. +| + +COMMENT | + +-- Lots of this is wrong now... -- + +Buffers are all 256 (400 octal) words long, and 4 of them fit on one +ITS page. This size was chosen because the maximum length of an IMP +message (not counting IMP-Host padding) is 255 words of 4 8-bit bytes +per word. This allows one extra word; not much. Taking away the +3 IMP leader words (which has to be done anyway for NCP to continue +working) gives us 4 spare words per buffer. + +This still may not be enough. Rather than shoe-horn some clever stuff +into each buffer header, I am opting to maintain "Packet Entries" in a +"Packet Table" separate from the "Packet Buffers" themselves. All +messages/datagrams/segments/packets are identified by a pointer +into the table. (Could use index, as for sockets/TCBs, but this is +awkward for lists). The entry identified by the pointer will contain +the actual pointers into the buffer associated with that packet. +[NOTE: may want to have these pointers point into various places, not +necessarily all the same buffer. Must think about this.] + +Free buffers are linked by a freelist pointer in their first word, +with an identifier in the second word to help GC. The only design +issue for the buffers themselves is how to set things up so that it is +easy to GC a large freelist, i.e. identify pages that have nothing +but free buffers in them and thus can be removed from the system's +address space. Currently I have simply adopted the strategem used for +CHAOS buffers (at CHCLN) to have the core job snuffle over the freelist. + +Note that the low-level routines for manipulating lists are actually +referenced via macros which are given an offset as argument. This +offset refers to the offset between the node pointer and the location +of the "next" pointer in the node; the macro will assemble into a +call to the right routine for that offset. Currently only offsets +up to 2 are supported; any lists that the packet is put on must +be threaded through the first 3 words of the node, and the macros check +for this. +| + + SUBTTL Packet Tracing Code + +IFNDEF PKTTRC,PKTTRC==:0 ; Nonzero turns tracing code on +IF1,IFN PKTTRC,.ERR IP packet tracing code included. + +COMMENT | + +This code can be used to keep a history of what happens to a packet. +The history is stored in the packet buffer as a series of indexes +into a table of named events. + +To trace a particular event use the TRCPKT macro. + + TRCPKT(REG,"String") + +REG is the register which currently contains an index to the packet +buffer table. The code is more efficient if the register is R. String +is the description of the event. + +To generate the event table, you must call the TRCCOD macro somewhere +after the last call to TRCPKT. + +| + +%NTRCE==:77 ; Allow this many trace events. Value must be a bit mask (all + ; ones) to work right. If you make it bigger than 77 + ; you have to change the "TRC%" in the macros to something + ; shorter, too. + +%%%TRC==1 + +; TRCCOD generates TRCTBL, which holds +; for each trace event. +DEFINE TRCCOD +IFN PKTTRC,[ +TRC%0==:<0,,[ASCIZ /Null event/]> +TRCTBL: REPEAT %%%TRC,CONC TRC%,\.RPCNT +IF2, REPEAT %%%TRC,CONC EXPUNGE TRC%,\.RPCNT +] +TERMIN + +DEFINE TRCPKT REG,&(EVENT) +IFN PKTTRC,[ +IFG %%%TRC-%NTRCE,.ERR Too many packet trace events! +CONC TRC%,\%%%TRC,==:<.,,[ASCIZ EVENT]> + IFN REG-R,[ + PUSH P,R + MOVE R,REG + ] + PUSH P,TT + MOVEI TT,%%%TRC + PUSHJ P,PKTPTS + POP P,TT + IFN REG-R,[ + POP P,R + ] +%%%TRC==%%%TRC+1 +] +TERMIN + +IFN PKTTRC,[ + +; Store information in the packet history data buffer +; "Information" is a 6-bit quantity which indexes into a table +; of strings. +; TT/ Reason index +; R/ Pkt Buffer index + +PKTPTS: CONO PI,PIOFF ; Freeze machine + DPB TT,PK.HSP(R) ; Store trace info + IBP PK.HSP(R) ; Bump BP + HRRZ TT,PK.HSP(R) ; Pick up history byte ref (address only) + CAIL TT,PK.HSP(R) ; If we've gotten to the bottom, + JRST [ MOVEI TT,PK.HST(R) ;Wrap around + HRLI TT,(<.BP %NTRCE_30.>) ; BP to left 6 bits + MOVEM TT,PK.HSP(R) ;Reset it to top + JRST .+1 ] + CONO PI,PION + POPJ P, +] + +;;; Packet Table Entries + +EBLK +IFNDEF PKBSIZ,PKBSIZ==1000 ; 512. words per packet buffer (2048 byte MTU) +IFNDEF NPKPGS,NPKPGS==40. ; # pages OK to use for packet buffers +NPKB==:> ; # packet buffers available +NPKE==:NPKB ; # packet entry nodes. +IFN NPKB-NPKE,.ERR You must fix the UFLS at PKTGF. + +PKETBL: OFFSET -. + ; General (device driver, etc) +PK.FLG:: 1,,PKETBL+PK.L ; General - ,, + %PKPIL==: ; Packet locked at PI level, being output + %PKODN==:<1000,,> ; Packet has been output (else not yet) +;;; %PKNOF==:<2000,,> ; Packet should not be freed when output done. + %PKFLS==:<4000,,> ; Flush pkt if seen on output queue (ie dont output) + %PKRTR==:<10000,,> ; Packet is being re-transmitted by TCP + .SEE %PQFLX ; Low bits of LH used for on-list flags. + +PK.IP:: 0 ; IP Datagram - ,, + ; May be strung on Internet Queue, IP output queue +PK.TCP:: 0 ; TCP Segment - ,, + ; May be strung on TCB input Q, output retransmit Q +PK.TCI:: 0 ; TCP Segment - <# bytes data><# bytes offset> + PK%TDL==:<777700,,0> ; # octets of data in TCP segment + PK%TDO==:< 77,,770000> ; # octets data is offset from TCP header + PK%TCB==:< ,,007777> ; TCB connection index + PK$TDL==:<.BP PK%TDL,PK.TCI> + PK$TDO==:<.BP PK%TDO,PK.TCI> + PK$TCB==:<.BP PK%TCB,PK.TCI> +PK.BUF:: 0 ; General - <# wds>,, +PK.TIM:: 0 ; General - Time sent or received, int level (Sys time) +PK.DST:: 0 ; Immediate destination address if on output queue +PK.HWI:: 0 ; Hardware Information - currently KS Unibus address + +IFN PKTTRC,[ +PK.HST:: BLOCK 3 ; Packet trace history buffer +PK.HSP:: 0 ; Packet trace history pointer +] + +PK.L:: OFFSET 0 ; Length of a Packet-Entry (PE) node + REPEAT ,[ + IFN .RPCNT-, 1,,.+PK.L ; Build initial freelist + .ELSE 1,,0 + BLOCK PK.L-1 + ] +PKETBE==:.-PK.L ; Last legal PE pointer value + +PKEQHF: PKETBE,,PKETBL ; Header for Packet-Entry node freelist + +BBLK + +; A "queue" is a list of nodes pointed to by a "queue header" word +; of format ,,. Each node pointer points to +; the next node pointer (or zero if no more). +; There is a set of flags in the LH of a certain word, at offset +; PQ.FLG, that indicate which lists a node is currently on. + +PQ.FLG==:PK.FLG ; Offset of word list-flags are in. +%PQFLX==0 ; Initial val +IFNDEF %%%QOF,%%%QOF==0 ; This gets set to highest offset supported + +IRPS PKQGF,,[PKQGF0:PKQGF1:PKQGF2:]PKQPL,,[PKQPL0:PKQPL1:PKQPL2:]PKQPF,,[PKQPF0:PKQPF1:PKQPF2:]%PQFL,,[%PQFL0:%PQFL1:%PQFL2:] +IFG .IRPCNT-%%%QOF,%%%QOF==.IRPCNT + + %PQFL==:<1_.IRPCNT,,> ; Def a flag in LH at offset PQ.FLG + %PQFLX==%PQFLX\%PQFL ; Mask of all list-flags def'd. + +; PKQGF - Get first node from queue +; Q/ addr of queue header +; A/ addr of node (zero if none) + +PKQGF: CONO PI,PIOFF ; Work at all levels + HRRZ A,(Q) ; Get 1st from queue header word + JUMPE A,PIONJ ; None, so return zero. + MOVSI T,(%PQFL) ; Now clear appropriate flag for list + XORB T,PQ.FLG(A) ; to indicate it's not on it any more. + TLNE T,(%PQFL) ; Paranoia plus + BUG HALT,[PK: GF node wasnt on list] + HRRZ T,.IRPCNT(A) ; Get 2nd + HRRM T,(Q) ; Make it 1st + CAIN T, ; If all's well, done. + SETZM (Q) ; Else must clear whole header +IFNDEF PIONJ,PIONJ: + CONO PI,PION + POPJ P, + +; PKQPL - Put node on queue as last thing. +; Q/ addr of queue header +; A/ addr of node +PKQPL: TRNN A,-1 ; More paranoia + BUG HALT,[PK: zero node ptr] + HLLZS .IRPCNT(A) ; Say this node is last one + CONO PI,PIOFF ; Work at all levels + MOVSI T,(%PQFL) ; Paranoia: Set appropriate flag for list + XORB T,PQ.FLG(A) ; to indicate it's on it now. + TLNN T,(%PQFL) ; plus check... + BUG HALT,[PK: node already on list] + HLRZ T,(Q) ; Get last node + HRLM A,(Q) ; Point to new last node + JUMPN T,[HRRM A,.IRPCNT(T) ; Make prev last node point to new last + JRST .+2] ; Skip over next instr!! + HRRM A,(Q) ; Queue was empty, make this the new first too + CONO PI,PION + POPJ P, + +; PKQPF - Put node on queue as first thing. +; Q/ addr of queue header +; A/ addr of node +PKQPF: TRNN A,-1 ; Yes more paranoia + BUG HALT,[PK: zero node ptr] + CONO PI,PIOFF + MOVSI T,(%PQFL) ; Paranoia: Set appropriate flag for list + XORB T,PQ.FLG(A) ; to indicate it's on it now. + TLNN T,(%PQFL) ; check... + BUG HALT,[PK: node already on list] + HRRZ T,(Q) ; Get first thing + CAIN A,(T) ; paranoia, avoid loops to self + BUG + HRRM T,.IRPCNT(A) ; Make it second thing + HRRM A,(Q) ; Make new first thing + CAIN T, + HRLM A,(Q) ; Was empty, also make it last thing. + CONO PI,PION + POPJ P, +TERMIN + +; Define PKQGF, etc so that they actually reference PKQGF0, etc as +; appropriate for the given offset. +IRP RTN,,[PKQGF,PKQPF,PKQPL] +DEFINE RTN ?OFFST=0, +CONC RTN,\OFFST +IFG OFFST-%%%QOF,.ERR RTN used with bad offset +TERMIN +TERMIN + + +; PKEGF - Get a free Packet-Entry node +; Clears node contents. +; Clobbers Q,T +; Returns A/ PE ptr (0 if none) + +PKEGF: MOVEI Q,PKEQHF +IFE PKTTRC,[ + CALRET PKQGF ; Get a node +] +IFN PKTTRC,[ + CALL PKQGF + JUMPE A,CPOPJ ; No packet + SETZM PK.HST(A) + SETZM PK.HST+1(A) + SETZM PK.HST+2(A) + MOVEI Q,PK.HST(A) ; Build byte ref to history trail + HRLI Q,(<.BP %NTRCE_30.>) ; (dpb ref) + MOVEM Q,PK.HSP(A) ; save ref + POPJ P, +] + +; PKERT - Return a Packet-Entry node to freelist +; A/ PE ptr to node +; Clobbers Q,T + +PKERT: MOVEI Q,PKEQHF ; Use Packet-Entry freelist + CALRET PKQPF ; Put back on start of list. + +; Note that all MP calls to the routines below which allocate or free +; entries/buffers must be sure not to block (page fault or UFLS) +; while any "loose" entries/buffers exist (not pointed to by any list) +; unless there something on the PCLSR locked-switch list which will return the +; currently "loose" entry/buffer to its freelist -- otherwise +; it is possible for "loose" stuff to slowly accumulate. + +; PKTGF - Get a free Packet-Entry node and Packet Buffer. Hangs until +; it wins. Note that it depends on fact there is one PE node +; for every packet buffer, and vice versa! If this becomes untrue +; then the way it UFLSes should be fixed up. +; PKTGFI - version that skips if wins, doesn't hang. +; Returns A/ PE ptr Clobbers Q,T + +PKTGF: SKIPN PKEQHF ; Fast check, see if any packet entries/buffers free + CALL UFLS ; Nope, hang until something turns up. + CALL PKTGFI ; Get a entry/buffer! + JRST PKTGF ; None? Sigh, go hang. + RET + +PKTGFI: CALL PKEGF ; Get a free node + JUMPE A,CPOPJ + PUSH P,A ; Save pointer to it +PKTGF1: CALL PKBGF ; Get a free buffer + JUMPN A,PKTGF8 ; Jump if found one right away! + CALL PKBAL ; None left on freelist, try to allocate more. + CAIA ; Sigh, failed. + JRST PKTGF1 ; Won, go pluck a buffer from freelist. + + ; Lost, can't get any more buffers. + POP P,A ; None available, take non-skip return + CALRET PKERT ; Put PE node back on its freelist. + + ; Won, store buffer pointer in PE. +PKTGF8: MOVE T,A + POP P,A ; Restore PE ptr + MOVEM T,PK.BUF(A) + MOVE T,PQ.FLG(A) ; Paranoia dept, verify not on any lists. + TLNE T,(%PQFLX) + BUG HALT,[PK: Freelist node not free!] + SETZM PK.FLG(A) ; Zap all other entries in packet node. + SETZM PK.IP(A) + SETZM PK.TCP(A) + SETZM PK.TCI(A) + SETZM PK.TIM(A) + AOS (P) ; Win, skip on return! + RET + +; PKTRT - Return both a Packet-Entry and its associated buffer to freelist +; only if check shows that it doesn't belong to any lists. +; PKTRTA - Always return to freelist. If check shows that it is still +; on some list, bad error! +; Clobbers A,Q,T +; A/ PE ptr (must be off all lists) + +PKTRTA: CAIL A,PKETBL ; Paranoia check for legal pointers + CAILE A,PKETBE + BUG HALT,[PK: Bad PE pointer] + MOVE T,PQ.FLG(A) + TLNE T,(%PQFLX\%PKPIL) ; On list or locked at I/O PI level? + BUG HALT,[PK: Freeing packet still in use!] + JRST PKTRTX ; Nope, can proceed to put on freelist. + +PKTRT: CAIL A,PKETBL ; Paranoia check for legal pointers + CAILE A,PKETBE + BUG HALT,[PK: Bad PE pointer] + MOVE T,PQ.FLG(A) + TLNE T,(%PQFLX\%PKPIL) ; On a list or locked by interface PI level? + RET ; Yes, don't return to freelist yet. +PKTRTX: PUSH P,A ; Save PE ptr + SKIPE A,PK.BUF(A) ; Get buffer pointer associated with PE + CALL PKBRT ; Return the buffer + POP P,A + SETZM PK.BUF(A) ; Ensure buffer pointer zapped. + CALRET PKERT ; Then return the packet entry + +; PKTPCL - Return a packet entry/buffer while PCLSR'ing. +; This is the standard LOSSET routine to use. +; A must hold the PE ptr at time of the block (which we are backing +; out of). +; Must only clobber A and T!! + +PKTPCL: MOVE A,AC0S+A(U) ; Get ac A at time of the block + PUSH P,Q ; Mustn't clobber Q + CALL PKTRT ; Return the entry/buffer (clobbers Q,T) + JRST POPQJ + + +EBLK +PKBNF: 0 ; # free Packet Buffers +PKBNT: 0 ; # total Packet Buffers +PKBCTM: 0 ; Time of last no-more-core complaint +PKBQHF: 0 ; Queue Header for buffer freelist +PKBQHC: 0 ; Queue Header for core job cleanup +BBLK + +; PKBGF - Get a free Packet Buffer +; Clobbers Q,T +; Returns A/ PB ptr (0 if none) + +PKBGF: MOVEI Q,PKBQHF ; Point to buffer freelist + CALL PKQGF ; Get first thing off it + JUMPE A,CPOPJ ; If got nothing, just return. + SETZM 1(A) ; Aha, got it! Flush free-buffer identifier. + SOS PKBNF ; Decrement # free packet buffers. + RET + +; PKBRT - Return a Packet Buffer to freelist. Puts back at END of freelist, +; as PKBCLN clean-up depends on this. +; Clobbers Q,T +PKBRT: SETZM (A) ; Paranoia aid - clear "flags" in LH of 1st wd. + ; Otherwise PKQ routines complain. + MOVE T,[SIXBIT /BRUNCH/] + MOVEM T,1(A) ; Set up free-buffer identifier + AOS PKBNF ; Increment # free packet buffers. + MOVEI Q,PKBQHF ; Point to buffer freelist + CALRET PKQPL ; Put it back on, at end. + +; PKBRTL - Return a list of Packet Buffers to freelist +; Q/ ptr to queue header of list +; Clobbers A,T +PKBRTL: CALL PKQGF ; Get first thing off list + JUMPE A,CPOPJ + PUSH P,Q + CALL PKBRT ; Return it to buffer freelist + POP P,Q + JRST PKBRTL + +; PKBAL - Allocate more Packet Buffers +; Clobbers A,Q,T +; Returns .+1 if lost +; .+2 if won (must still call PKBGF to get a buffer from list) + +PKBAL: PUSH P,B + CONI PI,Q ; Save PI channel-on status + ANDI Q,177 + CONO PI,UTCOFF ; Make the world safe for IOMQ + MOVE B,PKBNT ; Check total # of buffers so far + CAIL B,NPKB ; Make sure we're not already using max allowed + JRST PKBAL4 ; Ugh, already at max! Go complain. + PUSHJ P,IOMQ ; Get 1K of memory + JRST PKBAL3 ; Mem not available, fail + CONO PI,PICON(Q) ; Won, restore PI status + MOVEI B,MUPKT ; Set page type = packet + DPB B,[MUR,,MEMBLT(A)] + LSH A,10. ; Turn allocated page # into mem address + HRLI A,-<2000/PKBSIZ> ; Make AOBJN into page (# buffers per page) +PKBAL2: PUSHJ P,PKBRT ; Put them all on free list + ADDI A,PKBSIZ-1 + AOBJN A,PKBAL2 + MOVEI B,<2000/PKBSIZ> ; This many more buffers have been created + ADDM B,PKBNT ; Increase total (PKBNF bumped by PKBRT) + POP P,B + AOS (P) ; Take win return. + RET + + ; Here if packet stuff trying to use up too much core +PKBAL4: MOVE B,PKBCTM ; Don't complain too often + ADDI B,60.*30. ; Just once a minute + CAMLE B,TIME + JRST PKBAL3 + BUG CHECK,[PACKET NET ATTEMPTING TO USE TOO MUCH CORE] + MOVE B,TIME + MOVEM B,PKBCTM +PKBAL3: CONO PI,PICON(Q) ; Lost, restore PI status + POP P,B + POPJ P, ; and take error return. + + +; PKBCLN - Called only by core job, to clean up packet buffers. +; Smashes all ACs. + +PKBCLN: SKIPE A,PKBNT ; See if 2/3 or more of buffers free + SKIPN B,PKBNF + POPJ P, ; No buffers or none free, nothing to do + SUBM A,B + IDIV A,B ; Get ratio of total to used + CAIGE A,3 ; Note if B is zero, A is unchanged + POPJ P, ; and at least 32. +IFL TSYSM-256., MOVEI D,TSYSM-1 ; Scan memory for packet buffer pages +.ELSE MOVEI D,255. +PKBCL0: LDB A,[MUR,,MEMBLT(D)] + CAIE A,MUPKT +PKBCL4: SOJGE D,PKBCL0 + JUMPL D,CPOPJ + MOVE A,D ; Quickly determine if any non-free buffers + LSH A,10. ; on this page + HRLI A,-<2000/PKBSIZ> + MOVE T,[SIXBIT/BRUNCH/] +PKBCL5: CAME T,1(A) + JRST PKBCL4 ; Not free, don't bother with slow stuff + ADDI A,PKBSIZ-1 + AOBJN A,PKBCL5 + SETZB C,PKBQHC ; Collect all free buffers on this page + MOVE E,PKBNF ; Loop about as many times as there are free buffers +PKBCL1: PUSHJ P,PKBGF ; Get next free buffer + JUMPE A,PKBCL2 + LDB B,[121000,,A] + CAMN B,D + JRST [ MOVEI Q,PKBQHC ; This one's on the page, save it + PUSHJ P,PKQPL + AOJA C,.+2 ] ; Count them + PUSHJ P,PKBRT ; Not on the page, put back. This depends on + ; the fact PKBRT puts back at END of list! + SOJG E,PKBCL1 +PKBCL2: CAIE C,<2000/PKBSIZ> ; Did we get the whole page? + JRST [ MOVEI Q,PKBQHC ; No, must punt this one, and + PUSHJ P,PKBRTL ; return all the buffers we saved up. + JRST PKBCL4] + MOVNS C ; Yes, get rid of these buffers + ADDM C,PKBNT ; Decrement total # of buffers in use + MOVE A,D + PUSHJ P,MEMR ; Flush the page from addr space + JRST PKBCLN ; Back to flush more, until quota done. diff --git a/src/system/time.950 b/src/system/time.950 new file mode 100755 index 00000000..06e616fc --- /dev/null +++ b/src/system/time.950 @@ -0,0 +1,343 @@ +;I T S .OPERS RELEVANT TO REAL TIME + + ;.PDTIME AC, ;RETURNS PDUPS*<# SECS SINCE BEGINNING OF YEAR> + +APDTIM: PUSHJ P,GPDTIM + JRST RETM1 ;-1 IF NOT KNOWN + JRST APTUAJ + + ;.RDATE AC, ;RETURNS SIXBIT YYMMDD IN AC + +ARDATE: PUSHJ P,GLPDTM ;GET LOCALIZED PDTIME + JRST RETM1 ;NOT AVAILABLE + IDIVI A,SPD ;GET # DAYS SINCE BEGINNING OF YEAR + PUSHJ P,RDATE ;GET THE ANSWER + JRST APTUAJ ;RETURN IT + + ;.RTIME AC, ;RETURNS SIXBIT HHMMSS (24 HOUR TIME) IN AC + +ARTIME: PUSHJ P,GLPDTM ;GET LOCALIZED PDTIME + JRST RETM1 ;NOT AVAILABLE + IDIVI A,SPD ;GET # SECS SINCE MIDNIGHT IN B + PUSHJ P,RTIME ;CONVERT TO SIXBIT HHMMSS + JRST APTUAJ ;RETURN IT + + ;.RDATIM AC, ;DOES .RTIME TO AC, .RDATE TO AC+1 + +ARDATI: PUSHJ P,GLPDTM ;GET CRUD + JRST RETM1 ;NO LUCK (THIS IS GETTING BORING) + IDIVI A,SPD ;CONVERT TO DAYS AND SECONDS + HRLM A,(P) ;SAVE DAYS ON PDL + PUSHJ P,RTIME ;GET TIME (HHMMSS) + UMOVEM A,(J) ;GIVE TO USER + HLRZ A,(P) ;GET DAYS AGAIN + PUSHJ P,RDATE ;CONVERT TO SIXBIT + AOJA J,APTUAJ ;GIVE TO USER AND RETURN + + ;.RYEAR AC, ;PUSHJ'S TO RYEAR AND MOVEM'S E TO AC + +ARYEAR: PUSHJ P,RYEAR ;GET THE CRUFT + UMOVEM E,(J) ;STORE YEAR AND CRUD + POPJ P, + + ;.RLPDT AC, ;DOES .RYEAR AC+1, AND ALSO MOVEM'S A TO AC + +ARLPDT: PUSHJ P,RYEAR ;GET THE CRUFT + UMOVEM E,1(J) ;STORE YEAR AND CRUD + JRST APTUAJ ;STORE TIME AND RETURN + + ;ROUTINE TO RETURN -1 ON AN OPER + +RETM1: XCTR XRW,[SETOM (J)] + POPJ P, + + ;GET THE CORRECTED PDUPS*<# SECS SINCE BEGINNING OF YEAR> IN A + ;SKIP IF OFFSET AVAILABLE AND CLOCK ON + +GPDTIM: +IFN PDCLKP,[ + SKIPN A,PDTIME ;GET THE OFFSET + JRST GPDTM2 ;NOT AVAILABLE + DATAI PDCLK,B ;GET WHAT THE CLOCK IS SAYING + TLZ B,600000 + JUMPE B,GPDTM2 ;POWER PROBABLY (BUT NOT NECESSARILY) TURNED OFF + SUBM B,A ;DO THE CORRECTION + JUMPL A,CPOPJ ;LOST, DON'T RETURN A NEGATIVE NUMBER! + JRST POPJ1 ;EXIT SKIPPING (SUCCESS) +] ;PDCLKP +IFN KS10P,[ + SKIPN PDTIME ; Offset available? + JRST GPDTM2 ; No: Try backup + RDTIM A ; Read clock into A!B + TLC A,1729. ; "A most interesting number" + TLNE A,-1 ; Does the clock look like it has been set? + JRST GPDTM2 ; Must have been reset + DIVI A,KSFREQ ; Convert to 60ths + SUB A,PDTIME ; Subtract offset + JUMPL A,CPOPJ ; Wooops, don't return a negative number! (Why + ; don't we use the backup in this case?) + JRST POPJ1 +] ;KS10P +GPDTM2: SKIPGE A,PDYTIM ;CLOCK NOT ON, TRY BACKUP + POPJ P, ;SORRY, NOT AVAILABLE + IMULI A,30. ;CONVERT TO SIXTIETHS OF A SECOND + JRST POPJ1 ;CALL IT CORRECT AND AVAILABLE + + ;GET SIXBIT YYMMDD (DATE) IN A (LOCALIZED PDTIME/SPD IN A, YEAR IN RH(E)) + +RDATE: PUSHJ P,RDATE1 ;GET DAY IN C, MONTH IN B + MOVE T,[1400,,A];SET UP BYTE POINTER FOR OUTPUT + PUSHJ P,RDATM1 ;DEPOSIT DAY + MOVE C,B ;GET MONTH + PUSHJ P,RDATM1 ;DEPOSIT MONTH + MOVEI B,(E) ;GET YEAR + IDIVI B,100. ;GET LAST TWO DIGITS IN C +ARTIMX: PUSHJ P,RDATM1 ;DEPOSIT YEAR (ENTRY FROM RTIME TO DEPOSIT HOUR) + IOR A,[SIXBIT /000000/] ;CONVERT TO REAL SIXBIT + POPJ P, + + ;GET MONTH (1 => JAN) IN B, DAY (1 => THE FIRST) IN C + +RDATE1: AOS C,A ;GET DAY OF YEAR (LOCALIZED) (1 => THE FIRST) + MOVEI B,12. ;INITIALLY ASSUME DECEMBER FOR MONTH + CAMG C,LMNTBL-1(B) ;IF DAY IN YEAR .LE. DAY IN YEAR AT BEGINNING OF THIS MONTH, + SOJA B,.-1 ;THEN DECREMENT TO PREVIOUS MONTH AND TRY AGAIN + SUB C,LMNTBL-1(B) ;C(C) := DAY OF MONTH + POPJ P, + +LMNTBL: MNIRP [] ;TABLE OF DAYS GONE BY AT BEGINNING OF MONTH + + ;GET THE SIXBIT TIME IN A (# SECS SINCE MIDNIGHT IN B) + +RTIME: MOVE T,[1400,,A];SET UP BYTE POINTER FOR OUTPUT + IDIVI B,60. ;GET SECONDS IN C + PUSHJ P,RDATM1 ;DEPOSIT INTO A + IDIVI B,60. ;GET HOURS IN B, MINUTES IN C + PUSHJ P,RDATM1 ;DEPOSIT MINUTES + MOVE C,B ;GET HOURS IN C + JRST ARTIMX ;DEPOSIT HOURS, CONVERT TO SIXBIT, AND RETURN + + ;DEPOSIT C(C) AS TWO SIX BIT (AS OPPOSED TO SIXBIT) DECIMAL DIGITS + ; VIA T (INTO A) THEN DECREMENT T + +RDATM1: IDIVI C,10. ;SEPARATE DIGITS + DPB C,[60600,,D] ;DEPOSIT FIRST DIGIT TO GIVE 12 BITS + DPB D,T ;OUTPUT BYTE + ADD T,[140000,,] ;DECREMENT BYTE POINTER + POPJ P, ;THAT'S ALL + + ;DO A PUSHJ P,GLPDTM THEN HACK AROUND + ;DO THOSE THINGS TO E COMMENTED IN GLPDTM AS BEING DONE BY RYEAR + ;TRY TO GET YEAR EVEN IF GLPDTM DOESN'T SKIP, BUT IN THAT CASE CLOBBER A TO -1 + +RYEAR: PUSHJ P,GLPDTM ;GET THE CRUFT + JRST RYEAR2 ;DIDN'T SKIP, SEE WHAT CAN BE SALVAGED +RYEAR1: PUSH P,A ;PROTECT A FROM FUTURE CLOBBERAGE + IDIVI A,SPD ;GET LOCALIZED # DAYS SINCE BEGINNING OF YEAR + JUMPL E,[SOJA A,.+1] ;DE-LOCALIZE + LDB B,[270300,,E] ;DAY OF WEEK OF BEGINNING OF YEAR + ADD A,B ;ADD IN + IDIVI A,7 ;GET TODAY'S DAY OF WEEK (0 => SUNDAY) IN B + DPB B,[320300,,E] ;DEPOSIT IN E + TLO E,40000 ;DOCUMENT FACT THAT TIME OF YEAR KNOWN + JRST POPAJ ;RESTORE A AND RETURN + +RYEAR2: PUSHJ P,GDWOBY ;GLPDTM DIDN'T SKIP, TRY TO SALVAGE CRUFT: FIRST DOWOBY + MOVNI A,1 ;DOCUMENT FACT THAT TIME OF YEAR NOT KNOWN + JUMPE E,CPOPJ ;RETURN IF YEAR NOT KNOWN EITHER + DPB B,[270300,,E] ;DAY OF WEEK OF BEGINNING OF YEAR + JRST CMPF29 ;SEE IF LEAP YEAR, AND RETURN + + ;NOTE: THE SYMS JAN, FEB, MAR, ETC. ARE DEFINED AFTER (AND BY) MNIRP (A MACRO) + + ;INCREMENT YEAR + +NUPDT: TLNN E,200000 ;SEE IF LEAP YEAR + SKIPA A,[<365.*SPD*PDUPS>] ;NORMAL YEAR + MOVE A,[<366.*SPD*PDUPS>] ;LEAP YEAR + ADDM A,PDTIME ;UPDATE PDCLK OFFSET + IDIVI A,30. ;CONVERT TO HALF-SECONDS + EXCH A,PDYTIM ;ALSO UPDATE BACKUP SYSTEM + SUBM A,PDYTIM + AOS FYEAR ;INCREMENT YEAR + + ;INSERT OTHER CRUFT HERE IF DESIRED + ;DROPS THROUGH + + ;CODING DROPS THROUGH FROM PREVIOUS PAGE +;GET "LOCALIZED" NUMBER OF SECONDS SINCE BEGINNING OF YEAR IN A + ;IF DIVIDED BY # SECONDS IN A DAY, + ;GIVES REMAINDER OF # SECONDS SINCE MIDNIGHT LOCAL TIME + ;QUOTIENT WHEN FED TO DATE GENERATOR ROUTINE ASSUMING LEAP YEAR GIVES CORRECT DATE +;ALSO GET YEAR AND FLAGS (AS RETURNED BY .RYEAR) IN E + ;1.1-2.9 => YEAR (E.G. 1969.) + ;3.1-3.5 ZERO + ;3.6-3.8 => DAY OF WEEK OF BEGINNING OF YEAR (0 => SUNDAY) + ;3.9-4.2 ZERO (RYEAR SETS THIS BYTE TO TODAY'S DAY OF WEEK IF TIME OF YEAR KNOWN) + ;4.6 ZERO (RYEAR SETS IT TO 1 IF TIME OF YEAR KNOWN) + ;4.7 ONE => DAYLIGHT SAVINGS TIME IN EFFECT + ;4.8 ONE => LEAP YEAR + ;4.9 ONE => 365 DAY YEAR AND AFTER FEB 28 +;SKIPS IF PDCLK ON AND BOTH PDTIME AND FYEAR NON-ZERO (IN OTHER WORDS IF SUCCESSFUL) +;PREVIOUS CODING DROPS THROUGH ON YEAR INCREMENT + +GLPDTM: CONO PI,CLKOFF ;AVOID DOUBLE YEAR INCREMENT + SKIPE E,FYEAR ;GET YEAR IN E, SKIP IF NOT AVAILABLE + PUSHJ P,GPDTIM ;GET PDTIME, SHOULD SKIP + JRST CLKONJ ;SOMETHING NOT AVAILABLE, DON'T SKIP + IDIVI A,60. ;CONVERT TO SECONDS + PUSHJ P,CMPF29 ;MAYBE SET BIT 4.8 OR 4.9 OF E, IF 4.9 SET THEN ADD SPD TO A + CAML A,[366.*SPD] ;IF MORE THAN A YEAR HAS GONE, + JRST NUPDT ;THEN INCREMENT YEAR + CONO PI,CLKON ;TIMIMG ERROR PROBLEM GONE + PUSH P,A ;SAVE # SECONDS DURING NEXT CALL + PUSHJ P,GDWOBY ;GET DAY OF WEEK OF BEGINNING OF YEAR (0 => SUNDAY) + DPB B,[270300,,E] ;DEPOSIT IN RIGHT PLACE + POP P,A ;RESTORE A + AOS (P) ;CAUSE RETURN TO SKIP + + ;IF DAYLIGHT SAVINGS TIME THEN ADD 3600. TO A AND SET BIT 4.7 IN E + +GLPDT2: JFCL ;POPJ FOR STD TIME + ;JRST CRDDST FOR DAY LIGHT TIME + ;JFCL "NORMAL" + CAML A,[*SPD+7200.] ;IF BEFORE 2AM APR 1, + CAML A,[*SPD+3600.] ;OR IF AFTER 1AM STANDARD TIME OCT 31, + POPJ P, ;THEN OBVIOUSLY STANDARD TIME IS IN EFFECT + CAML A,[*SPD+7200.] ;IF BEFORE 2AM APR 7 STANDARD TIME, + CAML A,[*SPD+3600.] ;OR IF AFTER 1AM STANDARD TIME OCTOBER 25, + JRST GLPDT3 ;THEN NOT OBVIOUS +CRDDST: TLO E,100000 ;DAYLIGHT SAVINGS TIME, SET BIT IN E + ADDI A,3600. ;CONTINUE TO LOCALIZE THE TIME THAT WILL BE RETURNED + POPJ P, + + ;IT IS NOW SOMETIME DURING THE WEEKS IN APR AND OCTOBER + ;WHEN IT MAY BE EITHER STANDARD OR DAYLIGHT SAVINGS TIME + +GLPDT3: PUSH P,A ;SAVE # SECS + CAMG A,[JUL*SPD] ;IF NOT YET JULY, + TDZA D,D ;THEN IT MUST BE APR, SET INDEX + MOVEI D,1 ;OCTOBER, SET INDEX + SUB A,CRDSB(D) ;COMPENSATE FOR 2AM OR 1AM + IDIVI A,SPD ;FLUSH SECONDS, LEAVE ONLY DAYS (IT LOOKS LIKE A LEAP YEAR, REMEMBER) + LDB C,[270300,,E] ;GET DAY OF WEEK OF BEGINNING OF YEAR IN C + JUMPGE E,.+3 ;IF REGULAR YEAR, + SOJGE C,.+2 ;THEN DE-LOCALIZE SO IT WILL RE-LOCALIZE LATER... + MOVEI C,6 ;MOD 7 + ADD A,C ;ADD TO NUMBER OF DAYS + IDIVI A,7 + IMULI A,7 + SUB A,C ;C(A) := NUMBER OF DAYS IN YEAR BEFORE LAST SUNDAY (MAYBE TODAY) + ;IF LAST SUNDAY (AS DEFINED ABOVE) IS BELOW THE "REGION OF AMBIGUITY", + ;THEN IT HAS NOT YET CHANGED TO THE LATER TIME + XCT CRDTST(D) ;SKIP IF DAYLIGHT SAVINGS TIME + JRST POPAJ ;STANDARD TIME, NO CHANGES NECESSARY + POP P,A ;DAYLIGHT SAVINGS TIME, RESTORE A + JRST CRDDST ;MUNG A AND E AND RETURN + +CRDSB: 7200. ;IN APR CHANGES AT 2AM EST + 3600. ;IN OCTOBER CHANGES AT 1AM EST + +CRDTST: CAIGE A, + CAIL A, + + ;IF LEAP YEAR THEN SET BIT 4.8 OF E + ;IF NOT LEAP YEAR THEN IF AFTER FEB 28 THEN SET BIT 4.9 OF E AND ADD SPD TO A + +CMPF29: TRNN E,3 ;IF LEAP YEAR, (HOPEFULLY THIS ONLY PLACE WHERE DIRECTLY CHECKED FOR LEAP YEAR) + TLOA E,200000 ;THEN SET BIT 4.8 OF E AND RETURN + CAMGE A,[<-1>*SPD] ;365 DAY YEAR, IF BEFORE MARCH FIRST, + POPJ P, ;THEN RETURN + TLO E,400000 ;365 DAY YEAR AFTER FEB 28, SET BIT 4.9 OF E + ADDI A,SPD ;INCREMENT A ONE DAY + POPJ P, + + ;GET DAY OF WEEK OF BEGINNING OF YEAR (IN E) (0 => SUNDAY) IN B + ;FOLLOWING ROUTINE HAS BEEN EXHAUSTIVELY CHECKED + +GDWOBY: MOVEI A,-1(E) + IDIVI A,400. + MOVEI A,1(B) + IDIVI B,4 + ADD A,B + IDIVI B,25. + SUB A,B + IDIVI A,7 + POPJ P, + + ;SLOW CLOCK ROUTINE TO CHECK ON REAL-TIME CLOCK SYSTEM + +PDCCHK: SKIPL PDYTIM ;IF BACKUP TIME (SINCE BEGINNING OF YEAR) CALCULATED, + AOS PDYTIM ;THEN UPDATE IT + SKIPGE TIMOFF ;IF TIMOFF NOT CALCULATED, + POPJ P, ;THEN RETURN + AOS A,TIMOFF ;UPDATE TIMOFF + CAMGE A,[2*SPD] ;Incremented beyond length of day? + JRST PDCCH1 + SETZB A,TIMOFF ;Yes - reset it. + MOVEM A,RSWTIM ;Also reset last-resource-warning timestamp. +PDCCH1: TRNE A,64.*2-1 ;Is this a 64. second (based on TIMOFF) clock break? + POPJ P, ; No, so return. +INITIM: +IFN PDCLKP,[ + SKIPN A,PDTIME ;MAYBE UPDATE BACKUP SYSTEM + JRST INITM2 ;PDTIME NOT AVAILABLE, DON'T + DATAI PDCLK,B + TLZ B,600000 + JUMPE B,INITM2 ;JUMP IF CLOCK OFF + SUBM B,A + JUMPL A,CPOPJ + IDIVI A,30. ;CONVERT TO HALF-SECONDS SINCE BEGINNING OF YEAR + MOVEM A,PDYTIM ;STORE RE-CALCULATED BACKUP TIME +] ;PDCLKP +IFN KS10P,[ + SKIPN PDTIME ; Update backup system? + JRST INITM2 ; Not without offset + RDTIM A + TLC A,1729. + TLNE A,-1 + JRST INITM2 ; Not if clock reset + DIVI A,KSFREQ + SUB A,PDTIME ; 60ths since Jan 1 + JUMPL A,CPOPJ + IDIVI A,30. ; halfs since Jan 1 + MOVEM A,PDYTIM ; Store backup +] ;KS10P +INITM2: PUSHJ P,GLPDTM ;GET LOCALIZED PDTIME + POPJ P, ;SOMETHING'S MISSING + IDIVI A,SPD ;SEPARATE INTO DAYS AND SECONDS + LSH B,1 ;CONVERT TIME SINCE MIDNIGHT TO HALF-SECONDS + MOVEM B,TIMOFF ;STORE RE-CALCULATED NUMBER OF HALF-SECONDS SINCE MIDNIGHT + PUSHJ P,CLCQDT ;GET QDATE,,TIMOFF IN A + CONO PI,UTCOFF ;INHIBIT INTERRUPTS DURING THIS RITUAL + SKIPGE A,QMDRO ;GET ORIGIN OF MASTER DSK DIRECTORY + JRST UTCONJ ;DIRECTORY LOCKED + MOVE B,QACTB ;DIRECTORY CHANGED BIT FOR DSK DIRECTORY + SKIPE T,PDTIME ;GET OFFSET FOR DECORIOLIS CLOCK + CAMN T,MPDOFF(A) ;SEE IF IT MATCHES RELEVANT WORD IN DSKDIR + JRST .+3 ;MATCHES OR PDTIME NOT AVAILABLE + MOVEM T,MPDOFF(A) ;NO MATCH, CORRECT THE DSKDIR ONE + IORM B,QMDRO ;SET DIRECTORY CHANGED BIT + SKIPE T,FYEAR ;NOW DO THE SAME FOR THE YEAR, + CAMN T,MDYEAR(A) ;AND THE RELEVANT WORD IN DSKDIR + JRST .+3 + MOVEM T,MDYEAR(A) + IORM B,QMDRO + JRST UTCONJ ;THAT'S ALL + +CLCQDT: PUSHJ P,RDATE1 ;GET DAY OF MONTH IN C, MONTH IN B + SETZM QDATE ;INITIALIZE FOR FOLLOWING + PUSH P,E-1 + PUSH P,E + MOVE E-1,FYEAR + IDIVI E-1,100. + DPB E,[330700,,QDATE] ;YEAR + POP P,E + POP P,E-1 + DPB B,[270400,,QDATE] ;MONTH + DPB C,[220500,,QDATE] ;DAY + MOVE C,QDATE ;THE FIRST TIME QDATE IS SET UP, + HRR C,TIMOFF ;SET UP QDATEI = TIME SYSTEM CAME UP. + SKIPGE QDATEI + MOVEM C,QDATEI ;MECHANISM IS, SET QDATEI UNLESS ALREADY SET. + POPJ P, diff --git a/src/system/tm03s.defs4 b/src/system/tm03s.defs4 new file mode 100755 index 00000000..172054fe --- /dev/null +++ b/src/system/tm03s.defs4 @@ -0,0 +1,151 @@ +;;; -*- Mode: Midas -*- +.AUXIL + +;;; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + + +;;; RH11/TM03 Interrupt vector: +DEFSYM %TMVEC==224 ;(224/4 = 45) Interrupts occur on level 6 + ; (high priority) on UBA #1. +DEFSYM %TMBAS==772400 ;Unibus address of first register + +;;; RH11/TM03 Unibus register addresses: + +DEFSYM %TMCS1=:%TMBAS ;CONTROL AND STATUS 1 + DEFSYM %TM1SC==1_15. ; Special Condition + DEFSYM %TM1TE==1_14. ; Transfer Error + DEFSYM %TM1MP==1_13. ; Massbus Control Bus Parity Error + DEFSYM %TM1DA==1_11. ; Drive Available + DEFSYM %TM1A7==1_9. ; UB Address Extension Bit 17 + DEFSYM %TM1A6==1_8. ; UB Address Extension Bit 16 + DEFSYM %TM1RY==1_7. ; Ready + DEFSYM %TM1IE==1_6. ; Interrupt Enable + DEFSYM $TM1CM==.BP 77 ; Bits 0-5 specify commands. + DEFSYM %TM1GO==1_0. ; GO bit + +;;; Commands with bit 0 (GO) included: + +DEFSYM %TMNOP==1 ;No Operation +DEFSYM %TMUNL==3 ;Unload +DEFSYM %TMREW==7 ;Rewind +DEFSYM %TMCLR==11 ;Formatter clear (reset errors etc.) +DEFSYM %TMER3==25 ;Erase three inch gap +DEFSYM %TMWTM==27 ;Write Tape Mark +DEFSYM %TMSPF==31 ;Space Forward +DEFSYM %TMSPR==33 ;Space Reverse +DEFSYM %TMWCF==51 ;Write Check FOrward +DEFSYM %TMWCR==57 ;Write Check Reverse +DEFSYM %TMWRT==61 ;Write Forward +DEFSYM %TMRDF==71 ;Read Forward +DEFSYM %TMRDR==77 ;Read Data Reverse + +DEFSYM %TMWC=:%TMBAS+2 ;WORD COUNT. + +DEFSYM %TMBA=:%TMBAS+4 ;UNIBUS ADDRESS. + +DEFSYM %TMFC=:%TMBAS+6 ;TAPE FRAME COUNT + +DEFSYM %TMCS2=:%TMBAS+10 ;CONTROL AND STATUS 2. + DEFSYM %TM2DL==1_15. ; Data Late + DEFSYM %TM2UP==1_13. ; Unibus Parity Error + DEFSYM %TM2NF==1_12. ; Non-existant Formatter + DEFSYM %TM2NM==1_11. ; %TMBA is NXM during DMA + DEFSYM %TM2PE==1_10. ; Program Error + DEFSYM %TM2MT==1_9. ; Missed Transfer + DEFSYM %TM2MP==1_8. ; Massbus Data Bus Parity Error + DEFSYM %TM2OR==1_7. ; Output Ready (for Silo buffer diag.) + DEFSYM %TM2IR==1_6. ; Input Ready (for Silo buffer diag.) + DEFSYM %TM2CC==1_5. ; Controller Clear + DEFSYM %TM2PT==1_4. ; Parity Test + DEFSYM %TM2AI==1_3. ; Unibus Address Increment Inhibit + +DEFSYM %TMFS=:%TMBAS+12 ;FORMATTER STATUS + DEFSYM %TMSAA==1_15. ; Attention Active + DEFSYM %TMSES==1_14. ; Error Summary + DEFSYM %TMSPP==1_13. ; Positioning in Progress + DEFSYM %TMSOL==1_12. ; Medium On-Line + DEFSYM %TMSWL==1_11. ; Write Locked + DEFSYM %TMSET==1_10. ; End of Tape + DEFSYM %TMSFP==1_8. ; Formatter Present + DEFSYM %TMSFR==1_7. ; Formatter Ready + DEFSYM %TMSSC==1_6 ; Slave Status Change + DEFSYM %TMSPE==1_5. ; Phase Encoded (1600BPI) Mode + DEFSYM %TMSSD==1_4. ; Slowing Down + DEFSYM %TMSIB==1_3. ; PE Identification Burst Detected + DEFSYM %TMSTM==1_2. ; Tape Mark detected + DEFSYM %TMSBT==1_1. ; Beginning of Tape + DEFSYM %TMSSA==1_0. ; Slave Attention (on-line) + +DEFSYM %TMERR=:%TMBAS+14 ;ERROR REGISTER + DEFSYM %TMECE==1_15. ; Correctable Data/CRC Error + DEFSYM %TMEUS==1_14. ; Unsafe + DEFSYM %TMEOI==1_13. ; Operation Incomplete + DEFSYM %TMECT==1_12. ; Controller Timing Error + DEFSYM %TMENX==1_11. ; Non Executable Function + DEFSYM %TMECS==1_10. ; Correctable Skew/Illegal Tape Mark Error + DEFSYM %TMEFC==1_9. ; Frame Count Error + DEFSYM %TMENG==1_8. ; Non-standard Gap + DEFSYM %TMEFL==1_7. ; PE Format/LRC Error + DEFSYM %TMEIC==1_6. ; Incorrectable Data/Hard Error + DEFSYM %TMEMD==1_5. ; Massbus Data Parity Error + DEFSYM %TMEFS==1_4. ; Format Select Error + DEFSYM %TMEMC==1_3. ; Massbus Control Parity Error + DEFSYM %TMERM==1_2. ; Register Modification Refused + DEFSYM %TMEIR==1_1. ; Illegal Register + DEFSYM %TMEIF==1_0. ; Illegal Function + DEFSYM %TMEHD==44077 ; Hard errors - US,NX,MD,FS,MC,RM,IR,IF + +DEFSYM %TMASN=:%TMBAS+16 ;ATTENTION SUMMARY. + ;Each bit 7-0 corresponds to a formatter asserting ATA. + +DEFSYM %TMCCR=:%TMBAS+20 ;CHECK CHARACTER REGISTER + DEFSYM %TMCDP==1_8. ; Dead Track Parity/CRC Parity + DEFSYM $TMCEI==.BP 177 ; Error Information + +DEFSYM %TMBUF=:%TMBAS+22 ;DATA BUFFER REGISTER + +DEFSYM %TMMNT=:%TMBAS+24 ;MAINTENANCE. + +DEFSYM %TMTYP=:%TMBAS+26 ;DRIVE TYPE. + ;2.7 Not Sector addressed + ;2.6 Tape + ;2.5 Moving Head + ;2.3 Dual controller option available + ;1.9 - 1.1 Drive Type Number. + ; TU77=14, TU45=12, TE16=11 Nothing=10 + +DEFSYM %TMSER=:%TMBAS+30 ;SERIAL NUMBER + +DEFSYM %TMTC=:%TMBAS+32 ;TAPE CONTROL REGISTER + DEFSYM %TMTAC==1_15. ; Acceleration (not up to speed) + DEFSYM %TMTFC==1_14. ; Frame Count non-zero + DEFSYM %TMTSA==1_13. ; Slave Address (selected slave) Changed + DEFSYM %TMTEA==1_12. ; Enable Abort on data transfer error + DEFSYM %TMTDS==7_8. ; Density Select Field + DEFSYM $TMTDS==.BP %TMTDS + DEFSYM %TMD08==3 ; 800 BPI NRZI + DEFSYM %TMD16==4 ; 1600 BPI PE + DEFSYM %TMTFS==17_4. ; Format Select + DEFSYM $TMTFS==.BP %TMTFS + DEFSYM %TMFCD==0 ; PDP10 Core Dump + DEFSYM %TMFIC==3 ; Industry Compatible (32 bit mode) + DEFSYM %TMTEP==1_3. ; Even Parity + DEFSYM %TMTTS==7 ; Transport Select + DEFSYM $TMTTS==.BP %TMTTS + +IFN $$TEMP,EXPUNG DEFSYM + + diff --git a/src/system/tm78s.defs2 b/src/system/tm78s.defs2 new file mode 100755 index 00000000..5f02e013 --- /dev/null +++ b/src/system/tm78s.defs2 @@ -0,0 +1,178 @@ +;;; -*- Mode: Midas -*- +.AUXIL + +;;; Canonical symbol definition macro, FOO==BAR with error check. +IFNDEF DEFSYM,[ +DEFINE DEFSYM X/ +IRPS Z,,[X] +IFNDEF Z,X +.ELSE [ $$TEM1==Z + X + IFN Z-$$TEM1,.ERR Z MULTIPLY .QUOTE`.QUOTE/DEFINED/` + ] +.ISTOP +TERMIN TERMIN +$$TEMP==1 +] ;IFNDEF DEFSYM +.ELSE, $$TEMP==0 + + +;;; RH11/TM78 Interrupt vector: +DEFSYM %ARVEC==224 ;(224/4 = 45) Interrupts occur on level 6 + ; (high priority) on UBA #1. +DEFSYM %ARBAS==772400 ;Unibus address of first register + +;;; RH11/TM78 Unibus register addresses: + +DEFSYM %ARCS1==%ARBAS ;CONTROL AND STATUS 1 (RH11 and MB Reg 00) + DEFSYM %A1SC==1_15. ; Special Condition + DEFSYM %A1TE==1_14. ; Transfer Error + DEFSYM %A1MCP==1_13. ; Massbus Control Bus Parity Error + DEFSYM %A1DA==1_11. ; Drive (TM78) Available + DEFSYM %A1A7==1_9. ; UB Address Extension Bit 17 + DEFSYM %A1A6==1_8. ; UB Address Extension Bit 16 + DEFSYM %A1RDY==1_7. ; Ready + DEFSYM %A1IE==1_6. ; Interrupt Enable + DEFSYM %A1CMD==77 ; Bits 0-5 specify commands. + DEFSYM %A1GO==1_0. ; GO bit + +;;; Commands, with GO bit or'd in. +;;; --NOTE-- +;;; Commands are passed to the controller in two ways. Data transfer +;;; command get written into the CS1 register, as usual. Non-data-transfer +;;; commands are written to the %ARNDC register for the desired drive +;;; unit (see below). Non-data-transfer commands are marked with a '*'. + +DEFSYM %ACNOP==3 ;(*) No Operation +DEFSYM %ACUNL==5 ;(*) Unload +DEFSYM %ACREW==7 ;(*) Rewind +DEFSYM %ACSNS==11 ;(*) Sense (Get status from TM) +DEFSYM %ACDSE==13 ;(*) Data Security Erase! (Erase rest of tape) +DEFSYM %ACWPM==15 ;(*) Write Phase Encoded (1600bpi) Tape Mark +DEFSYM %ACWGM==17 ;(*) Write GCR (6250bpi Tape Mark +DEFSYM %ACSFR==21 ;(*) Space Forward Record +DEFSYM %ACSRR==23 ;(*) Space Reverse Record +DEFSYM %ACSFF==25 ;(*) Space Forward File +DEFSYM %ACSRF==27 ;(*) Space Reverse File +DEFSYM %ACSFE==31 ;(*) Space Forward Either (record or file) +DEFSYM %ACSRE==33 ;(*) Space Reverse Either +DEFSYM %ACE3P==35 ;(*) Erase Three-inch gap, set PE +DEFSYM %ACE3G==37 ;(*) Erase Three-inch gap, set GCR +DEFSYM %ACCFP==41 ;(*) Close File PE (write two marks, back one) +DEFSYM %ACCFG==43 ;(*) Close File GCR +DEFSYM %ACEOT==45 ;(*) Space to Logical EOT +DEFSYM %ACSFU==47 ;(*) Space forward usefully (to file or EOT) +DEFSYM %ACWCF==51 ;Write Check Forward +DEFSYM %ACWCR==57 ;Write Check Reverse +DEFSYM %ACWRP==61 ;Write Forward PE +DEFSYM %ACWRG==63 ;Write Forward GCR +DEFSYM %ACRDF==71 ;Read Forward +DEFSYM %ACRES==73 ;Read Extended Sense Information +DEFSYM %ACRDR==77 ;Read Data Reverse + + +DEFSYM %ARWC==%ARBAS+2 ;UNIBUS DMA WORD COUNT. (RH11) + ; Negative count of the number of PDP11 (18-bit) words to DMA + +DEFSYM %ARBA==%ARBAS+4 ;UNIBUS ADDRESS. (RH11) + ; Unibus address of start of DMA transfer + +DEFSYM %ARFC==%ARBAS+6 ;TAPE FRAME BYTE COUNT (MB Reg 05) + +DEFSYM %ARCS2==%ARBAS+10 ;CONTROL AND STATUS 2. (RH11) + DEFSYM %A2DL==1_15. ; Data Late + DEFSYM %A2UPE==1_13. ; Unibus Parity Error + DEFSYM %A2NF==1_12. ; Non-existant Formatter (TM78) + DEFSYM %A2NM==1_11. ; Unibus mem NXM during DMA + DEFSYM %A2PE==1_10. ; Program Error + DEFSYM %A2MT==1_9. ; Missed Transfer + DEFSYM %A2MDP==1_8. ; Massbus Data Bus Parity Error + DEFSYM %A2OR==1_7. ; Output Ready (for Silo buffer diag.) + DEFSYM %A2IR==1_6. ; Input Ready (for Silo buffer diag.) + DEFSYM %A2CC==1_5. ; Controller Clear + DEFSYM %A2PT==1_4. ; Parity Test + DEFSYM %A2UAI==1_3. ; Unibus Address Increment Inhibit + +DEFSYM %ARDER==%ARBAS+12 ;DATA TRANSFER ERROR REPORT (MB Reg 01) + DEFSYM %ADEIC==77 ; Interrupt Code + DEFSYM %ADEDP==1_8. ; DPR ??? + DEFSYM %ADEFC==77_10. ; Failure Code + +DEFSYM %ARDCA==%ARBAS+14 ;DATA COMMAND ARGUMENTS (MB Reg 02) + DEFSYM %ADACA==3 ; Command Address (TU78 unit number) + DEFSYM %ADARC==77_2. ; Record Count + DEFSYM %ADASC==17_8. ; Skip Count + DEFSYM %ADAFT==7_12. ; Format + DEFSYM %ADASR==1_15. ; Supress Repositioning on error + +DEFSYM %ARASN==%ARBAS+16 ;ATTENTION SUMMARY. (MB Reg 04) + ;Each bit 3-0 corresponds to a drive wanting attention + ; You must explicitly -RESET- an attention bit by writing a + ; one into it before the controller can interrupt you again. + +DEFSYM %ARDS==%ARBAS+20 ;DRIVE STATUS (MB Reg 07) + ;;; This register is valid only after a SENSE command + ;;; (or possibly an unsolicited ONLINE interrupt) + DEFSYM %ASRDY==1_15. ; Tape Ready + DEFSYM %ASPRE==1_14. ; Present (TM78 powered up) + DEFSYM %ASONL==1_13. ; Online + DEFSYM %ASREW==1_12. ; Tape Rewinding + DEFSYM %ASPE==1_11. ; Tape is Phase Encoded + DEFSYM %ASBOT==1_10. ; Tape at BOT + DEFSYM %ASEOT==1_9. ; Tape at EOT + DEFSYM %ASWPT==1_8. ; Tape is Write Protected + DEFSYM %ASUA==1_7. ; Unit Available + DEFSYM %ASUS==1_6. ; Unit is shared + DEFSYM %ASMMD==1_5. ; Unit is in Maintainance mode + DEFSYM %ASDSE==1_4. ; Data Security Erase in progress. + +DEFSYM %ARBUF==%ARBAS+22 ;DATA BUFFER REGISTER (RH11) + +DEFSYM %ARMR1==%ARBAS+24 ;MAINTENANCE REGISTER 1 (MB Reg 03) + +DEFSYM %ARTYP==%ARBAS+26 ;DRIVE TYPE. (MB Reg 06) + ;;; This register is valid only after a SENSE command + ;2.7 Not Sector addressed + ;2.6 Tape + ;2.5 Moving Head (always 0) + ;2.4 7 track (always 0) + ;2.3 Dual port (must do arbitration) + ;2.2 Slave present (always 1) + ;2.1 Writable Control Store (always 0) + ;1.9 - 1.1 Drive Type Number. + ; TU78=101 + +DEFSYM %ARSER==%ARBAS+30 ;SERIAL NUMBER (MB Reg 010) + ;;; This register is valid only after a SENSE command + ;0-3 SN digit 0, in BCD + ;4-7 SN digit 1 + ;8-11 SN digit 2 + ;12-15 SN digit 3 + +DEFSYM %ARMR2==%ARBAS+32 ;MAINTAINANCE REGISTER 2 (MB Reg 011) + +DEFSYM %ARMR3==%ARBAS+34 ;MAINTAINANCE REGISTER 3 (MB Reg 012) + +DEFSYM %ARNDE==%ARBAS+36 ;NON-DATA CMD ERROR REGISTER (MB Reg 013) + DEFSYM %ANEIC==77 ; NDT Interrupt code + DEFSYM %ANEAA==3_8. ; Attention Address (drive that caused this) + DEFSYM %ANEFC==77_10. ; NDT Failure Code + +DEFSYM %ARNDA==%ARBAS+40 ;NON-DATA CMD ARG REGISTERS (MB Reg 014 - 017) + ;;; There are four of these, one for each of the possible slave TU78 + ;;; units on the TM78. This is where you write commands that don't + ;;; move data over the massbus. + DEFSYM %ANCMD==77 ; Command to execute + DEFSYM %ANCNT==377_8. ; Count + +DEFSYM %ARIA==%ARBAS+50 ;INTERNAL ADDRESS (MB Reg 020) + +DEFSYM %ARID==%ARBAS+52 ;HARDWARE CONTROL (MB Reg 021) + DEFSYM %AHRDY==1_15. ; Set when controller is ready. (read only) + DEFSYM %AHCLR==1_14. ; Write 1 here to reset controller. + ;;; And a bunch of other stuff + + +IFN $$TEMP,EXPUNG DEFSYM + + diff --git a/src/system/ts3tty.400 b/src/system/ts3tty.400 new file mode 100755 index 00000000..be6f862e --- /dev/null +++ b/src/system/ts3tty.400 @@ -0,0 +1,8214 @@ +;-*-MIDAS-*- + +TTYVRS==.IFNM2 + +OVHMTR TTY ;MISC TTY CODE + +SUBTTL SPY DEVICE + +;FIRST FILE NAME MUST BE TTY NUMBER (NOT CHARACTERS) + +SPYO: JUMPN D,OPNL12 ;ONLY UNIT ASCII INPUT ALLOWED + JUMPL A,OPNL11 + CAIL A,NCT + JRST OPNL11 + MOVE E,TIIP(A) + MOVEM E,IOCHST-IOCHNM(R) + MOVEI C,ISPY + HRL C,A + MOVEM C,(R) + JRST POPJ1 + +;A HAS LH OF IOCHNM =TTY # + +SPYI: MOVE T,IOCHST-IOCHNM(R) ;POINTER TO INPUT BUFFER + HRRZ B,TIBEP(A) + CAIL B,(T) + CAILE B,TIBL(T) + JRST SPYIL +SPYILL: CAMN T,TIIP(A) + PUSHJ P,UFLS + CAMN T,TIBEP(A) + SUBI T,TIBL + HRRM T,IOCHST-IOCHNM(R) + ILDB W,IOCHST-IOCHNM(R) + POPJ P, + +SPYIL: MOVE T,TIIP(A) + MOVEM T,IOCHST-IOCHNM(R) + JRST SPYILL + +;.CALL RFNAME on a SPY channel. A contains LH(IOCHNM) = TTY # +SPYRCH: MOVEI B,(A) ;FN1 is TTY # + POPJ P, ;easy! + +SUBTTL STY DEVICE + +;STY OPEN + +;MODE BITS (LH) +;3.1=0 => INPUT =1 => OUTPUT (FROM PROGRAM POINT OF VIEW) +;3.2=0 => UNIT =1 => BLOCK +;INPUT +;3.3=0 => FULL DUPLEX =1 => HALF DUPLEX +;3.4=1 => DON'T HANG ON INPUT IOTS, INPUT -1 INSTEAD (IGNORED ON OUTPUT OPEN) +;3.5=1 => WANT TO GET %TDORS ON OUTPUT RESET. + ;BIT 3.5 NOTICED ON OUTPUT, TOO, BUT THAT'S NO FEATURE? + +STTYO: HRRZ I,USTYN(U) + JUMPN I,STTYO3 ;JUMP IF STY ALREADY OPEN + PUSHJ P,SWTL ;LOCK STY OPEN SWITCH + STYOSW + MOVE I,[-NSTTYS,,NFSTTY] + MOVSI TT,%SSUSE +STTYO1: TDNE TT,STYSTS-NFSTTY(I) ;SKIP ON FREE SLOT +STTYO5: AOBJN I,STTYO1 + JUMPGE I,OPNL6 ;NO SLOTS. GIVE DEVICE FULL + SKIPGE TTYSTA(I) ;SKIP IF CONSOLE FREE MSG NOT TYPED. + SKIPE TTNTO(I) ;SKIP IF NOT OPEN. + JRST STTYO5 + MOVEI I,(I) ;We want to compare left half + CAMLE I,STYMAX ;If we're limiting STY's, is this over our + JRST OPNL6 ; limit? If so, give DEVICE FULL + HRRM I,USTYN(U) ;STORE TTY NUMBER OF STY +STTYO4: ANDI I,-1 + SETZM STYNTO-NFSTTY(I) + SETZM STYMSK-NFSTTY(I) + MOVSI TT,%SSUSE + MOVEM TT,STYSTS-NFSTTY(I) ;SET IN USE BIT + MOVSI TT,(<.BM ($TTISP)>+<.BM ($TTOSP)>) + ANDCAM TT,TTYTYP(I) ;RESET SPEEDS TO ZERO + PUSH P,C + PUSHJ P,NCNSSP ;MAKE THE TTY A PRINTING TTY. + PUSHJ P,TTYIN1 ;INIT THE TTYOPT AND TTYCOM USER OPTION BITS. + PUSHJ P,STYIR1 ;FLUSH TTY'S OUTPUT BUFFER. + PUSHJ P,STYOR1 ;AND ITS INPUT BUFFER. + PUSHJ P,LSWPOP ;UNLOCK STY OPEN SWITCH + POP P,C + HRRM U,STYSTS-NFSTTY(I) + MOVE T,UTMPTR(U) ;Check out this tree + CAIE T,SYSRCE-1 ;Is this a top-level non-console tree, + CAIN T,SYSRCE ;or a system demon? + JRST STTYO3 ; Yes, don't print on console. + ; since TELSER, etc., logs in + MOVEI T,(I) ;Get TTY number + HRLI T,[ASCIZ / STYOPN /] + PUSHJ P,SGWAIT ;Ask SYSJOB to print the info + MOVE T,JNAME(U) ;Add the JNAME to the info + MOVEM T,SLGIV+2 ;to be printed + +STTYO3: JUMPL D,[MOVSI TT,%SSOHG ;JUMP IF OPENING FOR OUTPUT + JRST STTYO2] + LDB TT,[240100,,C] + DPB TT,[400100,,STYSTS-NFSTTY(I)] .SEE %SSHDX + DPB TT,[$TOHDX,,TTYOPT(I)] + MOVSI TT,%SSHNG +STTYO2: TLNE C,10 + IORM TT,STYSTS-NFSTTY(I) + MOVSI TT,%SSORS + TLNE C,20 + IORM TT,STYSTS-NFSTTY(I) + MOVE J,R + SUBI J,IOCHNM(U) ;CHANNEL BEING OPENED FOR INPUT ON + MOVE J,CHNBIT(J) + SKIPL D ;SKIP IF OUTPUT + IORM J,STYMSK-NFSTTY(I) + SKIPGE D ;SKIP IF INPUT + IORM J,STYOMS-NFSTTY(I) + AOS STYNTO-NFSTTY(I) + HRLZ A,I ;LH OF IOCHNM GETS STY NUMBER + MOVSS C + JSP Q,OPSLC3 + STYDUI,,STYDUO + STYDBI,,STYDBO + + +;ENTRY FOR OPEN OF PSEUDO-TTY AS SNM OR STN +STTYOA: JUMPL I,OPNL1 + CAIL I,NSTTYS + JRST OPNL1 + ADDI I,NFSTTY + PUSHJ P,SWTL + STYOSW + MOVE TT,STYSTS-NFSTTY(I) ;SKIP IF IN USE + TLNN TT,%SSUSE + JRST STTYO4 ;OK TO OPEN IF FREE + CAIE U,(TT) + JRST OPNL10 ;DIFFERENT USER HAS IT OPEN + PUSHJ P,LSWPOP + JRST STTYO3 + + JRST STTS ;STY INPUT SIOT ROUTINE. +;PSEUDO-TTY INPUT ROUTINE. RETURNS CHAR WITHOUT PARITY BIT +STTYI: MOVE I,A +STTYIA: SKIPGE TTYOAC(I) ;SKIP IF ANY CHARS AVAIL (MAYBE) + JRST STTYI1 +STTYI4: PUSH P,C + PUSH P,E + CONO PI,TTYOFF + PUSHJ P,TYPSC + POP P,E + POP P,C + MOVE U,USER + MOVE W,STYICH + SKIPGE DBBBP + JRST STTYI2 ;REALLY NO CHARS AVAIL + CONO PI,TTYON + MOVSI R,%SSONT ;FOR TTYO INT TO STYI + JRST STTYIC ;INT CLEAR + +STTYI2: CONO PI,TTYON +STTYI1: SKIPGE STYSTS-NFSTTY(I) + JRST STTYI3 ;DON'T HANG + SKIPGE TTYOAC(I) + PUSHJ P,UFLS + JRST STTYIA + +STTYI3: MOVNI W,1 + TLO E,100000 .SEE INBTCH ;UNHANG BLOCK MD IOT IMMEDIATELY. + JRST POPJ1 ;UNHANG SIOT IMMEDIATELY. + +;STY INPUT SIOT; GOES 1 WORD AT A TIME, WHATEVER THE USER'S BYTE SIZE. +STTS: XCTR XRW,[SKIPG E,(C)] + JRST POPJ1 ;RETURN AT ONCE IF NO CHARS WANTED BY USER. + PUSH P,B ;SAVE ADDRS OF USER'S B.P. AND COUNT. + PUSH P,C +STTSA: SKIPGE TTYOAC(I) + JRST STTS4 ;NO INPUT AVAILABLE. +STTS2: UMOVE B,@-1(P) +STTS1: XCTR XRW,[MOVES D,(B)] +;IT IS ASSUMED THAT E HAS THE # OF CHARS THE USER WANTS. + CONO PI,TTYOFF + MOVEM D,STYICH ;STORE THE WORD THE USER'S B.P. POINTS AT. + LDB C,[360600,,B] + LDB D,[300600,,B] + IDIV C,D ;HOW MANY MORE CHARS GO IN THIS WORD? + JUMPE C,STTS7 + PUSH P,B ;SAVE STARTING B.P. AND # CHARS FITTING IN WORD. + HRRI B,STYICH ;SET UP TO STORE CHARS AT APPRO. PLACE IN STYICH. + MOVEM B,DBBBP + CAML C,E + MOVE C,E ;GET MIN OF # CAHRS FITTING IN WORD AND # CHARS USER WANTS. + MOVEM C,DBBCC ;THAT'S HOW MANY CHARS WE CAN ACCEPT THIS TIME. + MOVEM C,DBBCC1 + PUSHJ P,TYP ;FILL UP STYICH WITH CHARS, VIA DBBBP. + POP P,B ;NOTE E HAS -<# CHARS GOBBLED> + MOVE D,STYICH ;GET USER'S WORD, WITH CHARS STUCK IN IT. + UMOVEM D,(B) ;STORE IT WHERE IT CAME FROM. + XCTR XRW,[ADDB E,@(P)] ;UPDATE COUNT BY -<# CHARS OBTAINED>. + HLL B,DBBBP ;UPDATE B.P. TO THE L.H. CORRESP. TO CHARS STORED IN STYICH. + UMOVEM B,@-1(P) + SKIPE DBBCC ;DID WE GET AS MANY CHARS AS WE WANTED? + JRST STTS3 ;NO, SO EITHER RETURN OR HANG UP. + CONO PI,TTYON + JUMPG E,STTS7 ;USER WANTS MORE CHARS => TRANSFER ANOTHER WORD. +STTS5: MOVE U,USER + MOVSI R,%SSONT + SUB P,[2,,2] + AOS (P) + JRST STTYIC + +;COME HERE DURING STY INPUT SIOT IF USER WANTS CHARS BUT THERE ARE NONE. +STTS3: CONO PI,TTYON +STTS4: SKIPGE STYSTS-NFSTTY(I) + JRST STTS5 ;DON'T HANG MODE. + SKIPGE TTYOAC(I) + PUSHJ P,UFLS + JRST STTSA + +STTS7: AOS B +STTS6: TLZ B,770000 + TLO B,440000 + JRST STTS1 + +;PSEUDO-TTY OUTPUT +STTYW: MOVE I,A + SKIPGE C + SKIPA A,(C) + UMOVE A,(C) +BSTTYW: MOVSI T,%SSOHG ;BIT ON SAYS DONT HANG + TDNE T,STYSTS-NFSTTY(I) + JRST BSTTYX ;J TO NOT HANG. CHARS MAY BE LOST + MOVEI T,TIBS + CAMG T,TICC(I) + PUSHJ P,UFLS ;HANG UNTIL ROOM IN INPUT BUFFER +BSTTYX: CONO PI,TTYOFF + PUSH P,I + PUSHJ P,NTYI5 + POP P,I + MOVE U,USER + MOVSI R,%SSINT +STTYIC: ANDCAM R,STYSTS-NFSTTY(I) ;CALLED BY STTYI ABOVE ALSO + HRRZ R,UUAC(U) + MOVE R,CHNBIT(R) + ANDCAM R,IFPIR(U) ;FLUSH ANY OUTPUT INTERRUPT + CONO PI,TTYON + POPJ P, + +STTBI: JSP E,INBTCH + JRST STTYI + +STTBO: JSP E,NBTOCH + CAIN A,EOFCH + POPJ P, + HLRZ I,(R) + PUSH P,R + PUSH P,D + PUSH P,TT + PUSH P,E + PUSH P,C + PUSHJ P,BSTTYW + POP P,C + POP P,E + POP P,TT + POP P,D + POP P,R + POPJ P, + +;STY OUTPUT CLOSE. +STYOCL: SUBI R,IOCHNM(U) + MOVE B,CHNBIT(R) + ANDCAM B,STYOMS-NFSTTY(A) + JRST STYCL + +;STY INPUT CLOSE +STYICL: SUBI R,IOCHNM(U) + MOVE B,CHNBIT(R) + ANDCAM B,STYMSK-NFSTTY(A) +STYCL: SOSE STYNTO-NFSTTY(A) + POPJ P, +STYCL1: PUSHJ P,TTYLFC ;LEAVE COM. MODE, PUT TTY # IN I. +IFN NETP,[ + PUSHJ P,NSTYN0 ;DISCONNECT ANY NET SOCKETS FROM THE STY + JFCL +] + CONO PI,TTYON#200_<-APRCHN> ;LEAVE CLOCK OFF. + SKIPGE C,TTYSTS(I) + JRST STYOC8 ;TTY NOT IN USE. + TLNN C,%TSCNS + JRST STYOC9 ;OPEN AS DEVICE, NOT AS CONSOLE. + PUSH P,U +STYOC3: HRRZ U,C + SKIPL C,SUPPRO(U) + JRST STYOC3 ;NOT TOP LEVEL + MOVE C,USER +STYC4A: HRRZ TT,C + SKIPL C,SUPPRO(TT) + JRST STYC4A + AOS STYNTO-NFSTTY(I) ;IN CASE WE PCLSR, PREVENT JRST 4,. + PUSH P,I + CAME U,USER ;DON'T GET INTO LOOP AT ALOGO1 + PUSHJ P,ALOGOUT ;TELL SYS JOB TO FLUSH THE TREE UNDER THE STY. + POP P,I + POP P,U + SOS STYNTO-NFSTTY(I) +STYOC5: PUSHJ P,STYIR1 ;FLUSH TTY OUTPUT BUFFER. +STYOC9: SETZM STYSTS-NFSTTY(I) + CAIN I,@USTYN(U) ;IF HE'S CLOSING HIS STY:, SAY HE HAS NONE. + HLLZS USTYN(U) + JRST CLKONJ + +STYOC8: SKIPGE TTYSTA(I) ;IN TRANSIENT STATE BETWEEN USAGE AND NOT? + JRST STYOC5 ;NO, REALLY FREE, SIMPLE. + CONO PI,CLKON + AOS STYNTO-NFSTTY(I) + MOVE T,I + PUSHJ P,STYOCF + PUSHJ P,UFLS + MOVE A,I + JRST STYCL + +STYOCF: SKIPGE TTYSTS(T) ;IF NOW IN USE + SKIPGE TTYSTA(T) ;OR COMPLETELY FREE, + AOS (P) ;THEN NO LONGER IN TRANSIENT STATE. + POPJ P, + +;STY OUTPUT .CALL FINISH +STYFIN: SKIPE TICC(A) ;WAIT UNTIL CORRESPONDING INPUT BUFFER IS EMPTY + PUSHJ P,UFLS + JRST POPJ1 + +;STY OUTPUT .CALL WHYINT +STOWHY: MOVEI A,%WYSTO ;NULL ROUTINE FOR NOW + JRST POPJ1 + +;STY INPUT .CALL WHYINT +STIWHY: MOVEI A,%WYSTI ;NULL ROUTINE FOR NOW + JRST POPJ1 + +;STY INPUT RESET. DOES TTY OUTPUT RESET, WITH THE TTY'S OWNER STOPPED. +STYIRS: HLRZ I,(R) +STYIR1: CONO PI,TTYOFF + SKIPGE B,TTYSTS(I) + JRST STYIR2 ;TTY IS FREE => NO PROBLEM. + HRRZ A,B + PUSHJ P,RPCLSR ;ELSE MUST MAKE SURE ITS OWNER ISN'T TYPING OUT. + CONO PI,TTYOFF + XOR B,TTYSTS(I) ;WE MIGHT HAVE BEEN DELAYED - HAS TTY MOVED AROUND? + TRNN B,-1 + JRST STYIR4 ;NO; THE GUY WAS STOPPED WHILE STILL ITS OWNER. + PUSHJ P,UPCLSR ;YES; UNSTOP GUY WE STOPPED, + JRST STYIR1 ;THEN GO STOP THE NEW OWNER. + +STYIR4: PUSH P,A ;SAVE JOB STOPPED + PUSHJ P,STYIR2 ;ACTUALLY DO THE RESET OF TTY OUTPUT + POP P,A + JRST UPCLSR ;THEN UNSTOP THE TTY'S OWNER + +STYIR2: SETOM TTYOAC(I) ;WE WILL NO LONGER BE LOOKING FOR TTY'S OUTPUT. + JRST TYORS1 ;DO THE TTY OUTPUT RESET AND TURN ON PI CHANNELS. + +;STY OUTPUT RESET. +STYORS: HLRZ I,(R) +STYOR1: CONO PI,TTYOFF + PUSHJ P,TYIRS1 ;TURNS INTO TTY INPUT RESET. + JRST TTYONJ + +;STY OUTPUT STATUS - BIT 2.1 => BUFFER FULL, 2.2 => EMPTY. +STASTO: ANDI A,77 + SKIPN B,TICC(A) + IORI D,1_<9+1> ;BUFFER EMPTY. + CAIL B,TIBS-10. + IORI D,1_9 ;ALMOST FULL. + POPJ P, + +;STY INPUT STATUS - THE SAME 2 BITS. +STASTI: ANDI A,77 + SKIPG B,TORM(A) + IORI D,1_9 ;FULL. + CAIN B,TOBS + IORI D,1_<9+1> ;EMPTY. + POPJ P, + +;"STYGET" SYSTEM CALL. 1 ARG, A TTY SPECIFYER. +;1ST VALUE IS STYSTS WORD (RH IS JOB NUMBER OF OWNER OF STY). 0 FOR FREE STY. +; %SSHNG AND %SSOHG BITS MAY BE INTERESTING. +;2ND VALUE IS JOB THAT OWNS CORRESP. TTY (OR -1 IF TTY FREE). +;3RD VALUE IS -1 IF TTY NOT CONSOLE; ELSE JOB NUMBER OF TOP OF TREE IN RH +; AND BIT 4.8 SET IFF IT IS LOGGING OUT. +; AND BIT 4.7 SET IF IT IS LOGGED IN. +;4TH VALUE BITS ARE: +; 1 IF TTY OWNER IS IN TYO WAIT +; SIGN IF HE'S IN TYI WAIT. +;5TH VALUE BITS ARE: +; 4.9 => TTY INPUT AVAILABLE +; 4.8 => TTY OUTPUT BUFFER HAS ROOM +;6TH VALUE IS TTYSTA WORD + +NSTYGT: JSP J,ATTYCI ;DECODE A TTY-SPECIFYER IN A. + CONO PI,CLKOFF + SETZ A, + MOVE TT,TTYTYP(I) + TRNN TT,%TYSTY ;IF SPEC'D TTY ISN'T ASSOCIATED WITH A STY, IT HAS NO STYSTS WORD. + JRST NSTYG3 + HRRZ A,STYSTS-NFSTTY(I) + IDIVI A,LUBLK ;NUMBER OF JOB USING THE STY. + HLL A,STYSTS-NFSTTY(I) ;AND SOME RANDOM BITS. +NSTYG3: SETOB B,C ;B GETS # OF JOB THAT HAS TTY, OR -1. + ;C GETS (IF TTY IS CONSOLE, JOB # OF TOP OF TRREE, ELSE -1). + SETZB D,E ;D, E SHOULD GET 0 IF NO JOB HAS TTY. + HRRE B,TTYSTS(I) + JUMPL B,NSTYG1 ;JUMP IF CONSOLE NOT IN USE. + IDIVI B,LUBLK ;ELSE GET JOB NUMBER OF JOB USING IT. + MOVE D,TTYSTS(I) + TLNN D,%TSCNS ;TTY NOT CONSOLE => DON'T REPLACE THE -1 IN C WITH ANYTHING. + JRST NSTYG2 + HRRZ C,TTYSTS(I) + SKIPL D,SUPPRO(C) ;ELSE TRACE SUPPRO'S TO TOP OF TREE. + JRST [ HRRZ C,D + JRST .-1] + MOVE TT,APRC(C) + HLRE W,UNAME(C) + IDIVI C,LUBLK ;GET JOB # OF TOP OF TREE. + TLNE TT,BULGOS + TLO C,200000 + AOSE W + TLO C,100000 +NSTYG2: SETZ D, + MOVE TT,TTYSTS(I) + HRRZ TT,FLSINS(TT) ;WHAT VARIABLE IS FLSINS OF JOB OWNING TTY WAITING ON? + CAIE TT,TICC(I) ;RETURN IN D SETZ IFF JOB IS IN TYI WAIT, + CAIN TT,TACC(I) + MOVSI D,(SETZ) + CAIN TT,TORM(I) + MOVEI D,1 ;OR 1 IF JOB IS IN TYO WAIT; ELSE 0. +NSTYG1: SKIPE TICC(I) + TLO E,400000 + MOVE TT,TORM(I) + CAIL TT,TYOWNC + TLO E,200000 + MOVE TT,TTYSTA(I) + CONO PI,CLKON + JRST POPJ1 + +;.CALL STLGET - GET INFO FROM SERVER TELNET + +; Arg 1: a TTY +; Val 1: XJNAME of server telnet +; Val 2: TRMNAM of server telnet (has sixbit name of host) +; Val 3: SNAME of server telnet +; Val 4: STY control bits,,STY owner idx + +NSTLGT: JSP J,ATTYCI + SETZB A,B + SETZB C,D + MOVE TT,TTYTYP(I) + TRNN TT,%TYSTY + JRST OPNL34 + SKIPN T,STYSTS-NFSTTY(I) ;Get STY status bits,,STY user. + JRST POPJ1 + MOVE A,XJNAME(T) + MOVE B,TRMNAM(T) + MOVE C,USYSNM(T) + HRRZ D,T + IDIVI D,LUBLK ;Make it into user index. + HLL D,T ;Stuff STY status bits in LH. + JRST POPJ1 + + +SUBTTL .ATTY, .DTTY - PASS CONTROL OF TTY + +NATTY: MOVE J,A ;.CALL ATTY + JSP T,NCRUI2 ;DECODE JOBSPEC BUT DON'T SET DIELOK + JFCL +IFN PDP6P,[ + CAIN J,-1 + JRST OPNL34 ;SORRY, I/O BUS MPXR IS NOT THAT HAIRY +] + HRRZ B,SUPPRO(J) + CAME B,U + JRST OPNL31 ;NOT DIRECT INFERIOR (CAN'T MODIFY JOB) + MOVE A,J + JRST NATTY1 + +; .ATTY USR, OPER 11 + +AATTY: HLRZ A,(R) ;A HAS INFERIOR'S USER INDEX + HRRZ B,(R) + SKIPL CLSTB(B) .SEE %CLSU ;SKIP IF USER OPEN ON CHANNEL + JRST OPNL34 +NATTY1: MOVE TT,APRC(A) + TLNE TT,BULGOS ;REFUSE TO GIVE TTY TO A DYING JOB. + JRST OPNL42 ;JOB GOING AWAY + CONO PI,CLKOFF + MOVE I,TTYTBL(U) + JUMPL I,AATT1 ;DOESNT HAVE TTY NOW + HLLZS TTYTBL(U) + HRLI A,%TBNOT + IORM A,TTYTBL(U) ;NO LONGER HAS TTY. STORE USER INDEX GIVEN TO + PUSHJ P,AATT6 ;A _ IDX OF USER TO RECEIVE TTY, + ;ALSO CHANGE ALL TTYTBL VARS THAT NEED IT. + EXCH A,U + PUSHJ P,AGBLT6 ;TAKE TTY FROM USER IN A (ME), + ;GIVE TO USER IN U (HIM) + ;CHANGES TTY VARS AND TTSTSV VARS. + ;ALSO SETS CHANNELS-OPEN MASKS. + ;TURNS ON ALL PI CHNLS. + EXCH A,U + JRST POPJ1 + +AATT1: TLZN I,%TBDTY ;SAY OUR INFERIOR HAD IT WHEN TAKEN + JRST OPNL10 ;DEVICE NOT AVAILABLE, ALREADY GAVE TTY AWAY + HRRI I,(A) + MOVEM I,TTYTBL(U) + PUSHJ P,AATT6 ;SET UP HIS VARS + JRST CLKOJ1 + +;CHANGE TTYTBL VARS OF ALL JOBS DOWN TO THE ONE GETTING THE TTY. +;RETURN IN A, T, TT THE TTYSTS, TTYST1, TTYST2 SETTINGS FOR THAT JOB. +;IF THAT JOB NEVER HAD THE TTY, INIT HIS TTSTSV VARS. +;I HAS TTY #, U HAS RUNNING JOB. +AATT6: MOVE E,TTYTBL(A) + MOVSI T,%TSATY ;TELL THIS GUY TTY WAS TAKEN FROM HIM & RETURNED. + IORM T,TTSTSV+2(A) + TLNE E,%TBDTY ;SKIP IF NOT TAKEN FROM ME + JRST AATT3 ;GUY IT WAS TAKEN FROM (I.E. HE HADN'T GIVEN IT TO SOMEONE ELSE) + HRRZ A,TTYTBL(A) + JRST AATT6 + +AATT3: HRRZS I ;TTY NUMBER + HLL A,TTSTSV+2(A) + TLZ A,%TSFRE+%TSLCZ ;CLEAR TTY NOT OPEN AND ^Z BITS + MOVEM A,TTSTSV+2(A) ;UPDATE SAVED TTY STATUS + POPJ P, + +;SET UP TYIMSK AND TYOMSK. ARGS: TTY # IN I, +;D -> 1ST IOCHNM WORD OF USER TO SET UP FOR. +;MAKE LAST CHAR IN INPUT BFR AN ACTIVATION CHAR. TURN ON TTYCHN. +AATT8: SETZM TYOMSK(I) + SETZM TYIMSK(I) + CONO PI,TTYOFF + HRLI D,A ;INDIRECTION POINTER TO INFERIOR'S IO CHANNELS + MOVSI A,-20 ;AOBJN POINTER +AATT9: MOVE B,@D ;GET IOCHNM IN B + JUMPGE B,AATT10 ;IF CHANNEL HAS CONSOLE BIT SET, + ANDI B,-1 + MOVE C,CHNBIT(A) ;GET THE BIT WE MIGHT WANT TO SET. + CAIE B,TYODN + CAIN B,TYOBN ;IF TTY OUTPUT CHNL, + IORM C,TYOMSK(I) ;SET BIT IN OUTPUT MASK. + CAIE B,TYIDN + CAIN B,TYIBN ;IF INPUT, SET IN INPUT MASK. + IORM C,TYIMSK(I) +AATT10: AOBJN A,AATT9 ;TRY NEXT CHANNEL OR CONTINUE IF DONE + JRST ATTYS1 ;ALL CHRS SO FAR ARE ACTIVATION CHRS + +ADTTY: ;DON'T CLOBBER R (SEE AUCL2) +SDTTY: CONO PI,CLKOFF + MOVE A,TTYTBL(U) + JUMPGE A,CLKOJ1 ;I ALREADY HAVE IT + TLNE A,%TBDTY + JRST CLKOJ1 ;I ALREADY DID A .DTTY AND SO DID MY SUPERIOR + +;LOOK FOR SUBJOB THAT HAS TTY, OR DOESN'T WANT TO GIVE TTY +;AWAY IF IT GETS THE TTY. +AGBLT3: MOVE I,TTYTBL(A) + TLNE I,%TBDTY ;REACHED A JOB THAT DIDN'T GIVE TTY AWAY + JRST AGBLT1 ;THIS IMPLIES OUR SUPERIOR TOOK TTY AWAY. + JUMPL I,AGBLT2 ;IF THIS GUY GAVE IT AWAY THEN TRY THE ONE HE GAVE IT TO + HRRZS A ;A HAS IDX OF TTY OWNER; TAKE TTY FROM HIM. + PUSHJ P,RPCLSR ;TURNS CLOCK ON! + CONO PI,CLKOFF + SKIPGE TTYTBL(A) ;DID TTY MOVE WHILE CLOCK WAS ON? + JRST [PUSHJ P,UPCLSR ;IF SO, START OVER + JRST SDTTY] + HLLZ D,TTYTBL(A) + TLZ D,%TBCLR ;DON'T ALTER USER-SETTABLE BITS, BUT + TLO D,%TBNOT+%TBDTY ;TELL HIM HE HASN'T GOT TTY. + MOVEM D,TTYTBL(A) + AOS (P) ;THE .DTTY SHOULD SKIP. + PUSH P,[UPCLSR] ;AFTER RESTARTING THE SUBJOB. +AGBLT6: ANDI I,-1 ;LH(TTYTBL) MAY BE NONZERO EVEN IF JOB HAS TTY! + MOVSI D,%TCLED + TDNE D,TTYCOM(I) ;IF OLD JOB WAS WANTING LOCAL EDITING, + PUSHJ P,AGBLT5 ;TELL TERMINAL TO STOP IMMEDIATELY. + ANDCAM D,TTYCOM(I) ;ASSUME NEW JOB DOES NOT WANT LOCAL EDITING + ;AND SHOULD NOT SEE RESYNCHS (TOP-S). + MOVEI D,TTSTSV-1(A) ;SAVE CURRENT TTY STATUS IN + PUSH D,TTYST1(I) ;USER VARS OF USER GIVING AWAY THE TTY. + PUSH D,TTYST2(I) + PUSH D,TTYSTS(I) + MOVE TT,I + IMULI TT,TPLEN*2 + MOVE D,TPVB+TPLEN(TT) + SUB D,TCMXV(I) + MOVNS D + DPB D,[$TBECL,,TTYTBL(A)] +IFN N11TYS,[ + EXCH U,A ;GET USER GIVING AWAY TTY IN U + MOVE D,TVVBN(U) ;SAVE THIS + PUSHJ P,TVBNCL ;CLEAR OUT CURRENT GUY (MAYBE CLEARING RUN GLITCH ON SCREEN) + MOVEM D,TVVBN(A);PASS THE BALL TO HIM + EXCH U,A +] +;ENTRY FROM "ATTACH". GIVE TTY TO JOB W/ IDX IN U, WITHOUT +;"TAKING" IT FROM ANY JOB. USED WHEN TTY HAD BEEN FREE; JOB, DISOWNED. +AGBLT4: HRROI D,TTSTSV+2(U) + POP D,TTYSTS(I) ;RESTORE THE TTY STATUS OF JOB GIVING TTY TO. + POP D,TTYST2(I) + POP D,TTYST1(I) + HRRM I,TTYTBL(U) ;INDICATE THAT IT HAS THE TTY + LDB H,[$TBECL,,TTYTBL(U)] + HRLOI D,#%TBCLR + ANDM D,TTYTBL(U) + PUSHJ P,ASCML1 ;SET # COMMAND LINES FROM H + MOVSI D,%PJATY + AND D,MSKST(U) + IORM D,PIRQC(U) + MOVEI D,IOCHNM(U) + PUSH P,A ;GENERATE CHNLS-OPEN MASKS, CREATE AN + PUSHJ P,AATT8 ;ACTIVATION CHAR IF NEC, TURN ON PI. + JRST POPAJ + +AGBLT2: HRRZ A,TTYTBL(A) + JRST AGBLT3 + +AGBLT1: MOVSI A,%TBDTY ;TTY WAS TAKEN AWAY FROM US, + IORM A,TTYTBL(U) ;WHEN GIVEN BACK WILL STOP WITH THIS JOB. + JRST CLKOJ1 + +;TELL TERMINAL TO STOP DOING LOCAL EDITING IMMEDIATELY. +AGBLT5: MOVE H,TTYOPT(I) + TRNE H,%TP11T + POPJ P, ;DON'T EVEN TRY ON A TV -- TORM DOESN'T MEAN ANYTHING. + SKIPG TORM(I) ;WAIT FOR ROOM IN OUTPUT BUFFER. + PUSHJ P,UFLS + PUSH P,A + MOVE Q,TOIP(I) + MOVEI A,%TDNLE + PUSHJ P,TYOOU1 ;PUT CMD IN OUTPUT BFR, + MOVEM Q,TOIP(I) + AOSN TTYOAC(I) + XCT TTYST(I) ;AND TELL INT. LVL. ABOUT IT. + JRST POPAJ + +SUBTTL CNSSET, TTYSET, ETC. .CALLS FOR TTYS + +;DECODING TTY SPECIFIERS. CALL WITH JSP,J. MAY RETURN TO (J), +;OR POPJ AND REPORT AN ERROR. + +;DECODE A TTY SPECIFIER, BUT DON'T CHECK FOR PERMISSION TO +;USE THE TTY. ALWAYS RETURN IMMEDIATELY WITH LEGAL TTY SPECIFIER. +ATTYCI: MOVEI Q,CPOPJ + JRST ATTYC8 + +;DECODE A TTY SPECIFIER. +;IF W IS GREATER THAN ONE, DO NOT ALLOW RANDOM TTY NUMBERS. +;ALWAYS WAIT FOR PERMISSION TO OUTPUT. +;IF THE SPECIFIED TTY IS OUR CONSOLE AND OUTPUT IS BEING IGNORED, +;CLOBBER W TO ONE, SO THAT ITS PARAMETERS WILL NOT BE CHANGED (FOR SCPOS). +ATTYCW: JSP Q,[ CAIGE W,2 + JRST ATTYC8 + JRST ATTYC7 ] + PUSHJ P,TTYWO2 + MOVEI W,1 + POPJ P, + +;DECODE A TTY SPEC. +;IF THERE ARE TWO OR MORE ARGS, AND IT IS OUR CONSOLE, +;WAIT UNTIL WE OWN IT, OR MAYBE INTERRUPT. +ATTYC: CAIGE W,2 + JRST ATTYCI +;DECODE A TTY SPEC. +;IF IT IS OUR CONSOLE, WAIT TILL WE OWN IT, OR MAYBE INTERRUPT. +ATTYC2: MOVEI Q,TTYWC2 + JRST ATTYC7 + +;DECODE A TTY SPEC. +;IF IT IS OUR CONSOLE, WAIT TILL WE CAN DO INPUT, +;OR INTERRUPT IF DOING INPUT WOULD. +ATTYCR: MOVEI Q,TTYWI2 + JRST ATTYC7 + +;DECODE A TTY SPEC. SKIP IF IT REFERS TO OUR CONSOLE. +;DO NOT ALLOW RANDOM TTY NUMBERS. +ATTYCM: MOVEI Q,[AOJA J,CPOPJ] + JRST ATTYC7 + +;DECODE A TTY SPEC. SKIP IF IT REFERS TO OUR CONSOLE. +ATTYC9: MOVEI Q,[AOJA J,CPOPJ] +;DECODE CHNL # (IF < 400000) OR TTY # (OTHERWISE) IN A. -1 MEANS TREE'S CONSOLE. +;IF CHNL # BAD, POPJ WITH OPNL. IF NOT STY OR TTY, POPJ WITH OPNL. +;IF OUR CONSOLE, CALL THE ROUTINE Q POINTS TO. +;THEN RETURN WITH TTY # IN I. +ATTYC8: TDZE A,[-400000] ;IS IT A TTY NUMBER? + JRST ATTYC3 ;YES, DECODE THAT. +;DECODE CHNL #, TTY # NOT ALLOWED. +ATTYC7: HRRE T,A + AOJE T,ATTYC6 + HRLI J,ATTYC5 ;RETURN THERE IF NORMAL, OPEN CHANNEL + MOVEI T,AIOCAL ;USE JOB DEVICE CHECKER + JRST CHNDCD ;DECODE CHANNEL AND HANDLE JOB DEVICE SPECIALLY. + +;CHNDCD RETURNS HERE WITH IOCHNM WORD CONTENTS IN H. +ATTYC5: HRRZ T,H + LDB I,[$TIIDX,,H] ;FOR EITHER TTY CHNL OR STY CHNL, GET TTY #. + CAIN I,%TINON ;TREE HAS NO TTY => RETURN "DEVICE NOT AVAILABLE". + JRST OPNL10 + CAIG T,4 ;TTY CHNL => GOOD. + JUMPG T,ATTYC4 + CAIL T,STYDUI + CAILE T,STYDBO + JRST OPNL34 ;NOT STY => BAD. + JRST (J) ;STY => GOOD. + +ATTYC4: LDB T,[.BP <%TICNS,,>,H] ;GET DEVICE/CONSOLE BIT + JUMPE T,ATTYC1 ;JUMP IF IT'S A DEVICE. + PUSHJ P,(Q) ;AWAIT TTY OR INTERRUPT + LDB I,[$TIIDX,,(R)] + SKIPGE T,TTYTBL(U) + JRST (J) ;USER DOESN'T HAVE THE TTY (^P), ERROR CHECKS DON'T APPLY + CAIE I,(T) + BUG ;USER HAS TWO DIFFERENT CONSOLE TTYS +ATTYC1: HRRZ T,TTYSTS(I) ;USER INDEX THAT HAS THIS TTY + CAME T,U + BUG ;USER HAS TTY BUT TTY DOESN'T HAVE THAT USER + JRST (J) + +ATTYC3: MOVEI I,(A) + CAIGE I,NCT ;IS THE ARG THE # OF A REAL TTY? + JRST (J) ;YES, OK. + CAIE I,377777 ;SKIP IF ARG WAS -1 + JRST OPNL1 ;"NO SUCH DEVICE" ERROR. +ATTYC6: PUSHJ P,(Q) ;"MY OWN CONSOLE" SPECIFIED; WAIT OR INTERRUPT. + HRRZ I,TTYTBL(U);NOW GET TTY NUMBER + CAIN I,%TINON ;TREE HAS NO TTY => RETURN "DEVICE NOT AVAILABLE". + JRST OPNL10 + JRST ATTYC1 + +;TTYSET SYSTEM CALL +;SETS TTYST1, TTYST2, TTYSTS, WHEN THE USER HAS THE TTY +;HANGS UNTIL HE GETS IT +ATTYST: JSP J,ATTYCM ;GET TTY NUMBER IN I; SKIP IF IT'S OUR CONSOLE. + JRST ATTYS6 + SKIPGE TTYTBL(U) + JRST ATTYS5 ;JUMP IF OUR CONSOLE AND WE DON'T OWN IT. +ATTYS6: CONO PI,TTYOFF + MOVEM B,TTYST1(I) + MOVEM C,TTYST2(I) + CAIGE W,4 + JRST ATTYS0 ;NO 4TH ARG => DON'T SET TTYSTS. + TLNE D,%TSINT ;SETTING "INT ON NEXT CHAR REGARDLESS"? + PUSHJ P,ATTYS3 ;MAYBE THE "NEXT CHAR" HAS ALREADY BEEN READ. + HRLOI B,%TSFRE+%TSCNS+%TSLCZ+%TSHDX ;DON'T CHANGE THESE. + TLZ D,%TSFRE+%TSCNS+%TSLCZ+%TSHDX + ANDCMI D,-1 + ANDM B,TTYSTS(I) + IORM D,TTYSTS(I) +ATTYS0: AOS (P) ;MAKE ALL CHRS IN BUFFER ACTIVATION CHARS +ATTYS1: SKIPG TICC(I) + JRST TTYONJ + LDB E,TIIP(I) ;MAKE LAST CHAR AN ACTIVATION CHAR + TRON E,%TXACT + AOS TACC(I) ;IF IT WASN'T ONE, IS ONE MORE ACT CHAR NOW + DPB E,TIIP(I) + JRST TTYONJ + +ATTYS3: SKIPE B,TINTP(I) +ATTYS4: CAMN B,TIIP(I) ;ANY MORE CHARS TO CHECK? + POPJ P, + CAMN B,TIBEP(I) + SUBI B,TIBL + ILDB E,B ;YES, CHECK THE NEXT ONE. + TRNE E,%TXIGN ;IF IT ISN'T REALLY THERE, IT SHOULDN'T + JRST ATTYS4 ;INTERRUPT. + TLZ D,%TSINT ;ELSE THIS CHAR IS THE "NEXT CHAR" THAT + TROE E,%TXINT ;SHOULD INTERRUPT REGARDLESS. + POPJ P, + AOS TINTC(I) ;SO MAKE IT AN INT. CHAR IF IT ISN'T. + DPB E,B + MOVE B,TYIMSK(I) + AND B,MSKST2(U) + MOVN C,B + AND B,C + IORM B,IFPIR(U) + MOVEI A,%PITYI + TDNE A,MSKST(U) + IORM A,PIRQC(U) + POPJ P, + +;TTYSET WHEN WE DON'T OWN OUR CONSOLE. +ATTYS5: MOVEM B,TTSTSV(U) + MOVEM C,TTSTSV+1(U) + CAIGE W,4 + JRST POPJ1 + HRLOI B,%TSFRE+%TSCNS+%TSLCZ+%TSHDX ;DON'T CHANGE THESE. + TLZ D,%TSFRE+%TSCNS+%TSLCZ+%TSHDX ;CHANGE ONLY CERTAIN LH BITS. + ANDCMI D,-1 + ANDM B,TTSTSV+2(U) + IORM D,TTSTSV+2(U) + JRST POPJ1 + +;TTYGET SYSTEM CALL +;GETS TTYST1, TTYST2 AND TTYSTS WHEN THE USER HAS THE TTY +;HANGS UNTIL HE GETS IT, IF IT'S HIS CONSOLE. +;ALSO RETURNS HIS TTYTYP, TCTYP. +;THE RH OF TTYSTS AS RETURNED IS PRE-DIVIDED BY LUBLK +ATTYGT: JSP J,ATTYC9 ;GET TTY NUMBER NOW IN I; SKIP IF IT'S OUR CONSOLE. + CAIA + SKIPL TTYTBL(U) + JRST ATTYG1 +;OUR CONSOLE AND WE DON'T CURRENTLY OWN IT. + MOVE A,TTSTSV(U) + MOVE B,TTSTSV+1(U) + MOVE C,TTSTSV+2(U) + JRST ATTYG2 + +;EITHER NOT OUR CONSOLE OR WE OWN IT. +ATTYG1: MOVE A,TTYST1(I) + MOVE B,TTYST2(I) + HLLZ C,TTYSTS(I) +ATTYG2: HRRZ D,TTYSTS(I) ;GET IDX OF TTY'S OWNER + CAIE D,-1 ;(BUT MAY BE NO OWNER IF WE SPECIFIED RANDOM TTY) + IDIVI D,LUBLK ;RETURN IN EASY-TO-DIGEST FORM. + HRR C,D + MOVE D,TTYOPT(I) + TLNE D,%TOHDX ;THE %TSHDX BIT REFLECTS THE %TOHDX BIT. + TLO C,%TSHDX + MOVE D,TTYTYP(I) + MOVE E,TCTYP(I) + JRST POPJ1 + +;SCML SYSTEM CALL. 1ST ARG TTY OR STY CHNL, +;2ND ARG IS DESIRED # COMMAND LINES(FOR ECHOING AT BOTTOM OF SCREEN) +;2ND ARG 0 => NO ECHO REGION. +ASCML: JSP J,ATTYCM + JRST ASCML3 + SKIPL TTYTBL(U) + JRST ASCML3 + DPB B,[$TBECL,,TTYTBL(U)] ;IT'S OUR CONSOLE AND WE DON'T OWN IT. + JRST POPJ1 + +ASCML3: PUSH P,[TTYOJ1] + CONO PI,TTYOFF + MOVEI H,(B) +;I HAS TTY #, H HAS # CMD LINES, TTY CHANNEL OFF (TURNED BACK ON). +ASCML1: MOVE TT,TCMXV(I) + CAMN TT,[MOVE] + JRST [ MOVE H,TT ;PRINTING TERMINALS (INFINITE SCREEN) ARE A SPECIAL CASE + JRST ASCML2 ] + CAML H,TT + SOS H,TT + SUB H,TCMXV(I) + MOVMS H ;VPOS OF START OF ECHO AREA. + CAIL H,117. + MOVEI H,117. ;IF TCMXV GARBAGE, AVOID GETTING GARBAGE INTO TPVP +ASCML2: MOVE TT,I + IMULI TT,TPLEN*2 + ADDI TT,TPLEN + CAMN TT,TTYLPP(I) ;MAKE SURE TTY ISN'T ASSOCIATED WITH PC OF PPR + PUSHJ P,TYOMVC ;WHILE THE LATTER'S SIZE IS CHANGING. + SUBI TT,TPLEN + MOVEM H,TPVB+TPLEN(TT) + MOVEM H,TPVP+TPLEN(TT) + HRLM H,TPSP+TPLEN(TT) + JRST NCNSSG + +;RCPOS SYSTEM CALL. (READ CURSOR POSITION) +;1 ARG - TTY OR STY CHNL. +;1ST VALUE ,, +;2ND VALUE
,,
+;1ST VALUE IRRELEVANT IF NO ECHO LINES. +ARCPOS: JSP J,ATTYCW + HRRZ B,H + CAILE B,4 + JRST NRCPO1 + SKIPL TTOALC(I) + PUSHJ P,UFLS +NRCPO1: MOVE TT,I + IMULI TT,TPLEN*2 + HRRZ B,TPVP+TPLEN(TT) + SUB B,TPVB+TPLEN(TT) + HRLZS B + HRR B,TPHP+TPLEN(TT) + HRLZ A,TPVP(TT) + HRR A,TPHP(TT) + JRST POPJ1 + +;SCPOS SYSTEM CALL GETS OR SETS THE SYSTEM'S IDEA OF WHERE THE TTY'S +;CURSOR IS REALLY LOCATED (AT THE M.P. SIDE OF THE OUTPUT BUFFER). +;TO BE USED AFTER OUTPUTTING IN SUPERIMAGE MODE, TO TELL THE SYSTEM +;WHAT THE CHARS ALREADY OUTPUT WILL DO TO THE TTY. MAY ALSO BE USED +;BY A STY PROGRAM LOOKING AT A SOFTWARE TTY, TO TELL THE SYSTEM HOW +;IT HAS INTERPRETED THE CURSOR-MOVING DISPLAY CODES, PROVIDED THE +;OUTPUT BUFFER IS EMPTY (AS IT WILL BE AFTER AN OUTPUT RESET). +;FOR THAT APPLICATION, A WAY TO SET TTOALC IS PROVIDED. +;3 VALUES - VPOS, HPOS AND TTOALC. +;1 ARG (TTY SPEC) => JUST READ THEM. +;2 MORE ARGS => THEY ARE NEW VPOS AND HPOS. +;A FOURTH ARG WILL SET TTOALC. +NSCPOS: JSP J,ATTYCW + HRRZ T,H + CAILE T,4 ;IF WE'RE HACKING A TTY CHANNEL + JRST NSCPO4 + SKIPL TTOALC(I) ;THEN MAYBE THE TTY WANTS TO HACK IT FIRST. + PUSHJ P,UFLS +NSCPO4: SOJE W,NSCPO2 + JUMPL B,OPNL33 + JUMPL C,OPNL33 + CAIG B,118. ;DON'T ALLOW GARBAGE TO GET INTO TPVP + CAIGE W,2 + JRST OPNL33 ;NOT 3 ARGS?? + CAMGE B,TCMXV(I) + ;CAML C,TCMXH(I) + CAIL C,400 ;PREVIOUS LINE MESSES UP ON !-CONTINUED LINES + JRST OPNL33 +NSCPO2: MOVSI TT,%TCLED ;CONTROL BIT SET => SET %TCLED, ALLOWING THIS JOB TO + SKIPE CTLBTS(U) ;READ TOP-E AND TOP-S CHARS. NORMALLY, ITS DISCARDS THEM. + IORM TT,TTYCOM(I) + CONO PI,TTYOFF + SKIPL TT,TTYLPP(I) + JRST NSCPO1 ;WHERE POS LIVES DEPENDS ON WHETHER TTY IS ASSOCIATED. + HRRZ T,C + HRL T,B ;FOR DISSOCIATED TTYS, TTYLPS HAS POS, MUST BE SET. + CAIE W, + MOVEM T,TTYLPS(I) + SETCA TT, ;MAKE SURE TT HAS THE PC PPR #, UNCOMPLEMENTED. +NSCPO1: MOVE A,TPVP(TT) ;FOR ASSOCIATED TTY, POS LIVES IN TPVP AND TPHP OF PC PPR. + CAIE W, + MOVEM B,TPVP(TT) + MOVE B,TPHP(TT) + CAIE W, + MOVEM C,TPHP(TT) +NSCPO3: MOVE C,TTOALC(I) ;NOW GET OLD TTOALC, AND SET IT IF THERE WERE 4 ARGS. + CAIGE W,3 + JRST TTYOJ1 + MOVEM D,TTOALC(I) + CONO PI,TTYON + AOSN TTYOAC(I) ;MAY BE RESTARTING FROM ZERO ALLOCATION + XCT TTYST(I) + JRST POPJ1 + +;CNSGET OR RSSIZE SYSTEM CALL. 1 ARG - TTY OR STY CHNL. +;RETURNS THE SAME VARS THAT CNSSET SETS, IN THE SAME ORDER. +NCNSGET: ;RETURN PERMANENT AND SEMIPERMANENT TTY INFO. +ARSSIZ: JSP J,ATTYCI + MOVE TT,TTYTYP(I) + MOVE E,TTYOPT(I) + MOVE D,TTYCOM(I) + MOVE C,TCTYP(I) + MOVE B,TCMXH(I) ;NOTE TCMXH IS LINEL INCLUDING THE CONTIN. COLUMN, + MOVE A,TCMXV(I) + MOVE I,TTYSMT(I) + SOJA B,POPJ1 + +;CNSSET SYSTEM CALL. +;1ST ARG TTY OR STY CHNL. NEXT ARGS SET +;VERT SIZE, HORIZ SIZE, TCTYP, TTYCOM, TTYOPT VARS RESPECTIVELY. +;TCTYP CAN'T BE SET TO A NONSENSE VALUE, SOME TTYCOM BITS CAN'T BE SET. +;IF 2ND, 3RD OR 4TH ARG IS NEGATIVE, ITS VALUE ISNT CHANGED +NCNSSET: + JSP J,ATTYC + MOVE H,TT +;.CALL TTYVAR ENTERS HERE WITH B/TCMXV, C/TCMXH-1, D/TCTYP, E/TTYCOM, H/TTYOPT +;AND I/TTY#, W/6 +NCNSS0: SKIPL D ;MAKE SURE D HAS NEW VALUE OF TCTYP, + CAIG W,3 ;WHETHER WE'RE CHANGING IT NOW OR NOT. + MOVE D,TCTYP(I) + CAIL D,%TNMAX ;DON'T LET TCTYP BE SET TO ILLEGAL VALUE. + JRST OPNL33 + CONO PI,TTYOFF + MOVE T,TTYTYP(I) ;DON'T LET %TPORS BE SET FOR PDP11 TV. + TRNE T,%TY11T + TRZA H,%TPORS+7*%TPPCR+%TPCBS + TRZA H,%TP11T ;%TP11T MUST REFLECT %TY11T. + IORI H,%TP11T + TRNE T,%TY11T + JRST [ MOVEI B,37. ;DON'T ALLOW A TV TO BE CALLED ANYTHING BUT. + MOVEI C,95. + MOVEI D,%TNTV + JRST NCNSS3] + CAIN D,%TNTV ;NOT A PDP11 LINE => DON'T LET IT BE TREATED AS ONE. + MOVEI D,%TNDP +NCNSS3: CAIGE W,6 + MOVE H,TTYOPT(I) + SKIPE D + TLZ H,%TORAW ;"RAW" MODE EXISTS ONLY ON PRINTING TTYS. + SKIPGE TYMDTB(D) + TLZ H,%TOMVU+%TOERS ;DON'T CLAIM TO DO SOMETHING WE DON'T KNOW HOW TO DO + MOVEI T,1 + TLNN H,%TOMVU + MOVEM T,TTYROL(I) ;ON PRINTING TTYS TTYROL MUST BE 1 + TRNN H,%TPCBS ;IF ^\ ISN'T TO BE HANDLED SPECIALLY, MAKE SURE ALL OF + SETOM TTOALC(I) ;THE FEATURES IT PROVIDES ARE IN THEIR NORMAL STATES. + MOVEI TT,TYBN + TRNN H,%TPCBS+%TPTEL + MOVEM TT,TYBPC(I) + MOVE TT,I + IMULI TT,TPLEN*2 ;TT HAS IDX OF MAIN PC PPR OF TTY. + XORI W,-1 ;EACH OF THE INSNS AFTER THE JRST SETS ONE PARAMETER. + CAIL W,#6 ;>6 ARGS SAME AS 6 ARGS. + JRST NCNSS1+2(W) ;ELSE DON'T SET VARS WE DIDN'T GET ARGS FOR. + MOVEM H,TTYOPT(I) + PUSHJ P,NCNSSC ;SET TTYCOM + MOVEM D,TCTYP(I) ;SET TCTYP. + PUSHJ P,[CAIL C,3 ;DON'T ALLOW SCREEN WIDTH LESS THAN 3. + CAIL C,377777 ;DON'T ALLOW AN HPOS THAT WON'T FIT IN HALFWORD. + POPJ P, ;SPEC NO GOOD, IGNORE + JRST NCNSSH ] ;SET TCMXH. + PUSHJ P,[CAMN B,[200000,,] ;200000,, IS SPECIAL (PRINTING TTY). + JRST NCNSSV + CAIL B,3 ;DON'T ALLOW SCREEN HEIGHT LESS THAN 3. + CAIL B,120. ;VPOS MUST FIT IN ASCII CHARACTER, USUALLY. + POPJ P, ;NO GOOD, IGNORE + JRST NCNSSV ] ;SET TCMXV +NCNSS1: PUSHJ P,NCNSSG ;COMPUTE TTYEPP FROM NEW SETTINGS OF TTY VARS. + JRST TTYOJ1 + +;SET TTY WIDTH (NOT INCLUDING THE SPACE FOR THE "!") TO ARG IN C. +;TTY # IN I, MAIN PC PPR IDX IN TT. +NCNSSH: ADDI C,1 + MOVEM C,TCMXH(I) + CAMG C,TTYIHP(I) ;DON'T ALLOW TTYIHP TO HAVE ILLEGAL VALUE. + SETZM TTYIHP(I) +.SEE TPHE ; MOVEM C,TPHE(TT) +.SEE TPHE ; MOVEM C,TPHE+TPLEN(TT) + CAMG C,TPHP(TT) + MOVEM C,TPHP(TT) + CAMG C,TPHP+TPLEN(TT) + MOVEM C,TPHP+TPLEN(TT) + POPJ P, + +;SET TTY SCREEN HEIGHT FROM VALUE IN B. +NCNSSV: MOVEM B,TCMXV(I) + CAMG B,TTYIVP(I) ;DON'T ALLOW TTYIVP TO GET ILLEGAL VALUE. + SETZM TTYIVP(I) +.SEE TPVE ; MOVEM B,TPVE(TT) +.SEE TPVE ; MOVEM B,TPVE+TPLEN(TT) + HRLM B,TPSP+TPLEN(TT) ;CLOBBER THE 2ND PC PPR TO NULL STATE. + MOVEM B,TPVP+TPLEN(TT) + MOVEM B,TPVB+TPLEN(TT) + CAMG B,TPVP(TT) + SETZM TPVP(TT) + HRRZS TPSP(TT) + POPJ P, + +;MAKE A TTY INTO AN ORDINARY PRINTING TTY. +;TTY # IN I; CLOBBERS TT,B,C. +NCNSSP: SETZM TCTYP(I) + MOVE TT,[%TOMVB+%TOOVR+%TOLWR,,%TPORS] + MOVE B,TTYTYP(I) + TRNN B,%TYSTY + IORI TT,%TPPCR + LDB B,[$TTOSP,,B] + CAIN B,2 + TLC TT,%TOALT+%TOMVB+%TOLWR ;10CPS => ASSUME TELETYPE. +IFN 0,[ ;THIS WOULD TURN THE MOTOR OF A CRTSTY DISPLAY ON AND OFF. + CAIN B,5 ;120CPS => ASSUME TERMINET. + JRST [ TRC TT,%TPPCR+5*%TPPLF + MOVEI C,%TNTRM + MOVEM C,TCTYP(I) + JRST .+1 ] +];IFN 0 + MOVEM TT,TTYOPT(I) + SETZM TTYSMT(I) ;NO GRAPHICS, NO LOCAL EDITING. + SETOM TTOALC(I) ;%TPCBS TURNED OFF + MOVEI TT,1 ;SCROLLS A LINE AT A TIME (THIS IS + MOVEM TT,TTYROL(I) ; MAINLY FOR THE BENEFIT OF TYIFLS) + HRRZ TT,I + IMULI TT,TPLEN*2 + MOVEM TT,TTYEPP(I) + MOVEI C,71. + CAIE B,2 ;10 CPS => TELETYPE + MOVEI C,79. ;ANYTHING ELSE IS AT LEAST 80 WIDE +IFN 0,[ + CAIN B,5 + MOVEI C,119. +] + MOVSI B,(MOVE) + PUSHJ P,NCNSSH + JRST NCNSSV + +;SET TTYEPP OF TTY # IN I, MAIN PC PPR # IN TT. CLOBBER H,TT. +;HAD BETTER ALWAYS BE CONO PI,CLKOFF HERE, OR SYSTEM MAY CRASH IN ECHOING CODE. +NCNSSG: MOVE H,TTYOPT(I) + TLNE H,%TOMVU ;NOT DISPLAY OR + TLNN H,%TOERS ;ARDS-LIKE (CAN'T ERASE) + JRST NCNSSF ; => CAN'T HAVE ECHO AREA. + MOVE H,TPLEN+TPVB(TT) + CAMGE H,TCMXV(I) ;NO ECHO LINES => CAN'T USE ECHO AREA. + ADDI TT,TPLEN ;ELSE USE IT. +NCNSSF: MOVEM TT,TTYEPP(I) + POPJ P, + +IFN N11TYS,[ +;RE-INIT THE PARAMETERS OF A T.V. WHEN IT BECOMES FREE. +NCNSST: HRRZ TT,I + IMULI TT,TPLEN*2 + MOVEI B,%TNTV + MOVEM B,TCTYP(I) + MOVE B,[%TOMVB+%TOMVU+%TOERS+%TOSAI+%TOLWR+%TOOVR+%TOFCI+%TOLID+%TOCID,,%TP11T+%TPRSC] + MOVEM B,TTYOPT(I) + MOVEI B,4 ;TV'S SCROLL BY 4 LINES PER GLITCH + MOVEM B,TTYROL(I) + MOVEI B,37. + MOVEI C,95. + PUSHJ P,NCNSSH + JRST NCNSSV +];N11TYS + +NCNSSC: XOR E,TTYCOM(I) ;DON'T CHANGE TTYCOM BITS EXCEPT THESE. + AND E,[%TCQRY+%TCRFS+%TCICO+%TCOCO,,] + XORM E,TTYCOM(I) + POPJ P, + +TYVSRO: JUMPL A,OPNL33 ;CAN'T BE NEGATIVE + ;CAME D,%TNTV ;CAN'T SET NON-ZERO ON TVS + CAML A,TCMXV(I);CAN'T BE BIGGER THAN SCREEN SIZE + JUMPN A,OPNL33 + TLNN H,%TOMVU ;ON PRINTING TTYS, TTYROL MUST BE 1 OR GET INTO + CAIN A,1 ; INFINITE RECURSION AT TYOLF3/TYOCLR/TYOCRL + CAIA + JRST OPNL33 + MOVEM A,TTYROL(I) + JRST TTYOJ1 + +;TTYVAR SYSTEM CALL - READ AND WRITE VARIOUS TTY VARIABLES + +;TABLES OF TTY VARIABLES. +;THE NEXT 3 TABLES ARE PARALLEL, IF YOU CHANGE ONE CHANGE THEM ALL. + +;TTY VARIABLE NAMES. MUST BE SORTED IN SIXBIT ORDER. + +TYVTAB: SIXBIT/HEIGHT/ + SIXBIT/IDLTIM/ + SIXBIT/ISPEED/ ;IN BITS PER SECOND + SIXBIT/OSPEED/ ;IN BITS PER SECOND + SIXBIT/SMARTS/ + SIXBIT/TCTYP/ + SIXBIT/TTYCOM/ + SIXBIT/TTYOPT/ + SIXBIT/TTYROL/ + SIXBIT/TTYSMT/ + SIXBIT/TTYTYP/ + SIXBIT/WIDTH/ +LTYVTA==:.-TYVTAB +TYVTL2==.RADIX 2,CONC [.LENGTH/]\.-TYVTAB-1,/ ;BASE 2 LOG-1 OF TABLE SIZE +REPEAT 1_-<.-TYVTAB-1>-1, -1 ;PAD OUT TO POWER OF 2 SIZE + +;INSTRUCTIONS TO GET VARIABLE INTO A + +TYVGET: MOVE A,TCMXV(I) + PUSHJ P,[MOVE A,TIME ? SUB A,TTITM(I) ? POPJ P,] + PUSHJ P,[LDB A,[$TTISP,,TTYTYP(I)] ? MOVE A,BAUDRT(A) ? POPJ P,] + PUSHJ P,[LDB A,[$TTOSP,,TTYTYP(I)] ? MOVE A,BAUDRT(A) ? POPJ P,] + MOVE A,TTYSMT(I) + MOVE A,TCTYP(I) + MOVE A,TTYCOM(I) + MOVE A,TTYOPT(I) + MOVE A,TTYROL(I) + MOVE A,TTYSMT(I) + MOVE A,TTYTYP(I) + PUSHJ P,[MOVE A,TCMXH(I) ? SOJA A,CPOPJ] + +;INSTRUCTIONS TO SET VARIABLE FROM A. OPNL33 IF VALUE BAD. OPNL26 IF CAN'T WRITE. +;OTHERWISE, IF GOES VIA .CALL CNSSET, MOVE A INTO APPROPRIATE AC (SEE COMMENT AT NCNSS0). +;FOR OTHER VARIABLES, JRST TO ROUTINE TO STORE A INTO VARIABLE. + +TYVSET: MOVE B,A ;HEIGHT + JRST [SUB A,TIME ? MOVNM A,TTITM(I) ? JRST TTYOJ1] ;IDLTIM + JRST TYSISP ;ISPEED + JRST TYSOSP ;OSPEED + JRST TYVSSM ;SMARTS + MOVE D,A ;TCTYP + MOVE E,A ;TTYCOM + MOVE H,A ;TTYOPT + JRST TYVSRO ;TTYROL + JRST TYVSSM ;TTYSMT + JRST OPNL26 ;TTYTYP + MOVE C,A ;WIDTH + +TYVSSM: MOVEM A,TTYSMT(I) + JRST TTYOJ1 + +;SET SPEED. MAYBE THIS SHOULD CHANGE IT IN HARDWARE ALSO? +TYSISP: SKIPA B,[$TTISP,,TTYTYP(I)] +TYSOSP: MOVE B,[$TTOSP,,TTYTYP(I)] + MOVEI C,17 ;FIND CODE + CAME A,BAUDRT(C) + SOJGE C,.-1 + JUMPL C,OPNL33 ;NON-EXISTENT + DPB C,B + JRST TTYOJ1 + +;TRANSLATION FROM INTERNAL SPEED CODES TO BAUDS +BAUDRT: 0 ? 600. ? 110. ? 150. + 300. ? 1200. ? 1800. ? 2400. + 4800. ? 9600. ? 25000. ? 40000. + 50000. ? 80000. ? -1 ? -2 + +;CODE FOR TTYVAR SYS CALL BEGINS HERE + +NTTYVA: HRRE E,A + JSP J,ATTYC9 ;I TTY NUMBER + SKIPA J,[1] + SETO J, ;J GETS -1 IF IT'S OUR CONSOLE, 1 IF OTHER TTY CHNL. + AOSGE E ;SKIP IF ARG WAS -1 (OWN CNSL) OR CHANNEL NUMBER + MOVEI J,0 ;J ZERO IF TTY SPECIFIED BY NUMBER. + PUSHJ P,VARCAL ;RETURN WITH SUITABLE STUFF IN E,D,W + JUMPE W,NTTYV1 + JUMPE J,OPNL26 ;ERR OUT IF WRITE LOCKED (SOMEONE ELSE'S TTY) + JUMPG J,NTTYV1 ;IF IT'S OUR CONSOLE, WAIT TILL WE OWN IT, OR INTERRUPT. + PUSHJ P,TTYWC2 +NTTYV1: TLNN E,-1 ;DEFAULT LH OF SIXBIT VARIABLE NAME TO 'TTY' + HRLI E,'TTY ;SO CALLER CAN USE IMMEDIATE ARGUMENT -- PRETTY RANDOM + MOVEI B,0 ;LOOK UP IN TABLE OF TTY VARIABLES (TYVTAB) + REPEAT TYVTL2,[CAML E,TYVTAB+1_(B) + ADDI B,1_ + ] + CAME E,[-1] + CAME E,TYVTAB(B) + JRST OPNL11 ;IILEGAL TTY VARIABLE NAME + CONO PI,TTYOFF + XCT TYVGET(B) ;GET VALUE OF VARIABLE INTO A + JUMPE W,TTYOJ1 ;RETURN IF READING + HRRI W,A + XCT W ;PUT NEW VALUE INTO A + MOVE W,TYVSET(B) ;GET INSTRUCTION TO PUT A IN PROPER PLACE + MOVE B,TCMXV(I) ;SET UP OLD VARIABLES FOR NCNSS0 + MOVE C,TCMXH(I) + SUBI C,1 + MOVE D,TCTYP(I) + MOVE E,TTYCOM(I) + MOVE H,TTYOPT(I) + XCT W ;CHANGE THE AC CONTAINING THE VARIABLE TO BE CHANGED + MOVEI W,6 ;TELL CNSSET TO CHANGE EVERYTHING + JRST NCNSS0 ;MAKE THE CHANGES, THEN TTYOJ1. + +;.CALL TTYFLS +; ARG 1 - +;WITH CONTROL BITS 0, MARKS LAST INTERRUPT CHARACTER ITYIC'ED +; TO BE IGNORED AT MAIN PROGRAM LEVEL. +;WITH CONTROL BIT 1, DISCARDS ALL INPUT THROUGH LAST CHARACTER ITYIC'ED. +NTTYFLS:JSP J,TTYNGT + MOVE A,CTLBTS(U) + TRNN A,1 + JRST NTTYF2 + CONO PI,TTYOFF +NTTYF1: MOVE C,TIOP(I) + CAMN C,TINTP(I) + JRST TTYOJ1 + PUSHJ P,TYIREM + JRST NTTYF1 + +NTTYF2: LDB A,TINTP(I) + TRO A,%TXIGN + DPB A,TINTP(I) + JRST POPJ1 + +NTTYESC: ;SIMULATES TYPING OF ^_ + JSP J,ATTYC2 ;DECODE TTY SPEC. IF OUR CONSOLE, WAIT TILL WE CAN INPUT. + CONO PI,TTYOFF + HRRZ A,TTYIPC(I) + CAIE A,TTYI + JRST OPNL7 ;DEVICE NOT READY + MOVEI A,TYCI + MOVEM A,TTYIPC(I) + JRST TTYOJ1 + +;WHOLINE SYSTEM CALL. +;TAKES A MANDATORY 1ST ARGUMENT SPECIFYING A TTY. +;RETURNS TWO VALUES - THE OLD SETTINGS OF WHMODE AND WHJOB +;FOR THAT TTY. +;OPTIONAL 2ND AND 3RD ARGUMENTS SET WHMODE AND WHJOB. IF THEY +;ARE PRESENT, THE RETURNED VALUES ARE THE OLD SETTINGS. +;THE CALL FAILS FOR TTY'S OTHER THAN TV'S. + +NWHOLI: JSP J,ATTYC ;DECODE THE TTY SPEC. + MOVE H,TTYOPT(I) +IFN N11TYS,TRNN H,%TP11T ;FAIL IF NOT PDP11 TV. + JRST OPNL34 +IFN N11TYS,[ + SKIPL TT11P ;TV PDP11 DOWN => DON'T USE IT. + JRST OPNL10 + CAIGE W,2 ;IF THERE ARE OPTIONAL ARGS, DECODE THEM. + JRST NWHOL2 + CAIE B,1 ;DECODE 3RD ARG ONLY IF RELEVANT. + JRST NWHOL2 + MOVE J,C ;IT SHOULD BE A JOB SPEC. + CAIGE W,3 + SETO J, ;USE -1 (SELF) AS THE DEFAULT. + JSP T,NCRUI2 + JFCL + JUMPL J,OPNL34 ;PDP6 IS NO GOOD. + MOVE C,J + IDIVI C,LUBLK ;CONVERT USER IDX TO JOB #. +NWHOL2: ADD I,TT11HD + ADD I,TT1111 + ADD I,TT1111 + LDB TT,[$11AD0,,1-NF11TY(I)] + ADDI TT,TT11LO ;TT HAS PDP10 ADDR OF TTY'S WHOLINE VARS. + CONO PI,TTYOFF + MOVE T,WHMODE(TT) ;FIRST, GET THE CURRENT SETTINGS. + LDB Q,[$11WD0,,WHJOB(TT)] + CAIGE W,2 + JRST NWHOL3 + DPB B,[$11WD0,,WHMODE(TT)] ;THEN, SET TO NEW VALUES IF REQUIRED. + DPB C,[$11WD0,,WHJOB(TT)] +NWHOL3: CONO PI,TTYON + MOVE A,T ;PUT RETURN VALUES IN APPRO. ACS + ASH A,-24 + MOVE B,Q + JRST POPJ1 +] + +;TVWHER SYSTEM CALL. +;TAKES 1 ARG SPECIFYING A TTY, WHICH MUST BE A TV TTY. +;RETURNS 2 VALUES. +;1ST VALUE: THE KEYBOARD NUMBER OF THE PHYSICAL TERMINAL IN USE. +;2ND VALUE: THE NUMBER OF THE DISPLAY BUFFER IN USE ON THIS TTY. + +NTVWHE: JSP J,ATTYCI + MOVE H,TTYOPT(I) +IFN N11TYS, TRNN H,%TP11T + JRST OPNL34 +IFN N11TYS,[ +NTVWH1: LDB A,[$11AD0,,TT11HA] + ADDI A,TT11LO(I) + LDB B,[$11BY3,,1-NF11TY(A)] + LDB A,[$11BY2,,1-NF11TY(A)] + JRST POPJ1 +] + +SUBTTL .ITYIC, .LISTEN, TTY WHYINT + +;.CALL ITYIC. 1 ARG, A TTY INPUT CHANNEL; 1 VALUE, THE INTERRUPT CHAR. +;FAILS IF THERE ARE NO INTERRUPT CHARACTERS. +NITYIC: JSP J,TTYNGT +AITYI1: SKIPG D,TINTC(I) + POPJ P, + MOVE A,TINTP(I) ;SAVE SOME INFO FOR DEBUGGING + MOVE J,TICC(I) + MOVE C,TIIP(I) ;GET THE END OF FILLED PART OF BUFFER +AITYI2: CAMN C,TINTP(I) ;IF OUR MOVING POINTER PASSES THERE, THERE ARE REALLY + BUG ;NO INT CHARS IN THE BUFFER. BUT TINTC NON-ZERO?? + MOVE B,TINTP(I) + CAMN B,TIBEP(I) ;WRAP AROUND AT END OF BUFFER + SUBI B,TIBL + HRRM B,TINTP(I) ;ADVANCE TINTP TO NEXT CHARACTER. + ILDB B,TINTP(I) + TRZN B,%TXINT ;KEEP LOOKING TILL FIND NEXT INT. CHAR. + JRST AITYI2 + DPB B,TINTP(I) + SOS TINTC(I) + HLRZ R,H ;GET IOCHNM BITS IN R. UNLESS %TIFUL IS SET, + MOVE A,B + AOS (P) + JRST TYINRM ;NORMALIZE PDP-11 12-BIT CHARACTERS TO 7-BIT. + +;.CALL WHYINT ON TTY INPUT CHANNEL IS SIMILAR TO ITYIC +TYIWHY: JSP J,TTYNG1 + PUSHJ P,AITYI1 + SOS (P) ;DON'T SKIP-RETURN IF NO INTERRUPT CHARS + MOVE B,A ;SECOND RESULT IS INTERRUPT CHARACTER + MOVEI A,%WYTYI ;FIRST RESULT IS DEVICE CODE + JRST POPJ1 + +AITYI: SETO A, ;.ITYI OBSOLETE. + TDZA H,H +AITYIC: UMOVE A,(J) ;.ITYIC + PUSH P,J ;TURN INTO NEW SYSTEM CALL ITYIC + MOVE B,[SIXBIT /ITYIC/] + MOVEM B,LSCALL(U) ;FOR JOB DEVICES' SAKE. + MOVEI W,1 + PUSHJ P,NITYIC + JRST POP1J + UMOVEM A,@(P) + JRST POP1J1 + +ALISTEN:SKIPGE I,TTYTBL(U) ;.LISTEN + JRST ALIS1 + PUSHJ P,TYOWC + SKIPA B,TICC(I) +ALIS1: SETZ B, + MOVE A,PIRQC(U) + TRNE A,%PIC.Z + JRST UDELAY + UMOVEM B,(J) + POPJ P, + +TTYFIN: JSP J,TTYNG1 ;HERE FOR .CALL FINISH ON TTY OUTPUT CHANNEL + PUSHJ P,TYOWC + JRST POPJ1 + +NLISTE: JSP J,TTYNGT ;HERE FOR .CALL LISTEN + PUSHJ P,TYOWC + MOVE A,TICC(I) + JRST POPJ1 + +TTYNGT: TRC A,-1 ;RH(A)=-1 => TREE'S CONSOLE + TRCN A,-1 + JRST TTYNG2 + MOVEI T,AIOCAL ;OTHERWISE MUST BE CHANNEL NUMBER + HRLI J,.+2 + JRST CHNDCD + TLNN R,%CLSTI ;CHNDCD RETURNS CLSTB BITS IN R, IOCHNM WD CONTENTS IN H + JRST OPNL34 +TTYNG1: HLRZ I,H + TRZ I,377700 + TRZE I,400000 ;SKIP IF DEVICE (RATHER THAN CONSOLE) +TTYNG2: SKIPL I,TTYTBL(U) + JRST (J) + JRST OPNL10 + +TYOWHY: MOVEI A,%WYTYO ;.CALL WHYINT ON TTY OUTPUT CHANNEL + MOVSI B,(SETZ) ;FOR NOW, JUST ASSUME REASON IS **MORE** + JRST POPJ1 + +SUBTTL TTY OPEN + +;LH TTY OPEN +;3.1 0 -> IN 1 -> OUT +;3.2 0 -> UNIT 1 -> BLOCK + +;OUTPUT +;3.3 => IMAGE MODE (SET ALL %TGIMG BITS IN TTYST1 AND TTYST2) +;3.4 0 -> NORMAL 1 -> ECHO MODE OUTPUT (SET %TJECH, %TJPP2, %TJMOR). +;3.5 0 -> NORMAL 1 -> DISPLAYMODE, LOOK FOR ^P (SET %TJDIS). +;3.6 0 -> NORMAL 1 -> SUPER-IMAGE OUTPUT (SET %TJSIO). + +;INPUT +;3.3 => IMAGE MODE (CLEAR ALL ECHO BITS IN TTYST1, TTYST2). +;3.4 => "DDT" (DON'T ECHO CR, LF, TAB) +;3.5 => CONVERT LOWER TO UPPER CASE +;3.6 => WANT 3 LINES IN ECHO AREA. + +;BITS 3.4 AND 3.6 ON INPUT, AND BIT 3.3, HAVE EFFECT +;ONLY ON THE FIRST OPEN IN EITHER DIRECTION. +;(THEY ARE OBSOLETED BY THE TTYSET SYSTEM CALL) + +;LH OF IOCHNM WD +;(SHOWS UP IN RH OF A ON .IOT, .CLOSE, ETC) + +%TICNS==400000 ;4.9 1-> CONSOLE 0 -> DEVICE. THIS BIT EXIST IN INPUT AND OUTPUT CHNLS. +%TJCNS==400000 ;4.9 1-> CONSOLE 0 -> DEVICE + +;OUTPUT: +%TJCP1==200000 ;^P-CODE ANTICIPATION STATE. +%TJCP2==100000 ; ". 0=>NORMAL, 1=> CHAR AFTER ^P, 2=> ^PH, 3=>^PV. +%TJECH==40000 ;SET => ECHO MODE OUTPUT.-MODE OUTPUT (ALL CHARS OUTPUT THE + ;WAY THEY WOULD BE ECHOED) +%TJCTN==20000 ;SET => DON'T DO LINE-CONTINUATION. +%TJSTP==10000 ;SET => THIS CHANNEL IS HUNG IN **MORE**. +%TJDIS==4000 ;SET => LOOK FOR ^P CODES. +%TJSIO==2000 ;SET => SUPERIMAGE OUTPUT, NO PADDING OR CURSOR CTL. +%TJMOR==1000 ;SET => DON'T DO **MORE** PROCESSING. +%TJPP2==400 ;SET => USE ALTERNATE PC PPR (THE ECHO AREA) +%TJINK==200 ;SET => NEXT CHAR ASSUMED TO BE 1-POSITION PRINTING. +%TJHDE==100 ;SET => ACCOUTING FOR CURSOR MOTION DUE TO + ;CHAR ECHOED ON A HALF-DUPLEX TTY. + +;INPUT +;3.3 => NO ECHO. +%TIECH==40000 ;CAN READ EVEN IF CHAR NEEDS PI ECHOING. +%TIPEK==20000 ;DON'T REMOVE CHAR FROM BUFFER. +%TIACT==4000 ;SET => DON'T WAIT FOR ACTIVATION CHARACTER. +%TIINT==2000 ;SET => CAN READ A CHAR EVEN IF IT IS SUPPOSED TO INTERRUPT & HASN'T YET. +%TINWT==1000 ;SET => IF NO INPUT AVAILABLE, DON'T WAIT, JUST RETURN -1. +%TIFUL==400 ;SET => GIVE FULL CHARACTER (SIGNIFICANT ON IMLAX, TVS) + +$TIIDX==220600 ;3.6-3.1 CONSOLE #, OR 77 FOR A "DISOWNED" CONSOLE TTY CHNL +;IE, ONE THAT CORRESPONDS TO NO REAL TTY. THEY EXIST ONLY IN +;TREES WITH NO TTY, IN JOBS THAT CAM FROM TREES WITH TTYS. +%TINON==77 ;"TTY #" FOR A CHANNEL WITH NO REAL TTY. + +;ENTRY FOR OPEN OF TTY AS DEVICE TYN OR TNM + + +IFN TTLPTP,[ +LPTO: MOVE J,TIME + SUB J,LPTTIME ;"LPT" INPUTS EVERY ONCE IN A WHILE IF IT IS UP + CAIL J,60. ;2 SECONDS + JRST OPNL7 + SKIPA I,LPTTTY +] +TTYO: PUSHJ P,TTYFD ;TEST FOR FILE NAME OF .FILE. (DIR) + CAIL I,NCT + JRST OPNL1 ;TTY NUM TOO LARGE +TTYO3C: +IFN NNVTTS,[ + .ERR Shouldn't this be using NFNVTY instead? + CAIGE I,NOTYS+NNTYS+NNVTTS + CAIGE I,NOTYS+NNTYS ;SKIP ON NOVA TTY + JRST TTYO3A + SKIPGE NOVATT + JRST OPNL10 ;NOVA LINK NOT ACTIVE +TTYO3A: CAMN I,NOVATT + JRST OPNL10 ;CANT OPEN TTY USED AS CNHL TO NOVA +] + MOVEI A,0 ;MARK AS A DEVICE + CONO PI,TTYOFF ;INTERLOCK WITH OTHER TTY OPENS, AND ^Z'S. + SKIPGE TT,TTYSTS(I) ;SKIP IF TTY OPEN + JRST TTYO3B ;OK IF TTY NOT OPEN + CAIE U,(TT) ;SAME USER THAT HAS IT? + JRST OPNL10 ;TTY ALREADY OPEN AS DEVICE BY SOMEONE ELSE. + TLNN TT,%TSCNS ;OPEN AS CONSOLE? + JRST TTYO8 ;NO, AS DEVICE + CONO PI,TTYON + JRST TTYO7 ;OPEN, THIS TIME AS CONSOLE. + +TTYO3B: SKIPGE TTYSTA(I) ;TTY IS FREE: IS IT IN TRANSITION TO OR FROM BEING IN USE? + JRST TTYO8 ;OK IF NOT; + MOVE T,I ;STYOCF TAKES TTY # IN T. + PUSHJ P,STYOCF ;AND WAIT TILL TTY IS NO LONGER IN TRANSITION + PUSHJ P,UFLS + JRST TTYO3C ;THEN TRY AGAIN TO OPEN IT. + +;TTY IS AVAIL. TO OPEN AS A DEVICE. +TTYO8: SKIPN TTNTO(I) ;IF TTY USED TO BE FREE, INIT. IT. + PUSHJ P,TTYINI + MOVSI TT,%TSFRE + ANDCAM TT,TTYSTS(I) + JRST TTYO3 + +TTYFD: PUSHJ P,FLDRCK ;SKIP IF FILE DIR BEING OPENED + JRST TTYFD1 ;FILE NAMES NOT SPECIAL + SUB P,[1,,1] + MOVEI J,6 + JRST LISTF7 ;GO GET DIRCTORY + +TTYFD1: JUMPE W,CPOPJ ;0 IS THE ONLY DEFINED MODE FOR ANY TTY OPEN + SUB P,[1,,1] + JRST OPNL12 + +FLDRCK: CAMN A,[SIXBIT /.FILE./] + CAME B,[SIXBIT /(DIR)/] + POPJ P, + JRST POPJ1 + +;INIT A TTY WHEN IT CEASES TO BE FREE. (ZFLAG7 FOR TTY, TTYO8 FOR TNM) +;CHNL 3 (TTYCHN) MUST BE OFF OR IN PROGRESS. +TTYINI: SETZM TTYST1(I) + SETZM TTYST2(I) + MOVSI J,%TACFM ;TTY NEEDS A CONSOLE FREE MESSAGE. + ANDCAM J,TTYSTA(I) + MOVE J,TTYTYP(I) + TRNN J,%TYSTY ;EXCEPT ON STY TTYS, + PUSHJ P,TTYIN1 ;INIT THE USER OPTIONS IN TTYOPT, TTYCOM. + MOVE J,TTYOPT(I) + HRLOI H,%TSFRE ;INITIALIZE TTYSTS FROM TTYOPT + TLNE J,%TOROL + TLO H,%TSROL + TLNN J,%TOMOR ;NOTE %TOMOR SAYS DO **MORE** PROC, + TLO H,%TSMOR ;%TSMOR SAYS INHIBIT **MORE** PROC. + TLNE J,%TOSA1 + TLO H,%TSSAI + MOVEM H,TTYSTS(I) + HRRZ TT,I + IMULI TT,TPLEN*2 + SETZM TPFLAG(TT) + SETZM TPFLAG+TPLEN(TT) + SETZ H, ;START OUT WITH NO ECHO LINES. + JRST ASCML1 + +;INIT A FEW BITS IN TTYOPT, TTYCOM THAT ARE CONSIDERED USER OPTIONS. +;NORMALLY DONE WHENEVER A TTY BECOMES IN USE, BUT ON STY TTY'S +;DONE ONLY WHEN THE STY IS INITIALIZED (SO STY-USER CAN SET THESE OPTIONS). +TTYIN1: MOVE J,TTYCOM(I) + TLZ J,%TCRFS+%TCQRY+%TCOCO+%TCICO + MOVEM J,TTYCOM(I) + MOVE J,TTYOPT(I) ;INIT SOME TTYOPT BITS. + TLZ J,%TOUSR + TRZ J,%TPUSR + TLO J,%TOMOR ;DO **MORE** + HLLM J,TTYOPT(I) + POPJ P, + +;TELETYPE OPEN ROUTINES + +;ENTRY FOR OPEN OF "TTY" AS A CONSOLE + +TTYO1: PUSHJ P,TTYFD ;TEST FOR FILE NAME OF .FILE. (DIR) +TTYO7: MOVE I,TTYTBL(U) + JUMPGE I,TTYO2 ;JUMP IF HAS TTY NOW + TLNE I,%TBWAT + JRST TTYO2A + TLNN I,%TBNVR ;IF I SHOULD FAIL IF TRY TO OPEN TTY WHEN DON'T HAVE IT, + TLNN I,%TBDTY ;OR IF I HAVE DONE A .ATTY, + JRST OPNL10 ;THE OPEN SHOULD FAIL. +TTYO2A: PCLT + SKIPGE TTYTBL(U) + PUSHJ P,UFLS ;HANG UNTIL HAS TTY + MOVE I,TTYTBL(U) +TTYO2: HRRZS I ;TTY NUMBER + CAIL I,NCT + JRST 4,OPNL1 ;TTY NUM TOO LARGE + MOVSI A,%TICNS ;SAY TTY CHNL WILL BE OPEN AS CONSOLE. + CONO PI,TTYOFF +TTYO3: HRLZI J,(D) ;SET IOCHNM BITS (IN A) FROM OPEN MODE. + LSH J,1 + TLZ J,700077 ;BUT DON'T USE PARTS OF OPEN WD USED FOR OTHER THINGS. + IOR A,J +IFN TTLPTP,[ + CAMN I,LPTTTY ;SKIP IF OT TTY + HRRZM U,LPTUSR +] + DPB I,[$TIIDX,,A] ;LH OF A WILL BE STORED IN LH OF IOCHNM WORD + HRRZ TT,UUAC(U) ;TT HAS CHNL # BEING OPENED. + JUMPGE D,TTYO4 ;J IF INPUT OPEN. + TRNE D,20 + TLO A,%TJSIO ;SUPER IMAGE OUT. + TRNE D,4 + TLO A,%TJECH+%TJPP2+%TJMOR ;ECHO OUTPUT + TRNE D,10 + TLO A,%TJDIS ;DISPLAY OUTPUT MODE. + MOVE J,TYOMSK(I) + IOR J,CHNBIT(TT) ;UPDATE CHANNELS-OPEN MASK + EXCH J,TYOMSK(I) ;FOR THE NEW OUTPUT CHANNEL. + JUMPN J,TTYO5 ;FOR 1ST OUTPUT OPEN, INIT TTYST1,2. + MOVE J,[101010,,101010] + IORM J,TTYST1(I) + IORM J,TTYST2(I) ;SET ALL THE OUTPUT-IN-IMAGE-MODE BITS. + TRNN D,2 + ANDCAM J,TTYST1(I) ;IF NOT IMAGE, CLEAR THEM. + TRNN D,2 + ANDCAM J,TTYST2(I) + JRST TTYO5 + +TTYO4: MOVE J,TYIMSK(I) + IOR J,CHNBIT(TT) ;UPDATE INPUT-CHNLS-OPEN MASK + EXCH J,TYIMSK(I) ;FOR NEWLY OPENED INPUT CHANNEL. + JUMPN J,TTYO5 ;THE 1ST INPUT CHNL OPEN, INIT ECHO BITS... + MOVEI H,0 ;INPUT + TRNE D,20 + MOVEI H,3 ;# COMMAND LINES + PUSHJ P,ASCML1 + MOVE J,TTYST1(I) + AND J,[101010,,101010] ;SAVE IMAGE MODE OUTPUT BITS + TRNN D,2 ;SKIP ON IMAGE MODE INPUT + IOR J,[202020,,202020] ;ASCII MODE INPUT + IOR J,[030303,,030303] ;ENABLE INTERRUPT AND ACTIVATE ON ANY CHARACTER + MOVEM J,TTYST1(I) ;STORE BACK + MOVE J,TTYST2(I) + AND J,[101010,,101010] ;SAVE IMAGE MODE OUTPUT BITS + TRNN D,2 ;SKIP ON IMAGE MODE INPUT + IOR J,[202020,,200020] ;SAY ALL CHARS EXCEPT RUBOUT SHOULD ECHO. + TRNE D,4 ;SKIP ON NOT DDT MODE + ANDCM J,[006000,,606000] ;DDT MODE + IOR J,[030303,,030303] ;ENABLE INTERRUPT AND ACTIVATE ON ANY CHARACTER + MOVEM J,TTYST2(I) ;STORE BACK +TTYO5: HRRM U,TTYSTS(I) + AOS TTNTO(I) ;INCREMENT NUMBER OF CHNLS THIS TTY OPEN ON. + CONO PI,TTYON + MOVSS C + JSP Q,OPSLC3 ;SET UP IO CHNM WORD AND RETURN + TYIDN,,TYODN + TYIBN,,TYOBN + +SUBTTL WAITING FOR ACCESS TO TTY + +;HERE WHEN WANT TO DO TTY INPUT, TO CHECK FOR PERMISSION. +TTYWI: HLRZ I,(R) + ANDI I,%TICNS+(.BM $TIIDX) + TRZN I,%TICNS ;CLEAR AND CHECK CONSOLE/DEVICE BIT + POPJ P, ;RETURN RIGHT AWAY IF DEVICE +;CALL FROM ATTYCR. +TTYWI2: MOVE T,TTYTBL(U) + TLNN T,%TBNOT ;RETURN RIGHT AWAY IF WE OWN THE TTY. + POPJ P, + TLNE T,%TBIIN ;ELSE INTERRUPT IF %TBIIN IS SET. + JRST TTYLOS +TTYWC3: TLC T,%TBINT ;ELSE INTERRUPT IF %TBINT IS SET AND NOT %TBWAT. + TLNN T,%TBINT+%TBWAT + JRST TTYLOS + PCLT + SKIPGE TTYTBL(U) + PUSHJ P,UFLS ;WAIT TILL HAS TTY (CANT HAVE TTY IF DISOWNED) + POPJ P, + +;CALL FROM ATTYC, ATTYC2. WAIT TILL WE OWN THE TTY. +TTYWC2: MOVE T,TTYTBL(U) + TLNN T,%TBNOT ;RETURN RIGHT AWAY IF WE OWN THE TTY. + POPJ P, + JRST TTYWC3 + +;HERE WHEN WANT TO DO A TTY RESET. +;SKIP IF THE RESET SHOULD REALLY BE DONE. +TTYWR: HLRZ I,(R) + ANDI I,%TICNS+(.BM $TIIDX) + TRZN I,%TICNS ;CLEAR AND CHECK CONSOLE/DEVICE BIT + JRST POPJ1 ;RETURN YES IF DEVICE + MOVE T,TTYTBL(U) + TLNN T,%TBNOT ;RETURN YES IF WE OWN THE TTY. + JRST POPJ1 + POPJ P, ;OTHERWISE IGNORE THE RESET. + +;HERE TO WAIT FOR OUTPUT PERMISSION FOR TTY +;RETURN WITHOUT SKIP IF THE OUTPUT SHOULD BE THROWN AWAY +;AND REPORTED TO THE USER AS DONE. +TTYWO: HLRZ I,(R) + ANDI I,%TICNS+(.BM $TIIDX) + TRZN I,%TICNS + JRST POPJ1 ;ALWAYS HAVE PERMISSION IF TTY IS A DEVICE. +;CALL FROM ATTYC, ETC. +TTYWO2: MOVE A,U + HRRZ T,I + CAIN T,%TINON ;NEVER HAVE PERMISSION FOR CONSOLE IF WE'RE DISOWNED. + JRST TTYWO1 + MOVE T,TTYTBL(U) ;WE HAVE OUTPUT PERMISSION IFF ALL OUR SUPERIORS + ;HAVE PERMISSION AND WE HAVE %TBOUT + ;AND THE TREE HAS A TTY. +;THE NEXT INSN IS TEMPORARY, UNTIL DDT ETC. ARE CHANGED TO WIN FULLY. +TTYWO3: JUMPGE T,TTYWO4 ;IF WE HAVE THE TTY, WE CAN TYPE ON IT. + SKIPGE SUPPRO(A) ;ALL OK TO TOP OF TREE => SEE IF TREE HAS A TTY. + JRST TTYWO4 + TLNN T,%TBOUT ;NOT AT TREE TOP => DOES THIS JOB HAVE PERMISSION + JRST TTYWO1 ;FROM ITS SUPERIOR? + MOVE A,SUPPRO(A) ;AND IS THE SUPERIOR ALLOWING ANY INFERIORS PERMISSION? + MOVE T,TTYTBL(A) + TLNE T,%TBINF ;SUPERIOR SAYS WE'RE OK => SEE IF SUPERIOR HAS PERMISSION. + JRST TTYWO3 +TTYWO1: MOVE T,TTYTBL(U) ;HERE IF WE DON'T HAVE PERMISSION. + TLNE T,%TBOIG ;IF OUTPUT IS TO BE IGNORED, + POPJ P, ;TELL OUR CALLER TO THROW IT AWAY, RIGHT NOW. + TLNE T,%TBWAT+%TBOUT + JRST TTYWO6 + TLNE T,%TBINT + JRST TTYLOS + TLNE T,%TBNVR+%TBDTY + JUMPL I,[ SUB P,[1,,1] ? JRST OPNL10 ] +TTYWO6: MOVE T,TTYTBL(A) ;ELSE MUST WAIT. WAIT FOR A CHANGE IN THE + CAMN T,TTYTBL(A) ;TTYTBL OF THE SUPERIOR DENYING US PERMISSION. + PUSHJ P,UFLS + JRST TTYWO ;NOW RE-CHECK EVERYTHING. + +;WE HAVE PERMISSION, BUT MAYBE WAIT ANYWAY TO AVOID MIXING JOBS' OUTPUT. +TTYWO4: SKIPGE TTYTBL(U) ;NO NEED TO WAIT IF WE OWN THE TTY + CAMN U,TTYLJB(I) ;OR WE WERE LAST JOB TO USE IT. + JRST TTYWO5 + MOVEI T,TOBS ;ELSE WAIT FOR BUFFER TO BE EMPTY + CAMN T,TORM(I) + JRST TTYWO5 + CAME T,TORM(I) + PUSHJ P,UFLS + JRST TTYWO ;RECHECK EVERYTHING, SINCE WE MAY HAVE LOST PERMISSION. + +;WE ARE ALLOWED TO OUTPUT RIGHT AWAY. +TTYWO5: MOVEM U,TTYLJB(I) ;MAKE SURE WE DON'T HAVE TO WAIT AGAIN. + JRST POPJ1 + +;TURN TTY OFF, THEN WAIT UNTIL EITHER TTY ISN'T IN COM MODE OR +;ONE OF THE BITS IN T IS SET IN TTYCOM(I). +TTYCMW: CONO PI,TTYOFF + TDNN T,TTYCOM(I) + SKIPL TTYCOM(I) + POPJ P, + SKIPN USER + POPJ P, ;SYS JOB TRYING TO HACK + HRR T,I ;WAIT UNTIL NOT COM MODE OR IN COM MODE BUT ONE OR MORE BITS IN LH OF T + PUSHJ P,LWAIT1 ;COME ON. WAIT UNTIL OUT OF COM MODE WITH UTCOFF + PUSHJ P,TTYSCM + POPJ P, + +TTYSCM: SKIPL TTYCOM(T) + JRST POPJ1 ;NOT COM MODE + PUSH P,A + HLLZ A,TTYCOM(T) + TDNE A,T + AOS -1(P) ;MASKED BIT(S) ON + POP P,A + POPJ P, + + +;ECHOIN SYSTEM CALL. ASK FOR ECHOING OF CERTAIN CHARACTERS +;UNTIL A BREAK CONDITION OCCURS. +;A BREAK CONDITION IS WHEN EITHER A NON-ECHOED CHARACTER IS TYPED IN +;OR A CERTAIN NUMBER OF CHARACTERS HAVE BEEN TYPED IN. +;CHARACTERS ECHOED BY THE ECHOIN ARE STORED INTO THE USER'S +;MEMORY BY THE INTERRUPT LEVEL. IF THE NECESSARY AREAS OF MEMORY +;ARE SWAPPED OUT, THAT CONSTITUTES A BREAK CONDITION. + +;THE BREAK TABLE IS 128 BITS (DIVIDED INTO 4 WORDS THE LOW 4 BITS OF EACH UNUSED) +;ONE BIT FOR EACH ASCII CHARACTER. A 1 INDICATES A CHARACTER THAT +;IS A BREAK CONDITION. A 0 INDICATES A CHARACTER THAT CAN BE ECHOED. +;A CHARACTER WITH THE CONTROL OR META BIT IS ALWAYS A BREAK. + +;ARG 1 TTY INPUT CHANNEL +;ARG 2 B.P. TO WHERE IN USER'S MEMORY TO STORE CHARACTERS. +;ARG 3 NUMBER OF CHARACTERS TO ALLOW +;ARG 4 ADDRESS OF BREAK TABLE. +;ARG 5 ADDRESS OF BLOCK OF COUNTERS TO BE INCREMENTED OR DECREMENTED FOR EACH CHARACTER. +; IF THE ADDRESS IS ZERO, ALL THIS IS OMITTED. +; THE BLOCK HAS SEVEN WORDS. +; THE FIRST TWO WORDS ARE LEFT ALONE. +; THE NEXT FOUR ARE INCREMENTED. +; THE SEVENTH IS DECREMENTED. + +;THE WORDS OF THE BREAK TABLE RESIDE IN ACS Q, J, R AND W. +;SIMILARLY, THE ADDRESS OF THE COUNT RESIDES IN AC C, +;THE ADDRESS OF THE BYTE POINTER IN B, +;AND THE ADDRESS OF THE BLOCK OF COUNTERS IN E. +;THEY ARE LOOKED AT BY THE INTERRUPT LEVEL, +;WHICH KNOWS THAT THE PROGRAM IS EXECUTING AN ECHOIN +;BY THE FACT THAT THE PC IS NECHO1. IT IS IMPORTANT THAT WE +;NOT LOCK ANY SWITCHES SO THAT SWAPPING OUT A PAGE WON'T PCLSR +;US UNTIL WE ARE AWAKENED BY THE INTERRUPT LEVEL WHEN IT SEES +;THAT THE PAGES IT NEEDS ARE NOT IN CORE. + +NECHOIN: + JSP J,ATTYCR ;DECODE CHANNEL. GET TTY NUMBER IN I. + XCTR XRW,[MOVES A,(C)] ;MAKE SURE COUNT IS IN CORE AND WRITABLE. + JUMPLE A,POPJ1 ;IF WANT ZERO OR FEWER CHARACTERS, RETURN IMMEDIATELY. + XCTR XRW,[MOVES A,(B)] ;MAKE SURE BYTE POINTER IS IN CORE AND WRITABLE. + IBP A ;MAKE SURE BYTE BUFFER IS IN CORE AND WRITABLE. + XCTR XRW,[MOVES (A)] ; (NO LOSSAGE IF IT ISN'T, BUT MIGHT AS WELL SWAP IT IN NOW.) + XCTR XRW,[MOVES (E)] ;MAKE SURE BLOCK OF COUNTERS IS IN CORE AND WRITABLE. + XCTR XRW,[MOVES 6(E)] + UMOVE Q,(D) ;LOAD BREAK TABLE WORDS INTO Q, J, R, W. + UMOVE J,1(D) + UMOVE R,2(D) + UMOVE W,3(D) + SKIPE TICC(I) ;IF TYPE-AHEAD AVAILABLE, WE CAN'T DO ANYTHING. + JRST POPJ1 + SKIPG TACC(I) ;WAIT FOR AN ACTIVATION (PROBABLY NON-ECHOED) CHARACTER. + PUSHJ P,TYIFL2 ;CALL TYIFL2 INSTEAD OF UFLS TO PREVENT IMPENDING **MORE**. +NECHO1: JRST POPJ1 ;THE JOB IS INSIDE AN ECHOIN IF ITS PC IS HERE. + +SUBTTL TTY INPUT IOT + +;BLOCK MODE INPUT IOT. +TTYBI: JSP E,INBTCH + +;UNIT MODE INPUT IOT. +;R HAS THE ADDRESS OF THE IOCHNM WORD. +;VALUE RETURNED IN W. +TYI: PUSHJ P,TTYWI ;WAIT FOR THE TTY IF ITS A CONSOLE. TTY NUMBER IN I + HLRZ R,(R) ;GET IOCHNM WORD FLAGS, MODIFIED BY CTL BITS + XOR R,CTLBTS(U) ;R HAS CHANNEL FLAGS + PUSH P,E + PUSHJ P,TYI0 ;GET THE CHAR IN D. + POP P,E + JUMPL D,UNIEOF ;TYI0 RETURN -1 => DON'T FLUSH THE SIGN BIT, AND TERMINATE BLOCK IOT. + ANDI D,%TXPIE+%TXMPE+%TXECI+%TXCTL+%TXMTA+%TXSUP+%TXTOP+%TXASC + CAIN A,^C + AOS (P) ;EOF, SKIP RETURN + MOVE W,D + POPJ P, + +;ASSUMING I HAS TTY NUMBER AND R HAS IOCHNM BITS. +;READ A CHARACTER FROM THE TERMINAL AND RETURN IT IN D. +TYI0: MOVE D,TTYTYP(I) + TRNN D,%TYSTY ;SKIP IF TTY IS ALTER EGO OF STY. + JRST TYI1B1 + MOVSI D,%SSINT + TDNE D,STYSTS-NFSTTY(I) + JRST TYI1B1 ;HAVE ALREADY GIVEN INT + SKIPE TICC(I) + JRST TYI1B1 + IORB D,STYSTS-NFSTTY(I) + MOVE TT,STYOMS-NFSTTY(I) ;CHANNELS OPEN FOR OUTPUT ON + AND TT,MSKST2(D) + MOVN B,TT + AND TT,B + IORM TT,IFPIR(D) ;GIVE INT ON LOWEST-NUMBERED CHANNEL. + JRST TYI1B1 + +TYI1B1: TRNE R,%TIACT + JRST TYI1B ;GOBBLE NEXT CHR REGARDLESS OF ACTIVATION + MOVE TT,TTYSTS(I) + TLNE TT,%TSACT + JRST TYI1B + PCLT + SKIPG TACC(I) + PUSHJ P,TYIFLS +TYI1B: PCLT ;WAIT TILL THERE'S A CHAR TO READ. + SKIPG TICC(I) + PUSHJ P,TYIFLS + CONO PI,CLKOFF ;PREVENT ECHOING WHILE WE'RE MESSING WITH POINTERS. + MOVE B,TIOP(I) + MOVE T,B + CAMN B,TIBEP(I) + SUBI B,TIBL + ILDB D,B + SKIPN TT,TICC(I) ;CHECK FOR CHAR FLUSHED BY ECHO BEFORE WE TURNED OFF CLOCK. + JRST TYI1A + TRNN D,%TXIGN + JRST TYI1 + TRNN R,%TIECH + TRNN D,%TXPIE + JRST [ PUSHJ P,TYIREM + JRST TYI1A ] + PCLT + CAMN T,TIOP(I) ;WAIT FOR ECHOING TO FLUSH THIS CHAR FROM BUFFER, + PUSHJ P,UFLS +TYI1A: CONO PI,CLKON ;ALLOW ECHOING. + JRST TYI1B1 ;THEN TRY AGAIN TO READ CHAR. + +TYI1: CONO PI,CLKON ;ALLOW ECHOING. + MOVE T,TTYSTS(I) + TLNN T,%TSNOE ;ECHOING BEING DEFERRED OR + TRNE R,%TIECH ;THIS CHANNEL NEEDN'T WAIT FOR ECHO + ANDCMI D,%TXPIE ;=> DON'T. + SKIPE PICLR(U) ;AT INT LVL IN USER PRGM OR + TRNE R,%TIINT ;THIS CHNL NEEDN'T WAIT FOR CHAR TO INTERRUPT + ANDCMI D,%TXINT ;=> DON'T WAIT FOR THAT. + MOVEI T,(D) + ANDI T,%TXINT+%TXPIE ;WAIT FOR THESE BITS TO CLEAR. + TRNE T,%TXINT ;IF ABOUT TO WAIT FOR %TXINT TO CLEAR, + PUSHJ P,TYIIWT ;TAKE CARE OF SEVERAL POSSIBLE SCREWS - MAY SET T. + LDB D,[360600,,B] + LSH T,(D) + PCLT + TDNE T,@B + PUSHJ P,UFLS ;HANG UNTIL PI ECHO BIT FOR THIS CHAR IS TURNED OFF + LDB D,B ;GET CHARACTER + TRNN R,%TIECH ;IF WE AREN'T SUPPRESSING ECHOING, + TRNN D,%TXMPE ;AND M.P. ECHOING NEEDED BUT NOT YET DONE, + JRST TYI2 + MOVE T,TTYSTS(I) + TLNE T,%TSNOE + JRST TYI2 + JRST TYIMP1 ;GO DO IT. + +TYIMP1: PUSH P,R ;DO MAIN-PRGM ECHO IF NECESSARY. + PUSH P,C + PUSHJ P,[MOVEI J,1(P) + ADD P,[3,,3] + HRRZM P,(P) + MOVE TT,TTYEPP(I) + PUSHJ P,NULSET ;NO LOSSET OF IOCHNM + JSP E,TYOSE1 + MOVEI R,%TJECH+%TJMOR + MOVE A,D + ANDI A,%TXCTL+%TXMTA+%TXSUP+%TXTOP+%TXASC + JRST TYO6] + POP P,C + POP P,R + CONO PI,TTYOFF + MOVE B,TIOP(I) + CAMN B,TIBEP(I) + SUBI B,TIBL + ILDB D,B + TRZ D,%TXMPE ;M.P. ECHOING NO LONGER PENDING FOR THIS CHAR. + DPB D,B + CONO PI,TTYON +TYI2: TRNN R,%TIPEK ;DON'T REMOVE IF CHNL SAYS DON'T. + PUSHJ P,TYIREM ;FINALLY REMOVE CHAR FROM BUFFER. + MOVE TT,TTYCOM(I) + TLNE TT,%TCLED ;DOES THIS JOB WANT TO SEE LOCAL EDITING PROTOCOL + JRST TYI2Z ;REPLIES, ETC.? + MOVE TT,D + ANDI TT,%TXTOP+%TXASC ;NO. DISCARD THEM. + CAIE TT,%TXTOP+"S ;TOP-S AND TOP-E ARE SPECIAL COMMANDS SENT + CAIN TT,%TXTOP+"E ;BY LOCAL EDITING TTYS. + JRST [SKIPG TICC(I) ;IGNORE THE TOP-E OR TOP-S, + PUSHJ P,UFLS ;AND THE CHARACTER AFTER IT AS WELL. + PUSHJ P,TYIREM + JRST TYI1B1] + CAIN TT,%TXTOP+"T ;TOP-T MEANS "LABEL FAILURE" IN LINE SAVING PROTOCOL. + JRST [ MOVEI T,3 ;IGNORE COMMAND AND THREE ARGS. + CAMLE T,TICC(I) + PUSHJ P,UFLS + PUSHJ P,TYIREM + PUSHJ P,TYIREM + PUSHJ P,TYIREM + JRST TYI1B1] +TYI2Z: MOVE T,TTYSTS(I) + TLNE T,%TSCNS + SKIPGE SUPPRO(U) + JRST TYI3 ;DEFERRED CALL IGNORED IF TOP-LEVEL, OR NOT A CONSOLE + CAIN TT,%TXTOP+"Z + JRST [ TRNE R,%TIPEK ;DEFERRED CALL + PUSHJ P,TYIREM ;REMOVE IT IF DIDN'T ALREADY + MOVSI T,(%PIDCL) + JRST UUOER1 ] +TYI3: MOVSI TT,%TSACT + ANDCAM TT,TTYSTS(I) +;TYIFLS CAN COME HERE AFTER THROWING AWAY 1 WORD FROM STACK, FOR NO CHARS AVAIL WITH %TINWT. +TYI4: MOVSI TT,%SSINT ;IF TTY IS STY'S, MAKE SURE NEXT TTY IOT GIVES STY OUTPUT INT. + MOVE B,TTYTYP(I) + TRNE B,%TYSTY + ANDCAM TT,STYSTS-NFSTTY(I) + SKIPGE A,D ;CHAR IN A FOR TYINRM + POPJ P, ;DON'T CANONICALIZE A -1 (NO CHARS AVAILABLE) TO A RUBOUT! + PUSHJ P,TYINRM ;CANONICALIZE TO ASCII UNLESS %TIFUL IS SET. + ANDI D,%TXPIE\%TXMPE\%TXECI ;BUT PRESERVE THE EXTRA INFO BITS + IOR D,A ;WHICH ARE NOT REALLY PART OF THE CHARACTER. + ANDI A,%TXASC + POPJ P, + +;ASSUME R HAS IOCHNM BITS (OR AT LEAST THE %TIFUL BIT). +;TURN CHAR. IN A TO 7-BIT ASCII CHAR IF %TIFUL IS OFF. +TYINRM: ANDI A,%TXCTL+%TXMTA+%TXSUP+%TXTOP+%TXASC + TRNE R,%TIFUL + POPJ P, + MOVE TT,A ;LEAVE THE HELP CHARACTER ALONE + ANDI TT,%TXTOP+%TXASC ;(THIS USED TO FLUSH THE SUPER ("SHIFT") BIT + CAIN TT,%TXTOP+"H ; PERHAPS IT SHOULD FLUSH ALL OF CTL/MTA/SUP?) + POPJ P, +TYINR2: ANDI A,%TXCTL+%TXASC ;FLUSH THE EXTRA BITS. + TRZE A,%TXCTL ;DON'T WANT FULL CHAR SET: TURN CTL+X INTO ASCII CTL-X + CAIN A,177 ;BUT LEAVE CTL-RUBOUT AS RUBOUT, FOR TECO'S SAKE. + POPJ P, + CAIGE A,77 ;CTL-? => RUBOUT + JRST [ CAIN A,40 ;CTL-SPACE => CTL-@ + MOVEI A,^@ ;41-76 STAY THE SAME + POPJ P, ] ;LETTERS TURN INTO ASCII CONTROLS + CAIL A,140 ;TO CONTROLIFY, FIRST TURN LOWER CASE TO UPPER, + SUBI A,40 + XORI A,100 ;THEN TOGGLE 100 BIT, TURNING A INTO ^A AND ? INTO RUBOUT. + POPJ P, + +;REMOVE THE FIRST CHAR. FROM THE INPUT BUFFER, AND RETURN IT IN D. +;UPDATES ALL COUNTS AND POINTERS. HALTS IF BUFFER EMPTY. +;CLOBBERS B,TT. +TYIREM: CONO PI,TTYOFF + PUSHJ P,TYIRE1 + JRST TTYONJ + +TYIRE1: SOSGE TICC(I) ;ENTRY WHEN TTYCHN IS OFF. + BUG PAUSE,[TTY: BUFFER EMPTY AT TYIREM] + MOVE B,TIOP(I) ;SAVE COPY OF BUFFER-EMPTYING POINTER IN TT. + MOVE TT,B + CAMN B,TIBEP(I) ;ADVANCE THE POINTER, FETCHING THE CHARACTER. + SUBI B,TIBL + ILDB D,B + MOVEM B,TIOP(I) + TRNE D,%TXACT ;IF CHAR SAYS IT WAS AN ACTIVATION CHAR, UPDATE # OF ACTIVATION + SOS TACC(I) ;CHARS STILL INB THE BUFFER. + TRNE D,%TXPIE ;IF IT NEEDED PI ECHO, + SOS ECHOC(I) ;ONE FEWER CHAR AWAITS PI ECHO. + TRNE D,%TXINT + SOS TINTC(I) ;SIMILAR FOR INT. TO PROGM. + SKIPL TINTC(I) + SKIPGE ECHOC(I) + BUG PAUSE,[TTY: TINTC OR ECHOC OVER-DECREMENTED] + CAMN TT,ECHOP(I) ;IF ECHOP POINTED AT THIS CHAR, + MOVEM B,ECHOP(I) ;ADVANCE IT. + CAMN TT,TINTP(I) ;SIMILAR FOR TINTP + MOVEM B,TINTP(I) + POPJ P, + +;COME HERE WHEN ABOUT TO WAIT FOR A CHAR'S %TXINT TO CLEAR OUT. +;CLOBBERS D, TT; MAY ZERO %TXINT IN T, IN WHICH CASE CALLER SHOULD +;NOT BOTHER TO WAIT FOR %TXINT TO CLEAR. +TYIIWT: MOVE D,MSKST2(U) + AND D,TYIMSK(I) ;D GETS ENABLED TTY INPUT CHANNELS. + MOVE TT,D + ANDCM TT,IDF2(U) ;TT GETS ENABLED, UNDEFERRED TTY INPUT CHANNELS. + TDNE TT,IFPIR(U) ;IF AN INTERRUPT IS PENDING ON ONE OF THEM, %TXINT + POPJ P, ;WILL CLEAR IF WE LET THE INT. HAPPEN. + MOVN TT,D ;ELSE GET LOWEST NUMBERED ENABLED INPUT CHANNEL'S BIT + AND D,TT + AND D,IDF2(U) ;IF THAT CHANNEL ISN'T DEFFERED, + IORM D,IFPIR(U) ;REQUEST AN INTERRUPT ON IT, AND WE CAN STILL WIN. + JUMPN D,CPOPJ + ANDCMI T,%TXINT ;CAN'T RQ AN INT, SO BIT WON'T BE CLEARED, IT IS CERTAIN, + POPJ P, ;SO GIVE UP ON WAIITING FOR IT TO CLEAR. + +;COME HERE TO HANG UP FOR INPUT. LIKE UFLS BUT PREVENTS +;A **MORE** THIS TIME AROUND THE SCREEN, ON GROUNDS THAT USER +;HAS COMMANDED THE OUTPUT FOR 1 MORE PAGE AT LEAST. +;IF %TINWT IS SET, INSTEAD OF HANGING, THROW AWAY RETURN ADDRESS +;AND JUMP TO TYI4, TO RETURN -1 FROM THE IOT. +;CLOBBERS A,D,H. +TYIFLS: TRNE R,%TINWT + JRST [ SUB P,[1,,1] + SETO D, + JRST TYI4] +;ENTER HERE FROM ECHOIN - R IS NOT MEANINGFUL. +TYIFL2: MOVE H,TTYOPT(I) + TLNE H,%TOMVU ;THIS DOESNT APPLY TO ARDS-LIKE DISPLAYS + TLNE H,%TOERS + SKIPA D,I + JRST UFLS + IMULI D,TPLEN*2 + MOVEI A,%TFEOP + ANDCAM A,TPFLAG(D) ;CLEAR PENDING MORE + HLL D,TTYSTS(I) + MOVE A,TCMXV(I) .SEE TPVE;(D) + TLNE H,%TOMVU ;PRINTING TTY'S AND DISPLAYS IN SCROLL MODE + TLNE D,%TSROL ;DO ONE THING. + JRST TYIFL1 + CAME A,TPVB+TPLEN(D) ;FOR WRAP-AROUND DISPLAYS, + JRST UFLS ;IF NOT USING AN ECHO AREA, + MOVEI A,6 ;PREVENT MORES FOR THE NEXT 6 LINES. + MOVEM A,TPVM(D) + JRST UFLS + +TYIFL1: SUB A,TTYROL(I) ;IN SCROLL MODE, **MORE** WHEN THIS LINE GOES OFF THE SCREEN. + MOVEM A,TPVM(D) + JRST UFLS + +SUBTTL TTY OUTPUT IOT + +;THESE PUSHED BY TYOSET, REFERENCED INDEX OF J. +TYOPV0==0 ;COUNT OF NUMBER OF CHARACTERS THAT WE CAN TAKE A SHORTCUT FOR, + ;IN SUPERIMAGE MODE SIOT. +;TYOPV1 UNUSED, BUT SPACE ALLOCATED. +TYOPV2==2 ;-> IOCHNM WORD OF CHANNEL IOT IS ON. +TYOPV3==3 ;PC PPR IDX,,TTY #. + + +;TO OUTPUT TO A TTY (R -> IOCHNM WD OF TTY CHNL) +; JSP E,TYOSET ;WAIT TILL JOB HAS TTY AND OUT OF COM MODE, +; ;INIT FOR PCLSRING, PUSH VARS ON STACK. +; JRST IGNORE ;TYOSET RETURNS HERE IF THIS OUTPUT SHOULD BE DISCARDED. +; ... ;OUTPUT 1 OR MORE CHARS TO TTY +; ;MEANWHILE, J -> BLOCK OF 4 STACK VARS. +; POPJ P, ;RETURNS TO TYOUNS TO FLUSH STACK, ETC. + +TYOSET: PUSHJ P,TTYWO ;WAIT TILL THIS JOB HAS OUTPUT PERMISSION. + JRST (E) ;RETURN IF OUTPUT BEING IGNORED. + AOS E ;SKIP THAT RETURN IF WE ARE GOING TO DO THE OUTPUT. + JUMPN U,TYOSE3 + MOVEI T,TYOWNC ;FOR SYSTEM JOB, CHECK TTOALC WITH A TIMEOUT IN CASE + SKIPL TTOALC(I) ;THE TTY IS FORGETTING TO TURN TYPEOUT BACK ON. + PUSHJ P,TYOW2 + JRST TYOSE4 ;NOTE THAT TYOW2 CAN POP1J. + +TYOSE3: SKIPL TTOALC(I) ;^\ CAN DELAY TYPEOUT AT M.P. LEVEL THROUGH SIGN OF TTOALC. + PUSHJ P,UFLS ;ALSO USED BY OUTPUT RESET ON SOFTWARE TTY. +TYOSE4: MOVEI J,1(P) ;PROVIDE SPACE FOR TEMPS, WHERE FINSET CAN FIND THEM. + ADD P,[2,,2] + PUSH P,R .SEE TYOPV2 + MOVE H,TTYOPT(I) + MOVSI T,%TCLFT+%TCOCO+%TCICO + SKIPGE TTYCOM(I) + PUSHJ P,TTYCMW ;WAIT TILL TTY IS NOT IN COM MODE, OR OVER-RIDDEN. + CONO PI,TTYON + MOVEI A,%TJCNS+77+%TJCP1+%TJCP2+%TJSTP+%TJINK ;DON'T LET THESE IOCHNM BITS BE CHANGED + ANDCAB A,CTLBTS(U) ;EVEN TEMPORARILY. + HRLZS A ;ELSE, IF A BIT IS SET IN THE CTL BITS, + XORB A,(R) ;CHANGE IT (TEMPORARILY) IN IOCHNM WORD. + PUSHJ P,LOSSET ;SET UP ROUTINE TO UNDO THAT TEMPORARY CHANGE + [MOVE A,AC0S+J(U) ;IF WE SHOULD PCLSR OUT + HLRZ T,@TYOPV2(A) + XOR T,CTLBTS(U) + HRLM T,@TYOPV2(A) + POPJ P,] + HLRZS A + TRNE A,%TJSTP ;IF WE ARE HUNG IN A **MORE**, WAIT TILL THERE'S A CHARACTER + PUSHJ P,TYOSMR ;IT'S IMPORTANT WE WAIT WITOUT TYOSW SET - ELSE NO ECHOING! + MOVE TT,I ;NOW MAKE TT -> APPRO. PC PPR FOR THIS CHNL. + IMULI TT,TPLEN*2 + TRNE A,%TJPP2 + MOVE TT,TTYEPP(I) +TYOSE1: PCLT ;ENTER HERE FROM INPUT IOT WHEN DOING M.P. ECHOING + AOSE TYOSW(I) ;SEIZE THIS TTY FOR MP LEVEL. + JRST [SKIPL TYOSW(I) + PUSHJ P,UFLS + JRST .-1] + PUSHJ P,LSWDEL ;THEN SET UP LOSSET ROUTINE FOR BOTH TYOSW AND + PUSHJ P,LOSSET ;PREVIOUSLY-LOSSET'ED CHANGE TO IOCHNM BITS. + [MOVE A,AC0S+J(U) + HLRZ T,@TYOPV2(A) + XOR T,CTLBTS(U) + HRLM T,@TYOPV2(A) + MOVE A,TYOPV3(A) + SETOM TYOSW(A) + POPJ P,] + CAMN TT,TTYLPP(I) ;IF TTY IS ASSOCIATED W/ ANOTHER PC PPR, + JRST TYOSE2 + PUSH P,TT + SKIPL TT,TTYLPP(I) + PUSHJ P,TYOMVC ;DISASSOCIATE THEM. + POP P,TT + SETCAM TT,TTYLPP(I) +TYOSE2: PUSH P,I .SEE TYOPV3 + HRLM TT,(P) + MOVE Q,TTYCOM(I) + TLNE Q,%TCECH ;IF THERE'S ECHOING OUTPUT IN OUTPUT BUFFER, + JRST [ PCLT ;WAIT FOR IT TO GET PRINTED. MUSTN'T HAVE ECHO AND + PUSHJ P,TYOWC ;OUTPUT IN THE OUTPUT BUFFER AT ONE TIME. + MOVSI Q,%TCECH + ANDCAB Q,TTYCOM(I) + JRST .+1] + TLNE Q,%TCMTR ;IF THIS TTY IS A TERMINET & ITS MOTOR IS OFF, + PUSHJ P,TTTMTO ;TURN THE MOTOR ON BEFORE OUTPUT. + PUSHJ P,(E) + +TYOUNS: CAIA ;IF WE ARE SKIPPED INTO, PROPAGATE THE SKIP. + AOS -4(P) + SUB P,[4,,4] + +TYOUN1: HRLZ R,CTLBTS(U) ;UNDO TEMPORARY CHANGES IN IOCHNM WD. + XORM R,@TYOPV2(J) + PUSHJ P,LSWDEL + SKIPGE TTYERQ(I) ;IF ECHOING ISN'T ALREADY REQUESTED, + SKIPL TTYLPP(I) ;AND THERE IS BUFFERED CURSOR POSITIONING, + JRST TYOUN3 + CONO PI,TTYOFF + MOVEI J,TTEDMY ;SO TYOFNR WON'T CLOBBER RANDOMNESS. + SETCM TT,TTYLPP(I) ;TT -> PC PPR TTY WAS DISSOCIATED FROM. + MOVE H,TTYOPT(I) + MOVE A,TORM(I) + CAIN A,TOBS ;AND IT CAN BE DONE NOW, + PUSHJ P,TYOFRC ;FORCE OUT BUFFERED CURSOR MOTION. + SETOM TYOSW(I) + JRST TTYONJ + +TYOUN3: SETOM TYOSW(I) ;RELEASE TTY. + POPJ P, + +;WAIT TILL THERE'S A TTY INPUT CHARACTER. +TYOSMR: PUSH P,A + PUSH P,R + MOVEI R,%TIACT+%TIECH+%TIPEK + PUSHJ P,TYI0 + POP P,R + JRST POPAJ + +;OUTPUT IOT + +;BLOCK MODE. +TTYBO: JSP E,TYOSET + JRST TTYBOI + JSP E,NBTOCH +TTYBO3: CAIN A,EOFCH + POPJ P, + PUSH P,TT + PUSHJ P,TTYBO1 + POP P,TT + MOVEI E,TTYBO3 + POPJ P, + +;IGNORE SOME BLOCK MODE OUTPUT. +TTYBOI: XCTR XRW,[MOVES D,(C)] + TLO D,700000 + HLRE A,D + MOVNS A + HRLS A + ADD D,A ;COUNT THE AOBJN POINTER ALL THE WAY OUT. + XCTR XRW,[MOVEM D,(C)] + POPJ P, + + JRST TYOBP ;SIOT DISPATCH IS -1 + ADDR. OF UNIT MODE ROUTINE. +;UNIT MODE TTY OUTPUT. +TYO: JSP E,TYOSET + POPJ P, ;JUST RETURN IF WE ARE SUPPOSED TO DISCARD THE OUTPUT. + SKIPGE C + SKIPA A,(C) + UMOVE A,(C) +;MUSTN'T CLOBBER C OR D. +TTYBO1: HLRZ R,@TYOPV2(J) ;RH(R) GETS LH(IOCHNM WD) + HRRZ I,TYOPV3(J) + HLRZ TT,TYOPV3(J) +TYOBP2: ANDI A,%TXCTL+%TXMTA+%TXSUP+%TXTOP+%TXASC + SKIPGE E,TTYCOM(I);IN COM MODE W/ LOCAL FEED THRU, + TLNN E,%TCLFT + JRST TYO6 + PUSH P,C + PUSH P,D + PUSH P,U + PUSH P,TT ;ECHO CHAR ON ALL TTYS IN LOOP + PUSH P,R ;THAT HAVE REMOTE-FEED-THRU. + PUSHJ P,TYCREP ;DO FOLLOWING INSN FOR EACH TTY IN LOOP. + PUSHJ P,TYO7 ;(# OF TTY DOING IT FOR PUT IN I) + JFCL ;(TYCREP WILL SKIP IF THAT INSN ALWAYS DOES) + POP P,R + POP P,TT + POP P,U + POP P,D + POP P,C + JRST TYO6 + +TYO7: MOVE D,TTYCOM(I) ;IF THIS TTY WANTS MY TYPEOUT. + TLNE D,%TCRFT + CAMN I,-2(P) ;AND IF IT ISN'T ME, + JRST POPJ1 + PUSHJ P,TYCSET ;SET UP ACS Q,R,U FOR TTY TO ECHO ON. + CONO PI,TTYOFF + PUSH P,A + PUSHJ P,TTYI13 ;ECHO CHAR ON THIS TTY. + CONO PI,TTYON + JRST POPAJ1 + +;SIOT ROUTINE FOR TTY OUTPUT - JUST LIKE REPEATED UNIT MODE, +;BUT MOVES THE TYOSET OUTSIDE THE LOOP TO SAVE TIME. +TYOBP: MOVEM B,SRN3(U) ;SAVE B, C; CAN'T USE STACK SINCE TYOSET PUSHES. + MOVEM C,SRN4(U) + JSP E,TYOSET ;SET UP FOR DOING TTY OUTPUT. + JRST TYOBPI ;RETURN HERE IF WE SHOULD DISCARD THE OUTPUT + HLRZ R,@TYOPV2(J) ;FOR TYOFRC + CAME TT,TTYLPP(I) + TRNN R,%TJSIO ;ONLY IN SUPER-IMAGE MODE, + CAIA + PUSHJ P,TYOFRC ;FORCE OUT ALL PREVIOUS MAIN PROGRAM CURSOR MOTION + MOVE B,SRN3(U) ;BE JUST LIKE ORDINARY REPEATED-UNIT-MODE SIOT, + MOVE C,SRN4(U) ;EXCEPT THAT THE TYOSET IS OUTSIDE THE LOOP. + SETOM TYOPV0(J) ;CAN'T TAKE SHORTCUT AT FIRST. + MOVE D,[%IOTOT,,.+2] + JRST NSIOT1 ;SIOT ROUTINE WILL COME BACK FOR EACH CHAR, PRESERVING I,J,TT + HLRZ R,@TYOPV2(J) + MOVE A,D ;PUSHJ HERE FOR EACH CHARACTER. + SOSG TYOPV0(J) ;PERHAPS THE PREVIOUS CHARACTER DISCOVERED WE CAN + ;START TAKING THE SHORTCUT. + JRST TYOBP2 ;IF NOT, DO THE WHOLE PILE OF WORK. + ANDI A,%TXDIS+%TXASC + SKIPGE E,TTYCOM(I) + TLNN E,%TCLFT ;SHORT CUT IS TO PUT THE CHARACTER RIGHT IN THE OUTPUT BUFFER. + JRST TYONCC ;MAY BE USED ONLY FOR SUPERIMAGE OUTPUT. + JRST TYOBP2 ;AND BETTER NOT BE IN COM MODE WITH LOCAL FEED THRU. + +;IGNORE THIS STRING OF OUTPUT; TELL THE USER WE OUTPUT IT. +TYOBPI: MOVE B,SRN3(U) + MOVE C,SRN3(U) + UMOVE T,(B) + UMOVE TT,(C) + JUMPE C,POPJ1 + IBP T + SOJG TT,.-1 + XCTR XRW,[MOVEM T,(B)] + XCTR XRW,[MOVEM TT,(C)] + JRST POPJ1 + + +;A USUALLY HOLDS THE CHAR BEING IOTTED, OR THE CHAR TO BE PUT IN BUFFER. +;B IS A TEMP. +;C IS USUALLY UNUSED, AND MUSTN'T BE CLOBBER BY IOT RTN. +;D " +;E IS A TEMP. +;TT HOLDS THE INDEX OF THE PC PPR BEING USED. +;I HOLDS THE TTY NUMBER. +;H HOLDS THE TTY'S TTYOPT WORD. +;J HOLDS THE INDEX OF A 4-WORD BLOCK USUALLY ON THE STACK +; INDEX USING TYOPV0, TYOPV1, TYOPV2, TYOPV3. +;T IS A TEMP. +;R'S RH HOLDS THE IOCHNM WORD'S LH. +;Q HOLDS THE BP FOR STORING IN OUTPUT BUFFER. +; INITTED FROM TOIP, AND STORED BACK IN TOIP WHEN FINALIZED. + +TYO6: PCLT + MOVEI T,TYOWNC ;MAKE SURE AT LEAST TYOWNC + CAML T,TORM(I) ;CHARS OF SPACE LEFT IN OUTPUT BUFFER. + PUSHJ P,TYOW2 ;NOTE THIS CAN POP1J. SO CAN TYOWN. + MOVE H,TTYOPT(I) +IFN N11TYS,[ + TRNN H,%TP11T ;FOR A PDP11 TV TTY, + JRST TYO8 + SKIPL TT11P ;IGNORE IT IF PDP11 ISN'T UP. + POPJ P, + PUSHJ P,TYOWN ;WAIT TILL AT LEAST TYOWNC CHARS SPACE. +] ;(TORM HAS NO INFO ON TV TTYS). +;A,R,I,TT,H,J SET UP AT THIS POINT. +;ENTER HERE FROM PI LEVEL TO ECHO CHARS +TYO8: MOVE Q,TOIP(I) ;GET COPY OF BP TO STORE WITH. + ;WHEN OUTPUTTING CHARS, WILL UPDATE Q INSTEAD TOIP. + ;THEN, WHEN CAN NO LONGER PCLSR, DO TOIP(I)_Q. + MOVE B,TPFLAG(TT) +TYOIG1: TRNE B,%TFEOP+%TFIGL ;ANY EXCEPTIONAL CONDITION FOR THIS PC PPR? + JRST TYOIGL ;IF SO, HANDLE IT. +TYOEO9: TRNE R,%TJCP1+%TJCP2+%TJSTP+%TJSIO+%TJINK + JRST TYOCP1 ;HANDLE ANY EXCEPTIONAL CONDITION FOR CHANNEL. + TRNE A,%TXCTL+%TXMTA+%TXSUP+%TXTOP + JRST TYOMTA ;TAKE CARE OF FUNNY BITS IN CHARACTER. +TYOMT9: CAILE A,40 + JRST TYONRM ;PRINTING CHARS AND RUBOUT. + CAIN A,40 + JRST TYOSPC ;SPACE MAY BE EITHER PRINTING OR CURSOR MOTION. + CAIL A,^G ;< ^G OR > ^S => NORMAL CTL CHAR, +IFE 0, CAIL A,^Q ;RIGHT NOW, ^S USES %TGIMG OF GROUP 0. +IFN 0, CAIL A,^T ;BUT FOR INPUT, IT USES GROUP 6. THIS INSN MAKES IT USE GROUP 6 FOR OUTPUT TOO. + JRST TYOCTL + JRST @.+1-^G(A) ;ELSE DO WHAT THIS PARTICULAR ONE WANTS. + + TYOBEL ;^G DOESN'T MOVE CURSOR. + TYOBS ;^H MOVES BACKWARDS. + TYOTAB ;^I MOVES TO TAB STOP. + TYOLF ;^J IS LINEFEED. + TYOCTL ;^K IS NORMAL. + TYOFF ;^L MAY CAUSE A **MORE** + TYOCR ;^M IS A CARRET + TYOCTL ;^N IS NORMAL + TYOCTL ;^O IS NORMAL + TYOCTP ;^P MAY SIGNIFY A CURSOR CTL CODE. + TYOCTL ;^Q IS NORMAL + TYOCTL ;^R IS NORMAL + TYOCTS ;^S IS NORMAL EXCEPT USES A DIFFERENT GROUP'S %TGIMG. + +;OUTPUT CHARACTER IN SUPERIMAGE MODE. +TYOSIO: ANDI A,377 + MOVEI B,TYOWNC ;IF WE'VE GOT THIS FAR, THEN THERE'S AT LEAST TYOWNC CHARS OF SPACE, + CAME TT,TTYLPP(I) ;IF DISSOCIATED, + PUSHJ P,[ + PUSH P,Q + PUSHJ P,TYOASS ;ASSOCIATE, + POP P,T + CAME T,Q ;AND IF THAT REQUIRED OUTPUT, + SUBI B,5 ;THAT'S SO MANY FEWER CHARS BEFORE TIME TO CHECK TORM AGAIN. + POPJ P,] + MOVEM B,TYOPV0(J) ;AND NO UNUSUAL CONDITIONS, SO SIOT CAN GO FAST FOR A WHILE. +;OUTPUT A CHAR WITH NO CURSOR CONTROL. +;ASSUMES ITS POSITION DOESN'T MATTER. +TYONCC: PUSHJ P,TYOOUT + JRST TYOFN2 + +;COME HERE WHEN ^P IS OUTPUT. +TYOCTP: TRNN R,%TJDIS ;IS THIS OUTPUT CHNL TREATING ^P SPECIALLY? + JRST TYOCTL ;NO, TREAT ^P AS NORMAL CTL CHAR. + TRO R,%TJCP1 ;YES, SAY TREAT NEXT CHAR AS CURSOR CODE. + JRST TYOFNR + +;COME HERE TO OUTPUT A ^S. +TYOCTS: CAME TT,TTYLPP(I) + PUSHJ P,TYOASS ;PREPARE TO OUTPUT PRINTING CHARACTERS. + HLLZ T,TTYST2(I) ;GET THE RELEVANT %TGIMG BIT. + TLZ T,#<%TGIMG_12.> + JRST TYORU2 + +;HERE TO OUTPUT ^G +TYOBEL: MOVEI A,%TDBEL + JRST TYONCC + +;COME HERE FOR ^PP - OUTPUT A ^P. +TYOCPP: SKIPA A,[^P] + +;COME HERE FOR ^PQ TO OUTPUT A ^C. +TYOCPQ: MOVEI A,^C + +;COME HERE FOR NORMAL (NON-FORMATTING) CONTROLS. +TYOCTL: CAME TT,TTYLPP(I) + PUSHJ P,TYOASS ;PREPARE TO OUTPUT PRINTING CHARACTERS. + CAIN A,33 + JRST TYOALT ;CHECK FOR ALTMODE. + HLLZ T,TTYST1(I) ;GET THE "OUTPUT IN IMAGE MODE" BIT THAT'S RELEVANT. + TLZ T,#<%TGIMG_12.> +TYORU2: TRNE R,%TJECH ;ECHO-MODE OUT => PRINT IN ASCII MODE. + JRST TYOCT1 + MOVE B,TTYSTS(I) + TLNE B,%TSSAI ;SHOULD USE SAIL CHAR SET FOR OUTPUT => DO SO. + JRST TYONR0 + JUMPN T,TYOAL1 ;IF "OUTPUT IN IMAGE" IS SET, GO DO SO. +TYOCT1: HRLM A,(P) ;ELSE OUTPUT CTL CHAR IN ASCII MODE, + MOVEI A,"^ ;AS "^" FOLLOWED BY UN-CTL'ED CHAR. + TLNE H,%TOSAI + MOVEI A,13 ;IF TTY HAS SAIL MODE, USE A SAIL UPARROW. + PUSHJ P,TYONR1 + HLRZ A,(P) + XORI A,100 + JRST TYONR0 + +TYOAL1: TLNN H,%TOSAI + JRST TYORU1 + JRST TYONR0 + +;HANDLE CHARACTERS WHICH HAVE %TXCTL, %TXMTA, %TXSUP OR %TXTOP SET. +TYOMTA: MOVE B,TTYSTS(I) + TLNN B,%TSFCO ;IF USER DOESN'T WANT FULL CHAR SET OUTPUT, + JRST TYOMT4 ;IGNORE THE META BITS (USUALLY). + TRNE A,%TXCTL + PUSHJ P,TYOMT1 ;ECHO AN ALPHA FOR %TXCTL. + TRZE A,%TXMTA + PUSHJ P,TYOMT2 ;TYPE A BETA FOR %TXMTA + TRZE A,%TXSUP + PUSHJ P,TYOMT5 + TRZN A,%TXCTL+%TXTOP ;IF CTL OR TOP IS SET, THE CHARACTER + JRST TYOMT9 + CAIN A,40 ;ISN'T AN ASCII CONTROL CHAR EVEN IF < 40 + JRST TYOSPC ;(BTW, SPACE IS STILL SPACE) + CAIE A,177 + CAIG A,40 +TYOMT3: TLNE H,%TOSAI + JRST TYONRM + CAME TT,TTYLPP(I) ;WE HAVE WHAT WOULD OTHERWISE BE AN ASCII CTL CHAR. + PUSHJ P,TYOASS + CAIN A,33 + JRST TYOAL3 + JRST TYOCT1 + +TYOMT5: MOVEI B,6 ; EPSILON + JRST TYOMT6 + +TYOMT1: SKIPA B,[2] ; ALPHA +TYOMT2: MOVEI B,3 ; BETA +TYOMT6: CAME TT,TTYLPP(I) + PUSHJ P,TYOASS + PUSH P,A + MOVE A,B + PUSHJ P,TYONR1 + JRST POPAJ + +TYOMT4: TRNN R,%TJECH ;FOR OUTPUT, IGNORE THE META BITS. FOR ECHO, + ANDI A,%TXASC ; TRY TO ECHO WHAT THE GUY TYPED. + TRNE A,%TXTOP ;IF TOP IS ON, + TLNN H,%TOSAI ;AND THE TTY HAS THE SAIL CHAR SET, + TRZA A,%TXMTA+%TXSUP+%TXTOP + JRST TYONR3 ;ECHO THE CHAR USING SAIL CHAR SET. + PUSHJ P,TYINR2 ;ECHO AS WHAT PROGRAM SEES + JRST TYOMT9 ;ALSO HACKS SUCH AS ^L MAY CLEAR THE SCREEN + +;HANDLE SPACE: ON OVERPRINTING TERMINALS, SPACE = ^PF. +;ON IMLACS, SPACE = SPACE BECAUSE THE IMLAC PROGRAM LOSES FOR ^PF AT END OF LINE. +;ON RAW TERMINALS, SPACE OF COURSE GOES OUT AS SPACE. +;ON OTHER TERMINALS, SPACE = SPACE. THIS IS A CROCK, BUT IT IS NECESSARY +;BECAUSE ^PF TAKES 6 TIMES AS LONG ON DATAPOINTS BECAUSE OF PADDING, +;AND TWICE AS LONG ON VT52S BECAUSE IT TAKES TWO CHARACTERS. + +TYOSPC: TLNN H,%TOOVR ;NON-OVERPRINTING => OUTPUT A REAL SPACE. + JRST [ TLNE H,%TOMVU + JRST TYONRM + HLRE B,TTYLPS(I) ;BUT ON GLASS TTY'S (NON-OVERPRINTING, NO UPWARD MOTION) + CAMGE B,TPVP(TT) + JUMPGE B,.+1 ;IT IS SAFE TO TREAT SPACES AS CURSOR MOTION + JRST TYONRM] ;IF THEY ARE GOING TO FOLLOW DOWNWARD MOTION ANYWAY. + TLNE H,%TORAW+%TOIML ;IMLAC, OR NO OPTIMIZATION => OUTPUT A REAL SPACE. + JRST TYONRM ;NORMAL CHARACTER. + CAMN TT,TTYLPP(I) + PUSHJ P,TYOMVC ;PREPARE FOR CURSOR MOTION. + AOS B,TPHP(TT) ;MOVE FORWARD 1 POS. + CAML B,TCMXH(I) .SEE TPHE;(TT) + TRNE R,%TJCTN + JRST TYOFNR + SOS TPHP(TT) ;IF NECESSARY, CONTINUE TO NEXT LINE AND RETRY. + PUSHJ P,TYOCTN + JRST TYOSPC + +TYONR3: ANDI A,%TXASC +;OUTPUT A NORMAL CHARACTER, AND FINALIZE. COME HERE FOR +;NORMAL CHAR ACTUALLY IOTTED. +TYONRM: CAME TT,TTYLPP(I) ;ABOUT TO OUTPUT PRINTING CHARS SO + PUSHJ P,TYOASS ;FORCE ANY CURSOR MOTION INTO OUTPUT BFR + CAIN A,177 + JRST TYORUB + +;CALL HERE TO OUTPUT NORMAL CHAR, IF CURSOR POSITIONING KNOWN +;NOT TO BE NECESSARY. +TYONR0: PUSH P,[TYOFNA] ;CAUSE FINALIZATION WHEN FINISHED. + +;CALL HERE TO OUTPUT NORMAL CHAR AS PART OF TASK OF OUTPUTTING +;SOME LARGER GROUP. DOESN'T FINALIZE, IN CASE WE PCLSR LATER. +TYONR1: AOS B,TPHP(TT) ;ADVANCE CURSOR OF PC PPR 1 SPACE. + CAML B,TCMXH(I) .SEE TPHE;(TT) ;NOT YET AT END OF LINE => OUTPUT CHAR. + TRNE R,%TJCTN ;AT END: NO CONTIN => OUTPUT, + JRST TYOOUT + PUSHJ P,TYONR2 ;CONTINUE THE LINE (NOTE CURSOR POS FOR + CAME TT,TTYLPP(I) ;THE "!" WAS ALREADY DONE) + PUSHJ P,TYOASS ;TYONR2 DISSOCIATED THE TTY + JRST TYONR1 ;BUT TYONR1 NEEDS IT ASSOCIATED. + +;TYPE "!" TO CONTINUE A LINE. +;THIS FINALIZES THE !CRLF BUT ALSO REMOVES THE CONDITIONS WHICH +;CAUSED IT TO BE CALLED; SO PCLSRING IS NO PROBLEM. +;LEAVES TTY DISSOCIATED FROM PC PPR. +TYOCTN: CAME TT,TTYLPP(I) + PUSHJ P,TYOASS + AOS TPHP(TT) ;ACCOUNT FOR THE "!". +TYONR2: PUSH P,A + MOVEI A,"! ;PUT "!" IN OUTPUT BUFFER, + PUSHJ P,TYOOUT + PUSHJ P,TYORCR ;AND GO TO NEXT LINE. + PUSHJ P,TYOLF + MOVE B,TPFLAG(TT) ;IF THAT LF TOOK US TO LAST LINE, + TRNE B,%TFEOP + JRST TYOEO5 ;DO **MORE** PROCESSING IF NEC. + JRST POPAJ ;AND RETRY WHATEVER CAUSED CONTINUATION. + +;COME HERE TO OUTPUT A RUBOUT. +TYORUB: TRNN R,%TJECH + JRST TYORU3 + TLNN H,%TOERS ;RUBOUT ON A DISPLAY CONSOLE ECHOES AS DELETE BACKWARDS. + TLNN H,%TOOVR ;LIKEWISE ON A GLASS TTY + JRST TYODLB +TYORU3: MOVE T,TTYST2(I) + ANDI T,%TGIMG_6 ;GET RUBOUT'S "OUTPUT IN IMAGE MODE" BIT. + JRST TYORU2 + +;COME HERE TO OUTPUT A LF. FINALIZES. LEAVES TTY DISSOCIATED. +TYOLF: CAMN TT,TTYLPP(I) ;BEFORE MUNGING PC PPR'S CURSOR POS, + PUSHJ P,TYOMVC ;MUST DISASSOCIATE TTY'S POS FROM PC PPR. + SOS TPVM(TT) ;COUNT DOWN # LINES TILL NEXT **MORE**. + AOS B,TPVP(TT) ;MOVE PC PPR'S CURSOR 1 LINE DOWN. + CAIG B,118. ;DON'T LET VPOS ON PRINTING TTY GET TOO BIG. + CAML B,TCMXV(I) .SEE TPVE;(TT) ;END OF RANGE => GO TO TOP OR SCROLL. + JRST TYOLFE +TYOLF0: MOVE A,TTYSTS(I) + TLNE A,%TSMOR ;IF **MORE** DESIRED, + JRST TYOLF1 + ADDI B,1 ;THEN IF ENTERING LAST LINE OF RANGE, + CAME B,TCMXV(I) .SEE TPVE;(TT) + JRST TYOLF1 + SKIPGE TPVM(TT) ;UNLESS NOT TIME YET, + SKIPA B,[%TFEOP] ;TELL NEXT OUTPUT ATTEMPT TO CAUSE **MORE**. +TYOLF1: SETZ B, + PUSH P,B + TLNE H,%TORAW + JRST [ MOVEI A,%TDLF ;NO OPTIMIZATION => + PUSHJ P,TYOOUT ;OUTPUT A REAL LF (PLUS PADDING) + PUSHJ P,TYOMVC + JRST TYOLF5] + TLNN H,%TOERS ;IF TTY HAS SELECTIVE ERASE, + JRST TYOLF5 + PUSH P,TPHP(TT) + PUSHJ P,TYORCR ;GO TO BEGINNING OF LINE + HLRZ B,TTYLPS(I) ;IF CR AND LF AND CLR-EOL ARE EXACTLY + ADDI B,1 ;WHAT WE NEED, + CAMN B,TPVP(TT) + SKIPN TTYROL(I) ;AND TTY CAN DO IT, DO THEM ALL AT ONCE. + SKIPA A,[%TDEOL] ;OTHERWISE, OUTPUT MOVE-CURSOR AND %TDEOL. + SKIPA A,[%TDCRL] ;OUTPUT %TDCRL = %TDMOV AND %TDEOL TOGETHER. + PUSHJ P,TYOASS + PUSHJ P,TYOOUT + PUSHJ P,TYOMVC + POP P,TPHP(TT) +TYOLF5: POP P,B + IORM B,TPFLAG(TT) + JRST TYOFND + +;LINEFEED THAT WRAPS AROUND. +TYOLFE: MOVE A,TTYSTS(I) + TLNN H,%TOMVU ;END OF SCREEN ON PRINTING TTY => SCROLL BY 1. + JRST TYOLF2 + TLNE A,%TSROL ;DISPLAY IN SCROLL MODE? + SKIPE TPVB(TT) ;CAN'T SCROLL UNLESS PC PPR IS WHOLE SCREEN. + JRST TYOLF3 +TYOLF2: MOVN A,TTYROL(I) ;A GETS - # LINES TO SCROLL AT ONCE. + JUMPE A,TYOLF3 ;JUMP IF THIS TTY CAN'T SCROLL + SOS TPVP(TT) + PUSH P,TPHP(TT) + HRRZ B,TTYLPS(I) + MOVEM B,TPHP(TT) + PUSHJ P,TYOASS ;MOVE CURSOR DOWN TO LAST LINE ON SCREEN, PREPARING FOR SCROLL + PUSHJ P,TYOMVC + POP P,TPHP(TT) + AOS TPVP(TT) +;SCROLL: A HAS -<# LINES TO ADJUST ALL VPOS'S BY>. +TYOLF6: HLRZ B,TTYLPS(I) ;COMPUTE NEW TTYLPS LH. + ADD B,A + JUMPGE B,TYOLF7 ;IF IT WOULD BE NEGATIVE, + TLNN H,%TORAW ;ON DISPLAY WRAP AROUND INSTEAD (LOSSAGE HAPPENING). + JRST TYOLF3 + SETZ B, ;IN RAW MODE, DON'T WORRY ABOUT IT. +TYOLF7: HRLM B,TTYLPS(I) ;STORE UPDATED M.P. VPOS. + ADDM A,TPVP(TT) ;CHANGE OTHER MAIN PRGM VPOS'S. + MOVE B,TPVP(TT) ;IF SCROLLING 1 LINE AT A TIME, + JRST TYOLF0 ;MAY NEED TO SET %TFEOP. + ;IN ANY CASE, CLEAR NEXT LINE & FINALIZE. + +;HERE TO WRAP AROUND TO TOP OF SCREEN. +TYOLF3: SETZM TPVM(TT) ;TURN OFF ANY SUPPRESSION OF MORES BY INPUT + TLNN H,%TOERS ;ON DISPLAYS WITHOUT SELECTIVE ERASE, + JRST [ PUSHJ P,TYOCLR ;MUST CLEAR SCREEN WHEN WRAP AROUND. + JRST TYOMVC] ;MUST LEAVE TTY DISSOCIATED. +TYOLF4: MOVE B,TPVB(TT) ;ELSE JUST MOVE TO TOP OF PC PPR + MOVEM B,TPVP(TT) + JRST TYOLF1 ;AND CLEAR THE TOP LINE. + +;HANDLE BACKSPACE. +TYOBS: TLNN H,%TOIML ;BACKSPACE ON IMLAC ISN'T SAME AS MOVE BACK. + JRST TYOBS1 + MOVE B,TPHP(TT) ;ON IMLAC, FIRST, IF AT LEFT MARGIN, + SKIPG B .SEE TPHB;(TT) ;DO NOTHING. + JRST TYOFN2 +TYOBS2: CAME TT,TTYLPP(I) + PUSHJ P,TYOASS ;IF WE SHOULD BACKSPACE, + SOSGE TPHP(TT) + SETZM TPHP(TT) + JRST TYORU1 ;DO IT BY SENDING A ^H. + +TYOBS1: TLNE H,%TOMVB ;ARE WE ECHOING ^H ON TTY THAT CAN'T BS? + JRST TYOBS4 + TRNN R,%TJECH + JRST TYOBS3 + JRST TYOCTL ;ECHO "^H" RATHER THAN CR AND SPACE FWD. + +TYOBS4: TLNE H,%TORAW ;IN RAW MODE ON TTY THAT CAN BS? + JRST [ MOVEI A,%TDBS ;IF NO OPTIMIZATION, + JRST TYOBS2 ] ;ARRANGE TO OUTPUT REAL BS. +TYOBS3: CAMN TT,TTYLPP(I) ;BS ON TTY THAT ISN'T AN IMLAC. + PUSHJ P,TYOMVC ;PREPARE TO DO CURSOR MOTION. + SOS B,TPHP(TT) ;MOVE BACK 1 POS. + SKIPGE B .SEE TPHB;(TT) + AOS TPHP(TT) ;AT LEFT MARGIN, DO NOTHING. + JRST TYOFNX + +;COME HERE WHEN TAB OUTPUT (AT TOP LEVEL ONLY) +TYOTAB: TRNE R,%TJECH + JRST TYOTA1 + MOVE B,TTYST2(I) ;MAYBE TABS SHOULD BE OUTPUT IN IMAGE MODE. + TLNE B,%TGIMG_6 + JRST TYONMV +TYOTA1: MOVE A,TPHP(TT) + ADDI A,10 + TRZ A,7 ;HPOS OF NEXT TAB STOP. + MOVE B,TCMXH(I) .SEE TPHE;(TT) + TRNN R,%TJCTN + SUBI B,1 ;B HAS EFFECTIVE LINEL. + CAML A,B + MOVE A,B ;A HAS PLACE TAB MOVES TO. + SUB A,TPHP(TT) ;HOW FAR TO MOVE RIGHT? + TRNN R,%TJCTN + JUMPE A,[PUSHJ P,TYOCTN + JRST TYOTAB] + CAMN TT,TTYLPP(I) + PUSHJ P,TYOMVC ;PREPARE FOR CURSOR CTL. + ADDM A,TPHP(TT) ;MOVE CURSOR TO TAB STOP. + JRST TYOFNX + +;HANDLE ^L. +TYOFF: TRNN R,%TJECH ;ECHOING? + JRST TYOCTL + MOVE B,TTYSTS(I) ;YES; ^L ECHOES AS UPARROW-L + TLNE H,%TOMVU ;EXCEPT ON DISPLAYS, UNLESS PRGM HAS DISABLED. + TLNE B,%TSCLE + JRST TYOCTL ;ECHO AS UPARROW L + JRST TYOCLR ;ECHO AS CLEAR SCREEN. + +;^M IOTTED - MAYBE DO CR AND LF. +TYOCR: TRNE R,%TJECH ;IF ECHO MODE OUT, CR DOES CRLF. + JRST TYOCRL + MOVE B,TTYST2(I) + TRNE B,%TGIMG_12. ;ELSE OUTPUT-CR-IN-IMAGE PREVENTS LF. + JRST TYOCR1 + PUSHJ P,TYOCRL ;DO CR AND LF, + MOVEI B,%TFIGL ;THEN SAY IGNORE NEXT CHAR IF IT'S A LF. + IORM B,TPFLAG(TT) + POPJ P, + +TYOCRL: PUSHJ P,TYORCR + PUSHJ P,TYOLF + JRST TYOFND + +TYOCR1: PUSHJ P,TYORCR + JRST TYOFND + +;ALTMODE IOTTED - SHOULD WE OUTPUT DOLLARSIGN? +TYOALT: MOVE B,TTYST2(I) + TRNN R,%TJECH ;ECHO MODE => YES. + TLNN B,%TGIMG ;OUTPUT ALT IN ASCII MODE SAYS YES. + JRST TYOAL4 + JRST TYOAL1 ;NO, OUTPUT AN ALTMODE, WHETHER IT PRINTS OR NOT. + +TYOAL4: TLNN H,%TOSAI ;IF ALTMODE IS A GRAPHIC, USE IT; +TYOAL3: MOVEI A,"$ ;ELSE USE DOLLARSIGN. + JRST TYONR0 ;EITHER WAY IT'S A NORMAL PRINTING CHAR. + +;IF ABOUT TO CHANGE PC PPR'S CURSOR POS WITHOUT PUTTING +;ANYTHING IN THE OUTPUT BUFFER THAT WILL CHANGE THE TTY'S +;REAL CURSOR POS THE SAME WAY, MUST DISASSOCIATE TTY'S +;CURSOR POS FROM THIS PC PPR. TTYLPS WILL THEN +;SAY WHERE THE TTY'S CURSOR WILL BE AFTER CHARS IN OUTPUT +;BUFFER ARE ALL OUTPUT. +TYOMVC: HRLZ B,TPVP(TT) + HRR B,TPHP(TT) + MOVEM B,TTYLPS(I) + SETCAM TT,TTYLPP(I) ;TTY NO LONGER ASSOCIATED. + POPJ P, + +;BEFORE PUTTING ANYTHING IN OUTPUT BUFFER USING A PC PPR, +;TTY'S CURSOR MUST BE ASSOCIATED WITH PC PPR (THAT IS, +;THE TTY'S CURSOR MUST BE WHERE THE PC PPR'S CURSOR IS) +;WHEN A TTY IS ASSOCIATED WITH A PC PPR, TTYLPS +;IS NONSENSE, AND IT IS NECESSARY FOR OUPUT RTNS +;TO UPDATE PC PPR'S CURSOR IN ACCORDANCE WITH WHAT +;IS PUT IN THE OUTPUT BUFFER. +;THIS ROUTINE ASSOCIATES TTY IN I WITH PC PPR IN TT. +TYOASS: TRNE R,%TJHDE + POPJ P, + PUSH P,A + HLRZ T,TTYLPS(I) ;CURRENT VERTICAL POS + HRRZ A,TTYLPS(I) ;CURRENT HORIZONTAL POS + CAMN T,TPVP(TT) ;IF CURSOR IS WHERE WE WANT IT, + CAME A,TPHP(TT) + AOSA A + JRST TYOAS3 ;JUST SAY WE'RE ASSOCIATED. + SKIPGE TTYLPS(I) + BUG ;TTY ALREADY ASSOCIATED WITH A PC PPR? + CAMN T,TPVP(TT) ;SEE IF JUST MOVING ONE SPACE TO THE RIGHT + CAME A,TPHP(TT) + JRST TYOAS6 ;NO, NEED FULLY GENERAL CURSOR MOTION + MOVEI A,%TDFS ;SAVE BUFFER SPACE IN THIS COMMON CASE + TLNE H,%TOOVR + MOVEI A,40 ;IF SPACE OVERPRINTS, IT IS BETTER THAN %TDFS SINCE FEWER CHARS + PUSHJ P,TYOOUT ;IF SENT TO A SOFTWARE TTY OVER HARDWARE LINE. + JRST TYOAS3 + +TYOAS6: MOVEI A,%TDMV0 ;TELL THE TTY TO PUT ITS CURSOR + TLNE H,%TOMVU + JRST TYOAS7 + MOVEI A,%TDMOV + PUSHJ P,TYOOUT ;WHERE THIS PC PPR WANTS IT. + HLRZ A,TTYLPS(I) + PUSHJ P,TYOOUT + HRRZ A,TTYLPS(I) +TYOAS7: PUSHJ P,TYOOUT + MOVE A,TPVP(TT) + CAML A,TCMXV(I) ;ATTEMPT TO GO BELOW SCREEN BOTTOM? + BUG + PUSHJ P,TYOOUT ;AND THE NEW POSITION. + MOVE A,TPHP(TT) + PUSHJ P,TYOOUT +TYOAS3: MOVEM TT,TTYLPP(I) ;TELL TTY IT IS ASSOCIATED. + SETOM TTYLPS(I) + JRST POPAJ + +TYOAS5: PUSH P,A ;REGARD TTY AS ASSOCIATED WITHOUT ACTUALLY + JRST TYOAS3 ;MOVING ITS CURSOR. + +;FORCE OUT BUFFERED CURSOR MOTION. +;CALL ONLY IF TTY DISSOCIATED, FROM M.P. OR CLOCK LEVEL. +;H MUST BE SET UP ALREADY +TYOFRC: MOVE Q,TOIP(I) + PUSHJ P,TYOASS + JRST TYOFN2 + +;PUT CHAR IN OUTPUT BFR (BUT IT DOESN'T BECOME VISIBLE +;TO INT. LEVEL UNTIL WE FINALIZE - IN CASE WE PCLSR) +TYOOUT: TRNE R,%TJHDE + POPJ P, +TYOOU1: CAMN Q,TOBEP(I) ;Going to deposit past end of buffer? + MOVE Q,TOBBP(I) ; Yes, make wrap around instead. + HRRZI T,(Q) ;Get addr part of the buffer pointer. + CAILE T,@TOBEP(I) ;Reasonable buffer pointer? + ; CANT HAVE BEEN DUE TO 11 DOWN + BUG HALT,[TTY: OUTPUT BUFFER POINTER PAST END OF BUFFER] + IDPB A,Q ;Stuff char into output buffer. +IFN N11TYS, TRNN H,%TP11T ;TV-11 ttys dont have TORM. + SOSL TORM(I) ; One less space available in buffer. + POPJ P, + BUG HALT,[TTY: OUTPUT BUFFER OVERFLOWED, TYOWNC IS TOO SMALL] + +;FINALIZE, UPDATING TOIP, TORM AND FLAGS. +;ALSO RESET Q FOR ANOTHER BUNCH OF OUTPUT. +TYOFNX: ;FINALIZE WHEN TTY DISSOCIATED AND NOTHING PUT IN BFR. +TYOFND: ;SIMILAR, WHEN SOMETHING MIGHT HAVE BEEN PUT IN BFR. +TYOFNA: ;FINALIZE WHEN TTY ASSOCIATED W/ PC PPR. +TYOFN2: MOVEM Q,TOIP(I) + AOSN TTYOAC(I) ;START THE TTY. + XCT TTYST(I) + JRST TYOFNR + +;ON ORDINARY TTY, CALL WHEN BUFFER FULL. +;WAIT TILL AT LEAST 3/4 EMPTY. T HAS MINIMUM # CHARS NEEDED. +;IF RUNNING SYS JOB, POP1J IF TTY SEEMS TO BE HUNG. +TYOW1: CAIGE T,TOBS*3/4 ;DON'T UNBLOCK TILL BUFFER AT LEAST 3/4 EMPTY. + MOVEI T,TOBS*3/4 +TYOW2: MOVEM I,EPDL3(U) ;MAY TRAP OUT ON SYSTEM JOB + CAME U,USER + BUG + JUMPN U,TYOW4 + JRST TYOW5 ;HANG UP SYS JOB FOR MAX OF 5 SEC + + PUSHJ P,TYOW6 +TYOW5: PUSHJ P,UFLS + MOVE T,TTYCOM(I) + TLNE T,%TCHNG + SUB P,[1,,1] ;TIMED OUT + POPJ P, + + CAMLE T,TORM(I) +TYOW4: PUSHJ P,UFLS + POPJ P, + +TYOW6: MOVE A,AC0S+U(U) ;(IN CASE U DIDN'T EQUAL USER AT TYOW1) + MOVE A,EPDL3(A) ;IF SYS JOB, FLUSH IF NO CHR PROCESSED FOR 15 SEC + MOVE Q,TTYTYP(A) + SKIPL TTOALC(A) ;TIME OUT ON SOFTWARE TTY'S WITHOUT ALLOCATION. + JRST TYOW6A ;IF THIS IS A PDP-11 TV, + TRNE Q,%TY11T ;TEST FOR ROOM IN BUFFER IS DIFFERENT ON TV'S + JRST TYOW7 + CAMG T,TORM(A) ;FOR NON-TV'S, TORM IS VALID. + JRST TYOW6B ;THERES ROOM NOW +TYOW6A: MOVSI T,%TCHNG + MOVE Q,TIME + SUB Q,TTLTM(A) + CAIG Q,5.*30. + JRST TYOW6C ;NO NEW TIMEOUT YET + IORM T,TTYCOM(A) ;MARK THIS TTY AS HUNG FOR SYS JOB + JRST POPJ1 + +TYOW6C: CAILE Q,3 + TDNN T,TTYCOM(A) ;SKIP ON CONSOLE WAS LOSING RECENTLY + POPJ P, + JRST POPJ1 ;TIME OUT MUCH SHORTER IF CONSOLE DETERMINED TO BE A LOSER + +TYOW7: LDB Q,T + CAIE Q,1_TT11BY-1 + JRST TYOW6A +TYOW6B: MOVSI T,%TCHNG ;GET HERE WHEN ROOM EXISTS IN BUFFER + ANDCAM T,TTYCOM(A) ;ITS NOT HUNG NOW + JRST POPJ1 + +IFN N11TYS,[ +;ON A PDP-11 TV, CALL HERE TO WAIT UNTIL THERE ARE AT LEAST +;TYOWNC CHARS OF SPACE IN THE OUTPUT BUFFER. +;CAN POP1J FOR THE SYS JOB. +TYOWN: PUSHJ P,TYOWN1 + LDB B,T ;IS THE POS. 20. CHARS UP VACANT? + CAIN B,1_TT11BY-1 + POPJ P, ;YES, NO NEED TO WAIT. + JUMPN U,TYOWN2 ;IF SYS JOB, TIME OUT BEFORE TOO LONG. + MOVEM I,EPDL3(U) + MOVE B,TIME + MOVEM B,TTLTM(I) + JRST TYOW5 + +TYOWN2: PUSH P,A ;SEEMS TO BE NO SPACE, CHECK AGAIN + MOVE B,(T) ;DOING THINGS IN THE RIGHT ORDER THIS TIME + LDB A,T ;TO AVOID GETTING HUNG BY A TIMING ERROR + CAIN A,1_TT11BY-1 + JRST POPAJ ;SOME SPACE APPEARED IN THE MEANTIME + POP P,A + EXCH B,T + CAMN T,(B) ;WAIT FOR THIS WORD TO CHANGE + PUSHJ P,UFLS + JRST TYOWN ;THEN CHECK IT AGAIN + +TYOWN1: MOVE T,TOIP(I) + ADDI T,TYOWNC/<36./TT11BY> + HRRZ B,TOBEP(I) + CAIGE B,(T) + SUB T,TT11OL + HRLI T,040000+TT11BY_6 ;BP TO WHOLE OF RIGHTMOST BYTE IN WORD + POPJ P, +] + +;COME HERE WHEN DETECT THAT %TFEOP OR %TFIGL IS SET. +TYOIGL: TRZN B,%TFIGL ;%TFIGL TAKES PRIORITY. + JRST TYOEOP + MOVEM B,TPFLAG(TT) ;CLEAR IT, AND IGNORE THIS CHAR + CAIE A,^J + JRST TYOIG1 + POPJ P, + +;%TFEOP IS SET AND OUTPUT IS DONE: DO **MORE** PROC. +TYOEOP: PUSH P,[TYOEO9] + PUSH P,A +TYOEO5: SKIPE USER ;DON'T DO MORES IF SYSTEM JOB IS TYPING + TRNE R,%TJMOR+%TJECH ;OR THIS CHANNEL DOESN'T WANT TO + JRST TYOEO7 + MOVSI B,%TSMOR + TDNE B,TTYSTS(I) ;OR THIS JOB DOESN'T WANT TO + JRST TYOEO7 + HRRZ B,TTYSTS(I) ;DON'T **MORE** AN $$^P'ED JOB'S OUTPUT + CAME B,U + JRST POPAJ + MOVE B,TCMXV(I) .SEE TPVE;(TT) + MOVEM B,TPVM(TT) + HRRZ B,UUAC(U) ;GET INTERRUPT BIT FOR CHANNEL THIS IOT IS ON + MOVE B,CHNBIT(B) + AND B,MSKST2(U) ;HAS USER ENABLED OUTPUT INTERRUPT? + JUMPE B,TYOEO1 ;NO, SYSTEM DOES **MORE** PROC. + IORM B,IFPIR(U) ;YES, JUST GIVE USER INT + MOVEI B,%TFEOP ;HE CAN TYPE **MORE** IF HE WANTS TO. + ANDCAM B,TPFLAG(TT) ;INT. HAS BEEN GIVEN. + PUSHJ P,TYOUN1 ;LSWPOP THE FINSET, ETC. + SKIPA + SKIPA + PUSHJ P,UFLS ;MAKE HIM TAKE THE INT. RIGHT NOW. +TYOEO6: PUSHJ P,LSWCLR + SOS UUOH ;HIS PICLR IS SET? RETRY THE UUO. + JRST URET + +TYOEO7: MOVEI B,%TFEOP ;MORE SUPPRESSED, TURN OFF THE FLAG + ANDCAM B,TPFLAG(TT) + JRST POPAJ + +;COME HERE AT END OF PAGE IF PROGRAM ISN'T SMART. +TYOEO1: PUSH P,TPHP(TT) + MOVE A,TPHP(TT) + ADDI A,10 + CAML A,TCMXH(I) + PUSHJ P,TYORCR + CAME TT,TTYLPP(I) + PUSHJ P,TYOASS + IRPC X,,**MORE** + MOVEI A,"X + PUSHJ P,TYONR1 + TERMIN ;OUTPUT THE STRING "**MORE**" + IORI R,%TJSTP ;MAKE ALL OUTPUT ON THIS CHNL HANG. + MOVEI B,%TFEOP ;NO LONGER WANT NEXT CHAR TO DO **MORE** + ANDCAM B,TPFLAG(TT) + POP P,A ;REMEMBER VALUE TO RESET HPOS TO LATER. + HRLM A,TPFLAG(TT) + PUSHJ P,TYOFNA ;FINALIZE SO "**MORE**" WILL TYPE OUT; + ;PCLSRING NO PROBLEM; SINCE %TJSTP IS SET THE IOT + ;WILL COME TO TYOEO3. +TYOEO3: +IFN N11TYS,[ + TRNE H,%TP11T ;WAIT FOR BUFFER SPACE ON TV. + PUSHJ P,TYOWN ;NOTE THIS CAN POP1J +] + PCLT + MOVEI T,TOBS ;WAIT FOR ALL OF "**MORE**" TO GET OUT. + CAME T,TORM(I) + PUSHJ P,TYOW1 + PUSH P,C + PUSH P,D + PUSH P,R + PUSH P,TT + MOVEI R,%TIPEK+%TIACT+%TIECH+%TINWT + PUSHJ P,TYI0 ;LOOK AHEAD AT NEXT INPUT CHAR. + JUMPL D,TYOEO6 ;IS NONE => RETRY UUO AND WAIT IN TYOSET. + EXCH TT,(P) + EXCH R,-1(P) + MOVE Q,TOIP(I) + MOVE C,TTYSTS(I) + TLNE C,%TSROL ;IN SCROLL MODE, MAKE NEXT LINE OF OUTPUT OVERWRITE **MORE**. + JRST [ PUSHJ P,TYORCR + PUSHJ P,TYOCEL + SOS TPVM(TT) ;MORE AGAIN BEFORE THIS LINE GOES OFF SCREEN + JRST TYOEO4] + TRZN R,%TJCP1 ;UNLESS THIS IS ^PN + PUSHJ P,TYOHD1 ;HOME UP (BY HOMING DOWN AND LF'ING) + PUSHJ P,TYOLF ;OTHERWISE (FOR ^PN) JUST LF. +TYOEO4: CAMN TT,TTYLPP(I) + PUSHJ P,TYOMVC ;PREPARE FOR CURSOR MOTION. + HLRZ A,TPFLAG(TT) ;SET HPOS TO WHAT IT WAS BEFORE THE **MORE**. + MOVEM A,TPHP(TT) + HRRZS TPFLAG(TT) + EXCH TT,(P) + EXCH R,-1(P) + ANDI D,177 + CAIE D,177 + CAIN D,40 ;IF A SPACE, FLUSH IT FROM INPUT BFR + PUSHJ P,TYIREM + POP P,TT + POP P,R + POP P,D + POP P,C + ANDCMI R,%TJSTP ;RETURN CHANNEL TO NORMAL. + MOVE Q,TOIP(I) + PUSHJ P,TYOFNR + POP P,A ;RESTORE THE CHAR BEING IOTTED + POPJ P, ;AND TRY AGAIN TO IOT IT. + +TYOEO2: PUSH P,[TYOEO9] + PUSH P,A ;COME HERE IF PCLSR OUT OF TYOEO3, ETC. + JRST TYOEO3 ;WHEN THE IOT IS RETRIED. + +TYOCP1: TRZE R,%TJINK ;IF THIS IS THE CHAR AFTER A ^PI, TREAT IT AS + JRST TYONR3 ;NORMAL PRINTING CHARACTER. + TRNE R,%TJSTP + JRST TYOEO2 ;CHANNEL HUNG IN **MORE**. +;HANDLE CURSOR CONTROL CODES. COME HERE WITH IOTTED CHAR IN A. +;IF WE ARE IN THE MIDDLE OF A ^P CODE. +;OR IF THE CHANNEL IS A SUPERIMAGE OUTPUT CHANNEL. + TRZE R,%TJCP2 ;AFTER A ^PV OR ^PH ? + JRST TYOCP2 + TRZN R,%TJCP1 ;NO, NEXT CHAR ISN'T IN THE ^P CODE. + JRST TYOSIO ;MUST BE %TJSIO THAT WAS SET. +TYOCP4: CAIL A,"A ;IF ^P CODE IS A LETTER, + CAILE A,"_ + JRST TYOCP3 + MOVE B,TYOCPT-"A(A) ;GET THE DISPATCH ENTRY FOR IT, + TLNN H,%TOMVU + JUMPL B,TYOCPA ;TURN SOME CURSOR OPERATIONS INTO CRLF ON PRINTING TTY + TLNE B,200000 + PUSH P,[TYOCPR] ;SOME OPERATIONS RETURN HERE FOR FINALIZATION + JRST (B) ;FINALLY, DISPATCH + +TYOCPR: MOVEI B,%TFEOP + ANDCAM B,TPFLAG(TT) + JRST TYOFNX + +TYOCP3: CAIL A,140 ;LOWERCASE LETTERS ACT LIKE UPPERCASE + JRST [ SUBI A,40 + JRST TYOCP4] + HRLM R,@TYOPV2(J) + PUSHJ P,TYOUN1 ;OR IT'S ILLEGAL. + JRST IOCR11 ;IOC ERROR. + +TYOCPV: IORI R,%TJCP1 ;HERE FOR ^PV +TYOCPH: IORI R,%TJCP2 ;SAME FOR ^PH. SAY NEXT CHAR IS THE CURSOR POS. +TYOFNR: HRLM R,@TYOPV2(J) + POPJ P, + +TYOCP2: CAMN TT,TTYLPP(I) ;INTERPRET THE CHAR AFTER ^PH OR ^PV. + PUSHJ P,TYOMVC + ANDI A,177 + TRZN R,%TJCP1 ;WHICH OF THOSE 2 WAS IT? + JRST TYOCH1 ;IT WAS ^PH + ADD A,TPVB(TT) + SUBI A,10 + CAML A,TCMXV(I) .SEE TPVE;(TT) ;DON'T PUT CURSOR PAST END. + JRST [ MOVE A,TCMXV(I) .SEE TPVE;(TT) + SOJA A,.+1] + CAMGE A,TPVB(TT) ;OR BEFORE BEGINNING. + MOVE A,TPVB(TT) + MOVEM A,TPVP(TT) + JRST TYOCPR + +TYOCH1: .SEE ADD A,TPHB;(TT) + SUBI A,10 + CAML A,TCMXH(I) .SEE TPHE;(TT) ;DON'T PUT CURSOR PAST END. + JRST [ MOVE A,TCMXH(I) .SEE TPHE;(TT) + SOJA A,.+1] + SKIPGE A .SEE TPHB;(TT) ;OR BEFORE BEGINNING. + SETZ A, .SEE TPHB;(TT) + MOVEM A,TPHP(TT) + JRST TYOCPR + +;DISPATCH TABLE FOR ^P CODES. +;SIGN => TURN INTO ^PA ON PRINTING TTY. +;4.8 => PUSHJ, ELSE JRST +TYOCPT: TYOCPA ;A - ADVANCE TO FRESH LINE. + 200000,,TYOMVB ;B - MOVE BACK. + TYOCLR ;C - CLEAR SCREEN. + 200000,,TYOMVD ;D - MOVE DOWN. + TYOCEF ;E - CLEAR TO END OF SCREEN. + 200000,,TYOMVF ;F - MOVE FORWARD. + TYOCP3 ;G - ILLEGAL. + TYOCPH ;H - NEXT CHAR IS DESIRED HPOS. + TYOCPI ;I - NEXT CHARACTER TREATED AS NORMAL PRINTING. + TYOCP3 ;J - ILLEGAL. + 200000,,TYODLF ;K - DELETE FORWARD. + TYOCEL ;L - CLEAR REST OF LINE. + TYOMOR ;M - DO **MORE**. + TYOMO1 ;N - SIMILAR BUT DON'T HOME UP. + TYOCP3 ;O - ILLEGAL. + TYOCPP ;P - TYPE "^P". + TYOCPQ ;Q - TYPE "^C". + 600000,,TYORPS ;R - RESTORE SAVED POS. + 200000,,TYOSPS ;S - SAVE POSITION (FOR A ^PR). + 600000,,TYOHMU ;T - HOME UP. + 200000,,TYOMVU ;U - MOVE UP. + TYOCPV ;V - NEXT CHAR IS DESIRED VPOS. + TYOCP3 ;W - ILLEGAL. + 200000,,TYODLB ;X - DELETE BACKWARDS. + TYOCP3 ;Y - ILLEGAL. + 600000,,TYOHMD ;Z - HOME DOWN. + 200000,,TYOILP ;[ - INSERT LINE POSITION + 200000,,TYODLP ;\ - DELETE LINE POSITION + TYOCEL ;] - CLEAR TO END OF LINE (USE ^PL IT'S BETTER) + 200000,,TYOICP ;^ - INSERT CHARACTER POSITION + 200000,,TYODCP ;_ - DELETE CHARACTER POSITION +IFN .-31.-TYOCPT,.ERR WRONG LENGTH TABLE. + +;^PM AND ^PN DON'T WORK IN PROGRAMS THAT TAKE **MORE** +;INTERRUPTS - OR, PRECISELY, THEY ALWAYS ENTER +;THE STATE OF A CHANNEL THAT HAS JUST TYPED OUT "**MORE**". +TYOMO1: IORI R,%TJCP1 .SEE TYOEO3 ;^PN - ENTER **MORE** STATE. +TYOMOR: IORI R,%TJSTP ;^PM. + HRRZS TPFLAG(TT) + JRST TYOFNR + +TYOCPI: IORI R,%TJINK + JRST TYOFNR + +;INSERT AND DELETE CHARACTERS AND LINES +TYOILP: SKIPA A,[%TDILP] +TYODLP: MOVEI A,%TDDLP + TLNN H,%TOLID + POPJ P, + PUSH P,A ;SUPPOSED TO BE AT LEFT MARGIN + PUSHJ P,TYORCR ;MAKE SURE + POP P,A + JRST TYOIL1 + +TYOICP: SKIPA A,[%TDICP] +TYODCP: MOVEI A,%TDDCP + TLNN H,%TOCID + POPJ P, +TYOIL1: CAME TT,TTYLPP(I) + PUSHJ P,TYOASS + PUSHJ P,TYOOUT + MOVEI A,1 ;SUPPLY PARAMETER OF 1 + JRST TYORU1 ;IF YOU WANT TO OPTIMIZE CONSECUTIVE ONES + ; USE SUPER-IMAGE OUTPUT, AT LEAST FOR NOW + +;RTNS FOR VARIOUS ^P CODES. +;THE FIRST FOUR DON'T FINALIZE ANYTHING. +TYOMVF: CAMN TT,TTYLPP(I) ;^PF + PUSHJ P,TYOMVC ;PREPARE FOR CURSOR MOTION. + AOS B,TPHP(TT) + CAMGE B,TCMXH(I) .SEE TPHE;(TT) + POPJ P, + ;SETZ A, .SEE TPHB;(TT) ;WRAP AROUND FROM LAST POS. TO FIRST. + SETZM TPHP(TT) +TYOMVD: CAMN TT,TTYLPP(I) ;^PD + PUSHJ P,TYOMVC ;PREPARE FOR CURSOR MOTION. + AOS B,TPVP(TT) + MOVE A,TPVB(TT) + CAIGE B,119. + CAML B,TCMXV(I) .SEE TPVE;(TT) ;WRAP AROUND FROM LAST POS. TO FIRST. + MOVEM A,TPVP(TT) + POPJ P, + +TYOMVB: CAMN TT,TTYLPP(I) ;^PB - MOVE BACK. + PUSHJ P,TYOMVC + SOSL B,TPHP(TT) .SEE TPHB;(TT) + POPJ P, + MOVE A,TCMXH(I) .SEE TPHE;(TT) ;WRAP AROUND FROM FIRST TO LAST. + SUBI A,2 + MOVMM A,TPHP(TT) +TYOMVU: CAMN TT,TTYLPP(I) ;^PU - MOVE UP. + PUSHJ P,TYOMVC + SOS B,TPVP(TT) + MOVE A,TCMXV(I) .SEE TPVE;(TT) ;WRAP AROUND FROM FIRST TO LAST. + SUBI A,1 + CAIL A,119. + MOVEI A,118. + CAMGE B,TPVB(TT) + MOVEM A,TPVP(TT) + POPJ P, + +TYOSPS: MOVE B,TPHP(TT) ;^PS - SAVE CURSOR POS. + HRL B,TPVP(TT) + MOVEM B,TPSP(TT) + POPJ P, + +TYORPS: CAMN TT,TTYLPP(I) ;^PR - RESTORE CURSOR POS FROM SAVED. + PUSHJ P,TYOMVC + MOVE B,TPSP(TT) + HRRZM B,TPHP(TT) + HLRZM B,TPVP(TT) + POPJ P, + +TYOCPA: CAMN TT,TTYLPP(I) ;ADVANCE TO FRESH LINE, IN ANY CASE CLEAR REST OF LINE + PUSHJ P,TYOMVC + SKIPE TPHP(TT) ;IF NOT AT THE BEGINNING OF A LINE, + JRST TYOCRL ;CRLF. MAYBE SOMEDAY THIS WILL CHECK + JRST TYOCEL ;WHETHER ANYTHING HAS YET BEEN TYPED ON THIS LINE. + +TYOCLR: TLNN H,%TOMVU ;^PC - CLEAR SCREEN. + JRST [ MOVE A,TCMXV(I) ;ON PRINTING TTYS, JUST CRLF. + SUB A,TTYROL(I) ;BUT DON'T --MORE-- UNTIL THIS LINE + MOVEM A,TPVM(TT);GOES OFF THE SCREEN + JRST TYOCRL ] + SKIPN TPVB(TT) ;USE FAST METHOD IF REALLY CLEARING WHOLE SCREEN + JRST TYOCIM +TYOCI1: PUSHJ P,TYOHMU +TYOCEF: SKIPA A,[%TDEOF] ;^PE CLEAR EOF +TYOCEL: MOVEI A,%TDEOL ;[ ^P] - CLEAR EOL. + TLNN H,%TOERS + JRST TYOFNR +TYONMV: CAME TT,TTYLPP(I) ;HERE FOR CHARS THAT DON'T MOVE THE CURSOR + PUSHJ P,TYOASS ;BUT DO DEPEND ON BEING PRINTED AT THE RIGHT PLACE ON THE SCREEN +TYORU1: PUSHJ P,TYOOUT + JRST TYOFNA + +TYOCIM: PUSHJ P,TYOHMU ;CLEAR WHOLE SCREEN + MOVEM TT,TTYLPP(I) + SETOM TTYLPS(I) + MOVEI A,%TDCLR + JRST TYONMV + +TYOHMU: SETZM TPVM(TT) ;^PT - HOME UP + CAMN TT,TTYLPP(I) + PUSHJ P,TYOMVC ;GO TO COLUMN 0, + MOVE B,TPVB(TT) ;LINE 0. + MOVEM B,TPVP(TT) + +TYORCR: TLNE H,%TORAW ;GO TO COLUMN 0 - CR IN IMAGE MODE. + JRST [ CAME TT,TTYLPP(I) + PUSHJ P,TYOASS ;NO OPTIMIZATION => + SETZM TPHP(TT) + MOVEI A,%TDRCR ;ARRANGE TO SEND REAL CR. + PUSHJ P,TYONCC + JRST TYOMVC] + CAMN TT,TTYLPP(I) + PUSHJ P,TYOMVC ;ELSE DO CURSOR-MOTION. + SETZ B, .SEE TPHB;(TT) + MOVEM B,TPHP(TT) + POPJ P, + +TYOHMD: PUSHJ P,TYORCR ;^PZ - HOME DOWN. +TYOHD1: MOVE B,TCMXV(I) .SEE TPVE;(TT) + SUBI B,1 + CAIGE B,119. + MOVEM B,TPVP(TT) + POPJ P, + +TYODLB: SKIPN TPHP(TT) ;^PX - DELETE BACKWARD. + PUSHJ P,.+1 ;IN COLUMN 0, DO IT TWICE SO AS TO ERASE THE "!" AND CHAR BEFORE IT + PUSH P,TPHP(TT) + PUSHJ P,TYOMVB + POP P,B + SKIPN B + AOS TPHP(TT) ;IF WRAPPED AROUND, SET TO TCMXH-1 +TYODLF: MOVE B,TPHP(TT) ;^PK - ERASE 1 CHARACTER. + CAML B,TCMXH(I) .SEE TPHE;(TT) ;DO NOTHING AT END OF LINE. + POPJ P, + TLNE H,%TOOVR ;IF CAN'T OVERPRINT, USE SPACE TO ERASE + JRST [ TLNN H,%TOERS + POPJ P, ;OTHERWISE, USE SPECIAL CONTROL SEQUENCE IF KNOWN + MOVEI A,%TDDLF + JRST TYONMV ] + CAME TT,TTYLPP(I) + PUSHJ P,TYOASS + AOS TPHP(TT) + MOVEI A,40 ;USE REALLY SPACE, NOT CURSOR MOTION! + PUSHJ P,TYOOUT + PUSHJ P,TYOMVB ;THEN BACKSPACE OVER IT + JRST TYOFNX + +SUBTTL .STATUS AND IOPDL FOR TTY + +;2.4 HAS "TTY" +;2.3 DDT MODE ON INPUT +;(STATYI);2.5 CHRS HAVE BEEN ITYI'ED BUT NOT .IOT'ED (STATYI) + ;2.8 TELETYPE NEXT TO 340 OR 340 SLAVE + ;2.9 TELETYPE IS LOCAL, NOT DIAL IN + +STATYO: ANDI A,77 + CAIN A,%TINON ;IF CHANNEL HAS NO REAL TTY, + POPJ P, ;THERE ARE NO SPECIFICS WE CAN SAY. + SKIPN B,TORM(A) + TRO D,1_9. ;BUF CAP FULL + CAIN B,TOBS + TRO D,1_<9.+1> ;BUFFER CAP EMPTY +STATY1: SKIPL TTYTBL(U) + TRO D,1_<9.+3> ;HAS TTY + IORI D,SNTTY + MOVE H,TTYOPT(A) + TLNE H,%TOERS + TRC D,SNTTY#SNTDS + POPJ P, + +STATYI: ANDI A,77 + CAIN A,%TINON ;CATCH "DISOWNED" TTY CHNLS. + POPJ P, + TRO D,1_<9+1> ;ASSUME BUF CAP EMPTY + SKIPN B,TICC(A) ;SEE IF THERE ARE ANY INPUT CHARACTERS + JRST STATY2 ;NOT INCLUDING COM MODE ECHO + MOVE E,TIOP(A) +STATY3: CAMN E,TIBEP(A) + SUBI E,TIBL + ILDB TT,E + TLNN TT,%TXIGN + TRZA D,1_<9+1> ;INPUT SEEN, BUF CAP NOT EMPTY + SOJG B,STATY3 +STATY2: CAIL B,TIBS-10. + TRO D,1_9. ;BUF CAP NEARLY FULL + LDB B,[400400,,TTYTYP(A)] ;GET LOCAL AND 340 MDS + DPB B,[160400,,D] ;DEPOSIT IN STATUS WORD + CONO PI,TTYOFF + MOVE TT,TICC(A) + CAMLE TT,TINTC(A) + TRO D,20000 ;MORE CHRS HAVE BEEN ITYI'ED THAN .IOT'ED + CONO PI,TTYON + JRST STATY1 + +;TELETYPE IO PUSHDOWN ROUTINES + +TYOIOP: TDZA A,A ;OUUTPUT CHNL. +TYIIOP: MOVEI A,TYIMSK-TYOMSK ;INPUT CHNL, SET TYIMSK INSTEAD TYOMSK. + CONO PI,CLKOFF ;TO PREVENT TELETYPE (IF CONSOLE) FROM MOVING AROUND + JUMPGE B,TYIOP1 ;JUMP IF OPEN AS DEVICE + SKIPGE TTYTBL(U) ;IF PROCEDURE DOESN'T HAVE CONSOLE, + JRST CLKONJ ;THEN THAT'S ALL +TYIOP1: LDB E,[$TIIDX,,B] ;GET TTY NUMBER IN E + ADDI E,(A) ;IF INPUT, TYOMSK(E) WILL BE TYIMSK VAR. + HRRZ R,UUAC(U) ;GET "AC FIELD" (IO PUSHDOWN ROUTINES RESTORE R) + MOVE A,CHNBIT(R) ;GET RELEVANT CHANNEL INTERRUPT BIT + XCT TYIOPT(I) ;IORM OR ANDCAM A TO TYOMSK(E) + JRST CLKONJ ;RETURN + +TYIOPT: ANDCAM A,TYOMSK(E) ;IOPUSH (PSEUDO-CLOSE) + IORM A,TYOMSK(E) ;IOPOP (PSEUDO-OPEN) + +;STY IO PDL ROUTINES + +STYOIP: TDZA A,A +STYIIP: MOVEI A,STYMSK-STYOMS + ADDI A,STYOMS-NFSTTY-TYOMSK + JRST TYIOP1 + +SUBTTL TTY CLOSE ROUTINES + +;INPUT CLOSE + +TYICLS: JSP E,TYCLOS ;IGNORE FOR DISOWNED CONSOLE + ANDCAM B,TYIMSK(A) ;INDICATE CHANNEL CLOSURE + JRST TYICL2 + +TYCLOS: LDB I,[210100,,A] + ANDI A,77 ;THROW AWAY TOP BITS OF IOCHNM WD, GET TTY #. + CAIN A,%TINON ;FOR A CHNL IN A TTYLESS TREE, + POPJ P, ;DON'T SOS ANYONE'S TTNTO. + SKIPGE APRC(U) ;SKIP UNLESS DISOWNED + JUMPN I,[JRST 4,.] ;DISOWNED JOB HAS REAL CONSOLE TTY? + SKIPGE TTYTBL(U);IF IT'S A CONSOLE AND THIS JOB DOESN'T + JUMPN I,TYICL2 ;HAVE TTY, DON'T CHANGE TYIMSK OR TYOMSK. + HRRZ R,UUAC(U) + MOVE B,CHNBIT(R) ;GET THE BIT TO CLEAR IN TYIMSK OR TYOMSK. + JRST (E) ;RETURN & CLEAR IT. + +;OUTPUT CLOSE + +TYOCLS: JSP E,TYCLOS ;IGNORE FOR DISOWNED CONSOLE + MOVE I,A + SKIPE USER + PUSHJ P,TYOWC ;WAIT A WHILE FOR OUTPUT TO FINISH + ANDCAM B,TYOMSK(A) ;SET OF OUTPUT CHNLS OPEN. +TYICL2: SOSLE TTNTO(A) + POPJ P, ;MORE OPENS ON TTY + SKIPE TTNTO(A) + BUG + MOVE B,TTYSTS(A) + TLNE B,%TSCNS + POPJ P, ;OPEN AS CONSOLE + JRST TTYLO1 + +;WAIT FOR TTY OUTPUT BUFFER TO BE EMPTY, +;BUT TIME OUT IF TTY DOESN'T TYPE OUT FOR 5 SEC. +TYOWC: MOVEM I,EPDL3(U) ;SAVE TTY # FOR TYOW5. +IFN N11TYS,[ + MOVE T,TTYTYP(I) + TRNE T,%TY11T + POPJ P, +] + MOVEI T,TOBS ;WAIT TILL OUTPUT BUFFER EMPTY + PUSHJ P,TYOW5 ;BUT DON'T WAIT TOO LONG. + POPJ P, ;TYOW5 MAY POP1J. + +;TTY # IN A - MAKE THE TTY FREE. +TTYLO1: SETZM TTNTO(A) + SETZM TYIMSK(A) + SETZM TYOMSK(A) + HRLOI B,%TSFRE + IORB B,TTYSTS(A) ;SAY TTY FREE (BUT TTYSTA OFF SO CAN'T ^Z) + PUSHJ P,TTYLFC ;REMOVE TTY FROM COM MODE AND + PUSHJ P,TYIRS0 ;RESET INPUT BUFFER +IFN TTLPTP,[ + CAMN I,LPTTTY ;IF TTY'S THE LPT, IT'S NOT IN USE. + SETOM LPTUSR +] + MOVE T,TTYTYP(I) + TRNN T,%TYSTY + PUSHJ P,TTYIN1 ;RE-INIT USER OPTIONS + TRNE T,%TYDIL\%TYRLM ;DIALUP LINE => MAKE IT PRINTING. + TRNE T,%TYMDM ;UNLESS WE CAN DETECT DISCONNECTS, IN WHICH CASE DO IT THEN. + CAIA + PUSHJ P,NCNSSP +IFN N11TYS,[ + TRNE T,%TY11T + PUSHJ P,NCNSST +] + MOVEI B,SCRCFM + SKIPL TTYSTA(I) + IORM B,SUPCOR ;REQUEST A CONSOLE-FREE MESSAGE. + MOVE A,I ;IN CASE OUR CALLER WANTS TTY # IN A. + POPJ P, + +IFN N11TYS,[ +TTYLO2: MOVE B,TTYTYP(A) ;TTY BEING CLOSED & CNSL FREE MSG NOT NEEDED, + SKIPGE TT11P ;IF IT'S A PDP11-TV TTY + TRNN B,%TY11T + POPJ P, + MOVE I,A ;MAKE ALL JOBS CEASE TO HACK THIS SCREEN + PUSHJ P,NTVWH1 ;B := VIDEO BUFFER NUMBER + BUG + SETZ A, +TTYLO3: LDB C,[$11BY0,,TVCREG(A)] ;VIDEO BUFFER HACKED BY THIS JOB OR 377 + CAMN C,B + SETOM TVCREG(A) ;IF JOB HACKING THIS VIDEO BUFFER, MAKE IT STOP. + ADDI A,LUBLK + CAMGE A,USRHI + JRST TTYLO3 + MOVE B,TT11HD ;TELL THE 11 THE TTY IS FREE. + ADDI B,1-NF11TY(I) + ADD B,TT1111 + HRROI T,-1_4+10 ;SET TTY'S PHYSLC WORD TO -1. + MOVEM T,(B) + MOVE T,TOBBP(I) ;RESET OUTPUT BUFFER POINTER TO BEGINNING OF + MOVEM T,TOIP(I) ; BUFFER. THE 11 DOES ALSO. + POPJ P, +] + +;REMOVE A TTY FROM COM MODE IF IT IS COM MODE. +;CALLED WHEN TTY BECOMES FREE, ETC. +;TAKES TTY # IN A; LEAVES IT IN A AND I. +TTYLFC: HRRZ I,A + CONO PI,TTYOFF + SKIPL Q,TTYCOM(I) + JRST TTLFC1 + PUSH P,I + PUSH P,U + PUSHJ P,TYCSET + TLZ Q,%TCCBK+%TCTPN+%TCCBS + MOVEM Q,TTYCOM(I) ;FLUSH COM MODE TEMP FLAGS. + PUSHJ P,TYCGTM ;REMOVE THE TTY FROM COM LINKS. + POP P,U + POP P,I +TTLFC1: MOVE A,I + MOVEI B,TTYI + MOVEM B,TTYIPC(A) + POPJ P, + +SUBTTL TTY RESET ROUTINES + +;TTY INPUT RESET + +TYIRS: PUSHJ P,TTYWR + POPJ P, ;IGNORE IF WE DON'T OWN THE TTY. +TYIRS0: MOVSI T,%TCLFT+%TCICO + PUSHJ P,TTYCMW ;MAYBE WAIT FOR COM LINK TO FINISH. RETURN WITH TTYCHN OFF. + PUSHJ P,TYIRS1 ;DISCARD THE INPUT. + JRST TTYONJ + +;; DISCARD THE CONTENTS OF THE TTY INPUT BUFFER. TTY NUMBER IN I. +TYIRS1: MOVE B,TIIP(I) ;Get input pointer. + MOVEM B,TIOP(I) ;Bash output ptr to it. + MOVEM B,TINTP(I) ;Bash interrupt-peeked ptr to it. + MOVEM B,ECHOP(I) ;Bash echo ptr to it. + SETZM ECHOC(I) ;Nothing to echo. + CLEARM TICC(I) ;Nothing has been input. + CLEARM TACC(I) ;No activation chars either. + CLEARM TINTC(I) ;Nothing to ITYIC either. + POPJ P, + +;OUTPUT RESET + +TYORS: PUSHJ P,TTYWR ;CHECK FOR OWNING TTY. TTY NUMBER IN I. + POPJ P, ;NON-SKIP MEANS NO; IGNORE THE .RESET. + SKIPL TTOALC(I) + PUSHJ P,UFLS + MOVSI T,%TCLFT+%TCOCO+%TCICO+%TCFPD ;ALSO WAIT FOR OUTPUT SEQ TO FINISH. + PUSHJ P,TTYCMW ;HANG UNTIL OUT OF COM MODE, OR OVER-RIDDEN. MAY UTCOFF. + MOVSI B,%TJCP1+%TJCP2+%TJSTP ;IF LAST CHAR THIS CHNL WAS ^P, + ANDCAM B,(R) ;FORGET IT. ALSO UNHANG CHANNEL FROM **MORE**. + MOVE TT,I + IMULI TT,TPLEN*2 + MOVEI B,%TFEOP+%TFIGL ;RESTORE BOTH PCS OF PPR TO NORMAL STATE. + ANDCAM B,TPFLAG(TT) + ANDCAM B,TPFLAG+TPLEN(TT) + MOVE B,TTYOPT(I) ;IS OUTPUT RESET SUPPOSED TO DO SOMETHING? + TRNN B,%TPORS ;(ON FAST TTYSS IT DOESN'T) + JRST UTCONJ + MOVE B,TTYCOM(I) + TLNE B,%TCECH + JRST UTCONJ +TYORS1: MOVE B,TOOP(I) ;SCAN BACKWARD 4 CHARS FROM TOOP TO SEE IF A %TDMOV + MOVEM B,TOIP(I) + MOVEI TT,TOBS-4 ;HAS BEEN PARTIALLY REMOVED FROM THE BUFFER. + MOVEM TT,TORM(I) ;TORM HAS THE RIGHT VALUE ASSUMING A %TDMOV APPEARS + ;JUST BEFORE TOOP - THE FIRST PLACE WE WILL LOOK FOR ONE. +TYORS4: LDB T,B + CAIE T,%TDMV0 + CAIN T,%TDMV1 + JRST TYORS8 + CAIN T,%TDMOV ;IF ONE IS FOUND IN THOSE 4 CHARS, IT MUST EXTEND PAST TOOP, + JRST TYORS5 ;SO TAKE TOOP AND INCREMENT IT TO GET NEW TOIP. + IBP B ;DBP B - KNOWING THAT THERE ARE 4 BYTES/WORD. + IBP B + IBP B + SUBI B,1 + CAMN B,TOBBP(I) + MOVE B,TOBEP(I) + AOS TT,TORM(I) ;AS THE %TDMOV GETS FARTHER BACK, ITS REMNANT OCCUPIES LESS SPACE. + CAIE TT,TOBS ;IF ITS REMNANT TAKES NO SPACE, FORGET ABOUT IT. + JRST TYORS4 + JRST TYORS6 + +TYORS8: ADDI TT,2 ;THIS REMNANT IS TWO CHARS LONG + CAIL TT,TOBS + JRST [ MOVEI TT,TOBS + MOVEM TT,TORM(I) + JRST TYORS6 ] + MOVEM TT,TORM(I) +TYORS5: SUBI TT,TOBS ;TT GETS - + MOVE B,TOOP(I) +TYORS7: CAMN B,TOBEP(I) ;SCAN FORWARD FROM TOOP TO FIND END OF REMNANT + MOVE B,TOBBP(I) + IBP B + AOJL TT,TYORS7 + MOVEM B,TOIP(I) ;AND FLUSH FROM BUFFER ALL BUT THAT REMNANT. +;DROPS THROUGH + ;DROPS IN +TYORS6: MOVE B,TCTYP(I) ;IF A "SOFTWARE" TTY, SEND A %TDORS. + CAIE B,%TNSFW + JRST [ MOVE B,TTYTYP(I) + TRNN B,%TYSTY ;ELSE, ON A STY, IF %SSORS + JRST TYORS2 + MOVE B,STYSTS-NFSTTY(I) + TLNN B,%SSORS + JRST TYORS2 + JRST .+1] ;THEN SEND %TDORS + SOS TORM(I) + MOVE B,TOIP(I) + CAMN B,TOBEP(I) + MOVE B,TOBBP(I) + MOVEM B,TOIP(I) ;CHECK FOR WRAP + MOVEI B,%TDORS ;RESET CODE + IDPB B,TOIP(I) + PUSHJ P,TYORS2 ;FINISH RESETTING, TURN TTYCHN BACK ON, + AOSN TTYOAC(I) ;AND ACTIVATE INT. LEVEL, SO %TDORS WILL BE SENT. + XCT TTYST(I) ;(THIS MAY TURN TTYCHN OFF AND ON AGAIN). + MOVE B,TTYOPT(I) + TRNN B,%TPCBS ;ON SOFTWARE TTY WITH ^\ TURNED ON, STOP TYPEOUT AT M.P. + POPJ P, ;LEVEL UNTIL THE TTY SAYS WHAT ITS CURSOR POSITION IS NOW, + HRRZS TTOALC(I) ;USING ^\^P... OR SCPOS + POPJ P, + +TYORS2: SKIPGE TT,TTYLPP(I) + SETCMB TT,TTYLPP(I) + SKIPL B,TTYIHP(I) ;AND UNDO MAIN PRGM CURSOR POS MVT + CAMGE B,TCMXH(I) + JRST TYORS3 + MOVE B,TCMXH(I) + SUBI B,1 + MOVEM B,TTYIHP(I) +TYORS3: MOVEM B,TPHP(TT) + MOVE B,TTYIVP(I) + CAML B,TCMXV(I) + BUG + MOVEM B,TPVP(TT) + SETOM TTYLPS(I) + JRST UTCONJ + +;SEND A %TDINI TO ALL TTYS. CALLED AT SYSTEM STARTUP. +TTRSAL: MOVSI I,-NCT +TTRSA1: MOVE T,TCTYP(I) + MOVE H,TTYOPT(I) + MOVE Q,TOIP(I) + CONO PI,TTYOFF + MOVEI A,%TDINI + PUSHJ P,TYOOU1 ;YES, SEND IT A REINIT CHARACTER + MOVEM Q,TOIP(I) + CONO PI,TTYON + AOSN TTYOAC(I) + XCT TTYST(I) ;AND MAKE SURE IT GETS SENT TO THE TTY +TTRSA2: AOBJN I,TTRSA1 + POPJ P, + +SUBTTL TV-11 INPUT PROCESSOR + +IFN N11TYS,[ +;CALL HERE FROM CLOCK LEVEL WHEN THERE IS INPUT FROM THE PDP-11. +;TAKE CHARACTERS FROM THE PDP11 AND CALL THE TTY INPUT INT. LVL. +;ROUTINES WITH THEM ONE AT A TIME. MAY CLOBBER ANY ACS. +TT11IN: SKIPL TT11P ;IF 11 DOWN, DON'T LOOK FOR INPUT FROM IT. + JRST TT11D1 + LDB TT,[$11WD0,,@TT11HD] + SETZM @TT11HD ;GET AND RESET CHAIN OF INPUT BUFFERS. +;HANDLE THE NEXT INPUT BUFFERFULL. PDP11 ADDRESS IN TT. +TT11I1: LSH TT,-2 ;CONVERT PDP11 ADDRESS TO PDP10 ADDR. + ADDI TT,TT11LO + MOVE A,(TT) ;GET -<# CHARS IN BUFFER> + ASH A,-24 + LDB I,[$11WD0,,2(TT)] ;GET # OF TTY THE CHARS ARE FOR. + CAML A,[-400] ;IF A OR I IS RIDICULOUS, + CAML I,TT1111 + JRST TT11LS ;ASSUME 11 HAS CRASHED. + JUMPG A,TT11LS + ADDI I,NF11TY + MOVEI B,3(TT) ;SET UP BP TO DATA AREA OF BUFFER. + HRLI B,$11WD1 ;EACH CHAR IS 16. BITS - A PDP11 WORD. + PUSH P,TT ;SAVE BUFFER ADDR SO CAN FIND NEXT BFR. + CAIL I,NF11TY+N11TYS + JRST [ MOVE A,I ;IF 11 KNOWS MORE TV'S THAN 10, IGNORE THOSE 10 ISN'T USING. + PUSHJ P,TTYLO2 ;AND IF THE 11 STARTS USING ONE, FREE IT SO USER ISN'T CONFUSED. + JRST TT11I3] + CONO PI,TTYOFF-1 + JUMPE A,TT11I4 + PUSH P,I + PUSH P,A + PUSH P,B +TT11I2: ILDB A,(P) ;GET NEXT CHAR FROM BFR, + MOVE I,-2(P) + PUSHJ P,NTYI5 ;PRETEND IT CAME FROM A TTY CONTROLLER INT., + AOSE -1(P) + JRST TT11I2 ;MORE CHARS => HANDLE THEM. + SUB P,[3,,3] +TT11I3: CONO PI,TTYON-1 + POP P,A ;ADDR. OF BUFFER JUST EMPTIED. + LDB TT,[$11WD1,,1(A)] ;GET ADDR OF NEXT BUFFER. + SETZB B,(A) ;THIS BUFFER NOW FREE. + DPB B,[$11WD1,,1(A)] + JUMPN TT,TT11I1 ;LOOK AT NEXT ONE, IF ANY. + POPJ P, + +TT11I4: PUSHJ P,TYPEND ;INPUT BUFFER WITH 0 CHARS SAYS OUTPUT BUFFER + JRST TT11I3 ;IS EMPTY, SO MAYBE REQUEST ECHOING. + +TT11LS: MOVEM A,TT11ER ;LEAVE DIAGNOSTIC INFO BEHIND + MOVEM I,TT11ER+1 + MOVEM TT,TT11ER+2 + MOVE A,(TT) + MOVEM A,TT11ER+3 + MOVE A,1(TT) + MOVEM A,TT11ER+4 + MOVE A,2(TT) + MOVEM A,TT11ER+5 +TT1LS1: SETZM TT11P ;MARK 11 DOWN AND DONT TRY TO COME BACK UP FOR NOW + MOVEI A,SCR11D ;MAKE SYS JOB PRINT "11 WENT DOWN" MESSAGE. + IORM A,SUPCOR +TT11D1: MOVEI A,TT11HD+1 ;MAKE SURE CLOCK LEVEL DOESN'T THINK + MOVEM A,TT11HD ;THAT THE 11 IS SENDING INPUT. + POPJ P, +] + +SUBTTL TERMINET MOTOR CONTROL + +;COME HERE FROM VERY SLOW CLOCK (2 MIN.), RUNNING IN SYS JOB. +;TURN OFF MOTORS OF ALL TERMINETS THAT HAVE BEEN IDLE 30. SEC. +;MAY CLOBBER ANY ACS. +TTTMNT: MOVE TT,TIME + SUBI TT,900. ;TT=30. SECONDS AGO. + CAIA +TTTMN2: MOVE TT,TIME ;TURN OFF ALL TERMINETS AT SYSTEM STARTUP. + MOVSI I,-NCT +TTTMN0: MOVE T,TCTYP(I) + CONO PI,TTYOFF + SKIPL SHUTDN + CAML TT,TTLTM(I) ;IF TTY HAS OUTPUT RECENTLY + CAIE T,%TNTRM ;OR ISN'T A TERMINET, + JRST TTTMN1 ;NOTHING TO DO. + MOVSI T,%TCMTR + TDNE T,TTYCOM(I) ;DITTO IF MOTOR ALREADY OFF. + JRST TTTMN1 + IORM T,TTYCOM(I) + MOVE H,TTYOPT(I) + MOVE Q,TOIP(I) + MOVEI A,%TDMTF ;PUT A MOTOR-OFF COMMAND IN OUTPUT BFR + PUSHJ P,TYOOU1 + MOVEM Q,TOIP(I) + CONO PI,TTYON + AOSN TTYOAC(I) + XCT TTYST(I) ;AND TELL INT. LVL. ABOUT IT. +TTTMN1: CONO PI,TTYON + AOBJN I,TTTMN0 + POPJ P, + +;CALL HERE WHEN ABOUT TO OUTPUT TO A TERMINET WHOSE MOTOR IS OFF +;TTY # IN I. LEAVES TTY'S TTYCOM IN Q. +TTTMTO: MOVE Q,TOIP(I) + MOVEI A,%TDMTN + MOVE H,TTYOPT(I) + PUSHJ P,TYOOU1 ;PUT MOTOR-ON CMD IN OUTPUT BFR, + MOVEM Q,TOIP(I) + MOVSI Q,%TCMTR ;MOTOR NOW ON AS FAR AS MAIN PRGM + ANDCAB Q,TTYCOM(I) ;IS CONCERNED. + POPJ P, + +SUBTTL PI-LEVEL ECHOING + +;ECHOING - CALLED AT CLOCK LEVEL. MAY CLOBBER ANY AC. +;ECHOES CHARS BY COPYING THEM FROM INPUT BFR TO OUTPUT BFR. +TTECH: MOVSI I,200000 ;GET LIST OF TTYS NEEDING ECHO, AND REINIT IT. + EXCH I,TTERQS +TTELUP: AOS NTTELU ;TAKE STATISTICS. + CAIL I,-1 + POPJ P, ;NO MORE TTYS NEED ECHOING. + ;I HAS IDX OF A TTY NEEDING ECHOING. +IFN N11TYS,[ + MOVE T,TTYTYP(I) + TRNE T,%TY11T + JRST TTELU3 +TTELU4: ] + MOVEI A,TOBS + MOVSI T,%TCECH + TDNE T,TTYCOM(I);CAN'T ECHO UNLESS OUTPUT BUFFER HAS ENOUGH ROOM, + MOVEI A,TYOWNC+1 + CAMG A,TORM(I) ;NO MAIN PROGRAM OUTPUT IN IT, + SKIPL TTOALC(I);OUTPUT NOT BLOCKED AT M.P. LEVEL, + JRST TTEDU4 + SKIPL TYOSW(I) ;AND NO MORE OUTPUT COMING SOON. + JRST TTEWAT ;PUT TTY BACK ON LIST. + MOVE H,TTYOPT(I) + MOVE Q,TTYCOM(I) + TLNE Q,%TCMTR ;IF TTY'S MOTOR IS OFF, TURN IT ON. + PUSHJ P,TTTMTO + MOVEI J,TTEDMY ;PROVIDE IOT RTNS WITH VARIABLE-BLOCK. + SKIPGE TT,TTYLPP(I) ;TT HAS IDX OF MOST RECENTLY USED PC PPR + SETCM TT,TTYLPP(I) ;WHETHER NOW ASSOCIATED OR NOT. + MOVE A,TPVB(TT) ;PERHAPS MOST RECENT PC PPR IS ECHO AREA, + CAMN A,TCMXV(I) ;BUT THERE'S NO ECHO AREA NOW. IN THAT CASE, + SUBI TT,TPLEN ;MAKE SURE DON'T TRY TO FORCE OUT BUFFERED CURSOR POS IN THAT PC PPR. +TTEDU2: TLZE Q,%TCDNG ;SHOULD BELL BE TYPED BECAUSE INPUT BFR FULL? + PUSHJ P,[MOVEM Q,TTYCOM(I) + MOVEI R,%TJECH+%TJMOR + MOVEI A,^G ;DING ON TTY IF DESIRED. + JRST TYO8] +TTELP1: SKIPN T,ECHOC(I) ;ANY CHARS TO BE ECHOED NOW IN INPUT BFR? + JRST TTEDUN ;NO, FINISHED ECHOING. + SKIPG T + BUG ;ECHOED MORE CHARS THAN THERE WERE? + AOS NTTEL1 +;NOW FIND NEXT CHARACTER NEEDING PI ECHO, +;AND MARK IT AS NO LONGER NEEDING IT. +;CAN EXIT TO TTEDU5 IF MUST STOP ECHOING BECAUSE ECHOING IS DEFERRED. + CONO PI,TTYOFF-1 ;PREVENT INTERACTION WITH INPUT INTERRUPTS. + MOVE B,ECHOP(I) +TTELP2: MOVE C,TICC(I) + CAMN B,TIIP(I) + JRST TTELBG + MOVE C,B + CAMN B,TIBEP(I) ;LOOK FOR 1ST CHAR NEEDING PI ECHO. + SUBI B,TIBL + ILDB A,B + TRZN A,%TXPIE + JRST TTELP2 + TRNN A,%TXIGN ;DON'T ECHO NON-COM-MODE CHARS + JRST [ MOVE T,TTYSTS(I) ;IF ECHOING BEING DEFERRED. + TLNE T,%TSNOE + TLNE H,%TOHDX ;BUT IF HALF-DUPLEX, IT ECHOES IN ANY CASE. + JRST .+1 + JRST TTEDU5] + SOSGE ECHOC(I) ;FOUND ONE; NOW ECHO IT. + BUG + MOVEM B,ECHOP(I) + DPB A,B ;MARK IT AS ECHOED. + LDB A,B ;CHECK FOR HARDWARE LOSSAGE. + TRNE A,%TXPIE + BUG ;DPB OR TRZN LOST?? + TRNN A,%TXIGN ;IF CHAR IS IN BFR ONLY TO BE ECHOED, + JRST TTELP5 + CAMN C,TIOP(I) ;IF IT'S 1ST CHAR IN CUFFER, + JRST [ PUSHJ P,TYIRE1 ;REMOVE IT THE NORMAL WAY. + JRST TTELP5] + CAMN B,TIIP(I) ;IF CHAR IS LAST CHAR IN BFR, + PUSHJ P,TTEBAK ;DELETE IT, & MAYBE OTHERS BEFORE IT. +TTELP5: CONO PI,TTYON-1 +;DECIDE WHICH PC PPR TO USE. + MOVE T,I + IMULI T,2*TPLEN ;COMPUTE INDEX OF M.P. PC-PPR. + SKIPGE Q,TTYCOM(I) ;COM MODE, UNLESS %TCICO OR %TCLFT, MEANS USE M.P. AREA. + TDNE Q,[%TCICO+%TCLFT,,400000] + MOVE T,TTYEPP(I) ;OTHERWISE USE THE ECHO AREA IF ANY. + MOVE B,TTYSTS(I) + TRNN A,%TXECI + TRNN A,%TXIGN ; FOR ^_ COMMANDS, DON'T OBEY %TSNEA. + TLNN B,%TSNEA ; %TSNEA SAYS USE M.P. AREA. + JRST TTELP4 + MOVE T,I + IMULI T,2*TPLEN +TTELP4: SKIPGE TT,TTYLPP(I) ;TT GETS LAST PC PPR HACKED WITH THIS TTY. + SETCA TT, + CAMN TT,T ;IF WE ARE SWITCHING TO A DIFFERENT PC PPR, + JRST TTELU1 + SKIPL TTYLPP(I) ;DISASSOCIATE THE OLD ONE IF NEC. + PUSHJ P,TYOMVC +TTELU1: MOVE TT,T ;MOST RECENT PC PPR NOW ECHOING PC PPR. + MOVSI Q,%TCECH ;NOW DEFINITELY GOING TO PUT CHARS IN OUTPUT BUFFER + IORB Q,TTYCOM(I) + MOVEI R,%TJECH+%TJMOR + TLNN H,%TOHDX ;ON HALF-DUPLEX TTYS, EXCEPT FOR + JRST TTELP3 + TRNN A,%TXCOM ;CHARS PRODUCED BY COM LINKS, + PUSHJ P,[IORI R,%TJHDE + JRST TYOAS5] ;MOVE CURSOR BUT DON'T REALLY OUTPUT. + ;THUS, CURSOR MOTION DUE TO ECHOING BY TTY + ;IS ACCOUNTED FOR. +TTELP3: LDB B,[.BP %TXASC,A] + TRNE A,%TXECI + JRST TTELP6 + TRZE A,%TXIGN + CAIE B,^L ;^L ECHOED IN COM MODE SHOULD CLEAR SCREEN. + TRZA R,%TJCP1 + JRST [ MOVEI A,"C ;(BY SIMULATING A ^PC). + IORI R,%TJCP1 + JRST .+1] +TTELP6: ANDI A,%TXCTL+%TXMTA+%TXSUP+%TXTOP+%TXASC + PUSHJ P,TYO8 + TRZE R,%TJHDE + PUSHJ P,TYOMVC + SKIPN ECHOC(I) + JRST TTEDUN +IFN N11TYS,[ + TRNE H,%TP11T + JRST [ PUSHJ P,TYOWN1 + LDB B,T + CAIE B,1_TT11BY-1 + JRST TTEDU6 ;LESS THAN 20. FREE SPACES IN BFR => GIVE UP. + JRST TTELP1] +] + MOVE A,TORM(I) + CAIGE A,TYOWNC ;IS THERE A CHANCE OUTPUT WOULD HANG UP? + JRST TTEDU4 ;YES, WAIT UNTIL LATER TO ECHO THE REST. + JRST TTELP1 ;NO, ECHO MORE + +TTELBG: BUG PAUSE,[ECHOC is ],OCT,T,[ but ECHOP equals TIIP. TICC=],OCT,C,[. TTY ],OCT,I + SETZM ECHOC(I) +;COME HERE WHEN ALL ECHOING DESIRED ON THIS TTY WAS DONE. +TTEDUN: CONO PI,TTYOFF-1 + SKIPE ECHOC(I) + JRST TTEDU1 +TTEDU5: MOVE Q,TTYCOM(I) + TLNE Q,%TCDNG ;HAS ANOTHER REASON TO ECHO ARISEN AFTER WE CHECKED? + JRST TTEDU1 ;YES, GO PROCESS IT. + PUSH P,TTYERQ(I);SAVE NEXT TTY TO ECHO ON + SETOM TTYERQ(I) ;AND TURN OFF THIS ONE'S ECHO REQUEST + CONO PI,TTYON-1 + SETZ R, + CAME TT,TTYLPP(I) + PUSHJ P,TYOFRC ;FORCE OUT BUFFERED CURSOR MOTION. + POP P,I + JRST TTELUP + +TTEDU4: +TTEDU3: SETO A, ;NO, MOVE TO NEXT TTY ON LIST. + EXCH A,TTYERQ(I) + MOVE I,A + JRST TTELUP + +TTEDU1: CONO PI,TTYON-1 + JRST TTEDU2 + +;COME HERE WHEN CAN'T ECHO BECAUSE TYOSW IS LOCKED. +TTEWAT: AOS NTTEWA + MOVE A,I ;IF WE CAN'T DO ANY. + CONO PI,TTYOFF-1 + EXCH A,TTERQS ;PUT THIS TTY BACK ON LIST, + EXCH A,TTYERQ(I) ;SO IT WIL BE REEXAMINED NEXT TICK. + CONO PI,TTYON-1 + MOVE I,A ;MOVE TO NEXT TTY ON OLD LIST. + JRST TTELUP + +IFN N11TYS,[ +TTELU3: SKIPL TT11P + JRST TTEDU4 ;DON'T ECHO ON PDP11 TTYS IF PDP11 DOWN. + LDB A,TOIP(I) ;DEFER ECHOING UNLESS OUTPUT BFR EMPTY. + CAIN A,1_TT11BY-1 + JRST TTELU4 ;JUMP IF BUFFER EMPTY (LAST CHAR OUTPUT CHANGED TO -1) +TTEDU6: JRST TTEWAT ;TEMPORARY PATCH +.ERR IS THIS PATCH TEMPORARY OR PERMANENT? + MOVE A,TT11HD ;BFR NOT EMPTY: TELL 11 + ADDI A,1-NF11TY(I) ;(BY SETTING ECOFLG) + ADD A,TT1111 + MOVSI B,400000 ;TO SIGNAL TEN WHEN THE BUFFER BECOMES EMPTY. + IORM B,(A) .SEE TT11I4 + JRST TTEDU4 +] +;COME HERE WHEN ARE JUST ABOUT TO ECHO THE LAST CHAR +;IN THE INPUT BUFFER, AND ITS %TXIGN IS SET. +;TRY TO FLUSH THE CHARACTER FROM THE INPUT BFR, +;AND ALSO THE CHARS BEFORE IT, IF THEY TOO HAVE %TXIGN. +TTEBAK: SKIPE C,ECHOC(I) + BUG PAUSE,[ECHOING LAST CHAR BUT ECHOC IS ],OCT,C,[. TTY ],OCT,I + SETZM ECHOC(I) + IBP B ;THIS DEPENDS ON 18-BIT BYTES IN INPUT BUFFER. + SUBI B,1 + CAMN B,TIBEP-1(I) + ADDI B,TIBL + SOSN TICC(I) + JRST TTEBA1 + LDB C,B + TRNE C,%TXIGN + JRST TTEBAK +TTEBA1: MOVE C,TIIP(I) + CAMN C,TINTP(I) + MOVEM B,TINTP(I) + CAME C,ECHOP(I) + BUG + MOVEM B,ECHOP(I) + MOVEM B,TIIP(I) + POPJ P, + +SUBTTL TTY INTERRUPT HANDLING + +;MACRO TO SAVE ACS AND CONI APR ON ENTERING A TTYCHN INTERRUPT ROUTINE. +;PCLOC SHOULD BE THE ADDRESS OF THE STORED PC, WHICH IS MOVED TO TTYBRK. +DEFINE TTYSAV PCLOC=TTYBRK +IFN KL10P,[ + CONSO PI,1_<7-TTYCHN> + JRST 4,. ;HARDWARE BUG ALLEGEDLY FIXED +] +IFN KA10P, CONI TTYAPC + MOVEM A,TTYA + MOVE A,[B,,TTYACS] + BLT A,TTYACS+17-B+1-1 ;SAVE ALL ACS BUT 0 +IFSN PCLOC,TTYBRK,[ + MOVE A,PCLOC + MOVEM A,TTYBRK +] + MOVE P,TTYPDP + PUSH P,[TTYRET] +TERMIN + +EBLK + +TTYBRK: 0 + +BBLK + TTYSAV ;SAVE ACS AND SET UP P. +IFN KL10P,[ + CONSZ DTE,%DBL10+560 + JRST TTDTE1 ;DTE20 INTERRUPTED (DOORBELL OR BYTE TRANSFER ERROR OR DONE) +] ;KL10P +IFN DL10P,[ + CONSZ DLC,10 + JRST TTDLB0 ;DL10 INTERRUPTED +] +IFN TK10P,[ + CONSZ NTY,200000 + JRST NTY1 ;NEW TELETYPE KLUDGE +] +IFN MTYP,[ + CONSZ MTY,50 + JRST MTY1 ;MORTON BOX +] +IFN DPKPP,[ + CONSZ DPK,60 + JRST DPKPE ;PARITY ERROR OR NXM + CONSZ DPK,10 + JRST DPTI1 ;CHAR AVAIL DPK + CONSZ DPK,400 + JRST DPTO1 ;OUTPUT BUFFER FIN DPK +] +IFN NOTYS,[ + MOVEI I,0 + CONSZ TTY,50 + JRST GOTTY +] +IFN NDZTYS,[ +;DZ-11 Code The only place that emulates an interrupt on the TTY interrupt +; channel is the DTE code, handled above, so there should never be a +; need for a DZ11 entry here. +] +; MOVEI J,TTYCHN ;KNIGHT TTY KLUDGE GENERATES SPUR INTS +; JSP E,SPUR ;SPURIOUS INT +TTYRET: +TTYRT3: +IFN KA10P,[ + CONI A + ANDCM A,TTYAPC + TRNE A,220000 ;DID MPV OR PDL OV COME ON DURING THIS INT? + BUG PAUSE,[MPV OR PDL OV IN TTY INT HANDLER, APR CONI=],OCT,A +] ;KA10P + MOVS A,[B,,TTYACS] + BLT A,17 + MOVE A,TTYA + JRST 12,@TTYBRK + +IFN DPKPP,[ +DPKPE: AOS NDPKPE + CONO DPK,60+TTYCHN ;PARITY ERROR OR NXM + JRST TTYRT3 +] + +IFN DZ11P,[ ;DZ-11 Code + +IFE KS10P, .ERR DZ11 code only works on a KS-10. + +$INSRT DZ11 + +REPEAT DZ11NB,[ + +EBLK +CONC DZ,\.RPCNT,RB: 0 +BBLK + MOVEM U,TTYACS-B+U + JSP U,DZRBK + ;; ,,: + NFDZTY+,,CONC DZ,\.RPCNT,BA + +EBLK +CONC DZ,\.RPCNT,XB: 0 +BBLK + MOVEM U,TTYACS-B+U + JSP U,DZXBK + ;; ,,: + NFDZTY+,,CONC DZ,\.RPCNT,BA + +];DZ11NB + +DEFINE DZSAV + MOVEM A,TTYA + MOVE A,[B,,TTYACS] + BLT A,TTYACS-B+ ;SAVE ALL ACS BUT 0, A AND U... + MOVE A,-3(U) ;Get return address + MOVEM A,TTYBRK ;Save it in TTYBRK + MOVE P,TTYPDP ;Stack + PUSH P,[TTYRET] ;Set up return address + HRRZ C,(U) ;Get Unibus address + HLRZ I,(U) ;Get ITS TTY # of first DZtty on this board +TERMIN + +; DZ11 receiver interrupts (actually silo overflow) +DZRBK: DZSAV ;Save ACs and setup parameters + IORDI A,%DZRCS(C) + TRNN A,%DZCRD ;Character ready? + JRST [ AOS DZRSPR ;Count spurious interrupts + POPJ P, ] +DZRBK1: IORDI A,%DZRDR(C) + TRNN A,%DZDDV ;Data valid? + POPJ P, ;Nope, got it all + ; If parity must be hacked, it should be done here + LDB D,[.BP %DZLM,A] ;Get line number + ANDI A,%DZTCM ;Get character + ADD I,D ;Get TTY number + CAIL I,NFDZTY+NDZTYS + BUG + JRST NTYI1 + +; The following code can't work because I found the place where NTYI1 +; clobbers U (Alan 3/26/86): +; +; PUSHJ P,NTYI1 ;Process the input +; HRRZ C,(U) ;Get Unibus address +; HLRZ I,(U) ;Get ITS TTY # of first DZtty on this board +; JRST DZRBK1 + +; DZ11 transmitter interrupts +DZXBK: DZSAV ;Save ACs and setup + AOS DZXINC ;Count interrupts +DZXBK1: IORDI A,%DZRCS(C) + TRNN A,%DZCTR ;Transmitter ready? + POPJ P, + LDB D,[.BP %DZLM,A] ;Get line number + ADD I,D ;ITS terminal number of this line + CAIL I,NFDZTY+NDZTYS + BUG + AOS DZXCHC ;Count characters sent + PUSHJ P,TYPSC ;Merge with the rest of the world + HRRZ C,(U) ;Get UB address of board again + HLRZ I,(U) ;Get ITS TTY # of first DZtty on this board + JRST DZXBK1 ;Try to send another, maybe we'll get lucky + +];DZ11P + +IFN KL10P,[ +;HANDLE INTERRUPTS FROM THE CONSOLE PDP11 VIA THE DTE20 +;CODE FOR HANDLING MULTIPLE CONSOLES, BLOCK TTY OUTPUT, ETC. +;IN THE FUTURE ETHERNET STUFF WILL GET ADDED HERE. + +TTDTE1: CONI DTE,DTECNI ;SAVE FOR DEBUGGING + CONSZ DTE,460 ;TO11 ERROR OR TO10 DONE OR TO10 ERROR + BUG PAUSE,[DTE20 ERROR, CONI=],OCT,DTECNI + CONSZ DTE,100 ;TO11 TRANSFER COMPLETE + JRST [ CONO DTE,100 ;CLEAR TO11 TRANSFER COMPLETE + SETZM DTEBBY ;BUFFER NO LONGER BUSY + JRST .+1 ] + CONO DTE,%DBL10+40 ;CLEAR DTE20 INTERRUPTING STATE + SKIPGE A,DTETYI ;CHECK FOR TTY INPUT AVAILABLE + JRST TTDTE2 + SETOM DTETYI ;AVAILABLE. INDICATE HAS BEEN GOTTEN. + CONO DTE,%DBL11 ;SIGNAL 11 THAT WE'RE READY FOR MORE. + HLRZ I,A ;GET LINE NUMBER + CAIL I,NFETY ;CHECK IT + CAIL I,NFETY+NETYS + BUG PAUSE,[BAD TTY NUMBER ],OCT,I,[FROM PDP-11] + PUSHJ P,NTYI1 ;PROCESS THE INPUT + JRST TTDTE1 ;CHECK FOR MORE + +TTDTE2: MOVEI A,SCRHNG ;IF HANGUP/DIALIN, SIGNAL SYSTEM JOB TO HANDLE IT + SKIPL DTEHNG + IORM A,SUPCOR + SKIPN DTEBBY ;DON'T CHECK FOR OUTPUT DONE IF BUFFER BUSY + SKIPGE A,DTEODN ;CHECK FOR TTY OUTPUT DONE + POPJ P, ;NOTHING, DISMISS INTERRUPT + SETOM DTEODN ;INDICATE SIGNAL HAS BEEN RECEIVED + HLRZ I,A ;GET LINE NUMBER + CAIL I,NFETY ;CHECK IT + CAIL I,NFETY+NETYS + BUG PAUSE,[BAD TTY NUMBER ],OCT,I,[FROM PDP-11] + HRRZS A ;SET UP MULTI-CHARACTER TRANSFER, + HRRZ B,TTOALC(I) ;SETTING MAX# CHARACTERS FROM ELEVEN'S BUFFER SIZE + CAIGE B,(A) ;DON'T SEND MORE CHARACTERS THAN ALLOCATED + MOVE A,B + CAILE A,DTEOBL ;DON'T EXCEED SIZE OF OUR BUFFER + MOVEI A,DTEOBL + MOVEM A,DBBCC + MOVEM A,DBBCC1 + MOVE A,[441000,,DTEOBF] + MOVEM A,DBBBP + JRST TYP ;GO FILL OUTPUT BUFFER +];KL10P + +IFN DL10P,[ +;HANDLE THE DL-10 (A PDP-11 FRONT END FOR THE KL-10). +;ALL INTERRUPTS FROM DL-10 COME HERE. + +TTDLB0: CONO DLC,10+TTYCHN ;CLEAR INTERRUPT FLAG + SKIPN DL10F ;IGNORE DL10 IF IT IS MARKED OUT OF SERVICE. + POPJ P, +IFN CHAOSP, IFN DLCP, PUSHJ P,DLCWAK ;SEE IF INTR IS FOR CHAOS NET +IFN T300P,[ ;CHECK FOR T-300 INTERRUPT, PASS TO DISK LEVEL IF SO + SKIPE DSCDON + CONO PI,DSKRQ +];T300P + SKIPE I,DL10IL ;IS INPUT AVAIL? IF SO, READ WHICH LINE + PUSHJ P,TTDLIN ;AND PROCESS THE CHARACTER. + MOVEI A,SCRHNG ;DOES THE 11 SAY A MODEM WAS DISCONNECTED? + SKIPE DL10CL + IORM A,SUPCOR ;IF SO, TELL SYS JOB TO TAKE APPROPRIATE ACTION. + SKIPN DL10LN ;DON'T CHECK OUTPUT-DONE IF OUTPUT BUFFER IS BUSY + SKIPN I,DL10OD ;OUTPUT DONE ON SOME TTY? + POPJ P, + MOVE A,DL10BS ;YES, GET 11'S BUFFER SIZE AND + SETZM DL10OD ;MAKE COMMUNICATION CHANNEL FREE FOR -11 AGAIN + HRRZ B,TTOALC(I) + CAMLE A,B + MOVE A,B ;DON'T SEND MORE CHARACTERS THAN TERMINAL HAS ALLOCATION FOR + MOVEM A,DBBCC ;INIT CHARACTER COUNTERS TO SIZE OF BUFFER IN 11 + MOVEM A,DBBCC1 + MOVE A,[441000,,DL10BF] + MOVEM A,DBBBP ;INIT B.P. USED BY 10 TO STORE INTO BUFFER. + JRST TYP ;GO FILL UP THE OUTPUT BUFFER + +TTDLIN: MOVE A,DL10IC ;GET THE CHARACTER TYPED IN + SETZM DL10IL ;FREE THE INPUT CHANNEL SO 11 CAN USE IT AGAIN. + CONO DLC,100040+TTYCHN ;INTERRUPT 11 + JRST NTYI1 ;AND PROCESS THE INPUT. +] + +IFN DPKPP,[ +DPTO1: CONI DPK,A + LDB I,[220400,,A] + ADDI I,NFDPTY + SKIPL @DPKC-NFDPTY(I) + SETOM @DPKC-NFDPTY(I) + LDB J,[$TTOSP,,TTYTYP(I)] ;GET OUTPUT SPEED CODE. + CAIL J,LDPSPT + MOVEI J,LDPSPT-1 + HRRZ A,TTOALC(I) + CAMLE A,DPSPT(J) + MOVE A,DPSPT(J) ;# CHARS BUFFER SPACE FOR THAT SPEED. + MOVEM A,DBBCC + MOVEM A,DBBCC1 + MOVE A,DBBFP-NFDPTY(I) + MOVEM A,DBBBP ;BP FOR STORING CHARS. + MOVSM A,@DPKP-NFDPTY(I) + JRST TYP0 + +DPTI1: DATAI DPK,A + LDB I,[220400,,A] + ADDI I,NFDPTY + JRST NTYI1 +] +IFN TK10P,[ +NTY1: CONSZ NTY,400000 + POPJ P, ;SCANNER NOT STOPPED + CONI NTY,I ;READ IN TTY # +IFE NNTYS-10,LDB I,[110300,,I] +IFE NNTYS-20,LDB I,[100400,,I] +IFN *,.ERR + CAIL I,NNTYS + BUG + ADDI I,NFNTY ;CALCULATE CONSOLE # + CONO NTY,@TTYLT(I) ;SELECT APPROPRIATE TTY + CONSZ NTY,20 + JRST TYPSC ;DONE FLAG ON TYPEOUT + CONSO NTY,40 + JRST TTYRT2 ;THIS TTY NOT REALLY UNHAPPY + DATAI NTY,A + JRST NTYI1 + +TTYRT2: CONO NTY,200000+TTYCHN + JRST TTYRET +] + +IFN MTYP,[ +MTY1: CONI MTY,I + LDB I,[140500,,I] ;GET SUBDEVICE + CAIL I,NMTYS + JRST MTY2 ;NOT A VALID # + ADDI I,NFMTY + CONO MTY,@TTYLT(I) + CONSO MTY,40 ;INPUT DONE + JRST MTY6 + DATAI MTY,A + JRST NTYI1 + +MTY6: CONSO MTY,10 ;OUTPUT DONE + POPJ P, + HRRZ A,TTOALC(I) + CAILE A,MTYNC + MOVEI A,MTYNC + MOVEM A,DBBCC ;# CHARS CAN GIVE AT ONCE. + MOVEM A,DBBCC1 + SETZM MTYOW ;SET UP WORD TO FILL WITH OUTPUT CHARS. + MOVE A,[440700,,MTYOW] + MOVEM A,DBBBP ;SET UP BP FOR STUFFING THAT WORD. + JRST TYP + +MTY2: CONSZ MTY,10 + JRST MTY3 ;OUTPUT + CONSZ MTY,40 + DATAI MTY,A ;INPUT + POPJ P, ;AND IGNORE + +MTY3: LSH I,12. + CONO MTY,200+TTYCHN(I) ;CLEAR OUTPUT DONE FLAG + POPJ P, +] + +IFN NOTYS,[ +GOTTY: CONSZ TTY,10 + JRST TYPSC ;TTO DONE + CONSO TTY,40 + POPJ P, ;NONE + DATAI TTY,A ;TTI DONE, READ CHR + JRST NTYI1 +] + +;PROCESS INPUT INTERRUPT WITH CHARACTER IN A, TTY # IN I + +OVHMTR TTI ;TTY INPUT INTERRUPT LEVEL + +;ENTER HERE FOR "HARDWARE" TTYS, LOW 8 BITS OF A ARE THE INPUT, OTHER BITS ARE GARBAGE +NTYI1: +IFN NNVTTS,[ + CAME I,NOVATT ;SKIP IF THIS TTY IS NOVA + JRST NTYI3 + TRZE A,200 ;SKIP IF DATA AND NOT TTY # + JRST NTYI2 ;SET TTY # + SKIPGE I,NVIPTT ;CURRENTLY SELECTED CONSOLE ON INPUT + POPJ P, ;NONE SELECTED +NTYI3:] +IFN TTLPTP,[ + CAMN I,LPTTTY + JRST INLPT +] + ANDI A,377 ;FLUSH EXTRANEOUS BITS, KEEP LOW 7 + MOVE H,TTYOPT(I) + TRNN H,%TPMTA ; OR KEEP LOW 8 IF 8TH IS HARDWARE META KEY + ANDI A,177 +;ENTER HERE FOR TTYS WHICH MAY INPUT IN FULL-CHARACTER-SET +NTYI5: MOVEM I,LOCTTY ;TTY CHAR ACTUALLY TYPED ON + MOVSI U,%TSLCZ + ANDCAB U,TTYSTS(I) ;CLEAR LAST CHR ^Z BIT + MOVE Q,TTYCOM(I) + MOVE R,TTYTYP(I) + MOVE H,TTYOPT(I) + TRNE H,%TPMTA ;PROCESS HARDWARE META KEY IF PRESENT + TRZN A,200 + CAIA + IORI A,%TXMTA + ANDI A,%TXCTL+%TXMTA+%TXSUP+%TXTOP+%TXASC ;FLUSH MEANINGLESS BITS. + TLNE H,%TOALT ;IF THIS TTY WANTS IT, MAYBE STANDARDIZE ALTMODES + PUSHJ P,TTYSAM + HRRZ D,TTYIPC(I) + MOVEM D,LTTYIPC ;REMEMBER INPUT RTN FOR DEBUGGING + MOVE D,TYBPC(I) + MOVEM D,LTYBPC + JRST (D) ;PROCESS THE CHARACTER AND RETURN. + +IFN NNVTTS,[ +NTYI2: JUMPE A,CPOPJ + ADDI A,NFNVTY + CAIGE A,NFNVTY+NNVTTS + MOVEM A,NVIPTT ;SELECT CONSOLE + POPJ P, +] + +IFN TTLPTP,[INLPT: MOVE A,TIME + MOVEM A,LPTTIME + POPJ P, +] + +SUBTTL HANDLE ^\ CODES +;OR PASS CHARACTERS ON TO NEXT LEVEL OF INPUT +;PROCESSING IF NO ^\ CODE IS IN PROGRESS. + +;THIS IS THE NORMAL VALUE OF TYBPC FOR ALL TTY'S; IT IS THE ONLY POSSIBLE VALUE +;FOR A TTY WHOSE %TPCBS AND %TPTEL ARE 0. +TYBN: TRNE H,%TPPRN + PUSHJ P,TYBPRN + TRNN H,%TPCBS+%TPTEL + JRST TYBRT2 ;IF NOT ENABLED, JUST PASS CHAR TO NORMAL INPUT LEVEL. +; USED TO CLEAR %TXSFT (NOW %TXSUP) BEFORE CHECKING FOR ^\ +; MOVEI E,(A) +; ANDCMI E,%TXSUP + CAIN A,^\ + TRNN H,%TPCBS + JRST TYBCR1 ;IF NOT AN ENABLED ^\, GO CHECK FOR SPECIAL CR HANDLING + JSP D,TYBRED ;READ THE CHARACTER AFTER THE ^\ + CAIGE A,100 ;^\ FOLLOWED BY @ THROUGH _ IS THE HIGH BITS FOR THE NEXT CHARACTER. + JRST TYBCTL ;^\ FOLLOWED BY A CONTROL CHAR, ETC. IS A SPECIAL HACK. + ANDI A,<%TXCTL+%TXMTA+%TXSUP+%TXTOP>_-7 + LSH A,7+18. ;GET THE EXCESS OVER 100 AND SHIFT BY 7, + HRRI A,TYBPFX ;AND STORE IN LH OF TYBPC + MOVEM A,TYBPC(I) + POPJ P, ;RETURN. NEXT CHAR COMES TO TYBPFX + +TYBPFX: HLRZ D,TYBPC(I) ;GET THE HIGH BITS READ IN LAST TIME + IOR A,D ;AND MERGE INTO THE CHAR JUST READ IN +TYBRET: MOVEI D,TYBN ;RESET ^\ STATUS TO NORMAL +TYBRT1: MOVEM D,TYBPC(I) +TYBRT2: MOVE E,TIME + MOVEM E,TTITM(I) ;UPDATE TIME OF LAST INPUT ON THIS TTY. +;NOW DETECT SPECIAL TOP-CHARS THAT SHOULD NOT ECHO +;AND SHOULD BE IGNORED IN COM MODE OR IN ^_ COMMANDS. + SETZ E, ;WE SET E TO -1 BELOW FOR THOSE CHARACTERS. + MOVE D,TTYSTA(I) + TLNE D,%TANEC ;IF COUNT OF DON'T-ECHO CHARS IS >0, + JRST [ SUB D,[<.DPB 1,.BP %TANEC>,,] ;DECREMENT IT + SETO E, ;AND DON'T ECHO THIS ONE. + JRST TYBRT3] + MOVE E,A ;IS THIS INPUT REALLY FOR LOCAL EDITING PROTOCOL? + ANDI E,%TXTOP+%TXASC ;THAT IS, TOP-E OR TOP-S, OR THE CHARACTER FOLLOWING ONE? + CAIE E,%TXTOP+"E + CAIN E,%TXTOP+"S ;DON'T ECHO OR INTERRUPT FOR TOP-S OR TOP-E, + TLO D,<.DPB 1,.BP %TANEC> ;OR THE CHAR THAT FOLLOWS IT. + CAIN E,%TXTOP+"T ;DON'T ECHO OR INT FOR TOP-T, OR FOLLOWING 3 CHARS. + TLO D,<.DPB 3,.BP %TANEC> + CAIE E,%TXTOP+"Y ;GRAPHICS INPUT CMDS TAKE 5 ARG CHARS. + CAIN E,%TXTOP+"X + TLO D,<.DPB 5,.BP %TANEC> + SETZ E, + TLNE D,%TANEC + SETO E, +TYBRT3: MOVEM D,TTYSTA(I) + MOVEM E,LEPCHR ;LEPCHR IS -1 FOR SPECIAL CHARS THAT SHOULD USUALLY BE IGNORED. + HRRZ D,TTYIPC(I) + JUMPE E,(D) ;IN WHICH CASE, DROP THIS CHAR ENTIRELY + CAIN D,TTYI ;IF IT IS NOT THE NORMAL SORT OF INPUT. + JRST (D) + POPJ P, + +;COME HERE FOR ^\ FOLLOWED BY A CHARACTER < 100. +TYBCTL: CAIN A,^A ;^\^A => ALLOCATE OUTPUT CHARS. + JRST TYBA + CAIN A,^Z ;^\^Z => ZERO ALLOCATION + JRST TYBZ + CAIN A,^I ;^\^I => INFINITY ALLOCATION + JRST TYBI + CAIN A,^R ;^\^R => RESTART OUTPUT AT M.P. LEVEL. + JRST TYBR + CAIN A,^P ;^\^P => SET CURSOR POSITION AND RESTART OUTPUT AT M.P. LEVEL. + JRST TYBP + CAIN A,^\ ;^\^\ => INPUT A ^\. + JRST TYBRET + CAIN A,^C ;^\^C => SCREEN HAS BEEN SURREPTITIOUSLY CHANGED + PUSHJ P,TYBC +;RETURN TO NORMAL ^\ STATUS BUT DON'T PASS ANY INPUT UP TO NORMAL INPUT LEVEL. +TYBXIT: MOVEI D,TYBN +TYBRED: MOVEM D,TYBPC(I) ;JSP D,TYBRED TO WAIT FOR NEXT CHARACTER + POPJ P, + +TYBC: MOVSI D,%TSATY + IORB D,TTYSTS(I) + JUMPL D,CPOPJ + HLLZ E,MSKST(D) + TLZ E,#%PJATY + TLNE D,%TSCNS + IORM E,PIRQC(D) + POPJ P, + +TYBCR1: CAIN A,15 ;SEE IF ENABLED CR + TRNN H,%TPTEL + JRST TYBRT2 ;NO, JUST PASS CHAR TO NORMAL INPUT LEVEL + JSP D,TYBRT1 ;PASS CHAR TO NORMAL INPUT LEVEL BUT HACK NEXT CHAR + CAIE A,12 ;IF IT IS LF OR NULL IGNORE IT + JUMPN A,TYBRET ;BUT OTHERWISE PASS IT TO NORMAL INPUT LEVEL + JRST TYBXIT ;IN ANY CASE RESET TYBPC TO NORMAL + +TYBPRN: LDB E,[.BP %TXASC,A] + CAIE E,"( + CAIN E,"[ + XORI A,"(#"[ + CAIE E,") + CAIN E,"] + XORI A,")#"] + POPJ P, + +;^\^P - SET CURSOR POS, THEN RESTART OUTPUT AT M.P. LEVEL. +;THIS IS THE WAY TO RESPOND TO A %TDORS CHARACTER ON A SOFTWARE TTY, +;SINCE OUTPUT RESET WILL STOP OUTPUT AT M.P. LEVEL ON SOFTWARE TTY'S +;WHICH HAVE ^\ TURNED ON. +TYBP: JSP D,TYBRED ;WAIT FOR VPOS TO COME IN + CAML A,TCMXV(I) + SETZ A, + MOVEM A,TTYIVP(I) + SKIPGE TT,TTYLPP(I) + SETCA TT, + MOVEM A,TPVP(TT) + SKIPGE TTYLPP(I) + HRLM A,TTYLPS(I) + JSP D,TYBRED ;NOW WAIT FOR HPOS TO COME IN + CAML A,TCMXH(I) + SETZ A, + MOVEM A,TTYIHP(I) + SKIPGE TT,TTYLPP(I) + SETCA TT, + MOVEM A,TPHP(TT) + SKIPGE TTYLPP(I) + HRRM A,TTYLPS(I) +TYBR: HRROS TTOALC(I) ;RESTART AT M.P. LEVEL. + PUSHJ P,TYPEN2 ;REQUEUE ECHOING IF NECESSARY + JRST TYBXIT + +TYBZ: HLLZS TTOALC(I) ;SET ALLOCATION TO 0. + JRST TYBXIT + +TYBI: HLLOS TTOALC(I) ;SET ALLOCATION TO INFINITY. + JRST TYBST ;NOW MUST START THE TTY IN CASE IT WAS STOPPED DUE TO NO ALLOC. + +TYBA: JSP D,TYBRED ;^\^A => INCREMENT ALLOCATION BY + MOVE D,TTOALC(I) + TRNN D,400000 ;SKIP IF ALLOCATION = INFINITY + ADD D,A + HRRM D,TTOALC(I) +TYBST: AOSN TTYOAC(I) + XCT TTYST(I) + JRST TYBXIT + +SUBTTL NORMAL TTY INPUT HANDLER +;CLOBBERS A - E, EXPECTS R, U, I SET UP. +;R HAS TTYTYP, U HAS TTYSTS, I HAS # OF TTY. +;Also seems to expect Q/ TTYCOM and perhaps H/ TTYOPT -Alan 12/18/85 + +TTYI: CAIN A,^_ + JRST TTYICB ;CHAR IS ^_, MAYBE ENTER COM MODE. +TTYI2: CAIN A,^Z ;TEST FOR ^Z + JRST ZFLAG ;^Z TYPED +TTYI2A: JUMPL U,CPOPJ ;IGNORE CHAR IF NO USER. + TLNE U,%TSSII ;If in superimage input mode, + JRST TTYI2B ; don't check for magic chars. + CAIN A,%TXCTL+^Z ;Control-CALL is Deferred-Call + JRST [ MOVEI A,%TXACT+%TXPIE+%TXCTL+%TXTOP+"Z ;DEFERRED CALL + JRST TTYI19 ] + CAIN A,%TXTOP+"C ; CLEAR-INPUT does like TYCFLS, flushes + ; input buffer of TTY in I. + JRST TYIRS1 ; TYIRS1 does a POPJ P, for us: Hear no + ; evil, see no evil, echo no evil... +TTYI2B: TLZ A,-1 ;IF WE WERE CALLED FROM ^_-QUOTING RTN, BIT 3.1 WAS + ;SET TO FAKE OUT ABOVE JUNK. FLUSH FAKEOUT BIT. + MOVE E,TIME + MOVEM E,TTITM(I) ;REMEMBER TIME OF LAST TYPE-IN ON TTY. +TTYI11: MOVE E,TICC(I) + CAIL E,TIBS ;SKIP IF ANY ROOM LEFT IN INPUT BUFFER + JRST DING1 + MOVE C,A + ANDI C,%TXTOP+%TXASC + CAIL C,141 ;IF A LOWER CASE CHAR, + CAILE C,172 + JRST TTYI15 + MOVE C,TTYOPT(I) + TLNE C,%TOCLC ;CONVERT TO UPPER CASE IF WANTED + XORI A,40 +TTYI15: MOVE E,UPC(U) + TLZ E,#%PCUSR + CAIN E,NECHO1 ;IS THE JOB EXECUTING AN ECHOIN RIGHT NOW? + SKIPE E,TACC(I) ;IF SO, AND IF IT HASN'T HAD A BREAK CONDITION YET, + JRST TTYI12 + PUSHJ P,TTECIN ;MAYBE STORE CHAR IN USER MEMORY, AND JUST ECHO IT. + MOVEI E,0 ;E 0 IF CALLED TTECIN, NON-0 IF DIDN'T +TTYI12: TRNN A,%TXACT ;IF TTECIN DIDN'T ACTIVATE IT, THEN IGNORE TTYSET BITS + JUMPE E,TTYI19 ;AND DON'T ACTIVATE OR INTERRUPT NO MATTER WHAT. + MOVE C,LEPCHR + JUMPL C,TTYI19 ;JUMP IF LOCAL EDITING PROTOCOL COMMAND CHAR. + PUSHJ P,GETGRP ;GET 6 BIT BYTE FOR GROUP THIS CHARACTER IS IN + TLZE U,%TSINT ;IF WANT THIS CHAR TO INT. WHATEVER IT IS, + IORI B,%TGINT ;PRETEND IT'S AN INT. CHAR. + MOVEM U,TTYSTS(I) + LSH B,14 ;PUT %TXACT, %TXPIE, AND %TXMPE IN. + TRNN A,%TXECI + IORI A,(B) + ANDCMI A,%TXIGN+%TXINT+%TXCOM + TRNN B,%TXINT ;TEST INTERRUPT BIT FOR THIS GROUP + JRST TTYI19 ;OFF. DON'T INTERRUPT + HRRE B,U ;RH OF B IS USER INDEX + JUMPL B,[JRST 4,.] ;SHOULDN'T BE NO USER + HRL B,MSKST(B) ;LH OF B IS USER'S INTERRUPT MASK + TLNN B,%PITYI ;SKIP IF INTERRUPTS ON TYPE IN ENABLED + JRST TTYI5 ;DISABLED + MOVEI C,%PITYI + IORM C,PIRQC(B) ;GENERATE TYPE IN INTERRUPT REQUEST + TRO A,%TXINT ;INDICATE INTERRUPT +TTYI5: MOVE C,TYIMSK(I) ;GET TTY CHANNELS OPEN MASK + AND C,MSKST2(B) ;MASK OFF CHANNELS NOT ENABLED + JUMPE C,TTYI19 ;JUMP IF NO OPEN CHANNELS HAVE INTERRUPTS ENABLED + MOVN D,C + AND C,D ;ISOLATE LEAST SIGNIFICANT BIT + IORM C,IFPIR(B) ;GENERATE SECOND WORD INTERRUPT REQUEST + IORI A,%TXINT ;INDICATE INTERRUPT + JRST TTYI19 + +;LIKE TTYI18 BUT FOR A CHAR THAT WASN'T REALLY TYPED IN. +TTYI13: IORI A,%TXCOM + +;ECHO BUT DON'T USE AS INPUT THE CHAR IN A, +;ASSUMING IT WAS ACTUALLY TYPED IN BY USER. MUST NOT CLOBBER H, TT. +TTYI18: IORI A,%TXPIE+%TXIGN ;THIS CHAR WILL ECHO & BE IGNORED. + +;PUT CHARACTER IN A IN INPUT BUFFER, ADJUSTING ALL COUNTS AND POINTERS. +TTYI19: MOVE C,TICC(I) + CAIL C,TIBS + JRST DING1 ;NO ROOM IN INPUT BFR => COMPLAIN. + TRNE A,%TXACT ;IF ACTIVATION CHAR, COUNT IT. + AOS TACC(I) + TRNE A,%TXPIE ;IF PI ECHO CHAR, COUNT IT. + AOS ECHOC(I) + TRNE A,%TXINT ;SIMILAR FOR TINTC, TINTP IF INT. CHAR. + AOS TINTC(I) + MOVE E,TICC(I) + CAIL E,MICBAA + SKIPLE TACC(I) ;BUFFER FULL+ NO ACTV CHRS, GEN ONE + JRST TTYIS5 + AOS TACC(I) + IORI A,%TXACT +TTYIS5: MOVE E,TIIP(I) + CAMN E,TIBEP(I) ;SKIP IF NOT OFF THE END OF THE CIRCULAR BUFFER + SUBI E,TIBL ;RESET TIIP + HRRM E,TIIP(I) ;STORE BACK IN RH + IDPB A,TIIP(I) ;STORE CHARACTER IN INPUT BUFFER + AOS TICC(I) + TRNN A,%TXPIE ;IF PI ECHO NEEDED, + POPJ P, +TTYI7: MOVE C,TORM(I) + CAIL C,TOBS + SKIPL TTYERQ(I);PUT THIS TTY ON LIST OF THOSE NEEDING ECHO + POPJ P, ;UNLESS IT'S ALREADY ON. + TLNE I,-1 + BUG + MOVE C,TTERQS + MOVEM I,TTERQS + MOVEM C,TTYERQ(I) + POPJ P, + +DING1: TLNE R,%TTDDI ;SKIP IF WANT TO DING ON EXCESS INPUT + POPJ P, + MOVSI C,%TCDNG + IORM C,TTYCOM(I) + JRST TTYI7 ;TELL CLOCK LEVEL TO LOOK AT THIS TTY. + +TYCLWR: PUSHJ P,TCNRM + CAIL E,141 ;CONVERT LOWER CASE LTRS TO UPPER + CAILE E,172 + POPJ P, + SUBI E,40 + POPJ P, + +TTYSAM: ;STANDARDIZE ALT MODE (IF APPRO) + TLNE U,%TSALT+%TSSII ;SKIP IF ALT MODE NOT TO BE STANDARDIZED + POPJ P, ;DON'T STANDARDIZE ALT MODE + CAIE A,176 ;ALT MODE CAN BE 176 OR + CAIN A,175 ;175 + MOVEI A,33 ;CHANGE EITHER TO 33 + POPJ P, + +;GETS BYTE IN B, GROUP NUMBER IN C, BYTE POINTER IN D +GETGRP: PUSH P,A + PUSHJ P,TYINR2 ;NORMALIZE CHARACTER TO FIND CORRECT GROUP. + MOVE B,A + IDIVI B,5 + POP P,A + LDB C,GRPBPT(C) ;GET GROUP BITS + MOVEI D,TTYST1(I) + CAIL C,6 + JRST GETGR2 + LDB E,[301400,,SBTBL(C)] ;LOAD LH OF BYTE PTR +GETGR1: DPB E,[301400,,D] ;MAKE TTYST1 OR TTYST2 APPROPRIATE BYTE POINTER + LDB B,D + POPJ P, + +GETGR2: LDB E,[301400,,SBTBL-6(C)] + MOVEI D,TTYST2(I) + JRST GETGR1 + +DEFINE GGRPTB A,B,C,D,E +A_29.+B_22.+C_15.+D_8+E_1 +TERMIN + +GRPTBL: GGRPTB 0,0,0,0,0 + GGRPTB 0,0,6,13,7 + GGRPTB 7,0,0,11,0 + GGRPTB 0,0,0,0,6 + GGRPTB 0,0,0,0,0 + GGRPTB 0,0,10,0,0 + GGRPTB 0,0,13,3,3 + GGRPTB 3,3,3,3,3 + GGRPTB 5,5,4,4,3 + GGRPTB 4,3,4,2,2 + GGRPTB 2,2,2,2,2 + GGRPTB 2,2,2,3,3 + GGRPTB 5,4,5,3,3 + REPEAT 5,GGRPTB 1,1,1,1,1 + GGRPTB 1,5,3,5,4 + GGRPTB 4,3,1,1,1 + REPEAT 4,GGRPTB 1,1,1,1,1 + GGRPTB 1,1,1,5,3 + GGRPTB 5,3,12,0,0 + +GRPBPT: 350700,,GRPTBL(B) + 260700,,GRPTBL(B) + 170700,,GRPTBL(B) + 100700,,GRPTBL(B) + 010700,,GRPTBL(B) + +;HANDLE A CHARACTER TYPED WHILE THE TTY OWNER IS DOING AN ECHOIN. +;A HOLDS THE CHARACTER, U HOLDS THE JOB INDEX. CLOBBERS B, C, E. +;IF THE CHARACTER IS A BREAK, ACTIVATE ON IT. +;OTHERWISE, STORE IT IN THE USER'S BUFFER AND JUST ECHO IT AND DISCARD IT; +;BUT IF THAT IS IMPOSSIBLE BECAUSE PAGES HAVE BEEN SWAPPED OUT, +;JUST ACTIVATE INSTEAD. +TTECIN: HRRZ B,U ;PREVENT TIMING ERRORS BY NOT CONSIDERING + ; HIM INSIDE THE ECHOIN IF HE HAS THE + ; PROCESSOR, SINCE UPC NOT VALID. +IFE KA10P,[ ;IF HIS USER-MODE ACS ARE IN AC BLOCK 1, WE + ; HAVE TO GIVE UP SINCE THEY MIGHT BE SAVED + ; IN TTYACS OR SOME PLACE. + MOVEI C,UUOACS(U) + CAME C,AC1PTR +] ;IFE KA10P +IFN KA10P,[ ;ON KA10, DON'T DO THIS IF MPV IS SET + CONSO 20000 ;INTERRUPT OUT OF XCTR WITH PI TRAP SET +] ;KA10P ;GETS THE MACHINE VERY CONFUSED, I SUSPECT + CAMN B,USER + JRST TTECI9 + TRNN A,%TXCTL+%TXMTA+%TXSUP ;DECIDE WHETHER THIS CHAR ECHOES OR + ; BREAKS. + CAIGE A,40 ;CONTROL CHARS, EITHER 9-BIT OR ASCII, BREAK. + JRST TTECI9 ;NOTE THAT SAIL CHARS WILL HAVE %TXTOP. + CAIN A,%TXTOP+"H ;DON'T ECHO HELP CHAR. + JRST TTECI9 + LDB B,[050200,,A] ;WHICH WORD OF BREAK TABLE IS THIS CHARACTER IN? + ADD B,U ;JOB OWNING TTY + MOVE B,AC0S+Q(B) .SEE NECHOIN ;GET THAT WORD. + LDB E,[0500,,A] + LSH B,(E) ;GET THE BIT FOR THIS CHARACTER INTO THE SIGN BIT. + JUMPL B,TTECI9 ;IF BIT IS SET, THIS IS A BREAK CHARACTER. + SPM TTECIM ;SAVE PAGE MAP AND LOAD UP TTY-OWNING JOB'S MAP. + LPMR UPGML(U) +IFE KA10P,[ + JRST 2,@[%PSPCU,,.+1] ;XCTR DOESN'T WORK IF THIS BIT NOT SET + DATAI PAG,TTECIX ;SAVE ACS CONTEXT ALSO, SET PREVIOUS AC + ; CONTEXT TO AC BLOCK 2, BUT DON'T CHANGE + ; CURRENT CONTEXT WHICH MAY BE 0 OR 1. + MOVE B,[600200,,400000] .SEE SPCCTX ;THIS DATAO PAG, IS SAME AS IN + ; AC2CTX. (ALTHOUGH THERE ARE + ; A FEW SPURIOUS BITS SET ON + ; THE KS-10.) + LDB C,[330300,,TTECIX] ;BUT TRANSFER CURRENT AC BLOCK INTO IT + DPB C,[330300,,B] + DATAO PAG,B + MOVSI B,UUOACS(U) ;COPY THE JOB'S USER MODE ACS INTO THAT BLOCK. + XCTR XBW,[BLT B,17] +] ;IFE KA10P + MOVE C,AC0S+C(U) + XCTRI XRW,[MOVES E,(C)] ;MAKE SURE THE COUNT IS STILL IN CORE AND > 0. + CAIG E,0 + JRST TTECIL + MOVE B,AC0S+B(U) + XCTRI XRW,[MOVES E,(B)] ;MAKE SURE BYTE POINTER STILL IN CORE, + CAIA + JRST TTECIL + IBP E + XCTRI XRW,[MOVES (E)] ;AND THAT THE WORD THE CHARACTER WILL GO IN IS IN CORE + SKIPA E,AC0S+E(U) ; AND WRITABLE + JRST TTECIL + XCTRI XRW,[MOVES (E)] ;MAKE SURE THE BLOCK OF COUNTERS IS STILL IN CORE. + CAIA + JRST TTECIL + XCTRI XRW,[MOVES 6(E)] + CAIA + JRST TTECIL + XCTRI XBYTE,[IDPB A,(B)] ;STORE THE CHARACTER. + CAIA + BUG + XCTRI XRW,[SOS (C)] ;DECREMENT THE COUNT OF CHARS TO ECHO. + CAIA + BUG + JUMPE E,TTECI2 ;UPDATE THE BLOCK OF COUNTERS, IF THERE IS ONE. + ADDI E,2 ;THE FIRST TWO ARE IGNORED. + HRLI E,-4 ;THE NEXT FOUR ARE INCREMENTED. +TTECI1: XCTRI XRW,[AOS (E)] + CAIA + BUG + AOBJN E,TTECI1 + XCTRI XRW,[SOS (E)] ;THE SEVENTH IS DECREMENTED. + CAIA + BUG +;GOOD. CHARACTER HAS BEEN STORED IN THE USER'S MEMORY. +TTECI2: TRO A,%TXIGN\%TXPIE\%TXECI ;NOW MAKE IT ECHO. + PUSHJ P,TTECIR + POPJ P, + +;WE CAN'T HANDLE A CHARACTER, SO MAKE IT ACTIVATE SO THE ECHOIN WILL RETURN. +;TTECIL IS FOR AFTER THE MAP HAS BEEN SWITCHED. TTECI9 IS FOR BEFORE THEN. +TTECIL: PUSHJ P,TTECIR +TTECI9: IORI A,%TXACT + POPJ P, + +;RESTORE THE PAGE MAP THAT WE SAVED. +TTECIR: +IFE KA10P,[ + MOVEI B,UUOACS(U) ;COPY POSSIBLY ALTERED USER ACS BACK INTO + ; THE JOB. + XCTR XBR,[BLT B,UUOACS+17(U)] + DATAO PAG,TTECIX +] ;IFE KA10P + LPMR TTECIM + POPJ P, + +EBLK + +TTECIM: BLOCK 10 ;OUTER LEVEL MAP SAVED HERE AND RESTORED AT EXIT. +IF2 IFG UPGMLE-UPGML-10,.ERR TTECIM too short. +IFE KA10P,[ +TTECIX: 0 ;SAVED DATAI PAG VALUE. +] + +BBLK + +SUBTTL HANDLE ^Z + +ZFLAG: MOVSI U,%TSLCZ ;EVEN IF THIS BIT IN TTYSTS IS OFF, TTY MAY BE FREE + IORB U,TTYSTS(I) ;GET TTYSTS + JUMPGE U,ZFLAG2 ;(TTY IS IN USE) + SKIPGE TTYSTA(I) ;CONSOLE FREE MSG COMING OUT OR ALREADY TRYING TO ^Z + SKIPGE DEDTIM ;OR SYSTEM IS DOWN. DON'T CREATE A NEW JOB TREE. + POPJ P, + MOVN B,SYSDBG + SKIPGE SYSDBG ;IF NOT ALLOWING USERS, + CAMN I,B ;ALLOW ONLY THE SPEC'D TTY (= -C(SYSDBG) ) + JRST ZFLAG7 + MOVE B,TTYTYP(I) ;AND STY TTY'S, AS WELL AS TTY 0. + TRNN B,%TYSTY ;NOTE STELNT WILL REFUSE NETWORK LOGINS WHEN SYS BEING DEBUGGED. + JUMPN I,CPOPJ +ZFLAG7: CONO PI,PICOFF\<200_-UTCCHN> .SEE NUJBST + MOVE A,UTTYCT ;SET UP NEW USER + CAIL A,MXCZS ;BUT DON'T OVERFILL BUFFER + JRST [ CONO PI,PICON\<200_-UTCCHN> ? POPJ P,] + AOS UTTYCT + HRRZM I,@UTTYI + AOS A,UTTYI + CAIL A,UTTYS+MXCZS + MOVEI A,UTTYS + MOVEM A,UTTYI + CONO PI,PICON\<200_-UTCCHN> + MOVSI A,%TACTZ ;SAY TTY BEING ^Z'D - ELSE SYS JOB MIGHT TYPE CONSOLE-FREE MSG, + IORM A,TTYSTA(I) ;SINCE TTY IS FREE AND %TACFM IS OFF (OR WILL BE AFTER TTYINI) + JRST TTYINI + +ZFLAG4: HRR U,SUPPRO(U) +ZFLAG2: SKIPL SUPPRO(U) + TLNE U,%TSSII + JRST ZFLAG3 ;SUPER IMAGE INPUT MODE OR TOP LEVEL JOB + TLNN U,%TSCNS ;OR IN USE AS A DEVICE => DON'T TREAT ^Z SPECIALLY + JRST ZFLAG3 + MOVEI E,%PIC.Z + TDNE E,PIRQC(U) ;IF IMMEDIATE SUPERIOR DOESN'T RESPOND TO ^Z BY TAKING + JRST ZFLAG4 ;THE TTY FROM THE ^Z'ED JOB, TRY FOR HIS SUPERIOR. + IORM E,PIRQC(U) ;OTHERWISE GIVE ^Z INTERRUPT TO JOB + PUSHJ P,TYIRS1 ;DISCARD ALL PENDING INPUT BEFORE THE ^Z. + MOVEI A,^Z+%TXPIE+%TXIGN + JRST TTYI19 ;ARRANGE FOR THE ^Z TO BE ECHOED. + +ZFLAG3: MOVSI U,%TSLCZ ;CLEAR BIT + ANDCAB U,TTYSTS(I) + JRST TTYI2A ;TREAT ^Z AS ANY OTHER CHAR. + +SUBTTL HANDLE ^_ + +TTYICB: TLNE U,%TSSII ;^_ NOT SPECIAL IF TTY IS IN USE, IN SUPERIMAGE INPUT. + JUMPGE U,TTYI2 + SKIPGE DEDTIM ;DON'T ALLOW ^_ IF ITS IS DOWN + POPJ P, + JUMPGE U,TYCGTN ;DO ALLOW THEM ON ANY TTY THAT'S IN USE + SKIPGE SYSDBG ;IF ITS BEING DEBUGGED, ALLOW ^_ IN SAME CASES ^Z IS ALLOWED. + TRNE R,%TYSTY + JRST TYCGTN + MOVN B,SYSDBG + CAME B,I + JUMPN I,CPOPJ +TYCGTN: JSP D,TYCRDE ;ECHO IT, RETURN WITH NEXT CHAR TYPED. +TYCI: SETOM COMT1(I) ;CHR AFTER ^_ + PUSHJ P,TCNRM + CAIE E,^_ + CAIN E,^Z + JRST TYCI3A ;GIVE EITHER CHARACTER TO MAIN PROGRAM + CAIL E,^B + CAILE E,^D ;^B, ^C, ^D, ^F SIGNIFY META BITS BEING SPEC'D. + CAIN E,^F + JRST TYCMB + CAIL E,"0 ;DIGIT => CHARATER BEING TYPED IN BY ITS ASCII CODE. + CAILE E,"9 + JRST TYCI7 ;JUMP IF NOT A DIGIT. + MOVEI B,-"0(E) + MOVEM B,COMT1(I) ;STORE FIRST DIGIT + JSP D,TYCRDE ;ECHO DIGIT, READ ANOTHR. (TTYIPC LEFT -> TYCI4) +TYCI4: PUSHJ P,TYCI22 ;READ NUM AFTER FIRST DIGIT + JRST TYCI6 ;CHARACTER IS NON-NUMERIC + JRST TTYI18 ;ECHO THE DIGIT - IT'S ALREADY HANDLED. + +TYCI3A: TRNN H,%TP11T ;ON NON-TV TERMINALS, + MOVEI A,%TXCTL+100(E) ;MAKE QUOTED ^Z LOOK LIKE "CONTROL" AND "Z" IN FULL +TYCI3: PUSHJ P,TYCI17 ;RESTORE TTYIPC TO NORMAL, + HRLI A,1 ;PREVENT CHAR FROM BEING TAKEN AS ^Z OR ^_. + JRST @TTYIPC(I) ;HANDLE CHAR (BUT QUOTE ^_ AND ^Z) + + +TYCI22: LDB E,[700,,A] + CAIL E,"0 + CAILE E,"9 + POPJ P, ;RETURN WITHOUT SKIPPING IF NON-NUMERIC + MOVE B,COMT1(I) + LSH B,3 + ADDI B,-"0(E) + MOVEM B,COMT1(I) ;UPDATE VALUE SO FAR + JRST POPJ1 ;SKIP RETURN + +TYCMB: SETZM COMT1(I) ;^A THRU ^F SEEN - INITIALIZE, AND DECODE THE CHARACTER. + JRST TYCMB2 + +TYCMB1: IORM D,COMT1(I) ;SET THE SPEC'D META-BIT AND READ ANOTHER CHAR. + JSP D,TYCRDE ;WHICH WE THEN DECODE ... +TYCMB2: SETZ D, + PUSHJ P,TCNRM + CAIN E,^B + IORI D,%TXCTL + CAIN E,^C + IORI D,%TXMTA + CAIN E,^D + IORI D,%TXTOP + CAIN E,^F + IORI D,%TXSUP + JUMPN D,TYCMB1 ;IF CHAR WAS ^B THRU ^F, SET APPRO META-BIT AND LOOP. + CAIN E,^Q + JSP D,TYCRDE ;OTHERWISE, ^Q QUOTES, + IOR A,COMT1(I) ;JUST READ THE CHARACTER, WITH SPEC'D META-BITS MERGED IN. + JRST TYCI3 + +TYCI2: PUSHJ P,TTYI18 ;ECHO CHAR, RESET TTYIPC TO NORMAL. +TYCI17: MOVEI B,TYCG + SKIPL Q + MOVEI B,TTYI + MOVEM B,TTYIPC(I) + TLZ Q,%TCCBS+%TCCBK ;ALSO FLUSH TEMPORARY STATUS INFO. + MOVEM Q,TTYCOM(I) + POPJ P, + +TYCI6: EXCH A,COMT1(I) ;A NOW HAS CHAR REPRESENTED BY DIGITS; COMT1 HAS THE NON-DIGIT JUST TYPED IN. + ANDI A,7777 + PUSH P,I ;IF IN COME MODE, TYCI3 CALLS TYCG AND SMASHES I + PUSHJ P,TYCI3 ;SIMULATE ITS TYPE IN + POP P,I + MOVE A,COMT1(I) ;GET LAST CHARACTER TYPED + CAIN A,40 ;A SPACE GETS FLUSHED FOLLOWING DIGITS + POPJ P, + MOVE Q,TTYCOM(I) ;RESTORE ACS BASHED BY TYCG + MOVE R,TTYTYP(I) + MOVE H,TTYOPT(I) ;THIS ONE MAY BE SUPERFLUOUS + MOVE U,TTYSTS(I) + JRST @TTYIPC(I) ;PROCESS IT NORMALLY + +TCNRM: MOVE E,A + PUSHJ P,TYINR2 + EXCH E,A + POPJ P, + +TYCI7: PUSHJ P,TYCLWR ;NON-DIGIT, NON-^Z, NON-^_ AFTER ^_. + CAIN E,^U ;^U is CLEAR INPUT. + JRST TYCFLS + CAIL E,"A ;IF IT'S A LETTER, + CAILE E,"Z + JRST TYCI7A + XCT TYIQT-"A(E) ;JUST DISPATCH ON IT. + MOVEM H,TTYOPT(I) +TYCI7D: MOVEM U,TTYSTS(I) + JRST TYCI2 + +TYCI7A: CAIE E,"" ;ASIDE FROM LETTERS, " AND ^ ARE OK. + CAIN E,"^ + JRST TYCI7B +TYCI7F: MOVEI A,"? ;OTHER CHARS ARE ERRORS. +TYCI2A: PUSHJ P,TTYI13 ;ECHO A CHARACTER THAT WASN'T INPUT, AND RESET TTYCOM AND TTYIPC. + JRST TYCI17 + +TYCI7B: CAIE E,"" + TLCA U,%TSROL ;^_^ COMPLEMENTS SCROLL MODE. + TLC U,%TSSAI ;^_" COMPLEMENTS SAIL CHAR SET USAGE. + JRST TYCI7D + +TYIQT: JRST TYCA ;A => ACCEPT COM LINKS. + JRST TYCB ;B => TRIGGER A **MORE** (BLOCK TYPEOUT). + JRST TYCC ;C => CREATE COM LINK. + JRST TYCD ;D => DEFERRED CALL + JRST TYCRFT ;E => ENTER REMOTE FEED-THRU. + JRST TYCI7F ;F => ERROR. + TLC U,%TSMOR ;G => COMPLEMENT MORE-PROCESSING. + JRST TYCH ;H => HELP KEY. + TLC Q,%TCICO ;I => COMPLEMENT INPUT OVERRIDE. + JRST TYCJ ;J => Cause %PIJST interrupt. + JRST TYCK ;K => FLUSH SPEC'D TTY FROM COM LINK. + MOVEI A,^L+%TXIGN+%TXCOM ;L => CLEAR SCREEN. + TLC U,%TSMOR ;M => COMPLEMENT MORE-PROCESSING. + JRST TYCN ;N => BREAK COM LINK. + TLC Q,%TCOCO ;O => COMPLEMENT OUTPUT COM OVERRIDE. + JRST TYCI7F ;P => ERROR. + JRST TYCQ ;Q => ENTER QUERY MODE. + JRST TYCR ;R => ENTER REFUSE MODE. + JRST TYCS ;S => SLAVE ANOTHER TTY. + JRST TYCI7F ;T => ERROR. + TLC H,%TOCLC ;U => COMPLEMENT CASE-CONVERSION. + JRST TYCI7F ;V => ERROR. + JRST TYCI7F ;W => ERROR. + JRST TYCI7F ;X => ERROR. + JRST TYCQA ;Y => ACCEPT PENDING QUERIES FOR COM LINKS + JRST TYCQR ;Z => REJECT PENDING QUERIES. + +IFN .-TYIQT-26.,.ERR WRONG LENGTH TABLE. + +;PUT IN A DEFERRED CALL +TYCD: PUSHJ P,TTYI18 ;ECHO THE D + MOVEI A,%TXACT+%TXCTL+%TXTOP+"Z + PUSHJ P,TTYI19 ;PUT A DEFERRED CALL IN THE BUFFER + JRST TYCI17 ;RESET ^_ STATE + +;HELP KEY +TYCH: PUSHJ P,TTYI18 ;ECHO THE H + MOVEI A,%TXACT+%TXTOP+"H + PUSHJ P,TTYI19 ;PUT A [HELP] IN THE BUFFER + JRST TYCI17 ;RESET ^_ STATE + +;Cause %PIJST interrupt. +TYCJ: SKIPA B,[%PIJST] +TYCJ1: MOVE U,SUPPRO(U) + JUMPL U,TYCI7F ; Error if tty not in use or nobody enabled + ; for it. + TDNN B,MSKST(U) + JRST TYCJ1 + IORM B,PIRQC(U) + JRST TYCI2 ; Echo the J and reset ^_ state. + +;CLEAR INPUT +TYCFLS: CONO PI,TTYOFF ;No touching buffer while I'm frobbing it. + PUSHJ P,TYIRS1 ;Completely flush input buffer of TTY in I. + CONO PI,TTYON + MOVEI A,^U + PUSHJ P,TTYI13 ;Can echo the ^U now. + JRST TYCI17 ;Reset ^_ state. + + +TYCB: HRRZ B,I ;COME HERE FOR ^_B. + IMULI B,TPLEN*2 + MOVEI C,%TFEOP + IORM C,TPFLAG(B) + JRST TYCI2 + +TYCRFT: PUSH P,A ;COME HERE FOR ^_E. + MOVE A,TTYTYP(I) ;ARE WE A LOCAL TTY? + TRNN A,%TYDIL\%TYRLM\%TYSTY + JRST TYCRF0 ;LOCAL TTYS ARE ALLOWED TO SLAVE W/O LOGIN + TRNN A,%TYSTY ;Is it a STY? + JRST TYCRFA ; Nope + HRRZ A,STYSTS-NFSTTY(I) ;Special Check for TARAKA demons linking + MOVE A,UNAME(A) ;Is the UNAME of the owner of this STY + CAMN A,[SIXBIT /TARAKA/] ;TARAKA? + JRST TYCRF0 ;Yes, let it hack all it wants. +TYCRFA: HRRE A,TTYSTS(I) ;GET OWNER OF THIS TTY + AOJE A,TYCRF2 ;IF THIS IS A FREE TTY, DON'T LET HIM + HLRE A,UNAME-1(A) ;IS HE LOGGED IN? + AOJE A,TYCRF2 ; IF NOT, FAIL +TYCRF0: SETZ B, ;COMPLEMENT OUR %TCRFT BIT. + PUSHJ P,TYCREP ;1ST, COUNT # TTYS IN LOOP. + PUSHJ P,[ + MOVE A,TTYCOM(I) + TLNE A,%TCLFT ;IF ANY TTY IN LOOP HAS %TCLFT SET + POPJ P, ;THEN IT'S OK FOR OUR %TCRFT TO BE. + AOJA B,POPJ1] + JRST TYCRF1 ;SOME TTY IN LOOP HAS %TCLFT => OK TO SET %TCRFT. + CAIE B,2 ;ONLY 1 OTHER TTY => SET ITS %TCLFT, THEN OUR %TCRFT. + JRST TYCRF2 ;FAIL TO SET %TCRFT IF CAN'T FIND OTHER WITH %TCLFT. + MOVE A,TTYCOM(I) + MOVSI B,%TCLFT + IORM B,TTYCOM(A) +TYCRF1: TLC Q,%TCRFT + POP P,A + JRST TYCI7D + +TYCRF2: SUB P,[1,,1] + JRST TYCI7F + +;COME HERE AFTER READING UNAME FOR ^_S. B HAS IDX OF SPEC'D TTY. +;SET THAT TTY'S %TCLFT, ENSLAVING IT. CLEAR %TCLFT OF ALL OTHER TTYS +;IN THE SAME LOOP AS SPEC'D TTY. +TYCS1: PUSHJ P,TYCREP + CAIN B,(I) ;IF SPEC'D TTY NOT IN COM WITH US + CAIA + JRST TYCI7F ;THEN IT'S AN ERROR. + MOVSI A,%TCLFT + PUSHJ P,TYCREP ;CLEAR %TCLFT OF ALL TTY'S LINKED TO US, + ANDCAM A,TTYCOM(I) + JFCL + IORM A,TTYCOM(B) ;THEN SET IT FOR HIM. + POPJ P, + +;CALL WITH JSP D, ECHO CHAR IN A, RETURN WITH NEXT CHAR. +TYCRDE: HRRZM D,TTYIPC(I) + JRST TTYI18 + +;LIKE TYCRDE BUT DON'T ECHO THE CHARACTER IN A. +TYCRED: HRRZM D,TTYIPC(I) + POPJ P, + +;T -> ASCIZ STRING, ECHO ON TTY # IN I (MUST HAVE DONE TYCSET) +TYCI40: HRLI T,440700 +TYCI39: ILDB A,T + JUMPE A,CPOPJ + PUSHJ P,TTYI13 ;ECHO CHARACTER ON TTY + JRST TYCI39 + +;SET UP ACS FOR ECHOING ON TTY # IN I. +TYCSET: MOVE R,TTYTYP(I) + MOVE Q,TTYCOM(I) + MOVE U,TTYSTS(I) + POPJ P, + +;PUT TTY IN COM MODE IF IT ISN'T. TTY # IN I. +TYCI63: TLON Q,400000 + TLZ Q,%TCLFT+%TCRFT + MOVEM Q,TTYCOM(I) + JRST TYBC + +;TTY # IN I, REPEAT OVER THAT TTY AND ALL LINKED TO IT. +;INSN TO BE REPEATED FOLLOWS CALL. +;IF THE INSN DOESN'T SKIP, IMMEDIATELY RERURNS +;SKIPPING ONLY THAT INSN. ELSE RETURNS SKIPPING 2 WHEN ALL TTYS DONE. +TYCREP: PUSH P,I ;PUSH TTY STARTING WITH. + PUSH P,I ;PUSH TTY DOING NEXT. +TYCRE0: XCT @-2(P) ;(THE INSN AFTER THE PUSHJ) + JRST TYCRE1 ;IT DIDN'T SKIP, GIVE UP RIGHT AWAY. + MOVE I,(P) ;ELSE KEEP GOING, + SKIPL I,TTYCOM(I) + JRST TYCRE2 ;LAST TTY DONE NOT LINKED, THRU. + ANDI I,-1 + CAIE I,-1 ;IN COM MD BUT NOT LINKED OR + CAMN I,-1(P) ;HAVE GONE ALL AROUND CIRCULAR LIST + JRST TYCRE2 ;=> DONE. + MOVEM I,(P) ;ELSE DO THE NEXT ONE. + JRST TYCRE0 + +TYCRE2: AOS -2(P) ;RETURN SKIPPING 2. +TYCRE1: SUB P,[1,,1] + POP P,I + JRST POPJ1 + +;^_A - ACCEPT ALL PENDING AND FUTURE REQUESTS FOR COM LINKS. +TYCA: TLZ Q,%TCRFS+%TCQRY + +;^_Y - ACCEPT ALL PENDING REQUESTS FOR COM LINKS. +TYCQA: PUSHJ P,TYCI2 ;ECHO THE A OR Y. + PUSHJ P,TYCQRP ;FIND ALL PENDING QUERIES + PUSHJ P,TYCQAC ;ACCEPT EACH ONE. + POPJ P, + +TYCQAC: PUSHJ P,TYCREP ;DON'T ACCEPT A RQ FROM SOMEONE ALREADY LINKED TO US. + CAIN B,(I) + POPJ P, + MOVE H,B ;HIS TTY # IN H FOR TYCI43 + PUSHJ P,TYCSET + PUSHJ P,TYCI43 ;LINK HIM AND ME; ECHANGE I AND H. + MOVE B,I + MOVE I,H ;GET HIS # BACK IN B AND MINE IN I. + POPJ P, + +;^_R - REFUSE ALL PENDING AND FUTURE REQUESTS FOR COM LINKS. +TYCR: TLO Q,%TCRFS + TLZ Q,%TCQRY + +;^_Z - REFUSE ALL PENDING REQUESTS FOR COM LINKS. +TYCQR: PUSHJ P,TYCI2 ;ECHO THE R OR Z. + PUSHJ P,TYCQRP ;FIND ALL PENDING QUERIES + PUSHJ P,TYCQRF ;AND REFUSE EACH ONE. + POPJ P, + +TYCQRF: EXCH B,I + PUSHJ P,TYCSET ;TYPE ON REQUESTING TTY + PUSHJ P,TYCI36 ;THAT IT IS BEING REJECTED + EXCH B,I ;AND REMOVE IT FROM A QUERYING STATE. + POPJ P, + +;^_Q - ALL REQUESTS FOR COM LINKS SHOULD REMAIN PENDING UNTIL ANSWERED +;WITH ^_Y, ^_Z OR AN INVERSE ^_C. +;ALSO, LIST ALL REQUESTS THAT ARE NOW PENDING. +TYCQ: TLZ Q,%TCRFS + TLO Q,%TCQRY + PUSHJ P,TYCI2 ;ECHO THE "Q" AND RESET ALL STATUS INFO. + PUSHJ P,TYCSET + SETZ T, ;INDICATE NOTHING HAS BEEN TYPED YET. + PUSHJ P,TYCQRP ;FIND THE PENDING REQUESTS + PUSHJ P,TYCQLS ;SAY WHO EACH IS FROM. + POPJ P, + +TYCQLS: JUMPE T,TYCQL1 ;IF THIS ISN'T THE FIRST NAME MENTIONED, + MOVEI T,[ASCIZ/, /] ;SEPARATE FROM THE PREVIOUS NAME. + PUSHJ P,TYCI40 +TYCQL1: MOVE C,B ;THIS IS TTY NUMBER QUERYING US + PUSH P,C .SEE TYCI92 + PUSH P,[POPCJ-1] ;TYCI67 ALWAYS SKIP-RETURNS. + JRST TYCI67 ;TYPE THE USER'S NAME OR THE TTY NUMBER. + +; PUSHJ P,TYCQRP +; INSN +;EXECUTES INSN ONCE FOR EACH TTY QHICH IS QUERYING THE TTY IN I. +;THE QUERYING TTY'S NUMBER IS IN B. INSN MUST PRESERVE B AND I. +;A IS CLOBBERED BY TYCQRP. OTHER ACS ARE UNTOUCHED. + +TYCQRP: SETZ B, +TYCQR1: MOVE A,TTYIPC(B) + CAIE A,TYCRW + CAIN A,TYCRW2 + CAME I,COMT1(B) + JRST TYCQR2 ;TTY IN B ISN'T QUERYING TTY IN I. + XCT @(P) ;EXECUTE INSN. +TYCQR2: CAIE B,NCT-1 + AOJA B,TYCQR1 + JRST POPJ1 ;SKIP OVER INSN WHEN RETURN. + +SUBTTL HANDLE COM-LINKS + +TYCC: TLOA Q,%TCTPN ;^_C - WHEN LEAVE COM MODE MUST TYPE ^_N. +TYCK: TLO Q,%TCCBK ;SAY WE'RE DOING ^_K. + JRST TYCI19 + +TYCS: TLO Q,%TCCBS ;^_S - ENSLAVE SPEC'D TTY. +TYCI19: MOVEM Q,TTYCOM(I) + JSP D,TYCRDE ;ECHO, RETURN, COME BACK WITH NEXT CHAR. + PUSHJ P,TCNRM + CAIE E,15 ;SPACE OR CR IS 1ST CHAR, IGNORE. + CAIN E,40 + JRST TTYI18 + MOVEI B,TYCI27 + MOVEM B,TTYIPC(I) + SETZM COMT3(I) ;INIT. ACCUMULATED #. + SETZM COMT1(I) ;AND ACCUM UNAME. + +;READING CHARS AFTER ^_C (AFTER A NON-SPACE HAS BEEN SEEN) +;COMT1 ACCUMULATES SIXBIT, COMT3 OCTAL NUMBER. +;SIGN OF COMT3 SET => NONDIGIT WAS SEEN, USE THE SIXBIT. +TYCI27: PUSHJ P,TYCLWR ;CONVERT TO UPPER CASE. + CAIN E,^_ + JRST TYCI7F ;ANOTHER ^_ IS NO GOOD. + CAIE E,15 + CAIN E,40 + JRST TYCI28 ;SPACE DELIMITS UNAME OR NUMBER + CAIN E,^^ + JRST TYCI28 + CAIN E,177 + JRST TYCI7F ;RUBOUT => TYPE ? AND GIVE UP. + MOVE B,COMT3(I) ;ACCUM NUMBER IN RH OF COMT3. + LSH B,3 + ADDI B,-"0(E) + HRRM B,COMT3(I) + CAIL E,"0 + CAILE E,"9 ;NON-DIGIT SEEN => SET SIGN OF COMT3 SAYING + SETOM COMT3(I) ;CERTAINLY NOT NUMBER. + MOVE B,COMT1(I) + LSH B,6 + IORI B,-40(E) + MOVEM B,COMT1(I) ;ADD NEW CHARACTER ONTO THE END OF THE NAME + JRST TTYI18 ;EXIT TO ECHO THE CHARACTER + +TYCI28: MOVE H,Q ;SAVE SETTINGS OF %TCCBS, %TCCBK, SINCE TYCI2 WILL CLEAR THEM. + PUSH P,E + PUSHJ P,TYCI2 ;ECHO TERMINATING CHAR IN A, AND RESET ALL TO NORMAL. + POP P,E + SKIPGE B,COMT3(I) + JRST TYCI52 ;TYPEIN WASN'T NUMBER. + CAIGE B,NCT ;IS NUMBER THAT OF A TTY THAT EXISTS? + JRST TYCI53 +TYCI52: MOVE D,COMT1(I) +TYCI29: TLNE D,770000 ;LEFT ADJUST THE UNAME + JRST TYCI30 + LSH D,6 + JRST TYCI29 + +TYCI30: MOVEI U,LUBLK ;START LOOKING AT USER NUMBER 2 + MOVSI A,%TCRFS + SETO B, ;NO REFUSE-MODE TTY FOUND YET +TYCI31: ADDI U,LUBLK + CAML U,USRHI + JRST [ JUMPGE B,TYCI36 ;REFUSED + JRST TYCI7F ] ;OUT OF USERS SO GIVE ? AND RETURN + CAMN D,UNAME(U) ;SKIP IF UNAME DOESN'T MATCH + SKIPGE C,TTYTBL(U) ;SKIP IF PROCEDURE HAS THE TTY + JRST TYCI31 ;TRY NEXT PROCEDURE + HRRZ B,C ;TTY NUMBER + TDNE A,TTYCOM(B) ;IN REFUSE MODE? + JRST TYCI31 ;YES, MAY BE CRTSTY, TRY TO FIND A BETTER TTY WITH THIS UNAME +TYCI53: MOVEM B,COMT1(I) ;# OF TTY TRYING TO HACK + SETZM COMT3(I) ;IEC FLAG FOR QUERY MODE + CAIN E,^^ + SETOM COMT3(I) + TLZE H,%TCCBK ;JUMP IF DOING ^_K. + JRST TYCK1 +IFG APL,[ + CAIN B,APL ;DON'T SEND MESSAGE TO A.P. LINE + JRST TYCI7F ;(OK NOW TO SEND TO SYSTEM CONSOLE, HAS O.C.O. ANYWAY) +] + TLZE H,%TCCBS + JRST TYCS1 ;ALSO CHECK FOR ^_S. + PUSHJ P,TYCREP ;NO, IT'S ^_C. + CAIN B,(I) ;DON'T LET LINK TO SELF OR SOMEONE ALREADY LINKED TO. + JRST TYCI7F + HRRE C,TTYSTS(B) + AOJN C,TYCI34 ;TTY HAS A USER + MOVEI A,"F ;TTY IS FREE + PUSHJ P,TTYI13 ;TYPE AN F + MOVEI A,40 + PUSHJ P,TTYI13 ;FOLLOWED BY A SPACE + MOVE B,COMT1(I) ;RESTORE THAT TTY'S NUMBER. + JRST TYCI32 + +TYCI34: MOVE C,TTYSTS(B) ;TTY IN USE: AS A DEVICE? + TLNN C,%TSCNS + JRST TYCI7F ;^_C NOT ALLOWED TO TTY OPEN AS DEVICE. +TYCI32: MOVE A,TTYIPC(B) + CAIE A,TYCRW2 + CAIN A,TYCRW ;IF HE'S QUERYING ME, THEN HE AUTOMATICALLY ACCEPTS + JRST [CAME I,COMT1(B) ;REGARDLESS OF HIS %TCRFS AND %TCQRY. + JRST TYCI37 ;IF HE'S QUERYING SOMEONE ELSE, HE'S BUSY. + JRST TYCI33] + MOVE C,TTYCOM(B) + TLNE C,%TCRFS ;GIVE UP IF HE IS REFUSING ^_C'S. + JRST TYCI36 + CAIN A,TTYI ;MUNGING IPC WHILE NOT NORMAL WOULD LEAVE + JRST TYCI44 ;WHAT HE'S DOING UNFINISHED - CAUSING BUGS. + CAIE A,TYCG + JRST TYCI37 ;IPC NOT NORMAL. + MOVEM B,COMT1(I) ;IPC NORMAL BUT HE'S IN A COM LINK. + MOVE TT,I + MOVE H,B ;MY TTY # IN TT AND I, HIS IN H. + MOVEI T,[ASCIZ/ IN COM: /] + PUSHJ P,TYCI71 ;LIST ALL TTYS IN COM WITH HIM. + JFCL + MOVEI T,[ASCIZ/ +BREAK IN? /] + PUSHJ P,TYCI40 ;PRINT STRING ON MY TTY. + JSP D,TYCRED ;READ THE ANSWER + PUSHJ P,TTYI18 ;AND ECHO IT. + PUSHJ P,TYCLWR ;NORMALIZE IT AND CONVERT TO UPPER CASE IN E. + CAIE E,"Y + JRST TYCI17 ;NO => RESET US TO NORMAL AND GIVE UP. + MOVE B,COMT1(I) ;ANSWER IS YES, GO AHEAD. + MOVE A,TTYIPC(B) + CAIE A,TTYI + CAIN A,TYCG + CAIA + JRST TYCI37 ;CAN'T MUNG HIM IF IPC NOT NORMAL. + MOVE C,TTYCOM(B) + TLNE C,%TCRFS + JRST TYCI36 ;HE'S REFUSING. +TYCI33: PUSHJ P,TYCREP + CAIN B,(I) ;MAYBE HE ENTERED OUR LOOP WHILE WE WAITED. + JRST TYCI7F ;LINKING TO SOMEONE ALREADY LINKED TO CAUSES BUGS. + JRST TYCI44 ;GO AHEAD AND LINK UP. + +TYCI37: SKIPA T,[[ASCIZ/BUSY /]] ;TARGET IS BUSY. +TYCI36: MOVEI T,[ASCIZ/REFUSED /] ;TARGET IS REFUSING. + PUSHJ P,TYCI40 + JRST TYCI17 + +;NOW WE KNOW IT'S OK TO TRY TO ^_C HIM. HIS TTY # IN B, MINE IN I. +TYCI44: MOVE H,I ;PUT MY TTY # IN H, HIS IN I. + MOVE I,B + SETO TT, + PUSHJ P,TYCSET ;GET HIS TTYCOM IN Q FOR TYCI63 + PUSHJ P,TYCI64 ;TYPE MSG FROM ME ON HIM. + JFCL + MOVE A,TTYIPC(I) + CAIE A,TYCRW2 ;IF HE'S QUERYING US, NO NEED TO QUERY HIM; + CAIN A,TYCRW ;JUST PRETEND HE'S IN ACCEPT MODE. + JRST TYCI43 + MOVSI A,%TCQRY + TDNN A,TTYCOM(I) ;SKIP IF HE MUST BE ASKED + JRST TYCI43 ;HE'S IN ACCEPT MODE. + MOVEI T,[ASCIZ /- QUERYING/] ;ELSE JUST MENTION TO HIM THAT WE'RE QUERYING + SKIPL COMT3(H) + PUSHJ P,TYCI40 + MOVEM I,COMT1(H) ;AND SETTLE DOWN FOR HIM TO DO SOMETHING ABOUT IT. + MOVEI A,TYCRW + MOVEM A,TTYIPC(H) + MOVE I,H + PUSHJ P,TYCSET + MOVEI T,[ASCIZ /QUERYING /] ;TELL OUR USER THAT WE'RE WAITING FOR ANSWER. + JRST TYCI40 + +TYCI68: CAIN TT,(I) ;ENTRY TO DO FOR ALL LINKED TO HIM BUT NOT HIM. + JRST POPJ1 +TYCI64: MOVEI T,[ASCIZ / +MESSAGE FROM /] + MOVE R,LOCTTY + MOVE R,TTYTYP(R) + TRNN R,%TYSTY + JRST TYCI62 + MOVE R,LOCTTY + MOVE R,STYSTS-NFSTTY(R) + MOVE R,JNAME(R) + CAME R,[SIXBIT /PEEK/] ;THIS SEEMS TO BE A CROCK --RG +TYCI62: MOVEI T,[ASCIZ / +LINK FROM /] +TYCI71: PUSHJ P,TYCSET ;SET UP Q,R,U,W FOR HIS TTY (# IN I) + PUSHJ P,TYCI40 ;PRINT MSG <- T ON IT. + PUSH P,I ;SAVE HIS TTY #, + MOVE I,H ;GET MINE (ARG TO TYCREP) + PUSHJ P,TYCREP ;LOOP OVER ME AND ALL ALREADY LINKED TO ME. + PUSHJ P,TYCI66 + JFCL +TYCI41: POP P,I + MOVEI A,40 + PUSHJ P,TTYI13 + JRST POPJ1 + +;TYPE UNAME OF 1 OF MY TTYS ON 1 OF HIS. +TYCI66: HRRZ C,TTYCOM(H) + CAIE C,-1 + JRST TYCI72 + CAIN H,(I) ;BUT DON'T TYPE MY NAME ON HIM. + CAME TT,-4(P) + CAIA + JRST POPJ1 +TYCI72: MOVEI C,(I) ;PUT THIS TTY # IN C, + MOVE I,-4(P) ;GET HIS BACK IN I SINCE STILL TYPING ON HIM. + CAMN C,-2(P) ;IF THIS ISN'T MY TTY, + JRST TYCI67 + MOVEI T,[ASCIZ/ AND /] ;THEN IT'S SOMEONE LINKED TO ME + PUSHJ P,TYCI40 ;AND MY NAME WAS ALREADY TYPED + MOVE C,-1(P) +TYCI67: HRRE C,TTYSTS(C) ;MY USER INDEX + JUMPL C,TYCI92 + MOVE C,UNAME(C) + HLRE A,C + AOJE A,TYCI92 +TYCI91: PUSH P,C + MOVSI T,(440600,,(P)) +TYCI42: ILDB A,T + JUMPE A,POP1J1 + ADDI A,40 ;CONVERT MY UNAME FROM SIXBIT TO ASCII + PUSHJ P,TTYI13 ;ECHO CHARACTER ON HIS TTY + TLNE T,770000 + JRST TYCI42 + JRST POP1J1 + + +TYCI92: MOVSI C,(SIXBIT /T/) + LDB T,[030300,,-1(P)] + ADDI T,20 + DPB T,[300600,,C] + LDB T,[000300,,-1(P)] + ADDI T,20 + DPB T,[220600,,C] + JRST TYCI91 + +;ACTUALLY JOIN MY TTY AND HIS IN COM LINK. +;ENTER WITH HIS TTY # IN I AND MINE IN H. +;LEAVE WITH MINE IN I AND HIS IN H, TT. +TYCI43: TLO Q,%TCTPN ;WHEN HE LEAVES COM MODE TYPE ^_N AT HIM. + PUSHJ P,TYCI63 ;PUT HIM IN COM MODE IF HE ISN'T ALREADY. + MOVE TT,I ;HIS TTY # IN TT, MINE IN H. + PUSHJ P,TYCREP ;LOOP OVER TTYS LINKED TO HIM. + PUSHJ P,TYCI68 ;PRINT OUT MSG FROM ON ALL LINKED TO HIM, NOT HIM. + JFCL + EXCH TT,H ;INTERCHANGE HIS AND MINE. + MOVE I,TT ;LOOK AT ALL LINKED TO ME. + PUSHJ P,TYCSET ;WHEN I CHANGES, RELATED ACS SHOULD ALSO CHANGE. + TLO Q,%TCTPN ;WHEN HE LEAVES COM MODE TYPE ^_N AT HIM. + PUSHJ P,TYCI63 ;PUT HIM IN COM MODE IF HE ISN'T ALREADY. + PUSHJ P,TYCREP ;ON EACH OF MINE, GIVE NAMES OF HIS. + PUSHJ P,TYCI69 + JFCL + MOVE TT,H + MOVE A,TTYCOM(TT) ;SET UP LINK + MOVE B,TTYCOM(I) ;LINK TTYCOM WORDS + HRRE E,A + AOJN E,TYCI45 + HRRM TT,A +TYCI45: HRRE E,B + AOJN E,TYCI46 + HRRM I,B +TYCI46: HRRZ D,A + HRRZ E,B + HRRM E,A + HRRM D,B + MOVEM A,TTYCOM(TT) + MOVEM B,TTYCOM(I) + MOVEI A,TYCG + MOVEM A,TTYIPC(I) + MOVEM A,TTYIPC(TT) + POPJ P, + +TYCI69: CAIE I,(TT) ;PRINT MSG ON ONE OF MY TTYS. + JRST TYCI70 + SKIPA T,[[ASCIZ/OK /]] ;MY TTY, SAY "G". +TYCI70: MOVEI T,[ASCIZ/ +LINK TO /] + JRST TYCI71 ;DUE TO EXCH'S IN TYCI43, + ;EXCHANGE "ME" AND "HIM" IN COMMENTS IN TYCI71. + +;TTYIPC FOR A ^_C'ER WHO IS QUERYING IS EITHER TYCRW OR TYCRW2. +;THAT IS DEPENDED ON. +TYCRW: PUSHJ P,TCNRM + CAIE E,^G ;^_C'ER MAY USE ^G TO GET ATTENTION. + SKIPGE COMT3(I);IN IEC MODE CAN ALSO SAY THE NAME + JRST TYCRW4 + CAIE E,^_ ;IGNORE ALL TYPEIN EXCEPT ^G AND ^_N. + POPJ P, + JSP D,TYCRDE ;^_, ECHO IT AND GET NEXT CHAR. +TYCRW2: PUSHJ P,TYCLWR + CAIN E,"N + JRST TYCI2 + MOVEI A,"? ;^_ FOLLOWED BY OTHER THAN N. + MOVEI B,TYCRW + MOVEM B,TTYIPC(I) + JRST TTYI13 ;ECHO ? AND GO BACK TO TYCRW + +TYCRW4: PUSHJ P,TTYI18 ;^_C'ER TYPED ^G - ECHO ON HIS TTY + MOVE I,COMT1(I) ;AND ^_C'D TTY. + PUSHJ P,TYCSET + JRST TTYI13 + +;THE TTYIPC FOR A TTY IN A COM LINK NORMALLY POINTS HERE. +;ECHO OR INPUT THE CHAR ON ALL TTYS IN THE LOOP ACCORDING TO SETTINGS +;OF THE RELEVANT %TCICO, %TCLFT AND %TCRFT BITS. +TYCG: MOVE E,A + ANDCMI E,#177 .SEE TYCI3 + CAIN E,^_ ;REC CHRS IN COM MODE + JRST TYCGTN +TYCG21: PUSH P,TTYCOM(I) ;SAVE COMMUNICATE WORD. + PUSH P,I ;SAVE MY CONSOLE NUMBER + PUSH P,A ;SAVE THE CHARACTER + TLNE Q,%TCICO ;SKIP IF INPUT COM OVERRIDE OFF + PUSHJ P,TTYI2 ;PROCESS INPUT OVERRIDE + TLNN Q,%TCICO + PUSHJ P,TTYI18 ;ECHO CHR ON MY TTY IF %TCICO NOT SET, OTHERWISE GIVE TO PROGRAM + MOVE A,(P) ;RESTORE CHARACTER +TYCG5: HRRE B,TTYCOM(I) ;FIRST TTY IN CHAIN + JUMPL B,[JRST 4,.] ;I'M NOT COMMUNICATING WITH ANYONE + CAME B,-1(P) ;SKIP IF I'M COMMUNICATING WITH MYSELF +TYCG3: SKIPL C,TTYCOM(B) ;SKIP IF HE IS IN COMMUNICATE MODE (THIS POINT IS "COM IN") + BUG ;LOSSAGE + MOVE I,B ;GET HIS TTY NUMBER IN I + MOVE R,TTYTYP(I) + MOVE B,-2(P) + TLNE B,%TCRFT ;IF MY %TCRFT AND HIS %TCLFT SET, + TLNN C,%TCLFT + JRST TYCG1 + MOVSI U,%TSLCZ ;GIVE CHAR TO HIS PROGM. + ANDCAB U,TTYSTS(I) + PUSHJ P,TTYI2 ;TREAT CHAR AS INPUT FROM HIS TTY. + JRST TYCG2 ;PROCESS NEXT TTY IN CHAIN + +TYCG1: PUSHJ P,TTYI13 ;OUTPUT CHAR ON HIS CONSOLE +TYCG2: MOVE A,(P) ;RESTORE CHARACTER + HRRE B,TTYCOM(I) ;NEXT TTY IN CHAIN + JUMPL B,[JRST 4,.] ;CHAIN ENDS STRANGELY + CAME B,-1(P) ;SKIP IF DONE + JRST TYCG3 ;PROCESS NEXT TTY + SUB P,[3,,3] + POPJ P, + +;COME AFTER READING UNAME AFTER ^_K, HIS TTY # IN B. +TYCK1: PUSHJ P,TYCREP ;NO GOOD IF THAT TTY ISN'T LINKED TO ME. + CAIN B,(I) + CAIN B,(I) ;BUT NO GOOD IF IT IS ME. + JRST TYCK2 ;NO GOOD, COMPLAIN. + MOVE I,B + PUSHJ P,TYCSET ;GET HIS TTYCOM IN Q. + JRST TYCGTM ;NOW PRETEND HE DID ^_N (READ "HIM" FOR "ME") + +TYCK2: MOVE A,TTYIPC(B) + CAIE A,TYCRW + CAIN A,TYCRW2 + CAME I,COMT1(B) + JRST TYCI7F ;NOT LINKED TO THIS GUY, GIVE "?" + JRST TYCQRF ;FLUSH GUY WHO WAS QUERYING + +;^_N TYPED IN. +TYCN: TLZ Q,%TCTPN ;I DON'T NEED ^_N SUPPLIED IF I JUST TYPED IT IN MYSELF. + PUSHJ P,TYCI2 ;ECHO THE N AND STORE Q. ALSO RESTORE TTYIPC AND TTYCOM TO NORMAL. + SKIPL TTYCOM(I) + POPJ P, + +;ASSUMING THAT TTY IN I IS IN A COM LINK, UNLINK IT. +;IF ONLY ONE OTHER TTY IS IN THE LINK, REMOVE IT FROM COM MODE TOO. +TYCGTM: HRRE B,TTYCOM(I) .SEE TTYLFC + JUMPL B,[JRST 4,.] ;WASN'T COMMUNICATING WITH ANYONE + CAMN B,I + BUG ;COMMUNICATING WITH SELF +TYCGT3: HRRE C,TTYCOM(B) + JUMPL C,[JRST 4,.] ;LIST NOT CIRCULAR + CAMN C,I + JRST TYCGT4 ;B HAS TTY NUMBER OF GUY POINTING TO ME + MOVE B,C + JRST TYCGT3 + +TYCGT4: HRRZ C,TTYCOM(I) + PUSH P,B + PUSH P,C + PUSHJ P,TYCGT2 ;TAKE ME OUT OF COM MODE. + POP P,C + POP P,B + EXCH I,B + PUSHJ P,TYCSET + CAME C,I ;SKIP IF ONLY 1 IN LOOP BESIDES ME. IF SO, HE'S UNLINKED TOO. + JRST TYCGT5 +;MARK TTY IN I AS UNLINKED AND NOT N COM MODE. TYPE ^_N ON IT IF NECESSARY. +TYCGT2: HRRI Q,-1 + TLZ Q,400000+%TCLFT+%TCRFT + TLZN Q,%TCTPN + JRST TYCI17 + MOVEI T,[ASCIZ/N/] + PUSHJ P,TYCI40 + JRST TYCI17 + +TYCGT5: HRRM C,TTYCOM(I) ;TAKE ME OUT OF THE CIRCULAR LIST + MOVEI H,(B) + SETO TT, ;FOOL TEST AT TYCI66 + PUSHJ P,TYCREP ;TELL ALL THE OTHERS THAT I'VE LEFT. + PUSHJ P,TYCI73 + JFCL + POPJ P, + +TYCI73: JSP T,TYCI71 ;PRINT MSG AND MY UNAME ON TTY # IN I. + ASCIZ/ +BYE FROM / + +SUBTTL TTY OUTPUT INTERRUPT LEVEL + +OVHMTR TTO ;TTY OUTPUT INTERRUPT LEVEL + +;HANDLE AN OUTPUT INTERRUPT FROM A CHAR-AT-A-TIME CONTROLLER. +TYPSC: MOVEI B,1 + MOVEM B,DBBCC + MOVEM B,DBBCC1 + MOVE B,[444400,,STYICH] + MOVEM B,DBBBP +;HANDLE AN OUTPUT INT. ON A MULTI-CHAR CONTROLLER, ASSUMING +;COUNT AND B.P. ARE ALREADY SET UP. +TYP: LDB J,[220300,,TTYTYP(I)] ;GET TTY OUTPUT SPEED. +TYP0: ;COME HERE FOR DPK; J ALREADY SET UP. +IFN NNVTTS,[ + CAMN I,NOVATT + JRST TYP0N +] + HRRZ W,TCTYP(I) + MOVE T,TTYTYP(I) + MOVE H,TTYOPT(I) + HRRZ A,TTOALC(I) + JUMPE A,[SETOM TTYOAC(I) + JRST TYP1C] ;IF TTY HAS NO SPACE FOR ANY OUTPUT, STOP SENDING. + MOVE A,TIME + MOVEM A,TTLTM(I) ;UPDATE TIME OF LAST OUTPUT THIS TTY. +TYP0F: PUSHJ P,TYPLUP ;OUTPUT AT LEAST 1 CHAR. + SKIPGE TTYOAC(I) + JRST TYP1C + SKIPLE DBBCC ;SKIP IF OUT OF ROOM + JRST TYP0F ;CONTINUE MESSAGE +TYP1B: SKIPGE A,DBBCC + BUG ;CONTROLLER'S BUFFER OVERFILLED? + SUB A,DBBCC1 ;GET -<# CHARS WE ARE SENDING> + SKIPL E,A + BUG ;SENDING NO CHARS OR NEGATIVELY MANY? + ADD A,TTOALC(I) ;IF THE ALLOCATION ISN'T INFINITE, + TRNN A,400000 + HRRM A,TTOALC(I) ;DECREMENT IT BY # CHARS JUST OUTPUT. +IFN MTYP,[ + TRNN T,%TYMTY ;IF MTY ISN'T THE ONLY CONTROLLER, CHECK FOR THE OTHERS + JRST TYP1D + CONO MTY,@TTYLT(I) + DATAO MTY,MTYOW + POPJ P, + +TYP1D: ] +IFN DPKPP,[ + TRNN T,%TYDPK + JRST TYP1E + MOVN A,E ;- - # CHARS OUTPUT + ADDM A,@DPKC-NFDPTY(I) ;GIVES # OF CHARS FOR CONTROLLER. + XCT TTYST(I) ;TELL THE DPK THEY'RE THERE. + POPJ P, + +TYP1E:] +IFN DL10P,[ + TRNN T,%TYDL + JRST TYP1G + MOVNM E,DL10CC ;STORE # CHARS BEING SENT. + MOVE A,[340000,,DL10BF-1] + MOVEM A,DL10BP ;GIVE THE 11 ITS MAGIC POINTER TO SNARF THE BUFFER. + MOVEM I,DL10LN ;STORE LINE # OF TTY, THUS TELLING 11 TO GO AHEAD. + CONO DLC,100040+TTYCHN ;INTERRUPT 11 + POPJ P, +TYP1G:] +IFN KL10P,[ + TRNN T,%TYETY + JRST TYP1I + SKIPL DTEOUT + BUG ;OVER-RUNNING PREVIOUS TRANSFER + MOVE A,[441000,,DTEOBF] ;SET UP BYTE POINTER FOR 10-11 CHANNEL + MOVEM A,DTEBPO + MOVN A,E ;NUMBER OF CHARACTERS BEING SENT + HRLI A,%DCTYO(I);SEND TYPE-OUT COMMAND, AND LINE NUMBER + MOVEM A,DTEOUT ;GIVE COMMAND TO 11 + MOVEM A,DTEBBY ;FLAG BUFFER BUSY (AND REMEMBER WHICH COMMAND FOR DEBUGGING) + MOVEI A,10. ;5-SECOND TIMEOUT FOR LOST TO-11 XFER DONE INTERRUPT + MOVEM A,DTEBBT ;WHICH SEEMS TO HAPPEN NOW & THEN FOR SOME REASON + CONO DTE,%DBL11 ;AND GIVE INTERRUPT + POPJ P, +TYP1I:];KL10P + TRNN T,%TYSTY + JRST TYP1H + MOVEI A,TOBS + CAML A,TORM(I) + POPJ P, + MOVE A,TTYBYP(I) + ILDB B,A + JUMPE B,TYPEND + POPJ P, + +TYP1H: MOVE A,STYICH ;HANDLE CHAR-AT-A-TIME CONTROLLERS. + TLNN T,%TTPAR ;GENERATE A PARITY BIT IF NECESSARY. + JRST TYPDA1 + IMUL A,[2010040201] + AND A,[21042104377] + IDIVI A,17_7 + MOVE A,B +TYPDA1: CAIL I,NFDPTY + BUG + XCT TTYDO(I) ;DATAO XXX,A + POPJ P, + +TYP1C: MOVE E,DBBCC + CAME E,DBBCC1 ;SKIP IF NOTHING TO SEND + JRST TYP1F ;SEND WHAT THERE IS + XCT TTYDFF(I) ;CLEAR OUTPUT DONE + POPJ P, + +TYP1F: AOS TTYOAC(I) + JRST TYP1B + +IFN NNVTTS,[ +TYP0N: AOSE NVTSIP ;CHAR PENDING? + JRST TYP0A ;NO + DATAO NTY,NVTSSC ;SEND CHR AFTER SELECT + POPJ P, + +TYP0A: SKIPN A,NVOPTT + .ERR Shouldn't this be using NFNVTY Instead? + MOVEI A,NOTYS+NNTYS+NNVTTS-1 + MOVEM A,NNVSEC ;SET UP END CHECK + SKIPN I,NVOPTT + MOVEI I,NOTYS+NNTYS ;INITIALIZE + SETOM NNVSFL ;SET FIRST TIME THRU FLAG + MOVE A,NVTCC + CAIGE A,10 ;SENT TOO MANY CHRS TO THIS CONSOLE W/O LOOKING AT OTHERS? + JRST TYP ;NO, LOOK AT CONSOLE + SETZM NVOPTT + SETZM NVTCC ;YES LOOK AT OTHERS +TYP0C: AOS I + CAIL I,NOTYS+NNTYS+NNVTTS + SUBI I,NNVTTS + AOS NNVSFL + JRST TYP +] + +;FEED SOME CHARACTERS FROM OUTPUT BUFFER TO THE TTY. +TYPLUP: SKIPE TTYBYP(I) + JRST TYPBP + MOVE Q,TOOP(I) + MOVE E,TORM(I) +TYPLU1: CAIL E,TOBS + JRST [ MOVEM E,TORM(I) ;OUTPUT BUFFER EMPTY + MOVEM Q,TOOP(I) + JRST TYPEND ] + MOVE D,Q + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + ILDB A,Q ;GET NEXT CHARACTER FROM OUTPUT BUFFER + CAIL A,%TXDIS-1 ;IF DISPLAY OR CURSOR MOTION, DISPATCH. + JRST [ MOVEM E,TORM(I) ;LEAVING THE FAST LOOP + MOVEM D,TOOP(I) ;WITHOUT EATING THIS CHAR YET + CAIN W,%TNSFW ;"SOFTWARE" TTY GETS THE CODES + JRST TYPSFW ;AS THEY APPEAR IN THE BUFFER. + CAIL A,%TDMAX + JRST TYEEO1 + JRST @TYPDTB-%TXDIS(A)] + TLNN H,%TOSAI ;CTL CHARS ARE SPACING IFF SAIL CHAR SET; + CAIL A,40 ;NON-CONTROLS ARE SPACING. + AOS TTYIHP(I) +IFN MTYP,[ + JUMPE A,[ TRNE T,%TYMTY ;MTY CAN'T SEND NULLS EXCEPT AS FIRST CHAR IN WORD + PUSHJ P,MNULLO + JRST .+1 ;OUTPUT IT NOW + MOVE Q,D ;BACKUP BYTE POINTER AND OUTPUT IT LATER + JRST TYPLU2] +];MTYP + IDPB A,DBBBP ;PUT INTO DEVICE BUFFER + SOSLE DBBCC + AOJA E,TYPLU1 + AOS E ;MAXIMUM AMOUNT OF CRUFT GENERATED +TYPLU2: MOVEM E,TORM(I) + MOVEM Q,TOOP(I) + POPJ P, + +IFN MTYP,[ +MNULLO: MOVE A,DBBCC ;SKIPS IF NULL MAY NOT BE OUTPUT TO MTY NOW + SETZM DBBCC + SUBM A,DBBCC1 + MOVNS DBBCC1 + CAIE A,MTYNC + JRST POPJ1 + SETZB A,MTYOW + AOS DBBCC + AOS DBBCC1 + POPJ P, +];MTYP + +;HERE TO OUTPUT CHARACTER WHEN NOT IN FAST LOOP +TYPSIO: +IFN MTYP,[ + JUMPE A,[ TRNE T,%TYMTY ;MTY CAN'T SEND NULLS EXCEPT AS FIRST CHAR IN WORD + PUSHJ P,MNULLO + JRST .+1 ;OUTPUT IT NOW + POPJ P, ] ;WAIT +];MTYP + MOVEM Q,TOOP(I) ;REMOVE CHAR FROM OUTPUT BUFFER. + AOS TORM(I) + +;OUTPUT CHAR IN A TO TTY, AND LOOP BACK TO TYPLUP IF THERE IS +;ROOM FOR MORE CHARS. (OTHERWISE POPJ OUT OF TYPLUP). +TYPOU2: IDPB A,DBBBP ;FOR FAST CONTROLLERS, STICK CHAR IN LOW LVL BUFFER. + SOSLE DBBCC + JRST TYPLUP ;ROOM FOR MORE CHARS. + POPJ P, + +;ACTUALLY OUTPUT A CHAR TO THE TTY (AND POPJ). +TYPOUT: +IFN MTYP,[ + TRNE T,%TYMTY + JUMPE A,CPOPJ ;MTY CAN'T HANDLE NULLS. +] + IDPB A,DBBBP + SOSGE DBBCC + BUG + POPJ P, + +TYPSFW: TRNE T,%TYSTY ;STY TTY IN SOFTWARE MODE => + JRST TYPSFS ;SEND THE 8-BIT FROB + SUBI A,%TXDIS-2 ;ELSE SEND IT, ESCAPED BY A RUBOUT, WITH 176 + CAIE A,%TDMV0-%TXDIS+2 ; SUBTRACTED FROM IT SO FITS IN 7 BITS + CAIN A,%TDMV1-%TXDIS+2 + JRST [ MOVE E,TORM(I) ;FOR %TDMV1, MUST INCREMENT THE 2 ARGS. + CAILE E,TOBS-3 + JRST TYPEND + JRST TYPSF2] + CAIE A,%TDMOV-%TXDIS+2 + JRST TYPSF0 + MOVE E,TORM(I) ;AND FOR %TDMOV, MUST INCREMENT THE 4 ARGS SO THEY'RE NOT 0. + CAILE E,TOBS-5 ;IF NOT ALL IN BUFFER, WAIT FOR THEM. TTY WILL BE STARTED AGAIN. + JRST TYPEND +IRPS TYPSF1,,TYPSF4:TYPSF3:TYPSF2:TYPSF1: ;DIGIT MANY CHARS FOLLOW +TYPSF1: DPB A,Q ;STORE PREV. CHAR, FIXED UP. + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + ILDB A,Q + ADDI A,1 ;UPDATE %TDMOV ARGS BY ADDING 1. +TERMIN +TYPSF0: DPB A,Q ;OK, THE COMMANDS ARE ALTERED, SO SEND THE 177. + MOVEI A,%TXDIS-1 + JRST TYPOU2 + +IFE NETP,TYPSFS== +IFN NETP,[ +;HERE FOR OUTPUT OF 8-BIT FROB TO A SOFTWARE TTY THAT IS A STY +TYPSFS: CAIN A,%TDORS ;SKIPS INTO TYPORS +;HERE FOR %TDORS IN OUTPUT BUFFER +TYPORS: SKIPN TYPNTF + JRST TYPSIO +;HERE FOR %TDORS OUTPUT BY STY DIRECTLY INTO A NET SOCKET +IFN CHAOSP\TCPP, MOVE T,STYSTS-NFSTTY(I) ; Get flags for STY +IFN CHAOSP,[ + TLNE T,%SSCHA ; If Chaosnet, + JRST TYPOR1 ; don't send "INS" +];CHAOSP +IFN TCPP,[ + TLNN T,%SSTCP ; If TCP, send magic chars in URGENT mode. + JRST TYPOR2 + HRRZ A,STYNTI-NFSTTY(I) ; Get TCB index + SKIPL XBSTAT(A) ; Verify that COS is locked down + BUG HALT,[TCP: Buff not locked] + HLRZ T,XBOCOS(A) ; Find orig val of XBOBC + SUB T,XBOBC(A) ; Find # bytes already in buffer + CAIGE T, + BUG HALT ; Just-in-case check + MOVE H,STYORC-NFSTTY(I) ; Get magic 8-bit chars to send + TLNE H,(377_<<8.*3>+4>) ; Check 1st char + AOJA T,[TLNE H,(377_<<8.*2>+4>) ; Check 2nd char + AOJA T,[ TDNE H,[377_<8.+4>] ; Check 3rd char + AOJA T,.+1 + JRST .+1] + JRST .+1] + MOVEM T,XBSUP(A) ; Store # chars up to # including magic chars + ; as the TCP URGENT pointer. + JRST TYPOR1 +TYPOR2: +];TCPP +IFN NCPP,[ + HRRZ A,STYNTI-NFSTTY(I) ;GET NET INDEX + PI2SAF + MOVE T,IMFCQL ;IF INSUFFICIENT SPACE IN + CAIG T,2 ; THE CONTROL QUEUE, + JRST [ MOVSI T,200000 ; DEFER SENDING THIS + IORM T,IMSOC5(A) ;AND REQUEST TTY WAKEUP LATER + AOS IMNAS ;TELL 1/2 SECOND CLOCK + AOS IMNORH + MOVE T,TTYTYP(I) ;NEEDED BY TTY ROUTINES + JRST TYPEN1 ] + EXCH A,I ;A TTY IDX, I NET IDX + PUSH P,Q + PUSH P,IMPCSH + LDB T,IMSCFH + MOVEM T,IMPCSH ;SECRET ARGUMENT TO IMSTCM + JSP T,IMSTCM + 2,,1 + BUG PAUSE,[TTY: NO IMP BUFFERS AVAILABLE FOR "INS" MSG] + MOVSI B,8_10. ;INS + LDB C,IMSCLN ;LINK # + DPB C,[241000,,B] + MOVEM B,10(Q) + PUSHJ P,IMWCQ + POP P,IMPCSH + POP P,Q + MOVE I,A +] ;IFN NCPP +TYPOR1: MOVE H,TTYOPT(I) + MOVE T,TTYTYP(I) + MOVE W,TCTYP(I) + MOVEI A,STYORC-NFSTTY(I) ;TYPE OUT THE MAGIC CHARACTERS + HRLI A,440800 + JRST TYEEO2 +];NETP + +;COME HERE FROM TYPLUP WHEN THERE'S NOTHING TO TYPE OUT. +;CALL ALSO FROM TT11I4 WHEN THE PDP11 SAYS THE OUTPUT BUFFER IS EMPTY. +TYPEND: PUSHJ P,TYPEN2 +TYPEN1: SETOM TTYOAC(I) + POPJ P, + +;SUBROUTINE TO ACTIVATE ANY ECHOING ETC. THAT MAY NEED TO BE DONE +TYPEN2: SKIPGE TYOSW(I) ;IF ECHOING CAN BE DONE NOW, + SKIPL TTOALC(I) + POPJ P, + MOVE Q,TTYCOM(I) + TLNN Q,%TCDNG ;IS THERE ECHOING NEEDING TO BE DONE? + SKIPE ECHOC(I) + PUSHJ P,TTYI7 ;IF SO, QUEUE IT. + SKIPGE TTYLPP(I) + PUSHJ P,TTYI7 ;ALSO FORCE OUT BUFFERED CURSOR MVT. + POPJ P, + +IFN NNVTTS,[ +TYP5: CAMN I,NNVSEC ;REACHED END + AOSG NNVSFL ;AND NOT FIRST TIME + JRST TYP0C ;LOOK AT OTHER NOVA CONSOLES + MOVE I,NOVATT + JRST TYP1C +] + +;IF TTYBYP ISN'T 0, IT IS B.P. TO ASCIZ STRING TO TYPE. +;COME HERE TO OUTPUT THE NEXT CHAR OF THE STRING OR CLEAR TTYBYP. +TYPBP: ILDB A,TTYBYP(I) + TRZE A,400 ;KLUDGE FOR C-100 (and others) TO GET NULLS OUT +IFE MTYP,JRST TYPOU2 +.ELSE [ JRST [ TRNE T,%TYMTY + PUSHJ P,MNULLO ;MTY CAN'T SEND NULLS EXCEPT AS FIRST CHAR IN WORD + JRST TYPOU2 ;OUTPUT THE NULL NOW + MOVSI A,100000 ;BACK UP BYTE POINTER + ADDM A,TTYBYP(I) + POPJ P, ] ;OUTPUT PARTIAL WORD THEN SEND NULL NEXT TIME +];MTYP + JUMPN A,TYPOU2 ;NOT END => OUTPUT THE CHAR. + MOVE A,@TTYBYP(I) ;AT END, CHECK FOR SPECIAL + TRNE A,1 ; TEKTRONIX DELAY KLUDGE + JRST TYPBP1 +TYPBP2: CLEARM TTYBYP(I) ;END OF ASCIZ STRING. + JRST TYPLUP + +TYPBP1: MOVSI B,7700 ;CLEAR SIZE FIELD + ANDCAB B,TTYBYP(I) + LDB A,[$TTOSP,,TTYTYP(I)] + MOVM A,BAUDRT(A) ;GET BITS PER SECOND + MOVE B,1(B) ;GET SPECIFICATION WORD SAYING WHAT PADDING WE WANT. + CAMN B,[SETZ] + JRST TYPBP3 ;JUMP IF SPECIAL KLUDGE FOR TEKTRONIX + JUMPG B,TYPBP4 ;JUMP IF PADDING INDEPENDENT OF VPOS. +; this is fixed elsewhere now. +; MOVE Q,TCTYP(I) ;IS THIS AN H19 +; CAIN Q,%TNH19 ;H19'S HAVE TO BE PADDED WITH NUL's +; JRST TYPBP8 ; SO HANDLE THEM SPECIALLY + PUSHJ P,TYPBP6 ;CALCULATE NUMBER OF CHARACTERS OF PADDING NEEDED + JRST TYPBP5 + +TYPBP4: IMUL B,A ;1000. * NUMBER OF BITS PADDING + IDIVI B,10000. ;NUMBER OF CHARACTERS PADDING (NOTE ROUND-DOWN) +TYPBP5: SETZM TTYBYP(I) ;IN CASE NO PADDING REQUIRED + PUSHJ P,TYMPAD ;PUT THE PADDING BYTE POINTER INTO TTYBYP + JRST TYPLUP + +TYPBP3: IDIVI A,9 ;GET CHARACTERS PER 1.1 SECOND + SKIPL TTYIHP(I) ;KLUDGE KLUDGE + MOVNM A,TTYIHP(I) ;BUT IT'S GOTTA BE STORED SOMEPLACE + AOSL TTYIHP(I) + JRST TYPBP2 ;SIGH, DELAY COMPLETED + MOVEI A,^V ;NOT YET COMPLETED, SEND ANOTHER PAD + JRST TYPOU2 + +TYPBP6: MOVMS B + IMUL A,B ;IF NEGATIVE, TAKE ABS VALUE + MOVE B,TCMXV(I) ;TIMES NUMBER OF LINES AT AND BELOW THE CURSOR. + SUB B,TTYIVP(I) + IMUL B,A ; 1000.* NUMBER OF BITS OF PADDING + IDIVI B,10000.*8. ; DIVIDE BY 10000. TO GET NO. OF CHARS OF PADDING + ; AND THEN BY 8 BECAUSE PER LINE TIMES ARE EXPRESSED + POPJ P, ; IN TERMS OF 1/8 MS FOR BETTER RESOLUTION + +;once upon a time someone thought that this might cause padding with nulls to +;happen. It didn't work. +;TYPBP8: SKIPL TTYIHP(I) ;TO EXPAND UPON A KLUDGE +; JRST [ PUSHJ P,TYPBP6 ;CALCULATE THE # OF CHARS NEEDED +; MOVNM B,TTYIHP(I) ;AND SAVE THEM AWAY TO BE COUNTED +; JRST .+1 ] +; AOSL TTYIHP(I) ;COUNT THIS CHARACTER +; JRST TYPBP2 ; DELAY COMPLETED, RESET WORLD +; SETZ A, ;NUL! +; JRST TYPOU2 ;STUFF IT IN THE BUFFER, AND FIND WAY BACK HERE + +;COME HERE TO DO CURSOR MOTION ON PRINTING TTYS. +;TT HAS DESIRED HPOS; D HAS DESIRED VPOS. +TYMPRR: MOVE B,TCMXH(I) + SUBI B,1 + CAMGE B,TTYIHP(I) + MOVEM B,TTYIHP(I) +TYMPRT: CAIN W,%TNMEM + JRST [ CAMLE D,TTYIVP(I) ;VERTICAL MOTION NEEDED, AND CURSOR NOT AT LEFT MARGIN? + SKIPN TTYIHP(I) + JRST .+1 ;(PREVENT INFINITE CR LOOP). + SETZ TT, ;START WITH A CR. + JRST TYMPH1] ;MEMOWRECK LOSES LF'ING IN MID-LINE. + CAMGE TT,TTYIHP(I) ;BACKWARD MOTION TAKES PRIORITY. + JRST TYMPH1 + CAMLE D,TTYIVP(I) ;THEN DOWNWARD MOTION. + JRST TYMPV2 + CAMLE TT,TTYIHP(I) ;THEN FORWARD MOION. + JRST TYMPHF + MOVEM D,TTYIVP(I) ;MUST BE UPWARD MOTION + JRST TYMOV8 ;WHICH IS A NO-OP ON PRINTING TTYS. + +TYMPV2: AOS TTYIVP(I) ;MOVING DOWN: DO ONE LF + MOVEI A,^J + PUSHJ P,TYPOUT + PUSHJ P,TYMOVX ;IF REACHED GOAL, SAY FINISHED. + LDB B,[$TPPLF,,TTYOPT(I)] + CAIN W,%TNTRM + ADDI B,TYMTVT-TYMPVT + CAIN W,%TNMEM + ADDI B,TYMMVT-TYMPVT + HRRZ B,TYMPVT(B) ;# PADDING AFTER LF. + JUMPN B,TYMPAD + POPJ P, + +TYMPVT: 0 ;NORMAL + 2 ;2741, MEMOWRECK +REPEAT 6,2+.RPCNT ;EXTRA +TYMTVT: 0 ;UNPADDED TERMINET + 3 ;10CPS TERMINET + 4 ;15CPS TERMINET + 10 ;30CPS TERMINET + 17 ;60CPS TERMINET + 35 ;120CPS TERMINET (MAX SPEED) + 0 + 0 +TYMMVT: 0 ;UNPADDED WRECK + 0 + 0 + 1 ;30CPS WRECK + 2 ;60CPS +REPEAT 3,0 + +TYMPHF: LDB B,[$TPPTB,,TTYOPT(I)] ;FORWARD: CAN WE DO IT WITH TABS? + JUMPE B,TYMPH6 ;TABS NOT ALLOWED ON THIS TTY. + MOVE A,TTYIHP(I) + ANDCMI A,7 ;SEE WHERE A TAB WOULD BRING US. + ADDI A,10 + CAILE A,(TT) ;BEYOND WHERE WE WANT TO GO? + JRST TYMPH6 + SUBI A,(B) ;A HAS TAB STOP - <# PADDING>-1 + CAMG A,TTYIHP(I) ;TAB FASTER THAN SPACES (INCLUDING PADDING)? + JRST TYMPH6 ;NO, USE SPACES. + ADDI A,(B) ;A HAS TAB STOP. + MOVEM A,TTYIHP(I) + MOVEI A,^I + SOJA B,TYMPT1 ;B HAS # PADDING AFTER TAB. + +TYMPH6: MOVEI A,40 ;GO FORWARD WITH SPACES + MOVE C,[AOS TTYIHP(I)] + JRST TYMPH7 + +TYMPH2: MOVEI A,^H ;GO BACKWARD WITH BACKSPACES + MOVE C,[SOS TTYIHP(I)] +TYMPH7: MOVE B,TT + SUB B,TTYIHP(I) + MOVMS B ;HOW MANY TIMES TO PUT CHAR +TYMPH8: XCT C + IDPB A,DBBBP + SOSG DBBCC + JRST TYMOVY + SOJG B,TYMPH8 + JRST TYMOVX + +;COME HERE TO MOVE BACKWARDS. +TYMPH1: MOVE A,TTYIHP(I) + SUB A,TT ;A HAS # CHARS IF WE BACKSPACE. + LDB B,[$TPPCR,,TTYOPT(I)] + JUMPE B,TYMPH9 + MOVE E,B ;E HAS PADDING TYPE OF TTY, + MOVE B,TTYIHP(I) ;B HAS CURRENT HPOS. + CAIL E,<.BM $TPPCR,_-.TZ .BM $TPPCR>-TYMPHL+1 ;THIS ONE A SPECIAL $TPPCR CODE? + JRST @TYMPHT-<.BM $TPPCR,_-.TZ .BM $TPPCR>-1(E) + LDB C,[$TTOSP,,TTYTYP(I)] + SUBI C,2 ;(THIS ONLY WORKS FOR SPEED CODES 2,3,4,5) + ANDI C,3 ;(= 110, 150, 300, 1200 BAUD). + MOVE C,(C)[33. ? 20. ? 10. ? 5] + IDIV B,C ;1 PAD CHAR FOR EACH (33./20./10./5) SPACES TO MOVE. + ADDI B,1 ;I.E. MOVES AT 300/PADCODE COLUMNS PER SECOND + IMULI B,(E) ; OR 600/PADCODE COLUMNS PER SECOND AT 1200 BAUD + ADDI B,-1(E) +TYMPH9: MOVE C,D + SUB C,TTYIVP(I) ;IF WE'RE MOVING DOWN AFTER THE CR, HOW MANY LF'S? + JUMPLE C,TYMPH5 + SUB B,C ;EACH LF REDUCES # PADDING NEEDED BY CR. + CAIGE B, ;BUT CAN'T NEED LESS THAN 0 PADDING. + SETZ B, +;B HAS # CHARS PADDING NEEDED AFTER CR, IF WE DECIDE TO CR. +TYMPH5: TLNN H,%TOMVB ;HOW DO WE MOVE BACKWARD? + JRST TYMPH3 ;CAN'T BS => MUST CR AND SPACE FWD. + JUMPE TT,TYMPH3 ;GOING TO COLUMN 0 => ALWAYS CR + TLNN H,%TOOVR ;ON A GLASS TTY, IF STAYING ON THE SAME LINE, HAVE TO + JUMPLE C,TYMPH2 ; USE BACKSPACES TO NOT OBLITERATE PREVIOUS OUTPUT + LDB E,[$TPPTB,,TTYOPT(I)] + JUMPE E,[MOVE C,TT ;CAN'T USE TABS: C _ TIME IF MOVE FWD. + JRST TYMPT2] + PUSH P,B ;CAN USE TABS: SEE HOW LONG TO GO FWD + MOVE B,TT ;USING TABS. + IDIVI B,10 ;NEED C(B) TABS AND C(C) SPACES. + IMULI B,(E) ;B _ TIME NEEDED FOR TABS & PADDING. + ADDI C,(B) ;C _ TIME NEEDED TO GO FWD. + POP P,B +TYMPT2: ADDI C,1(B) ;ADD IN TIME TO CR, + PADDING. + CAMLE C,A + JRST TYMPH2 ;FASTER TO BACKSPACE. +TYMPH3: MOVEI A,^M ;OUTPUT A CR (WILL SPACE FORWARD LATER) + SETZM TTYIHP(I) ;WHEN WE COME BACK WE'LL SEE WE +TYMPT1: PUSH P,B ;NEED TO GO FORWARD. + PUSHJ P,TYPOUT + PUSHJ P,TYMOVX + POP P,B + JRST TYMPAD ;PAD THE TTY (# CHARS PADDING IN B) + +;DISPATCH TABLE FOR SPECIAL %TPPCR CODES. +TYMPHZ: TYMPEX ;EXECUPORT. + TYMP27 ;2741. + TYMPMW ;MEMOWRECK. + TYMPH5 ;CODE 7 NOT USED. +TYMPHT: TYMPHL==.-TYMPHZ + +TYMP27: IDIVI B,10. + CAILE B,14. + MOVEI B,14. + AOJA B,TYMPH5 + +TYMPMW: LDB E,[$TPPLF,,TTYOPT(I)] + JUMPE B,TYMPM1 ;NO CHRS + MOVNS B + ADD B,TYMPMT(E) + CAMGE B,TYMMVT(E) +TYMPM1: MOVE B,TYMMVT(E) + CAMLE D,TTYIVP(I) ;BEFORE LF'ING, MEMOWRECK + JRST TYMPH3 ;MUST CR RATHER THAN BS. + JRST TYMPH5 + +TYMPMT: 0 ;MEMOWRECK MIMIMUM LINE SIZE, AS FUNCTION OF SPEED + 8 ;VIA THE $TPPLF CODE. + 11. + 22. + 43. +REPEAT 3,0 + +TYMPEX: IDIVI B,10. ;EXECUPORT: 1 PAD CHAR FOR EVERY 10 POSITIONS TO CR THRU. + ADDI B,5 + JRST TYMPH9 + +;COME HERE TO PAD A PRINTING TERMINAL: # CHARS OF PADDING IN B. +TYMPAD: AOSG A,B ;AOS COMPENSATES FOR ILDB + POPJ P, + MOVE Q,TCTYP(I) ;is this an H19? + CAIN Q,%TNH19 ;H19's have to be nullified. I mean, padded with nulls. + JRST TYMPNL + CAILE A,199. ;DON'T TRY TO PAD MORE THAN 199 TIMES, WOULD + MOVEI A,199. ; BLOW OUT AT TYPBP1 + IDIVI A,5 + MOVNS A + ADD A,TYMPA1(B) ;CREATE A BP TO A STRING WITH THE RIGHT # OF RUBOUTS. + MOVEM A,TTYBYP(I) + POPJ P, +TYMPNL: CAILE A,399. ;we make an exception for H19's, which need a lot of + MOVEI A,399. ;padding. + IDIVI A,4 ;This works same as with rubouts, but for 9 bits + MOVNS A + ADD A,TYPNL1(B) + MOVEM A,TTYBYP(I) + POPJ P, + +;THIS IS AN ASCIZ STRING OF 199. RUBOUTS. +;SOME FINAL SEGMENT OF IT WILL BE TYPED OUT. +TYMPA0: REPEAT 199./5, -2 +TYMPA2: -400 + +TYMPA1: 010700,,TYMPA2 + 100700,,TYMPA2 + 170700,,TYMPA2 + 260700,,TYMPA2 + 350700,,TYMPA2 + +;This is a not-quite ASCIZ string of 399. pseudo-nulls. They are 9 bits long so +;that the typeout loop will spot the high bit and see that we're not at the end. +;This is used by things that want to be padded with nulls, like h19s. +TYPNL0: REPEAT 399./4,<.BYTE 9 ? 400 ? 400 ? 400 ? 400> +TYPNL2: 400400400000 + +TYPNL1: 001100,,TYPNL2 + 111100,,TYPNL2 + 221100,,TYPNL2 + 331100,,TYPNL2 + +;DISPATCH TABLE FOR CURSOR CONTROL CMDS AND RUBOUT + TYPSIO ;RUBOUT DISPATCHES HERE +TYPDTB: OFFSET %TDMOV-. +%TDMOV::TYMOV ;MOVE CURSOR +%TDMV1::TYMOV2 ;DUMMY COMMAND CREATED BY TYMOV. + ;MAKES IT POSSIBLE FOR TYMOV TO STOP WHEN BUFFER FULL + ;AND BE REENTERED NEXT INTERRUPT. +%TDEOF::TYEEOF ;CLEAR REST OF PAGE +%TDEOL::TYEEOL ;CLEAR REST OF LINE +%TDDLF::TYEDLF ;DELETE FORWARD (FOR ERASABLE OVERPRINTING TTYS) +%TDMTF::TYEMTF ;MOTOR OFF (FOR TERMINETS) +%TDMTN::TYEMTN ;MOTOR ON (FOR TERMINETS) +%TDCRL::TYECRL ;CRLF ON DATAPOINTS, IMLACS. +%TDNOP::TYEEO1 ;NO-OP FOR SUPERDUPERIMAGE MODE. +%TDBS:: TYEBS ;BACKSPACE (FOR TTY'S WITH %TORAW SET). +%TDLF:: TYELF ;LINEFEED ("). +%TDRCR::TYERCR ;CARRET ("). +%TDORS::TYPORS ;"OUTPUT RESET" FOR SAKE OF SOFTWARE TTYS & STYS +%TDQOT::TYEQOT ;DEVICE-DEPENDENT DATA IN NEXT BYTE. +%TDFS:: TYEFS ;FORWARD ONE SPACE +%TDMV0::TYMV0 ;REPLACEMENT FOR %TDMOV +%TDCLR::TYECLR ;CLEAR THE SCREEN +%TDBEL::TYEBEL ;DING THE BELL. +%TDINI::TYEINI ;REINITIALIZE INTELLIGENT TERMINAL +%TDILP::TYEILP ;INSERT LINE POSITION, FOLLOW BY COUNT +%TDDLP::TYEDLP ;DELETE LINE POSITION, FOLLOW BY COUNT +%TDICP::TYEICP ;INSERT CHARACTER POSITION, FOLLOW BY COUNT +%TDDCP::TYEDCP ;DELETE CHARACTER POSITION, FOLLOW BY COUNT +%TDBOW::TYEBOW ;ENTER INVERSE VIDEO MODE +%TDRST::TYERST ;CLEAR ALL SPECIAL MODES (SUCH AS INVERSE VIDEO). +%TDGRF::TYEEO1 ;GRAPHICS, FLUSH IT +%TDRSU::TYERSU ;REGION SCROLL UP +%TDRSD::TYERSD ;REGION SCROLL DOWN + TYEEO1 ;NEXT 4 CODES ARE USED FOR SOME WEIRD FORM OF GRAPHICS OUTPUT + TYEEO1 ;THAT WILL EVENTUALLY BE FLUSHED. + TYEEO1 + TYEEO1 +;FOLLOWING CODES ARE FOR LOCAL EDITING TERMINALS +;NON-SOTFWARE TERMINALS DON'T HANDLE THEM, SO IGNORE THEM. +%TDSYN::TYEIG1 ;RESYNCH REPLY TO LOCAL EDITING TERMINAL. IGNORE 1 ARG. +%TDECO::TYEEO1 ;ASK TERMINAL TO TRY LOCAL EDITING BY SENDING A RESYNCH. IGNORE. +%TDEDF::TYEIG2 ;SET LOCAL EDITING TERMINAL COMMAND DEFINITION. IGNORE 2 ARGS. +%TDNLE::TYEEO1 ;STOP DOING LOCAL EDITING. IGNORE. +%TDTSP::TYEEO1 ;DISPLAYS LIKE SPACE, BUT IS PART OF A TAB. IGNORE. SHOULDN'T HAPPEN. +%TDCTB::TYEEO1 ;THIS LINE IS CONTINUED AT THE BEGINNING. +%TDCTE::TYEEO1 ;THIS LINE IS CONTINUED AT THE END. +%TDMLT::TYEIG2 ;DECLARE MULTI-POSITION CHAR FOR LOCAL EDITING. IGNORE 2 ARGS. +%TDSVL::TYEIG3 ;SAVE LINE CONTENTS. IGNORE 3 ARGS. +%TDRSL::TYEIG3 ;RESTORE LINE CONTENTS. IGNORE 3 ARGS. +%TDSSR::TYEIG2 ;SET RANGE OF COLUMNS TO SAVE. IGNORE 2 ARGS. +%TDSLL::TYEIG2 ;SET LABEL FOR LOCAL LINE SAVING. IGNORE 2 ARGS. +%TDMAX::OFFSET 0 + + +;IGNORE THIS COMMAND AND 3 ARGS. +TYEIG3: MOVE A,TORM(I) + CAILE A,TOBS-4 + JRST TYPEND + AOS A,TORM(I) + IBP Q +;IGNORE THIS COMMAND AND 2 ARGS. +TYEIG2: MOVE A,TORM(I) + CAILE A,TOBS-3 + JRST TYPEND + AOS A,TORM(I) + IBP Q +;IGNORE THIS COMMAND AND 1 ARG. +TYEIG1: MOVE A,TORM(I) + CAILE A,TOBS-2 + JRST TYPEND + AOS A,TORM(I) + IBP Q + JRST TYEEO1 + +TYEQOT: MOVE A,TORM(I) + CAILE A,TOBS-2 + JRST TYPEND + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + ILDB A,Q + AOS TORM(I) + JRST TYPSIO + +TYEBEL: MOVEI A,7 + JRST TYPSIO + +;%TDMOV MOVE CURSOR COMMAND DISPATCHES HERE. +TYMOV: MOVE A,TORM(I) + CAILE A,TOBS-5 ;IF THE 4 ARGUMENT CHARS AREN'T IN THE BUFFER YET, + JRST TYPEND ;GO AWAY; WILL COME BACK WHEN THEY ARE OUTPUT. + CAMN Q,TOBEP(I) ;FETCH THE NEXT 2 CHARS WHICH + MOVE Q,TOBBP(I) ;HOLD THE "OLD" POSITION + ILDB A,Q + MOVEM Q,TOOP(I) ;FLUSH FIRST TWO CHARS (AS IF WAS %TDMV0) + MOVEI C,2 + ADDM C,TORM(I) + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + ILDB B,Q + CAMGE A,TCMXV(I) + MOVEM A,TTYIVP(I) ;SET INITIAL STARTING PLACE + MOVEM B,TTYIHP(I) + JRST TYMV0A + +TYMV0: MOVE A,TORM(I) ;MAKE SURE THE TWO ARG CHARS ARE IN THE BUFFER + CAILE A,TOBS-3 + JRST TYPEND ;GO AWAY; WILL COME BACK WHEN THEY ARE OUTPUT. +;DROPS THROUGH + ;DROPS IN +;%TDMOV COMMAND ON ALL TERMINALS. +TYMV0A: MOVSI C,%TCPAD+%TCFPD ;FOR DATAPOINTS, PADDING WILL BE NECESSARY NOW. + ANDCAM C,TTYCOM(I) ; ALSO, CLEAR FPD IF IT GOT LEFT ON SOMEHOW + MOVEI A,%TDMV1 ;PUT A NEW COMMAND IN OUTPUT BUFFER + DPB A,Q ; IN CASE WE FILL UP BUFFER AND HAVE TO COME BACK. + ; IN THAT CASE WILL RETURN TO TYMOV2. +;BUFFER NOW HOLDS: +; %TDMV1 ? NEW VPOS ? NEW HPOS +TYMOV2: CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) ;FETCH DESIRED POS. FROM BUFFER. + ILDB D,Q + CAML D,TCMXV(I) + SETZ D, + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + ILDB TT,Q + CAIGE W,%TNMAX ;If pointer to routine is within range, + JUMPGE W,@TYMDTB(W) ;GO TO DEVICE-DEPENDENT CURSOR POSITIONING ROUTINE + BUG + +TYMDTB: OFFSET -. +%TNPRT::SETZ TYMPRT ;PRINTING +%TNDP:: TYMDP ;DATAPOINT +%TNODP::TYMDP ;LOSING DATAPOINT +%TNIML::TYMIML ;IMLAC +%TNTEK::TYMDP ;TEKTRONIX +%TNTV:: [JRST 4,.+TYMDTB] +%TNMEM::SETZ TYMPRT ;MEMOWRECK +%TNSFW::[JRST 4,.+TYMDTB] +%TNTRM::SETZ TYMPRT ;TERMINET +%TNESC::TYMDP ;ASCII ESCAPE SEQUENCES TTY +%TNDTM::TYMIML ;DATAMEDIA +%TNRAY::TYMDP ;TELERAY 1061 +%TNHDS::TYMDP ;HDS CONCEPT-100 +%TNH19::TYMH19 ;H19 +%TNAAA::TYMAAA ;Ann Arbor Ambassador +%TNMAX::OFFSET 0 + +;DISPLAY TERMINALS THAT HAVE RELATIVE CURSOR POSITIONING +TYMDP: MOVE A,TTYIVP(I) ;CURRENT HARDWARE VERTICAL POSITION + SUB A,D ;SUBTRACT VERTICAL POSITION OF WHERE WE WANT TO BE + MOVMS A ;A IS HOW FAR WE HAVE TO GO UP OR DOWN + CAML TT,TCMXH(I) ;IF TRYING TO MOVE OFF RIGHT MARGIN, + JRST [ MOVE TT,TCMXH(I) ;CODE JUST BELOW CAUSES INFINITE LOOP + SOJA TT,.+1 ] ;SO PRETEND MOVING TO MARGIN + MOVE B,TTYIHP(I) ;COMPUTE NET CHRS TO POSITION + CAML B,TCMXH(I) ;IF WE THINK WE MOVED OFF THE END OF THE LINE, + JRST [ MOVE B,TCMXH(I) ;PRESUMABLY BY PRINTING IN THE LAST COLUMN, + SUBI B,1 ;THE CURSOR ACTUALLY STUCK IN THE LAST COLUMN + MOVEM B,TTYIHP(I) + JRST .+1 ] + SUB B,TT + MOVM C,B ;C IS HOW FAR WE HAVE TO GO HORIZONTALLY + TRNE H,%TPPTB ;IF TERMINAL HAS TABS + JRST TYMTB1 ;USE DIFFERENT CURSOR POSITIONING ROUTINE + CAMLE B,TT ;SKIP IF NOT SHORTER TO CR FIRST + MOVEI C,1(TT) ;# CHARS IF CR FIRST. + ADD A,C ;A NOW HAS TOTAL NUMBER OF CHARS TO SEND TO GET THERE + JUMPE A,TYMOV8 ;WE'RE THERE + MOVE C,D + ADDI C,1(TT) ;C HAS NUMBER OF CHARS IT WOULD TAKE IF WE HOMED UP FIRST + MOVE E,TCMXV(I) + SUBI E,1 + SUB E,D ;E HAS NUMBER IF HOME DOWN FIRST + JUMPL E,TYPCPG + ADD E,TT + CAMGE C,A + JRST TYMHU ;HOME UP SHORTER + CAMGE E,A + JSP A,TYMHD ;HOME DOWN SHORTER +TYPCPG: JUMPL B,TYMDP3 ;H POS TOO SMALL, MOVE FWD + JUMPG B,TYMDP6 ;MOVE BACKWARD (EITHER BS OR CR). +TYMDPL: MOVE B,TTYIVP(I) + SUB B,D + JUMPG B,TYMDP2 ;MOVE UP IF NECESSARY + JUMPL B,TYMDP1 ;OR DOWN. + JRST TYMOV8 ;OR WE'RE DONE. + +TYMDP3: JSP E,TYMDPP ;PAD IF NEC. + MOVE C,[AOS TTYIHP(I)] + SKIPL A,CCFS(W) ;GET FORWARD SPACE CHARACTER + JRST TYMDP7 ;IS ONE CHAR + HRRZS A + JRST TYMVT7 ;IS TWO CHARS + +TYMDP6: CAMG B,TT + JRST TYMDP8 +TYMTB6: MOVEI A,15 ;BETTER TO CR FIRST + CAIE W,%TNODP + CLEARM TTYIHP(I) + MOVEI B,1 + MOVSI C,(JFCL) + CAIE W,%TNODP + JRST TYMDP5 + MOVE E,TCMXV(I) + SUBI E,1 + CAMN E,TTYIVP(I) ;ON LOSERS, AFTER CR MUST GO LF TO TURN OFF SPOW MODE. + JRST TYMDP2 ;IF ON BOTTOM LINE, GO UP BEFORE CR SO CAN GO DOWN AFTER. + MOVE E,TTYCOM(I) + TLCN E,%TCFPD + MOVEM E,TTYCOM(I) + TLNE E,%TCFPD + JRST TYMDP5 ;JUMP IF HAVEN'T DONE CR YET + JSP E,TYMDPP ;AFTER CR, PAD + JRST TYMHU3 ;THEN GO SETZM TTYIHP(I) AND TURN OFF SPOW LATCH + +TYMDP8: JSP E,TYMDPP + MOVE C,[SOS TTYIHP(I)] + MOVEI A,%DPBS ;DATAPOINT BACK-SPACE. + JRST TYMDP7 + +TYMDP1: JSP E,TYMDPP + MOVEI A,%DPDN ;DATAPOINT LINEFEED. + MOVE C,[AOS TTYIVP(I)] + JRST TYMDP7 + +TYMDP2: JSP E,TYMDPP + MOVE C,[SOS TTYIVP(I)] + SKIPL A,CCUP(W) ;GET LINE-STARVE CHARACTER + JRST TYMDP5 + HRRZS A + JRST TYMVT7 ;IT'S TWO CHARS LONG + +TYMHU: SKIPN CCHUP(W) ;SKIP IF TTY CAN HOME UP + JRST TYPCPG + CAMLE C,E ;HOME UP IS BETTER THAN DIRECT ROUTE. + JSP A,TYMHD ;MAYBE HOME DOWN IS EVEN BETTER + CAIN W,%TNODP + JRST TYMHU1 + CLEARM TTYIVP(I) ;NO, HOME UP IS BEST. + CLEARM TTYIHP(I) +TYMHU2: MOVE A,CCHUP(W) + MOVEM A,TTYBYP(I) + JRST TYMOVX + +TYMHU1: MOVE E,TTYCOM(I) ;HERE FOR HOME UP ON DISAPPOINT + TLCN E,%TCFPD + MOVEM E,TTYCOM(I) + TLNE E,%TCFPD + JRST TYMHU2 ;JUMP IF HAVEN'T HOMED UP YET + MOVSI E,%TCPAD ;DON'T PAD AFTER HOME UP + IORM E,TTYCOM(I) + SETZM TTYIVP(I) ;AND TURN OFF THE SPOW LATCH +TYMHU3: MOVSI E,%TCFPD ;FIRST PART WILL HAVE BEEN DONE WHEN + ANDCAM E,TTYCOM(I) ; WE PUT OUT THE ONE CHAR TO GO DOWN ONE LINE + SETZM TTYIHP(I) + MOVEI B,1 ;GO DOWN ONE LINE TO RESET SPOW + JRST TYMDP1 + +TYMDP7: MOVMS B +TYMDP5: JUMPE A,[JRST 4,.] +TYMDP4: XCT C + IDPB A,DBBBP + SOSG DBBCC + JRST TYMOVY + SOJG B,TYMDP4 + JRST TYMOVC + +;CAN'T OUTPUT ANY MORE: IF REACHED DESIRED POS, FLUSH THE +;%TDMV1; OTHERWISE RETURN LEAVING IT TO COME BACK HERE WHEN +;TTY CAN ACCEPT MORE OUTPUT. +TYMOVY: SOJG B,TYMOVP +TYMOVX: CAMN D,TTYIVP(I) + CAME TT,TTYIHP(I) + POPJ P, +;WE USED UP ALL THE SPACE BUT GOT WHERE WE'RE GOING. +TYMOV9: MOVEM Q,TOOP(I) ;FLUSH THE %TDMV1 COMMAND. + MOVEI B,3 + ADDM B,TORM(I) + POPJ P, + +;WE FINISHED ONE SET OF OUTPUT CHARS, & HAVE ROOM FOR MORE. +;EITHER CONTINUE MOVING CURSOR, OR LOOK FOR NEXT THING TO DO. +TYMOVC: CAME TT,TTYIHP(I) + JRST TYMDP ;HORIZ POS STILL NEEDS CHANGING. + CAME D,TTYIVP(I) + JRST TYMDPL ;VERT POS STILL NEEDS CHANGING. +TYMOV8: MOVEM Q,TOOP(I) ;FLUSH THE %TDMV1 COMMAND + MOVEI B,3 + ADDM B,TORM(I) + JRST TYPLUP ;AND GO GET NEXT THING FROM BUFFER. + +;COME HERE TO PAD DATAPOINT IF NECESSARY. +;CALL WITH JSP E,. CLOBBERS A, C. +;MAY JUMP AWAY TO PAD, IN WHICH CASE TYMDP WILL BE RE-ENTERED LATER. +TYMDPP: MOVSI C,%TCPAD + TDNE C,TTYCOM(I) ;PADDING ALREADY DONE FOR THIS COMMAND => RETURN. + JRST (E) + LDB A,[$TPPCR,,TTYOPT(I)] + JUMPE A,(E) ;RETURN IF THIS TTY NOT PADDED. + MOVE B,A + IORM C,TTYCOM(I) ;AFTER WE PAD, PADDING WON'T BE NECESSARY. + MOVEI A,177 + MOVSI C,(JFCL) + JRST TYMDP5 ;GO OUTPUT THEM. + +TYMOVP: CAIE A,177 + POPJ P, + JRST TYMPAD + +;JSP A,TYMHD IF HOME-DOWN LOOKS BEST +TYMHD: CAIE W,%TNDP + JRST (A) ;BUT HOME-DOWN ONLY WORKS ON DATAPOINTS + SETZM TTYIHP(I) ;HOME DOWN IS BEST. + MOVE C,TCMXV(I) + SUBI C,1 + MOVEM C,TTYIVP(I) + MOVE A,CCHDP + MOVEM A,TTYBYP(I) + JRST TYPLUP + +;HERE TO SEND ONE OR MORE COPIES OF AN ESCAPE SEQUENCE. +;ESCAPED CHAR IN A. # TIMES IN B. INSN TO ADJUST TTYIVP,TTYIHP IN C. +TYMVT7: MOVMS B +TYMVT5: MOVE E,TTYCOM(I) ;STOPPED IN MIDDLE OF ESC SEQ? + TLZN E,%TCFPD + JRST TYMVT4 + MOVEM E,TTYCOM(I) ;YES, SKIP INITIAL ESC + JRST TYMVT6 + +TYMVT4: MOVEI E,33 + IDPB E,DBBBP + SOSG DBBCC ;NO MORE ROOM => + JRST TYMVT3 ;STOPPED WITHIN ESC SEQUENCE +TYMVT6: XCT C ;ELSE SEND THE ESCAPED CHAR + IDPB A,DBBBP + SOSG DBBCC + JRST TYMOVY ;NO ROOM => DISMISS + SOJG B,TYMVT4 ;ELSE SEND NEXT ESC SEQ + JRST TYMOVC ;FLUSH THE %TDMOV AND RETURN + +TYMVT3: MOVSI E,%TCFPD + IORM E,TTYCOM(I) + POPJ P, + +;CURSOR POSITIONING ON A DISPLAY TTY WITH TABS +TYMTB1: MOVE R,TT + IDIVI R,8 + ADD R,TYMTBC(W) ;COST OF TABBING TO DEST FROM LEFT MARGIN + MOVE W,TCTYP(I) ;RESTORE W, CLOBBERED BY IDIVI + JUMPG B,TYMTB2 ;JUMP IF MOVING BACKWARDS + JUMPE B,TYMTB3 ;JUMP IF NOT MOVING HORIZONTALLY + SKIPGE CCFS(W) + ADD C,C ;MOVING FORWARDS IS SLOW ON ESCAPE-C TYPE TERMINAL + MOVE E,TTYIHP(I) + LSH E,-3 + SUBM R,E ;COST OF TABBING FROM WHERE WE ARE NOW + CAMLE C,E + MOVE C,E ;FASTER IF TABS ARE USED + JRST TYMTB3 ;MOVING FORWARD, SO CR CAN'T HELP + +TYMTB2: CAILE C,1(R) + MOVEI C,1(R) ;BETTER TO CR FIRST +TYMTB3: ADD A,C ;TOTAL # CHARS TO BE SENT IF RELATIVE POSITIONING USED + JUMPE A,TYMOV8 ;WE'RE THERE + MOVE E,D + ADDI E,2(R) ;COST IF HOME-UP FIRST (ASSUMING HOME-UP IS 2 CHARS) + CAMG E,A + MOVE A,E ;RELATIVE POSITIONING SHOULD START WITH HOME-UP + CAILE A,4 ;COMPARE RELATIVE AND ABSOLUTE POSITIONING + TRNN H,2*%TPPTB + JRST TYMTB8 ;RELATIVE POSITIONING BETTER OR ONLY CHOICE +;USE ABSOLUTE POSITIONING, DROP INTO STRAIGHT ABS POS CODE. +;HERE FOR DIRECT POSITIONING ON IMLAC AND DATA MEDIA. SEND MAGIC CHARACTER +;FOLLOWED BY HORIZONTAL AND VERTICAL POSITION, OFFSET BY SUITABLE AMOUNT +;D FOR THE VERTICAL, TT FOR THE HORIZONTAL +TYMIML: MOVE Q,TOOP(I) ;CLOBBER OVER THE 3 CHARS IN OUTPUT BUFFER + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + HLRZ A,CCDPSO(W) ;GET ABS-POSITIONING CHARACTER, IT WILL + IDPB A,Q ; BE FOLLOWED WITH VERTICAL, HORIZONTAL COORDS + MOVEM D,TTYIVP(I) ;CURSOR WILL END UP HERE + MOVEM TT,TTYIHP(I) + TRNE A,200000 + EXCH D,TT ;SEND HORIZONTAL THEN VERTICAL + HRRZ E,CCDPSO(W) ;GET TABLE INDEX + MOVE B,D ;FIRST COORD TO SEND + XCT CCDPSM(E) ;MUNG B APPROPRIATELY + ANDI B,177 ;EXTRA BITS CAUSE TROUBLE LATER + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + IDPB B,Q + MOVE C,B ;SAVE + MOVE B,TT ;SECOND COORD TO SEND + XCT CCDPSM(E) ;MUNG B APPROPRIATELY + ANDI B,177 ;EXTRA BITS CAUSE TROUBLE LATER + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + IDPB B,Q + ANDI A,177 ;DON'T LET TYPLUP THINK THESE CHARACTERS PRINT + TLNN H,%TOSAI + CAIL A,40 + SOS TTYIHP(I) + TLNN H,%TOSAI + CAIL B,40 + SOS TTYIHP(I) + TLNN H,%TOSAI + CAIL C,40 + SOS TTYIHP(I) + SKIPL A,CCDPSO(W) + JRST TYPLUP + MOVEI A,33 ;PUT AN ESC BEFORE IT + JRST TYPOU2 + +TYMTB8: CAMN E,A + JRST TYMHU ;HOME-UP FIRST + JUMPL B,TYMTB4 ;JUMP IF MOVING TO THE RIGHT + JUMPE B,TYMDPL ;JUMP IF NOT MOVING HORIZONTALLY + CAIE C,1(R) ;MOVING TO THE LEFT, SKIP IF SHOULD CR FIRST + JRST TYMDP8 ;NO, JUST BS + JRST TYMTB6 ;GO CR + +TYMTB4: MOVE E,TT ;DESTINATION COLUMN + TRO E,7 ;ENSURE NO BORROW + MOVEI A,1(E) ;COLUMN TO TAB TO THEN BACKSPACE BACK + CAMGE A,TCMXH(I) ;BE SURE NOT TO TAB OFF THE RIGHT MARGIN + TRNN TT,4 ;SKIP IF FASTER TO TAB PAST AND BACKSPACE BACK + JRST TYMTB5 ;JUMP IF BETTER TO TAB THEN FORWARD-SPACE + CAMN B,[-1] + JRST TYMDP3 ;MOVING A SHORT WAY, JUST SEND A FORWARD-SPACE + MOVEI B,8(E) + SUB B,TTYIHP(I) + LSH B,-3 ;# TABS TO GET PAST DESTINATION +TYMTB7: MOVEI A,^I + MOVEI E,7 + ANDCAM E,TTYIHP(I) ;ALIGN TTYIHP WITH TAB STOPS + MOVE C,[ADDM E,TTYIHP(I)] ;EACH TAB ADVANCES TTYIHP BY 8 + AOJA E,TYMDP5 ;GO TAB + +TYMTB5: SUB E,TTYIHP(I) ;COMPUTE # TABS TO GET JUST TO + LSH E,-3 ; THE LEFT OF THE DESTINATION + JUMPE E,TYMDP3 ;WE'RE CLOSE, DO FORWARD SPACES + MOVE B,E ;TAB FIRST + JRST TYMTB7 + +TYMTBC: 0 ? 2 ? 4 ? 6 ;COST OF MOVING RIGHT FROM A TAB STOP + 1+4 ? 1+3 ? 1+2 ? 1+1 ;COST OF TABBING ONE MORE AND BACKSPACING BACK + +;setup routine for TYMH19, TYMAAA. Gets magnitude of horizontal and vertical +;motion in B and A, destinations in TT and D respectively, sets TTYIHP and +;TTYIVP. +TYMPOS: MOVE A,TTYIVP(I) ;current hardware vertical position + SUBM D,A ;subtract from vertical destination + CAML TT,TCMXH(I) ;if trying to move off right margin, + JRST [ MOVE TT,TCMXH(I) ;pretend moving to margin + SOJA TT,.+1 ] + MOVE B,TTYIHP(I) ;compute net chrs to position + CAML B,TCMXH(I) ;if we think we moved off the end of the line, + JRST [ MOVE B,TCMXH(I) ;presumably by printing in the last column, + SUBI B,1 ;the cursor actually stuck in the last column + MOVEM B,TTYIHP(I) + JRST .+1 ] + SUBM TT,B ;now we have horizontal motion in B + MOVEM D,TTYIVP(I) ;put vertical, horizontal destination + MOVEM TT,TTYIHP(I) ;into registers (we'll be there soon). + POPJ P, + +;cursor positioning on an H19. TYMDP occasionally stuffs rubouts into the +;buffer to do its own padding, thereby resulting in ^S ^Q lossage on H19s. I +;could patch TYMDP up, but it's too silly. Generates HCUF, HCUB, HCUD, HCUU, +;or HDCA. +TYMH19: PUSHJ P,TYMPOS ;get horizontal and vertical destinations, etc. + MOVEI C,2 ;now flush the first two chars of cursor + ADDM C,TORM(I) ;motion command (TYEEO2 will flush last) + MOVE C,TOCMBF(I) ;get byte pointer to tty command buffer in C + MOVEI E,33 + IDPB E,C ;send esc + JUMPE A,TYMHOX ;if vertical magnitude 0, only moving in X + JUMPE B,TYMHOY ;same for horizontal and Y +TYMABS: MOVEI E,"Y ;neither is 0, abs. positioning faster + IDPB E,C + ADDI D,40 ;convert line # to H19 coord system. + IDPB D,C + ADDI TT,40 ;convert column # to H19 coord system + IDPB TT,C +TYMHDN: MOVEI E,0 ;top it off with a null + IDPB E,C + MOVE A,TOCMBF(I) ;TYEEO2 wants bp in A + JRST TYEEO2 ;noone seems to think it's necessary to pad + +TYMHOX: CAIN B,1 ;if 1 or -1, then relative positioning is + JRST TYMHX2 ;plenty fast + CAIN B,-1 + JRST TYMHX3 + JRST TYMABS ;otherwise absolute positioning is faster +TYMHX2: MOVEI E,"C ;moving forward one space + IDPB E,C + JRST TYMHDN +TYMHX3: MOVEI E,"D ;moving backwards one space + IDPB E,C + JRST TYMHDN + +TYMHOY: CAIN A,1 ;if 1 or -1, then relative positioning is + JRST TYMHY2 ;plenty fast + CAIN A,-1 + JRST TYMHY3 + JRST TYMABS ;otherwise absolute positioning is faster +TYMHY2: MOVEI E,"B ;moving down one line + IDPB E,C + JRST TYMHDN +TYMHY3: MOVEI E,"A ;moving up one line + IDPB E,C + JRST TYMHDN + +;cursor positioning on an AAA. Generates either CUP, HPA, or VPA, +;whichever involves fewest chars. +TYMAAA: PUSHJ P,TYMPOS ;get X-Y motion and set dests. + MOVEI C,2 ;now flush the first two chars of cursor + ADDM C,TORM(I) ;motion command (TYEEO2 will flush last) + MOVE C,TOCMBF(I) ;get byte pointer to tty command buffer in C + MOVEI E,33 + IDPB E,C ;send esc + MOVEI E,"[ ;[ + IDPB E,C + JUMPE B,TYMAVT ;going vertically only + JUMPE A,TYMAHZ ;horizontally only + JUMPE D,TYMAP3 ;if going to top line, optimize out 1st coord + MOVE E,D + PUSHJ P,SNDNUM ;send vertical coord + JUMPE TT,TYMAP5 ;if moving to leftmost col no second coord +TYMAP3: MOVEI A,73 ;or semicolon + IDPB A,C + MOVE E,TT + PUSHJ P,SNDNUM ;send horizontal coord +TYMAP5: MOVEI A,"H ;absolute positioning char + JRST TYMADN +;going vertically only, use vertical absolute positioning +TYMAVT: MOVE E,D + PUSHJ P,SNDNUM + MOVEI A,"d ;vertical absolute positioning char + JRST TYMADN +;going horizontally only, horizontal absolute positioning +TYMAHZ: MOVE E,TT + PUSHJ P,SNDNUM + MOVEI A,"` ;horizontal absolute positioning char +;fall through into done code + +TYMADN: IDPB A,C ;send that last char + MOVEI A,4 ;padding is A*TT in ms + MOVEI TT,1 ;4 ms of padding ought to be enough + JRST TYDAPD ;go set it up + +;Add one to the number in E, convert it to ASCII decimal, and idpb it +;in the location pointed to by the bp in C. Assumes no more than 2 +;digits in E. Bashes A, B, E (B because of the IDIVI). +SNDNUM: AOS E ;bump + MOVE A,E + IDIVI A,10. ;divide by 10 for high digit + JUMPE A,SNDNM2 ;only one digit + ADDI A,"0 ;make high digit ascii + IDPB A,C ;put in buffer + SUBI A,"0 ;un-ascii high digit + IMULI A,10. ;find out what we printed + SUB E,A ;take it from what we had to get low digit +SNDNM2: ADDI E,"0 ;make low digit ascii + IDPB E,C ;put in buffer + POPJ P, + +TYEBS: SOSGE TTYIHP(I) ;%TDBS: OUTPUT BS. + SETZM TTYIHP(I) + MOVEI A,^H + JRST TYPSIO + +TYERCR: MOVE D,TTYIVP(I) ;%TDRCR: OUTPUT A CR (PLUS PADDING) + SETZ TT, + SKIPN TTYIHP(I) + AOS TTYIHP(I) +TYERC1: SOS TORM(I) .SEE TYMOVX ;WHICH WILL ADD 3 TO TORM. + SOS TORM(I) + JRST TYMPRR + +TYELF: MOVE TT,TTYIHP(I) ;%TDLF: OUTPUT LF (PLUS PADDING) + MOVE D,TTYIVP(I) + AOS D + CAIG D,118. + CAML D,TCMXV(I) + JRST TYELFE ;DETECT A LF THAT SCROLLS. + JRST TYERC1 + +TYELFE: SKIPN TTYROL(I) ;IF NOT A SCROLLING TTY, RESET VPOS TO 0 + TDZA D,D + SUB D,TTYROL(I) ;OTHERWISE, GLITCH UP + MOVEM D,TTYIVP(I) ;STORE VPOS AFTER SCROLLING. + SOS TTYIVP(I) ;MAKE SURE 1 LF IS OUTPUT. + JRST TYERC1 + +TYEFS: CAIN W,%TNAAA ;AAA's use a different format + JRST TYFSAA + MOVSI E,%TCFPD ;ON SOME TTYS, IS TWO PARTS + TDNE E,TTYCOM(I) + JRST TYEFS2 ;FIRST PART DONE, DO SECOND + IORM E,TTYCOM(I) ;ABOUT TO DO FIRST PART + CAIE W,%TNDP ;DATAPOINTS NEED PADDING + CAIN W,%TNODP + JRST TYEFSD ;SO GO DO IT + MOVEI A,33 ;VT52S ETC. NEED ALTMODE PREFIX + SKIPGE CCFS(W) + JRST TYPOU2 ;SO GO DO THAT +TYEFS2: ANDCAM E,TTYCOM(I) ;ABOUT TO DO SECOND PART + HRRZ A,CCFS(W) ;GET CHARACTER TO SEND + AOS TTYIHP(I) ;IT WILL MOVE THE CURSOR + JRST TYPSIO ;SEND IT, AND ABSORB THE %TDFS + +TYEFSD: LDB B,[$TPPCR,,TTYOPT(I)] + PUSHJ P,TYMPAD ;SET UP TTYBYP TO PAD + JRST TYPLUP ;PAD THEN COME BACK HERE + +;handle forward-space on AAA's +TYFSAA: MOVE A,CCFS(W) + JRST TYEEO2 + +;HANDLE CLEAR-EOL: +TYEEOL: SKIPA A,CCEOLP(W) + +;HANDLE CLEAR-EOF +TYEEOF: MOVE A,CCEOFP(W) +TYEEO2: CAILE A,0 + PUSHJ P,TYEEO3 ;JUMP IF OUTPUT SEQ IS mn,,TABLE +TYEEO4: MOVEM A,TTYBYP(I) ;STORE BYTE POINTER OR ZERO +TYEEO1: AOS TORM(I) ;FLUSH THE CURSOR CTL CMD FROM OUTPUT BFR. + MOVEM Q,TOOP(I) + JRST TYPLUP + +;OUTPUT SEQUENCE SPECIFIED AS mn,,TABLE +;m=LOWEST PAD CODE IN TABLE, n=HIGHEST +TYEEO3: LDB B,[$TPPCR,,TTYOPT(I)] + LDB C,[220300,,A] ;n + CAMLE B,C + MOVE B,C + LDB C,[250300,,A] ;m + SUB B,C + SKIPLE B + ADD A,B + MOVE A,(A) ;PICK UP BYTE POINTER OUT OF TABLE + POPJ P, + +;HANDLE CLEAR THE SCREEN +TYECLR: SETZM TTYIHP(I) ;AFTER CLEARING, CURSOR WILL BE AT TOP LEFT + SETZM TTYIVP(I) + SKIPA A,CCCLRP(W) +;HANDLE DELETE FWD, ON OVERPRINTING ERASABLE DISPLAYS, AND IMLACS (ACC TO %TOIML). +TYEDLF: MOVE A,CCDLFP(W) + JRST TYEEO2 + +;HANDLE ENTER-INVERSE-VIDEO AND LEAVE-ALL-SUCH-MODES +TYEBOW: SKIPA A,CCBOWP(W) +TYERST: MOVE A,CCRSTP(W) + JRST TYEEO2 + +TYEINI: MOVE A,CCINIP(W) + JRST TYEEO2 + +;REGION-SCROLL UP AND REGION-SCROLL DOWN HANDLED ONLY ON DM2500 +;FOR NOW. REAL DM2500'S CAN'T DO IT, BUT CERTAIN FAKE ONES CAN. +;SOMEDAY HAIRY CODE COULD BE ADDED TO DO IT ON C100 AND VT100. +TYERSU: +TYERSD: SUBI A,%TDRSU-^U ;SEND ^U OR ^V +; CAIE W,%TNDTM +; JRST TYEEO1 + MOVE B,TORM(I) ;MAKE SURE ARGS IN BUFFER + CAILE B,TOBS-3 + JRST TYPEND ;NO, COME BACK LATER + DPB A,Q + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + ILDB A,Q ;XOR 140 INTO ARGS + XORI A,140 + DPB A,Q + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + ILDB A,Q + XORI A,140 + DPB A,Q + MOVNI A,2 ;COMPENSATE FOR "PRINTING" CHARS + ADDM A,TTYIHP(I) + JRST TYPLUP + +;HANDLE DELETE AND INSERT CHARACTERS AND LINES +;DOESN'T TRY TO BE TOTALLY HAIRY ABOUT MULTIPLE INSERT/DELETES. +TYEILP: SKIPA A,CCILPP(W) +TYEDLP: MOVE A,CCDLPP(W) + JRST TYEIL1 + +;if we're on an H19 we don't want to call TYDH19 from TYEICP, because +;no multiple insert char. +TYEICP: MOVE A,CCICPP(W) + CAIE W,%TNH19 ;if we're on an H19, no multiple insert char + JRST TYEIL1 ;so hack locally, else go to main routine + MOVE B,TORM(I) ;MAKE SURE REPEAT-COUNT ARGUMENT IS IN THE BUFFER + CAILE B,TOBS-2 + JRST TYPEND ;if it's not, come back when it is + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + ILDB B,Q ;GET IT + JRST TYEIL2 +TYEDCP: MOVE A,CCDCPP(W) +TYEIL1: MOVE B,TORM(I) ;MAKE SURE REPEAT-COUNT ARGUMENT IS IN THE BUFFER + CAILE B,TOBS-2 + JRST TYPEND ;IT'S NOT, COME BACK WHEN IT IS + CAMN Q,TOBEP(I) + MOVE Q,TOBBP(I) + ILDB B,Q ;GET IT + CAIN W,%TNAAA ;AAA's have a better way of doing this + JRST TYIDAA + CAIN W,%TNH19 ;so do H19's + JRST TYDH19 +TYEIL2: SOJG B,[DPB B,Q ;NOT LAST TIME, LEAVE DECREMENTED REQUEST IN BUFFER + CAILE A,0 + PUSHJ P,TYEEO3 + MOVEM A,TTYBYP(I) ;AND DO ONCE + JRST TYPLUP] + AOS TORM(I) ;OTHERWISE, REMOVE FROM BUFFER + JRST TYEEO2 ;AND GO DO + +;Handle insert/delete line, delete char on an H19, without weenie +;weenie. Actually enters ANSI mode for multiple insert/deletes. +TYDH19: CAIG B,6 ;if we're doing < 6, non-hairy way is faster. + JRST [ MOVE A,1(A) ;format of table is + JRST TYEIL2 ] ; [ansicommand ? zdscommand] + MOVE A,@A ;get the command char + AOS TORM(I) ;flush the arg + MOVE C,TOCMBF(I) ;pointer to comand buffer + MOVEI E,33 ;send esc and + IDPB E,C + MOVEI E,"< ;< to enter ANSI mode + IDPB E,C + PUSHJ P,TYIDA2 ;send the command and set TT to arg + MOVEI A,19. ;19 ms padding per operation. + MOVE D,H19ZDS ;copy command to enter ZDS mode + ILDB E,D ;into buffer + JUMPE E,TYDAPD ;when done, go do padding + IDPB E,C + JRST .-3 + +H19ZDS: 440700,,[ASCIZ /[?2h/] ;command to enter ZDS mode + +;Handle insert/delete chars/lines on an AAA. This code avoids the +;"weenie weenie" syndrome, where lines get deleted one at a time +;(weenie weenie), and then get inserted one at a time (weenie weenie). +TYIDAA: AOS TORM(I) ;flush arg from buffer + MOVE C,TOCMBF(I) ;get pointer to command buffer + PUSHJ P,TYIDA2 ;send command and set TT to arg + MOVEI A,4 ;4 ms padding per operation + JRST TYDAPD ;send the padding + +TYIDA2: MOVEI E,33 ;send esc + IDPB E,C + MOVEI E,"[ ;send [ + IDPB E,C + MOVE E,B ;SNDNUM takes arg in E + MOVE D,A ;and bashes A + MOVE TT,B ;and B - so save 'em + SOS E ;SNDNUM also adds 1 to its arg. + PUSHJ P,SNDNUM ;send arg + IDPB D,C ;send command char, which is now in D + POPJ P, + +;TYDAPD sets up the end of TOCMBF to include a null and the amount of +;padding needed, and then jumps to TYEEO2. TT contains a number that +;is multiplied by the contents of A to get the number of ms of padding +;desired. TT usually has the number of inserts or deletes in it, and +;A usually has the pad factor. +TYDAPD: MOVEI D,0 ;put a null at end + IDPB D,C ;now do padding - set up for TYEEO2 + HLRZ D,C ;did we just deposit in the lowest + CAIN D,010700 ;byte in this word? + JRST [ HRRZ D,C ;yes, put a 1 in the next + AOS D + MOVEI E,1 + MOVEM E,@D + JRST .+2 ] + JRST [ HRRZ D,C ;turn on the low bit in this one + MOVEI E,1 + IORM E,@D + JRST .+1 ] + AOS D + IMUL TT,A ;ms padding = TT * A + MOVEM TT,@D ;TT usually has arg to command + MOVE A,TOCMBF(I) ;pointer to beginning of buffer + JRST TYEEO2 ;goes in A, where TYEEO2 wants it + +;HANDLE TURN-ON-MOTOR COMMAND. +TYEMTN: CAIE W,%TNTRM + JRST TYEEO1 ;NO-OP EXCEPT ON TERMINETS + LDB B,[$TPPLF,,TTYOPT(I)] + JUMPE B,TYEEO1 ;PADDING CODE 0 => DON'T HACK THE MOTOR. + HRRZ A,TYMTVT(B) + LSH A,1 + IDIVI A,5 + MOVNS A + ADD A,TYEMT1(B) ;CREATE A BP TO A STRING WITH THE RIGHT # OF RUBOUTS. + JRST TYEEO4 + +;THIS IS AN ASCIZ STRING OF 90. RUBOUTS. +;SOME FINAL SEGMENT OF IT WILL BE TYPED OUT. +TYEMT0: REPEAT 90./5, -2 +TYEMT2: ASCIZ /H/ + +TYEMT1: 010700,,TYEMT2-1 + 100700,,TYEMT2-1 + 170700,,TYEMT2-1 + 260700,,TYEMT2-1 + 350700,,TYEMT2-1 + +;HANDLE TURN-MOTOR-OFF COMMAND. +TYEMTF: CAIE W,%TNTRM + JRST TYEEO1 + LDB B,[$TPPLF,,TTYOPT(I)] + JUMPE B,TYEEO1 + MOVE A,[440700,,[ASCIZ/J/]] + JRST TYEEO2 + +;CRLF AND CLEAR EOL. +TYECRL: SETZM TTYIHP(I) + AOS B,TTYIVP(I) + MOVN A,TTYROL(I) + CAML B,TCMXV(I) + ADDM A,TTYIVP(I) + MOVE A,CCROLP(W) ;HOW TO SCROLL THIS KIND OF TTY? + JRST TYEEO2 + +SUBTTL TABLES OF CURSOR-CONTROL SEQUENCES + +;Note that a table entry can be (for those tables which are strings): +; mn,,TABLE - m is lowest pad code in table, n is highest +; These pad codes from the $TPPCR. The appropriate +; table entry is selected, indexed by pad code. +; The table entry should look like 440700,,string. +; 440700,,string - the string is output. If the low-order +; bit of the last word in the string is set, the +; following word contains the number of milliseconds +; of padding required. (max is 200 ms at 9600 baud, +; see TYMPAD), or if this word is SETZ, a special kludge +; for Tektronix screen-clear is invoked. +; A negative number is the number of 1/8 msec of padding +; per line below the cursor. Note carefully that is in +; 1/8 msec units! +; 0 - output nothing +; +; (for those tables which are characters): +; "ch - output the character +; SETZ "ch - output esc (033) followed by the character + +;DATAPOINT CURSOR CONTROL CHARACTERS +%DPFS==30 ;30 => FORWARD SPACE + ;31 => (NON-EXISTANT) +%DPUP==32 ;32 => MOVE UP + ;33 => (NON-EXISTANT) +%DPHD==34 ;34 => HOME DOWN (DOESN'T WORK ON OLD DATAPOINTS ABOVE 300 BAUD) +%DPHU==35 ;35 => HOME UP + ;36 => CLEAR EOL + ;37 => CLEAR EOF +%DPBS==10 ;BACKSPACE +%DPDN==12 ;LINEFEED. + +CCDPSO: 0 ;PRT ;LH DIRECT POSITIONING CHAR, RH INDEX INTO CCDPSM + 0 ;DPT ;4.9 ESC BEFORE CHAR, 4.8 HORIZONTAL THEN VERTICAL + 0 ;LSR + 200016,,0 ;IMLAC + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 400131,,2 ;ESC + 200014,,1 ;DTM + 400131,,2 ;RAY + 400141,,2 ;HDS + 0 ;H19's have their own routine + 0 ;AAA's have their own routine +IFN .-CCDPSO-%TNMAX, .ERR SOME TCTYP SETTING LACKS CCDPSO + +;INSTRUCTION TO MUNG B TO CONVERT TO TERMINAL'S COORDINATE SYSTEM +CCDPSM: ADDI B,1 ;IMLAC + XORI B,140 ;DATAMEDIA + ADDI B,40 ;VT52, TELERAY, CONCEPT-100, ETC. + +CCFS: 40 ;FORWARD-SPACE CHARACTER, 4.9 => IT NEEDS AN ESC IN FRONT OF IT + %DPFS ;DPT + %DPFS ;LSR + ^Y ;IMLAC + 40 ;TEK + 0 ;TV + 40 ;MEM + 0 ;SFW + 40 ;TRM + SETZ "C ;ESC + 34 ;DTM + SETZ "C ;RAY + SETZ "= ;HDS + SETZ "C ;H19 +;the AAA entry looks strange here, but it's the right thing. TYEFS +;checks for AAA's specially, and AAA's don't use TYMDP. + 440700,,[.BYTE 7 ? 33 ? "[ ? "C ] ;AAA +IFN .-CCFS-%TNMAX, .ERR SOME TCTYP SETTING LACKS CCFS + +CCUP: 0 ;LINE-STARVE CHARACTER, - => IT NEEDS AN ESC IN FRONT OF IT + %DPUP ;DPT + %DPUP ;LSR + 0 ;IMLAC + 13 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + SETZ "A ;ESC + 32 ;DTM + SETZ "A ;RAY + SETZ "; ;HDS + SETZ "A ;H19 + 0 ;AAA +;this entry isn't here because this is a stupid word table instead +;of a winning string table. +; 440700,,[.BYTE 7 ? 33 ? "[ ? "A ] ;AAA +IFN .-CCUP-%TNMAX, .ERR SOME TCTYP SETTING LACKS CCUP + +CCHUP: 0 ;HOME-UP SEQUENCE POINTER + 440700,,[.BYTE 7 ? %DPHU] ;DPT + 440700,,[.BYTE 7 ? %DPHU ? %DPHU ? %DPHU] ;LSR + 0 ;IMLAC + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 440700,,[.BYTE 7 ? 33 ? "H] ;ESC + 440700,,[.BYTE 7 ? 2] ;DTM + 440700,,[.BYTE 7 ? 33 ? "H] ;RAY + 440700,,[.BYTE 7 ? 33 ? "?] ;HDS + 440700,,[.BYTE 7 ? 33 ? "H] ;H19 + 440700,,[.BYTE 7 ? 33 ? "[ ? "H] ;AAA +IFN .-CCHUP-%TNMAX, .ERR SOME TCTYP SETTING LACKS CCHUP + +CCHDP: 440700,,CCHD +CCHD: 34_29.+177_22.+177_15.+177_8 + +CCEOLP: 0 ;PRT + 440700,,[.BYTE 7 ? 36 ? 177 ? 177 ? 177] ;DPT + 440700,,[.BYTE 7 ? 36 ? 36 ? 36 ? 36] ;LSR + 440700,,[.BYTE 7 ? ^Q] ;IMLAC + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 440700,,[.BYTE 7 ? 33 ? "K] ;ESC + 440700,,[.BYTE 7 ? 27] ;DTM + 440700,,[.BYTE 7 ? 33 ? "K] ;RAY + 01,,[ 440700,,[<.BYTE 7 ? 33 ? 23>+1 ? 8.] ;HDS 300/1200 + 440700,,[<.BYTE 7 ? 33 ? 23>+1 ? 16.] ] ;HDS 9600 + 440700,,[.BYTE 7 ? 33 ? "K] ;H19 + 440700,,[.BYTE 7 ? 33 ? "[ ? "K] ;AAA +IFN .-CCEOLP-%TNMAX,.ERR SOME TCTYP SETTING LACKS %TDEOL + +CCEOFP: 0 ;PRT + 440700,,[.BYTE 7 ? 37 ? 177 ? 177 ? 177] ;DPT + 440700,,[.BYTE 7 ? 37 ? 37 ? 37 ? 37 ? 37 ? 0] ;LSR + 440700,,[.BYTE 7 ? ^P] ;IMLAC + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 440700,,[.BYTE 7 ? 33 ? "J] ;ESC + 440700,,[.BYTE 7 ? 27] ;DTM (CAN'T CLEAR TO EOF, SO CLEAR TO EOL) + 440700,,[<.BYTE 7 ? 33 ? "J>+1 ? 90.] ;RAY + ;HDS PAD CODES ARE 0 1200 OR LESS, 1 9600 OR MORE + ; AT 9600 OR ABOVE, USE ERASE EOL INSTEAD OF ERASE EOS + 01,,[ ; DUE TO INABILITY TO SEND 340 (!!) MILLISECONDS OF PADDING + 440700,,[<.BYTE 7 ? 33 ? 3>+1 ? 170.] ;HDS 300/1200 + 440700,,[<.BYTE 7 ? 33 ? 23>+1 ? 16.] ] ;HDS 9600 + 440700,,[.BYTE 7 ? 33 ? "J] ;H19 + 440700,,[<.BYTE 7 ? 33 ? "[ ? "J>+1 ? 5.] ;AAA 5 ms padding +IFN .-CCEOFP-%TNMAX,.ERR SOME TCTYP SETTING LACKS %TDEOF + +CCDLFP: 0 ;PRT + 440700,,[.BYTE 7 ? 31] ;(DPT) FOR BENEFIT OF GT40 + 0 ;LSR + 440700,,[.BYTE 7 ? ^X] ;IMLAC + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 0 ;ESC + 0 ;DTM + 0 ;RAY + 0 ;HDS + 0 ;H19 + 0 ;AAA +IFN .-CCDLFP-%TNMAX,.ERR SOME TCTYP SETTING LACKS %TDDLF + +CCROLP: 0 ;PRT + 25,,CCCRLP ;DPT + 25,,CCCRL1 ;LSR + 440700,,[.BYTE 7 ? ^M ? ^K ? ^Q] ;IMLAC + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 440700,,[.BYTE 7 ? ^M ? ^J ? 33 ? "K] ;ESC + 440700,,[.BYTE 7 ? ^M ? ^J ? 27] ;DTM + ;NOTE: REAL DATAMEDIAS IGNORE THE ^J BUT IMITATION ONES MIGHT NOT + 440700,,[.BYTE 7 ? ^M ? ^J ? 33 ? "K] ;RAY + 440700,,[<.BYTE 7 ? ^M ? ^J ? 33 ? 23>+1 ? 16.] ;HDS + 440700,,[.BYTE 7 ? ^M ? ^J ? 33 ? "K] ;H19 + 440700,,[.BYTE 7 ? ^M ? ^J ? 33 ? "[ ? "K ? 0] ;AAA +IFN .-CCROLP-%TNMAX,.ERR SOME TCTYP SETTING LACKS %TDCRL + +;CRLF ON DATAPOINTS, DEPENDING ON LOSER-NESS AND SPEED. +CCCRLP: 440700,,[.BYTE 7 ? ^M ? ^J ? 36] + 440700,,[.BYTE 7 ? ^M ? ^J ? 177 ? 177 ? 177 ? 36] +REPEAT 2,440700,,[.BYTE 7 ? ^M ? ^J ? 177 ? 177 ? 177 ? 177 ? 36] + +CCCRL1: 440700,,[.BYTE 7 ? ^M ? ^J ? 36 ? 36 ? 36 ? 36] + 440700,,[.BYTE 7 ? ^M ? ^J ? 177 ? 177 ? 177 ? 36 ? 36 ? 36 ? 36] +REPEAT 2,440700,,[.BYTE 7 ? ^M ? ^J ? 177 ? 177 ? 177 ? 177 ? 36 ? 36 ? 36 ? 36 ? 0] + +CCCLRP: 0 ;CLEAR THE SCREEN SEQUENCE POINTER + 440700,,[.BYTE 7 ? %DPHU ? 37 ? 177 ? 177 ? 177 ? 0] ;DPT + 440700,,[.BYTE 7 ? %DPHU ? %DPHU ? %DPHU ? 37 ? 37 ? 37 ? 37 ? 37 ? 0] ;LSR + 440700,,[.BYTE 7 ? ^L] ;IMLAC + 440700,,[<.BYTE 7 ? 33 ? 14>+1 ? SETZ] .SEE TYPBP ;TEKTRONIX + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 440700,,[.BYTE 7 ? 33 ? "H ? 33 ? "J ? 0] ;ESC + 34,,[440700,,[.BYTE 7 ? 36] ;DTM + 440700,,[.BYTE 7 ? 36 ? 36]] + 440700,,[<.BYTE 7 ? 33 ? "j>+1 ? 90.] ;RAY + 440700,,[<.BYTE 7 ? 14>+1 ? 48.] ;HDS (RIGHT FOR 9600 BAUD, NEED HALF AS MUCH AT 300) + 440700,,[.BYTE 7 ? 33 ? "H ? 33 ? "J ? 0] ;H19 + 440700,,[<.BYTE 7 ? 33 ? "[ ? "H ? 33 ? "[ > + <.BYTE 7 ? "J>+1 ? 5.] ;AAA needs 5 ms padding + +IFN .-CCCLRP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDCLR + +CCILPP: 0 ;PRT + 0 ;DPT + 0 ;LSR + 0 ;IML + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 01,,[ ;ESC padding mainly based on H19 - CBF + 440700,,[<.BYTE 7 ? 33 ? "L>] ; no padding at all at 1200 baud + 440700,,[<.BYTE 7 ? 33 ? "L>+1 ? -6.]] ; .75 ms/line at higher + 04,,[440700,,[.BYTE 7 ? ^P ? ^J ? ^X ? 0] ;DTM + 440700,,[.BYTE 7 ? ^P ? ^J ? REPEAT 3,[177 ? ] ^X ? 0] + 440700,,[.BYTE 7 ? ^P ? ^J ? REPEAT 5,[177 ? ] ? ^X ? 0] + 440700,,[.BYTE 7 ? ^P ? ^J ? REPEAT 10.,[177 ? ] ^X ? 0] + 440700,,[.BYTE 7 ? ^P ? ^J ? REPEAT 20.,[177 ? ] ^X ? 0]] + 440700,,[<.BYTE 7 ? 33 ? "L>+1 ? -20.] ;RAY (2.5ms/line) + 01,,[ + 440700,,[<.BYTE 7 ? 33 ? ^R>+1 ? -14.] ;HDS AT 300/1200 (1.75ms/line) + 440700,,[<.byte 7 ? 33 ? ^R>+1 ? -3.*8]] ;HDS AT 9600 (3ms/line) + ["L ? 01,,[ ;H19's use this table differently + 440700,,[<.BYTE 7 ? 33 ? "L>] ; no padding at all at 1200 baud + 440700,,[<.BYTE 7 ? 33 ? "L>+1 ? -6.]]] ; .75 ms/line at higher + "L ;AAA (AAA's use this table differently) + +IFN .-CCILPP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDILP + +CCDLPP: 0 ;PRT + 0 ;DPT + 0 ;LSR + 0 ;IML + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 01,,[ ;ESC padding mainly based on H19 - CBF + 440700,,[<.BYTE 7 ? 33 ? "M>] ; no padding at all at 1200 baud + 440700,,[<.BYTE 7 ? 33 ? "M>+1 ? -6.]] ; .75 ms/line at higher + 34,,[440700,,[.BYTE 7 ? ^P ? ^Z ? ^X] ;DTM + 440700,,[.BYTE 7 ? ^P ? ^Z ? 177 ? ^X]] + 440700,,[<.BYTE 7 ? 33 ? "M>+1 ? -20.] ;RAY (2.5ms/line) + 01,,[ + 440700,,[<.BYTE 7 ? 33 ? ^B>+1 ? -14.] ;HDS AT 300/1200 (1.75ms/line) + 440700,,[<.byte 7 ? 33 ? ^B>+1 ? -3.*8.]] ;HDS AT 9600 (3ms/line) + ["M ? 01,,[ ;H19's use this table differently + 440700,,[<.BYTE 7 ? 33 ? "M>] ; no padding at all at 1200 baud + 440700,,[<.BYTE 7 ? 33 ? "M>+1 ? -6.]]] ; .75 ms/line at higher + "M ;AAA (AAA's use this table differently) +IFN .-CCDLPP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDDLP + +CCICPP: 0 ;PRT + 0 ;DPT + 0 ;LSR + 0 ;IML + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 440700,,[.BYTE 7 ? 33 ? "Q ? 40 ? 10 ? 33 ? "R] ;ESC + 34,,[440700,,[.BYTE 7 ? ^P ? ^\ ? ^X] ;DTM + 440700,,[.BYTE 7 ? ^P ? 40 ? 177 ? ^X ? ^H ? 40 ? ^H ? 0]] + 440700,,[.BYTE 7 ? 33 ? "P] ;RAY + ; The HDS requires a null in its insert char sequence so we + ; resort to non 7 bit char so the typeout loop won't think its + ; the end of an ASCIZ string. + 01,,[ ;HDS + 441100,,[<.byte 9 ? 33 ? 20 ? 40 ? 10 > ? + <.byte 9 ? 33 ? 400 >] ; no padding 1200 or under + 441100,,[<.byte 9 ? 33 ? 20 ? 40 ? 10 > ? + <.byte 9 ? 33 ? 400 >+1 ? 16.]] ; 16 ms per insert >1200 + 440700,,[.BYTE 7 ? 33 ? "@ ? 40 ? 10 ? 33 ? "O] ;H19 + "@ ;AAA's use this table differently +IFN .-CCICPP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDICP + +CCDCPP: 0 ;PRT + 0 ;DPT + 0 ;LSR + 0 ;IML + 0 ;TEK + 0 ;TV + 0 ;MEM + 0 ;SFW + 0 ;TRM + 440700,,[.BYTE 7 ? 33 ? "P] ;ESC + 34,,[440700,,[.BYTE 7 ? ^P ? ^H ? ^X] ;DTM + 440700,,[.BYTE 7 ? ^P ? ^H ? 177 ? ^X]] + 440700,,[.BYTE 7 ? 33 ? "Q] ;RAY + 01,,[ ;HDS + 440700,,[.byte 7 ? 33 ? 21] ; no padding 1200 or under + 440700,,[<.byte 7 ? 33 ? 21>+1 ? 16.]] ; 16 ms per del at >1200 + ["P ? 440700,,[.BYTE 7 ? 33 ? "N]] ;H19's also use this table differently + "P ;AAA's use this table differently +IFN .-CCDCPP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDDCP + +CCBOWP: + REPEAT %TNDTM,0 + 440700,,[.BYTE 7 ? 16] ;DTM + 0 ;RAY + 440700,,[.BYTE 7 ? 33 ? "D] ;HDS + 440700,,[.BYTE 7 ? 33 ? "p] ;H19 + 440700,,[.BYTE 7 ? 33 ? "[ ? "7 ? "m] ;AAA +IFN .-CCBOWP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDBOW + +CCRSTP: + REPEAT %TNESC,0 + 440700,,[.BYTE 7 ? 33 ? "G] ;VT52, ETC. + 440700,,[.BYTE 7 ? 30] ;DTM + 0 ;RAY + 440700,,[.BYTE 7 ? 33 ? "d] ;HDS + 440700,,[.BYTE 7 ? 33 ? "q] ;H19 + 440700,,[.BYTE 7 ? 33 ? "[ ? "m] ;AAA - this is not RIS, +;which could screw you over if your default state were a bad one. It's +;just SGR 0. +IFN .-CCRSTP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDRST + +CCINIP: ;initialize an intelligent terminal + REPEAT %TNESC,0 + 440700,,[.BYTE 7 ? 33 ? "G] ;VT52, ETC. + 440700,,[.BYTE 7 ? 30] ;DTM + 0 ;RAY + 440700,,[.BYTE 7 ? 33 ? "d] ;HDS + 440700,,[.BYTE 7 ? 33 ? "q] ;H19 +;all sorts of ways the AAA can be messed up. We fix just a few. + 440700,,[ASCII "[>27;29;30;33;34;35;37;40;46;51l[>52h[" + +1 ? 5.] ;First line must be multiple of 5 chars! +;does: turn off insert char, LF is LF, CR is CR, no destructive BS, no +;wrap forward, no wrap backward, no AUTO XON/XOFF, no half-duplex, no +;auto kbd disable(!), no alternate cursor mode. Let us clear entire +;screen, enable sending to host, turn off delete display, turn on META +;key. Finally, clears the screen, about 5 ms padding. +IFN .-CCINIP-%TNMAX, .ERR SOME TCTYP SETTING LACKS %TDINI + + +SUBTTL TTY CONTROL TABLES + +;TOTAL NUMBER OF TTYS +NCT==NOTYS+NKSTYS+NETYS+NNTYS+NNVTTS+NDZTYS+NDPTYS+NMTYS+NDLTYS+NSTTYS+N11TYS + +IFGE NCT-%TINON, .ERR EXCESSIVE NUMBER OF TTYS + +IFG NOTYS-1, .ERR MORE THAN ONE KA-10 CONSOLE TTY? +IFG NKSTYS-1, .ERR MORE THAN ONE KS-10 CONSOLE TTY? + +NFKSTY==NOTYS ;# OF FIRST KS-10 (BETTER BE ONLY) 8080 CONSOLE TTY +NFETY==NFKSTY+NKSTYS ;# OF FIRST DTE20 TTY +NFNTY==NFETY+NETYS ;# OF FIRST TK-10 TTY +NFNVTY==NFNTY+NNTYS ;# OF FIRST NOVA TTY +NFDZTY==NFNVTY+NNVTTS ;# OF FIRST DZ11 TTY. +; Terminals above this line have slow (char at a time) controllers +; below they have fast controllers. (Check TYPDA1: and TTYDO:) +NFDPTY==NFDZTY+NDZTYS ;# OF FIRST DATAPOINT LINE +NFMTY==NFDPTY+NDPTYS ;# OF FIRST MORTON TTY +NFDLTY==NFMTY+NMTYS ;# OF FIRST DL10 TTY. +NFSTTY==NFDLTY+NDLTYS ;# OF FIRST PSEUDO-TTY +NF11TY==NFSTTY+NSTTYS ;# OF FIRST PDP11-TV TTY. + +IFG NKSTYS, IFN NFKSTY, .ERR KS-10 CONSOLE TTY NOT ZERO? +IFG NETYS, IFN NFETY, .ERR FIRST DTE20 TTY NOT ZERO? + +;INSTRUCTION TO OUTPUT 1 CHAR TO A CHAR-AT-A-TIME CONTROLLER. +;INSNS NEED NOT EXIST FOR FAST CONTROLLERS. +TTYDO: REPEAT NOTYS,DATAO TTY,A + REPEAT NKSTYS, PUSHJ P,TTKSDO + REPEAT NETYS,JFCL + REPEAT NNTYS,DATAO NTY,A + REPEAT NNVTTS,PUSHJ P,TTNDO + REPEAT NDZTYS,PUSHJ P,TTDZDO + +IFN NKSTYS,[ +TTKSDO: ANDI A,177 ; Be sure it is ASCII + TRO A,400 ; Tell 8080 there is something there. + MOVEM A,8CTYOT ; Here is where it looks. + CONO 80INT\APRCHN ; Wake up! + POPJ P, +] ;NKSTYS + +IFN NDZTYS,[ ;DZ-11 Code +TTDZDO: PUSH P,C + ANDI A,177 ;Be sure it is ASCII, and no break bits set + HRRZ C,TTYLT(I) ;Unibus address + IOWRBI A,%DZRTD(C) ;Send it + POP P,C + POPJ P, +] ;NDZTYS + +IFN NNVTTS,[ +TTNDO: ANDI A,177 + CAME I,NVOPTT + JRST TTNDO1 + AOS NVTCC + DATAO NTY,A + POPJ P, + +TTNDO1: MOVEM I,NVOPTT ;MUST SELECT NEW CONSOLE + SETOM NVTSIP ;SIGNAL + MOVEM A,NVTSSC ;SAVE CHR + PUSH P,I + SUBI I,NFNVTY-1 + TRO I,200 + DATAO NTY,I + CLEARM NVTCC + POP P,I + POPJ P, +] + +;INSTRUCTION TO TELL A TTY'S CONTROLLER TO STOP INTERRUPTING FOR IT. +;(BECAUSE THERE IS NO OUTPUT TO BE SENT) +TTYDFF: REPEAT NOTYS,CONO TTY,200+TTYCHN + REPEAT NKSTYS, JFCL + REPEAT NETYS,JFCL + REPEAT NNTYS,CONO NTY,20+TTYCHN + REPEAT NNVTTS,JRST TYP5 + REPEAT NDZTYS,PUSHJ P,DZTYDF + REPEAT NDPTYS,CONO DPK,.RPCNT_12.+400+TTYCHN + REPEAT NMTYS,CONO MTY,.RPCNT_12.+200+TTYCHN + REPEAT NDLTYS,JFCL + REPEAT NSTTYS,JFCL + +;LINE-SPECIFIC INFORMATION +TTYLT: REPEAT NOTYS,500000+TTYCHN + REPEAT NKSTYS, 0 + REPEAT NETYS,0 + REPEAT NNTYS,.RPCNT_12.+400000+TTYCHN + REPEAT NNVTTS,0 + REPEAT NDZTYS, <.RPCNT&DZLNM>,,,BA> + REPEAT NDPTYS,0 + REPEAT NMTYS,.RPCNT_12.+TTYCHN + +;INSN TO EXECUTE TO SIGNAL THAT OUTPUT IS AVAILABLE ON A PREVIOUSLY +;IDLE TTY - TELLS THE CONTROLLER TO CAUSE AN "OUTPUT DONE" INTERRUPT. +TTYST: REPEAT NOTYS,CONO TTY,10+TTYCHN + REPEAT NKSTYS, CONO 10020\APRCHN + REPEAT NETYS,PUSHJ P,TTYSTE + REPEAT NNTYS,PUSHJ P,NTYST + REPEAT NNVTTS,PUSHJ P,NVTYST + REPEAT NDZTYS,PUSHJ P,DZTYST + REPEAT NDPTYS,CONO DPK,.RPCNT_12.+100+TTYCHN + REPEAT NMTYS,CONO MTY,.RPCNT_12.+10+TTYCHN + REPEAT NDLTYS,PUSHJ P,TTYSTD + REPEAT NSTTYS,PUSHJ P,TTYPT + REPEAT N11TYS,JFCL + +IFN DZ11P,[ ;DZ-11 Code +; Disable transmitter ready interrupts from this line +DZTYDF: PUSH P,[ANDCM B,DZLBIT(A)] ;Clear this line's bit + JRST DZTYDS + +; Enable transmitter ready interrupts from this line +DZTYST: PUSH P,[IOR B,DZLBIT(A)] ;Set this line's bit +DZTYDS: PUSH P,A + PUSH P,B + PUSH P,C + HRRZ C,TTYLT(I) ;Unibus address + HLRZ A,TTYLT(I) ;Line number + IORDBI B,%DZRTC(C) + XCT -3(P) ;Frob bit + IOWRBI B,%DZRTC(C) ;Write new state + POP P,C + POP P,B + POP P,A + SUB P,[1,,1] + POPJ P, + +; DZ11 initialization. +; No parity, character length = 8 bits, stop-code = 1 bit. +DZINIT: MOVEI C,NDZTYS-1 ;Relative last DZ TTY + SKIPGE C ;Don't do anything if there aren't any + POPJ P, +DZINI1: LDB A,[$TTOSP,,NFDZTY+TTYTYP(C)] ;Ospeed (assume it is = Ispeed) + HLRZ D,NFDZTY+TTYLT(C) ; Line number on board. + HRRZ B,NFDZTY+TTYLT(C) ; Bus address of controller. + SOSL A ;Is speed = 0? + CAILE A,10 ;Is speed > 9600? + BUG HALT,[BAD SPEED CODE FOR DZ-11. LINE],OCT,C + LSH A,32. ;Assemble byte pointer + IOR A,[400,,[.BYTE 4 ? 16 ? 14 ? 12 ? 10 ? 7 ? 5 ? 4 ? 2 ? 6]] + LDB A,A ;Obtain DZ11 speed code + LSH A,%DZLSS ;Assemble LPR code + IORI A,%DZLRO+3*%DZLCL(D) ;Line # to write and various bits + XCTRI [IOWRI A,%DZRLP(B)] ;Initialize this line + CAIA + BUG HALT,[DZ11 NOT RESPONDING (CHECK THE BREAKER ON THE UNIBUS). LINE],OCT,C + SOJGE C,DZINI1 ;Loop over all DZ TTYs. + +IFN ,[ + MOVEI C, ;First unused line on last used board +DZINI2: IOWRI C,%DZRLP+,BA> ; Disable line + CAIGE C,DZNLN-1 ;Only disable lines on last used board + AOJA C,DZINI2 ;Loop +] + MOVEI C,%DZCTE+%DZCRE+%DZCSE+%DZCMS ;Turn board on + MOVEI D,377_8 ; Set all DTR bits, clear enable bits +REPEAT <_-DZLNLN>,[ + IOWRI C,%DZRCS+ + IOWRI D,%DZRTC+ +] + POPJ P, + +;CALLED AT CLOCK LEVEL TO EMPTY DZ INPUT SILOS TO TTY CODE +; What you really want to do is measure the average interrupt rate of +; each DZ and use this scanning approach only when the DZ is heavily +; active. What fun. +DZSCAN: CONO PI,TTYOFF-1 ;No TTY or lower ints, leave clock on + PUSH P,I ;Just in case +REPEAT <_-DZLNLN>,[ + IORDI A,%DZRCS+ + TRNN A,%DZCRD ;Character in silo? + JRST CONC DZS,\.RPCNT,EN +CONC DZS,\.RPCNT,LP: + IORDI A,%DZRDR+ ;Get character from silo + TRNN A,%DZDDV ;Valid character? + JRST CONC DZS,\.RPCNT,EN ;Nope, done with this DZ + ;Check parity? + LDB I,[.BP %DZLM,A] ;Get line # on DZ + ADDI I,+NFDZTY + CAIL I,NFDZTY+NDZTYS + BUG + PUSHJ P,NTYI1 ;Send char to TTY code + JRST CONC DZS,\.RPCNT,LP +CONC DZS,\.RPCNT,EN: +] + POP P,I + CONO PI,TTYON-1 ;Turn ints back on + POPJ P, +];DZ11P + +IFN TK10P,[ +NTYST: PUSH P,C ;START A TK10 TTY + CONI PI,C + ANDI C,177 ;SAVE WHICH PI CHANNELS ARE ON + CONO PI,TTYOFF + CONO NTY,@TTYLT(I) + CONO NTY,10+TTYCHN + CONO PI,2000(C) ;RESTORE PI STATUS + POP P,C + POPJ P, +] + +IFN NNVTTS,[ +NVTYST: PUSH P,I + SKIPL I,NOVATT + PUSHJ P,NTYST + POP P,I + POPJ P, +] + +TTYPT: PUSH P,B ;TTYST ROUTINE FOR STY TTYS. + PUSH P,C + MOVE B,STYSTS-NFSTTY(I) ;USER +IFN NETP,[ + TLNE B,%SSNET + JRST TTYPT2 +TTYPT3: +];NETP + MOVE C,STYMSK-NFSTTY(I) ;CHANNELS OPEN MASK + AND C,MSKST2(B) + JUMPE C,POPCBJ ;JUMP IF INTS NOT ENABLED + MOVN B,C + AND C,B + MOVE B,STYSTS-NFSTTY(I) + IORM C,IFPIR(B) + JRST POPCBJ + +IFN NETP,[ ;START STY THAT'S DIRECT CONNECTED TO NETWORK +TTYPT2: CONI PI,C + ANDI C,177 ;SAVE WHICH PI CHANNELS ARE ON + CONO PI,NETOFF + MOVSI B,%SSNET + TDNN B,STYSTS-NFSTTY(I) + JRST [ CONO PI,2000(C) ? JRST TTYPT3 ] + SKIPL STYNTL-NFSTTY(I) + JRST TTYPT4 ;ALREADY ON ACTIVATE LIST + MOVE B,STYNTA + MOVEM B,STYNTL-NFSTTY(I) + MOVEM I,STYNTA +TTYPT4: CONO PI,2000(C) ;RESTORE PI STATUS + JRST POPCBJ +];NETP + +IFN NETYS,[ +TTYSTE: CONO PI,400 ;PI OFF + SKIPL DTEOST + JRST TYSTE1 + HRRZM I,DTEOST ;TELL 11 TO SET OUTPUT DONE + CONO PI,200 ;PI ON + CONO DTE,%DBL11 ;INTERRUPT 11 + POPJ P, + +TYSTE1: CONO PI,200 ;PI ON + CONO DTE,%DBL11 ;INTERRUPT 11 + AOS DTEHC ;COUNT NUMBER OF TIMES HAD TO WAIT + SKIPL DTEOST ;THERE'S NO WAY TO AVOID HAVING TO WAIT ONE PLACE + JRST .-2 ; OR ANOTHER. THE -11 TRIES TO PICK UP OUTPUT-DONE FAST. + JRST TTYSTE +];NETYS + +IFN DL10P,[ +TTYSTD: SKIPN DL10F + JRST TYPEN1 + CONO PI,400 ;PI OFF + SKIPE DL10SO + JRST TTYSD1 + HRRZM I,DL10SO ;TELL 11 TO SET OUTPUT DONE + CONO PI,200 ;PI ON + CONO DLC,100040+TTYCHN ;INTERRUPT 11 + POPJ P, + +TTYSD1: CONO PI,200 ;PI ON + CONO DLC,100040+TTYCHN ;INTERRUPT 11 + AOS DL10HC ;COUNT NUMBER OF TIMES HAD TO WAIT + SKIPE DL10SO ;THERE'S NO WAY TO AVOID HAVING TO WAIT ONE PLACE + JRST .-2 ;OR ANOTHER. THE -11 TRIES TO PICK UP OUTPUT-DONE FAST. + JRST TTYSTD +] + +EBLK + +DEFINE TTYREP WRD +.CRFOFF +REPEAT NCT,CONC T,\.RPCNT,$!WRD +.CRFON +TERMIN + +IFNDEF TIBL,TIBL==41 +IFNDEF TOBL,TOBL==101 +TIBS==TIBL*2-1 +TOBS==TOBL*4 + +IFNDEF MICBAA,MICBAA==50. ;MAXIMUM NUMBER OF INPUT BUFFER CHARACTERS BEFORE AUTOMATIC ACTIVATION + +IFNDEF TYOWNC,TYOWNC==20. ;MIN # BYTES OF SPACE THERE MUST BE + ;IN OUTPUT BUFFER BEFORE IT IS OK TO TRY TO OUTPUT ANYTHING. + +TIB: BLOCK TIBL*NCT ;TTY INPUT BUFFERS (18 BITS PER CHARACTER) +TOB: BLOCK TOBL* ;TTY OUTPUT BUFFERS (8 BITS PER CHARACTER) + +;INPUT BUFFER BITS: +%TXMPE==400000 ;MAIN PROGRAM ECHO CHARACTER +%TXPIE==200000 ;PI ECHO CHARACTER +%TXCOM==100000 ;COM MODE ECHO CHAR; DO PI ECHO EVEN IF HDX TTY. +%TXIGN==40000 ;IGNORE THIS CHAR AT .IOT TIME. +%TXACT==20000 ;THIS IS AN ACTIVATION CHAR. +%TXINT==10000 ;THIS CHAR SHOULD INTERRUPT THE USER. + +;NOW COME THE BITS OF THE CHARACTER ITSELF: +%TXTOP==4000 ;"TOP" KEY. +%TXECI==2000 ;ECHOED DUE TO ECHOIN SYSTEM CALL +;%TXSFT==1000 ;"SHIFT" KEY. +%TXSUP==1000 ;"SUPER" KEY. +%TXMTA==400 ;"META" KEY. +%TXCTL==200 ;"CONTROL" KEY. +%TXASC==177 ;THE ASCII PART OF THE CHARACTER. + ;%TXTOP+CERTAIN LETTERS ARE MAGIC KEYS. %TXTOP+"Z IS DEFERRED CALL. + +;OUTPUT BUFFER BIT: +%TXDIS==200 ;1 => THIS IS A %TD CHARACTER. +IF2 EXPUNGE %TXDIS ;SO %TX BIT TYPEOUT MODE LOOKS NICE. + +TIIP: REPEAT NCT, (002200)TIB-1+.RPCNT*TIBL+TIBL ;INPUT BUFFER INPUT POINTER +TIOP: REPEAT NCT, (002200)TIB-1+.RPCNT*TIBL+TIBL ;INPUT BUFFER OUTPUT POINTER + (002200)TIB-1 .SEE TTEBAK +TIBEP: REPEAT NCT, (002200)TIB-1+.RPCNT*TIBL+TIBL ;END OF INPUT BUFFER POINTER +TOIP: REPEAT NCT-N11TYS,(041000)TOB-1+.RPCNT*TOBL ;OUTPUT BUFFER INPUT POINTER + REPEAT N11TYS,0 +TOOP: REPEAT NCT-N11TYS,(041000)TOB-1+.RPCNT*TOBL ;OUTPUT BUFFER OUTPUT POINTER + REPEAT N11TYS,0 +TOBEP: REPEAT NCT-N11TYS,(041000)TOB-1+.RPCNT*TOBL+TOBL ;END OF OUTPUT BUFFER POINTER + REPEAT N11TYS,1 +TOBBP: REPEAT NCT-N11TYS,(041000)TOB-1+.RPCNT*TOBL ;BEG OF OUTPUT BUFFER POINTER + REPEAT N11TYS,1 +TINTP: REPEAT NCT,2200,,TIB-1+.RPCNT*TIBL+TIBL ;INTERRUPT CHARACTER POINTER +ECHOC: REPEAT NCT,0 ;COUNT OF ECHO BUF CHARS THAT ARE REALLY ECHO CHARS +ECHOP: REPEAT NCT,2200,,TIB-1+.RPCNT*TIBL+TIBL ;POINTER TO INPUT CHARACTER TO BE ECHOED NEXT +TINTC: REPEAT NCT,0 ;COUNT OF CHARACTERS AVAILABLE FOR .ITYIC'ING. +TICC: REPEAT NCT,0 ;TYPE IN CHARACTER COUNT +TACC: REPEAT NCT,0 ;ACTIVATION CHARACTER COUNT +TORM: REPEAT NCT,TOBS ;# CHARS ROOM LEFT IN OUTPUT BUFFER. +TOCMBF: REPEAT NCT,440700,,TCMBLK+.RPCNT*5 ;5-word string buffer for each +TCMBLK: BLOCK NCT*5 ;tty for outputting commands that are longer than a few chars. + +TTYERQ: REPEAT NCT,-1 ;LIST OF TTYS NEEDING ECHO LINKED THRU THESE WDS. (NIL = 200000,,) + ;-1 FOR TTY NOT NEEDING ECHO. +TYOSW: REPEAT NCT,-1 ;AOSE-STYLE SWITCH FOR MP USE OF TTY. +TTNTO: REPEAT NCT,0 ;# CHANNELS TTY IS OPEN ON (IN ALL JOBS.) +TYIMSK: REPEAT NCT,0 ;BIT SET FOR EACH CHANNEL THE TTY IS OPEN FOR + ;INPUT ON IN THE JOB THAT OWNS THE TTY NOW. +TYOMSK: REPEAT NCT,0 ;SIMILAR, BUT FOR OUTPUT CHANNELS. +TTYBYP: BLOCK NCT ;NOT 0 => B.P. TO ASCIZ STRING TO OUTPUT AT INT. LVL. +TTLTM: REPEAT NCT,0 ;TIME LAST CHRWAS REMOVED FROM OUTPUT BUFFER. +TTYOAC: REPEAT NCT,-1 ;-1 IF TTY OUTPUT INACTIVE +TTITM: REPEAT NCT,0 ;TIME OF LAST TYPE-IN ON TTY (NOT USED BY SYSTEM). +TTYLJB: REPEAT NCT,0 ;LAST JOB TO OUTPUT TO THIS TTY. DOES NO HARM IF ABSURD. + +TTYIPC: REPEAT NCT,[ +IFG APL,IFE APL-.RPCNT, TTYIS5 ;JUST STORE AND EXIT FOR AP LINE. + .ELSE TTYI ;TTY INPUT PC +] +TYBPC: REPEAT NCT,TYBN ;PC OF ^\-HANDLING CO-ROUTINE. +TTOALC: REPEAT NCT,-1 ;LH IS -1 TO ALLOW M.P. TYPEOUT, OR 0 TO DELAY IT. + ;RH IS OUTPUT ALLOCATION: -1 => INFINITY (THE NORMAL CASE), + ;ELSE # OF CHARS ALLOWED TO BE OUTPUT. ^\ COMMANDS ARE + ;USED BY THE TTY TO ALLOCATE FOR OUTPUT. + +TCMXV: TTYREP VER ;MAX LINES VERT +TCMXH: TTYREP HOR ;MAX CHR HORZ +TTYROL: TTYREP ROL ;# LINES PER GLITCH WHEN SCROLLING. +TTYIHP: REPEAT NCT,30. ;INT LVL HPOS +TTYIVP: REPEAT NCT,5 ;INT LVL VPOS +TTYLPP: REPEAT NCT,#-1 + ;IDX OF PC PPR ASSOCIATED WITH TTY, + ;OR NEGATIVE => NONE NOW ASSOCIATED, + ;AND IS 1'S COMP. OF IDX OF PC PPR + ;FORMERLY ASSOCIATED. +TTYEPP: REPEAT NCT, ;IDX OF PC PPR TO USE FOR ECHO. +TTYLPS: REPEAT NCT,5,,30. ;IF TTYLPP <0, THIS IS MAIN PRGM VPOS,,HPOS. + +TPBEG: ;BEGINNING OF PC PPR VARS. +TPHB: ;USE 0 ;HPOS OF LEFT MARGIN. +TPVB: BLOCK 1 ;VPOS OF TOP MARGIN (1ST LINE OF PC PPR) +TPHE: ;USE TCMXH ;HPOS OF 1ST COLUMN AFTER RIGHT MARGIN +TPVE: ;USE TCMXV ;VPOS OF 1ST LINE BELOW BOTTOM MARGIN +TPHP: BLOCK 1 ;HORIZONTAL POSITION OF CURSOR +TPVP: BLOCK 1 ;VERTICAL POSITION OF CURSOR +TPVM: BLOCK 1 ;NUMBER OF LINES BEFORE A **MORE** IS ALLOWED +TPSP: BLOCK 1 ;SAVED CURSOR POS (FOR ^PS AND ^PR) +TPFLAG: BLOCK 1 ;HOLDS RANDOM FLAGS. +%TF==0,,777775 +%TFEOP==1 ;1 => HAVE JUST ENTERED LAST LINE OF PC PPR. + ;NEXT ATTEMPT TO OUTPUT SHOULD DO **MORE** PROC. +%TFIGL==2 ;1 => LAST CHAR WAS CR NOT IN IMAGE MODE. + ;IF NEXT CHAR IS LF, IGNORE IT. + + TPLEN==.-TPBEG + .=TPBEG + +REPEAT 2*NCT,[ ;NOW ASSEMBLE INITIAL CONTENTS OF PC PPR VARS. + 0 + 0+IFE .RPCNT&1,30. ;TPHP & TPVP: NONZERO FOR MAIN PRGM. + 0+IFE .RPCNT&1,5 + 0 ? 0 ? 0 +] +EXPUNG TPHB,TPHE,TPVE + +IFN .-TPBEG-NCT*TPLEN*2,.ERR + +COMT1: BLOCK NCT ;COM TEMPORARY STORAGE +COMT3: BLOCK NCT ;DITTO. WHILE QUERYING FOR A LINK, THIS IS -1 IF + ;IN IEC MODE, WHICH MEANS OK TO PASS TYPEIN THROUGH +DZLBIT:: ; Also Line number bits for DZ11 +CHNBIT: REPEAT 20,1_<.RPCNT> + +;DATA POINT CONTROLLER LINE VARIABLES +;THIS ARRAY LOOKED AT BY HARDWARE + +IFNDEF LDBFF,LDBFF==10. ;LENGTH OF OUTPUT BUFFER^2 (PER LINE) + +IFN DPKPP,[ +DPKBAS: REPEAT NDPTYS,[ + -1 ;CHR CNT + (440701,,0) ;BYTE PNTR +] + +DBBFP: REPEAT NDPTYS, 440700,,DBBF+.RPCNT*LDBFF ;PNTRS TO OUTPUT BUFFER +DPKC: REPEAT NDPTYS, DPKBAS+2*.RPCNT ;PNTR TO HARDWARE COUNT WORD +DPKP: REPEAT NDPTYS, DPKBAS+2*.RPCNT+1 ;PNTR TO BUFFER PNTR WD +DBBF: BLOCK LDBFF*NDPTYS ;OUTPUT BUFFER + +DPSPT: 2 ;134 + 6 ;600 + 1 ;110 + 2 ;150 + 3 ;300 + 24. ;1200 + 36. ;1800 + 48. ;2400 + 48. ;4800 +LDPSPT==.-DPSPT +] +DBBCC: 0 ;CHRS REMAINING IN CURRENT BLOCK + ;FOR DPK, SET ACC. TO OUTPUT SPEED, TO + ;REPRESENT APPROX. 100MS TYPEOUT TIME. + ;FOR MTY, SET TO 5. + +DBBCC1: 0 ;INITTED LIKE DBBCC, BUT NOT DECREMENTED. + +DBBBP: 0 ;BYTE PNTR TO DBBF BUFFER OR MTYOW. + +;MORTON BOX LINE VARIABLES +IFN MTYP,[ +MTYOW: 0 ;UP TO 5 CHARS TO BE OUTPUT PUT IN THIS WD. +MTYNC==5 ;NUMBER OF CHARS PACKED IN ABOVE WORD. +] + +;DTE20 VARIABLES OTHER THAN THOSE IN LOW CORE +;I.E. NOT (DIRECTLY) REFERENCED BY 11 +IFN NETYS,[ +DTEHC: 0 ;NUMBER OF TIMES LOOPING AT TTYSTE +DTECNI: 0 ;CONI DTE, AT LAST INTERRUPT +DTEBBY: 0 ;NON-ZERO => BUFFER BUSY WITH TRANSFER IN PROGRESS + ; FOR DEBUGGING, THE NON-ZERO VALUE IS THE DTEOUT COMMAND. +DTEBBT: 0 ;TIME-OUT IN HALF-SECOND UNITS +DTEOBL==200 ;NUMBER OF CHARACTERS IN OUTPUT BUFFER +DTEOBF: BLOCK /4 ;TTY OUTPUT BUFFER +];NETYS + +IFN NNVTTS,[ +NOVATT: -1 ;TTY # NOVA CONNECTED TO -1 IF NONE +NVIPTT: -1 ;CURRENT NOVA PSEUDO TTY ON INPUT +NVOPTT: 0 ;CURRENT NOVA PSEUDO TTY ON OUTPUT +NVTSIP: 0 ;-1 IF NOVA TTY SELECT IN PROGRESS (OUTPUT) +NVTSSC: 0 ;CHAR SAVED HERE DURING NVTSIP -1 +NVTCC: 0 ;# CHARS SENT TO CURRENT TTY SINCE RESCANING OTHER PSEUDO TTYS +NNVSEC: 0 ;LAST CONSOLE TO CHECK IN TYP0 SEARCH +NNVSFL: 0 ;-1 IF SERVING PREV SELECTED + ;IE IF IT CRAPS OUT, SEARCH EVEN THO IT = NNVSEC +] + +IFN N11TYS,[ +;PDP11-TV COMMUNICATION VARIABLES: + +TT11HD: .+1 ;ADDR (IN PDP10 ADDRESS SPACE) OF PDP11 CHANNEL + 0 ;HEADER AREA. IF @TT11HD IS NONZERO, THERE + ;IS INPUT TO BE PROCESSED. + +TT1111: 0 ;# TV'S THE 11 IS SET UP FOR +TT11RL: 0 ;# TV'S IN USE = MIN (TT1111, N11TYS). +TT11OL: 0 ;# PDP10 WORDS IN A PDP11-TV OUTPUT BUFFER. +TT11ER: BLOCK 6 ;FILLED WHEN BAD DATA COMMING FROM PDP11 + .SEE TT11LS + +TT11LO=400000+TTPG0*2000 ;BEGINNING OF PDP11 MEMORY IN PDP10 ADDRESS SPACE. +TT11HA==10+TT11LO ;PDP10 ADDR OF PDP11'S 40 (CHNL HDR AREA ADDR) +TT11UP==TT11HA+2 ;PDP10 ADDR OF "11 UP" FLAG. +TT11DN==TT11UP+1 ;PDP10 ADDR OF "11 ABOUT TO GO DOWN" FLAG. + +$11==1,,777700 ;DEFINE B.P.'S TO PDP11 FIELDS OF A PDP10 WORD. +$11WD0==242000 ;LOW (EVEN) 11 WORD +$11WD1==042000 ;HIGH (ODD) 11 WORD + +$11AD0==261600 ;LOW 11 WORD, SHIFTED DOWN 2 (FOR CONVERTING 11-ADDRESS TO 10 ADDRESS). +$11AD1==061600 ;HIGH 11 WORD, SHIFTED DOWN 2 + +$11BY0==241000 ;LOWEST 11 BYTE. EACH 10-WORD HOLDS 4 11-BYTES. +$11BY1==341000 ;NEXT 11 BYTE +$11BY2==041000 ;THIRD BYTE +$11BY3==141000 ;FOURTH BYTE + +;FORMAT OF AN INPUT BUFFER: (ALL POINTERS ARE PDP11 ADDRS) +;PDP11 WORD #, ... MEANING. +; 0 ... 0 => FREE, ELSE -<# DATA CHARS>. +; 1 ... ZERO, ALWAYS. +; 2 ... -> NEXT BUFFER FOR THIS TTY. +; 3 ... -> NEXT ACTIVE BUFFER. +; 4 ... KEYBOARD NUMBER (= -NF11TY) +; 5+ ... DATA CHARS, 1 PER PDP11 WORD. + +;FORMAT OF AN OUTPUT BUFFER: +;STARTS AT A MULTIPLE-OF-FOUR PDP11 ADDRESS, HAS A BUNCH OF BYTES, +;TT11BY BITS PER BYTE (USED TO BE 16, NOW 8). BYTES ARE IN PDP10 ORDER. +;AFTER THE PDP11 PICKS UP A BYTE OUT OF THE BUFFER, IT STORES BACK -1, +;WHICH TELLS THE 10 THAT IT IS OK TO STORE ANOTHER BYTE THERE. +];N11TYS + +IFN DZ11P,[ +;DZ11 STORAGE +;Temp metering locs +DZXINC: 0 ;Count of DZ transmit interrupts +DZXCHC: 0 ;Count of DZ transmit characters +; +DZDCRQ: 0 ;Disconnect requests +DZCORQ: 0 ;Connect requests. +IFG NDZTYS-36.,.ERR Too many DZ TTYS, fix code using DZDCRQ or DZCORQ +];DZ11P + +LOCTTY: 0 ;CONSOLE INPUT CHAR READ FROM +LTTYIPC:0 ;TTYIPC USED IN LAST INPUT INT (DEBUGGING ONLY) +LTYBPC: 0 ;TYBPC USED IN LAST INPUT INT (DEBUGGING ONLY) +LEPCHR: 0 ;-1 IF CURRENT INPUT CHAR IS A LOCAL EDITING PROTOCOL COMMAND CHAR. + +TTYA: 0 +TTYACS: BLOCK 17-B+1 +IFN KA10P, TTYAPC: 0 ;APR CONI AT TTYBRK. +TTYPDP: -LTTYP,,TTYPDL-1 +TTYPDL: BLOCK LTTYP + +IFN TTLPTP,[ +LPTTTY: TTLPTP ;TTY# THAT IS REALLY LPT +LPTTIME: 0 ;LAST TIME SYSTEM GOT INPUT FROM LPT +] + +STYMAX: NCT ;Highest-numbered STY to be allocated (for limiting load) +STYOSW: -1 ;PSEUDO TTY OPEN SWITCH + 0 + +TTERQS: MOVE ;LIST (THREADED THRU TTYERQ) OF TTYS NEEDING ECHOING. + ;"MOVE" (= 200000,,) IS THE END OF THE LIST. + ;OTHERWISE, A POINTER IS THE NUMBER OF A TTY + ;WHOSE TTYERQ VAR. HOLDS THE NEXT POINTER. + +TTEDMY: 0 .SEE TYOPV0 ;DUMMY VARIABLE BLOCK + 0 .SEE TYOPV1 ;PASSED BY ECHO ROUTINE + TTEDMY .SEE TYOPV2 ;TO .IOT RTNS. + 0 .SEE TYOPV3,TTELUP + +NTTELU: 0 .SEE TTELUP ;ECHOING STATISTICS. +NTTEWA: 0 .SEE TTEWAT +NTTEL1: 0 .SEE TTELP1 + +STYNTO: BLOCK NSTTYS ;NUMBER TIMES PSEUDO TTY OPEN +STYMSK: REPEAT NSTTYS,0 ;BIT FOR EACH CHNL STY OPEN FOR INPUT ON +STYOMS: REPEAT NSTTYS,0 ;OUTPUT +STYSTS: REPEAT NSTTYS,0 ;STY STATUS 0 => FREE SLOT + ;RH = USER INDEX THAT HAS IT OPEN +%SSHNG==400000 ;4.9 = 1 => DON'T HANG ON INPUT IOTS +%SSUSE==200000 ;4.8 = 1 => IN USE +%SSINT==100000 ;4.7 = 1 => HAVE GIVEN INT ON STY OUTPUT CHNS ALREADY +%SSONT==040000 ;4.6 = 1 => DITTO FOR STY INPUT (TTY OUTPUT) +%SSOHG==20000 ;4.5 = 1 => DON'T HANG ON OUTPUT IOT +%SSORS==10000 ;4.4 = 1 => THIS STY WANTS %TDORS WHEN A + ;TTY OUTPUT RESET IS DONE. +IFN NETP,[ +%SSNET==4000 ;4.3 = 1 => THIS STY CONNECTED TO SOME NET SOCKETS. +%SSCHA==2000 ;4.2 = 0 FOR ARPANET, 1 FOR CHAOS NET +%SSTCP==1000 ;4.1 = 1 for TCP internet (%SSCHA must be 0) + +STYNTI: REPEAT NSTTYS,-1; If %SSNET set, holds net connection identifier. + ; NCP: Input IMSOC idx,,Output IMSOC idx + ; CHA: connection index + ; TCP: TCB (connection) index + ; Otherwise -1 +STYNTA: 0 ;HEAD OF LIST OF DIRECT-CONNECTED STYS NEEDING DATA XFER. + ;0 IS NIL; A TTY # POINTS TO A STY. +STYNTB: 0 .SEE STYNTC ;COPIED STYNTA LIST USED INSIDE STYNTC ONLY +STYNTL: REPEAT NSTTYS,-1;STYNTA LIST THREADED THROUGH THIS TABLE. + ;+ NEXT TTY IN LIST, 0 END OF LIST, - NOT IN LIST +STYORC: REPEAT NSTTYS,0 ;OUTPUT-RESET CHARACTERS, 8-BIT BYTES TERMINATED BY 0 +TYPNTF: 0 ;-1 WHILE TYP BEING CALLED FROM STYNT0 +NTORFU: 0 .SEE TYPOR3 +] ;NETP + +STYICH: 0 ;TEMP STORAGE FOR PSEUDO-TTY INPUT CHAR + +TCTYP: TTYREP TCT ;THIS WORD SAYS HOW TO PERFORM + ;CURSOR CTL FUNCTIONS ON TTY. +%TNPRT==0 ;PRINTING TTY. +%TNDP==1 ;TTY USES DATAPOINT CURSOR CTL CODES. +%TNODP==2 ;LOSING DATAPOINT (ML-KA HAS SOME). +%TNIML==3 ;TTY USES IMLAC CURSOR CODES. +%TNTEK==4 ;TEKTRONIX 4000 SERIES +%TNTV==5 ;TTY IS A KNIGHT TV DISPLAY. +%TNMEM==6 ;MEMOWRECK +%TNSFW==7 ;"SOFTWARE" TTY THAT WANTS I.T.S. CURSOR-MOTION CODES. +%TNTRM==10 ;TERMINET +%TNESC==11 ;TTY WANTING STANDARD ASCII ESCAPE SEQUENCES +%TNDTM==12 ;DATAMEDIA +%TNRAY==13 ;TELERAY 1061 +%TNHDS==14 ;HDS CONCEPT-100 +%TNH19==15 ;H19/Z19 +%TNAAA==16 ;AAA +%TNMAX==17 + +;TTYOPT WORD DESCRIBES CHARACTERISTICS OF THE PARTICULAR +;TERMINAL ATTACHED TO EACH LINE. +TTYOPT: TTYREP OPT + +;LEFT HALF BITS ARE: +%TOALT==200000 ;4.8 => STANDARDIZE ALTMODES. +%TOCLC==100000 ;4.7 => CONVERT LOWER CASE TO UPPER. +%TOERS==40000 ;4.6 => THIS TTY CAN SELECTIVELY ERASE. +%TOHDX==20000 ;4.5 => THIS TTY IS HALF-DUPLEX. +$TOHDX==370100 +%TOMVB==10000 ;4.4 => THIS TTY CAN BACKSPACE. +%TOSAI==4000 ;4.3 => THIS TTY HAS SAIL CHAR SET ON OUTPUT. +%TOSA1==2000 ;4.2 INIT %TSSAI OF NEW JOBS. +%TOOVR==1000 ;4.1 => THIS TTY CAN OVERPRINT SUCCESSFULLY. +%TOMVU==400 ;3.9 => THIS TTY CAN MOVE CURSOR UP (IS A DISPLAY). +%TOMOR==200 ;3.8 => DO **MORE** PROCESSING ON THIS TTY + ;(ACTUALLY JUST USED TO INIT %TSMOR FOR NEW JOBS). +%TOROL==100 ;3.7 SIMILARLY, INIT %TSROL FOR NEW JOBS. +%TORAW==40 ;3.6 => SUPPRESS CURSOR MOTION OPTIMIZATION. +%TOLWR==20 ;3.5 => THIS TTY HAS LOWER CASE KEYBOARD. +%TOFCI==10 ;3.4 => THIS TTY CAN INPUT 12-BIT CHARACTERS (HAS FULL KEYBOARD). +%TOIML==4 ;3.3 => IMLAC, HANDLES CURSOR MOTION STRANGELY. +%TOLID==2 ;3.2 => LINE INSERT AND DELETE WORK +%TOCID==1 ;3.1 => CHARACTER INSERT AND DELETE WORK + +;RIGHT HALF: +%TPPLF==100000 +$TPPLF==170300 ;3-BIT FIELD SAYING HOW TO PAD LF. + ;0 - DON'T. 1 - MEMOWRECK, 2741. 2 - TERMINET. +%TPPCR==10000 +$TPPCR==140300 ;3-BIT FIELD SAYING HOW TO PAD CR. + ;7 - UNUSED. 6 - MEMOWRECK. 5 - 2741. 4 - EXECUPORT. + ;0 - DON'T. 1 - NORMAL. 2 - DOUBLE. + ;ON DATAPOINTS, = # CHARS PADDING NEEDED FOR ALL CURSOR MOTION. + ;4 IS RIGHT FOR 2400 BAUD; 3, FOR 1200. + ;ON TERMINETS, 0 => NO PADDING, OTHER CODES ARE + ;1 FOR 10CPS, 2 FOR 15CPS, 3, 4, 5 FOR 30, 60, 120 CPS. +%TPPCW==6 ;FOR MEMO WRECK. +%TPPTB==1000 +$TPPTB==110300 ;3 BIT FIELD SAYING HOW MUCH PADDING NEEDED AFTER TAB. + ;0 => TABS NOT ALLOWED; ELSE 1 +<# PADDING CHARS NEEDED> +%TPMTA==400 ;1.9 => HARDWARE META KEY SETS 8TH BIT +%TPPRN==200 ;1.8 => INTERCHANGE () WITH [] ON INPUT +%TPTEL==100 ;1.7 => TREAT CRLF INPUT AS CR FOR TELNET PROTOCOL +%TPCBS==40 ;1.6 => ENABLE SPECIAL TREATMENT OF 034 ("CONTROL BACK SLASH") ON INPUT. + ;(THE "INTELLIGENT TERMINAL PROTOCOL"). +%TP11T==20 ;1.5 => PDP-11 TV TTY. REFLECTS %TY11T. + ;NOT SETTABLE BY USER. +%TPORS==10 ;1.4 => OUTPUT RESET ON THIS TTY SHOULD REALLY DO SOMETHING. +%TPRSC==4 ;1.3 => THIS TTY SUPPORTS %TDRSU, %TDRSD + +;SMARTS VARIABLE, %TQ IN LH, %TR IN RH, BIT DEFINITIONS IN BITS > +TTYSMT: TTYREP SMT +.SEE %TQ +.SEE %TR + +TTYST1: REPEAT NCT,0 ;FIRST SIX GROUPT (SIX BITS PER GROUP) +TTYST2: REPEAT NCT,0 ;SECOND SIX GROUPS (SIX BITS PER GROUP) +TTYSTS: REPEAT NCT,%TSFRE,,-1 ;MODE BITS FOR TTY + +;GROUP NUMBER CHARACTERS +;[ 0 ^A-^F ^K-^L ^N-^R ^T-^Z ^] ^^ ^_ ^@ ^\ +; 1 A-Z LOWER CASE A-Z +; 2 0-9 +; 3 !"#$(DOLLAR)%&',.:;?@\ (ACCENT GRAVE) (VERTICAL BAR) (TILDE) +; 4 *+-/=^_ +; 5 <>[]() (LEFT BRACE) (RIGHT BRACE) +; 6 ^G ^S (^S IS IN GROUP 0 AS FAR AS %TGIMG IS CONCERNED) +; 7 LF ^I(TAB) +; 10 (ALTMODE) +; 11 CR +; 12 RUBOUT +; 13 SPACE ^H(BACKSPACE) + +;TTYST1 HAS GROUPS 0 THROUGH 5 FROM LEFT TO RIGHT +;TTYST2 HAS 6 THROUGH 13 +;EACH GROUP HAS SIX BITS AS FOLLOWS: +%TGINT==1 ;N.1 => INTERRUPT ON THIS GROUP +%TGACT==2 ;N.2 => ACTIVATE ON THIS GROUP (FOR SWAPPING) +%TGSPC==4 ;N.3 => SPECIAL HACKS. (THIS SET ON GROUP 1 => CONVERT LOWER CASE INPUT) +%TGIMG==10 ;N.4 => IMAGE MODE OUTPUT (N.4=0 => ASCII MODE) + ;N.6-N.5 => ECHO MODE + ; 00 => NO ECHO +%TGPIE==20 ; 01 => PI ECHO (ECHO CHARACTER WHEN TYPED) +%TGMPE==40 ; 10 => MAIN PROGRAM ECHO (ECHO WHEN MAIN PROGRAM RECEIVES CHARACTER) + +;TTYSTS HAS RANDOM BITS ASSOCIATED WITH THE TELETYPE +%TSFRE==400000 ;4.9 => TTY FREE +%TSCLE==200000 ;4.8 => ECHO ^L AS UPARROW-L EVEN ON DISPLAYS + ;(OTHERWISE WOULD ECHO AS CLEAR SCREEN) +%TSHDX==100000 ;4.7 REFLECTS %TOHDX BIT. +%TSFCO==040000 ;4.6 => HANDLE 9-BIT CHARS ON OUTPUT, USING ALPHA, BETA. +%TSALT==020000 ;4.5 => DON'T STANDARDIZE ALTMODE. +%TSROL==010000 ;4.4 => SCROLL MODE. +%TSSAI==004000 ;4.3 => ECHO AND ASCII MODE SHOULD USE SAIL CHAR SET. +%TSACT==002000 ;4.2 => GOBBLE NEXT CHAR REGARDLESS OF ACTIVATION STATUS +%TSNEA==001000 ;4.1 => DON'T ECHO IN THE ECHO AREA. ECHO IN M.P. AREA. +%TSINT==000400 ;3.9 => INT ON NEXT CHAR REGARDLESS +%TSMOR==000200 ;3.8 => INHIBIT **MORE**. +%TSATY==000100 ;3.7 SET BY .ATTY, SAYS TTY WAS TAKEN AWAY & RETURNED. + ;3.6-3.5 UNUSED. +%TSNOE==000010 ;3.4 => DEFER ECHOING, AND MAKE INPUT IOT'S ACT AS IF %TIECH=1. +%TSLCZ==000004 ;3.3 => LAST CHARACTER TYPED WAS ^Z (NOT PRECEEDED BY ^_) +%TSSII==000002 ;3.2 => SUPER IMAGE INPUT MODE +%TSCNS==000001 ;3.1 => CONSOLE +$TSCNS==220100 + ;RH => USER INDEX + ; -1 => NO USER + +TTYSTA: REPEAT NCT,%TACFM,, ;NOT SAVED AT ATTY +%TACFM==400000 ;4.9 = 0 => NEEDS TO HAVE CONSOLE FREE MSG EVENTUALLY TYPED + ; CLEARED BY OPEN OR ZFLAG WHEN INITIALIZING CONSOLE PROCEDURE + ; SET BY SYS JOB AFTER TYPING CONSOLE FREE MSG + ;WHEN THIS BIT IS 0, TTY ISN'T AVAILABLE FOR BEING GOBBLED DOWN + ;FOR ANY NEW USE. +%TACTZ==200000 ;4.8 ON => TTY IS FREE AND BEING ^Z'D, SO EVEN THOUGH IT APPEARS + ;OTHERWISE TO NEED A CONSOLE-FREE MESSAGE IT SHOULDN'T GET ONE. +%TANJS==100000 ;4.7 ON => TTY IS BEING ^Z'D, BUT THERE ARE NO JOB SLOTS. + ;4.8 WILL BE ON AND 4.9 OFF. SYS JOB WILL RESTORE ALL TO NORMAL + ;AFTER TYPING "SYSTEM FULL" ON THE TTY. +%TANEC==070000 ;4.6-4.3 NUMBER OF FOLLOWING CHARS TO INHIBIT ECHO AND INTS FOR. + ;THIS IS USED FOR THE ARG CHARS THAT FOLLOW TOP-E, TOP-S, TOP-Y, ETC. + +TTYCOM: REPEAT NCT,0,,-1 ;COMMUNICATE WORD +;4.9 => TTY IN COMMUNICATE MODE +%TCLFT==200000 ;4.8 => LOCAL FEED THROUGH (SET IF MY PRGM RECIEVING HIS CHRS) +%TCRFT==100000 ;4.7 => REMOTE FEED THROUGH (SET IF HIS PRGM RECIEVING MY CHRS) +%TCICO==40000 ;4.6 => INPUT COMMUNICATE OVERRIDE (SET IF MY CONSOLE FEEDING MY + ; PRGM EVEN THO IN COMM MODE). ALSO IMPLIES OUTPUT OVER-RIDE. +%TCOCO==20000 ;4.5 => OUTPUT COMMUNICATE OVERRIDE (SET IF MY PRGM'S OUTPUT TO APPEAR ON MY CONSOLE ONLY EVEN THO IN COM MODE) +;4.4-4.3 => MESSAGE RECEIPT SWITCH + ;00 => ACCEPT +%TCRFS==10000 ;10 => REFUSE +%TCQRY==4000 ;01 => INTERROGATE +%TCMTR==2000 ;4.2 SET FOR TTY WHOSE MOTOR IS OFF & MUST BE TURNED +;ON BEFORE ANY OTHER OUTPUT IS DONE. +;(ONLY TERMINETS HAVE THEIR MOTORS SHUT OFF BY ITS). +%TCECH==1000 ;4.1 THE OUTPUT BUFFER CONTAINS ECHOING OUTPUT. + ;THIS MAKES OUTPUT RESET DO NOTHING. + ;THE BUFFER MUST NOT CONTAIN ECHO OUTPUT AND NORMAL OUTPUT AT ONE TIME. +%TCDET==200 ;3.8 CONSOLE'S TREE DETACHED BY TOP LEVEL INTERRUPT. + ;SET BY NDETAC AS SIGNAL TO SYSCFM (CNSL-FREE-MSG TYPER) +%TCDNG==100 ;3.7 => TYPE BELL ON TTY (BECAUSE INPUT BFR FULL). +%TCCBK==40 ;3.6 => READING UNAME OR TTY # AFTER ^_K. +%TCCBS==20 ;3.5 => READING UNAME OR TTY # AFTER ^_S. +%TCFPD==10 ;3.4 => FIRST PART DONE (USED FOR %TNESC ESCAPE SEQUENCES, %TNODP CR) +%TCTPN==4 ;3.3 TYPE ^_N ON LEAVING COM MODE (UNLESS USER EXPLICITLY TYPES ^_N) +%TCPAD==2 ;3.2 0 => PADDING NECESSARY ON DATAPOINT. +%TCHNG==1 ;3.1 TTY'S DONE FLAG APPEARS TO BE FRIED, TIME OUT QUICKLY +;RH => USER INDEX COMMUNICATING WITH (-1 NONE) + + +;TTYTYP TABLE +;THIS TABLE HOLDS BITS THAT DESCRIBE THE LINE +;AND ITS CONTROLLER, RATHER THAN THE TTY ATTACHED TO THE LINE. + +%TTLCL==400000 ;BIT 4.9 ONE => LOCAL TTY +%TT340==200000 ;BIT 4.8 ONE => CONSOLE NEXT TO 340 OR A 340 SLAVE +%TT3HP==100000 ;BIT 4.7 HIGH PRIORITY ON 340 +%TTPAR==004000 ;BIT 4.3 THIS TTY NEEDS PARITY BIT SENT. +%TTDDI==002000 ;BIT 4.2 DONT DING ON EXCESS INPUT +$TTISP==260400 ;3.8-3.5 INPUT SPEED CODE +$TTOSP==220400 ;3.4-3.1 OUTPUT SPEED CODE + +%TYDPK==400000 ;BIT 2.9 DATAPOINT KLUDGE TERMINAL +%TYSTY==200000 ;BIT 2.8 PSEUDO TTY +%TYNVA==100000 ;BIT 2.7 NOVA TTY +%TYMTY==040000 ;BIT 2.6 MORTON BOX +%TYDIL==020000 ;BIT 2.5 DIAL UP +%TY11T==010000 ;BIT 2.4 PDP-11 TV TTY. +%TYDL== 004000 ;BIT 2.3 DL10 TTY +%TYOTY==002000 ;BIT 2.2 ORDINARY KA-10 CONSOLE TTY +%TYETY==001000 ;BIT 2.1 DTE-20 TTY (KL-10 CONSOLE) +%TYNTY==000400 ;BIT 1.9 TK-10 TTY. +%TYMDM==000200 ;BIT 1.8 LINE HAS MODEM CONTROL, DETECTS DIALINS AND HANGUPS +%TYKST==000100 ;BIT 1.7 KS-10 CONSOLE TTY +%TYDZT==000040 ;BIT 1.6 DZ-11 TTY ON KS-10 +%TYRLM==000020 ;BIT 1.5 ROLM DATA SWITCH + +TTYTYP: TTYREP TYP ;PART OF TTYTYP MAY BE WRITEABLE. +BBLK + 0 ;DISOWNED JOBS CANT HAVE LPT + %TTLCL,,;SYSTEM JOB CAN GET LPT + +.CRFOFF +IRPS X,,TYP OPT HOR VER TCT ROL SMT +REPEAT NCT,[ +CONC EXPUNG T,\.RPCNT,$!X +] +TERMIN +.CRFON + +OVHMTR UUO ;YET MORE RANDOM UUOS diff --git a/src/system/ttytyp.314 b/src/system/ttytyp.314 new file mode 100755 index 00000000..edca0a6a --- /dev/null +++ b/src/system/ttytyp.314 @@ -0,0 +1,400 @@ + +;THE MASTER COPY OF THIS FILE IS KEPT ON AI:SYSTEM;TTYTYP > +;DUPLICATES ARE KEPT ON OTHER ITS MACHINES BUT THEY SHOULD +;NEVER BE EDITED. IF YOU'RE NOT TOTALLY SURE OF WHAT YOU'RE DOING +;DON'T EDIT THIS FILE; ASK A HACKER FOR ASSISTANCE. + +;HOW TO DESCRIBE EACH TTY. IT ASSUMES THE FOLLOWING: +;EACH MACHINE MUST HAVE A BLOCK OF ENTRIES, WHICH STARTS WITH +;THREE SEMICOLONS, A SPACE , AND THE NAME OF THE MACHINE. +;THEN MUST COME EXACTLY ONE COMMENT PER TTY, STARTING WITH +;"TNM ". THERE MAY BE OTHER COMMENTS NOT STARTING WITH A "TNM ". +;THOSE OTHER COMMENTS WILL BE IGNORED BY "NAME". + +;THIS FILE IS ARRANGED SO THAT IT CAN BE ASSEMBLED BY EITHER MIDAS OR PALX +;THE FOLLOWING MACROS ARE USED IN THIS FILE +; +;SEPARATORS: +; MCONDX CONDITIONAL FOR WHICH MACHINE +; .ENDC TERMINATE ... +; + +;TERMINAL TYPES: +;FIRST ARGUMENT TO TTDXXX MACRO IS THE LINE NUMBER +;FOLLOWING THAT CAN BE SEVERAL OPTIONS, SELECTED BY THE FOLLOWING KEYWORD PARAMETERS: +;TT LH(TTYTYP) ADDED TO SPEED CODE +;TY RH(TTYTYP) ADDED TO CONTROLLER-SELECT BIT +;TO LH(TTYOPT) ADDED TO DEFAULT BITS FOR DEVICE +;TP RH(TTYOPT) ADDED TO PAD CODES, DEFAULT IS DEFAULT %TPORS AND %TPCBS +;TCT TCTYP DEFAULT IS APPROPRIATE FOR TERMINAL BEING DEFINED +;HOR SCREEN WIDTH DEFAULT .. +;VER SCREEN HEIGHT DEFAULT .. +;ROL LINES/GLITCH DEFAULT .. +;SPEED OUTPUT SPEED IN BAUDS DEFAULT IS APPROPRIATE.. +;ISPEED INPUT SPEED IN BAUDS (IF DIFFERENT) +;SOME TERMINAL TYPES DON'T ACCEPT SOME OF THESE OPTIONS WHICH WOULD BE MEANINGLESS. + +.XCREF TT,TY,TO,TP,TCT,HOR,VER,ROL,SPEED,ISPEED ;FOOL @ + +; TTDPRT PRINTING TERMINAL (SPEED=110 => TTY35). DEFAULT SPEED IS 300. +; TTDMRX MEMOREX 1240 +; TTDTRM TERMINET 1200 +; TTDLPT BRIGHT (OR ODEC OR GOULD) LINE PRINTER ON TTY LINE +; TTDLA36 LA 36 +; TTDIML IMLAC +; TTDVT VT-52 +; TTDH19 H19 +; TTDTEK TEKTRONIX +; TTDLSR LOSING DATAPOINT +; TTDDPT DATAPOINT +; TTDGT40 GT-40 +; TTD11 PDP-11 (LOOKS LIKE PRINTING TERMINAL) +; TTDRAN RANDOM TYPE, YOU BETTER SPECIFY EVERYTHING +; TTDTV PDP-11 TV "LINE" VIA TEN-11 INTERFACE +; TTDGRN PDP-11 TV (OR GRINNELL TV) ON NORMAL TTY LINE +; TTD2741 N,CODE 2741 CODE=0 => EBCDIC, CODE=1 => CORRESPONDENCE +; TTDSTY SOFTWARE PSEUDO-TTY +; TTDC100 CONCEPT-100 +; TTDAAA Ann Arbor Ambassador + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX AIKA,{ ;;; AI-KA + TTDLA36 0,TT=%TTLCL,HOR=80.,SPEED=110 ;T00 System Console (9th) + TTDPRT 1,SPEED=150,TY=%TYDIL ;T01 Dialup 15CPS * + ; 8-7874 15CPS + TTDPRT 2,SPEED=110,TY=%TYDIL ;T02 Dialup 10CPS * + ; 258-8794 10CPS + TTDPRT 3,SPEED=110,TT=%TTLCL ;T03 XGP TTY (9TH) + TTDPRT 4,SPEED=110,TT=%TTLCL+%TT340+%TT3HP ;T04 PDP6 TTY (9th) + TTDPRT 5,SPEED=110,TT=%TTLCL ;T05 TTY Near LPT (9th) + TTDPRT 6,SPEED=150,TY=%TYDIL ;T06 Dialup 15CPS * + ; 258-8795 15CPS + TTDPRT 7,SPEED=110,TT=%TTLCL+%TT340 ;T07 Little Robot TTY (9th) + TTDPRT 10,SPEED=134 ;T10 Baudot AP * + ;NEXT 3 USED TO BE 2741S, BUT WERE FLUSHED + TTDPRT 11,SPEED=134 ;T11 TSTC (9th) * + TTDPRT 12,SPEED=134 ;T12 2741 (9th) * + TTDPRT 13,SPEED=134,TY=%TYDIL ;T13 2741 Dialup * + TTDPRT 14 ;T14 Unused * + TTDPRT 15,SPEED=300,TY=%TYDIL ;T15 Dialup 30CPS + TTDPRT 16,SPEED=300,TY=%TYDIL ;T16 Dialup 30CPS + TTDPRT 17,SPEED=300,TY=%TYDIL ;T17 Dialup 30CPS + TTDPRT 20,SPEED=300,TY=%TYDIL ;T20 Dialup 30CPS + TTDVT 21,SPEED=4800,TT=%TTLCL ;T21 814 x7881 Barton,Berwick,Brotsky,Sjoberg + TTDTRM 22,TT=%TTLCL ;T22 Terminet in 813 (Hewitt) + TTDVT 23,SPEED=4800,TT=%TTLCL ;T23 926 Under the Miro x6765 + TTDDPT 24,TT=%TTLCL+%TT340,HOR=71. ;T24 Datapoint Near XGP (9th) + TTDAAA 25,TT=%TTLCL,SPEED=4800,TP=%TPMTA ;T25 810 Marty, Toto, Kansas x7836 + TTDDPT 26 ;T26 Datapoint in 822 (Stansfield) + TTDAAA 27,TT=%TTLCL,SPEED=4800 ;T27 926 Under ee cummings x6765 + TTDTRM 30,ISPEED=150,TY=%TYDIL ;T30 Dialup 120/15 CPS + ; 258-6091 150 IN, 1200 OUT TERMINET + TTDAAA 31,TT=%TTLCL,SPEED=4800,TP=%TPMTA ;T31 936 Lisp Machine Factory x6703 + TTDTRM 32,ISPEED=150,TY=%TYDIL ;T32 Dialup 120/15 CPS + ; 258-6090 150 IN, 1200 OUT TERMINET + TTDAAA 33,SPEED=4800,TT=%TTLCL ;T33 336 Sobalvarro, Delatizky x5834 + TTDVT 34,SPEED=4800,TT=%TTLCL ;T34 908 Oro + TTDDTM 35,SPEED=4800 ;T35 Poggio, Ullman x5781 (Bldg E10) + TTDRAY 36,SPEED=4800,TP=%TPMTA,TT=%TTLCL ;T36 812 Attardi, Barber, Koton (x7891) + TTDRAY 37,SPEED=4800,TP=%TPMTA,TT=%TTLCL ;T37 939 Kornfeld x5835 + TTDGT40 40,VER=29.,HOR=68.,TO=-%TOOVR ;T40 Micro-Automation PDP-11 (9th) +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX MLKA,{ ;;; ML-KA + TTDLA36 0,TT=%TTLCL,HOR=80.,SPEED=110 ;T00 System Console + TTDPRT 1,SPEED=1200,TY=%TYDIL ;T01 Dial-up 1.2KB Vadic + ;258-6756 + TTDPRT 2,SPEED=300,TY=%TYDIL ;T02 Dial-up line 30CPS + ;258-6742 + TTDPRT 3,SPEED=300,TY=%TYDIL ;T03 Dial-up line 30CPS + ;258-6743 + TTDPRT 4,SPEED=1200,TY=%TYDIL ;T04 Dial-up 1.2KB Vadic + ;258-7894 + TTDVT 5 ;T05 350 Waters x6037 + TTDDPT 6,TT=%TTLCL ;T06 9th flr near console + TTDLA36 7 ;T07 800D DECwriter + TTDVT 10 ;T10 3rd flr VT52 #833 + TTDPRT 11,SPEED=1200,TY=%TYDIL ;T11 Dial-up 1.2KB Vadic + ;258-6757 + TTDVT 12 ;T12 8th flr VT52 + TTDVT 13 ;T13 8th flr VT52 #433 + TTDVT 14 ;T14 8th flr VT52 + TTDVT 15 ;T15 8th flr VT52 + TTDVT 16 ;T16 3rd flr VT52 #517 + TTDVT 17 ;T17 3rd flr VT52 #256 + TTDVT 20 ;T20 3rd flr VT52 #342 + TTDVT 21 ;T21 3rd flr VT52 #1224 + TTDVT 22 ;T22 3rd flr VT52 #8462 + TTDVT 23 ;T23 3rd flr VT52 #8453 + TTDVT 24 ;T24 3rd flr VT52 #7559 + TTDVT 25 ;T25 3rd flr VT52 #8379 + TTDVT 26 ;T26 3rd flr VT52 #7320 + TTDVT 27 ;T27 3rd flr VT52 #8437 + TTDVT 30 ;T30 VT52 in Library + TTDVT 31 ;T31 5th flr VT52 + ;This is now plugged into the right-hand 4-prong in 512A. That is in + ;parallel with Ann Rubin (Liskov-Dennis's secretary), so she'd + ;need to be asked if someone wanted to do an - ahem - demo. + TTDPRT 32,SPEED=1200,TY=%TYDIL ;T32 Dial-up 1.2KB Vadic + ;258-6733 + TTDC100 33 ;T33 317 Burke x3546 +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX DM,{ ;;; DM + TTDLA36 0,TT=%TTLCL,HOR=80.,SPEED=110 ;T00 930 x2910 CPU + TTDLPT 1 ;T01 215 ODEC LPT + TTDVT 2 ;T02 205 x1440 Lebling + TTDVT 3 ;T03 219 x1450 Vezza + TTDVT 4 ;T04 203 x1429 Sangal + TTDVT 5 ;T05 214A x1410 Apollo Room + TTDIML 6 ;T06 [not in use] + TTDPRT 7 ;T07 214A x1410 APOLLO + TTDVT 10 ;T10 204 x1418 Galley + TTDVT 11 ;T11 801/A x6025/4 Faris/Meyer + TTDVT 12 ;T12 218 x7706 Venckus + TTDVT 13 ;T13 222 x5800 Niamir + TTDPRT 14,SPEED=110,TT=%TTLCL ;T14 [not in use] + TTDIML 15 ;T15 [not in use] + TTDVT 16 ;T16 209 x1430 Ilson + TTDIML 17 ;T17 [not in use] + TTDVT 20 ;T20 218A x7705 Licklider + +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX MX,{ ;;; MX + TTDLA36 0,TT=%TTLCL,HOR=110. ;T00 System Console + TTDPRT 1,SPEED=1200,TY=%TYDIL+%TYMDM ;T01 Vadic Dialup + ;253-6045 + TTDVT 2,SPEED=9600 ;T02 TRANTOR Math Dept 2-366 x3-6598 + TTDPRT 3,TY=%TYDIL+%TYMDM ;T03 Dialup + TTDPRT 4,TY=%TYDIL+%TYMDM ;T04 Dialup + ;253-7985 + TTDPRT 5,TY=%TYDIL+%TYMDM ;T05 Dialup + ;253-7986 + TTDPRT 6,TY=%TYDIL+%TYMDM ;T06 Dialup + ;253-7987 + TTDPRT 7,TY=%TYDIL+%TYMDM ;T07 Dialup + ;253-7988 + TTDPRT 10,TY=%TYDIL+%TYMDM ;T10 Vadic Dialup + ;253-6985 + TTDPRT 11,TY=%TYDIL+%TYMDM ;T11 Vadic Dialup + ;253-6986 + TTDPRT 12,TY=%TYDIL+%TYMDM ;T12 Vadic Dialup + ;253-6987 + TTDPRT 13,TY=%TYDIL+%TYMDM ;T13 Vadic Dialup + ;253-6988 + TTDPRT 14,TY=%TYDIL+%TYMDM ;T14 Vadic Dialup + ;253-6989 + TTDPRT 15,TY=%TYDIL+%TYMDM ;T15 Vadic Dialup + ;253-6990 + TTDPRT 16,TY=%TYDIL+%TYMDM ;T16 Vadic Dialup + ;Draper Lab + TTDPRT 17,TY=%TYDIL+%TYMDM ;T17 Vadic Dialup + TTDDPT 20 ;T20 not connected + TTDPRT 21,TY=%TYRLM,SPEED=9600 ;T21 ROLM Data Feature + ; #4997 + TTDPRT 22,TY=%TYRLM,SPEED=9600 ;T22 ROLM Data Feature + ; #4996 + TTDPRT 23,TY=%TYRLM,SPEED=9600 ;T23 ROLM Data Feature + ; #4601 + TTDPRT 24,TY=%TYRLM,SPEED=9600 ;T24 ROLM Data Feature + ; #4999 + TTDPRT 25,TY=%TYRLM,SPEED=9600 ;T25 ROLM Data Feature + TTDPRT 26,TY=%TYRLM,SPEED=9600 ;T26 ROLM Data Feature + ; #4603 + TTDPRT 27,TY=%TYRLM,SPEED=9600 ;T27 ROLM Data Feature + TTDPRT 30,TY=%TYRLM,SPEED=9600 ;T30 ROLM Data Feature + TTDPRT 31,TY=%TYRLM,SPEED=9600 ;T31 ROLM Data Feature + ; #4991 + TTDPRT 32,TY=%TYRLM,SPEED=9600 ;T32 ROLM Data Feature + ; #4992 + TTDPRT 33,TY=%TYRLM,SPEED=9600 ;T33 ROLM Data Feature + TTDPRT 34,TY=%TYRLM,SPEED=9600 ;T34 ROLM Data Feature + TTDPRT 35,TY=%TYRLM,SPEED=9600 ;T35 ROLM Data Feature + TTDPRT 36,TY=%TYRLM,SPEED=9600 ;T36 ROLM Data Frobozz + ; #4990 + TTDPRT 37,TY=%TYRLM,SPEED=9600 ;T37 ROLM Data Feature + TTDPRT 40,TY=%TYRLM,SPEED=9600 ;T40 ROLM Data Feature + TTDPRT 41,TY=%TYRLM,SPEED=300 ;T41 ROLM slow + TTDPRT 42,TY=%TYRLM,SPEED=9600 ;T42 ROLM Data Feature + TTDVT 43,TT=%TTLCL ;T43 9th Floor VT52 + TTDPRT 44,SPEED=110,TT=%TTLCL ;T44 DC76 TTY +.ENDC ;} + +REPEAT NSTTYS,[ + TTDSTY \NFSTTY+.RPCNT +.ENDR ;] + +REPEAT N11TYS,[ + TTDTV \NF11TY+.RPCNT +.ENDR ;] + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX AI,{ ;;; AI + TTDLA36 0,SPEED=1200,HOR=132.,TT=%TTLCL ;T00 System Console + TTDPRT 1,SPEED=1200 ;T01 Chronograph + TTDPRT 2,SPEED=9600 ;T02 DZ Line 2 + TTDPRT 3,SPEED=2400,TY=%TYDIL ;T03 Dialup + ;258-7814 + TTDPRT 4,SPEED=2400,TY=%TYDIL ;T04 Dialup + ;258-7815 + TTDVT 5,SPEED=9600 ;T05 DZ Line 5 (VT52) + TTDVT 6,SPEED=9600,TT=%TTLCL ;T06 9th Floor VT52 by AI x6765 + TTDVT 7,SPEED=9600 ;T07 DZ Line 7 (VT52) + TTDAAA 10,SPEED=9600 ;T10 DZ Line 8 (AAA) + +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX MC,{ ;;; MC + TTDLA36 0,SPEED=1200,HOR=132.,TT=%TTLCL ;T00 System Console + TTDPRT 1,SPEED=2400,TY=%TYDIL ;T01 Dialup + ;258-7585 + TTDPRT 2,SPEED=2400,TY=%TYDIL ;T02 Dialup + ;258-7586 + TTDVT 3,SPEED=9600,TT=%TTLCL ;T03 9th Floor VT52 by MC x6765 + TTDPRT 4,SPEED=9600 ;T04 DZ Line 4 + TTDPRT 5,SPEED=9600 ;T05 DZ Line 5 + TTDAAA 6,SPEED=9600 ;T06 DZ Line 6 (AAA) + +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX ML,{ ;;; ML + TTDLA36 0,SPEED=1200,HOR=132.,TT=%TTLCL ;T00 System Console + TTDPRT 1,SPEED=2400,TY=%TYDIL ;T01 Dialup + ;258-7832 + TTDPRT 2,SPEED=2400,TY=%TYDIL ;T02 Dialup + ;258-7833 + TTDVT 3,SPEED=9600,TT=%TTLCL ;T03 9th Floor VT52 by ML x6765 + TTDPRT 4,SPEED=9600 ;T04 DZ Line 4 + TTDPRT 5,SPEED=9600 ;T05 DZ Line 5 + TTDAAA 6,SPEED=9600 ;T06 DZ Line 6 (AAA) + +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX MD,{ ;;; MD + TTDLA36 0,SPEED=1200,HOR=132.,TT=%TTLCL ;T00 System Console + TTDVT 1,SPEED=9600,TT=%TTLCL ;T01 9th Floor VT52 by MD x6765 + TTDPRT 2,SPEED=9600 ;T02 DZ Line 2 + TTDPRT 3,SPEED=9600 ;T03 DZ Line 3 + TTDAAA 4,SPEED=9600 ;T04 DZ Line 4 (AAA) + +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX SI,{ ;;; SI + TTDLA36 0,SPEED=1200,HOR=132.,TT=%TTLCL ;T00 System Console + TTDPRT 1,SPEED=9600 ;T01 DZ Line 1 + TTDPRT 2,SPEED=9600 ;T02 DZ Line 2 + TTDPRT 3,SPEED=9600 ;T03 DZ Line 3 + TTDPRT 4,SPEED=9600 ;T04 DZ Line 4 + TTDPRT 5,SPEED=9600 ;T05 DZ Line 5 + TTDPRT 6,SPEED=9600 ;T06 DZ Line 6 + TTDPRT 7,SPEED=9600 ;T07 DZ Line 7 + TTDPRT 10,SPEED=9600 ;T10 DZ Line 10 + TTDPRT 11,SPEED=9600 ;T11 DZ Line 11 + TTDPRT 12,SPEED=9600 ;T12 DZ Line 12 + TTDPRT 13,SPEED=9600 ;T13 DZ Line 13 + TTDPRT 14,SPEED=9600 ;T14 DZ Line 14 + TTDPRT 15,SPEED=9600 ;T15 DZ Line 15 + TTDPRT 16,SPEED=9600 ;T16 DZ Line 16 + TTDPRT 17,SPEED=9600 ;T17 DZ Line 17 + TTDPRT 20,SPEED=9600 ;T20 DZ Line 20 + TTDPRT 21,SPEED=9600 ;T21 DZ Line 21 + TTDPRT 22,SPEED=9600 ;T22 DZ Line 22 + TTDPRT 23,SPEED=9600 ;T23 DZ Line 23 + TTDPRT 24,SPEED=9600 ;T24 DZ Line 24 + TTDPRT 25,SPEED=9600 ;T25 DZ Line 25 + TTDPRT 26,SPEED=9600 ;T26 DZ Line 26 + TTDPRT 27,SPEED=9600 ;T27 DZ Line 27 + TTDPRT 30,SPEED=9600 ;T30 DZ Line 30 + TTDPRT 31,SPEED=9600 ;T31 DZ Line 31 + TTDPRT 32,SPEED=9600 ;T32 DZ Line 32 + TTDPRT 33,SPEED=9600 ;T33 DZ Line 33 + TTDPRT 34,SPEED=9600 ;T34 DZ Line 34 + TTDPRT 35,SPEED=9600 ;T35 DZ Line 35 + TTDPRT 36,SPEED=9600 ;T36 DZ Line 36 + TTDPRT 37,SPEED=9600 ;T37 DZ Line 37 + TTDPRT 40,SPEED=9600 ;T40 DZ Line 40 + +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX FU,{ ;;; FU + TTDLA36 0,SPEED=1200,HOR=132.,TT=%TTLCL ;T00 System Console + TTDPRT 1,SPEED=9600 ;T01 DZ Line 1 + TTDPRT 2,SPEED=9600 ;T02 DZ Line 2 + TTDPRT 3,SPEED=9600 ;T03 DZ Line 3 + TTDPRT 4,SPEED=9600 ;T04 DZ Line 4 + TTDPRT 5,SPEED=9600 ;T05 DZ Line 5 + TTDPRT 6,SPEED=9600 ;T06 DZ Line 6 + TTDPRT 7,SPEED=9600 ;T07 DZ Line 7 + TTDPRT 10,SPEED=9600 ;T10 DZ Line 10 + +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX PM,{ ;;; PM + TTDLA36 0,SPEED=1200,HOR=132.,TT=%TTLCL ;T00 System Console + TTDPRT 1,SPEED=9600 ;T01 (9600 baud) + TTDPRT 2,SPEED=9600 ;T02 (9600 baud) + TTDPRT 3,SPEED=1200,TY=%TYDIL ;T03 Dialup (1200 baud) + TTDPRT 4,SPEED=1200,TY=%TYDIL ;T04 Dialup (1200 baud) + TTDPRT 5,SPEED=9600 ;T05 (9600 baud) + +.ENDC ;} + +;NOTE: SEE COMMENT AT FRONT OF FILE FOR CONSTRAINTS ON THE COMMENTS +;THAT APPEAR ON THE FOLLOWING LINES. ALSO NOTE THAT LOWER CASE +;CHARACTERS MAY BE PRESENT IN THEM. + +MCONDX DX,{ ;;; DX + TTDLA36 0,SPEED=1200,HOR=132.,TT=%TTLCL ;T00 System Console + TTDPRT 1,SPEED=300 ;T01 DZ Line 1 (300 baud) + TTDPRT 2,SPEED=1200 ;T02 DZ Line 2 (1200 baud) + TTDPRT 3,SPEED=2400 ;T03 DZ Line 3 (2400 baud) + TTDPRT 4,SPEED=4800 ;T04 DZ Line 4 (4800 baud) + TTDPRT 5,SPEED=9600 ;T05 DZ Line 5 + TTDPRT 6,SPEED=9600 ;T06 DZ Line 6 + TTDPRT 7,SPEED=9600 ;T07 DZ Line 7 + TTDPRT 10,SPEED=9600 ;T10 DZ Line 10 + +.ENDC ;} diff --git a/src/system/tv.132 b/src/system/tv.132 new file mode 100755 index 00000000..e8d87f0d --- /dev/null +++ b/src/system/tv.132 @@ -0,0 +1,5995 @@ +;-*-MIDAS-*- + +.SBTTL MACROS AND CONDITIONAL ASSEMBLY + +;AI PDP-11 TV CONSOLE PROGRAM +; USER WHO-LINE VARIABLES CODE ADDED 7/28/75 BY GLS +; AUDIO SWITCH CODE REWRITTEN 7/12/76 BY ED +; TV IS PDP-11 NUMBER 0 TO THE 10-11 INTERFACE. +; ELEVATOR CODE 2/13/79 BY DANNY & HIC +; REGION-SCROLLING 11/3/79 MOON + +FONTSW==1 ;COMPILE FONTS +FONTMS==0 ;USE MACROS TO COMPILE FONTS + +;REGISTER ASSIGNMENTS + +A=%0 ;ASCII CHARACTER +B=%1 ;META BITS +C=%2 ;C, T, AND TT ARE TEMPORARIES +T=%3 +TT=%4 +U=%5 ;LINE EDITOR OR PAGE PRINTER +SP=%6 +PC=%7 + +.XCREF A,B,C,T,TT,U,SP,PC,...,.... + +.IIF E FONTSW,.TITLE TV NOFONTS + +.IF NE FONTSW +.TITLE TV +.IF NE FONTMS +.NLIST ;WE'RE ONLY INTERESTED IN FONTS +.IF1 +.PRINT /THIS ASSEMBLY WILL TAKE FOREVER! +/ +.ENDC ;.IF1 +.ENDC ;.IF NE FONTMS +.ENDC ;.IF NE FONTSW + +.MACRO PUSH A +.NLIST + MOV A,-(SP) +.LIST +.ENDM + +.MACRO POP A +.NLIST + MOV (SP)+,A +.LIST +.ENDM + +.MACRO REPORT TEXT,NUM +.NLIST +.IF2 +.LIST +.PRINT /TEXT'NUM +/ +.NLIST +.ENDC +.LIST +.ENDM + +.MACRO CHROFF +.NLIST + MOVB PS,-(SP) + MOVB #LKLVL,PS +.LIST +.ENDM + +.MACRO CHRON +.NLIST + MOVB (SP)+,PS +.LIST +.ENDM + +.MACRO BLKOFF A +.NLIST + INCB BLKSWT(A) +.LIST +.ENDM + +.MACRO BLKON A +.NLIST + DECB BLKSWT(A) + BGE .+4 + BPT +.LIST +.ENDM + +.MACRO TENWRD +.NLIST +.IIF NE .&3,.=<.&177774>+4 +.LIST +.ENDM + +.MACRO CHECK TAG,LENGTH +.NLIST +.IF NE .-- +.ERROR TAG WRONG LENGTH +.ENDC +.EVEN +.LIST +.ENDM + +.MACRO TYPOUT A +.NLIST + JSR PC,OUTSTR + .ASCIZ A + .EVEN +.LIST +.ENDM + +.MACRO DECTYPE NUM +.NLIST + MOV NUM,A + JSR PC,DECPNT +.LIST +.ENDM + +.MACRO OCTYPE NUM +.NLIST + MOV NUM,A + JSR PC,OCTPNT +.LIST +.ENDM + +.MACRO ZAPFLG FLAG +.NLIST +%COMPAT==0 + MOV PC,FLAG +%COMPAT==1 +.LIST +.ENDM + +.MACRO CONC A,B,C,D,E,F,G,H,I +A'B'C'D'E'F'G'H'I +.ENDM + +.IF NE 0 ;PROGRAM MAP: +0, TO PDLORG ;TRAP VECTORS +PDLORG, TO KBDBUF ;PUSH DOWN LIST +KBDBUF, TO GO ;KBD BUFFER +GO, TO XTAB ;PROGRAM +XTAB, TO FNTORG ;KEYBOARD TRANSLATION TABLE +FNTORG, TO VARORG ;FONT DEFINITION +VARORG, TO MISORG ;LINE EDITOR/PAGE PRINTER VARIABLES +MISORG, TO PATCH ;MISCELLANEOUS TABLES AND VARIABLES +PATCH, TO LEBUFS ;PATCH AREA +LEBUFS, TO RUGSA ;FREE STORAGE +.ENDC + +.SBTTL HOW IT WORKS +.REPT 0 +channel header pointer (location 40, read only) + + ADDRESS(channel header area) + ADDRESS(pointer area) + I/O version number + source file version number + 0 always 0 + INITED non-zero indicates PDP-11 is running ok(can be cleared by PDP-10) + 0 always 0 + GDOWN used as flag by PDP-10 to acknowledge clear of INITED +channel header area (aligned on PDP-10 word) + + KBD channel: + KBDFLG cleared by 10/set by 11 (chain of activated KBD buffers) + 0 allows PDP-10 to do SKIPN for activation test + DPY channel: (1 per console) + DPYCHN buffer assigned to channel, if zero then DPY channel is closed + DPYKBD .BYTE KBD#, DPY# (377 for either implies not assigned) + KBD flags: (1 per console) + ECOFLG Set by PDP-10. Next time DPYBUF is empty clear ECOFLG + and put flag on KBD ring to signal this condition + CHNCLS if -1, log this guy out!!!! + If non-negative, has keyboard number (377 if none). + WHO flags: (1 per console) + WHOLIN who line variables for this console + WHOUSR -1=>user who line, 0=>system who line + + +format of KBD buffer (aligned on PDP-10 word) + + KBDSTS negative=>-(data byte count), 0=>free + 0 + KBDRNG next KBD buffer associated with this KBD + KBDLST next buffer on activated list (0=>end of chain) + KBDCHN keyboard channel + 0 not used + KBDATA key board data area (1 PDP-11 word/character) + +format of DPY buffer (aligned on PDP-10 word) + (actually, this is the beginning of the "line editor vars" or "channel vars" block). + + DPY10B word PDP-10 is hacking (used only for initailization) + This always points at DPYATA for this buffer these days. + DPY11B word PDP-11 is hacking + 0 + DPYLGL last legal address in this buffer + DPYSIZ size of data area in bytes + 0 not used + DPYATA display data area (1 PDP-11 byte/character) + +format of pointer area (aligned on PDP-10 word) + + ADDRESS(system who line variables) + ADDRESS(PDP-10/PDP-11 communication area) + TENWHO -1=>PDP-10 should update who lines + TENWH1 pads TENWHO + SYMTAB BEGINNING OF TABLE OF SWITCHES WHICH 10 ACCESSES. + +Notes: + +1. All addresses and pointers are in PDP-11 address space. + +2. KBD buffers are ringed two per channel. While the PDP-10 is + emptying one, the PDP-11 can fill the other. + +3. There is only one DPY buffer per channel. When the buffer is filled + with negative ones, it is free. When the PDP-10 writes a character + in the current word: then the PDP-11 processes the data in that + word, sets that word to negative one, and advances to the next word. + (Formerly any negative number would do, but now that the byte size is + 8 rather than 16, -1 [377] must be used since valid characters > 200 exist.) + +WHO LINE VARIABLES + +SYSTEM WHO LINE (ALIGNED ON PDP-10 WORD) + ITSTDP # total # dpy's (read only for PDP-10) + ITSFDP # free dpys (read only for PDP-10) + ITSVER ITS version # + ITSJOB total jobs + ITSCOR total core + ITSRU runnable users + ITSWBJ # jobs swap blocked + ITSJWP # jobs waiting for pages + ITSTRC total runable core + ITSCFU core available for users + ITSDAT date [byte (7) year (4) month (5) day] + ITSDBG system debug flag + ITSTIM time of day (# half seconds since midnight) aligned on PDP-10 word + ITSTI1 low order of time + ITSUSR total number of users + ITSFSH fair share + +USER WHO LINE (ALIGNED ON PDP-10 WORD) + WHJOB job #, -1=>who line not in use + WHJOB1 if negative then clear who line + WHMODE mode 0=>follow keyboard + 1=>freeze + 2=>next higher (when PDP-10 sees this state, it searches + user variables for next higher job index number with same + uname. When it finds it, it stores the number in job # + and changes mode to 1 + 3=>next lower + WHMOD1 pads WHMODE + WHUNAM uname in sixbit (left 18 bits in first two words, right in next two) + WHUNM1 + WHUNM2 + WHUNM3 + WHJNAM jname in sixbit + WHJNM1 + WHJNM2 + WHJNM3 + WHSNAM sname in sixbit + WHSNM1 + WHSNM2 + WHSNM3 + WHSTAT status in sixbit, 0=>job does not exist + WHSTA1 + WHSTA2 + WHSTA3 + WHJ%RT job % run time + WHJTRT job total run time (in tenth's of seconds) + WHRPAG job real memory pages (swapped in) + WHTPAG job total pages + +NOTE: The PDP-11 will not update who lines until it sees that ITSTIM + has changed. + +PDP-10/PDP-11 COMMAND CHANNEL + + CMDFLG aligned on PDP-10 + 0=>buffer is free (PDP-10 can write CMDBUF) + positive=>command # from PDP-10 (PDP-11 can write CMDBUF) + negative=>affirmative reply from PDP-11 (0=>command failed) + PDP-10 can read CMDBUF, then must zero CMDFLG + CMDFL1 always 0 + CMDBUF each arg takes 4 bytes (1 PDP-10 word) + + PDP-10/PDP-11 COMMANDS + + 1 video switch + arg1: video switch input # (set by PDP-10) + arg2: video switch output # ( " " " " ) + + 2 reserve DPY + arg1: DPY reserved (set by PDP-11) + + 3 free DPY + arg1: DPY to free (set by PDP-10) + + 4 read video switch + arg1: < 0 for default setting, > 0 for current setting (set by PDP-10) + 1=>tty chnl, 2=>KBD, 3=>video switch output + arg2: # described by arg1 (set by PDP-10) + arg3: input (set by PDP-11) + arg4: input (set by PDP-11) + arg5: output(set by PDP-11) + + 5 audio switch + arg1: audio switch input # (set by PDP-10) + arg2: audio switch output # (set by PDP-10) + + 6 read audio switch (for this to be useful, 11 must maintain table, since + the audio switch is read-only. + arg1: < 0 for default setting, > 0 for current setting (set by PDP-10) + 1=>tty chnl, 2=>KBD, 3=>audio switch output + arg2: # described by arg1 (set by PDP-10) + arg3: input (set by PDP-11) + arg4: output(set by PDP-11) + +;other 10-11 commuincation issues .. + +;go down resetting video switch vs not +;PDP-11 indicates it has reset video switch + ;(PDP-10 then detaches all jobs with tv ttys) + +;console scroll register 6/23/74 + +CSA==157776 ;selects where video scan starts in video buffer + +__|_____|_____|_____|_____|_____| +15 1211 | +| 3 |1| 12 | +|_____|_|_______________________| + | | | + | | |----------------->scroll offset (start video scan at n*4 PDP-11 words from TVLO) + | | + | |------------------------------->black on white bit (1=>black on white) + | + |----------------------------------->not used + + + +;console register 6/24/74 + +CREG==164044 ;selects video buffer memory + +__|_____|_____|_____|_____|_____| +15 7 | +| 8 | 8 | +|_______________|_______________| + | | + | |-------------->console # (TVLO-TVHI on unibus is video bit map) + | + |------------------------------>ALU function + +video switch 4/17/74 + +VSW==164060 ;sets video switch + +__|_____|_____|_____|_____|_____| +15 12 10 7 3 | +| 3 | 2 | 3 | 4 | 4 | +|_____|___|_____|_______|_______| + | | | | | + | | | | |---------->video source + | | | | + | | | |------------------>not used + | | | + | | |------------------------->| |card section + | | |switch output| + | |------------------------------>| |card select + | + |----------------------------------->switch section number + + +audio switch 7/12/76 + +ASW==170670 ;SETS AUDIO SWITCH. (this is a write-only memory.) + +__|_____|_____|_____|_____|_____| +15 13 10 7 3 | +| 2 | 3 | 3 | 4 | 4 | +|___|_____|_____|_______|_______| + | | | | | + | | | | |---------->audio source + | | | | + | | | |------------------>not used + | | | + | | |------------------------->| |card section (complemented) + | | |switch output| + | |------------------------------->| |card select + | + |------------------------------------>not used + +ASWXOR==1617 ;complemented fields of ASW. + +keyboard multiplexor 3/15/74 + +KBDPC==340 ;interrupt vector +KBDLVL==5_7 ;interrupts on level 5 + +KMS==164050 ;keyboard status + +__|_____|_____|_____|_____|_____| +151413121110 9 8 7 6 5 4 1 | +|1|1|1|1|1|1|1|1|1|1|1| 3 | 2 | +|_|_|_|_|_|_|_|_|_|_|_|_____|___| + | | | | | | | | | | | | | + | | | | | | | | | | | | |------>KMA extension (bits 17 and 16) + | | | | | | | | | | | | + | | | | | | | | | | | |----------->not used + | | | | | | | | | | | + | | | | | | | | | | |--------------->interrupt enable + | | | | | | | | | | + | | | | | | | | | |----------------->direct memory access enable + | | | | | | | | | + | | | | | | | | |------------------->waiting to hack memory + | | | | | | | | + | | | | | | | |--------------------->8th floor elevator + | | | | | | |----------------------->9th floor elevator + | | | | | | + | | | | | |------------------------>extra OC output, pin BBF1. + | | | | | + | | | | |--------------------------->buzz the 9th floor door (dip relay) + | | | | + | | | |----------------------------->generate copy from second source(currently not + | | | enabled) + | | |------------------------------->generate copy from first source + | | + | |--------------------------------->ready line + | + |----------------------------------->waiting to interrupt + +KMA==165052 ;keyboard memory address register + +__|_____|_____|_____|_____|_____| +15 7 1 | +| 9 | 5 | 2 | +|_________________|_________|___| + | | | + | | |----->always 0 + | | + | |------------>binary counter (overflow lost) + | + |------------------------->buffer origin + +;keyboard multiplexor 3/15/74 +;format of data written into memory (each record is two words) + +;first word + +__|_____|_____|_____|_____|_____| +151413 11 9 7 5 | +|1|1| 2 | 2 | 2 | 2 | 6 | +|_|_|___|___|___|___|___________| + | | | | | | | + | | | | | | |--------->key struck + | | | | | | + | | | | | |----------------->shift (7-left, 6-right) + | | | | | + | | | | |--------------------->top (9-left, 8-right) + | | | | + | | | |------------------------->control (11-left, 10-right) + | | | + | | |----------------------------->meta (13-left, 12-right) + | | + | |-------------------------------->shift lock + | + |---------------------------------->always 1 + +;second word + +__|_____|_____|_____|_____|_____| +15 13 7 | +| 2 | 6 | 8 | +|___|___________|_______________| + | | | + | | |----------->high order bits of character (ignored) + | | + | |------------------------->console number + | + |--------------------------------->always 0 + +.ENDR + +;CHARACTER FORMAT WRITTEN BY KBD MULTIPLEXOR + +RCHAR==177700 ;6 BITS FOR KEY STRUCK +RSHBIT==300 ;SHIFT BITS +RTPBIT==1400 ;TOP BITS +RCLBIT==6000 ;CONTROL BITS +RMTBIT==30000 ;META BITS +RSLBIT==40000 ;SHIFT LOCK +RXTRA==100000 ;UNUSED BITS + +;XTAB BITS USED FOR XTAB LOOK UP + +XTPBIT==400 ;TOP +XSLBIT==200 ;SHIFT LOCK +XSHBIT==100 ;SHIFT + +;POSITION OF META BITS, ASCII COMPATIBLE + +ACTBIT==SNB ;CAUSES CHARACTER TO ACT AS ACTIVATOR +ACLBIT==200 ;CONTROL +AMTBIT==400 ;META +ASHBIT==XSHBIT_3 ;SHIFT +ASLBIT==XSLBIT_3 ;SHIFT LOCK +ATPBIT==XTPBIT_3 ;TOP +ACMBIT==AMTBIT+ACLBIT ;CONTROL AND META TOGETHER + +.SBTTL ASSIGNMENTS + +;GEOMETRY + +BITPL==1100 ;BITS PER LINE +NLINS==706 ;LINES ON SCREEN +BYTPL==BITPL/10 ;BYTES PER LINE +WRDPL==BYTPL/2 ;WORDS PER LINE + +CHRWD==6 ;CHARACTER WIDTH ON TEXT LINE +GRIDWD==5 ;WIDTH OF CHARACTER GRID +CHRHT==12 ;CHARACTER HEIGHT +CHRVSP==2 ;BLANK RASTER LINES BETWEEN CHARACTER LINES +LINHT==CHRHT+CHRVSP ;CHRACTER LINE HEIGHT +CHRPL==BITPL/CHRWD ;CHARACTERS PER LINE +CHRLN==NLINS/LINHT ;CHARACTER LINES ON SCREEN + +;MEMORY MAP + +NXMPC== 4 ;BUS ERROR VECTOR +NXMPSW== 6 +RESPC== 10 ;RESERVED INTRUCTION VECTOR +RESPSW== 12 +BPTPC== 14 ;BREAK POINT VECTOR +BPTPSW== 16 +IOTPC== 20 ;IOT VECTOR +IOTPSW== 22 +PWRPC== 24 ;POWER FAIL TRAP VECTOR +PWRPSW== 26 +EMTPC== 30 ;EMULATE TRAP VECTOR +EMTPSW== 32 +TRPPC== 34 ;TRAP INSTRUCTION VECTOR +TRPPSW== 36 +TYIPC== 60 ;TTY INPUT INTERRUPT VECTOR +TYIPSW== 62 +LKPC== 100 ;LINE CLOCK INTERRUPT VECTOR +LKPSW== 102 +KLIPC== 320 ;KL11 INPUT INTERRUPT VECTOR +KLIPSW==322 +KBDPC== 340 ;KEYBOARD MULTIPLEXOR INTERRUPT VECTOR +KBDPSW==342 + +PDLORG==400 ;ORIGIN OF PUSH DOWN LIST +TVLO=60000 ;ORIGIN OF DISPLAY MEMORY +TVFENCE=TVLO+ ;ADDR OF FIRST TEXT LINE THAT SHOULDN'T BE USED + ;(IT'S INCOMPLETE AND CONTAINS THE WHO-LINE). +TVCFENC=TVHI-> ;DON'T TRY TO DISPLAY A CHARACTER AFTER THIS POINT +TVHI=TVLO+-2 ;HIGHEST LEGAL DISPLAY ADDRESS +CSA=157776 ;DISPLAY REFRESH STARTING ADDRESS (STARTS AT 0) + +CREG== 164044 ;UNIBUS CONSOLE REGISTER ADDRESS +CALU== 164045 ;CONSOLE REGISTER LOGICAL FUNCTION ADDR +KMS== 164050 ;KEYBOARD MULTIPLEXOR STATUS +KMA== 164052 ;KEYBOARD MULTIPLEXOR MEMORY ADDRESS +VSW== 164060 ;VIDEO SWITCH +ASW== 170670 ;AUDIO SWITCH +KLIS== 174000 ;KL11 INPUT STATUS +KLIB== 174002 ;KL11 INPUT BUFFER +KLOS== 174004 ;KL11 OUTPUT STATUS +KLOB== 174006 ;KL11 OUTPUT BUFFER + +.EXPUNGE DIV,MUL,ASH ;THESE ARE PREDEFINED AS 11/45 INSTRUCTIONS. +DIV== 177300 ;EAE GOODIES +AC== 177302 +MQ== 177304 +MUL== 177306 +SC== 177310 +SR== 177311 +NOR== 177312 +LSH== 177314 +ASH== 177316 +LKS== 177546 ;LINE CLOCK STATUS +TKS== 177560 ;TTY KEYBOARD STATUS +TKB== 177562 ;TTY KEYBOARD BUFFER +TPS== 177564 ;TTY PRINTER STATUS +TPB== 177566 ;TTY PRINTER BUFFER +CSR== 177570 ;CONSOLE SWITCH REGISTER +PS== 177776 ;PROCESSOR STATUS REGISTER +...==0 +....==0 + +;TEN/11 COMMUNICATIONS AREA + +CHAP==40 ;CHANNEL HEADER AREA POINTER +POINTP==42 ;POINTER TO POINTER AREA +CIOVER==44 ;HOLDS I/O VERSION FOR PDP-10 TO LOOK AT +CVERSE==46 ;ASSEMBLY VERSION FOR PDP-10 + ;50 ;ALWAYS 0 +INITED==52 ;INITED FLAG, SET BY 11 CLEARED BY 10 + ;54 ;ALWAYS 0 +GDOWN==56 ;INTERLOCKS WITH INITED, CLEARED BY 11 SET BY 10 + +;CONSOLE REGISTER FUNCTIONS + +CSETC==0 +CNOR==1 +CANDC==2 +CSETZ==3 +CNAND==4 +CCOMP==5 +CXOR==6 +CANCSD==7 +CEQV==11 +CORCSD==10 +CSAME==12 +CAND==13 +CORSCD==13 +CSETO==14 +CIOR==16 +CSET==17 + +;INTERRUPT LEVELS + +KBDLVL==5_5 ;KEYBOARD MULTIPLEXOR INT. PRIORITY (BUT HANDLER RUNS AT LKLVL). +LKLVL==6_5 ;LINE CLOCK +ERRLVL==7_5 ;PROCESSOR ERRORS + +;MISCELLANEOUS ASSIGNMENTS + +IOVER==3 ;I/O VERSION FOR ITS +PDL==400 ;PUSH DOWN LIST SIZE +MAXKBD==64. ;MAXIMUM # OF KEYBOARDS +MAXTV==16. ;MAX NUMBER OF TV DISPLAYS +MAXBLK==MAXTV ;MAXIMUM # OF BLINKERS +MAXASI==20 ;AUDIO SWITCH INPUTS +MAXASO==100 ;AUDIO SWITCH OUTPUTS +ASWXOR==3400 ;XOR THIS INTO EACH CONTROL WORD TO BE SENT TO THE ASW. +MAXVSI==20 ;VIDEO SWITCH INPUTS +MAXVSO==40 ;VIDEO SWITCH OUTPUTS +VSWSEC==2 ;# VIDEO SWITCH SECTIONS +VSWINC==MAXVSO_10 ;INCREMENTS VIDEO SWITCH SECTION NUMBER +QPYVSW==27 ;VIDEO SWITCH OUTPUT FOR TEKTRONIX VIDEO HARD COPY UNIT +QPTIME==21.*60. ;21. SECONDS BETWEEN COPIES +QPYKMS==20000 ;GENERATE COPY FROM FIRST SOURCE (IN KEYBOARD STATUS, NATURALLY) +QPYKM2==10000 ;GENERATE COPY FROM SECOND SOURCE. +BUZKMS==4000 ;BUZZ DOOR (ALSO IN KEYBOARD STATUS) +BUZTIM==3*60. ;LEAVE THE DOOR BUZZING FOR 3 SECONDS +ELKMS8==1 ;8TH FLOOR ELEVATOR BIT, SWAPPED (IT LIVES IN BYTE 1 OR WORD) +ELKMS9==2 ;9TH FLOOR ELEVATOR BIT, SWAPPED. +ELEKMS==1400 ;ALL ELEVATOR BITS +ELETIM==20 ;PUSH THE BUTTON FOR 1/3 OF A SEC +KBDTIM==10. ;TIME UNTIL KEYBOARD GETS RESET (IN SEMI-SLOW CLOCK TICKS) +MAXBEL==4 ;MAXIMUM # OF BELLS ALLOWED +GLITIM==60.*60.*2 ;# CLOCK TICKS BETWEEN GLITCHES ON CONSOLE FREE DPY +NCQSLT==100 ;# CLOCK QUEUE SLOTS +KBDBFL==200 ;SIZE OF KEYBOARD BUFFER +LBLEN==100 ;PDP-10 INPUT BUFFER SIZE (BETTER BE DIVISIBLE BY 4) +LBCHRS==LBLEN/2 ;# CHARACTERS IN INPUT BUFFER +DPSIZE==600 ;PDP-10 OUTPUT BUFFER SIZE +BOWBIT==10000 ;CSA BLACK ON WHITE BIT +SAMSK==BOWBIT-1 ;MASK FOR SCROLL REGISTER +CSAMSK==170000 ;COMPLEMENT OF SAMSK +BLKTIM==15. ;CLOCK TICKS BETWEEN BLINKS +SNB==100000 ;SIGN BIT +PATL==400 ;SIZE OF PATCH AREA +CMDARG==10 ;# ARGUMENTS WHICH WILL FIT INTO PDP-10/PDP-11 COMMAND BUFFER +RUGSA==57100 ;STARTING ADDRESS OF RUG +TYMSLC==2 ;MAX # 60THS OF A SECOND, MINUS 1, TO CONCENTRATE ON ONE TV + +.SBTTL GO CODE, PDL, AND KBD BUFFER + +.ABS + +;PUSH DOWN LIST AND KEYBOARD BUFFER + +.=PDLORG+PDL +.IIF NE .&177,.=<.&177600>+200 ;ALIGN ON 200 BYTE BOUNDARY +PDBUF==. + +KBDBUF: +.=.+KBDBFL +KBDEND==. + +REPORT GO=,\GO + +GO: RESET ;IN THE PRIVACY OF YOUR OWN HOME + CLR PS + MOV #PDBUF,SP ;SET UP PUSH DOWN POINTER + MOV #ERRLVL,C ;ALL PROCESSOR TRAPS GO ON 7 + MOV #NXMPC,B + MOV #NXMBRK,(B)+ ;BUS TIME OUT + MOV C,(B)+ + MOV #RESBRK,(B)+ ;RESERVED INSTRUCTION + MOV C,(B)+ + MOV (B),T ;BREAK POINT + BNE .+6 + MOV #BPTBRK,T + MOV T,(B)+ + MOV C,(B)+ + MOV #IOTBRK,(B)+ ;IOT TRAP + MOV C,(B)+ + MOV #PWRBRK,(B)+ ;POWER FAILURE + MOV C,(B)+ + MOV #EMTBRK,(B)+ ;EMT + MOV C,(B)+ + MOV #TRPBRK,(B)+ ;"TRAP" TRAP (LEV 7) + MOV C,(B)+ + MOV #CHA,(B)+ ;CHANNEL HEADER AREA + MOV #POINTA,(B)+ ;POINTER AREA POINTER + MOV #IOVER,(B)+ ;I/O VERSION + MOV VERSE,(B)+ ;ASSEMBLY VERSION + CLR (B)+ ;INITED + CLR (B)+ + MOV C,(B)+ ;NON-ZERO SUFFICES + MOV C,(B)+ ;GDOWN + MOV #CLKBRK,LKPC ;CLOCK + MOV #LKLVL,LKPSW + MOV #KBDBRK,KBDPC ;KBD + MOV #LKLVL,KBDPSW + MOV #BPT,0 ;CATCH JUMPS TO ZERO. + +;FALLS THROUGH + +;INITIALIZE VARIBLES FALLS THROUGH + + JSR PC,INIT + +;ENABLE INTERRUPTS + + MOV #100,LKS ;CLOCK + MOV #KBDBUF,KMA + MOV #KBDBUF,OLDKMA + MOV #140,KMS ;KEYBOARD MULTIPLEXOR + MOV #-1,INITED + +;THE MAIN LOOP + +MAIN: MOV #MAXTV-1,U ;CHANNEL + CMP WHOTIM,ITSTI1 ;TIME FOR WHO LINES? + BEQ MAIN1 + ZAPFLG WHOFLG ;TRIGGER WHO LINES +MAIN1: TST INITED + BEQ GO ;RESET THE WORLD + TST CSR + BLT GO2RUG ;SWITCH 15 => GO TO RUG +MAIN3: JSR PC,DPYDPY + MOV CMDFLG,A ;PDP-10 GIVING COMMAND? + BLE MAIN2 + PUSH U + JSR PC,TENCMD ;PROCESS THE COMMAND + POP U +MAIN2: DEC U + BGE MAIN1 ;CYCLED THROUGH ALL CHANNELS? + CLR WHOFLG ;TURN OFF WHO LINES + BR MAIN + +GO2RUG: BPT + BR MAIN3 + +;HERE TO RESTART, NOTIFY THE PDP-10 + +GODOWN: RESET + CLR PS + MOV #INITED-2,B + CLR (B)+ + CLR (B)+ ;INITED + CLR (B)+ + CLR (B)+ ;GDOWN + TST GDOWN ;WAIT FOR THE PDP-10 TO REPLY + BEQ .-4 + JMP GO + +.SBTTL INITIALIZATION + +INIT: CLR TICKS + CLR TICKS1 +;******* TEMPORARY CODE FOR FONT CHECKSUM ******* + MOV #FNTORG,T + MOV T,CKSPNT + CLR CKSSUM + CLR TT +1$: ADD (T)+,TT + CMP T,#FNTEND + BLO 1$ + MOV TT,CKSSMG +;******* END OF TEMPORARY CODE ******* + CLR KBDFLG + CLR KBDFLG+2 + CLR KBDACT + CLR KBDLAST + CLR KBDTSW + CLR CMDFLG + CLR CMDFLG+2 + CLR WHOTIM + CLR ITSTI1 + CLR WHOFLG + CLR TENWHO + CLR QPYSWT + CLR BUZSWT + CLR ELESWT + CLR SSCC + JSR PC,REASW ;FEED EVERY SPEAKER SILENCE. + + MOV #LEBUFS,U ;INITIALIZE FREE LIST OF 11-TO-10 INPUT BUFFERS. + MOV U,FSP + MOV #NLBUFS-1,B +INIT6: MOV U,TT + ADD #,TT + MOV TT,LHFS(U) + MOV TT,U + DEC B + BGT INIT6 + CLR LHFS(U) ;END OF LIST + + CLR BLINK + MOV #BLINKS,A + MOV #BELCNT,C + MOV #-1,T ;SET UP BELL COUNTS + MOV #MAXTV-1,B + CLR ITSTDP +INIT5: CLRB CHNUSE(B) ;EVERY CHANNEL IS FREE. + CLRB BLKSWT(B) ;NO TV HAS BLINKING TEMPORARILY INHIBITED. + TSTB CHCREG(B) ;HOW MANY CHANNELS ARE WORKING? + BLT INIT5A + INC ITSTDP +INIT5A: CLR (A)+ + MOV T,(C)+ + DEC B + BGE INIT5 + MOV ITSTDP,ITSFDP ;# FREE DPY'S + + MOV #MAXBLK,B ;PUT ALL BLINKER BLOCKS ON THE FREE BLINKERS LIST. + MOV #BLKVAR,U + MOV U,FBLINK +INIT7: MOV U,TT + ADD #BLLEN,TT + MOV TT,BLNEXT(U) + CLRB BLON(U) + MOV TT,U + DEC B + BGT INIT7 + CLR (U) + + MOV #MAXTV-1,A + CLR T + MOV #WHVARS,C +INIT2: MOV DPYCHN(T),U + JSR PC,CHCLR ;SET UP THAT CHANNEL + MOV #-1,DPYKBD(T) + MOV #-1,CHNCLS(T) + CLR ECOFLG(T) + MOV C,WHOLIN(T) + MOV #-1,(C) .SEE WHJOB + ADD #WHLEN,C + CMP (T)+,(T)+ + DEC A + BGE INIT2 ;MORE DPY CHANNELS TO SET UP? + + MOV #-1,C + JSR PC,CHCONS ;GET A CHANNEL FOR THE FREE SCREENS. + TST T + BEQ .+4 ;THIS SHOULD ALWAYS GIVE US CHANNEL 0. + BPT + MOV WHOLIN,TT ;WANT SYSTEM WHO LINE ON CONSOLE FREE DPY + MOV #NWHCMD,WHMODE(TT) + MOVB CHCREG,TT ;TT GETS WHICH VIDEO BUFFER IT IS. + MOV TT,DPYFRE ;REMEMBER # OF DPY USED FOR FREE SCREENS. + MOVB TT,CREG ;SET UP CONSOLE REGISTER FOR PRINT + CLR CSA + TYPOUT + MOVB LECREG(U),C ;DPY + ASL C + MOV #MAXVSO-1,B ;SWITCH TO ALL OUTPUTS +INIT1: MOV DPYVSW(C),TT ;VIDEO SWITCH INPUT + MOV B,T ;SWITCH OUTPUT + JSR PC,VSWIT + DEC B + BGE INIT1 + + MOV #MAXKBD,A ;CLEAR KBDLE + CLR B +INIT8: CLR KBDLE(B) + CLR KBDESC(B) + MOV #-1,KBDDEF(B) + TST (B)+ + DEC A + BGT INIT8 + + MOV #NCQSLT-1,C ;INITIALIZE CLOCK QUEUE + CLR CLOCKQ + MOV #CQUEUE,A + MOV A,CLOCKF +INIT9: MOV A,B + ADD #CQLEN,B + MOV B,(A) + MOV B,A + DEC C + BGT INIT9 + CLR (A) + MOVB #CSET,CALU + MOV CREG,T ;SEED QUEUE WITH GLITCH CONSOLE FREE + JSR TT,ADQUE + GLITIM + MSGLIT + RTS PC + +.SBTTL MAIN PROGRAM LEVEL ROUTINES + +;HERE TO GET CHARACTER FROM OPEN CHANNEL +;LOOPS UNTIL NO MORE CHARACTERS AVAILABLE + +DPYDPY: TSTB CHNUSE(U) + BLE DPYD5 ;IGNORE FREE DISPLAYS. + PUSH U ;DPY CHANNEL NUMBER + ASL U + ASL U + PUSH U + MOV DPYCHN(U),U ;U GETS CHANNEL VAR BLOCK ADDR + JSR PC,GETCHR ;ANY OUTPUT FOR THIS CHANNEL? + BEQ DPYDON ;NO, GO CHECK FOR WHO LINES, ETC. + MOV #TYMSLC,TYMSHR ;MAX TIME BEFORE CHECKING OTHER CHANNELS + MOVB LECREG(U),T ;SET UP CONSOLE REGISTER + MOVB T,CREG + PUSH T + BLKOFF T ;TURN OFF ALL BLINKERS ON THIS SCREEN + JSR PC,CLBLIN ;AND CLEAR THEM + PUSH U ;SAVE PAGE PRINTER FOR DPYTVO+5 + MOVB #CIOR,CALU ;ALU FUNCTION FOR DRAWING CHARACTERS + MOV LECPC(U),TT ;RESUMING COROUTINE? + BEQ DPYDP1 ;NO. + MOV LESVB(U),B ;YES, RESTORE B AND PC FOR CORETURN FROM THE + CLR LECPC(U) ;GETCHC THAT DIDN'T FIND ANY CHARS. + BIC #-400,A ;CLEAR EXTRA BITS DUE TO SIGN-EXTENSION + PUSH #DPYXIT ;GETCHC'S CALLER'S RETURN ADDR MUST BE DPYXIT. + JMP (TT) ;GETCHC ENFORCES THAT. + +;FAST CHARACTER OUTPUT LOOP +DPYDP1: MOV (SP),U ;GET PP POINTER + MOVB A,A ;FLUSH HIGH BITS FROM CHAR + BLT DPYCTL ;BRANCH IF NON-PRINTING CONTROL FUNCTION +DPYTVO: MOV LEPHS(U),C ;SET UP TO DRAW CHARACTER + MOV LECC(U),TT ;THIS IS OPEN-CODED FOR SPEED + ASL A ;COPIED FROM CODE AT GENCHR + MOV CTAB(A),T + JSR PC,GENCH1 ;GENERATE CHARACTER, CLOBBER ALL ACS + MOV (SP),U ;RESTORE PP POINTER, CLOBBERED BY GENCH1 + JSR PC,LEDADC ;ADVANCE CURSOR +DPYXIT: TST TYMSHR ;TIME UP? + BMI DPYDX2 ;YES, LEAVE THIS TV FOR A WHILE + MOV (SP),U + JSR PC,GETCHR ;NO, GET NEXT CHARACTER + BNE DPYDP1 ;AND LOOP BACK TO PROCESS IT +DPYDX2: POP U + POP T ;DONE WITH THIS DPY FOR NOW + BLKON T ;ALLOW BLINKERS TO BLINK AGAIN + BR DPYDON + +;HERE IF NO CHARACTER AVAILABLE. TWO WORDS STILL ON THE STACK: +;(SP) IS 4 TIMES CHANNEL NUMBER, 2(SP) IS CHANNEL NUMBER (TO BE POPPED INTO U). + +DPYDON: POP B + TST CHNCLS(B) + BLT DPYFLS ;FLUSH DPY CHANNEL? + TST ECOFLG(B) + BEQ DPYD2 ;CAUSE PSEUDO ACTIVATION? + MOV U,T + ADD #LEZER0,T + + CHROFF + MOV KBDACT,LELIST(TT) ;PUT LINE EDITOR ON ACTIVE RING + MOV T,KBDACT + TST KBDFLG + BNE DPYD0 + MOV T,KBDFLG + CLR KBDACT + CLR KBDLAST +DPYD0: CHRON + +DPYD1: CLR ECOFLG(B) +DPYD2: TST WHOFLG ;DO WHO LINES? + BEQ DPYD3 + MOV WHOLIN(B),T + TST WHMODE(T) + BMI DPYD4 ;DON'T DO WHO LINE, BUT MIGHT WANT TO CLEAR IT + TST WHO1(T) + BMI DPYD4 ;USER WHO MODE VAR CAN ALSO DISABLE WHO LINE + JSR PC,DOWHO ;DO THE WHO LINE FOR THIS GUY +DPYD3: POP U +DPYD5: RTS PC + +;HERE IF NO WHO LINE IS TO BE DONE, WE MIGHT WANT TO CLEAR IT + +DPYD4: MOV WHOLIN(B),T + TST 2(T) ;IF NEGATIVE, THEN CLEAR IT + BGE DPYD3 + CLR 2(T) ;ZAP THE SWITCH + JSR PC,ZAPWHL ;CLEAR THE LINE + BR DPYD3 + +;HERE TO FLUSH DPY CHANNEL + +DPYFLS: MOV (SP),T + TSTB CHNUSE(T) ;ALREADY FREED? + BEQ DPYD3 ;YES, THIS MEANS MAIN LOOP SHOULD SIMPLY IGNORE THIS DPY. + CHROFF + JSR PC,CHRETN + CHRON + BR DPYD3 + +;HERE IF CONTROL CODE FOUND + +DPYCRF: SUB #5,A +DPYCTL: BIC #177600,A ;DISPATCH ON CONTROL CODE + CMP #ILLCTL,A + BLOS DPYTVO ;BRANCH IF ILLEGAL CODE + ASL A + PUSH #DPYXIT ;MAKE THE RETURN ADDR BE "DPYXIT" + JMP @CTLTAB(A) ;SO GETCHC COROUTINING WILL WORK. + +;CONTROL FUNCTION ROUTINES CALLED WITH PP INDEX IN U. +;MAY CLOBBER ALL ACS BUT MUST LEAVE CIOR IN CALU. MANY ARE ALSO +;CALLED FROM ELSEWHERE AND EXPECTED TO PRESERVE U. + +CTLTAB: SETCUR ;200 %TDMOV (FOLLOWED BY TWO IGNORED CHARS, THEN VPOS, HPOS). + SETCR1 ;201 %TDMV1 (FOLLOWED BY NEW VPOS AND NEW HPOS) + CLEOF ;202 %TDEOF (CLEAR TO END OF SCREEN) + CLEOL ;203 %TDEOL (CLEAR TO END OF LINE) + CLRCHR ;204 %TDDLF (DELETE FORWARD) + RTSPC ;205 %TDMTF (MOTOR OFF - IGNORED) + RTSPC ;206 %TDMTN (MOTOR ON - IGNORED) + CRLF ;207 %TDCRL (CRLF AND CLEAR EOL, BUT SCROLL AT END OF SCREEN) + RTSPC ;210 %TDNOP (NO-OP) + DPYBS ;211 %TDBS (BACKSPACE) + LF ;212 %TDLF (LF) + CR ;213 %TDRCR (RAW CR) + RTSPC ;214 %TDORS (OUTPUT RESET - WE CAN'T DO ANYTHING USEFUL) + RTSPC ;215 %TDQOT (DEVICE DEPENDENT DATA FOLLOWS - WELL, THIS DEVICE + ;SAYS IT DOESN'T REALLY DEPEND) + LEDADC ;216 %TDFS + SETCR1 ;217 %TDMV0 (SAME AS %TDMV1 FOR OUR PURPOSES) + DPYCLR ;220 %TDCLR (HOME UP AND CLEAR SCREEN) + BELL ;221 %TDBEL (FLASH THE SCREEN) + RTSPC ;222 %TDINI (REINITIALIZE INTELLIGENT TERMINAL (NOT APPLICABLE)) + LINS ;223 %TDILP (INSERT LINE POSITION (FOLLOW BY # LINES TO INSERT)) + LDEL ;224 %TDDLP (DELETE LINE POSITION (FOLLOW BY # LINES TO DELETE)) + CINS ;225 %TDICP (INSERT CHARACTER POSITION (FOLLOW BY # CHARS)) + CDEL ;226 %TDDCP (DELETE CHARACTER POSITION (FOLLOW BY # CHARS)) + RTSPC ;227 %TDBOW (IGNORED) + RTSPC ;230 %TDRST (IGNORED) + RTSPC ;231 %TDGPH (IGNORED) + RGSCUP ;232 %TDRSU (REGION SCROLL UPWARDS) + RGSCDN ;233 %TDRSD (REGION SCROLL DOWN) +ILLCTL==<.-CTLTAB>/2 + +.SBTTL WHO LINE ROUTINES + +;PRINTS WHO LINE, TAKES 10/11 CHANNEL IN B + +DOWHO: PUSH B ;SAVE 10/11 CHANNEL + MOV ITSTI1,WHOTIM ;TIME WE DID WHO LINE + MOV #WHOPP,TT ;SET DEFAULTS FOR WHO PAGE PRINTER + MOV #LEDFLT,T + MOV #LELEN,U + JSR PC,CALCPY ;ZAP + MOV #WHOPP,U ;SET UP PAGE PRINTER INDEX + CLR A ;CHARACTER X + MOV #CHRLN,B ;CHARACTER Y, PAST LAST LINE + JSR PC,SETXY0 + MOV (SP),B ;RESTORE 10/11 CHANNEL INDEX + MOV WHOLIN(B),A + TST WHO1(A) ;SIGN OF .WHO1 VARIABLE INHIBITS ALL HACKERY + BPL .+4 ;ASSUME USER HAS STUFF THERE AND SHOULDN'T CLOBBER IT. + RTS PC + JSR PC,ZAPWHL ;CLEAR OUT THE WHO LINE +WHINIT: MOV (SP),B ;10/11 CHANNEL INDEX + MOV WHOLIN(B),TT + CMP #NWHCMD-1,WHMODE(TT) + BHI DATIME ;NO VERSION NUMBER FOR USER WHO LINE + TYPOUT /ITS / + DECTYP ITSVER ;TYPE VERSION NUMBER + JSR PC,SPACE + TST ITSDBG + BEQ DATIME + TYPOUT /BEING DEBUGGED / + +;TYPES DAY TIME AND DATE + +DATIME: MOV ITSDAT,A ;PRINT PACKED DATE FIRST + JSR PC,DATTYP ; 7 BITS YEAR, 4 MONTH, 5 DAY + JSR PC,SPACE + MOV #MQ,B + MOV ITSTI1,(B) + MOV ITSTIM,-(B) + JSR PC,TIMTY1 ;TYPE DAY TIME NEXT + JSR PC,SPACE + POP B ;10/11 CHANNEL + MOV WHOLIN(B),TT + CMP #NWHCMD-1,WHMODE(TT) + BHI UWHLDO ;DO USER WHO LINE? + +;SYSTEM WHO LINE +;ITS XXX {BEING DEBUGGED} MM/DD/YY HH:MM:SS ITSFDP/ITSTDP USR RU/JOB SHARE SWBJ JWP TRC/COR CFU + +SWLDO: TYPOUT /TVS: / + DECTYP ITSFDP ;# FREE DPYS + JSR PC,SLASH + DECTYP ITSTDP ;TOTAL DPYS + TYPOUT / USERS: / + DECTYP ITSUSR ;# SYSTEM USERS + JSR PC,SPACE + DECTYP ITSRU ;RUNABLE JOBS/ + JSR PC,SLASH + DECTYP ITSJOB ;# SYSTEM JOBS + JSR PC,SPACE + DECTYP ITSFSH ;FAIR SHARE IN % + TYPOUT /% SB=/ + DECTYP ITSWBJ ;SWAP BLOCKED JOBS + TYPOUT / PG=/ + DECTYP ITSJWP ;JOBS WAITING FOR PAGES + TYPOUT / CORE: / + DECTYP ITSTRC ;RUNABLE CORE + JSR PC,SLASH + DECTYP ITSCOR ;TOTAL CORE + JSR PC,SPACE + DECTYP ITSCFU ;CORE FOR USERS + RTS PC + +;USER WHO LINE +;MM/DD/YY HH:MM:SS JOB UNAME JNAME SNAME STATUS J%RT HH:MM:SS.S JCORE {USER VARS} + +WHNOJB: TYPOUT / JOB SLOT VACANT/ ;HERE IF JOB SLOT VACANT + RTS PC + +UWHLDO: OCTYPE WHJOB(TT) ;JOB # + TST WHSTAT(TT) + BEQ WHNOJB ;VACANT JOB SLOT? + JSR PC,SPACE + MOV #WHUNAM,T + ADD TT,T + JSR PC,SIXPNT ;UNAME + JSR PC,SPACE + JSR PC,SIXPNT ;JNAME + JSR PC,SPACE + JSR PC,SIXPNT ;SNAME + JSR PC,SPACE + JSR PC,SIXPNT ;STATUS + JSR PC,SPACE + DECTYP WHJ%RT(TT) ;JOB % RUN TIME + JSR PC,SLASH + DECTYP ITSFSH ;OUT OF FAIR SHARE + JSR PC,PERCNT + JSR PC,SPACE + MOV WHJTRT(TT),A ;JOB RUNTIME IN .1-SEC TICKS + JSR PC,TIMTEN + JSR PC,SPACE + DECTYP WHRPAG(TT) ;# PAGES REAL CORE + JSR PC,SLASH + DECTYP WHTPAG(TT) ;# PAGES OF VIRTUAL CORE + MOV #'K,A + JSR PC,TVO + JSR PC,SPACE + MOV WHO1(TT),A ;PRINT FIRST USER WHO VAR + MOV #WHO2,T + JSR PC,UWVDO + MOV WHO1A(TT),A ;MAYBE PRINT SPACE + BMI UWHLD1 + JSR PC,SPACE + MOV WHO1A(TT),A +UWHLD1: MOV #WHO3,T ;NOW SECOND USER WHO VAR +;TAKE CONTROL WORD IN A, OFFSET (OFF TT) TO FOUR WORDS IN T, PRINT USER WHO VAR +;CONTROL WORD: +; 15 USED ELSEWHERE - IGNORE HERE +; 14 SUPPRESS SPACE BETWEEN TWO HALVES +; 13-11 MODE FOR FIRST HALF +; 10-08 MODE FOR SECOND HALF +; 07 DOUBLE 06-00 +; 06-00 CHARACTER TO PRINT AFTER FIRST HALF, BEFORE SPACE +UWVDO: PUSH A ;SAVE CONTROL WORD + ADD TT,T ;T POINT TO VAR + MOVB 1(SP),A + ASR A ;GET FIRST MODE + ASR A + ASR A + JSR PC,UWVDO4 ;PRINT FIRST HALF + MOVB (SP),A + BEQ UWVDO1 + BIT #200,A + BEQ UWVDO3 + JSR PC,TVOMSK ;SEPARATOR CHAR(S) +UWVDO3: JSR PC,TVOMSK +UWVDO1: BITB #100,1(SP) + BNE UWVDO2 + JSR PC,SPACE ;INTERVENING SPACE +UWVDO2: MOVB 1(SP),A ;GET SECOND MODE + TST (SP)+ ;POP CONTROL WORD, THEN DO SECOND HALF +UWVDO4: BIC #177770,A + ASL A + JMP @UWVDTB(A) + +UWVDTB: RTSPC ;0 DON'T PRINT + UWVDAT ;1 PACKED DATE AS MM/DD/YY + UWVTEN ;2 TIME IN .025 SECONDS AS HH:MM:SS.T + UWVHAK ;3 TIME IN .5 SECONDS AS HH:MM:SS + UWVHAK ;4 OCTAL (18. BITS) + UWVHAK ;5 DECIMAL (18. BITS) + SIXPN1 ;6 THREE SIXBIT CHARS + RTSPC ;7 RESERVED FOR EXPANSION + +;USER-CONTROLLED WHO-LINE FIELD PRINT-OUT ROUTINES. + +UWVHAK: MOV #MQ,B + TST (T)+ + MOV (T),(B) + MOV -(T),-(B) + CMP (T)+,(T)+ + MOV #-14.,LSH + JMP @UWVDT1-6(A) + +UWVDT1: TIMTY1 + UWVOCT + UWVDEC + +UWVOCT: MOV #10,B + BR UWVDC1 + +UWVDEC: MOV #10.,B +UWVDC1: PUSH RADIX + MOV B,RADIX + JSR PC,DECPN9 + POP RADIX + RTS PC + +UWVTEN: MOV (T)+,A + TST (T)+ + JMP TIMTEN + +UWVDAT: MOV (T)+,A + TST (T)+ + JMP DATTYP + +;SOME WHO LINE UTILITY ROUTINES + +PERCNT: MOV #'%,A +JMPTVO: JMP TVO + +SPACE: MOV #40,A + BR JMPTVO + +SLASH: MOV #'/,A + BR JMPTVO + +;TAKES POINTER TO SIXBIT IN T AND TYPES IT (ADVANCING T) + +SIXPNT: JSR PC,SIXPN1 ;DO TWO SETS OF THREE CHARS +SIXPN1: MOV #MUL,B ;DO ONE SET OF THREE CHARS + MOV #LSH,C + CMP (T)+,(T)+ ;BAG BITING EAE HAS TO LOADED IN JUST THE RIGHT ORDER + MOV -(T),-(B) ;LOW ORDER FIRST + MOV -(T),-(B) + CMP (T)+,(T)+ + MOV #-10.,(C) ;FIRST CHARCTER IN AC, THE REST IN MQ + JSR PC,SIXPN2 ;PRINT FIRST CHAR + JSR PC,SIXPN2 ;PRINT SECOND, FALL IN FOR THIRD +SIXPN2: MOV (B)+,A ;SIXBIT + ADD #40,A ;ASCII + PUSH (B)+ + JSR PC,TVO + POP -(B) + CLR -(B) ;CLEAR AC + MOV #6,(C) ;NEXT CHARACTER INTO AC + RTS PC + +;TAKES TENTHS OF SECONDS IN A AND PRINTS AS HH:MM:SS.T + +TIMTEN: MOV #MQ,T + MOV A,(T) + CLR -(T) + MOV #10.,-(T) ;DO DIVIDE + TST (T)+ + PUSH (T)+ ;TENTH'S OF SECONDS + MOV (T),A + ASL A ;# HALF SECONDS JOB HAS BEEN RUNNING + JSR PC,TIMTYP ;TYPE TIME + MOV #'.,A + JSR PC,TVO + POP A ;TENTH'S OF SECONDS + JMP DECPNT + +;TAKES # HALF SECONDS IN A AND TYPES TIME IN HH:MM:SS FORMAT + +TIMTYP: MOV #MQ,B + MOV A,(B) + CLR -(B) +;TAKE # HALF SECONDS IN EAE AC-MQ AND TYPE AS HH:MM:SS +TIMTY1: MOV #120.,-(B) ;MINUTES SINCE MIDNIGHT + TST (B)+ + PUSH (B) ;REMAINDER IS SS*2 + ASR (SP) + CLR (B) ;CLEAR AC + MOV #60.,-(B) ;HOURS SINCE MIDNIGHT + TST (B)+ + PUSH (B)+ ;REMAINDER IS MM + MOV (B),A ;HH + JSR PC,DECPNT + MOV #':,C ;COLON SEPARATES GOODIES + POP A + JSR PC,MSDPNT ;PRINTS COLON AND PADS WITH LEADING ZERO IF NECESSARY + POP A +MSDPNT: PUSH A + MOV C,A ;PRINT SEPARATING CHARACTER + JSR PC,TVO + CMP #10.,(SP) + BLE MSDPN1 ;PAD WITH LEADING ZERO? + MOV #'0,A + JSR PC,TVO +MSDPN1: POP A + JMP DECPNT ;PRINT NUMBER + +;TAKE DATE PACKED AS 7 BITS YEAR, 4 MONTH, 5 DAY AND PRINT AS MM/DD/YY + +DATTYP: MOV #MQ,B + MOV A,(B) + CLR -(B) ;CLEAR AC + MOV #LSH,C + MOV #7,(C) ;YEAR + PUSH (B) + CLR (B) + MOV #4,(C) ;MONTH + MOV (B),A + CLR (B) + MOV #5,(C) ;DAY + PUSH (B) + JSR PC,DECPNT ;PRINT MONTH + MOV #'/,C ;USE SLASH AS SEPARATOR + POP A + JSR PC,MSDPNT ;PRINT DAY + POP A + JMP MSDPNT ;PRINT YEAR + + +.SBTTL PDP-10 COMMAND PROCESSOR SWITCH VIDEO SWITCH, ETC. + +TENCMD: CMP #MAXCMD,A ;LEGAL COMMAND? + BLOS TENCFL ;NO, COMMAND FAILS + ASL A ;BYTES FOR DISPATCH + JMP @TENDSP(A) + +;PDP-10 COMMAND DISPATCH + +TENDSP: TENCFL ;0 ILLEGAL + TENVSW ;1 VIDEO SWITCH + TENDPC ;2 CONS DPY FOR PDP-10 + TENDPR ;3 RETURN DPY + TENRVS ;4 READ VIDEO SWITCH + TENASW ;5 AUDIO SWITCH + TENRAS ;6 READ AUDIO SWITCH +MAXCMD==<.-TENDSP>/2 + +;HERE TO SWITCH VIDEO SWITCH + +TENVSW: MOV CMDBUF,TT ;SWITCH INPUT + MOV CMDBUF+4,T ;SWITCH OUTPUT + CHROFF ;INHIBIT INTERRUPTS WHILE WE DO THIS + JSR PC,VSWCMD ;CHECKS FOR LEGAL BEFORE SWITCHING + BHIS TENCF1 ;JUMP IF THEY WERE ILLEGAL. +TENCS1: CHRON +TENCSD: MOV #-1,CMDFLG ;COMMAND SUCCEEDS + RTS PC + +;SWITCH AUDIO SWITCH UPON COMMAND FROM PDP-10 + +TENASW: MOV CMDBUF,TT ;SWITCH INPUT + MOV CMDBUF+4,T ;SWITCH OUTPUT + CHROFF + JSR PC,ASWCMD ;SWITCH SWITCH, TESTING LEGALITY. + BHIS TENCF1 ;JUMP IF THEY WERE ILLEGAL, TO SAY COMMAND FAILED. + BR TENCS1 + +;HERE TO CONS UP DPY FOR PDP-10 + +TENDPC: CHROFF ;INHIBIT INTERRUPTS AGAIN + MOV CMDBUF,C ;ARG IS KEYBOARD TO USE, OR -1 FOR NO KEYBOARD. + CMP C,#MAXKBD ;BUT BARF IF ILLEGAL KEYBOARD NUMBER. + BGE TENCF1 + JSR PC,CHCONS ;GET A CHANNEL, CONNECT IT TO THAT KEYBOARD. + TST T + BLT TENCF1 ;CAN'T => COMMAND FAILS. + MOVB LECREG(U),CMDBUF ;ELSE RETURN THE VIDEO BUFFER NUMBER + CLRB CMDBUF+1 + MOV T,CMDBUF+4 ;AND THE 10-11 CHANNEL NUMBER (TTY NUMBER MINUS 52). + BR TENCS1 + +TENCF1: CHRON +TENCFL: CLR CMDFLG ;REPORT FAILURE OF A COMMAND TO THE TEN. + RTS PC + +;HERE TO RETURN DPY ON COMMAND + +TENDPR: MOV CMDBUF,TT ;THE DPY TO RETURN + MOV #MAXTV-1,T +TENDR0: CMPB CHCREG(T),TT ;WHICH CHANNEL DOES IT BELONG TO? GET # IN T. + BEQ TENDR1 + DEC T + BGE TENDR0 + BR TENCSD + +TENDR1: TST CHNUSE(T) ;DO NOTHING IF THE CHANNEL IS FREE. + BEQ TENCSD + CHROFF ;OTHERWISE, FREE THAT CHANNEL. + JSR PC,CHRETN + BR TENCS1 + +;HERE RETURN STATE OF VIDEO SWITCH + +TENRVS: JSR PC,SWTARG ;SET UP 10-11 CHANNEL ARGUMENT + BLOS TENCFL ;ILLEGAL ARG MAKES COMMAND FAIL + JMP @RVSDSP(T) +RVSDSP: TENCFL ;0 IS ILLEGAL + RVSCHN ;1 10/11 CHANNEL # + RVSKBD ;2 KBD # + RVSOUT ;3 VIDEO SWITCH OUTPUT # +NSWTRG==<.-RVSDSP>/2 + +RVSKBD: JSR PC,CHKKBD ;HERE GIVEN KBD #; TEST IT. + BHI RVSCH1 ;IF LEGAL, FALL INTO MAIN LINE CODE + BR TENCFL ;ILLEGAL, TELL HIM SO + +RVSOUT: MOV CMDBUF+4,TT ;HERE GIVEN VIDEO SWITCH OUTPUT #. + MOV #-1,T ;ILLEGAL KBD # + CMP #MAXVSO,TT ;CHECK FOR LEGAL + BHI RVSCH2 ;FALL INTO MAIN LINE CODE + BR TENCFL ;HERE IF ILLEGAL + +RVSCHN: JSR PC,CHNKBD ;HERE GIVEN 10-11 CHANNEL #; GET KBD # IN T + BLOS TENCFL +RVSCH1: MOVB KBDVSW(T),TT ;GET VIDEO SWITCH OUTPUT INTO TT +RVSCH2: MOV TT,CMDBUF+<4*4> ;PUT VIDEO SWITCH OUTPUT INTO COMMAND BUFFER + MOV TT,CMDBUF+<3*4> + TST CMDBUF + BMI RVSDF ;BRANCH IF HE WANTS DEFAULT INPUT OF THIS OUTPUT. + MOVB VSWTAB(TT),TT ;GET CURRENT INPUT OF THIS OUTPUT AND STORE. + BR RVSCH3 + +RVSDF: ASL T ;MAKE IT BYTE INDEX + BMI RVSNL ;NEGATIVE IF NOT LOGGED IN + MOV KBDLE(T),U + BEQ RVSNL ;KBD NOT LOGGED IN, ITS THE DEFAULT +RVSDF1: MOVB LECREG(U),TT ;THE REGISTER HE HACKS + CMP #MAXTV,TT + BLOS TENCFL ;BRANCH IF ILLEGAL CONSOLE # + ASL TT ;MAKE IT A BYTE INDEX + MOV DPYVSW(TT),TT ;VIDEO SWITCH INPUT +RVSCH3: MOV TT,CMDBUF+<2*4> ;STORE SWITCH INPUT INTO COMMAND BUFFER + BR TENCSD + +RVSNL: MOV DPYCHN,U ;CHANNEL 0 IS CONSOLE FREE CHANNEL + BR RVSDF1 ;AND BACK INTO MAIN STREAM + +;GIVEN 10/11 CHANNEL # AND RETURNS KBD IN T + +CHNKBD: MOV CMDBUF+4,T ;PICK UP CHANNEL # + CMP #MAXTV,T + BLOS CHNKB2 + ASL T ;MAKE CHANNEL # INTO INDEX INTO CHANNEL TABLES + ASL T + TST CHNCLS(T) ;MAKE SURE CHANNEL IS OPEN + BLT CHNKB3 + MOVB DPYKBD(T),T ;PICK UP KBD # +CHNKB1: CMP #MAXKBD,T ;FIX CONDITION CODES FOR SUCCESSFUL RETURN +CHNKB2: RTS PC + +CHNKB3: MOV #MAXKBD+1,T ;HERE IF CHANNEL CLOSED + BR CHNKB1 ;CONS UP ILLEGAL KBD # + +CHKKBD: MOV CMDBUF+4,T ;CHECK FOR REASONABLE KBD # + BR CHNKB1 + +;HERE TO SET UP SWITCH ARG FOR 10-11 COMMAND RETURN IN CONDITION CODES +;IS THE RESULT OF CMP #NCHARG, TO CHECK FOR LEGALITY + +SWTARG: MOV CMDBUF,T ;ARGUMENT TYPE + BPL .+4 ;MAKE SURE WE HAVE A POSITIVE # + NEG T + ASL T ;MAKE IT INTO A BYTE INDEX + CMP #NSWTRG*2,T ;TEST FOR LEGAL + RTS PC + +;HERE RETURN STATE OF AUDEO SWITCH + +TENRAS: JSR PC,SWTARG ;SET UP 10-11 CHANNEL ARGUMENT + BLOS RASLOS ;ILLEGAL ARG MAKES COMMAND FAIL + JMP @RASDSP(T) +RASDSP: TENCFL ;0 IS ILLEGAL + RASCHN ;1 10/11 CHANNEL # + RASKBD ;2 KBD # + RASOUT ;3 AUDEO SWITCH OUTPUT # +.IIF NZ .--RASDSP,.ERROR RASDSP AND RVSDSP DIFFER. + +RASCHN: JSR PC,CHNKBD ;GIVEN A 10-11 CHANNEL #; GET KBD # IN T + BLOS RASLOS +RASCH1: MOVB KBDASW(T),TT ;GET AUDEO SWITCH OUTPUT INTO TT +RASCH2: MOV TT,CMDBUF+<3*4> ;PUT OUTPUT NUMBER IN AS RETURN VALUE. + CLR CMDBUF+<2*4> ;IF HE WANTS DEFAULT INPUT OF THIS OUTPUT, IT'S 0. + TST CMDBUF + BMI RASCH3 ;BRANCH IF HE WANTS DEFAULT INPUT OF THIS OUTPUT. + MOVB ASWTAB(TT),CMDBUF+<2*4> ;GET CURRENT INPUT OF THIS OUTPUT AND STORE. +RASCH3: JMP TENCSD + +RASKBD: JSR PC,CHKKBD ;HERE IF GIVEN KBD #; TEST FOR LEGALITY. + BHI RASCH1 ;IF LEGAL, FALL INTO MAIN LINE CODE +RASLOS: JMP TENCFL ;ILLEGAL, TELL HIM SO + +RASOUT: MOV CMDBUF+4,TT ;HERE IS GIVEN AUDEO SWITCH OUTPUT + CMP #MAXASO,TT ;CHECK FOR LEGAL + BHI RASCH2 ;FALL INTO MAIN LINE CODE + BR RASLOS ;HERE IF ILLEGAL + +.SBTTL ERROR TRAPS HERE + +NXMBRK: BPT +RESBRK: BPT +IOTBRK: BPT +PWRBRK: BPT +EMTBRK: BPT +TRPBRK: BPT + +;BPT BREAKS COME HERE IF THERE IS NO RUG. +;DON'T WANT TO HALT THE 11 SINCE 11TEN INTERFACE WOULDN'T BE ABLE TO GET TO BUS. +;WANT TO PUT CONTENTS OF REGISTERS IN CORE WHERE CARPET CAN GET AT THEM. + +BPTBRK: .REPT 7 ;SAVE THE ACS + MOV %0+.RPCNT,BPTACS+<2*.RPCNT> + .ENDR + MOV #INITED-2,A ;TELL THE 10 WE'RE DOWN + CLR (A)+ + CLR (A)+ + CLR (A)+ + CLR (A)+ + +; BELOW LOSES - PREVENTS RESTUFFING UNLESS YOU GO HIT SWITCHES +; WAIT ;PUT 000001 IN LIGHTS (11/05) + BR . ;WAIT FOR RELOAD OR MANUAL INTERVENTION + ;BRANCH TO POINT SO STUFF WILL AUTOMATICALLY START IT. + .REPT 7 ;PROCEED + MOV BPTACS+<2*.RPCNT>,%0+.RPCNT + .ENDR + RTI + +BPTACS: .BLKW 7 + +.SBTTL CLOCK ROUTINES CAUSE BLINKING + +CLKBRK: DEC TYMSHR ;COUNT DOWN THIS DPY'S QUANTUM +;******* TEMPORARY CODE TO CHECKSUM THE FONT ******* +;CHECKSUM IT 100 OCTAL WORDS AT A TIME, SO AS NOT TO SLOW THINGS DOWN +;TOO MUCH. WILL GET CHECKED APPROXIMATELY FOUR TIMES A SECOND. + PUSH T + PUSH TT + MOV CKSPNT,T + MOV T,TT + ADD #100*2,TT + CMP TT,#FNTEND + BLOS 1$ + MOV #FNTEND,TT +1$: ADD (T)+,CKSSUM + CMP T,TT + BLO 1$ + MOV T,CKSPNT + CMP TT,#FNTEND + BNE 2$ + CMP CKSSUM,CKSSMG + BEQ .+4 + BPT + CLR CKSSUM + MOV #FNTORG,CKSPNT +2$: POP TT + POP T +;******* END OF TEMPORARY CODE ******* + PUSH T + ADD #1,TICKS1 ;INC DOES NOT AFFECT C-BIT (SIGH) + ADC TICKS + TST KBDFLG + BNE CLKBR1 ;HAS PDP-10 HACKED THE LAST BUNCH? + MOV KBDACT,KBDFLG ;YES, GIVE HIM THE NEW BUNCH + CLR KBDFLG+2 ;PARANOIA REIGNS SUPREME + CLR KBDACT + CLR KBDLAST ;POINTS TO END OF ACTIVE CHAIN + +;CLOCK QUEUE DISPATCH + +CLKBR1: MOV CLOCKQ,T + BEQ CLKBR2 ;ANYTHING ON CLOCK QUEUE? + TST (T)+ ;IGNORE CDR + CMP (T)+,TICKS ;DOUBLE-PRECISION COMPARE TIME NOW + BHI CLKBR2 ;WITH TIME IN QUEUE BLOCK; TO CLKBR2 IF NOT DUE YET. + BLO CLKBR3 + CMP (T)+,TICKS1 + BHI CLKBR2 +CLKBR3: PUSH CLOCKQ ;CDR THE CLOCK QUEUE + MOV @(SP),CLOCKQ + JSR PC,@(T)+ ;CALL CLOCK LEVEL ROUTINE, T POINTS TO ARGUMENT + POP T + MOV CLOCKF,(T) ;PUT OLD SLOT ON FREE LIST + MOV T,CLOCKF + BR CLKBR1 ;CHECK AGAIN IF SOMETHING STILL ON QUEUE + +CLKBR2: DEC BLINK + BGE .+10 + MOV #BLKTIM,BLINK + CMP BLINK,#MAXTV + BHIS CLKR1 + MOV BLINK,T + TSTB BLKSWT(T) + BNE CLKR1 + PUSH U + PUSH CREG + PUSH AC + PUSH MQ + MOVB T,CREG + ASL T + MOV BLINKS(T),T ;BLINK CHAIN FOR THIS DPY + BEQ CLKBR4 +CLKLOP: MOV BLCURS(T),U ;CURSOR TO BLINK + JSR PC,XORCHR + COMB BLON(T) ;CHANGE STATE OF BLINK + MOV BLNEXT(T),T + BNE CLKLOP +CLKBR4: POP MQ ;CLOCK RETURN + POP AC + POP CREG + POP U +CLKR1: TST BLINK + BEQ CLKR3 + CMP BLINK,#BLKTIM/2 + BNE CLKR2 +CLKR3: JSR PC,RPT ;AS OFTEN AS WE BLINK, HANDLE THE REPEAT KEY. +CLKR2: INCB SSCC ;INCREMENT SEMI-SLOW CLOCK COUNT + BNE CLKRET ;WRAP-AROUND => SEMI-SLOW CLOCK TICK + BR CLKBRS + +;ON ALL CONSOLES IN "REPEAT" MODE, PERFORM ONE REPETITION +;BY SENDING AS INPUT TO THE PDP-10 ANOTHER COPY OF THE CHAR +;MOST RECENTLY SENT. ALSO DECREMENTS ALL FINITE REPEAT COUNTS. +RPT: JSR U,ACSAV + PUSH CREG + MOV #LEUVAR,U +RPT4: TST LERPT(U) + BEQ RPT3 + BMI RPT1 + DEC LERPT(U) +RPT1: MOV LELSTA(U),A + MOV LELSTB(U),B + JSR PC,PUTCHR +RPT3: ADD #LELEN,U + CMP #LEUEND,U + BGT RPT4 + POP CREG + JMP ACRES + +;COME HERE EVERY 256./60. = 4.27 SECONDS FOR SEMI-SLOW CLOCK +CLKBRS: PUSH TT + PUSH C + PUSH U + PUSH #69. ;FOR DEBUGGING + TST KBDTSW + BEQ SSCRET + CLR KBDTSW + MOV #KBDDEF+<2*MAXKBD>,T + BR CLKBR5 + +CLKBR9: INC KBDTSW +CLKBR5: CMP #KBDDEF-2,T + BEQ SSCRET + TST -(T) ;FAST LOOP LOOKING FOR ANY KEYBOARD + BGE CLKB10 ; NEEDING ITS CONSOLE'S VIDSW INPUT RESET + BR CLKBR5 +CLKB10: DECB 1(T) + BGE CLKBR9 ;NOT TIME TO RESET THIS SCREEN YET + MOV T,C + SUB #KBDDEF,C ;C HAS 2*KBD NUMBER, FOR VSWDEF. + PUSH T + JSR PC,VSWSGO ;SET UP L.E. INDEX IN U, VSW OUTPUT IN T + BLT CLKBR7 ;VSWSGO IS NEGATIVE IF SOMETHING IS FUNNY. + JSR PC,VSWDEF ;RESET VIDEO SWITCH INPUT +CLKBR7: POP T + BR CLKBR5 + +SSCRET: CMP (SP)+,#69. ;IS STACK SCREWED? + BEQ SSCRE1 + BPT +SSCRE1: POP U + POP C ;SEMI-SLOW CLOCK RETURN + POP TT +CLKRET: POP T +CRTI: RTI + +;CLEARS ALL BLINKERS ON THIS DPY + +CLBLIN: PUSH U + MOVB CREG,T + BIC #177400,T + ASL T + MOV BLINKS(T),T + BEQ CLBL2 +CLBL0: TSTB BLON(T) ;BLINK ON? + BEQ CLBL1 + MOV BLCURS(T),U + JSR PC,XORCHR + CLRB BLON(T) +CLBL1: MOV BLNEXT(T),T + BNE CLBL0 +CLBL2: POP U + RTS PC + +;CLOCK QUEUE ROUTINES + +;ADQUE CALLED WITH ARG IN T, THE CALLING SEQUENCE IS: + +; JSR TT,ADQUE +; DELTA T +; ROUTINE TO CALL AT CLOCK LEVEL + +ADQUE: PUSH T ;ARG FOR ROUTINE + MOV CLOCKF,T ;GET FREE CLOCK QUEUE SLOT + BEQ ADQFL ;IF THERE IS A FREE ONE + TST (T)+ ;IGNORE CDR + MOV TICKS,(T)+ ;MOVE IN CURRENT TIME + MOV TICKS1,(T) + ADD (TT)+,(T)+ ;TIME TO CALL ROUTINE + ADC -4(T) + MOV (TT)+,(T)+ ;ROUTINE TO CALL + MOV (SP)+,(T) ;AND ITS ARG + PUSH TT ;RETURN ADDRESS + MOV CLOCKF,TT ;ADDRESS OF THIS CLOCK QUEUE SLOT + MOV (TT),CLOCKF ;CDR THE FREE LIST + PUSH TT ;ADDRESS OF ONE TO ADD + PUSH #CLOCKQ ;ADDRESS OF PREVIOUS CLOCK QUEUE ENTRY +ADQUE1: MOV @(SP),TT ;CURRENT ENTRY IN QUEUE + BEQ ADQUE2 ;END OF QUEUE? + MOV 2(SP),T ;THE ONE WE WANT TO ADD + CMP (T)+,(TT)+ ;IGNORE CDR'S + CMP (T)+,(TT)+ ;HIGH ORDER OF TIME + BLO ADQUE2 ;GO SPLICE IT IN HERE + BHI ADQUE3 + CMP (T)+,(TT)+ ;LOW ORDER + BLOS ADQUE2 +ADQUE3: MOV @(SP),(SP) ;CDR THE QUEUE + BR ADQUE1 + +;HERE TO SPLICE ENTRY INTO CLOCK QUEUE + +ADQUE2: MOV @(SP),@2(SP) ;CDR OF QUEUE, GOES TO CDR OF NEW ENTRY + MOV 2(SP),@(SP) ;CURRENT SLOT GOES TO CDR OF PREVIOUS + CMP (SP)+,(SP)+ ;CLEANSE STACK + POP TT + RTS TT + +;HERE FOR NO FREE CLOCK QUEUE SLOTS + +ADQFL: CMP (TT)+,(TT)+ ;SKIP OVER ARGS + POP T ;CLEANSE STACK + RTS TT + +;THIS CAUSES CONSOLE FREE DPY TO GLITCH + +MSGLIT: PUSH CREG + MOV (T),T + MOV T,CREG + JSR TT,ADQUE + GLITIM + MSGLIT + MOV CSA,T + PUSH T + BIC #-BOWBIT,T ;CLEAR BOW AND OTHER GARBAGE + ADD #LINHT*BYTPL/10,T ;GLITCH ONE CHARACTER LINE + CMP #LINHT*BYTPL*CHRLN/10,T + BHI .+4 ;WRAP AROUND? + CLR T + BIC #-1#<-BOWBIT>,(SP) + BIS T,(SP) + POP CSA ;ZAP + POP CREG + RTS PC + +;HERE TO RING BELL ON DPY + +BELL: PUSH T + MOV CREG,T + MOVB T,TT ;DOUBLE TV BUFFER # FOR BYTE INDEX + ASL TT + + CHROFF ;INHIBIT INTERRUPTS WHILE WE HACK CLOCK QUEUE, ETC. + INC BELCNT(TT) ;FLASH SCREEN AT LEAST ONCE + BEQ BELL0 ;IF NONE PENDING, FLASH IT NOW + INC BELCNT(TT) ;IF BELLS PENDING THEN FLASH TWICE + CMP BELCNT(TT),#MAXBEL + BLOS BELL0A + DEC BELCNT(TT) + DEC BELCNT(TT) + BR BELL0A + +;HERE IF NO BELLS PENDING, FLASH SCREEN RIGHT AWAY, ADD CLOCK QUEUE ENTRY + +BELL0: JSR PC,BOWXOR ;FLASH THE SCREEN NOW! + JSR PC,BELL1A ;ADD CLOCK QUEUE ENTRY +BELL0A: CHRON + + POP T + RTS PC + +;CLOCK LEVEL BELL ROUTINE + +BELL1: PUSH CREG + MOV (T),T ;THE DESIRED CONSOLE REGISTER + MOV T,CREG ;N.B. THE ALU MODE WAS SAVED AS "XOR" + MOV #BOWBIT,CSA ;FLASH THE SCREEN + BIC #177400,T ;THE DPY # + ASL T ;BYTE INDEX + DEC BELCNT(T) ;WE JUST DID THAT ONE + BMI BELL1B ;ANY MORE PENDING? + JSR PC,BELL1A ;YES, PUT ANOTHER ON QUEUE +BELL1B: POP CREG + RTS PC + +BELL1A: MOV CREG,T ;PUT ANOTHER BELL ON CLOCK QUEUE + JSR TT,ADQUE + BLKTIM + BELL1 + RTS PC + +.SBTTL KEYBOARD INTERRUPT ROUTINES + +;KEYBOARD BREAK ROUTINES THE LINE EDITOR RUNS AT THIS LEVEL + +KBDBRK: JSR U,ACSAV ;PUT AC'S ON STACK + PUSH CREG + PUSH AC + PUSH MQ +KBDLOP: MOV OLDKMA,A + CMP #KBDEND,A ;CHECK WRAP AROUND + BHI .+6 + MOV #KBDBUF,A + CMP KMA,A + BEQ KBDRET ;NO MORE CHARACTERS + MOV (A)+,B ;RAW CHARACTER + TSTB (A)+ ;GARBAGE + MOVB (A)+,-(SP) ;KEYBOARD # + MOV A,OLDKMA + +;GET ASCII REPRESENTATION OF CHARACTER +; ASCII CODE IN A, META BITS IN B + + MOV B,C ;TWO COPIES OF RAW CHARACTER + BIC #RCHAR,B ;KEY STRUCK + BIT #RTPBIT,C ;TOP? + BEQ KBDX1 + BIS #XTPBIT,B + BR KBDX2 +KBDX1: BIT #RSLBIT,C ;SHIFT LOCK? + BEQ .+6 + BIS #XSLBIT,B + BIT #RSHBIT,C ;SHIFT? + BEQ KBDX2 + BIS #XSHBIT,B +KBDX2: MOVB XTAB(B),A ;ASCII REPRESENTATION + BIC #<#-1>,B ;FLUSH ALL UNINTERESTING BITS + ASL B ;XTAB TO ASCII REPRESENTATION + ASL B + ASL B + BIT #RMTBIT,C ;META? + BEQ .+6 + BIS #AMTBIT,B + BIT #RCLBIT,C ;CONTROL? + BEQ .+6 + BIS #ACLBIT,B + MOVB (SP)+,C ;KEYBOARD # + ASL C ;BYTE FOR INDEX INTO KBDLE + TST A + BLT NONASC ;NON-ASCII +KBDUN3: TSTB KBDESC(C) + BNE ESCBRK ;ESCAPE OR BREAK IS IN PROGRESS + TSTB KBDCNT(C) ;IF THIS SCREEN IS SPYING WITH A TIMEOUT, + BLT KBDUN1 + JSR PC,VSWUNS ;UN-SPY IT IMMEDIATELY. +KBDUN1: MOV KBDLE(C),U ;ASSOCIATED LINE EDITOR? + BEQ KBDLOP + TST LERPT(U) ;IF THE REPEAT KEY IS IN EFFECT, + BEQ KBDUN2 ;TURN IT OFF, AND FLUSH THIS CHARACTER. + CLR LERPT(U) + BR KBDLOP + +KBDUN2: MOVB LECREG(U),CREG ;SET UP CONSOLE REGISTER + BIS #ACTBIT,B ;FEED THIS CHAR TO THE PDP-10 + JSR PC,PUTCHR + BR KBDLOP + +;KEYBOARD RETURN + +KBDRET: POP MQ + POP AC + POP CREG + POP A + POP B + POP C + POP T + POP TT + POP U + RTI + +;NON-ASCII CHARACTERS COME HERE + +NONASC: NEG A + CMP #MAXNAS,A + BHIS .+4 +NONAS1: BPT ;ILLEGAL CHARACTER + CMP #,C ;C HAS BEEN DOUBLED + BHI .+4 + BPT ;GARBAGE KBD # + CLRB KBDESC(C) + ASL A ;BYTES + JSR PC,@NASCTB(A) ;DISPATCH TO ROUTINE +JBDLOP: JMP KBDLOP + +;PROCESS ESCAPE AND BREAK COMMANDS + +ESCBRK: JSR PC,UPPER ;CONVERT LOWER CASE TO UPPER CASE + MOV #ESCHAR,T +ESCBR1: CMPB (T),A ;MATCH? + BEQ DOESC + TSTB (T)+ ;END OF TABLE? + BNE ESCBR1 +ESCBR2: CLRB KBDESC(C) ;NO COMMAND + BR JBDLOP + +DOESC: MOV KBDLE(C),U ;IF COMMAND NEEDS LOGGED-IN KBD, + BEQ DOESC2 ; MAKE SURE WE'RE LOGGED IN, + MOVB LECREG(U),CREG ; AND SET UP U AND CREG +DOESC1: SUB #ESCHAR,T + CLRB KBDESC(C) + ASL T ;MAKE A WORD INDEX. + JSR PC,@ESCTAB(T) ;C MUST BE KBD #, SOME ESCAPE ROUTINES RELY ON IT + BR JBDLOP + +DOESC2: CMP #ESCSRN,T ;IF NOT LOGGED IN BUT MUST BE, + BLE ESCBR2 ; THEN WE LOSE TOTALLY + MOVB DPYFRE,CREG ;OTHERWISE SET UP CREG FOR THE + BR DOESC1 ; SAKE OF RANDOM BELLS + +;NASCTB FOR KEYS SUCH AS BREAK, CLEAR, ETC POINTS HERE +;TO TURN THOSE CHARACTERS INTO TOP-LETTERS STARTING WITH "A". +;A HOLDS TWICE THE NASCTB INDEX. +BRKCLR: ASR A + ADD #4000+'@,A +BRKCLX: TST (SP)+ ;FLUSH RETURN POINTER TO JBDLOP + JMP KBDUN3 ;AND GO GIVE CHARACTER TO TEN. + +GAMMA: MOV #4011,A + BR BRKCLX + +DELTA: MOV #4012,A + BR BRKCLX + +CRCPLS: MOV #4015,A + BR BRKCLX + +PLSMNS: MOV #4014,A + BR BRKCLX + +.SBTTL 10/11 INPUT/OUTPUT ROUTINES + +;HERE TO COMPLEMENT STATE OF BOW BIT WHEN PDP-10 FALLS BEHIND ON KBD + +SLOW10: MOVB LECREG(U),CREG + JMP BELL ;RING BELL + + +;PUT CHARACTER WHICH IS A OR'D WITH B INTO BUFFER. ACTIVATES IF +; 1 FINDS ACTIVATION CHARACTER +; 2 BUFFER FILLS +;A AND B ARE SAVED IN LELSTA AND LELSTB IN CASE THE USER DECIDES +;TO REPEAT THE CHARACTER. + +PUTCHR: TST @LEBUF(U) + BGT PUTCH0 ;BUFFER BEING FILLED? + BLT SLOW10 ;HAS PDP-10 FALLEN BEHIND? + MOV #LBCHRS,@LEBUF(U) ;MARK BUFFER BUSY WITH # FREE CHARACTERS +PUTCH0: TST LEFREE(U) ;ANY ROOM LEFT IN BUFFER? + BGT PUTCH2 + BEQ SLOW10 ;NOPE, DO SOME ERROR CHECKING + BPT ;LOSE IF LESS THAN NO ROOM + +PUTCH2: MOV A,@LECHR(U) + BIS B,@LECHR(U) + MOV A,LELSTA(U) + MOV B,LELSTB(U) + ADD #2,LECHR(U) + DEC LEFREE(U) ;BUFFER FULL? + BGT PUTCH4 + BEQ .+4 ;WE MUST ACTIVATE ANYWAY + BPT + MOV LEBUF(U),T + TST LHQUED(T) ;IF ALREADY QUEUED TO ACTIVATE, + BEQ ACTIVA ; DON'T ACTIVATE NOW + RTS PC + +PUTCH4: TST B + BGE RTSPC1 ;NOT ACTIVATING + MOV LEBUF(U),T ;ACTIVATION CHAR, MUST ACTIVATE + TST LHQUED(T) ;IF ALREADY QUEUED TO ACTIVATE, + BNE RTSPC1 ; DON'T ACTIVATE NOW + TST @LHNEXT(T) ;TEST NEXT BUFFER IN RING + BMI QBFR ;IF NOT FREE, TRY ACTIVATION ON NEXT CLOCK TICK + +;HERE TO ACTIVATE BUFFER + +ACTIVA: SUB #LBCHRS,LEFREE(U) ;NEGATIVE OF ACTIVE CHARS + BLT .+4 + BPT ;HAD BETTER BE NEGATIVE + MOV LEBUF(U),T ;THE BUFFER TO ACTIVATE + MOV LEFREE(U),LHFLAG(T) ;THAT ACTIVATES IT + + CHROFF + CLR LHALST(T) ;PUT THIS ONE AT END CHAIN + PUSH KBDLAST + MOV T,KBDLAST + POP T + BNE ACTIV0 ;EMPTY ACTIVATION LIST? + MOV KBDLAST,KBDACT ;YES, MAKE ACTIVE LIST POINT TO THIS ONE + BR ACTV0A +ACTIV0: MOV KBDLAST,LHALST(T) ;OLD LAST POINTS TO NEW LAST +ACTV0A: MOV KBDLAST,T ;IN ANY EVENT THIS THE ONE JUST ADDED + TST KBDFLG ;DOES THE PDP-10 WANT MORE + BNE ACTIV1 + MOV KBDACT,KBDFLG ;ACTIVATE THIS LIST + CLR KBDACT ;AND PREPARE FOR NEXT + CLR KBDLAST +ACTIV1: CHRON + + MOV LHNEXT(T),T ;NEXT ON RING + MOV #LHLEN,TT + ADD T,TT ;FIRST FREE CHARACTER + MOV T,LEBUF(U) ;NEW BUFFER + TST (T)+ ;LHFLAG IS SET AT PUTCHR + CLR (T)+ ;LHZERO +; CMP (T)+,(T)+ ;DON'T HACK LHNEXT AND LHALST + MOV TT,LECHR(U) ;FIRST FREE CHARACTER + MOV #LBCHRS,LEFREE(U) ;FREE CHARACTERS IN BUFFER +RTSPC1: RTS PC + +;HERE AT CLOCK LEVEL TO ACTIVATE BUFFER + +CLKACT: PUSH TT + PUSH U + MOV (T),U ;THE LINE EDITOR + MOV LEBUF(U),T ;THE BUFFER + TST LHFLAG(T) + BGE .+4 + BPT ;CAN'T ACTIVATE AN ALREADY ACTIVATED BUFFFER + TST @LHNEXT(T) ;THE NEXT BUFFER + BMI CLKAC1 ;ACTIVATE IF READY + CLR LHQUED(T) + JSR PC,ACTIVA +CLKAC2: POP U + POP TT + RTS PC + +CLKAC1: JSR PC,QBFR ;NOT, READY TRY ANOTHER CLOCK TICK + BR CLKAC2 + +;HERE IF NEXT BUFFER ON RING IS NOT FREE, TRY ACTIVATION AT NEXT CLOCK TICK + +QBFR: ZAPFLG LHQUED(T) ;SET FLAG THAT SAYS WE'RE QUEUED + MOV U,T ;ARG + CHROFF ;INHIBIT INTERRUPTS WHILE WE DO THIS + JSR TT,ADQUE ;PUT ON CLOCK QUEUE + 1 ;AT NEXT TICK + CLKACT ;CLOCK LEVEL ACTIVATION + CHRON + RTS PC + +;SAVE ALL ACS ON STACK + +ACSAV: PUSH TT + PUSH T + PUSH C + PUSH B + PUSH A + PUSH U ;RETURN ADDRESS + MOV 14(SP),U ;RESTORE U + RTS PC + +;GETS NEXT CHARACTER FROM DPY BUFFER +;DPY CHANNEL POINTER IN U. RETURNS SIGN-EXTENDED CHARACTER IN A, CLOBBERS TT. +;RETURNS 'EQ' IN CONDITION CODES IF NO CHARACTER PRESENT. + +GETCHR: MOV DPY11B(U),TT ;GET POINTER FOR EASE IN INCREMENTING + MOVB (TT),A ;GET NEXT CHARACTER + CMP A,#-1 ;HAS TEN PUT GOODIES THERE? + BEQ RTSPC1 ;NO + MOVB #-1,(TT) ;MARK AS TAKEN + DEC DPY11B(U) ;ADVANCE POINTER + ROR TT ;USING PDP10 BYTE ORDER (1, 0, 3, 2) + BCS GETCH1 ;BRANCH IF 1->0 OR 3->2 + ADD #4,DPY11B(U) ;0->3 OR 2->1 NEXT WORD + ROR TT + BCC GETCH1 ;BRANCH IF 0->3 + MOV DPY11B(U),TT ;OTHERWISE NEXT PDP10 WORD + DEC TT + MOV #-1,-2(TT) ;SO SET PREV ONE TO ALL -1. + MOV #-1,-4(TT) ; IN CASE OF TIMING ERROR + CMP TT,DPYLGL(U) ;PAST END OF BUFFER? + BLOS GETCH1 + MOV U,DPY11B(U) ;YES, RESET TO + ADD #DPDATA+1,DPY11B(U) ;FIRST WORD OF DATA AREA, HIGH BYTE +GETCH1: CLZ + RTS PC ;RETURN CONDITION CODE 'NE' + +;GET NEXT CHARACTER BUT IF NOT AVAILABLE DO A COROUTINE-RETURN +;FROM THE CHARACTER-READING LOOP, SO THAT WHEN THE NEXT CHARACTER +;IS READ THIS CALL WILL BE RETURNED FROM. ASSUMES THAT U CONTAINS THE +;ADDRESS OF THE CHANNEL VAR BLOCK, AND MAY RESET ALL ACS +;BUT B TO WHAT THEY HOLD AT DPYCTL. B IS ALWAYS PRESERVED. +GETCHC: JSR PC,GETCHR + BEQ GETCH2 + BIC #-400,A ;CLEAR EXTRA BITS DUE TO SIGN-EXTENSION + RTS PC + +GETCH2: MOV B,LESVB(U) + POP LECPC(U) + POP B + CMP B,#DPYXIT + BEQ GETCH3 + BPT ;CALLER OF GETCHC HAD WRONG RETURN ADDRESS +GETCH3: JMP DPYDX2 ;CEASE TYPING ON THIS TV FOR A WHILE + +.SBTTL DISPLAY FUNCTION (%TD, ETC) ROUTINES + +TVOMSK: BIC #177600,A ;HERE IF YOU DON'T TRUST THE HIGH BITS + +;TYPE CHARACTER IN A AND ADVANCE OVER IT. PRESERVES A. + +TVO: JSR PC,GENCHR ;GENERATES CHARACTER AND ADVANCES CURSOR + +;LEDADC ADVANCES LINE EDITOR CURSOR + +LEDADC: ADD #CHRWD,LEX(U) ;INCREMENT HPOS IN BITS FROM RIGHT MARGIN. + BEQ LEDAD2 ;REACHED MARGIN => WRAP AROUND. + TST LEPHS(U) ;ELSE, INCREMENT THE AUXILIARY VARIABLES. + BGT LEDAD1 + ADD #20,LEPHS(U) ;HERE IF WE ARE ADVANCING TO A NEW WORD. + ADD #2,LECC(U) + CMP LECC(U),#TVCFENCE + BLOS LEDAD1 + MOV #TVLO,LECC(U) +LEDAD1: SUB #CHRWD,LEPHS(U) + RTS PC + +LEDAD2: JMP CR + +;RETREATS LINE EDITOR CURSOR + +LEDREC: CMP LEX(U),#-BYTPL ;IF AT LEFT MARGIN, DON'T DO ANYTHING. WE COULD WRAP AROUND, + BEQ LEDRE1 ;BUT THAT'S MORE WORK, AND SHOULDN'T EVER HAPPEN ANYWAY. + ADD #CHRWD,LEPHS(U) + SUB #CHRWD,LEX(U) + CMP #<20-CHRWD>,LEPHS(U) + BGE LEDRE1 + SUB #20,LEPHS(U) ;BACKUP A WORD IN DISPLAY + SUB #2,LECC(U) + CMP LECC(U),#TVLO + BHIS LEDRE1 + BPT ;BACKING UP PAST BEGINNING OF SCREEN? +LEDRE1: RTS PC + +;HERE TO CRLF AND CLEAR EOL. +CRLF: JSR PC,CR + CMP #TVFENCE-,LELCC(U) ;IF NOW ON LAST LINE OF SCREEN, + BEQ CRLF1 ;MUST SCROLL. + JSR PC,LF ;ELSE JUST MOVE DOWN AND CLEAR A LINE. + JMP CLEOL + +CRLF1: JSR PC,SCROLL ;MOVE EVERYTHING UP 4 LINES, + JMP LF ;THEN MOVE DOWN 1 LINE. + +;SCROLL THE TEXT, MOVING THE CURSOR WITH IT, UP 4 LINES. +SCROLL: PUSH LEY(U) ;TO SCROLL, HOME UP AND DELETE 4 LINES AT SCREEN TOP. + PUSH LELCC(U) + PUSH LECC(U) + JSR PC,HU + MOV #4,A + JSR PC,LDEL0 + POP LECC(U) ;THEN RESTORE POSITION (TO LAST LINE, USUALLY) + POP LELCC(U) + POP LEY(U) + MOV LELCC(U),A + SUB #4*BYTPL*LINHT,A ;AND MOVE UP 4 LINES (OR TO SCREEN TOP). + CMP A,#TVLO + BHI SCROL1 + JMP HU + +SCROL1: MOV A,LELCC(U) + SUB #4*BYTPL*LINHT,LECC(U) + SUB #4*LINHT,LEY(U) +SCROLX: RTS PC + +;HERE TO BACKSPACE (NO-OP IF AT BEGINNING OF LINE) + +DPYBS: CMP LELCC(U),LECC(U) + BEQ SCROLX + JMP LEDREC + +;HERE TO HOME UP AND CLEAR SCREEN. + +DPYCLR: JSR PC,HU + JMP CLEOF + +;HERE FOR LINE FEED, NO FRILLS. WRAP AROUND AT SCREEN BOTTOM. +LF: ADD #,LELCC(U) + ADD #,LECC(U) + ADD #LINHT,LEY(U) + CMP #TVFENCE,LELCC(U) + BHI LF1 + SUB #TVFENCE-TVLO,LELCC(U) + SUB #TVFENCE-TVLO,LECC(U) + MOV #-NLINS,LEY(U) +LF1: RTS PC + +;HERE TO HOME UP +HU: MOV #TVLO,LELCC(U) ;RESET POINTER TO CURRENT LINE BEGINNING. + MOV #-NLINS,LEY(U) ;AND ITS POSITION ON SCREEN. + +;HERE FOR CARRIAGE RETURN +CR: MOV LELCC(U),LECC(U) ;ORIGIN OF THIS LINE +CR1: MOV #20-CHRWD,LEPHS(U) ;PHASE + MOV #-BITPL,LEX(U) ;RESET X + RTS PC + +;DELETE LINE(S). MOVE UP THE LINES BELOW THE CURRENT ONE, +;FLUSHING THE CURRENT ONE. BLANK LINES ARE SHIFTED IN AT THE BOTTOM. +LDEL: JSR PC,GETCHC ;READ NUMBER OF LINES TO DELETE IN A. +LDEL0: MOV #TVFENCE,B ;ADDRESS OF "END OF REGION" +LDEL00: MOV A,MQ + BEQ LINSX + CMP A,#50 + BHI LINS3 + MOV #BYTPL*LINHT,MUL ;GET # LINES * BYTPL*LINHT, = # BYTES TO SHIFT BY. + MOV LELCC(U),TT ;TT GETS ADDR OF THIS LINE. + MOV TT,T + ADD MQ,T ;T GETS ADDR OF LINE TO COPY INTO THIS. + BCS LDEL4 ;CARRY => T IS PAST BOTTOM OF SCREEN ALREADY. +LDEL3: CMP T,B ;NO MORE LINES AT BOTTOM TO COPY UP => + BHIS LDEL4 ; START CLEARING INSTEAD. + JSR PC,CPYCHL ;COPY THEM, INCREMENTING T AND TT TO NEXT LINES. + BR LDEL3 + +LDEL4: MOV TT,T +;CLEAR TEXT LINES FROM THE ONE T POINTS TO, TO END OF REGION IN B. PUTS CIOR IN CALU. +LDEL5: CMP T,B + BHIS LINSX ;POPJ, SETTING CALU TO CIOR. + JSR PC,CLRCHL + BR LDEL5 + +;INSERT LINE(S). MOVE THE CURRENT LINE AND LOWER ONES DOWN ONE OR MORE POSITIONS. +;BLANK LINES SHIFT IN AT THE CURRENT POSITION. +LINS: JSR PC,GETCHC ;HOW MANY LINES TO INSERT (IN A). + MOV A,MQ + BEQ LINSX ;DON'T WASTE TIME IF INSERTING 0 LINES. + CMP A,#50 ;DELETING INFINITE LINES = CLEAREOF + BHI LINS3 + MOV #BYTPL*LINHT,MUL + MOV #TVFENCE-,TT ;TT POINTS AT LAST ACTUAL LINE ON SCREEN. +LINS4: MOV TT,T + SUB MQ,T ;T IS LINE TO COPY INTO IT (COPYING DOWNWARD). + BCS LINS3 ;IF T IS ABOVE TOP OF SCREEN, GIVE UP. +LINS1: CMP LELCC(U),T ;STOP AFTER COPYING CURRENT LINE DOWN. + BHI LINS3 + JSR PC,CPYCHL ;COPY ONE LINE DOWNWARD. + SUB #2*BYTPL*LINHT,T ;THIS ADVANCES T AND TT TO NEXT LINE DOWN, + SUB #2*BYTPL*LINHT,TT ; WHEN WHAT WE WANT IS NEXT LINE UP. + BR LINS1 + +LINS3: MOV LELCC(U),T + +;CLEAR C(A) LINES OF CHARACTERS, STARTING AT THE LINE T POINTS TO, BUT STOP IF REACH END OF SCREEN. +;SETS CALU TO CIOR. +LINS2: CMP #TVFENCE,T + BLOS LINSX + JSR PC,CLRCHL + DEC A + BNE LINS2 +LINSX: MOVB #CIOR,CALU + RTS PC + +;REGION SCROLLING + +RGSCDN: JSR PC,GETCHC ;NUMBER OF LINES IN REGION + MOV A,B + JSR PC,GETCHC ;NUMBER OF LINES TO MOVE DOWN + MOV B,MQ + MOV #BYTPL*LINHT,MUL + MOV LELCC(U),TT + SUB #BYTPL*LINHT,TT + ADD MQ,TT ;ADDRESS OF LAST LINE IN REGION + BCS LINSX ;IGNORE IF GARBAGE REGION (WRAPPED AROUND ADDRESS) + CMP TT,#TVFENCE + BHIS LINSX ;IGNORE IF GARBAGE REGION + MOV A,MQ ;CONVERT DISTANCE TO MOVE TO BYTES + BEQ LINSX ;EXIT IF NOT MOVING + MOV #BYTPL*LINHT,MUL + BR LINS4 ;GO DO IT, USING INSERT-LINES SUBROUTINE + +RGSCUP: JSR PC,GETCHC ;NUMBER OF LINES IN REGION + MOV A,B + JSR PC,GETCHC ;NUMBER OF LINES TO MOVE UP + MOV B,MQ + MOV #BYTPL*LINHT,MUL + MOV LELCC(U),B + ADD MQ,B ;ADDRESS OF FIRST LINE AFTER REGION + BR LDEL00 ;GO DO IT, USING DELETE-LINES SUBROUTINE + +;INSERT CHARACTER(S). MOVE THE CURRENT CHARACTER AND FOLLOWING ONES TO THE RIGHT. +;BLANKS ARE SHOFTED IN AT THE CURRENT POSITION. +CINS: JSR PC,GETCHC ;A GETS HOW MANY CHARACTERS TO INSERT. + JSR PC,CINSET ;CHECK A FOR VALIDITY; PUSH A, LELCC(U), LINHT, AND LECC(U). +CINSL: MOV 6(SP),A + MOV (SP),T + MOV 4(SP),C + JSR PC,CINS1L + ADD #BYTPL,(SP) + ADD #BYTPL,4(SP) + DEC 2(SP) + BNE CINSL + ADD #6,SP ;FLUSH ALL BIT # CHAR POSITIONS FROM STACK. + POP B + PUSH LEX(U) + PUSH LEPHS(U) + PUSH LECC(U) +CINSC: JSR PC,CLRCHR ;NOW CLEAR OUT THE CHAR POSITIONS WE INSERTED. + JSR PC,LEDADC ;AND MOVE CURSOR PAST IT. + DEC B ;NOTE CLRCHR SETS CALU TO CIOR. + BNE CINSC + POP LECC(U) ;AND RESTORE THE CURSOR. + POP LEPHS(U) + POP LEX(U) +CINSX: RTS PC + +;INSERT C(A) CHARACTER POSITIONS IN ONE RASTER LINE AT PLACE T POINTS AT. +;C POINTS AT FRONT OF RASTER LINE. REQUIRES CALU/ CSET. +CINS1L: MOV A,MQ + MOV #CHRWD,MUL ;COMPUTE # OF BITS TO SHIFT THE LINE BY. + MOV #20,DIV ;COMPUTE # WORDS TO SHIFT IN MQ, # BITS IN AC. + MOV #20-CHRWD,TT + SUB LEPHS(U),TT ;TT GETS # BITS AT FRONT OF 1ST WORD NOT TO CHANGE. + PUSH TT + PUSH (T) ;ALSO SAVE THE WORD CONTAINING THEM. + PUSH T ;AND ITS ADDRESS + PUSH U ;FIT IN WITH WHAT CINS2 WILL POP. + MOV C,A + ADD #BYTPL,A ;A GETS ADDR TO AUTODECREMENT TO LAST WORD OF LINE. + MOV A,B + SUB MQ,B ;SUBTRACT THE # OF BYTES IN THE DESIRED # OF WORDS. + SUB MQ,B ;B GETS ADDR OF LAST WORD NOT SHIFTED INTO BIT BUCKET, + MOV -(B),TT ;TT GETS ITS CONTENTS, TO INIT THE LOOP. + MOV AC,C + NEG C ;C <= SHIFT COUNT, TO GET 1 NEW WORD FROM PAIR OF OLD. +CINS1: CMP B,T ;NOTE T STILL HAS ADDR OF LOWEST (LAST) WORD TO SHIFT + BEQ CINS3 + MOV TT,MQ + MOV -(B),TT ;FETCH ANOTHER (LOWER) OLD WORD, FROM WHICH + MOV TT,AC ;(COMBINED WITH PREVIOUS OLD WORD) + MOV C,LSH ;WE MAKE A NEW SHIFTED WORD. + MOV MQ,-(A) ;STORE THE NEXT NEW WORD. + BR CINS1 + +CINS3: MOV AC,-(A) ;REMAINDER OF LAST FROM-WORD GOES INTO LAST TO-WORD. + BR CINS2 + +;FOR INSERT/DELETE CHARACTER, CHECK ARG IN A FOR LEGALITY. MAYBE JUMP OFF +;TO CLEAR-TO-END-OF-LINE FOR INSERTING OR DELETING TOO MANY CHARACTERS. +;OTHERWISE, RETURN HAVING PUSHED ON THE STACK THE ARG, LELCC(U), #LINHT, AND LECC(U). +CINSET: POP B ;GET RET ADDR OFF STACK SO WE CAN POPJ OUR CALLER + MOV A,MQ ;OR PUSH ON HIS STACK. + BEQ CINSX ;IF ARG IS 0, OUR CALLER HAS NOTHING TO DO, SO POPJ HIM + MOV #CHRWD,MUL + MOV LEX(U),C ;AT WHAT DOT POSITION DOES REGION INSERTED/DELETED END? + ADD MQ,C + BLT .+6 ;PAST RIGHT MARGIN => THIS OPERATION EQUIVALENT + JMP CLEOL ;TO A CLEAR-TO-END-OF-LINE. + MOVB #CSET,CALU + PUSH A ;SAVE # CHAR POSITIONS TO INSERT. + PUSH LELCC(U) ;SAVE ADDR START OF 1ST RASTER LINE (ADVANCES) + PUSH #LINHT + PUSH LECC(U) ;AND ADDR OF CURSOR IN 1ST RASTER LINE. + JMP (B) ;RETURN TO OUR CALLER, HAVING PUSHED HIS TEMPS. + +;DELETE CHARACTERS. DELETE SOME CHARACTERS AFTER THE CURSOR. THE FOLLOWING ONES +;MOVE LEFT. BLANKS ARE SHOFTED IN AT THE RIGHT MARGIN. +CDEL: JSR PC,GETCHC ;A GETS HOW MANY CHARACTERS TO DELETE. + JSR PC,CINSET ;DECODE A. MAYBE POPJ OR JUMP TO CLEOL. + ;OTHERWISE, PUSH ON STACK A, LELCC(U), #LINHT, LECC(U). +CDELL: MOV 6(SP),A + MOV (SP),T + MOV 4(SP),C + JSR PC,CDEL1L + ADD #BYTPL,(SP) + ADD #BYTPL,4(SP) + DEC 2(SP) + BNE CDELL + ADD #10,SP + MOVB #CIOR,CALU +CDELX: RTS PC + +;DELETE C(A) CHARACTER POSITIONS FROM ONE RASTER LINE +;T POINTS AT WORD CONTAINING CURSOR, IN THAT RASTER LINE. +;C POINTS AT START OF THAT RASTER LINE. ASSUMES CALU/ CSET. +CDEL1L: MOV A,MQ + MOV #CHRWD,MUL ;COMPUTE # OF BITS TO SHIFT THE LINE BY. + MOV #20,DIV ;COMPUTE # WORDS TO SHIFT IN MQ, # BITS IN AC. + MOV #20-CHRWD,TT + SUB LEPHS(U),TT ;TT GETS # BITS AT FRONT OF 1ST WORD NOT TO CHANGE. + PUSH TT + PUSH (T) ;ALSO SAVE THE WORD CONTAINING THEM. + PUSH T ;AND ITS ADDRESS + MOV T,TT ;(WHICH IS ALSO ADDR TO START SHIFTING INTO). + ADD MQ,TT ;AND ADDR TO START SHIFTING FROM, AND 1ST FROM-WORD. + ADD MQ,TT ;MQ HAS # OF WORDS, BUT TT HAS AN ADDRESS. + MOV (TT)+,A + ADD #BYTPL,C ;C GETS ADDR OF 1ST WORD PAST END OF LINE. + PUSH U + MOV AC,U ;U HAS # BITS SHIFTING BY. +;NOW MAKE TO-WORDS 1 BY 1 EACH OUT OF A PAIR OF FROM-WORDS. +;THE LAST FROM-WORD IS IN A. T HAS STORE ADDRESS, TT HAS FETCH ADDRESS. +CDEL1: CMP C,TT ;STOP AFTER GOBBLING ALL OF THIS RASTER LINE. + BLOS CDEL2 + MOV (TT)+,B + MOV B,MQ ;CLOBBERS AC, SO RELOAD IT FROM T. + MOV A,AC + MOV U,LSH ;NOW SHIFT THE 2 FROM-WORDS BY # BITS SHIFTING BY, + MOV AC,(T)+ ;WHICH GIVES AC THE RIGHT STUFF FOR NEXT TO-WORD. + MOV B,A ;NOW T GETS THE NEWEST FROM-WORD, AND FETCH ANOTHER. + BR CDEL1 + +CDEL2: MOV A,MQ ;REMAINDER OF LAST FROM-WORD IS NEXT TO-WORD. + MOV U,LSH + MOV MQ,(T)+ + JSR PC,CLRRNG ;CLEAR STARTING WHERE T POINTS, ENDING WHERE C POINTS. +;NOW RESTORE THE FIRST FEW BITS OF THE FIRST WORD (WHICH WEREN'T SUPPOSED +;TO BE INCLUDED IN THE SHIFT). +CINS2: POP U + POP C ;GET ADDRESS OF 1ST TO-WORD + POP A ;GET OLD 1ST TO-WORD CONTENTS + POP T ;AND NUMBER OF BITS AT TOP NOT TO INCLUDE IN SHIFT. + MOV #-1,AC + NEG T + MOV T,LSH ;MQ GETS MASK TO BITS WE WANT SHIFTED INTO. + MOV AC,T + BIC T,A ;FLUSH THOSE IN SAVED CONTENTS. + COM T + BIC T,(C) ;FLUSH THE OTHERS IN SHIFTED CONTENTS. + BIS A,(C) ;MERGE OLD BITS WITH NEW. + RTS PC + +CLRRN1: CLR (T)+ +CLRRNG: CMP T,C + BNE CLRRN1 + RTS PC + +;CLEARS TO END OF LINE + +CLEOL: PUSH LECC(U) + PUSH LEPHS(U) + PUSH LEX(U) + JSR PC,CLEOL1 ;DO THE DIRTY WORK +CLEOX: POP LEX(U) + POP LEPHS(U) + POP LECC(U) + MOVB #CIOR,CALU ;RESTORE FOR DPYDP1 LOOP + RTS PC + +CLEOL1: MOV LEX(U),TT ;ALREADY AT END OF LINE? + BGE CLEOLX + CMP LEPHS(U),#20-CHRWD + BEQ CLEOL2 ;IF AT START OF WORD, START CLEARING WORD-WISE + JSR PC,CLRCHR ;ELSE CLEAR 1 CHAR AT A TIME TILL REACH WORD BOUNDARY. + JSR PC,LEDADC + CMP LEX(U),#-BITPL + BEQ CLEOLX ;CLEARED WHOLE LINE AND WRAPPED AROUND => DONE + BR CLEOL1 + +CLEOL2: ASR TT + ASR TT + ASR TT + ASR TT ;-(# WORDS TO CLEAR) + PUSH TT + PUSH LECC(U) ;ADDR OF 1ST WORD TO CLEAR, + PUSH #LINHT ;# LINES TO PROCESS + MOVB #CSET,CALU +CLEOL3: MOV 2(SP),T ;START CLEARING HERE +CLEOL4: CLR (T)+ + INC TT + BLT CLEOL4 + ADD #BYTPL,2(SP) + MOV 4(SP),TT ;-(# WORDS TO CLEAR) + DEC (SP) + BGT CLEOL3 + ADD #6,SP ;CLEANSE STACK + MOV T,LECC(U) + JMP CR1 ;RESET X AND PHASE + +CLEOLX: MOV LELCC(U),T + ADD #,T ;HERE IF ALREADY AT END OF LINE + MOV T,LECC(U) + JMP CR1 + +;CLEARS TO END OF SCREEN + +CLEOF: MOV LELCC(U),T ;IF AT START OF LINE, DO FAST CLEAR FROM THIS LINE. + CMP #-BYTPL,LEX(U) ;IF NOT AT BEGINNING OF LINE, USE CLEOL TO CLEAR + BEQ CLEOF1 ;ONLY THE REST OF THIS LINE. + JSR PC,CLEOL + MOV LELCC(U),T ;AND START FAST CLEAR WITH NEXT LINE. + ADD #BYTPL*LINHT,T +CLEOF1: MOV #TVFENCE,B + JMP LDEL5 + +;HERE TO FORWARD SPACE + +FS: JMP LEDADC + +;HANDLE %TDMOV +SETCUR: JSR PC,GETCHC ;OLD VERTICAL AND HORIZONTAL + JSR PC,GETCHC + +;HANDLE %TDMV0, %TDMV1 ABSOLUTE POSITIONING COMMANDS. +SETCR1: JSR PC,GETCHC ;NEW VERTICAL + MOV A,B + JSR PC,GETCHC ;NEW HORIZONTAL + ;NOTE GETCHC MAY RETURN AND BE REENTERED, + ;RESETTING ALL ACS BUT B. + +;HERE TO SET CURSOR GIVEN A COORDINATE PAIR (X,Y) IN CHARACTERS. +;X AND Y ARE IN A AND B RESPECTIVELY, (0,0) IS UPPER LEFTHAND CORNER +;(1,3) IS THE SECOND CHARACTER OF FOURTH LINE + +SETXY: CMP #CHRPL,A ;CHECK FOR LEGAL POSITION + BLOS SETXY1 + CMP #CHRLN,B + BLOS SETXY1 +SETXY0: MOV #MQ,T ;FOR THE MYRIAD MULTIPLIES AND DIVIDES + MOV B,(T)+ ;Y POSITION + MOV #BYTPL*LINHT,(T) ;FIND ORIGIN OF LINE IN MEMORY + MOV -(T),LECC(U) + MOV (T),LELCC(U) + MOV A,(T)+ ;X POSITION + MOV #CHRWD,(T) + MOV -(T),LEX(U) ;BITS FROM LEFT OF SCREEN + CLR -(T) ;CLEAR OUT AC + MOV #20,-(T) ;DIVIDE GIVES WORDS FROM LEFT AND PHASE + TST (T)+ + MOV (T)+,LEPHS(U) ;PHASE + ASL (T) ;BYTES FROM BEGIN OF LINE + ADD (T),LECC(U) ;LEAVE T POINTING AT MQ + ADD #-BITPL,LEX(U) ;THAT'S ALL DONE + NEG LEPHS(U) + ADD #20-CHRWD,LEPHS(U) ;PHASE IS SET + MOV B,(T)+ ;Y POSITION AGAIN + MOV #LINHT,(T) + MOV -(T),LEY(U) + ADD #-NLINS,LEY(U) ;LEY SET + ADD #TVLO,LECC(U) + ADD #TVLO,LELCC(U) + BIT #1,LECC(U) ;MAKE SURE IT LINES UP ON WORD BOUNDARY + BEQ .+4 + BPT +SETXY1: RTS PC + +;OUTSTR TAKES STRING TO PRINT IN B + +OUTSTR: +OUTS1: MOVB @(SP),A + INC (SP) + TST A + BEQ OUTSX + CMP #12,A + BEQ OUTSLF + CMP #15,A + BEQ OUTSCR + JSR PC,TVO + BR OUTS1 +OUTSLF: JSR PC,LF + BR OUTS1 +OUTSCR: JSR PC,CR + BR OUTS1 +OUTSX: ASR (SP) ;MAKE SURE WE RETURN TO EVEN ADDRESS + ADC (SP) + ASL (SP) + RTS PC + +;TAKES # IN A AND PRINTS AS UNSIGNED INTEGER + +OCTPNT: PUSH RADIX + MOV #10,RADIX +OCTPN1: JSR PC,DECPN0 + POP RADIX + RTS PC + +DECPNT: PUSH RADIX + MOV #10.,RADIX ;FOR DECIMAL PRINTING + BR OCTPN1 + +DECPN0: MOV A,MQ ;INTO EAE +DECPN9: MOV #AC,A ;FOR FAST ACCESS +DECPN1: MOV RADIX,-(A) ;DIVIDE BY RADIX + TST (A)+ ;POINTS AT AC + MOV (A)+,-(SP) ;REMAINDER + ADD #'0,(SP) + TST (A) ;QUOTIENT IS IN MQ + BEQ DECPN2 + CLR -(A) ;FLUSH OUT AC, LEAVING MQ UNTOUCHED + JSR PC,DECPN1 ;RECURSIVE YET! +DECPN2: POP A ;TYPE OUT THAT DIGIT + JMP TVO ;TYPES DIGIT AND ADVANCES CURSOR + +.SBTTL CALL, BREAK AND ESCAPE ROUTINES + +;LEGAL ESCAPE AND BREAK COMMAND TABLE + +ESCHAR: .BYTE '0,'1,'2,'3,'4,'5,'6,'7,'8,'9 ;DON'T DISTURB DIGITS + .BYTE 'S,'Q,'F,'D,'A,'E ;THESE CAN BE DONE ON ANY KBD +ESCSRN: .BYTE 'C,'L,'I,'R,'W,'U ;THESE NEED A SCREEN TO WIN +NESCMD==.-ESCHAR + .BYTE 0 ;MARKS END OF TABLE + .EVEN + +;DISPATCH TABLE + +ESCTAB: .REPT 10. + .NLIST + ESCDIG ;DIGIT + .LIST + .ENDR + VSWSEL ; SELECT VIDEO CHANNEL + ESCQPY ; CAUSE A HARD COPY TO EXIST + ESCFRE ; SAME AS S, BUT TO CONSOLE FREE BUFFER + ESCBUZ ; BUZZ 9TH FLOOR DOOR + ESCAUD ; SELECT AUDIO INPUT. + ESCELE ; CALL THE ELEVATOR +CHECK ESCTAB,<*2> + BOWXOR ; TOGGLE BLACK ON WHITE BIT + ESCCLR ; CLEAR SCREEN UNBEKNOWNST TO TEN. + ESCCSR ; CLEAR SCROLL REGISTER + ESCRPT ; START REPEATING THE PREV. CHAR TYPED IN. + ESCWHO ; WHO LINE CONTROL + ESCWHO ; WHO LINE CONTROL +CHECK ESCTAB,NESCMD*2 + +;HERE FOR ESCAPE + +ESCAPE: BIT #ACLBIT+AMTBIT,B + BEQ ESCAP1 ;ESCAPE WITH CONTROL OR META TURNS INTO TOP-A. + JMP BRKCLR + +ESCAP1: MOVB A,KBDESC(C) ;SAY FOLLOWING CHARS TO BE INTERPRETED AS AN ESCAPE CMD. + CLRB KBDARG(C) ;DEFAULT ARG TO ZERO +RTSPC4: RTS PC + +;ACCUMULATE ARGS FOR ESCAPE AND BREAK + +ESCDIG: ASR T ;DIGIT + MOVB KBDARG(C),A ;MULTIPLY ACCUMULATED VALUE BY 8 + ASL A + ASL A + ASL A + ADD T,A ;ADD IN NEW DIGIT + MOVB A,KBDARG(C) + INCB KBDESC(C) ;READ NEXT CHAR AS A COMMAND CHAR, NOT AS PDP-10 INPUT. + RTS PC + +;TAKES CHARACTER IN A AND CONVERTS IT UPPER CASE + +UPPER: TST A ;MAKE SURE ITS LEGAL ASCII + BLE UPPER1 + CMP #'a,A ;LOWER CASE? + BGT UPPER1 + CMP #'z,A + BLT UPPER1 + SUB #'a-'A,A ;MAKE IT UPPER CASE +UPPER1: RTS PC + +;HANDLE ESCAPE-R. WITH NO ARG, STARTS INDEFINITE REPETITION OF LAST CHARACTER TYPED. +;WITH ARG, STOPS AFTER THAT MANY REPETITIONS. IN ANY CASE, ANY USER-SUPPLIED +;INPUT STOPS THE REPETITION. +ESCRPT: MOVB KBDARG(C),A + BNE ESCRP1 + DEC A +ESCRP1: MOV A,LERPT(U) + RTS PC + +;HERE TO SELECT VIDEO SWITCH INPUT. +;C HAS 2*KBD NUMBER; KBDARG(C) HAS VSW INPUT # OR 0 => DEFAULT. + +VSWSEL: JSR PC,VSWSGO ;SET UP L.E. IDX IN U, VSW OUTPUT IN T. + BLT RTSPC4 + MOV #-1,KBDDEF(C) ;NORMALLY RESET ANY TIME-OUT, BUT + TSTB KBDARG(C) ;IF THERE'S AN ARGUMENT, + BEQ VSWSL0 + TST U + BNE VSWSL0 + JSR PC,VSWSL3 ;SET UP A TIMEOUT, IF WE ARE A FREE SCREEN. +VSWSL0: MOVB KBDARG(C),TT ;GET ARG + BNE VSWSL1 ;SELECT DEFAULT? + +;SELECT THE DEFAULT INPUT FOR A KEYBOARD. +;C HAS 2*KBD #, U HAS L.E. IDX OR 0 IF NONE, T HAS DEFAULT VSW OUTPUT OF THAT KBD. +VSWDEF: MOV #-1,KBDDEF(C) ;SAY THERE'S NO TIMEOUT ON THIS VSW SELECTION. + TST U ;FREE SCREEN => DEFAULT IS THE FREE DPY BUFFER. + BEQ VSWFRE + MOVB LECREG(U),TT ;GET DPY # TO SET DEFAULT + BLT RTSPC4 ;GARBAGE? +;COME HERE WITH DPY BUFFER # IN TT, TO SELECT THAT DPY BUFFER. +VSWDE1: ASL TT + MOV DPYVSW(TT),TT ;DEFAULT VIDEO SWITCH INPUT + JMP VSWIT ;DON'T NEED TO CHECK THIS + +;COME HERE FOR [ESC]S, WITH IN TT. +VSWSL1: BIC #-400,TT ;UNDO SIGN-EXTENSION AT VSWSL0 + CMP TT,NF11TY + BLO VSWSL2 ; TOO SMALL TO BE TTY # => IT IS VSW INPUT #. + CMP TT,#200 + BHIS VSWSL4 ; >= 200 => IT IS DPY BUFFER # PLUS 200. + TST NF11TY ;IF NF11TY ISN'T KNOWN, VSW INPUT #S LOOK LIKE TTY #S + BEQ VSWSL2 ;BUT WE ARE EVEN SMARTER AND KNOW IT'S REALLY VSW INPUT. + SUB NF11TY,TT ;ELSE SHOULD BE TTY NUMBER + CMP TT,#MAXTV + BHIS RTSPC4 ;DO NOTHING IF ARG OUT OF RANGE. + ASL TT + ASL TT + MOVB DPYKBD+1(TT),TT ;GET DPY BUFFER # FOR THIS TV, AND SELECT THAT DPY BUFFER. + BMI RTSPC4 + BR VSWDE1 + +VSWSL4: SUB #200,TT ;TT SUPPOSEDLY HAS 200 PLUS DPY BUFFER NUMBER. + CMP TT,#MAXTV + BLO VSWDE1 + BR RTSPC4 + +;COME HERE TO HANDLE SET-VSW COMMAND FROM PDP10. T HAS OUTPUT #, TT HAS INPUT #. +;IF THEY ARE ILLEGAL WE DO NOTHING. +;ON RETURN, BLO JUMPS IF THEY WERE LEGAL. +VSWCMD: MOV #-1,KBDDEF(C) ;FLUSH ANY TIME-OUT. + CMP T,#MAXVSO ;CHECK FOR LEGAL OUTPUT + BHIS RTSPC4 +;COME HERE WITH VALID OUTPUT # IN T, AND (MAYBE INVALID) INPUT # IN TT. +VSWSL2: CMP TT,#MAXVSI*VSWSEC + BHIS RTSPC4 ;REASONABLE? + JMP VSWIT ;SWITCH THE SWITCH + +ESCFRE: JSR PC,VSWSGO ;SET UP U AND T FOR VSWDE1. + BLT RTSPC5 + JSR PC,VSWSL3 ;THERE IS A TIMEOUT ON THIS SPYING. +VSWFRE: MOV DPYFRE,TT ;GET DPY # OF FREE CONSOLE SCREEN + BR VSWDE1 + +;SET UP A TIMEOUT WHEN A SPY IS ABOUT TO BE DONE. C HAS 2*KBD. +VSWSL3: MOVB #KBDTIM,KBDCNT(C) ;SET UP A TIMEOUT ON THIS KEYBOARD. + INC KBDTSW ;TELL CLOCK LEVEL TO START CHECKING TIMEOUTS. + RTS PC + +;SET UP U := L.E. IDX, OR 0 IF NONE; T HAS DEFAULT VSW OUTPUT; GIVEN 2*KBD # IN C +;NEGATIVE IF SOMETHING FUNNY IS GOING ON, AND CALLER SHOULDN'T HACK. +VSWSGO: MOV KBDLE(C),U + BLT RTSPC5 ;THIS IF TEN SELECTS NON-EXISTENT VSW OUTPUT. + BEQ VSWSG1 + TST LEKBD(U) + BLT RTSPC5 +VSWSG1: MOV C,T + ASR T + MOVB KBDVSW(T),T + RTS PC + +;DO [ESC]S ON KBD SPEC'D BY 2*KBD IN C. +VSWUNS: JSR PC,VSWSGO + BLT RTSPC5 + JMP VSWDEF + + +;HANDLE [ESC] A. +ESCAUD: MOVB KBDARG(C),TT ;ASW INPUT NUMBER. + MOV C,T + ASR T ;KEYBOARD NUMBER. + MOVB KBDASW(T),T ;OUTPUT NUMBER OF KEYBOARD. + BMI RTSPC5 ;WE DON'T KNOW YET OR IT HAS NO SPEAKER. + JMP ASWIT ;CONNECT THEM. + +;CHANGE STATE OF BOW BIT + +BOWXOR: MOVB #CXOR,CALU + MOV #BOWBIT,CSA + RTS PC + +;HERE TO CLEAR SCREEN + +ESCCLR: MOVB CREG,T ;THE SCREEN TO CLEAR + PUSH T + + BLKOFF T + JSR PC,CLBLIN ;CLEAR ALL BLINKERS + JSR PC,CLRSCR ;CLEAR THE SCREEN + POP T + BLKON T + + RTS PC + +;HERE TO RESET SCROLL REGISTER + +ESCCSR: MOVB #CSET,CALU + BIC #SAMSK,CSA ;RESET THE SCROLL REGISTER + RTS PC + +;HERE TO GENERATE VIDEO HARD COPY + +ESCQPY: TST QPYSWT ;IS THE SWITCH LOCKED? + BNE ESCQPB + TST QPYDWN ;IS THE QPY DOWN? + BNE ESCQPB +ESCQP1: MOV KBDLE(C),U + BEQ ESCQP6 + TST LEKBD(U) + BLT RTSPC5 +ESCQP6: MOV #QPYVSW,T ;THE VIDEO SWITCH OUTPUT FOR THE HARD COPY UNIT + JSR PC,VSWSL0 ;PROCESS THE ARG + CHROFF + ZAPFLG QPYSWT ;LOCK THE SWITCH + BIS #QPYKMS,KMS ;CAUSE THE COPY + JSR TT,ADQUE ;SCHEDULE THE UNCOPY + 2 + ESCQP2 + MOV CREG,T + JSR TT,ADQUE ;SCHEDULE THE SWITCH UNLOCK + QPTIME + ESCQP3 +RTSON: CHRON +RTSPC5: RTS PC + +ESCQPB: JMP BELL ;SOME ONE ELSE IS COPYING, GIVE HIM A BELL + +ESCQP2: BIC #QPYKMS,KMS ;UNCAUSE THE COPY + RTS PC + +ESCQP3: JSR PC,CLKBEL ;BELL WHEN COPY DONE + CLR QPYSWT + RTS PC + +;HERE TO BUZZ 9TH FLOOR DOOR +ESCBUZ: TST BUZSWT ;IS THE SWITCH LOCKED? + BEQ ESCBZ1 + JMP BELL +ESCBZ1: CHROFF + ZAPFLG BUZSWT ;LOCK SWITCH + BIS #BUZKMS,KMS ;BUZZ THE DOOR + MOV CREG,T + JSR TT,ADQUE ;SCHEDULE THE UNBUZZ + BUZTIM + ESCBZ2 + BR RTSON + +ESCBZ2: JSR PC,CLKBEL ;BELL WHEN BUZZ DONE + BIC #BUZKMS,KMS ;UNBUZZ THE DOOR + CLR BUZSWT ;UNLOCK THE SWITCH + RTS PC + +;HERE TO CALL THE ELEVATOR +; C HAS 2*KBD NUMBER + +ESCELE: TST ELESWT ;IS THE SWITCH LOCKED? + BEQ ESCEL1 + JMP BELL +ESCEL1: CHROFF + ZAPFLG ELESWT ;LOCK SWITCH + MOV C,T + ASR T ;DEVIDE BY 2 + CMP T,#MAXVSO ;IS IT IN RANGE? + BHIS RTSON + MOVB ELETAB(T),TT ;WHICH FLOOR IS IT ON? + SWAB TT ;GET CONSTANT INTO THE LEFT HALF WORD + BIS TT,KMS ;FROB THE CORRECT BIT + MOV CREG,T + JSR TT,ADQUE ;SCHEDULE THE UNPUSH + ELETIM + ESCEL2 + BR RTSON + + +ESCEL2: JSR PC,CLKBEL ;BELL WHEN DONE + BIC #ELEKMS,KMS ;UNPRESS + CLR ELESWT ;UNLOCK THE SWITCH + RTS PC + + + +CLKBEL: PUSH CREG ;FOR USE BY CLOCK QUEUED ROUTINES + MOV (T),CREG ;T POINTS TO DESIRED CREG + PUSH TT ;DON'T CLOBBER AT PI LEVEL!! + JSR PC,BELL + POP TT + POP CREG + RTS PC + +;HERE TO CONTROL WHO LINE + +; [ESC]W WHMODE +; N=0 TURN OFF WHO LINE -1 +; 1 FOLLOW KEYBORAD 0 +; 2 FREEZE 1 +; 3 NEXT HIGHER 2 +; 4 NEXT LOWER 3 +;ALL OTHERS SYSTEM WHO LINE + +; [ESC]U +;FREEZES WHOLINE ON JOB WHOSE USER INDEX IS N*L (L IS THE ITS SYMBOL). + +NWHCMD==5 ;NUMBER OF WHO COMMANDS + +ESCWHO: MOV LECHN(U),TT ;10/11 CHANNEL + ASL TT ;MAKE IT CHANNEL INDEX + ASL TT + MOV WHOLIN(TT),TT ;WHO LINE VARIABLES + CMPB A,#'U + BEQ ESCWHU + MOVB KBDARG(C),T ;ARGUMENT + DEC T ;HACK + BMI ESCWH2 ;TURN IT OFF? + MOV T,WHMODE(TT) ;SET THE MODE WE WANT +ESCWU1: CLR WHMOD1(TT) ;JUST TO BE SURE + MOV #-1,TENWHO ;TELL PDP-10 TO UPDATE WHO LINES + RTS PC + +;TURNS OFF WHO LINE + +ESCWH2: ;CLEAR WHO LINE AT MAIN PROGRAM LEVEL TOO + MOV T,2(TT) ;(T HAS -1 IN IT) + MOV T,WHMODE(TT) ;AND TURN IT OFF + BR CLRWHL + +ZAPWHL: MOV DPYCHN(B),A ;SET UP CREG + MOVB LECREG(A),CREG +CLRWHL: MOV #TVLO+,T + MOV #CHRHT-1,TT + JMP CLRCL0 + +ESCWHU: MOV #1,WHMODE(TT) + MOVB KBDARG(C),WHJOB(TT) + CLR WHJOB1(TT) + BR ESCWU1 + +;COME HERE FOR CALL KEY + +CALL: PUSH B + TSTB KBDCNT(C) + BLT CALL1 + JSR PC,VSWUNS ;IF DOING A SPY WITH A TIMEOUT, UNDO IT. +CALL1: MOV KBDLE(C),U ;LINE EDITOR VARIABLES + BNE UPTREE ;GET FRESH LINE EDITOR? + ASR C + JSR PC,CHCONS ;ALLOCATE A CHANNEL. +;T HAS CHANNEL NUMBER. U HAS LINE EDITOR ADDR. A HAS WHOLINE VAR BLOCK ADDR. + TST T ;-1 RETURNED AS CHANNEL # => NONE AVAILABLE. + BLT CALLLS + MOVB LECREG(U),CREG + CLR CSA ;CLRSCR SETS UP CALU + +;HERE IF CALL AND LINE EDITOR EXISTS. + +UPTREE: POP B + CLR LERPT(U) + MOV #32,A ;CONTROL-Z (SIGH) + BIS #ACTBIT,B ;ACTIVATES BUFFER + JMP PUTCHR ;SEND THAT CHARACTER TO PDP-10 + +CALLLS: POP B +RTSPC2: RTS PC + +;HERE TO ALLOCATE A DISPLAY CHANNEL. +;CALLED WITH KEYBOARD NUMBER IN C, OR -1 IF NOT ALLOCATING THIS DPY FOR A KEYBOARD. +;RETURNS THE CHANNEL NUMBER (TTY NUMBER MINUS NF11TY) IN T, +;THE LINE EDITOR BLOCK ADDR IN U, +;AND THE ADDRESS OF THE WHOLINE VARIABLE BLOCK IN A. SETS WHMODE TO 0. +;IF NO CHANNEL IS AVAILABLE, OR THE KEYBOARD CAN'T BE USED FOR SOME REASON, +;WE RETURN -1 IN T TO INDICATE THAT. + +CHCONS: MOV C,T ;IF A KEYBOARD IS SPECIFIED, + BLT CHCON4 + TSTB KBDVSW(C) ;DON'T ALLOW IT IF KEYBOARD HAS NO SCREEN + BLT CHCNFL + ASL T + TST KBDLE(T) ;OR IS ALREADY IN USE. + BNE CHCNFL +CHCON4: CLR T ;NOW FIND A FREE CHANNEL +CHCON1: TSTB CHCREG(T) ;DON'T ALLOCATE CHANNELS THAT DON'T HAVE BUFFERS. + BLT CHCON0 + TSTB CHNUSE(T) + BEQ CHCON2 +CHCON0: INC T + CMP T,#MAXTV + BLT CHCON1 +CHCNFL: MOV #-1,T + RTS PC ;NO FREE CHANNEL + +CHCON2: INCB CHNUSE(T) ;FOUND A CHANNEL. MARK IT IN USE. + DEC ITSFDP ;DECREASE COUNT OF FREE CHANNELS. + MOVB CHCREG(T),A + PUSH A ;SAVE VIDEO BUFFER NUMBER FOR POPPING INTO LECREG + MOVB A,CREG ;SELECT THAT BUFFER + PUSH T ;PROTECT T, SMASHED BY CLRSCR (TT ALSO SMASHED) + JSR PC,CLRSCR ;AND CLEAR IT (SLOW, BUT NECESSARY BEFORE SWITCHING VSW) + POP T + MOV T,A + ASL A + ASL A + MOV DPYCHN(A),U ;GET THE ADDR OF CHANNEL'S VAR BLOCK. + JSR PC,CHCLR ;PUT -1'S IN THE 10-TO-11 BUFFER, RESET POINTERS. + JSR PC,LECON2 ;INITIALIZE THE LINE EDITOR BLOCK. + MOVB (SP),DPYKBD+1(A) ;TELL THE 10 WHICH TV BUFFER. + POP LECREG(U) ;TELL THE LINE EDITOR WHICH TV BUFFER IT IS. + MOV C,LEKBD(U) ;AND WHICH KEYBOARD IT IS. + BLT CHCON3 + MOV C,CHNCLS(A) ;TELL THE 10 ABOUT THE KEYBOARD. + CLRB CHNCLS+1(A) ;MAKE SURE CHNCLS IS NON-NEGATIVE EVEN IF KBD WAS -1 + MOVB C,DPYKBD(A) + MOV T,LECHN(U) ;TELL LE WHICH DPY CHANNEL NUMBER IT IS + PUSH T ;SHOW OUR DPY BUFFER ON THE KBD'S SCREEN. + MOVB KBDVSW(C),T ;VIDEO SWITCH OUTPUT + MOVB LECREG(U),B + ASL B + MOV DPYVSW(B),TT ;GET OUR DPY'S VIDEO INPUT NUMBER. + JSR PC,VSWIT ;SWITCH THE SWITCH + MOV FBLINK,T ;CONS UP A BLINKER FOR THE CURSOR + BNE .+4 ;ARE THERE FREE BLINKERS? + BPT + + MOV BLNEXT(T),FBLINK + MOV BLINKS(B),BLNEXT(T) + MOV T,BLINKS(B) ;THE BLINKER + MOV U,BLCURS(T) ;FOLLOW PAGE PRINTER + CLRB BLON(T) ;BLON + + POP T + ASL C ;MAKE THE KEYBOARD AND THIS LINE EDITOR POINT AT EACH OTHER. + MOV U,KBDLE(C) +CHCON3: PUSH WHOLIN(A) + PUSH T + MOV T,TT + MOV LEBUF(U),T + JSR PC,CLRING ;CLEAR THE 11-TO-10 INPUT BUFFER RING. + POP T + POP A + MOV #0,WHMODE(A) + RTS PC + +;CLEAR OUT THE 10-TO-11 BUFFER WHICH U POINTS AT. + +CHCLR: MOV DPY10B(U),TT ;POINTER TO START OF BUFFER + MOV TT,DPY11B(U) ;RESET OUR POINTER INTO THE CHANNEL'S BUFFER. + INC DPY11B(U) ;MAKE POINT AT 1ST BYTE IN PDP10 ORDER! +CHCLR1: MOV #-1,(TT)+ + CMP TT,DPYLGL(U) + BLOS CHCLR1 + RTS PC + +;HERE TO INITIALIZE MOST OF THE WORDS OF A LINE EDITOR BLOCK, +;AND GET A RING OF KEYBOARD BUFFERS FOR IT. +LECON2: PUSH T + PUSH U + MOV U,TT ;SET DEFAULTS + ADD #DPSIZE+DPDATA,TT + MOV #LEDFLT+DPSIZE+DPDATA,T + MOV #LELEN-DPSIZE-DPDATA,U + JSR PC,CALCPY ;DEFAULT IS FOR FREE VARIABLES + POP U + MOV FSP,T ;FIRST FREE BUFFER + BEQ LECON3 + MOV LHFS(T),TT ;NEXT BUFFER + BEQ LECON3 + MOV LHFS(TT),FSP ;TAKE THOSE TWO + MOV T,LHNEXT(TT) + MOV TT,LHNEXT(T) ;ALL NICE AND COZY + MOV T,LEBUF(U) ;POINTER TO RING + ADD #LHLEN,T + MOV T,LECHR(U) ;BUFFER ACCESS POINTER + POP T + RTS PC + +LECON3: BPT ;NO 11-TO-10 BUFFERS AVAILABLE FOR A RING? + +;CLEARS HEADERS OF BUFFER RING, CALLED WITH RING IN T, CHN# IN TT + +CLRING: PUSH T +CLRNG1: CLR (T)+ .SEE LHFLAG + CLR (T)+ .SEE LHZERO + TST (T)+ .SEE LHNEXT + CLR (T)+ .SEE LHALST + CLR 2(T) .SEE LHFS + CLR 4(T) .SEE LHQUED + MOV TT,(T) .SEE LHCHN + TST -(T) .SEE LHALST + MOV -(T),T ;.SEE LHNEXT COMMENT THIS OUT DUE TO PALX BRAIN DAMAGE + CMP (SP),T + BNE CLRNG1 + POP T + RTS PC + +;HERE TO COPY A BLOCK OF CORE +: T SOURCE +; TT DESTINATION +; U BYTE COUNT (ONLY EVEN NUMBERS WILL WORK) + +CALCPY: INC U ;MAKE A WORD COUNT + ASR U +CALCP1: MOV (T)+,(TT)+ + DEC U + BGT CALCP1 + RTS PC + +;HERE TO RETURN DPY CHANNEL. T HAS CHANNEL NUMBER. + +CHRETN: TST T ;DON'T RETURN CHANNEL 0. + BEQ CHRET0 + DECB CHNUSE(T) ;MARK THE CHANNEL AS NOT IN USE + BGE .+4 + BPT + INC ITSFDP ;AND INCLUDE IT IN THE COUNT OF FREE CHANNELS. + BR CHRET1 + +CHRET0: MOV #377,CHNCLS ;IF FREEING THE FREE TV DISPLAY, DON'T REALLY FREE IT +CHRET1: ASL T + ASL T + MOV DPYCHN(T),U + JSR PC,CHCLR ;RESET THE 10-TO-11 BUFFER AND POINTERS. + TST T + BEQ CHRETX ;DON'T RETURN CHANNEL 0 (FREE CONSOLE DISPLAY) + MOV #-1,DPYKBD(T) ;TELL THE PDP-10 WE'RE LOGGING OUT + MOV WHOLIN(T),TT + MOV #-1,WHMODE(TT) ;TURN OFF WHO-LINE GENERATION ON THIS CHANNEL. + +;HERE TO FREE THE 11-TO-10 INPUT BUFFERS, AND MARK THE KEYBOARD AND CHANNEL +;AS DISCONNECTED. ALSO FREE THE BLINKERS. +LERETN: CLR LERPT(U) + MOV LEBUF(U),T ;RETURN BUFERS IN RING + BEQ LERT2A ;BUFFERS TO RETURN? + PUSH T +LERET1: MOV LHNEXT(T),LHFS(T) + CMP LHFS(T),(SP) + BEQ LERET2 + MOV LHFS(T),T + BR LERET1 +LERET2: MOV FSP,LHFS(T) ;CUT RING, PATCH ON TO FREE LIST + POP FSP + CLR LEBUF(U) ;MARK AS FREE +LERT2A: MOV LEKBD(U),T + BLT LERT2B ;A KEYBOARD? + ASL T ;BYTES + CLR KBDLE(T) + ASR T + MOVB KBDVSW(T),T ;VSW THE OUTPUT + BLT LERT2B + MOV DPYFRE,TT ;MESSAGE DPY + ASL TT ;BYTES + MOV DPYVSW(TT),TT + JSR PC,VSWIT ;GIVE HIM THE CONSOLE FREE MESSAGE +LERT2B: MOVB LECREG(U),T ;RETURN ALL THE BLINKERS + BLT LERET5 ;A DPY? + MOVB #-1,LECREG(U) ;INVALIDATE DPY # + ASL T + TST BELCNT(T) ;ANY BELLS PENDING? + BMI LERET6 + CLR BELCNT(T) ;THE NEXT FLASH WILL BE THE LAST +LERET6: MOV BLINKS(T),TT ;RETURN THIS DISPLAY'S BLINKERS TO FREE LIST. + BEQ LERET5 +LERET3: TST BLNEXT(TT) + BEQ LERET4 + MOV BLNEXT(TT),TT + BR LERET3 +LERET4: MOV FBLINK,BLNEXT(TT) + MOV BLINKS(T),FBLINK + CLR BLINKS(T) +LERET5: MOV #-1,LEKBD(U) +CLRUJ: CLR U ;SEARCH FAILED +CHRETX: RTS PC + +.SBTTL VIDEO AND AUDIO SWITCH ROUTINES + +;VIDEO SWITCH TABLES (ONE INPUT CAN DRIVE MANY OUTPUTS) + +;THE SWITCH IS COMPOSED OF SEVERAL IDENTICAL SECTIONS, THE CORRESPONDING +;OUTPUTS OF EACH SECTION ARE MIXED TOGETHER TO FORM THE FINAL VIDEO THAT IS +;SENT TO THE MONITOR. INPUT 0 OF EACH SECTION OF THE SWITCH IS THE NULL INPUT, +;HENCE WE USUALLY USE THAT INPUT WHEN USING A MONITOR AS A DISPLAY. + +;VSWTAB, INDEXED BY OUTPUT NUMBER, IS A BYTE GIVING THE NONNULL INPUT FEEDING THAT OUTPUT. +;THE INPUT NUMBER IS RELATIVE TO THE WHOLE SWITCH, NOT JUST THE SECTION. +;0 MEANS THAT ONLY NULL INPUTS ARE FEEDING AN OUTPUT. + +VSWTAB: .BLKB MAXVSO + + +;HERE TO SWITCH VIDEO SWITCH (OUTPUT IN T, INPUT IN TT). +;CLOBBERS NO ACS. + +VSWIT: PUSH TT + JSR PC,VSWNUL ;FLUSH ALL OTHER INPUTS TO THAT OUTPUT. + POP TT +VSWIT1: PUSH B + PUSH C + MOVB TT,VSWTAB(T) ;UPDATE OUR OWN INTERNAL TABLE. + MOV TT,MQ + MOV #MAXVSI,DIV ;DIVIDE TO TURN INPUT NUMBER + MOV MQ,C ;INTO SECTION NUMBER + MOV AC,B ;AND NUMBER WITHIN SECTION. + TST A ;CLEAR C BIT + ROR C + ROR C + ROR C + ROR C ;GET SECTION NUMBER INTO TOP THREE BITS OF WORD. + BIS C,B + MOV T,C + SWAB C + BIS C,B ;CREATE ARGUMENT FOR VIDEO SWITCH. + MOV B,VSW ;SWITCH IT! + POP C + POP B + RTS PC + +;HERE SEND NULL VIDEO TO OUTPUT SPECIFIED IN T +;CLOBBERS TT +VSWNUL: PUSH #VSWSEC ;# SECTIONS + CLR TT ;INPUT 0 IN SECTION 0. +VSWN1: JSR PC,VSWIT1 ;SWITCH IT + ADD #MAXVSI,TT ;ADVANCE TO INPUT 0 IN NEXT SECTION + DEC (SP) + BGT VSWN1 ;MORE + TST (SP)+ ;CLEANSE STACK + CLRB VSWTAB(T) ;MAKE SURE INTERNAL TABLE SAYS NOTHING FEEDING THIS OUTPUT. + RTS PC + +;AUDEO SWITCH TABLES (ONE INPUT CAN DRIVE MANY OUTPUTS) + +;INPUT 0 IS SILENCE. RIGHT NOW, THAT IS THE NORMAL SETTING FOR ANY OUTPUT. + +;ASWTAB, INDEXED BY OUTPUT NUMBER, IS A BYTE GIVING THE INPUT FEEDING THAT OUTPUT. +ASWTAB: .BLKB MAXASO + + +;GIVEN ASW OUTPUT IN T AND INPUT IN TT, CONNECT THEM IF THEY ARE LEGAL. +;ON RETURN, BLO JUMPS IF THEY WERE LEGAL. +ASWCMD: CMP T,#MAXASO + BHIS ASWITX + CMP TT,#MAXASI + BHIS ASWITX + +;HERE TO SWITCH AUDEO SWITCH (OUTPUT IN T, INPUT IN TT). +;CLOBBERS NO ACS. + +ASWIT: PUSH C + MOV T,C + SWAB C + BIS TT,C ;CONSTRUCT OUTPUT,,INPUT AND GIVE TO SWITCH AS COMMAND. + PUSH B + MOV C,B ;NOW COMPLEMENT SOME OF C (WHAT'S IN ASWXOR). + BIC #<-1>#ASWXOR,B + BIS #ASWXOR,C + BIC B,C + POP B + MOV C,ASW + MOVB TT,ASWTAB(T) ;UPDATE OUR OWN INTERNAL TABLE. + POP C +ASWITX: RTS PC + +;RESET THE AUDEO SWITCH (ALL OUTPUTS RECEIVING SILENCE). +REASW: MOV #MAXASO-1,T + CLR TT +REASW1: JSR PC,ASWIT + DEC T + BGE REASW1 + RTS PC + +.SBTTL CHARACTER GENERATOR ROUTINES + +;CLEARS CHARACTER AT LINE EDITOR CURSOR + +CLRCHR: JSR U,ACSAV + MOVB #CANDC,CALU +CLCHR1: MOV #BLOB,T ;BLOB MASKS ENTIRE CHARACTER +CLCHR2: MOV LEPHS(U),C + MOV LECC(U),TT + JSR PC,GENCH1 + MOVB #CIOR,CALU ;RESTORE FOR DPYDP1 LOOP + BR ACRES + +;BLINK CHARACTER AT CURSOR + +XORCHR: JSR U,ACSAV + MOVB #CXOR,CALU + MOV #BLOB,T + BR CLCHR2 + +;GENERATE A CHARACTER +;CALL WITH CHARACTER IN A AND PAGE PRINTER IN U +;PRESERVES ALL ACS + +GENCHR: JSR U,ACSAV + MOV LEPHS(U),C + MOV LECC(U),TT + MOVB #CIOR,CALU + ASL A ;MAKE IT A BYTE OFFSET + MOV CTAB(A),T ;POINTS AT FONT DESCRIPTION + JSR PC,GENCH1 +ACRES: POP A + POP B + POP C + POP T + POP TT + POP U + RTS PC + +;The lowest level character generator +;Initial AC settings + +;A LSH address of EAE shift counter +;B MQ address of EAE regiseter +;C number of desired shifts +;T points into font description +;TT points into display memory +;U number of bytes per line of display memory + +;initial memory settings + +;AC 0, EAE register +;CREG CIOR,,console number, console register +;;NOTE THAT MQ=AC+2 +;THIS ROUTINE CLOBBERS -ALL- ACS + +GENCH1: MOV #LSH,A + TST C + BLT OVRLAP +EZCASE: MOV #BYTPL,U + MOV #AC,B + CLR (B)+ ;CLEAR AC + +.REPT CHRHT +.NLIST + MOVB (T)+,(B) ;5.2 ;CHARACTER RASTER LINE INTO MQ + MOV C,(A) ;3.7 ;INITIATE SHIFT + MOV (B),(TT) ;5.2 ;OUT OF MQ INTO DISPLAY MEMORY + ADD U,TT ;2.3 ;GET TO NEXT RASTER LINE +; TOTAL 16.4 MICRO-SECONDS +.LIST +.ENDR + RTS PC + +;initial settings same as EZCASE with one exception +;U -2 + +OVRLAP: MOV #BYTPL-2,U + MOV #MQ+2,B + +.REPT CHRHT +.NLIST + CLR -(B) ;3.7 ;CLEAR MQ + CLRB -(B) ;2.3 ;CLEAR HIGH ORDER OF AC + MOVB (T)+,-(B) ;5.2 ;LOAD AC WITH CHARACTER LINE + MOV C,(A) ;3.7 ;INIATE SHIFT + MOV (B)+,(TT)+ ;5.2 ;AC TO DISPLAY MEMORY + MOV (B)+,(TT) ;5.2 ;MQ TO DISPLAY MEMORY + ADD U,TT ;2.3 ;SET TO NEXT RASTER LINE + ;TOTAL 27.6 MICRO-SECONDS +.LIST +.ENDR +RTSPC: RTS PC + +;SOME LOW LEVEL GOODIES + +;CLEARS ONE RASTER LINE + +CLRRST: MOVB #CSET,CALU +CLRRS1: .REPT WRDPL + .NLIST + CLR (T)+ + .LIST + .ENDR + RTS PC + +;CLEARS ONE CHARACTER LINE + +CLRCHL: MOV #LINHT-1,TT +CLRCL0: JSR PC,CLRRST +CLRCH1: JSR PC,CLRRS1 + DEC TT + BGT CLRCH1 + RTS PC + +;CLEAR ENTIRE SCREEN + +CLRSCR: MOV #TVLO,T + JSR PC,CLRRST + MOV #NLINS-1,TT +CLRSC1: JSR PC,CLRRS1 + DEC TT + BGT CLRSC1 + RTS PC + +;COPIES ONE RASTER LINE + +CPYRST: MOVB #CSET,CALU +CPYRS1: .REPT WRDPL + .NLIST + MOV (T)+,(TT)+ + .LIST + .ENDR + RTS PC + +;COPIES ONE CHARACTER LINE + +CPYCHL: PUSH A + MOV #LINHT-1,A + JSR PC,CPYRST +CPYCH1: JSR PC,CPYRS1 + DEC A + BGT CPYCH1 + POP A + RTS PC + +.SBTTL KEYBOARD TABLES + +.MACRO KBDKEY N,PLAIN,SH,SL,SLSH,TOP +.XLIST +.=XTAB+N +.BYTE PLAIN +.=XTAB+N+100 +.BYTE SH +.=XTAB+N+200 +.BYTE SL +.=XTAB+N+300 +.BYTE SLSH +.=XTAB+N+400 +.BYTE TOP +.LIST +.ENDM + +;WHAT FOLLOWS IS THE GRAND CHARACTER CONVERSION TABLE + +;AN 8 BIT QUANTITY IS USED TO INDEX INTO THE XTAB +; 0-5 KEYBOARD KEY NUMBER +; 6 SHIFT +; 7 SHIFT LOCK +; 8 TOP (6 AND 7 GUARANTEED TO BE ZERO) + +;IF THE BYTE PICKED IS NEGATIVE, YOU HAVE STRUCK A KEY THAT DOES NOT +;HAVE AN ASCII CODE. THESE CODES ARE ASSIGNED AS FOLLOWS: + +NASCTB: NONAS1 ; 0 ILLEGAL + ESCAPE ; -1 ESCAPE + BRKCLR ; -2 BREAK + BRKCLR ; -3 CLEAR + PLSMNS ; -4 PLUS-MINUS + CRCPLS ; -5 CIRCLE-PLUS + DELTA ; -6 DELTA + GAMMA ; -7 GAMMA + BRKCLR ; -10 HELP + RTSPC ; -11 BACK -- not really used + RTSPC ; -12 NEXT -- not really used + CALL ; -13 CALL +MAXNAS==<<.-NASCTB>/2>-1 ;MAXIMUM # NON-ASCII CHARACTERS + +.EVEN + +; CHAR NORMAL SHIFT LOCK SHIFT&LOCK TOP + +XTAB: +KBDKEY 0, -2, -2, -2, -2, -2 ;BREAK +KBDKEY 1, -1, -1, -1, -1, -1 ;ESCAPE +KBDKEY 2, '1, '!, '1, '!, '! +KBDKEY 3, '2, '", '2, '", '" +KBDKEY 4, '3, '#, '3, '#, '# +KBDKEY 5, '4, '$, '4, '$, '$ +KBDKEY 6, '5, '%, '5, '%, '% +KBDKEY 7, '6, '&, '6, '&, '& +KBDKEY 10, '7, '', '7, '', '' +KBDKEY 11, '8, '(, '8, '(, '( +KBDKEY 12, '9, '), '9, '), ') +KBDKEY 13, '0, '_, '0, '_, '_ +KBDKEY 14, '-, '=, '-, '=, '= +KBDKEY 15, '@, '`, '@, '`, '` +KBDKEY 16, '^, '~, '^, '~, '~ +KBDKEY 17, 10, 10, 10, 10, 10 ;BACK SPACE +KBDKEY 20, -13, -13, -13, -13, -13 ;CALL +KBDKEY 21, -3, -3, -3, -3, -3 ;CLEAR +KBDKEY 22, 11, 11, 11, 11, 11 ;TAB +KBDKEY 23, 33, 33, 33, 33, 33 ;ALT-MODE +KBDKEY 24, 'q, 'Q, 'Q, 'Q, 4, ;and +KBDKEY 25, 'w, 'W, 'W, 'W, 37 ;or +KBDKEY 26, 'e, 'E, 'E, 'E, 22 ;intersection +KBDKEY 27, 'r, 'R, 'R, 'R, 23 ;union +KBDKEY 30, 't, 'T, 'T, 'T, 20 ;subset +KBDKEY 31, 'y, 'Y, 'Y, 'Y, 21 ;superset +KBDKEY 32, 'u, 'U, 'U, 'U, 5 ;not +KBDKEY 33, 'i, 'I, 'I, 'I, 26 ;xor +KBDKEY 34, 'o, 'O, 'O, 'O, 1 ;down arrow +KBDKEY 35, 'p, 'P, 'P, 'P, 13 ;up arrow +KBDKEY 36, '[, '{, '[, '{, '{ +KBDKEY 37, '], '}, '], '}, '} +KBDKEY 40, '\, '|, '\, '|, '| +KBDKEY 41, '/, 16, '/, 16, 16 ;infinity +KBDKEY 42, -4, -6, -4, -6, -6 ;plus-minus, delta +KBDKEY 43, -5, -7, -5, -7, -7 ;circle-plus, gamma +KBDKEY 44, 14, 14, 14, 14, 14 ;form +KBDKEY 45, 13, 13, 13, 13, 13 ;vertical tab +KBDKEY 46, 177, 177, 177, 177, 177 ;rubout +KBDKEY 47, 'a, 'A, 'A, 'A, 34 ;.leq. +KBDKEY 50, 's, 'S, 'S, 'S, 35 ;.geq +KBDKEY 51, 'd, 'D, 'D, 'D, 36 ;equivalence +KBDKEY 52, 'f, 'F, 'F, 'F, 17 ;delta (partial derivative) +KBDKEY 53, 'g, 'G, 'G, 'G, 32 ;not equals +KBDKEY 54, 'h, 'H, 'H, 'H, -10 ;HELP!!!!! +KBDKEY 55, 'j, 'J, 'J, 'J, 30 ;back arrow +KBDKEY 56, 'k, 'K, 'K, 'K, 31 ;forward arrow +KBDKEY 57, 'l, 'L, 'L, 'L, 27 ;both ways arrow +KBDKEY 60,<';>, '+,<';>, '+, '+ +KBDKEY 61, ':, '*, ':, '*, '* +KBDKEY 62, 15, 15, 15, 15, 15 ;carriage return +KBDKEY 63, 12, 12, 12, 12, 12 ;line feed +KBDKEY 64, 37, 37, 37, 37, 37 ;next, back gives ^_ +;KBDKEY 64, -12, -11, -12, -11, -11 ;next, back +KBDKEY 65, 'z, 'Z, 'Z, 'Z, 2 ;alpha +KBDKEY 66, 'x, 'X, 'X, 'X, 3 ;beta +KBDKEY 67, 'c, 'C, 'C, 'C, 6 ;epsilon +KBDKEY 70, 'v, 'V, 'V, 'V, 10 ;lambda +KBDKEY 71, 'b, 'B, 'B, 'B, 7 ;pi +KBDKEY 72, 'n, 'N, 'N, 'N, 24 ;for all +KBDKEY 73, 'm, 'M, 'M, 'M, 25 ;there exists +KBDKEY 74,<',>, '<,<',>, '<, '< +KBDKEY 75, '., '>, '., '>, '> +KBDKEY 76, '/, '?, '/, '?, '? +KBDKEY 77, 40, 40, 40, 40, 40 ;space + +.SBTTL FONT MACROS AND DEFINITION + +.IIF E FONTSW,CTAB==0 +.IF NE FONTSW +FNTORG==. + .MACRO CTBENT A + .XCREF ...'A + ...'A + .ENDM + +CTAB: .REPT 200 + .NLIST + CTBENT \.RPCNT + .LIST + .ENDR + ...200 ;THIS CHAR IS A BLOB FOR CURSORS. + +.MACRO FONT A +.NLIST +....==0 +...==1_GRIDWD + +.IRPC CHR,A +...==..._<-1> +.IF NB CHR +....==....!... +.ENDC +.ENDM + +.IF NE ...-1 +ERROR \CURCHR +.ENDC + +;...FOO==%XLIST +;.REPT ...FOO +;.LIST +;.ENDR +.BYTE .... +;.XLIST +;%XLIST=...FOO +.LIST +.ENDM + +.MACRO CDEF A +.NLIST +CURCHR==''A +CDEF1 \CURCHR +.LIST +.ENDM + +.MACRO CDEF1 A +.NLIST +.XCREF ...'A +CURCHR==A +;...FOO==%XLIST +;.REPT ...FOO +;.LIST +;.ENDR +...'A==. +;.XLIST +;%XLIST=...FOO + +.LIST +.ENDM + +.MACRO ERROR NUM +.IF1 +.ERROR ;FONT LOSSAGE NUM +.ENDC +.ENDM +.ENDC +.XLIST +.IF NE FONTSW +.IF NE FONTMS +.XCREF CURCHR,FONT,CDEF1,CDEF + +CDEF1 0 +FONT < > +FONT < > +FONT < > +FONT < *** > +FONT < *** > +FONT < *** > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF1 1 +FONT < > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT <* * *> +FONT < *** > +FONT < * > +FONT < > +FONT < > + +CDEF1 2 +FONT < > +FONT < > +FONT < > +FONT < ** *> +FONT <* * > +FONT <* * > +FONT <* * > +FONT < ** *> +FONT < > +FONT < > + +CDEF1 3 +FONT < > +FONT < > +FONT < > +FONT < *** > +FONT <* *> +FONT <**** > +FONT <* *> +FONT <**** > +FONT <* > +FONT <* > + +CDEF1 4 +FONT < > +FONT < > +FONT < > +FONT < * > +FONT < * * > +FONT <* *> +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF1 5 +FONT < > +FONT < > +FONT < > +FONT < > +FONT <*****> +FONT < *> +FONT < *> +FONT < > +FONT < > +FONT < > + +CDEF1 6 +FONT < > +FONT < > +FONT < > +FONT < ** > +FONT < * > +FONT < *** > +FONT < * > +FONT < ** > +FONT < > +FONT < > + +CDEF1 7 +FONT < > +FONT < > +FONT < > +FONT <*****> +FONT < * * > +FONT < * * > +FONT < * * > +FONT < * * > +FONT < > +FONT < > + +CDEF1 10 +FONT < > +FONT < > +FONT <* > +FONT <* > +FONT < * > +FONT < * > +FONT < * * > +FONT <* *> +FONT < > +FONT < > + +CDEF1 11 +FONT < > +FONT <* *> +FONT < * * > +FONT < * > +FONT < * * > +FONT <* *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF1 12 +FONT < > +FONT < *** > +FONT < *> +FONT < * > +FONT < * > +FONT < * * > +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF1 13 +FONT < > +FONT < * > +FONT < *** > +FONT <* * *> +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < > + +CDEF1 14 +FONT < > +FONT < * > +FONT < * > +FONT <*****> +FONT < * > +FONT < * > +FONT <*****> +FONT < > +FONT < > +FONT < > + +CDEF1 15 +FONT < > +FONT < > +FONT < *** > +FONT <* * *> +FONT <*****> +FONT <* * *> +FONT < *** > +FONT < > +FONT < > +FONT < > + +CDEF1 16 +FONT < > +FONT < > +FONT < > +FONT < * * > +FONT <* * *> +FONT <* * *> +FONT < * * > +FONT < > +FONT < > +FONT < > + +CDEF1 17 +FONT < > +FONT < ** > +FONT < * > +FONT < *> +FONT < ****> +FONT <* *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF1 20 +FONT < > +FONT < > +FONT < ****> +FONT <* > +FONT <* > +FONT <* > +FONT < ****> +FONT < > +FONT < > +FONT < > + +CDEF1 21 +FONT < > +FONT < > +FONT <**** > +FONT < *> +FONT < *> +FONT < *> +FONT <**** > +FONT < > +FONT < > +FONT < > + +CDEF1 22 +FONT < > +FONT < > +FONT < *** > +FONT <* *> +FONT <* *> +FONT <* *> +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF1 23 +FONT < > +FONT < > +FONT <* *> +FONT <* *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF1 24 +FONT < > +FONT <* *> +FONT <* *> +FONT <*****> +FONT <* *> +FONT < * * > +FONT < * * > +FONT < * > +FONT < > +FONT < > + +CDEF1 25 +FONT < > +FONT <*****> +FONT < *> +FONT < *> +FONT < ****> +FONT < *> +FONT < *> +FONT <*****> +FONT < > +FONT < > + +CDEF1 26 +FONT < > +FONT < > +FONT < *** > +FONT <** **> +FONT <* * *> +FONT <** **> +FONT < *** > +FONT < > +FONT < > +FONT < > + +CDEF1 27 +FONT < > +FONT < * > +FONT < * > +FONT <*****> +FONT < * > +FONT < * > +FONT < * > +FONT <*****> +FONT < * > +FONT < * > + +CDEF1 30 +FONT < > +FONT < > +FONT < * > +FONT < * > +FONT <*****> +FONT < * > +FONT < * > +FONT < > +FONT < > +FONT < > + +CDEF1 31 +FONT < > +FONT < > +FONT < * > +FONT < * > +FONT <*****> +FONT < * > +FONT < * > +FONT < > +FONT < > +FONT < > + +CDEF1 32 +FONT < > +FONT < *> +FONT < * > +FONT <*****> +FONT < * > +FONT <*****> +FONT < * > +FONT <* > +FONT < > +FONT < > + +CDEF1 33 +FONT < > +FONT < * > +FONT < * > +FONT < * * > +FONT <* *> +FONT < * * > +FONT < * > +FONT < * > +FONT < > +FONT < > + +CDEF1 34 +FONT < > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < *** > +FONT < > +FONT < > + +CDEF1 35 +FONT < > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < *** > +FONT < > +FONT < > + +CDEF1 36 +FONT < > +FONT < > +FONT <*****> +FONT < > +FONT <*****> +FONT < > +FONT <*****> +FONT < > +FONT < > +FONT < > + +CDEF1 37 +FONT < > +FONT < > +FONT < > +FONT <* *> +FONT < * * > +FONT < * > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF +FONT < > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < * > +FONT < > +FONT < > + +CDEF <"> +FONT < * * > +FONT < * * > +FONT < * * > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF <#> +FONT < > +FONT < > +FONT < * * > +FONT <*****> +FONT < * * > +FONT < * * > +FONT <*****> +FONT < * * > +FONT < > +FONT < > + +CDEF <$> +FONT < * > +FONT < *** > +FONT <* * *> +FONT <* * > +FONT < *** > +FONT < * *> +FONT <* * *> +FONT < *** > +FONT < * > +FONT < > + +CDEF <%> +FONT < > +FONT <*****> +FONT <** *> +FONT < * > +FONT < * > +FONT < * > +FONT <* **> +FONT <* **> +FONT < > +FONT < > + +CDEF <&> +FONT < > +FONT < * > +FONT <* * > +FONT <* * > +FONT < * > +FONT <* * *> +FONT <* * > +FONT < ** *> +FONT < > +FONT < > + +CDEF <'> +FONT < ** > +FONT < ** > +FONT <** > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF <(> +FONT < > +FONT < *> +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < *> +FONT < > +FONT < > + +CDEF <)> +FONT < > +FONT <* > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT <* > +FONT < > +FONT < > + +CDEF <*> +FONT < > +FONT < * > +FONT <* * *> +FONT < *** > +FONT < * > +FONT < *** > +FONT <* * *> +FONT < * > +FONT < > +FONT < > + +CDEF <+> +FONT < > +FONT < > +FONT < * > +FONT < * > +FONT <*****> +FONT < * > +FONT < * > +FONT < > +FONT < > +FONT < > + +CDEF <,> +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < ** > +FONT < ** > +FONT <** > +FONT < > + +CDEF <-> +FONT < > +FONT < > +FONT < > +FONT < > +FONT <*****> +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF <.> +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < ** > +FONT < ** > +FONT < > +FONT < > + +CDEF +FONT < > +FONT < > +FONT < *> +FONT < * > +FONT < * > +FONT < * > +FONT <* > +FONT < > +FONT < > +FONT < > + +CDEF 0 +FONT < > +FONT < *** > +FONT <* *> +FONT <* **> +FONT <* * *> +FONT <** *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF 1 +FONT < > +FONT < * > +FONT < ** > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < *** > +FONT < > +FONT < > + +CDEF 2 +FONT < > +FONT < *** > +FONT <* *> +FONT < *> +FONT < * > +FONT < * > +FONT < * > +FONT <*****> +FONT < > +FONT < > + +CDEF 3 +FONT < > +FONT < *** > +FONT <* *> +FONT < *> +FONT < ** > +FONT < *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF 4 +FONT < > +FONT < * > +FONT < ** > +FONT < * * > +FONT <* * > +FONT <*****> +FONT < * > +FONT < * > +FONT < > +FONT < > + +CDEF 5 +FONT < > +FONT <*****> +FONT <* > +FONT <**** > +FONT < *> +FONT < *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF 6 +FONT < > +FONT < ** > +FONT < * > +FONT <* > +FONT <**** > +FONT <* *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF 7 +FONT < > +FONT <*****> +FONT < *> +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < > + +CDEF 8 +FONT < > +FONT < *** > +FONT <* *> +FONT <* *> +FONT < *** > +FONT <* *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF 9 +FONT < > +FONT < *** > +FONT <* *> +FONT <* *> +FONT < ****> +FONT < *> +FONT < * > +FONT < ** > +FONT < > +FONT < > + +CDEF <:> +FONT < > +FONT < > +FONT < > +FONT < ** > +FONT < ** > +FONT < > +FONT < ** > +FONT < ** > +FONT < > +FONT < > + +CDEF <;> +FONT < > +FONT < > +FONT < > +FONT < ** > +FONT < ** > +FONT < > +FONT < ** > +FONT < ** > +FONT <** > +FONT < > + +CDEF1 74 +FONT < > +FONT < > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < > +FONT < > + +CDEF <=> +FONT < > +FONT < > +FONT < > +FONT <*****> +FONT < > +FONT <*****> +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF1 76 +FONT < > +FONT < > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < > +FONT < > + +CDEF +FONT < > +FONT < *** > +FONT <* *> +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < * > +FONT < > +FONT < > + +CDEF <@> +FONT < > +FONT < *** > +FONT <* *> +FONT <* ***> +FONT <* * *> +FONT <* ***> +FONT <* > +FONT < *** > +FONT < > +FONT < > + +CDEF A +FONT < > +FONT < *** > +FONT <* *> +FONT <* *> +FONT <*****> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < > +FONT < > + +CDEF B +FONT < > +FONT <**** > +FONT <* *> +FONT <* *> +FONT <**** > +FONT <* *> +FONT <* *> +FONT <**** > +FONT < > +FONT < > + +CDEF C +FONT < > +FONT < *** > +FONT <* *> +FONT <* > +FONT <* > +FONT <* > +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF D +FONT < > +FONT <**** > +FONT < * *> +FONT < * *> +FONT < * *> +FONT < * *> +FONT < * *> +FONT <**** > +FONT < > +FONT < > + +CDEF E +FONT < > +FONT <*****> +FONT <* > +FONT <* > +FONT <**** > +FONT <* > +FONT <* > +FONT <*****> +FONT < > +FONT < > + +CDEF F +FONT < > +FONT <*****> +FONT <* > +FONT <* > +FONT <**** > +FONT <* > +FONT <* > +FONT <* > +FONT < > +FONT < > + +CDEF G +FONT < > +FONT < *** > +FONT <* *> +FONT <* > +FONT <* > +FONT <* **> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF H +FONT < > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <*****> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < > +FONT < > + +CDEF I +FONT < > +FONT < *** > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < *** > +FONT < > +FONT < > + +CDEF J +FONT < > +FONT < *> +FONT < *> +FONT < *> +FONT < *> +FONT < *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF K +FONT < > +FONT <* *> +FONT <* * > +FONT <* * > +FONT <** > +FONT <* * > +FONT <* * > +FONT <* *> +FONT < > +FONT < > + +CDEF L +FONT < > +FONT <* > +FONT <* > +FONT <* > +FONT <* > +FONT <* > +FONT <* > +FONT <*****> +FONT < > +FONT < > + +CDEF M +FONT < > +FONT <* *> +FONT <** **> +FONT <* * *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < > +FONT < > + +CDEF N +FONT < > +FONT <* *> +FONT <* *> +FONT <** *> +FONT <* * *> +FONT <* **> +FONT <* *> +FONT <* *> +FONT < > +FONT < > + +CDEF O +FONT < > +FONT < *** > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF P +FONT < > +FONT <**** > +FONT <* *> +FONT <* *> +FONT <**** > +FONT <* > +FONT <* > +FONT <* > +FONT < > +FONT < > + +CDEF Q +FONT < > +FONT < *** > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* * *> +FONT <* * > +FONT < ** *> +FONT < > +FONT < > + +CDEF R +FONT < > +FONT <**** > +FONT <* *> +FONT <* *> +FONT <**** > +FONT <* * > +FONT <* * > +FONT <* *> +FONT < > +FONT < > + +CDEF S +FONT < > +FONT < *** > +FONT <* *> +FONT <* > +FONT < *** > +FONT < *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF T +FONT < > +FONT <*****> +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < > + +CDEF U +FONT < > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF V +FONT < > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < * * > +FONT < * * > +FONT < * > +FONT < > +FONT < > + +CDEF W +FONT < > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* * *> +FONT <** **> +FONT <* *> +FONT < > +FONT < > + +CDEF X +FONT < > +FONT <* *> +FONT <* *> +FONT < * * > +FONT < * > +FONT < * * > +FONT <* *> +FONT <* *> +FONT < > +FONT < > + +CDEF Y +FONT < > +FONT <* *> +FONT <* *> +FONT < * * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < > + +CDEF Z +FONT < > +FONT <*****> +FONT < *> +FONT < * > +FONT <*****> +FONT < * > +FONT <* > +FONT <*****> +FONT < > +FONT < > + +CDEF <[> +FONT < ***> +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < ***> +FONT < > + +CDEF <\> +FONT < > +FONT < > +FONT <* > +FONT < * > +FONT < * > +FONT < * > +FONT < *> +FONT < > +FONT < > +FONT < > + +CDEF <]> +FONT <*** > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT <*** > +FONT < > + +CDEF <^> +FONT < * > +FONT < * * > +FONT <* *> +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF <_> +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT <*****> + +CDEF <`> +FONT < ** > +FONT < ** > +FONT < **> +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF a +FONT < > +FONT < > +FONT < > +FONT < *** > +FONT < *> +FONT < ****> +FONT <* *> +FONT < ****> +FONT < > +FONT < > + +CDEF b +FONT < > +FONT <* > +FONT <* > +FONT <**** > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <**** > +FONT < > +FONT < > + +CDEF c +FONT < > +FONT < > +FONT < > +FONT < *** > +FONT <* *> +FONT <* > +FONT <* > +FONT < ****> +FONT < > +FONT < > + +CDEF d +FONT < > +FONT < *> +FONT < *> +FONT < ****> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < ****> +FONT < > +FONT < > + +CDEF e +FONT < > +FONT < > +FONT < > +FONT < *** > +FONT <* *> +FONT <**** > +FONT <* > +FONT < *** > +FONT < > +FONT < > + +CDEF f +FONT < > +FONT < ** > +FONT < * *> +FONT < * > +FONT <*** > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < > + +CDEF g +FONT < > +FONT < > +FONT < > +FONT < *** > +FONT <* *> +FONT <* *> +FONT <* *> +FONT < ****> +FONT < *> +FONT < *** > + +CDEF h +FONT < > +FONT <* > +FONT <* > +FONT <**** > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < > +FONT < > + +CDEF i +FONT < > +FONT < > +FONT < * > +FONT < > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < > + +CDEF j +FONT < > +FONT < > +FONT < *> +FONT < > +FONT < *> +FONT < *> +FONT < *> +FONT < *> +FONT <* *> +FONT < *** > + +CDEF k +FONT < > +FONT <* > +FONT <* > +FONT <* *> +FONT <* * > +FONT <*** > +FONT <* * > +FONT <* *> +FONT < > +FONT < > + +CDEF l +FONT < > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < > +FONT < > + +CDEF m +FONT < > +FONT < > +FONT < > +FONT <** * > +FONT <* * *> +FONT <* * *> +FONT <* * *> +FONT <* * *> +FONT < > +FONT < > + +CDEF n +FONT < > +FONT < > +FONT < > +FONT <* ** > +FONT <** *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < > +FONT < > + +CDEF o +FONT < > +FONT < > +FONT < > +FONT < *** > +FONT <* *> +FONT <* *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF p +FONT < > +FONT < > +FONT < > +FONT <**** > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <**** > +FONT <* > +FONT <* > + +CDEF q +FONT < > +FONT < > +FONT < > +FONT < *** > +FONT <* *> +FONT <* *> +FONT <* *> +FONT < ****> +FONT < *> +FONT < *> + +CDEF r +FONT < > +FONT < > +FONT < > +FONT <* ** > +FONT <** *> +FONT <* > +FONT <* > +FONT <* > +FONT < > +FONT < > + +CDEF s +FONT < > +FONT < > +FONT < > +FONT < ****> +FONT <* > +FONT < *** > +FONT < *> +FONT <**** > +FONT < > +FONT < > + +CDEF t +FONT < > +FONT < * > +FONT < * > +FONT <*****> +FONT < * > +FONT < * > +FONT < * > +FONT < **> +FONT < > +FONT < > + +CDEF u +FONT < > +FONT < > +FONT < > +FONT <* *> +FONT <* *> +FONT <* *> +FONT <* *> +FONT < *** > +FONT < > +FONT < > + +CDEF v +FONT < > +FONT < > +FONT < > +FONT <* *> +FONT <* *> +FONT <* *> +FONT < * * > +FONT < * > +FONT < > +FONT < > + +CDEF w +FONT < > +FONT < > +FONT < > +FONT <* *> +FONT <* *> +FONT <* * *> +FONT <* * *> +FONT < * * > +FONT < > +FONT < > + +CDEF x +FONT < > +FONT < > +FONT < > +FONT <* *> +FONT < * * > +FONT < * > +FONT < * * > +FONT <* *> +FONT < > +FONT < > + +CDEF y +FONT < > +FONT < > +FONT < > +FONT <* *> +FONT <* *> +FONT <* *> +FONT < * * > +FONT < * > +FONT < * > +FONT <* > + +CDEF z +FONT < > +FONT < > +FONT < > +FONT <*****> +FONT < * > +FONT < *** > +FONT < * > +FONT <*****> +FONT < > +FONT < > + +CDEF1 173 +FONT < *> +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < *> +FONT < > + +CDEF1 174 +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > + +CDEF1 175 +FONT <* > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT <* > +FONT < > + +CDEF1 176 +FONT < ** *> +FONT <* ** > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > +FONT < > + +CDEF1 177 +FONT < * > +FONT < * *> +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT < * > +FONT <* * > +FONT < * > +FONT < > + +CDEF1 200 ;BLOB CHARACTER FOR CURSORS +FONT <*****> +FONT <*****> +FONT <*****> +FONT <*****> +FONT <*****> +FONT <*****> +FONT <*****> +FONT <*****> +FONT <*****> +FONT <*****> + +.ENDC ;.IF NE FONTMS + +.IF E FONTMS +...0==. +.BYTE 000,000,000,016,016,016,000,000,000,000 +...1==. +.BYTE 000,004,004,004,004,025,016,004,000,000 +...2==. +.BYTE 000,000,000,015,022,022,022,015,000,000 +...3==. +.BYTE 000,000,000,016,021,036,021,036,020,020 +...4==. +.BYTE 000,000,000,004,012,021,000,000,000,000 +...5==. +.BYTE 000,000,000,000,037,001,001,000,000,000 +...6==. +.BYTE 000,000,000,006,010,016,010,006,000,000 +...7==. +.BYTE 000,000,000,037,012,012,012,012,000,000 +...10==. +.BYTE 000,000,020,020,010,004,012,021,000,000 +...11==. +.BYTE 000,021,012,004,012,021,021,016,000,000 +...12==. +.BYTE 000,016,001,002,004,012,021,016,000,000 +...13==. +.BYTE 000,004,016,025,004,004,004,004,000,000 +...14==. +.BYTE 000,004,004,037,004,004,037,000,000,000 +...15==. +.BYTE 000,000,016,025,037,025,016,000,000,000 +...16==. +.BYTE 000,000,000,012,025,025,012,000,000,000 +...17==. +.BYTE 000,014,002,001,017,021,021,016,000,000 +...20==. +.BYTE 000,000,017,020,020,020,017,000,000,000 +...21==. +.BYTE 000,000,036,001,001,001,036,000,000,000 +...22==. +.BYTE 000,000,016,021,021,021,000,000,000,000 +...23==. +.BYTE 000,000,021,021,021,016,000,000,000,000 +...24==. +.BYTE 000,021,021,037,021,012,012,004,000,000 +...25==. +.BYTE 000,037,001,001,017,001,001,037,000,000 +...26==. +.BYTE 000,000,016,033,025,033,016,000,000,000 +...27==. +.BYTE 000,004,002,037,002,004,010,037,010,004 +...30==. +.BYTE 000,000,004,010,037,010,004,000,000,000 +...31==. +.BYTE 000,000,004,002,037,002,004,000,000,000 +...32==. +.BYTE 000,001,002,037,004,037,010,020,000,000 +...33==. +.BYTE 000,004,004,012,021,012,004,004,000,000 +...34==. +.BYTE 000,002,004,010,004,002,000,016,000,000 +...35==. +.BYTE 000,010,004,002,004,010,000,016,000,000 +...36==. +.BYTE 000,000,037,000,037,000,037,000,000,000 +...37==. +.BYTE 000,000,000,021,012,004,000,000,000,000 +...40==. +.BYTE 000,000,000,000,000,000,000,000,000,000 +...41==. +.BYTE 000,004,004,004,004,004,000,004,000,000 +...42==. +.BYTE 012,012,012,000,000,000,000,000,000,000 +...43==. +.BYTE 000,000,012,037,012,012,037,012,000,000 +...44==. +.BYTE 004,016,025,024,016,005,025,016,004,000 +...45==. +.BYTE 000,037,031,002,004,010,023,023,000,000 +...46==. +.BYTE 000,010,024,024,010,025,022,015,000,000 +...47==. +.BYTE 014,014,030,000,000,000,000,000,000,000 +...50==. +.BYTE 000,001,002,004,004,004,002,001,000,000 +...51==. +.BYTE 000,020,010,004,004,004,010,020,000,000 +...52==. +.BYTE 000,004,025,016,004,016,025,004,000,000 +...53==. +.BYTE 000,000,004,004,037,004,004,000,000,000 +...54==. +.BYTE 000,000,000,000,000,000,014,014,030,000 +...55==. +.BYTE 000,000,000,000,037,000,000,000,000,000 +...56==. +.BYTE 000,000,000,000,000,000,014,014,000,000 +...57==. +.BYTE 000,000,001,002,004,010,020,000,000,000 +...60==. +.BYTE 000,016,021,023,025,031,021,016,000,000 +...61==. +.BYTE 000,004,014,004,004,004,004,016,000,000 +...62==. +.BYTE 000,016,021,001,002,004,010,037,000,000 +...63==. +.BYTE 000,016,021,001,006,001,021,016,000,000 +...64==. +.BYTE 000,002,006,012,022,037,002,002,000,000 +...65==. +.BYTE 000,037,020,036,001,001,021,016,000,000 +...66==. +.BYTE 000,006,010,020,036,021,021,016,000,000 +...67==. +.BYTE 000,037,001,002,002,004,004,004,000,000 +...70==. +.BYTE 000,016,021,021,016,021,021,016,000,000 +...71==. +.BYTE 000,016,021,021,017,001,002,014,000,000 +...72==. +.BYTE 000,000,000,014,014,000,014,014,000,000 +...73==. +.BYTE 000,000,000,014,014,000,014,014,030,000 +...74==. +.BYTE 000,000,002,004,010,004,002,000,000,000 +...75==. +.BYTE 000,000,000,037,000,037,000,000,000,000 +...76==. +.BYTE 000,000,010,004,002,004,010,000,000,000 +...77==. +.BYTE 000,016,021,002,004,004,000,004,000,000 +...100==. +.BYTE 000,016,021,027,025,027,020,016,000,000 +...101==. +.BYTE 000,016,021,021,037,021,021,021,000,000 +...102==. +.BYTE 000,036,021,021,036,021,021,036,000,000 +...103==. +.BYTE 000,016,021,020,020,020,021,016,000,000 +...104==. +.BYTE 000,036,011,011,011,011,011,036,000,000 +...105==. +.BYTE 000,037,020,020,036,020,020,037,000,000 +...106==. +.BYTE 000,037,020,020,036,020,020,020,000,000 +...107==. +.BYTE 000,016,021,020,020,023,021,016,000,000 +...110==. +.BYTE 000,021,021,021,037,021,021,021,000,000 +...111==. +.BYTE 000,016,004,004,004,004,004,016,000,000 +...112==. +.BYTE 000,001,001,001,001,001,021,016,000,000 +...113==. +.BYTE 000,021,022,024,030,024,022,021,000,000 +...114==. +.BYTE 000,020,020,020,020,020,020,037,000,000 +...115==. +.BYTE 000,021,033,025,021,021,021,021,000,000 +...116==. +.BYTE 000,021,021,031,025,023,021,021,000,000 +...117==. +.BYTE 000,016,021,021,021,021,021,016,000,000 +...120==. +.BYTE 000,036,021,021,036,020,020,020,000,000 +...121==. +.BYTE 000,016,021,021,021,025,022,015,000,000 +...122==. +.BYTE 000,036,021,021,036,024,022,021,000,000 +...123==. +.BYTE 000,016,021,020,016,001,021,016,000,000 +...124==. +.BYTE 000,037,004,004,004,004,004,004,000,000 +...125==. +.BYTE 000,021,021,021,021,021,021,016,000,000 +...126==. +.BYTE 000,021,021,021,021,012,012,004,000,000 +...127==. +.BYTE 000,021,021,021,021,025,033,021,000,000 +...130==. +.BYTE 000,021,021,012,004,012,021,021,000,000 +...131==. +.BYTE 000,021,021,012,004,004,004,004,000,000 +...132==. +.BYTE 000,037,001,002,037,010,020,037,000,000 +...133==. +.BYTE 007,004,004,004,004,004,004,004,007,000 +...134==. +.BYTE 000,000,020,010,004,002,001,000,000,000 +...135==. +.BYTE 034,004,004,004,004,004,004,004,034,000 +...136==. +.BYTE 004,012,021,000,000,000,000,000,000,000 +...137==. +.BYTE 000,000,000,000,000,000,000,000,000,037 +...140==. +.BYTE 006,006,003,000,000,000,000,000,000,000 +...141==. +.BYTE 000,000,000,016,001,017,021,017,000,000 +...142==. +.BYTE 000,020,020,036,021,021,021,036,000,000 +...143==. +.BYTE 000,000,000,016,021,020,020,017,000,000 +...144==. +.BYTE 000,001,001,017,021,021,021,017,000,000 +...145==. +.BYTE 000,000,000,016,021,036,020,016,000,000 +...146==. +.BYTE 000,006,011,010,034,010,010,010,000,000 +...147==. +.BYTE 000,000,000,016,021,021,021,017,001,016 +...150==. +.BYTE 000,020,020,036,021,021,021,021,000,000 +...151==. +.BYTE 000,000,004,000,004,004,004,004,000,000 +...152==. +.BYTE 000,000,001,000,001,001,001,001,021,016 +...153==. +.BYTE 000,020,020,021,022,034,022,021,000,000 +...154==. +.BYTE 000,004,004,004,004,004,004,004,000,000 +...155==. +.BYTE 000,000,000,032,025,025,025,025,000,000 +...156==. +.BYTE 000,000,000,026,031,021,021,021,000,000 +...157==. +.BYTE 000,000,000,016,021,021,021,016,000,000 +...160==. +.BYTE 000,000,000,036,021,021,021,036,020,020 +...161==. +.BYTE 000,000,000,016,021,021,021,017,001,001 +...162==. +.BYTE 000,000,000,026,031,020,020,020,000,000 +...163==. +.BYTE 000,000,000,017,020,016,001,036,000,000 +...164==. +.BYTE 000,004,004,037,004,004,004,003,000,000 +...165==. +.BYTE 000,000,000,021,021,021,021,016,000,000 +...166==. +.BYTE 000,000,000,021,021,021,012,004,000,000 +...167==. +.BYTE 000,000,000,021,021,025,025,012,000,000 +...170==. +.BYTE 000,000,000,021,012,004,012,021,000,000 +...171==. +.BYTE 000,000,000,021,021,021,012,004,010,020 +...172==. +.BYTE 000,000,000,037,002,016,010,037,000,000 +...173==. +.BYTE 001,002,002,002,004,002,002,002,001,000 +...174==. +.BYTE 004,004,004,004,004,004,004,004,004,004 +...175==. +.BYTE 020,010,010,010,004,010,010,010,020,000 +...176==. +.BYTE 015,026,000,000,000,000,000,000,000,000 +...177==. +.BYTE 002,005,004,004,004,004,004,024,010,000 +...200==. +.BYTE 037,037,037,037,037,037,037,037,037,037 +.ENDC ;.IF E FONTMS +.LIST + +BLOB=...200 ;BLOB IS THE CHAR THAT COVERS ENTIRE CHARACTER AREA. + +.IIF E FONTSW,.=.+3000 ;APPROXIMATE SIZE OF FONT + +REPORT FONT SIZE=,\.-FNTORG +FNTEND==. +.NLIST +.ENDC ;.IF NE FONTSW +.LIST + +.SBTTL LINE EDITOR AND PAGE PRINTER VARIABLES +VARORG==. + +.MACRO ...TEN +.=<.+3>&<-4> +.ENDM + +;LINE EDITOR VARIABLE BLOCK FORMAT: +;THIS DOESN'T REALLY HAVE ANYTHING TO WITH LINE-EDITING. THIS BLOCK +;CONTAINS MOST OF THE VARIABLES FOR EACH TV-CHANNEL (OR VIRTUAL TTY), +;COMBINING THE OLD IDEAS OF DPY BUFFER, LINE EDITOR, AND PAGE PRINTER. +;THERE IS ALSO A TV-BUFFER NUMBER, WHICH GOES IN THE CREG, AND INDEXES +;SOME ARRAYS ON THE LAST PAGE, A DPY CHANNEL # WHICH = A PDP10 TTY # MINUS NF11TY +;AND INDEXES SOME 11-10 SHARED ARRAYS, AND A KBD# WHICH IS A HARDWARE KEYBOARD +;NUMBER AND INDEXES SOME ARRAYS ON THE LAST PAGE. + +LEDFLT: .OFFSET -. +;FIRST COMES THE 10-TO-11 DPY OUTPUT BUFFER. NOTE THAT THE "DEFAULT VALUES +;FOR THIS PART ARE NOT USED IN INITIALIZATION. +DPY10B:: .=.+2 ;WORD PDP-10 IS HACKING (USED FOR INITIALIZATION ONLY) +DPY11B:: .=.+2 ;WORD PDP-11 IS HACKING +DPYFS1:: .=.+2 ;WASTED WORD. +DPYLGL:: .=.+2 ;HIGHEST LEGAL BUFFER CELL +DPYSIZ:: .=.+2 ;SIZE OF DATA AREA +DPYFS:: .=.+2 ;NOT USED +...TEN +DPDATA:: .BLKB DPSIZE ;DATA AREA OF BUFFER. + +LECC:: TVLO ;ADDRESS OF CURSOR +LEPHS:: 20-CHRWD ;PHASE OF CURSOR +LEX:: -BITPL ;X POSITON OF LE CURSOR +LECREG:: .BYTE -1 ;CONSOLE REGISTER FOR THIS LE DISPLAY + .BYTE 0 ;UNUSED +...TEN + +LEZER0:: 0 ;FAKE LINE BUFFER HEADER (SENT TO PDP10 IN RESPONSE TO ECOFLG) +LEZER1:: 0 +LEBUF:: 0 ;CURRENT TEXT BUFFER +LELIST:: 0 ;KEYBOARD BUFFER CHAIN +LECHN:: -1 ;DPY CHANNEL NUMBER, SET UP AT INIT TIME. +LEKBD:: -1 ;KEYBOARD DRIVING THIS LINE EDITOR +LEY:: -NLINS ;Y COORDINATE OF LINE EDITOR DISPLAY +LELCC:: TVLO ;ADDRESS OF START OF CURRENT CHARACTER LINE, IN VIDEO BUFFER. +;LEFONT:: CTAB ;FONT FOR WRITING WITH IN THIS L.E. (NOT USED) +LECPC:: 0 ;COROUTINE PC SAVED BY GETCHC. +LESVB:: 0 ;VALUE OF B SAVED OVER CALL TO GETCHC. +LEFREE:: LBCHRS ;FREE CHARACTER COUNT +LECHR:: 0 ;POINTS AT FREE CHARACTER IN BUFFER +;LEBLNK:: 0 ;LINE EDITOR BLINKER (NOT USED, THERE IS NO LINE EDITOR) +LERPT:: 0 ;0 NORMAL, -1 => INDEFINITE REPEAT, ELSE REPEAT COUNT. + ;REPEAT REFERS TO REPEAT-ACTION ON AN INPUT CHARACTER. +LELSTA:: 0 ;A AND B AT MOST RECENT CALL TO PUTCHR. +LELSTB:: 0 ;FOR THE SAKE OF REPEAT-ACTION ON INPUT. +...TEN +LELEN:: .OFFSET 0 + +;LINE EDITOR VARIABLE AREAS. + +TENWRD +;HERE WE ASSEMBLE IN THE "DPY BUFFERS". +LEUVAR: .REPT MAXTV + .+DPDATA + .-2+DPDATA + 0 + .-6+DPDATA+DPSIZE-2 + DPSIZE + 0 + .BLKB LELEN-DPDATA + .ENDR +LEUEND==. + +;THE WHO-LINE LINE EDITOR IS DIFFERENT AND APART FROM ALL THE REST + +WHOPP: .=.+LELEN + +;CLOCK QUEUE ENTRY + + .OFFSET -. ;CLOCK QUEUE ENTRY +CQNEXT:: .=.+2 ;CDR OF QUEUE +CQTIME:: .=.+2 ;HIGH ORDER OF TIME +CQTIM1:: .=.+2 ;LOW ORDER +CQROUT:: .=.+2 ;ROUTINE TO CALL AT CLOCK LEVEL +CQARG:: .=.+2 ;ARGUMENT FOR CLOCK LEVEL ROUTINE +CQLEN:: .OFFSET 0 + + + + .OFFSET -. ;LINE BUFFER HEADER AREA + ;DON'T ADD NEW VARS WITHOUT CHANGING PDP10 CODE + ;IN TT11IN. +LHFLAG:: .=.+2 ;0=>FREE, POS=>BUSY, NEG=>ACTIVE. +LHZERO:: .=.+2 ;BETTER BE ZERO SO THAT PDP-10 CAN TEST LHFLAG +LHNEXT:: .=.+2 ;NEXT BUFFER ON RING OF TWO FOR THIS TTY +LHALST:: .=.+2 ;NEXT BUFFER ON LIST OF ACTIVE BUFFERS. +LHCHN:: .=.+2 ;PDP-10 LINE NUMBER (TTY NUMBER MINUS NF11TY). +LHFS:: .=.+2 ;CHAINS FREE STORAGE BLOCKS +LHQUED:: .=.+2 ;NON-ZERO => THIS BUFFER CLOCK QUEUED FOR ACTIVATION (SEE QBFR) +...TEN +LHLEN:: .OFFSET 0 + + .OFFSET -. ;BLINKER VARIABLES +BLNEXT:: 0 ;NEXT BLINKER ON LIST +BLCURS:: 0 ;POINTS AT CURSOR VARIABLES +BLON:: .BYTE 0 ;PHASE; 0=INVISIBLE, 377=VISIBLE +BLCHAR:: .BYTE 177 ;UNUSED +BLLEN:: .OFFSET 0 + +BLKVAR: .=.+ + .EVEN + + .OFFSET -. ;USER WHO LINE +WHJOB:: .=.+2 ;job # +WHJOB1:: .=.+2 ;if negative then clear who line +WHMODE:: .=.+2 ;mode + ;-1=>who line is off + ; 0=>follow keyboard + ; 1=>freeze + ; 2=>next higher (when PDP-10 sees this state, it searches + ; user variables for next higher job index number with same + ; uname. When it finds it, it stores the number in job # + ; and changes mode to 1 + ; 3=>next lower + ;any other=>system who line +WHMOD1:: .=.+2 ;pads WHMODE +WHUNAM:: .=.+2 ;uname in sixbit (left 18 bits in first two words, right in next two) +WHUNM1:: .=.+2 +WHUNM2:: .=.+2 +WHUNM3:: .=.+2 +WHJNAM:: .=.+2 ;jname in sixbit +WHJNM1:: .=.+2 +WHJNM2:: .=.+2 +WHJNM3:: .=.+2 +WHSNAM:: .=.+2 ;sname in sixbit +WHSNM1:: .=.+2 +WHSNM2:: .=.+2 +WHSNM3:: .=.+2 +WHSTAT:: .=.+2 ;status in sixbit, 0=>job does not exist +WHSTA1:: .=.+2 +WHSTA2:: .=.+2 +WHSTA3:: .=.+2 +WHJ%RT:: .=.+2 ;job % run time +WHJTRT:: .=.+2 ;job total run time (in tenth's of seconds) +WHRPAG:: .=.+2 ;job real pages (swapped in) +WHTPAG:: .=.+2 ;job total pages +WHO1:: .=.+2 ;user who mode control word +WHO1A:: .=.+2 +WHO2:: .=.+2 ;first user who line var +WHO2A:: .=.+2 +WHO2B:: .=.+2 +WHO2C:: .=.+2 +WHO3:: .=.+2 ;second user who line var +WHO3A:: .=.+2 +WHO3B:: .=.+2 +WHO3C:: .=.+2 +...TEN + .=.+30 ;EXTRA SPACE SO NEW HACKS CAN SAFELY BE PUT IN PDP10. +WHLEN:: .OFFSET 0 + +;USER WHO LINE VARIABLES + +TENWRD + +WHVARS: .=.+ + +.SBTTL MISCELLANEOUS TABLES +MISORG==. + +;KEYBOARD/VIDEO SWITCH DEFAULTS +;INDEXED BY KBD #, GIVES NEAREST VIDEO SWITCH OUTPUT, -1=>NO DEFAULT + +KBDVSW: .BYTE 0 ; 0 809 FAHLMAN, HOLLOWAY, KNIGHT + .BYTE 23 ; 1 810 LAVIN, KUIPERS, MILLER + .BYTE 24 ; 2 919 Very Small Data Bases NORTH (FAR END) + .BYTE 20 ; 3 812 YVONNE + .BYTE 6 ; 4 813 HEWITT + .BYTE 7 ; 5 814 SUSSMAN + .BYTE 3 ; 6 808 FREILING, ULLMAN + .BYTE -1 ; 7 + .BYTE 4 ;10 817 JABARI + .BYTE -1 ;11 + .BYTE -1 ;12 + .BYTE 10 ;13 819 GOLDSTEIN + .BYTE 1 ;14 820 MINSKY + .BYTE -1 ;15 + .BYTE -1 ;16 + .BYTE 11 ;17 821A MARR + .BYTE -1 ;20 + .BYTE 2 ;21 824 RICH, DEKLEER + .BYTE 5 ;22 825 Sjoberg + .BYTE 26 ;23 826 Fredkin + .BYTE 31 ;24 815 Horn + .BYTE -1 ;25 + .BYTE -1 ;26 + .BYTE -1 ;27 + .BYTE 15 ;30 925 MOON'S REFRIGERATOR + .BYTE 16 ;31 902 TAENZER, MASON + .BYTE 17 ;32 919 Very Small Data losers + .BYTE 14 ;33 334 EDWARDS, LEBEL + .BYTE 13 ;34 913 BAISLEY, GREENBLATT + .BYTE 12 ;35 914 COHEN, GOSPER, ETC. + .BYTE 21 ;36 912 9TH FLOOR LOUNGE + .BYTE 22 ;37 907 CHESS, LISP MACHINES + .BYTE -1 ;40 906 Lisp Machines + .BYTE 37 ;41 3rd Floor #1 + .BYTE 36 ;42 3rd Floor #2 + .BYTE 35 ;43 3rd Floor #3 + .BYTE 34 ;44 3rd Floor #4 + .BYTE 33 ;45 3rd Floor #5 + .BYTE 30 ;46 3rd Floor #6 + .BYTE -1 ;47 NOT CONNECTED + .BYTE -1 ;50 NOT CONNECTED + .BYTE -1 ;51 NOT CONNECTED + .BYTE -1 ;52 NOT CONNECTED + .BYTE -1 ;53 NOT CONNECTED + .BYTE -1 ;54 NOT CONNECTED + .BYTE -1 ;55 NOT CONNECTED + .BYTE -1 ;56 NOT CONNECTED + .BYTE -1 ;57 NOT CONNECTED + .BYTE -1 ;60 NOT CONNECTED + .BYTE -1 ;61 NOT CONNECTED + .BYTE -1 ;62 NOT CONNECTED + .BYTE -1 ;63 NOT CONNECTED + .BYTE -1 ;64 NOT CONNECTED + .BYTE -1 ;65 NOT CONNECTED + .BYTE -1 ;66 NOT CONNECTED + .BYTE -1 ;67 NOT CONNECTED + .BYTE -1 ;70 NOT CONNECTED + .BYTE -1 ;71 NOT CONNECTED + .BYTE -1 ;72 NOT CONNECTED + .BYTE -1 ;73 NOT CONNECTED + .BYTE -1 ;74 NOT CONNECTED + .BYTE -1 ;75 NOT CONNECTED + .BYTE -1 ;76 NOT CONNECTED + .BYTE -1 ;77 NOT CONNECTED +CHECK KBDVSW,MAXKBD + + +;THIS TABLE SAYS WHICH FLOOR TO CALL THE ELEVATOR TO FOR E + +ELETAB: .BYTE ELKMS8 ; 0 809 FAHLMAN, HOLLOWAY, KNIGHT + .BYTE ELKMS8 ; 1 810 LAVIN, KUIPERS, MILLER + .BYTE ELKMS9 ; 2 919 Very Small Data Bases NORTH (FAR END) + .BYTE ELKMS8 ; 3 812 YVONNE + .BYTE ELKMS8 ; 4 813 HEWITT + .BYTE ELKMS8 ; 5 814 SUSSMAN + .BYTE ELKMS8 ; 6 808 FREILING, ULLMAN + .BYTE 0 ; 7 + .BYTE ELKMS8 ;10 817 JABARI + .BYTE 0 ;11 + .BYTE 0 ;12 + .BYTE ELKMS8 ;13 819 GOLDSTEIN + .BYTE ELKMS8 ;14 820 MINSKY + .BYTE 0 ;15 + .BYTE 0 ;16 + .BYTE ELKMS8 ;17 821A MARR + .BYTE 0 ;20 + .BYTE ELKMS8 ;21 824 RICH, DEKLEER + .BYTE ELKMS8 ;22 825 Sjoberg + .BYTE ELKMS8 ;23 826 Fredkin + .BYTE ELKMS8 ;24 815 Horn + .BYTE 0 ;25 + .BYTE 0 ;26 + .BYTE 0 ;27 + .BYTE ELKMS9 ;30 925 MOON'S REFRIGERATOR + .BYTE ELKMS9 ;31 902 TAENZER, MASON + .BYTE ELKMS9 ;32 919 Very Small Data losers + .BYTE 0 ;33 334 EDWARDS, LEBEL + .BYTE ELKMS9 ;34 913 BAISLEY, GREENBLATT + .BYTE ELKMS9 ;35 914 COHEN, GOSPER, ETC. + .BYTE ELKMS9 ;36 912 9TH FLOOR LOUNGE + .BYTE ELKMS9 ;37 907 CHESS, LISP MACHINES + .BYTE ELKMS9 ;40 906 Lisp Machines + .BYTE 0 ;41 NOT CONNECTED + .BYTE 0 ;42 NOT CONNECTED + .BYTE 0 ;43 NOT CONNECTED + .BYTE 0 ;44 NOT CONNECTED + .BYTE 0 ;45 NOT CONNECTED + .BYTE 0 ;46 NOT CONNECTED + .BYTE 0 ;47 NOT CONNECTED + .BYTE 0 ;50 NOT CONNECTED + .BYTE 0 ;51 NOT CONNECTED + .BYTE 0 ;52 NOT CONNECTED + .BYTE 0 ;53 NOT CONNECTED + .BYTE 0 ;54 NOT CONNECTED + .BYTE 0 ;55 NOT CONNECTED + .BYTE 0 ;56 NOT CONNECTED + .BYTE 0 ;57 NOT CONNECTED + .BYTE 0 ;60 NOT CONNECTED + .BYTE 0 ;61 NOT CONNECTED + .BYTE 0 ;62 NOT CONNECTED + .BYTE 0 ;63 NOT CONNECTED + .BYTE 0 ;64 NOT CONNECTED + .BYTE 0 ;65 NOT CONNECTED + .BYTE 0 ;66 NOT CONNECTED + .BYTE 0 ;67 NOT CONNECTED + .BYTE 0 ;70 NOT CONNECTED + .BYTE 0 ;71 NOT CONNECTED + .BYTE 0 ;72 NOT CONNECTED + .BYTE 0 ;73 NOT CONNECTED + .BYTE 0 ;74 NOT CONNECTED + .BYTE 0 ;75 NOT CONNECTED + .BYTE 0 ;76 NOT CONNECTED + .BYTE 0 ;77 NOT CONNECTED +CHECK ELETAB,MAXKBD + +;CHCREG TABLE, INDEXED BY CHANNEL NUMBER, GIVES TV BUFFER NUMBER. +;NON-WORKING TV BUFFERS SHOULD NOT BE IN THE LIST. +;IF THERE ARE MORE CHANNELS THAN BUFFERS, PUT -1 IN FOR SOME CHANNELS. + +CHCREG: .BYTE 0,1,4,5,6,7,10,11,12,13,14,15,16,17,-1,-1 + + +;VIDEO SWITCH INPUT INDEXED BY DPY #, HIGH ORDER BYTE GIVES SWITCH SECTION + +DPYVSW: 1 ; 0 + 2 ; 1 + 3 ; 2 + 4 ; 3 + 5 ; 4 + 6 ; 5 + 7 ; 6 + 10 ; 7 + 21 ;10 THESE INPUTS ARE IN SECOND SECTION + 22 ;11 + 23 ;12 + 24 ;13 + 11 ;14 1ST SECTION AGAIN + 12 ;15 + 13 ;16 + 14 ;17 +CHECK DPYVSW,MAXTV*2 + +;AUDIO SWITCH TABLES (INDEXED BY KBD #, GIVES AUDIO SWITCH OUTPUT #) + +KBDASW: .BYTE 00 ; 0 + .BYTE 01 ; 1 + .BYTE 02 ; 2 + .BYTE 03 ; 3 + .BYTE 04 ; 4 + .BYTE 05 ; 5 + .BYTE 06 ; 6 + .BYTE 07 ; 7 + .BYTE 10 ;10 + .BYTE 11 ;11 + .BYTE 12 ;12 + .BYTE 13 ;13 + .BYTE 14 ;14 + .BYTE 15 ;15 + .BYTE 16 ;16 + .BYTE 17 ;17 + .BYTE 20 ;20 + .BYTE 21 ;21 + .BYTE 22 ;22 + .BYTE 23 ;23 + .BYTE 24 ;24 + .BYTE 25 ;25 + .BYTE 26 ;26 + .BYTE 27 ;27 + .BYTE 30 ;30 + .BYTE 31 ;31 + .BYTE 32 ;32 + .BYTE 33 ;33 + .BYTE 34 ;34 + .BYTE 35 ;35 + .BYTE 36 ;36 + .BYTE 37 ;37 + .BYTE -1 ;40 + .BYTE -1 ;41 + .BYTE -1 ;42 + .BYTE -1 ;43 + .BYTE -1 ;44 + .BYTE -1 ;45 + .BYTE -1 ;46 + .BYTE -1 ;47 + .BYTE -1 ;50 + .BYTE -1 ;51 + .BYTE -1 ;52 + .BYTE -1 ;53 + .BYTE -1 ;54 + .BYTE -1 ;55 + .BYTE -1 ;56 + .BYTE -1 ;57 + .BYTE -1 ;60 + .BYTE -1 ;61 + .BYTE -1 ;62 + .BYTE -1 ;63 + .BYTE -1 ;64 + .BYTE -1 ;65 + .BYTE -1 ;66 + .BYTE -1 ;67 + .BYTE -1 ;70 + .BYTE -1 ;71 + .BYTE -1 ;72 + .BYTE -1 ;73 + .BYTE -1 ;74 + .BYTE -1 ;75 + .BYTE -1 ;76 + .BYTE -1 ;77 +CHECK KBDASW,MAXKBD + +;POINTER AREA + +TENWRD + +POINTA: ITSWHO + CMDFLG +TENWHO: 0 ;-1=>PDP-10 SHOULD UPDATE WHO LINES +TENWH1: 0 ;FILLS OUT TENWHO + MAXTV ;PUT # OF PDP-10 CHANNELS HERE FOR ITS. + 0 +NF11TY: 0 ;PDP-10 PUTS TTY # OF FIRST CHANNEL HERE. + 0 +QPYDWN: 0 ;THIS NEEDS TO BE READ BY THE 10 FOR LOCK TVQPY CMD. + 0 +.=.+10 ;LEAVE A LITTLE ROOM FOR GROWTH + +;10/11 CHANNEL HEADER AREA + +TENWRD + +CHA==. +KBDFLG: 0 ;KEYBOARD ACTIVATED LIST (SET BY 11 CLEARED BY 10) + 0 ;ALWAYS ZERO +DPYCHN: LEUVAR ;THE CHANNEL VARS BLOCK ADDR +DPYKBD: 0 ;.BYTE KBD #,DPY #, OR -1 FOR FREE CHANNEL. +.REPT MAXTV-1 + LEUVAR+<<.RPCNT+1>*LELEN> + 0 +.ENDR +ECOFLG: 0 +CHNCLS: 0 ;FLAGS DPY CHANNEL AS OPEN (SET TO -1 BY TEN) + .=.+<*4> +WHOLIN: 0 ;POINTS TO WHO LINE VARIABLES FOR THIS CHANNEL + 0 ;NOT USED + .=.+<*4> + +;PDP-10/PDP-10 COMMAND BUFFER + +TENWRD + +CMDFLG: 0 ;0=>TEN CAN WRITE, POSITIVE=>ELEVEN CAN WRITE, NEGATVE=>TEN WON + 0 ;FULL PDP-10 WORD BOUNDARY +CMDBUF: .=.+ ;EACH ARG IN COMMAND BUFFER IS PDP-10 WORD + +;SYSTEM WHO LINE + +TENWRD + +ITSWHO==. +ITSTDP: 0 ;# total # dpy's (read only for PDP-10) +ITSFDP: 0 ;# free dpys (read only for PDP-10) +ITSVER: 0 ;ITS version # +ITSJOB: 0 ;total jobs +ITSCOR: 0 ;total core +ITSRU: 0 ;runnable users +ITSWBJ: 0 ;# jobs swap blocked +ITSJWP: 0 ;# jobs waiting for pages +ITSTRC: 0 ;total runable core +ITSCFU: 0 ;core available for users +ITSDAT: 0 ;date [byte (7) year (4) month (5) day] +ITSDBG: 0 ;system debug flag +ITSTIM: 0 ;time of day (# half seconds since midnight) aligned on PDP-10 word +ITSTI1: 0 ;low order of time +ITSUSR: 0 ;total number of users +ITSFSH: 0 ;fair share in % + +.SBTTL MISCELLANEOUS VARIABLES AND FREE STORAGE + +;CHANNEL USE FLAGS NON-ZERO MEANS CHANNEL IN USE +CHNUSE: .BLKB MAXTV ;BYTES INDEXED BY DPY CHANNEL # + .EVEN + + +;BLINKERS. INDEXED BY TV-BUFFER # (CREG) +BLINKS: .BLKW MAXTV ;ADDRESS OF 1ST BLINKER OF THIS TV'S BLINKER LIST. + +BLKSWT: .BLKB MAXTV ;NONZERO => DON'T DO ANY BLINKING ON THIS TV NOW. + .EVEN + +;BELLS PENDING COUNTS. INDEXED BY TV-BUFFER # +BELCNT: .BLKW MAXTV + + +;PER-KEYBOARD INFORMATION. INDEXED BY KBD#. +KBDLE: .BLKW MAXKBD ;KEYBOARD/LINE EDITOR ASSOCIATION + +KBDESC: .BYTE 0 ;NON-ZERO => KEY HAS BEEN TYPED, READING ARG +KBDARG: .BYTE 0 ;NUMERIC ARGUMENT FOR + .=.+<*2> ;THE ABOVE TWO BYTE ARRAYS ARE INTERLEAVED. + + 0 ;THIS ZERO WORD NEEDED - SEE CLKBR5 +KBDDEF: .BYTE 0 ;DEFAULT VIDEO SOURCE FOR THIS KBD WHEN LOOKING AT ANOTHER +KBDCNT: .BYTE 0 ;COUNTDOWN UNTIL RESET TO DEFAULT VIDEO SOURCE, OR -1 + .=.+<*2> + + +;CLOCK QUEUE + +CLOCKF: 0 ;CLOCK QUEUE FREE LIST +CLOCKQ: 0 ;FIRST ENTRY ON CLOCK QUEUE +CQUEUE: .=.+ + +;MISCELLANEOUS VARIBLES + +FSP: 0 ;POINTS TO LEBUFS FREE SPACE +OLDKMA: 0 ;LAST KMA +BLINK: 0 ;TV-BUFFER # OF NEXT GUY TO BLINK. ALSO, COUNTS CLOCK TICKS + ; UNTIL NEXT BLINK. IT'S PRETTY KLUDGEY, SEE CODE AT CLKLOP. +FBLINK: BLKVAR ;LIST OF FREE BLINKERS +TICKS: 0 ;HIGH ORDER OF TIME +TICKS1: 0 ;LOW ORDER OF TIME +SSCC: .BYTE 0 ;SEMI-SLOW CLOCK COUNTER (WRAPS AROUND EVERY 256./60. SEC) + .BYTE 0 ;UNUSED +QPYSWT: 0 ;INTER LOCK TO SAVE COPY PAPER +BUZSWT: 0 ;INTERLOCK FOR BUZZING 9TH FLOOR DOOR +ELESWT: 0 ;INTERLOCKING THE ELEVATOR +RADIX: 0 ;HOLDS OUTPUT RADIX +VERSE: %FNAM2 ;SOURCE FILE VERSION # +KBDACT: 0 ;KEYBOARD ACTIVE LIST (NOT YET SEEN BY PDP-10) +KBDLAST:0 ;POINTS TO LAST BUFFER ON ACTIVE LIST +KBDTSW: 0 ;NON-ZERO => EXAMINE KBDCNT ARRAY AT SSC LEVEL. +WHOTIM: 0 ;LAST TIME WE DID WHO LINES +WHOFLG: 0 ;DO WHO LINES FLAG +DPYFRE: 0 ;DPY # OF FREE-CONSOLE CHANNEL. +TYMSHR: 0 ;# CLOCK TICKS TO GO BEFORE CHECKING NEXT DPY CHANNEL + +;PATCH AREA +PATCH: .=.+PATL + +;******* TEMPORARY VARIABLES FOR FONT CHECKSUMS ******* +CKSPNT: 0 ;RUNNING POINTER +CKSSUM: 0 ;RUNNING CHECKSUM +CKSSMG: 0 ;GOOD CHECKSUM OF [FNTORG,FNTEND) + +;LINE EDITOR BUFFER RINGS + +TENWRD +NLBUFS==/ + +.IIF LT NLBUFS-, .ERROR NOT ENOUGH LEBUFS +REPORT NLBUFS=,\NLBUFS + +LEBUFS: .=.+> + +REPORT HIGHEST USED=,\. + +.END GO diff --git a/src/system/utape.952 b/src/system/utape.952 new file mode 100755 index 00000000..d41f5fe2 --- /dev/null +++ b/src/system/utape.952 @@ -0,0 +1,2009 @@ +; I T S UTAPE SERVICE ROUTINE + +UTBLKS==3 + +;UT CHANNEL STORAGE + +EBLK +UTCHNT: ;BEG FOR GETSYS (UTAPE) +UTBFP: REPEAT NUTIC+NUTOC,400000,,377 ;L H BUFFER LINK PTR (INPUT PI) + ;RH " " OUTPUT MAIN PROG +UTUSR: ;USER OR -1 IF FREE (LH) +UTUL: REPEAT NUTIC+NUTOC,-1 ;LINK TO CHANNEL ON SAME UTAPE OR -1(RH) +UTDIRP: BLOCK NUTIC+NUTOC ;BYTE POINTER TO UTDIR +UTDBC: BLOCK NUTIC+NUTOC ;RH BLCK COUNT CORRESP WITH UTDIRP + ;L H 3.1 3.5 READ FILE NO 4.9 ERROR 4.5 4.8 ERROR CNT + ;3.6 =0 FORD EXT =1 BACK EXT 3.7 4.2 PUT FILE NO + ;4.4 DELETE ON READ CLOSE +UTBFS: BLOCK NUTIC+NUTOC ;BUFFERS IN USE +UTLSTM: BLOCK NUTIC+NUTOC ; TIME LAST BUF TAKEN BY PROG +UTMBN: BLOCK NUTIC+NUTOC ; MN PROG ACTIVE BFFR NO OR -1,IF NO BUFFER ACIVE (LH) +UTRAC: BLOCK NUTIC+NUTOC+1 ;ACTIVE BUFFER NO PI RH + ;FLAG TO MAIN PROG TP FULL (WRITE) RH + ;SIGN SET =>CHANNEL LOCKED + ;4.8 READ EOF REACHED AT PILEVEL OR CHNL CLOSED + ;EXTRA WORD FOR FILE DIR CHNL + ;4.7 DONT RELOAD AT PI +UTN1=.-NUTIC+1 + BLOCK NUTOC +UTN2=.-NUTIC+1 + BLOCK NUTOC ;NAME OF FILE BEING WRITTEN +UTBKNP=.-NUTIC+1 + BLOCK NUTOC +MPRP: BLOCK NUTIC+NUTOC ;MAIN PRGM BUFFER PNTR +MPRC: BLOCK NUTIC+NUTOC ;CNT REMAINING +UTTNO: BLOCK NUTOC+NUTIC ;TAPE NO (RH) + ;LH CLOSE FLAG WRITE ORG FILE NO READ +UTEOF: BLOCK NUTIC ;END OF FILE CHR + +UTLDD: BLOCK NUTIC+NUTOC+1 ;IF -1, DC IS ACTUALLY SET UP AND TRANSFER CAN + ;BE EXPECTED IN LESS TAH 100 MS. + ;IF D CHANNEL LOCKED FLAG(4.9 UTRAC) WELL BE CHECKED + ;BEFORE GOING TO THE -1 STATE + ;EXTRA WORD FOR DIR CHNL +UTDERR: BLOCK NUTIC+NUTOC+1 ;4.9 ERROR 4.8 ABORT 4.7 UTAPE FULL + +NUTCA: 0 ;NUMBER UTAPE CHANNELS ACTIVE +NUWCA: 0 ;# WRITE CHNLS ACT + +UPCHFS: 0 ;FAIR SHARE BFS PER CHNL + +LUTWBF==40 ;LENGTH OF BLK # PASSING LIST +UTWBF: REPEAT LUTWBF,.+1 ;LIST FOR PASSING BLK NOS FROM M.P. TO PI ON WRITE (INIT FS) + 0 ;TERMINATOR FOR FS LIST +UTWBFS: UTWBF ;FS PNTR + +IFNDEF MXUTBF,MXUTBF==40 ;MAX BUFFERS FOR AN INPUT CHANNEL. + +;TABLE AREAS + +DEFINE TAG A +IRPS TAGX,,A +BBLK +TAGX: 0 +EBLK +TERMIN +TERMIN + +UTCH: ;BEG FOR GETSYS (UTAPE) +TAG ULCTM:, REPEAT NUNITS,-1 ;LAST TIME EUPOS RECOMPUTED + ;IF DG2=0.E. 0 THEN ACT POS =EUPOS+*UDIR +TAG DRTM:, REPEAT NUNITS,177777,,-1 ;177777,,-1 => NO TIMING OP + ;N => DEAD RECKON UNTIL T=N + +TAG UDIR:, BLOCK NUNITS ;0=>STOP -1=>BACK 1=>FORW +IFN NEWDTP, TAG OUDIR:, BLOCK NUNITS ;DIR OF LAST OP +TAG UGOAL:, REPEAT NUNITS,-1;POSIT GOAL OR -1 IF UNIT FREE +TAG EUPOS:, BLOCK NUNITS ;ESTIMATED UNIT POSITION + ;SEE ULCTM IF DGW .NE. 1 +TAG DCHNT:, REPEAT NUNITS,-1;HEAD CHANNEL LIST OF UT OR -1 IF NO CHN ACT +TAG UMEMAD:, IFE NEWDTP,REPEAT NUNITS, BLKO DC, ;GOAL MEMADR-1 + IFN NEWDTP,REPEAT NUNITS,BLKO DTC, +TAG URDWR:, BLOCK NUNITS ;0 READ -1 WRITE(LOADED OPERATION) +TAG DG2:, REPEAT NUNITS,-1;+ => ACCURATE + ;0 => EUPOS FAIRLY ACCURATE + ;-1 => DO NOT DEAD RECKON WITHOUT UTC +TAG UTASS:, REPEAT NUNITS,0 ;0 IF NOT ASSIGNED, SYSTEM NAME IF ASSIGNED +TAG UDIRO:, REPEAT NUNITS,-1;ORGIN OF DIRECTORY +;OR -1 DIR NOT LOADED OR 4.9 DIR LOCKED OR 4.8+4.9 DIR DOUB LOCKED +;4.7 DIR CHANGED +;IF DIR LOCKED, IT MAY BE REFERENCED BUT NOT CHANGED +;4.5=0 => DIR AT LEAST ON WAY IN +;4.4=1 => TAPE IN UBLAT MODE + + +TAG UFLAPF:, BLOCK NUNITS ;4.9 FLAPPING RQSTED OR IN PROGRESS + ;4.8 RQ TO ABORT FLAPPING + ;4.7 DRIVE ACTUALLY ON THE WAY + ;4.6 (TD10 ONLY) 0 PHASE 1 STOP 1 PHASE 1 STOP DONE + ;RH TIME TO STOP AFTER FLAPPED + +TAG ULDCH:, BLOCK NUNITS ;NUMBER OF LOADED CHANNEL IN LH + ;BUFFER NO OF DIR (INDEX INTO IOBFT) IN RH + ;LH 4.9 = LOW PRIORITY POSIT + + +TAG UDPWF:, REPEAT NUNITS,-1 ;DIRECTORY PAWED OVER FLAG + +TAG UMNFB:, BLOCK NUNITS ;MAIN PRGM FREE BLOCKS ON TAPE + +TAG UTERP:, BLOCK NUNITS ;LH ERROR CODE (CONI UTS,) RH # ERRORS + +TAG UMNTR:, BLOCK NUNITS ;UNAME OF LAST JOB TO READ IN DIRECTORY + +SUNIT: 0 ;SELECTED UNIT OR 0 +IFE NEWDTP, SUNITL: 0 ;SAME _ 3 +SMODE: -1 ;-1 POSIT 0 DATA +UIDLE: -1 ;-1 UTAPES COMPLETELY IDLE + +IFN NEWDTP, CUINT: 0 ;-1 CLK HAS CAUSED BREAK +WRITE: 0 ;0 READ -1 WRITE +TAPCNT: 0 +TAP1: 0 +TAP2: 0 +TAP3: 0 +UTTM1: 0 ;UNIT COULD START IN SEARCH LOOP +UTTM2: 0 ;MOST PRESSING UNIT SO FAR +UTTM3: 0 ;TIME FOR ABOVE OR -1 IF NONEî +UTTM4: 0 ;TAPE TO START FLAPPING (FLAG FLAP IN PROG IF NEWDTP=1) +IFE NEWDTP,[ +UTTM5: 0 ;TAPE TO STOP FLAPPING +FLPUNT: 0 +] +UTENB: 0 +LUTOTM: 0 ;TIME OF LAST UT OPER +UTHERR: 0 ;UT HANGUP ERR +USTSW: 0 ;UT START SWITCH +UDCC: 0 ;-1 IF UTAPE HAVE DC FOR BLK CYCLE +UTCHE==.-1 ;END FOR GETSYS (UTAPE) + +BBLK + +;UTAPE CONTINUOUS NON-FILE IO + +AUBL2: CONO PI,UTCON ;DIRECTORY LOCKED, MAYBE ITS BEING FLAPPED + PUSHJ P,UDELAY +AUBLAT: XCTR XRW,[SKIPLE I,(J)] ;GET TAPE NUM, C(AC), SKIP IF NEG OR ZERO + CAIG I,NUNITS ;SKIP IF TOO BIG + PUSHJ P,UTSNMK ;DON'T ALLOW UTAPE HACKERY UNLESS ASSIGNED + POPJ P, ;ERR EXIT, BAD TAPE NUM + CONO PI,UTCOFF + MOVE B,UDIRO(I) + AOJE B,AUBL1 ;DIR NOT IN + TLNN B,10000 + JRST UTCONJ ;NOT IN UBLAT MODE + JUMPL B,AUBL2 +AUBL1: MOVSI B,10000 + MOVEM B,UDIRO(I) + CONO PI,UTCON + JRST POPJ1 + +;.ASSIGN - ASSIGN A DECTAPE UNIT. +AASSIGN:XCTR XR,[MOVE I,(J)] + CAILE I,NUNITS + POPJ P, + JUMPLE I,CPOPJ + MOVE A,UNAME(U) + CONO PI,CLKOFF + CAMN A,UTASS(I) + JRST CLKOJ1 + SKIPE UTASS(I) + JRST CLKONJ + MOVEM A,UTASS(I) + JRST CLKOJ1 + +ADESIGN:XCTR XR,[MOVE I,(J)] ;DEASSIGN UTAPE + CAILE I,NUNITS + POPJ P, + JUMPLE I,CPOPJ + SKIPN A,UTASS(I) + JRST POPJ1 + CAME A,UNAME(U) + POPJ P, + SETZM UTASS(I) + JRST POPJ1 + +;SET UTAPE NAME ;.UTNAM AC, ;LH(AC)=6BIT NAME, RH(AC)=TAPE # + +AUTNAM: XCTR XR,[MOVE Q,(J)] + HRRZ I,Q ;GET TAPE # + JUMPE I,CPOPJ ;TOO SMALL + CAIG I,NUNITS ;TOO LARGE? + PUSHJ P,UTSNMK ;ASSIGNED TO SOMEONE ELSE? + POPJ P, ;YES, LOSE + TLO D,1 ;SET FLAG TO EXIT FROM OPEN ROUTINE + PUSHJ P,UTO0 ;GET DIR IN CORE, LOCK, ETC. + TLNE TT,210000 ;CHECK FOR DIRECTORY NOT READ IN, UBLAT MODE + JRST LSWPOP ;JUMP ON LOSSAGE + HLRZ A,Q ;GET TAPE NAME + AOSN UDPWF(I) ;DIRECTORY PAWED OVER YET? + PUSHJ P,UDPW ;NO, GO DO IT + MOVE J,UDIRO(I) ;GET POINTER TO DIR + XOR A,177(J) ;GET DIFF BETWEEN OLD & NEW NAMES + TRNN A,-1 ;IS THERE ANY? + JRST AUTN2 ;NO, SKIP SOME CRUFT + TLZ A,-1 ;IGNORE DIFFERENCES IN LH + XORM A,177(J) ;MODIFY NAME TO NEW NAME + TLO J,100000 ;SET DIR CHANGED BIT +AUTN2: MOVEM J,UDIRO(I) ;STORE MODIFIED POINTER + JRST LSWPJ1 + +UDPW: HRRZ J,UDIRO(I) + MOVEI TT,37 + DPB TT,[370500,,177(J)] + ADD J,[500,,23.*2-1] + MOVEI TT,0 +UDPW2: ILDB Q,J + SKIPN Q + AOS TT + CAIE Q,37 + JRST UDPW2 + MOVEM TT,UMNFB(I) + POPJ P, + +;INITIALIZE UTAPE DIRECTORY ;.UINIT AC, ;C(AC)=TAPE # +;TAPE MUST BE ASSIGNED + +AUINIT: XCTR XRW,[SKIPLE I,(J)] ;TAPE # TOO LOW? + CAILE I,NUNITS ;OR HIGH? + POPJ P, ;YES + PUSHJ P,UTSNMK ;OR NOT ASSIGNED TO THIS USER + POPJ P, + TLO D,1 ;SET EXIT FLAG FOR OPEN ROUTINE + PUSHJ P,UTO0 ;GET DIR, LOCK IT, ETC. + TLNE TT,210000 ;CHECK FOR UBLAT MODE, DIRECTORY NOT READ (TT=UDIRO(I)) + JRST LSWPOP + SETZM (TT) ;CLEAR FIRST LOC + HRLI A,(TT) ;SET UP LH OF BLT POINTER + HRRI A,1(TT) ;& RH + BLT A,177(TT) ;ZAP + MOVE A,[757367573674] ;GET WORD OF 7 5-BIT BYTES VALUE 36 + MOVEM A,56(TT) ;INDICATE FIRST 7 BLOCKS RESERVED + MOVSI A,660000 ;ONE 5-BIT BYTE, VALUE 33 + MOVEM A,67(TT) ;MARK FILE DIRECTORY BLOCK + HRROS 177(TT) ;MARK END OF DIR + SETZM UDPWF(I) ;INDICATE DIR PAWED OVER + MOVEI A,559. ;# OF FREE BLOCKS IN EMPTY TAPE + MOVEM A,UMNFB(I) ;STORE FOR FUTURE REFERENCE + TLO TT,100000 ;INDICATE CHANGED + MOVEM TT,UDIRO(I) ;UPDATE POINTER + JRST LSWPJ1 + +;UTAPE DISMOUNT + +AUDISM: XCTR XRW,[MOVE A,(J)] ;OPER 22 +NFLAP: JUMPLE A,CPOPJ + CAILE A,NUNITS + POPJ P, + MOVSI C,-NUTIC-NUTOC + CONO PI,UTCOFF +AUTDM1: SKIPGE UTUSR(C) + JRST AUTDM2 + HRRZ D,UTTNO(C) + CAMN A,D + JRST UTCONJ ;SOME ONE USING TAPE +AUTDM2: AOBJN C,AUTDM1 + CONO PI,UTCON + MOVSI C,(SETZ) + IORM C,UFLAPF(A) + JRST POPJ1 + +;ATTEMPTED DIRECTORY READ GOT FLUSHED +UTOLOS: TLNE D,1 ;CHECK EXIT FLAG + JRST NULSET ;NOT .OPEN, SEIZE NOTHING AND RETURN + JRST OPNL7 ;.OPEN, SIGNAL DEVICE NOT READY + +UTOF1: MOVSI TT,200000 + IORM TT,UFLAPF(I) ;RQEST ABORT OF FLAP + CONO PI,UTCON + SKIPGE UFLAPF(I) + PUSHJ P,UFLS ;HOPE FOR BEST +UTO: PUSHJ P,UTSNMK ;MUST BE ASSIGNED + JRST NCA + JUMPE I,OPNL1 ;UTAPE OPEN + CAILE I,NUNITS + JRST OPNL1 +UTO0: CONO PI,UTCOFF + SKIPGE UFLAPF(I) + JRST UTOF1 ;FLAPPING IN PROGRESS + SKIPGE TT,UDIRO(I) + AOSE TT + JRST UTO4 ;FILE DIR IN OR ON THE WAY + MOVEI TT,200000 + MOVEM TT,DCHNT(I) + MOVE TT,UNAME(U) + MOVEM TT,UMNTR(I) ;TELL WHO FIRST CAUSED DIR TO BE READ IN + MOVSI TT,20000 + ANDCAM TT,UDIRO(I) +UTO4: CONO PI,UTCON + MOVSI TT,400000 + MOVNI T,1 + PUSHJ P,LWAIT + CAMLE T,UDIRO(I) ;WAIT FOR DIRECTORY TO COME IN OR GO OUT + IORB TT,UDIRO(I) ;IF IN THEN LOCK IT + CONO PI,UTCON + CAMN TT,[-1] + JRST UTOLOS ;DIDN'T GET READ IN + PUSHJ P,SGNSET ;MAKE SUURE DIRECTORY GETS UNLOCKED ON PCLSR + UDIRO(I) + TLNE D,1 ;CHECK SPECIAL EXIT FLAG + POPJ P, ;EXIT + TLNE TT,10000 + JRST UTOBL1 ;IN UBLAT MODE + AOSN UDPWF(I) + PUSHJ P,UDPW +UDPW1: TRNE D,200000 + JRST UTDEL1 ;DELETE OR RENAME + JUMPL D,UTOW1 ;WRITE + PUSHJ P,FLDRCK + JRST UTO5B ;NORMAL FILE WANTED + MOVEI J,0 ;UTAPE DIRECTORY WANTED + PUSHJ P,LSWPOP + JRST LISTFE ;JOIN DIRECTORY CODE FOR OTHER DEVICES + +UTOBL1: CAIN W,4 + JRST OPNL4 ;DELETE ILLEGAL IN UBLAT MODE + CLEARB A,B + JRST UTO8 + +UTO5B: PUSHJ P,UTLK3 ;MUST NOT CLOBBER TT + JUMPE B,OPNL4 +UTOW2:UTO8: CONO PI,UTCON + MOVSI TT,-NUTIC + TLNE C,1 + MOVE TT,[-NUTOC,,NUTIC] + SKIPL UTUSR(TT) + AOBJN TT,.-1 + JUMPG TT,UNCA ;NO CHANNEL AVAILABLE + CONO PI,UTCOFF + SKIPL UTUSR(TT) + JRST UTO8 + MOVEI J,DCHNT-UTUL(I) + JRST .+2 +UTO2: MOVE J,Q + HRRE Q,UTUL(J) + JUMPGE Q,UTO2 ;INSERT CHNL ONTO LIST FOR TAPE + HRLOM U,UTUSR(TT) + HRRM TT,UTUL(J) + HRRZM I,UTTNO(TT) + HRRZ J,UDIRO(I) + ADD J,A + MOVE Q,133(J) + MOVEI J,EOFCH + TRNN Q,1 + MOVEI J,141 + MOVEM J,UTEOF(TT) ;STORE EOF CHR + SETZM UTDBC(TT) + DPB A,[300500,,UTDBC(TT)] + JUMPL D,UTOW3 ;WRITE + DPB A,[220500,,UTDBC(TT)] +UTOW4: HRLM A,UTTNO(TT) + HRRZ J,UDIRO(I) + ADD J,[500,,23.*2-1] + MOVEM J,UTDIRP(TT) + MOVE J,[SETZ 377] + MOVEM J,UTBFP(TT) + CLEARM UTBFS(TT) + MOVE J,TIME + MOVEM J,UTLSTM(TT) + HRROS UTMBN(TT) + HLLOS UTRAC(TT) + HRRZS UTRAC(TT) + CONO PI,UTCON + CLEARM MPRC(TT) + AOS NUTCA + PUSHJ P,FSCMP + HRRZS UTRAC(TT) + PUSHJ P,LSWPOP ;RELEASE FILE DIR + MOVSS C + HRL A,TT + JSP Q,OPSLC7 + DNUACII,,DNUACCO ;ASCII UNITS INPUT ;ASCII UNITS OUTPUT + DNUBKI,,DNUBKO ;BLOCK INPUT ;BLOCK OUTPUT + DNUDTI,,DNUDTO ;WORD INPUT ;WORD OUTPUT + DNUBKI,,DNUBKO ;BLOCK INPUT ;BLOCK OUTPUT + +UTOW1: SKIPN UMNFB(I) + JRST OPNL6 ;FULL + PUSH P,B + PUSH P,A + PUSHJ P,UTSNMK + JRST UTWNA ;NOT ASSIGNED + SETZB A,B + PUSHJ P,UTLK3 + JUMPE B,UFILDF ;FILE DIR FULL + JRST UTOW2 + +UTSNMK: SKIPN T,UTASS(I) ;TAPE MUST BE ASSIGNED TO THIS LOSER + POPJ P, + CAME T,UNAME(U) + CAMN T,USYSN1(U) + AOS (P) + POPJ P, + +UTOW3: HRROM TT,1(B) ;RESERVE FILE NAME + POP P,UTN1(TT) ;STORE NAMES + POP P,UTN2(TT) + MOVSI J,100000 + IORM J,UDIRO(I) ;SET FILE DIR MODIFYED + MOVSI J,UTBKNP(TT) ;GET LIST PNTR PNTR + MOVEM J,UTBKNP(TT) ;MAKE LH SELF-REFERENT SO INIT LINK WILL GO IN RH + AOS NUWCA ;INCR # ACT UWRITE CHNLS + JRST UTOW4 + +UNCA: JUMPGE D,NCA +UTWNA: SUB P,[2,,2] +NCA: JRST OPNL10 + +UFILDF: SUB P,[2,,2] +FILDF: JRST OPNL5 + +S1NL14: SUB P,[1,,1] + JRST OPNL14 + +UDATAI: SKIPA E,[444400,,1] +UASCII: MOVE E,[440700,,5] + MOVEI B,UBLKI2 + JRST CHRKTI + +UBLKI: MOVE E,[444400,,1] + JSP B,BLKT +UBLKI2: MPRP(A) + MPRC(A) + UTBGB ;4.9 = 0 UTAPE 1 DISK + UTBRB + JRST 4,. + SKIPG UTBFS(A) + +;INPUT BLK BUFFER-GET RTN + +UTBGB: LDB Q,[IOLO,,UTBFP(A)] + CAIN Q,377 + JRST 4,. ;PNTRS OUT OF PHASE + CAIN Q,376 + JRST POPJ2 ;END OF FILE + CONO PI,UTCOFF + SKIPL UTRAC(A) + SKIPGE IOBFT(Q) + JRST UTBGB1 + LDB J,[IOLO,,IOBFT(Q)] + HRRM J,UTBFP(A) + MOVEI TT,(SETZ) + CAIL J,376 + HRLM TT,UTBFP(A) + CONO PI,UTCON + SOS UTBFS(A) +UTBWG4: MOVE J,TIME + MOVEM J,UTLSTM(A) + MOVEI J,-3 + DPB J,[IOLO,,IOBFT(Q)] + LDB TT,[IOSA,,IOBFT(Q)] + LSH TT,6 + HLL TT,E + MOVEM TT,MPRP(A) + MOVEI TT,200 + IMULI TT,(E) + MOVEM TT,MPRC(A) + HRLM Q,UTMBN(A) + JRST POPJ1 + +UTBGB1: CONO PI,UTCON + SKIPL IOBFT(Q) + SKIPGE UTRAC(A) + PUSHJ P,UFLS ;REALLY? + JRST UTBGB + +UBLKO: MOVE E,[444400,,1] + JSP B,BLKT +UBLKO2: SETZ MPRP(A) + MPRC(A) + UTBWG + UTBWW + JRST 4,. + TRNA + +UASCCO: SKIPA E,[440700,,5] +UDATAO: MOVE E,[444400,,1] + MOVEI B,UBLKO2 + JRST CHRKTO + +;OUTPUT BLKT BUFFER-GET RTN + +UTBWG: MOVE Q,UTBFS(A) ;GET # BUFS IN CHNL + IMUL Q,NUWCA ;SCALE TO # ACT UWRITE CHNLS + CAIL Q,LUTWBF ;IF BEING TOO GREEDY WITH BLOCK LIST SPACE + POPJ P, ;LOSE + PUSH P,A + PUSH P,B + MOVE D,A + HRRZ Q,UTBFP(D) + CAIL Q,376 + JRST UTBWG1 ;NO BUFS NOW RELOAD + SKIPGE UTDBC(D) + JRST POPBAJ ;CHNL IN ERR + +UTBWG2: HRRZ J,UTBFS(D) + CAMG J,UPCHFS + JRST UTBWG1 + PUSHJ P,TCALL + JRST UIMRQ + JRST POPBAJ + PUSHJ P,TCALL + JRST UTMGB + JRST UTBWG2 + +UTBWG1: HRRZ Q,UTTNO(D) + SOSGE UMNFB(Q) + JRST UTBWG5 + PUSHJ P,AOSSET + UMNFB(Q) + PUSHJ P,LSWTL ;WAIT FOR + UDIRO(Q) ;DIR TO UNLOCK + PUSH P,E ;SAVE E + PUSHJ P,TCALL + JRST IUTCONS + JRST UTBWG6 + PUSH P,A ;SAVE A + PUSH P,B + PUSH P,C + MOVE C,Q + MOVE B,UDIRO(C) + MOVEI E,0 ;INDICATE ADVANCE TO UDIRAD + PUSHJ P,UDOUT2 ;ADV DIR PNTRS (SKIP LOCK CHECK IN UDIRAD) + JRST 4,. ;SHOULDN'T GET HERE + JRST UTPFUL ;NO ROOM FOR EXT + PUSHJ P,LSWPOP ;UNLOCK DIR + PUSHJ P,LSWDEL ;UNHACK UTFAOS + POP P,C + POP P,B + POP P,Q ;GET BACK BUF # + POP P,E ;RESTORE E + POP P,B + POP P,A + AOS UTBFS(A) + JRST UTBWG4 + +UTBWG5: AOS UMNFB(Q) + JRST IOCER9 + +UTBWG6: PUSHJ P,LSWCLR ;UNLOCK DIR & ADJ BLK CNT + POP P,E + JRST POPBAJ + +UTPFUL: SUB P,[2,,2] + POP P,A ;GET BACK BUF # + PUSHJ P,BRTN ;RETURN BUF + JRST IOCER9 ;BARF ABOUT TAPE FULL + +UTBWW: HLRE Q,UTMBN(A) + JUMPL Q,CPOPJ + PUSHJ P,LWAIT ;WAIT FOR + SKIPN UTWBFS ;SPACE IN BLK LIST & GET PNTR + MOVE J,UTWBFS ;(DO NOT COMBINE WITH PRECEDING INST) + HRRZ H,(J) ;GET PNTR TO NEXT FREE WD + MOVEM H,UTWBFS ;UPDATE FS PNTR + CONO PI,UTCON ;TURN ON UTC NOW TO MINIMIZE OFF TIME EVEN THOUGH OFF AGAIN LATER + HRRZ D,UTDBC(A) ;GET NEXT BLK # + MOVSM D,(J) ;PUT IN NEW WD + HLRZ D,UTBKNP(A) ;GET PNTR TO LAST WD IN LIST + HRRM J,(D) ;STORE LINK IN END OF LIST + HRLM J,UTBKNP(A) ;UPDATE END PNTR + MOVEI J,377 + IORM J,IOBFT(Q) + SKIPGE UTTNO(A) + SOS IOBFT(Q) ;CHANGE TO EOF + CONO PI,UTCOFF + HLRE J,UTBFP(A) + JUMPL J,UTBWW1 + DPB Q,[IOLO,,IOBFT(J)] + +UTBWW2: HRLM Q,UTBFP(A) + CONO PI,UTCON + HRROS UTMBN(A) + POPJ P, + +UTBWW1: HRRM Q,UTBFP(A) + JRST UTBWW2 + +UTOCL: MOVSI Q,(SETZ) + IORM Q,UTTNO(A) + LDB E,[300600,,MPRP(A)] ;NOW FILL OUT BLOCK WITH EOF CHARS + CAIN E,7 + JRST UTOCL6 +UTOCL1: HRROI C,[EOFWRD] + SKIPG MPRC(A) + JRST UTOCL2 + PUSHJ P,UDATAO + JRST UTOCL1 + +UTOCL6: HRROI C,UTEOF(A) + SKIPG MPRC(A) + JRST UTOCL2 + PUSHJ P,UASCCO + JRST UTOCL6 + +UTOCL2: SKIPG MPRC(A) + PUSHJ P,UTBWW ;MAKE SURE BUFFER WRITTEN OUT SINCE MAYBE GOT + ;PCLSRED FROM UTBWW DURING .IOT THAT JUST FILLED BUFFER + PUSH P,R + MOVE D,A + SKIPE UTBFS(D) + PUSHJ P,UFLS + HRRZ C,UTTNO(D) + PUSHJ P,LSWTL + UDIRO(C) + HRRZ Q,UTBFP(D) + CAIL Q,376 + JRST UTOCL4 ;NORMAL CLOSE + MOVEI Q,%PIIOC ;ABORT WORKS + IORM Q,PIRQC(U) + MOVEI A,0 + HRROI B,(D) + PUSHJ P,UDELETE +UTOCL5: PUSHJ P,LSWPOP + POP P,R + SOS NUWCA ;DECR # ACT UWRITE CHNLS + JRST UTOCL3 + +UTOCL4: MOVE A,UTN1(D) + MOVE B,UTN2(D) + PUSHJ P,UDELETE + LDB Q,[220500,,UTTNO(D)] + LSH Q,1 + ADD Q,UDIRO(C) + MOVE A,UTN1(D) + MOVE B,UTN2(D) + MOVEM A,-2(Q) + MOVEM B,-1(Q) + LDB Q,[220500,,UTTNO(D)] + ADD Q,UDIRO(C) + MOVEI A,1 + IORM A,133(Q) + JRST UTOCL5 + + +UTDEL1: MOVE C,I ;DELETE + SKIPE SRN3(U) + JRST UTRN1 ;RENAME + PUSHJ P,UTSNMK + JRST NCA + PUSHJ P,UDELETE + JUMPE TT,OPNL4 + JRST LSWPJ1 + + +UTRN1: JUMPE A,UTRN3 ;RENAME OF OPEN FILE + PUSHJ P,UTSNMK ;ALLOW RENAME OF OPEN FILE + JRST NCA + PUSHJ P,UTLOOK + JUMPE B,OPNL14 + PUSH P,Q + MOVE A,SRN3(U) + MOVE B,SRN4(U) + PUSHJ P,UTLOOK + POP P,Q + JUMPN B,OPNL13 + MOVE A,SRN3(U) + MOVE B,SRN4(U) + MOVEM A,0(Q) + MOVEM B,1(Q) +UTRN4: MOVSI A,100000 + IORM A,UDIRO(C) + JRST LSWPJ1 + +UTRN3: ADDI B,IOCHNM(U) + HLRZ TT,(B) + MOVE A,SRN3(U) + MOVE B,SRN4(U) + MOVEM A,UTN1(TT) + MOVEM B,UTN2(TT) + JRST UTRN4 + +UDELETE: MOVEI TT,0 ;TT=0 IF NOTHING DELETED + OTHERWISE +UDELA: PUSHJ P,UTLOOK + JUMPE B,CPOPJ ;TAPE NO IN C,FILE NAME IN A,B + MOVEI E,NUTIC-1 +UDELE4: HRRZ J,UTTNO(E) + SKIPL UTUSR(E) + CAME J,C + JRST UDELE3 + HLRZ J,UTTNO(E) + CAME J,A + JRST UDELE3 + MOVSI J,10000 + TDNE J,UTDBC(E) + JRST UDELE3 ;THIS IS LOSER WHO IS CLOSING FILE + IORM J,UTDBC(E) + CLEARM (Q) + SETOM 1(Q) + AOJA TT,CPOPJ + +UDELE3: SOJGE E,UDELE4 +UDELE1: CLEARM (Q) + CLEARM 1(Q) + MOVE J,A + ADD J,UDIRO(C) + MOVEI B,1 + ANDCAM B,133(J) + MOVSI J,100000 + IORM J,UDIRO(C) +UDELE6: HRRZ B,UDIRO(C) + ADD B,[500,,23.*2-1] + MOVEI J,0 +UDELE2: ILDB E,B + CAMN E,A + AOS UMNFB(C) + CAMN E,A + DPB J,B + CAIE E,37 + JRST UDELE2 + MOVE B,A + MOVEI A,0 + AOJA TT,UDELA + + +UTICL: PUSH P,R + MOVE D,A + MOVSI C,200000 + IORM C,UTRAC(D) ;SET EOF + MOVEI T,400000 + TDNN T,UTRAC(D) + PUSHJ P,UFLS ;WAIT FOR ACTIVE BUFFER TO TRANSFER + PUSHJ P,UTBRB1 ;RETURN ACTIVE BUFFER MAIN PROG + HLRZ A,UTTNO(D) + MOVE B,UTDBC(D) + TLNE B,10000 + PUSHJ P,UDELE5 ;FINISH FILE DELETE + POP P,R +UTOCL3: HRRZ A,UTBFP(D) +UTICL2: CAIL A,376 + JRST UTICL3 + LDB C,[IOLO,,IOBFT(A)] + PUSHJ P,BRTN + MOVE A,C + JRST UTICL2 + +UTICL3: PUSHJ P,UCPAT0 ;UT CHANNEL PATCH OUT + CLEARM UTDIRP(D) + SETOM UTUSR(D) + CLEARM (R) + POPJ P, + + + +UCPAT0: HRRZ B,UTTNO(D) ;PATCH OUT CHANNEL + MOVEI C,DCHNT-UTUL(B) + CONO PI,UTCOFF +UCPAT2: HRRE E,UTUL(C) + JUMPL E,UTCOP + CAMN E,D + JRST UCPAT1 + MOVE C,E + JRST UCPAT2 + +UCPAT1: HRRZ E,UTUL(E) + HRRM E,UTUL(C) + SOS NUTCA +UTCOP: JRST UTCONJ + +UDELE5: HRRZ C,UTTNO(D) + PUSHJ P,LSWTL + UDIRO(C) + HLRZ Q,UTTNO(D) + MOVE A,Q + LSH Q,1 + ADD Q,UDIRO(C) + SUBI Q,2 + PUSHJ P,UDELE1 + JRST LSWPOP + +UTBRB1: MOVE A,D +UTBRB: PUSH P,A + HLRE A,UTMBN(A) + JUMPL A,POPAJ + PUSHJ P,BRTN + POP P,A + HRROS UTMBN(A) + POPJ P, + +UTRL1: JUMPE B,UTRLDR + HRRZ B,UTBFP(D) + CAIE B,377 + JRST JDB6C +UTRLDR: LDB R,[270100,,UTDBC(D)] + JUMPN R,UTRLD1 + SKIPL R,UDIRO(C) ;SPECIAL KLUDGE TO RUN FAST + TLNE R,10000 ;SKIPN ON NOT IN UBLAT MODE + JRST UTRLD1 + LDB TT,[220500,,UTDBC(D)] + ILDB B,UTDIRP(D) + AOS UTDBC(D) + CAME B,TT + JRST UTRLD2 +UTRLD3: PUSHJ P,IUTCONS ;RTN BUFFER NO IN A + JRST UTRLR1 ;MEM LOCKED (OR SOMETHING) + CLEARM URDWR(C) + HRRZ B,UTDBC(D) ;GET BLK # TO READ + JRST UTRLD + +UTRLD2: CAIN B,37 + PUSHJ P,UAR + +UTRLD1: PUSHJ P,UDIRAD + JRST JDB6C2 ;DIR DOUBLE LOCKED + JRST UTREOF + JRST UTRLD3 + + +JDDTA: HLRZ D,ULDCH(C) ;FINISHED DATA TRANS TAPE IN C GET CHNL NO + CLEARM UTLDD(D) + SETOM SMODE +IFE NEWDTP, CONSZ DC,7 +IFN NEWDTP, CONSO DTS,100000 + JRST UDATER ;DC STILL ENABLED => ERROR + SETOM UGOAL(C) + CAIL D,NUTIC + JRST JDDT1 ;WRITE OR FILE DIRECTORY + MOVE E,UTRAC(D) + HLLOS UTRAC(D) + MOVEI B,377 + IORM B,IOBFT(E) + HLRE B,UTBFP(D) + JUMPL B,JDDT5 + DPB E,[IOLO,,IOBFT(B)] +JDDT6: HRLM E,UTBFP(D) + AOS UTBFS(D) + + +JDDT2: PUSHJ P,JDB6W + JRST JDDT3 ;SAME TAPE CAN RELOAD, DONT CHECK OTHERS +JDDT4: HRRZS ULDCH(C) +IFE NEWDTP, JRST JDB4A ;UNIT NOW IDLE STOP IT +IFN NEWDTP,[ + PUSHJ P,JDSTP + JRST JDB3 +] + +JDDT1: CAIL D,NUTIC+NUTOC + JRST UDRDD3 ;FILE DIR IN OR OUT + HRRZ A,UTRAC(D) + PUSHJ P,IBRTN + HLLOS UTRAC(D) + SOS UTBFS(D) + JRST JDDT2 + + +JDDT5: HRRM E,UTBFP(D) + JRST JDDT6 + UTREOF: MOVSI E,200000 + IORM E,UTRAC(D) + HLRE E,UTBFP(D) + SKIPL E + SOSA IOBFT(E) ;TURN END OF LIST TO END OF FILE + SOS UTBFP(D) + AOS UTBFS(D) ;TO START MAIN PROG + JRST JDB6C + +JDB6W: HRRE D,DCHNT(C) + JUMPL D,JDB6W1 ;NO CHANNELS ACTIVE + CAIN D,200000 + JRST UDRDD ;READ FILE DIR +JDB6C1: SKIPL E,UTRAC(D) + TLNE E,300000 + JRST JDB6C2 ;CHANNEL LOCKED + CAIL D,NUTIC + JRST JDB6A ;WRITE CHANNEL + HRRZ B,UTBFS(D) + CAILE B,MXUTBF ;READ CHANNEL; SHOULDN'T LET IT GET TOO MANY BUFFERS. + JRST JDB6C + HRRZ B,UTFS + CAIN B,377 + JRST JDB6E ;TRY TO GET MORE MEMORY + MOVE B,UTBFS(D) + SOJLE B,UTRL1 ;RELOAD CHANNEL WITH ONE OR NO BUFFERS + MOVE B,UTLSTM(D) + SUB B,TIME + CAMG B,[-300.] + JRST JDB6C2 ;NO RELOAD +JDB6F: HRRZ B,UTBFS(D) ;NUMBER BUFS THIS CHANNEL HAS + CAMGE B,UPCHFS + JRST UTRLDR +JDB6E: PUSHJ P,UIMRQ ;TRY TO GET MORE MEMORY (IO) + JRST JDB6C2 ;NOT AVAIL + PUSHJ P,UTMGB ;ADD TO MEM ALLOC UTAPE + JRST JDB6F + +UTRLR1: PUSHJ P,UDIRR ;BACK UP + JRST 4,. + JRST 4,. ;LOSSAGE +JDB6C2: +JDB6C: HRRE D,UTUL(D) + JUMPGE D,JDB6C1 + JRST POPJ1 + +JDB6W1: LDB D,[410300,,UDIRO(C)] + SOJN D,POPJ1 ;DIR CHANGED AND NOT LOCKED + HRRZ D,UDIRO(C) + LDB D,[370500,,177(D)] + CAIE D,37 + JRST 4,. ;DIRECTORY CLOBBERED SINCE READ IN + MOVEI D,100 ;INITIATE FILE DIR WRITE + SKIPL ULDCH(C) ;SKIPN ON ALREADY LOW PRIORITY POSIT + PUSHJ P,ILLP ;INITIATE LOW PRIOR POSIT + JRST POPJ1 + +ULLP1: SKIPGE UDIRO(C) + POPJ P, + SETOM URDWR(C) ;SET FILE DIR WRITE CYCLE FROM LOW PRIORITY CYCLE + MOVSI D,400000 ;LOCK DIR + IORM D,UDIRO(C) + MOVEI D,NUTIC+NUTOC + HRRZ A,ULDCH(C) ;BUFFER NO OF DIRECTORY + JRST JDB6W2 + + +JDB6A: HRRZ A,UTBFP(D) + CAIGE A,376 + SKIPGE IOBFT(A) + JRST JDB6C2 ;LOCKED OUT SNIFFLE + MOVE E,UTBKNP(D) ;GET BLK LIST PNTR + MOVE J,UTWBFS + EXCH J,(E) + HRRZM E,UTWBFS + HLRZ B,J ;GET BLK # FROM HEAD OF LIST + HRR E,J ;SET LINK TO NEXT WD IN LIST + TRNN E,-1 ;IF LIST EMPTY + MOVSI E,UTBKNP(D) ;SET END PNTR TO PNTR SO NEXT LINK WILL GO HERE + MOVEM E,UTBKNP(D) ;UPDATE PNTR + SETOM URDWR(C) + HRRZ A,UTBFP(D) + LDB E,[IOLO,,IOBFT(A)] + HRRM E,UTBFP(D) + MOVEI J,(SETZ) + CAIL E,376 + HRLM J,UTBFP(D) + +UTRLD: HRRM A,UTRAC(D) +UDRR2: MOVEM B,UGOAL(C) + MOVEI B,-4 + DPB B,[IOLO,,IOBFT(A)] + LDB B,[IOSA,,IOBFT(A)] + LSH B,6 + SOS B + HRRM B,UMEMAD(C) + HRLM D,ULDCH(C) + MOVE B,TIME + MOVEM B,DRTM(C) + POPJ P, + +JDB6: PUSHJ P,JDB6W + JRST JDBRK7 ;SUCCESFUL RELOAD + SKIPL ULDCH(C) +IFE NEWDTP,[ + JRST JDBRK4 ;CAN NOT RELOAD + JRST JDF2A +] +IFN NEWDTP,[ + JRST JDBRK6 + JRST JDS1 +] + +UDRDD: MOVE D,UDIRO(C) ;TAPE WANTS FILE DIRECTORY READ + TLO D,20000 ;OK FOR 4.5 CLEAR + AOSE D ;REST SHOULD BE -1 + JRST 4,. ;FILE DIRECTORY READ REQUEST WHEN ALREAD IN + MOVEI D,NUTIC+NUTOC ;GET DIRECTORY CHANNEL NUMBER IN D + PUSHJ P,IUTCONS + JRST POPJ1 ;NO MEM + LDB B,[IOSA,,IOBFT(A)] ;GET ORIGIN _ -6 + LSH B,6 + TLO B,600000 ;SET LOCK, DOUBLE LOCK BITS + MOVEM B,UDIRO(C) ;STORE ORIGIN + HLLOS DCHNT(C) ;NO CHANNEL ACTIVE THIS UNIT YET + CLEARM URDWR(C) ;SIGNAL WANT READ + HRRM A,ULDCH(C) ;STORE BUFFER NUMBER +JDB6W2: MOVEI B,100 ;DIRECTORY BLOCK NUMBER + JRST UDRR2 + +UDRDD3: HRRZ D,ULDCH(C) ;FILE DIR IN OR OUT + HRRZS UDIRO(C) ;UNLOCK DIRECTORY + DPB C,[IOLO,,IOBFT(D)] + HRRZS ULDCH(C) + JRST JDDT2 + UDIRAD: TDZA E,E ;ADVANCE DIR PNTRS OF CHANNEL IN D +UDIRR: MOVEI E,1 ;REV DIR PNTRS THIS WINS FOR READS ONLY HA HA + SKIPGE B,UDIRO(C) + JRST UDOUT3 +UDOUT2: TLNE B,10000 + JRST UDBL1 ;UBLAT MODE +UDOUT7: LDB R,[270100,,UTDBC(D)] + XOR R,E + MOVEI Q,0 + CAIL D,NUTIC + MOVEI Q,UTBLKS + LDB TT,[220500,,UTDBC(D)] + +UDIR1: PUSHJ P,UITAB(R) + TRNE J,-1 ;BLK NO RTN IN RH J + CAIN B,37 + JRST UDOUT ;END OF EXTENSION + CAME B,TT + SOJA Q,UDIR1 + SOJG Q,.-1 + LDB B,[300500,,UTDBC(D)] + DPB B,UTDIRP(D) +UDARET: JRST POPJ2 + +UDBL1: AOS A,UTDBC(D) + CAILE A,1101 + JRST POPJ1 ;EOF + JRST POPJ2 + +UDOUT: JUMPN E,UDOUT5 + CAIL D,NUTIC + JRST UDOUT1 + MOVEI A,0 ;READ + MOVE B,TT + PUSHJ P,UTLOOK ;TAP NO IN C NAME IN A,B + JUMPE B,POPJ1 ;EOF OR ADR OF FIRST WD +UDOUT6: DPB A,[220500,,UTDBC(D)] ;FILE NO +UDOUT4: DPB A,[300500,,UTDBC(D)] + MOVSI A,1_5 + XORM A,UTDBC(D) + JRST UDOUT7 + + +UDOUT3: TLNN B,200000 ;DIRECTORY DOUBLE LOCKED + CAIL D,NUTIC + POPJ P, + JRST UDOUT2 + +UDOUT1: SETZB A,B + PUSHJ P,UTLOOK + JUMPE B,UDOUT8 ; FILE DIR FULL + LDB J,[300500,,UTDBC(D)] + MOVEM J,1(B) + JRST UDOUT4 + +UDOUT8: XORI R,1 ;REVERSE DIR + AOS (P) ;SKIPN ONCE + JRST UITAB(R) ;BACK UP PNTRS AND RETURN + +UDOUT5: LDB A,[220500,,UTDBC(D)] + LSH A,1 + ADD A,UDIRO(C) + SKIPE -2(A) + JRST UDARET + MOVE A,-1(A) + JRST UDOUT6 + +UTLK3: SKIPA Q,UDIRO(I) +UTLOOK: MOVE Q,UDIRO(C) ;B=0 => NOT FOUND + HRLI Q,-23. + PUSH P,[1] +UTLK2: CAMN A,(Q) + CAME B,1(Q) + AOJA Q,UTLK1 + MOVE B,Q + JRST POPAJ + +UTLK1: AOS(P) + AOBJN Q,UTLK2 + MOVEI B,0 + JRST POPAJ + +UITAB: AOSA J,UTDBC(D) + JRST UAR + +UAF: ILDB B,UTDIRP(D) + POPJ P, + +UAR: MOVSI B,50000 + ADD B,UTDIRP(D) + SKIPGE B + SUB B,[430000,,1] + MOVEM B,UTDIRP(D) + LDB B,B + SOS J,UTDBC(D) + POPJ P, + +EBLK + IFN NEWDTP,{ +; T S UTAPE ROUTINES PI SERV (NEW UTAPE CONTROL) + +TAPE: 0 +UTP1: 0 ;JRST PIPOS OR DATAI DC, OR JRST UTP3 + +BBLK + + SOS .-1 + AOSGE TAPCNT + JRST 12,@TAPE + +UTP3: CONO DTS,770001 + JRST 12,@TAPE + +PIPOS: MOVEM A,TAP1 + MOVEM B,TAP2 + MOVEM C,TAP3 + MOVE C,SUNIT + DATAI DTC,B + TDZE B,[1777#-1] + JRST PIPOS7 + MOVEM B, EUPOS(C) + HRRZM C, DG2(C) + SKIPGE UGOAL(C) + JRST PIPF1 + SUB B,UGOAL(C) + JUMPE B,PIPOS2 + ADD B,UDIR(C) + MOVMM B,UTENB + SKIPGE ULDCH(C) + JRST PIPOS3 + JUMPN B,PIPOS3 +PIPOSL: MOVEI A,40000+DCCHN_3 + DPB C,[110300,,A] ;SET SELECTED UNIT CONO DTC,FOO(A) + MOVE B,UDIR(C) + XCT UTST2(B) +PIPOS5: MOVE C,TAP3 + MOVE B,TAP2 + MOVE A,TAP1 + JRST 12,@TAPE + +PIPOS7: AOS BDBLKC + JRST PIPOSL + +EBLK + +BDBLKC: 0 + BBLK + +PIPOS3: MOVE A,UDIR(C) + LSH A,2 + SUB B,A + XOR B,UDIR(C) + MOVEI A,40000 + DPB C,[110300,,A] + JUMPG B,PIPOS4 ;GOING WRONG DIR +PIPOS6: MOVE B,TIME + MOVEM B,ULCTM(C) + ADD B,UTENB + MOVEM B,DRTM(C) +PIPF2: MOVE B,UDIR(C) + TRNN A,40000 + TRO A,30000 + XCT UTST2(B) +; CLEARM UDCC +; SETOM DCFREE + CONO DTS,770001 ;ENABLE ALL INTERUPTS AND SET FUNCTION STOP + JRST PIPOS5 + +PIPF1: MOVEI A,40000 + DPB C,[110300,,A] + MOVE B,TIME + MOVEM B,ULCTM(C) + JRST PIPF2 + PIPOS4: TRZ A,40000 ;TURN TAPE AROUND + CLEARM DG2(C) + MOVNS B,UDIR(C) + MOVEM B,OUDIR(C) + JRST PIPOS6 + +PIPOS2: HLRZ A,ULDCH(C) + SKIPL ULDCH(C) + SKIPGE UTRAC(A) + JRST PIPOS3 ;CHANNEL LOCKED + SETOM UTLDD(A) ;CHANNEL ACTUALLY LOADED TRANSFER IMMINENT + AOS SMODE + MOVEI A,0 + MOVE B,UMEMAD(C) + SKIPGE URDWR(C) + TROA A,400 ;WRITE + TLZ B,(BLKO-BLKI) + SKIPL UDIR(C) + JRST TAPFOR + TRO A,100000 + ADD B,[DATAI-BLKI 200] + MOVEM B,UTP1 + MOVNI B,200 + MOVEM B,TAPCNT + +TAP4: CONO DTC,300+DCCHN_3+UTCCHN(A) + CONO DTS,770000 + MOVE B,URDWR(C) + MOVEM B,WRITE + MOVE C,TAP3 + MOVE B,TAP2 + MOVE A,TAP1 + JRST 12,@TAPE + +TAPFOR: TRO A,200000 + HRRM B,TAPCNT + HRRI B,TAPCNT + MOVEM B,DCMLOC + MOVE B,[-200,,UTP3] + HRRM B,UTP1 + HLLM B,TAPCNT + JRST TAP4 + UTERR: CONI DTS,E + SKIPL SMODE + JRST UDATER +; SKIPGE UDCC +; SETOM DCFREE +UTER5: SKIPN C,SUNIT + JRST JDB3 + SETOM DG2(C) + SKIPL UFLAPF(C) + JRST UTER6 + CLEARM UFLAPF(C) + CLEARM EUPOS(C) + CLEARM UDIR(C) + CLEARM OUDIR(C) + CONO DTC,400000 ;STOP DRIVE + JRST JDB3 + +UTER6: AOS UTERP(C) + HRLM E,UTERP(C) + TRNN E,20000 + JRST JDB3 ;END ZONE + MOVNS B,UDIR(C) + MOVEI A,0 + SKIPGE B + MOVEI A,1103 + MOVEM A,EUPOS(C) + MOVE A,TIME + MOVEM A,ULCTM(C) + MOVEM A,DRTM(C) + JRST JDB7 + +UDATER: CONO DTS,770001 ;ENABLE ALL INTERUPTS AND STOP FUNCTION + SETOM SMODE + HLRZ D,ULDCH(C) + CLEARM UTLDD(D) + JRST JDB3 + UTCB0: MOVE C,SUNIT + AOSE CUINT ;SKIP IF CLOCK CAUSED INTERUPT + JRST JDBRK ;NOT TIME FLAG +UTCB1: MOVE B,UDIR(C) + AOSN UTHERR ;HANG UP ERROR SENT FOR SLOW CLOCK ROUTINE + JRST UTERR + JRST JDB3 + +JDDT3: MOVE A,EUPOS(C) ;AFTER DATA XFER + SUB A,UGOAL(C) + MOVMS E,A + ADD A,TIME + MOVEM A,DRTM(C) + MOVE C,[-NUNITS,,1] + MOVM B,DRTM(C) + CAMGE B,TIME + JRST JDB3 ;SOMETHING ELSE DUE + AOBJN C,.-3 + MOVE C,SUNIT + SOJLE E,JDB7 ;RELOADING FOR NEXT BLOCK + JRST JDB3 + ILLP: MOVEM D,UGOAL(C) ;LOW PRIORITY POSIT ENTRY + MOVSI A,(SETZ) + IORM A,ULDCH(C) + +UTDC: SKIPGE UGOAL(C) + POPJ P, ;UNIT IDLE + SKIPGE DG2(C) + JRST UTDC3 +UTDC1: MOVE A,EUPOS(C) ;ESTIMATE UNIT TIME AND UPDATE EUPOS + SKIPG DG2(C) ;SKIP ON EXACT POS KNOWN + SKIPN UDIR(C) ;SKIP ON UNIT RUNNING + JRST UTDC4 + MOVE B,TIME + SUBM B,ULCTM(C) + EXCH B,ULCTM(C) + IMUL B,UDIR(C) + ADD A,B ;ACTUAL ESTIMATED POSITION + MOVEM A,EUPOS(C) ;UPDATE EUPOS +UTDC4: SUB A,UGOAL(C) + MOVM B,A + CAIG B,2 + JRST UTDC2 + ADD A,UDIR(C) + MOVMS Aî + CAMLE A,B + SETZB A,B ;GOING WRONG DIR +UTDC2: CAILE B,200. + MOVEI B,200. ;LIMIT LONGEST DEAD RECKON + ADD B,TIME + MOVEM B,DRTM(C) + POPJ P, + +UTDC3: MOVEI B,0 ;NOT KNOWN EXACT POS REQUIRES IMMEDIATE ATTENTION + JRST UTDC2 + +JDBRK: CONSZ DTC,7 + CONSO DTS,2 + JRST POPRET + CONSZ DTS,670300 + JRST UTERR + CONSO DTS,100000 + JRST POPRET + SKIPL SMODE + JRST JDDTA ;DATA MODE +JDB3: +; SKIPGE UDCC +; SETOM DCFREE + HRLOI B,177777 + MOVEM B,UTTM2 + SETZM UTTM4 + SETOM UTTM3 ;UNIT MOST URGENT + CLEARM UTTM1 ;UNIT COULD START + MOVE C,[-NUNITS,,1] + JDBRK7: SKIPGE B,UFLAPF(C) + JRST JDF1 ;FLAPPING OP +JDF2: SKIPL ULDCH(C) ;SKIP ON LOW PRIOR POSIT + SKIPGE UGOAL(C) + JRST JDB6 ;UNIT FREE +JDS1: SKIPE UDIR(C) + JRST JDBRK4 + SKIPN UTTM1 ;UNIT TO START + HRRZM C,UTTM1 + JRST JDBRK6 +JDBRK4: MOVE B,DRTM(C) + SUB B,TIME + MOVE E,B + SUB E,UTTM2 ;TIME SOME OTHER UNIT NEEDS ATTN + JUMPL B,JDCV1 ;ALREADY OVERDUE + MOVM D,E + CAIG B,20. ;CONFLICT MORE THAN 20 BLKS AWAY + CAIL D,20. ;THEY ARE SEPARETED BY 20 BLKS + JRST JDCV1 + HRRZS C ;RELIEVE CONFLICT BY STOPPING UNIT DUE LATEST + CAMG B,UTTM2 + HRRZ C,UTTM3 +JDF5: PUSHJ P,JDSTP ;STOP UNIT + JRST JDB3 + +JDCV1: JUMPGE E,ULLP + MOVEM B,UTTM2 ;UNIT DUE SOONEST + HRRZM C,UTTM3 +ULLP: SKIPL ULDCH(C) + JRST JDBRK6 + MOVE B,TIME ;LOW PRIORITY POSIT IN PROGRESS + SUB B,ULCTM(C) + IMUL B,UDIR(C) + SKIPE DG2(C) + MOVEI B,0 + ADD B,EUPOS(C) + SUB B,UGOAL(C) + MOVMS B + CAIGE B,10. + PUSHJ P,ULLP1 ;TERM LOW PRIORITY DIRECTORY POS (COMMIT TO ACTUAL WRITE) + JDBRK6: AOBJN C,JDBRK7 + MOVE C,UTTM3 ;MOST PRESSING RUNNING UNIT + MOVE B,UTTM2 + CAIGE B,30. + JRST JDB7 ;STAY WITH PRESSING UNIT + SKIPE UTTM1 + JRST JDB5 ;START UNIT IF POSSIBLE +JDF6A: CAMG B,[10000000.] + JRST JDB7 + AOSE UTTM4 ;DON'T IF FLAP OP STILL IN PROGRESS + PUSHJ P,JDDS + SETOM UIDLE + JRST POPRET + +JDF1: MOVE E,UDIRO(C) + AOJE E,JDF1A + TLNE E,100000 + JRST JDF2 +JDF1A: SKIPGE UGOAL(C) ;FLAPPING OP + SKIPGE ULDCH(C) + JRST JDF2 + SKIPE UDIR(C) + SKIPG DG2(C) + JRST .+2 + JRST JDF3A ;HAVE JUST READ IN TAPE POS + TLNN B,100000 + JRST JDF3 ;UNIT TO START FLAPPING (I.E. READ IN TAPE POS, THEN FLAP) + LDB D,[4000,,B] + TLNN B,100000 + JRST JDBRK6 + TLNN B,200000 ;ABORT FLAPPING + CAMG D,TIME + JRST JDF4 ;UNIT TO STOP FLAPPING + SETOM UTTM4 ;INDICATE FLAP OP STILL ACTIVE + JRST JDBRK6 + +JDDS: CONO DTC,10000 ;DESELECT + CLEARM SUNIT + POPJ P, + +JDSTP: MOVEI A,430000 + SETZM UDIR(C) + SETZM OUDIR(C) +JDCNN: HRRZS C + CAME C,SUNIT ;DIR CONO IN A TO UNIT IN C + SKIPN SUNIT + JRST JDSTP1 + PUSHJ P,JDDS +JDSTP1: DPB C,[110300,,A] + CONO DTC,(A) + MOVEM C,SUNIT + POPJ P, + +JDF3: MOVE A,UDIRO(C) ;WANT TO FLAP + AOJE A,JDF3A1 ;DIR NOT IN + TLNE A,10000 + JRST JDF3A2 ;TAPE IN UBLAT MODE (COMMENT USED TO SAY DIR ON WAY IN) (??) + HRRZ A,ULDCH(C) + LDB Q,[IOCH,,IOBFT(A)] + CAIE Q,NUTIC+NUTOC + JRST 4,. + LDB Q,[IOLO,,IOBFT(A)] + CAIE Q,(C) + JRST 4,. + PUSHJ P,IBRTN ;RETURN DIR BUFFER +JDF3A2: SETOM UDIRO(C) + SETZM UTASS(C) +JDF3A1: SETOM UDPWF(C) + SKIPGE DG2(C) + JRST JDF6 +JDF3A: SETOM DG2(C) ;FLAP UNIT INC(KNOWING WHERE IT IS) + MOVE E,EUPOS(C) + IMULI E,50. ;50 MS/BLOCK + IDIVI E,33. ;33 MS/(1/2 SEC) + ADDI E,30. ;15 SECS EXTRA + ADD E,TIME ;NET TIME TO STOP FLAPPING + TLO E,100000 + DPB E,[4200,,UFLAPF(C)] + LSH C,9. + CONO DTC,130000(C) ;GO REVERSE + PUSHJ P,JDDS + JRST JDB3 + +JDF6: HRRZS C + SETOM UDIR(C) + JRST JDB7 + +JDF4: TLNE B,40000 + JRST JDF4A + MOVEI A,230000 ;A SHOT OF FOWARD + PUSHJ P,JDCNN ;REEL WILL STOP + AND B,[700000,,] + ADD B,[40000,,2] + ADD B,TIME + MOVEM B,UFLAPF(C) + JRST JDB3 + +JDF4A: PUSHJ P,JDSTP + CLEARM UFLAPF(C) + CLEARM EUPOS(C) + SETOM DG2(C) + JRST JDF5 + JDB5: HRRZ C,UTTM1 + MOVE E,UGOAL(C) + CAML E,EUPOS(C) + SKIPA B,[1] + MOVNI B,1 + MOVEM B,UDIR(C) +JDB7: SKIPN B,UDIR(C) + JRST 4,. ;NOT TRYING TO GO + MOVEI A,DCCHN_3 + SKIPN SUNIT + JRST DCGB1 + CAME C,SUNIT + JRST DCGB2 + CAMN B,OUDIR(C) + TRO A,40000 ;INHIBIT START DELAY (SAME UNIT, SAME DIRECTION) +DCGB1: MOVEM C,SUNIT + MOVEM B,OUDIR(C) + TRNN A,40000 + TRO A,30000 + DPB C,[110300,,A] + XCT UTST2(B) + CONO DTS,770000 + MOVE C,[JSR TAPE] + MOVEM C,DCMLOC + MOVEM C,DCMLOC+1 + MOVE C,[JRST PIPOS] + MOVEM C,UTP1 + JRST POPRET + +DCGB2: PUSHJ P,JDDS + JRST DCGB1 + + CONO DTC,130200+UTCCHN+(A) +UTST: CONO DTC,430000+UTCCHN+(A) + CONO DTC,230200+UTCCHN+(A) + + CONO DTC,130200+UTCCHN(A) +UTST1: CONO DTC,430000+UTCCHN(A) + CONO DTC,230200+UTCCHN(A) + + CONO DTC,100200+UTCCHN(A) +UTST2: CONO DTC,400000+UTCCHN(A) + CONO DTC,200200+UTCCHN(A) +};IFN NEWDTP + IFE NEWDTP,{ + +; T S UTAPE ROUTINES PI SERV (OLD UTAPE CONTROL) + +JDENB==40000 ;ENABLE JOB DONE (CONO UTC,) +20MSEN==5000 ;20MS, ENABLED (") + +TAPE: 0 +UTP1: 0 ;DATAI DC, OR JRST UTP3 + +BBLK + + SOS .-1 + AOSGE TAPCNT + JRST 12,@TAPE + + +UTP3: SKIPN WRITE + CONO DC,0 + CONO DC,400000 ;CLEAR PIA + JRST 12,@TAPE + +PIPOS: CONSO DC,1000 + JRST PIPX + SKIPN C,SUNIT + JRST PIPOS8 ;NO UNIT SELECTED? + DATAI DC,B ;UNIT SELECTED, GET BLOCK NUMBER + TDZE B,[1777#-1] ;CLEAR OUT GARBAGE IN BLOCK NUMBER WORD + JRST PIPOS7 ;GARBAGE THERE, BAD BLOCK NUMBER + MOVEM B,EUPOS(C) ;STORE POSITION + HRRZM C,DG2(C) ;SIGNAL EUPOS IS ACCURATE + SKIPGE UGOAL(C) ;GOING SOMEWHERE? + JRST PIPF1 ;NO + SUB B,UGOAL(C) ;GET CURRENT - DESIRED + JUMPE B,PIPOS2 ;JUMP IF THERE + ADD B,UDIR(C) + MOVMM B,UTENB + SKIPGE ULDCH(C) + JRST PIPOS3 + JUMPN B,PIPOS3 +PIPOSL: MOVE A,SUNITL ;HOLD DC + MOVE B,UDIR(C) + XCT UTST(B) + CONO DC,4010+UTCCHN +PIPOS5: JRST PIPX + +PIPOS7: AOS BDBLKC + JRST PIPOSL + +EBLK + +BDBLKC: 0 + +BBLK + +PIPOS3: MOVE A,UDIR(C) + LSH A,2 + SUB B,A + XOR B,UDIR(C) + MOVE A,SUNITL + JUMPG B,PIPOS4 ;GOING WRONG DIR +PIPF2: TRO A,JDENB ;ENB JD SO NEXT BREAK TO UTC ON BLOCK +PIPOS6: MOVE B,TIME + MOVEM B,ULCTM(C) + ADD B,UTENB + MOVEM B,DRTM(C) + MOVE B,UDIR(C) + XCT UTST(B) +PIPOS8: CONO DC,0 + JRST PIPOS5 + + + +PIPF1: MOVE A,SUNITL + JRST PIPF2 + +PIPOS4: CLEARM DG2(C) + MOVNS UDIR(C) + TRO A,6000 + JRST PIPOS6 + +PIPOS2: HLRZ A,ULDCH(C) ;TAPE NOW POSITIONED + SKIPL ULDCH(C) + SKIPGE UTRAC(A) + JRST PIPOS3 ;CHANNEL LOCKED + SETOM UTLDD(A) ;CHANNEL ACTUALLY LOADED TRANSFER IMMINENT + AOS SMODE + MOVE A,SUNITL + MOVE B,UMEMAD(C) + SKIPGE URDWR(C) + TROA A,400 + TLZ B,(BLKO-BLKI) + SKIPL UDIR(C) + JRST TAPFOR + TRO A,10000 + ADD B,[DATAI-BLKI 200] + MOVEM B,UTP1 + MOVNI B,200 + MOVEM B,TAPCNT + + +TAP4: CONO UTC,360300+UTCCHN(A) + MOVE B,URDWR(C) + MOVEM B,WRITE + CONO DC,400000+DCCHN ;GIVE CHN FOR READ + SKIPGE B + CONO DC,3410+DCCHN + JRST PIPX + + +TAPFOR: HRRM B,TAPCNT + HRRI B,TAPCNT + MOVEM B,DCMLOC + MOVE B,[-200,,UTP3] + HRRM B,UTP1 + HLLM B,TAPCNT + JRST TAP4 + +UTERR: CONSZ UTC,4000 ;CHECK TIME ENABLE + CONSO UTS,20 ;CHECK TIME FLAG + JRST .+2 + JRST UTCB1 ;ELIMINATE TIMING ERROR IF FLAG COMES ON + CONI UTS,E + SKIPL SMODE + JRST UDATER ;DATA ERROR + CONO DC,0 + SKIPN C,SUNIT + JRST JDB3 ;NO UNIT SELECTED, IGNORE ERROR + SETOM DG2(C) + SKIPL UFLAPF(C) + JRST UTER6 ;NOT FLAPPING + CLEARM UFLAPF(C) ;ERROR WHILE FLAPPING, JUST FORGET ABOUT IT + CLEARM EUPOS(C) + CLEARM UDIR(C) + JRST JDB3 +UTER6: AOS UTERP(C) ;INCREMENT ERROR COUNT + HRLM E,UTERP(C) ;STORE UTS CONI + MOVE B,UDIR(C) + TRZ E,7650 ;CLEAR RANDOMNESS, WRITE, PARITY ERROR + JUMPE E,JDB3 ;JUMP ON ONLY PARITY ERROR (IF ANYTHING), TRY AGAIN NOW + TRNN E,2 ;CHECK EOT FLAG + JRST UTER1 ;NOT SET + MOVNS B,UDIR(C) ;EOT, WANT TO GO OTHER DIRECTION + MOVEI A,0 + SKIPGE B + MOVEI A,1103 + MOVEM A,EUPOS(C) ;STORE NEW ESTIMATED POSIION + MOVE A,TIME + MOVEM A,ULCTM(C) + MOVEM A,DRTM(C) +UTER1: JRST UTER3 ;GIVE MAX DELAY + +UDATER: SETOM SMODE ;DATA ERROR, TRY REPOSITIONING + HLRZ D,ULDCH(C) + CLEARM UTLDD(D) + JRST JDB3 + + UTCB0: MOVE C,SUNIT + CONSZ UTC,4000 + CONSO UTS,20 + JRST JDBRK ;NOT TIME FLAG +UTCB1: MOVE A,SUNITL + MOVE B,UDIR(C) + AOSN UTHERR ;HANG UP ERROR SENT FOR SLOW CLOCK ROUTINE + JRST UTERR + AOSN USTSW + JRST DCGBL1 + AOSN USTPF + JRST JDB7D + MOVEI C,0 + EXCH C,FLPUNT + JUMPN C,JDF8 + EXCH C,STPUNT + JUMPN C,JDB4B + JRST JDB3 + + +JDDT3: MOVE A,EUPOS(C) + SUB A,UGOAL(C) + MOVMS E,A + ADD A,TIME + MOVEM A,DRTM(C) + MOVE C,[-NUNITS,,1] + MOVM B,DRTM(C) + CAMGE B,TIME + JRST JDB3 ;SOMETHING ELSE DUE + AOBJN C,.-3 + MOVE C,SUNIT + MOVE B,UDIR(C) + MOVE A,SUNITL + SOJLE E,DCGBL1 ;RELOADING FOR NEXT BLOCK + JRST JDB3 + + +ILLP: MOVEM D,UGOAL(C) ;LOW PRIORITY POSIT ENTRY + MOVSI A,(SETZ) + IORM A,ULDCH(C) + +UTDC: SKIPGE UGOAL(C) + POPJ P, ;UNIT IDLE + SKIPGE DG2(C) + JRST UTDC3 + MOVE A,EUPOS(C) ;ESTIMATE UNIT TIME AND UPDATE EUPOS + SKIPG DG2(C) ;SKIP ON EXACT POS KNOWN + SKIPN UDIR(C) ;SKIP ON UNIT RUNNING + JRST UTDC4 + MOVE B,TIME + SUBM B,ULCTM(C) + EXCH B,ULCTM(C) + IMUL B,UDIR(C) + ADD A,B ;ACTUAL ESTIMATED POSITION + MOVEM A,EUPOS(C) ;UPDATE EUPOS +UTDC4: SUB A,UGOAL(C) + MOVM B,A + CAIG B,2 + JRST UTDC2 + ADD A,UDIR(C) + MOVMS Aî + CAMLE A,B + SETZB A,B ;GOING WRONG DIR +UTDC2: CAILE B,200. + MOVEI B,200. ;LIMIT LONGEST DEAD RECKON + ADD B,TIME + MOVEM B,DRTM(C) + POPJ P, + +UTDC3: MOVEI B,0 ;NOT KNOWN EXACT POS REQUIRES IMMEDIATE ATTENTION + JRST UTDC2 + +JDBRK: CONSZ UTS,16 ;CHECK PARITY ERROR, ILLOP, EOT + JRST UTERR +JDBK1: CONSZ UTS,1 ;SKIP ON NO JOB DONE + CONSZ DC,7 + JRST POPRET ;NO ERRS + HAS DC CHNL, GO AWAY + SKIPL SMODE + JRST JDDTA ;DATA MODE + JUMPE C,JDB3 ;POSITIONING, JUMP ON NO UNIT SELECTED + MOVE A,UDIR(C) + ADDM A,EUPOS(C) + MOVE A,TIME + MOVEM A,ULCTM(C) + PUSHJ P,UTDC ;COMPUTE DELAY + + JDB3: CONO DC,0 + HRLOI B,177777 + MOVEM B,UTTM2 + SETOM UTTM3 ;UNIT MOST URGENT + CLEARM UTTM1 ;UNIT COULD START + SETOM UTTM4 ;TAPE TO START FLAPPING + SETOM UTTM5 ;TAPE TO STOP FLAPPED + MOVE C,[-NUNITS,,1] +JDBRK7: SKIPGE B,UFLAPF(C) + JRST JDF1 ;FLAPPING OP +JDF2: SKIPL ULDCH(C) ;SKIP ON LOW PRIOR POSIT + SKIPGE UGOAL(C) + JRST JDB6 ;UNIT FREE +JDF2A: SKIPGE DG2(C) + SKIPN UDIR(C) + JRST JDS1 + MOVEM C,UTTM1 ;UNIT IS RUNNING BLIND (OR NOT RUNNING) + JRST JDBRK6 +JDS1: SKIPE UDIR(C) + JRST JDBRK4 + SKIPN UTTM1 + HRRZM C,UTTM1 + JRST JDBRK6 +JDBRK4: SKIPN UDIR(C) + JRST ULLP ;TAPE MAY NOT BE RUNNING IF IDLE + MOVE B,DRTM(C) + SUB B,TIME + MOVE E,B + SUB E,UTTM2 + JUMPL B,JDCV1 ;ALREADY OVERDUE + MOVM D,E + CAIG B,20. ;CONFLICT MORE THAN 20 BLKS AWAY + CAIL D,20. ;THEY ARE SEPARETED BY 20 BLKS + JRST JDCV1 + HRRZS C ;RELIEVE CONFLICT BY STOPPING UNIT DUE LATEST + CAMG B,UTTM2 + HRRZ C,UTTM3 +JDF5: CAME C,SUNIT + SKIPN SUNIT + JRST JDB4B ;STOP UNIT + MOVEM C,STPUNT + JRST JDB7D ;DESLECT FIRST +JDCV1: JUMPGE E,ULLP + MOVEM B,UTTM2 + HRRZM C,UTTM3 +ULLP: SKIPL ULDCH(C) + JRST JDBRK6 + MOVE B,TIME + SUB B,ULCTM(C) + IMUL B,UDIR(C) + SKIPE DG2(C) + MOVEI B,0 + ADD B,EUPOS(C) + SUB B,UGOAL(C) + MOVMS B + CAIGE B,10. + PUSHJ P,ULLP1 ;TERM LOW PRIORITY DIRECTORY POS (COMMIT TO ACTUAL WRITE) + + + +JDBRK6: AOBJN C,JDBRK7 + MOVE C,UTTM3 ;MOST PRESSING RUNNING UNIT + MOVE B,UTTM2 + CAIGE B,30. + JRST JDB7 ;STAY WITH PRESSING UNIT + SKIPE UTTM1 + JRST JDB5 ;START UNIT IF POSSIBLE + SKIPL D,UTTM4 + JRST JDF3 +JDF6A: SKIPL D,UTTM5 + JRST JDF4 + CAMG B,[10000000.] ;SKIP ON ALL TAPES IDLE + JRST JDB7 + SKIPE SUNIT + JRST JDB7D + SETOM UIDLE ;NO UNIT SELECTED + CONO UTC,0 + JRST POPRET + +JDF1: MOVE E,UDIRO(C) + AOJE E,JDF1A + TLNE E,100000 + JRST JDF2 ;DONT FLAP IF DIR NOT WRITTEN +JDF1A: SKIPGE UGOAL(C) + SKIPGE ULDCH(C) + JRST JDF2 ;FILE DIR WRITE IN PROG + SKIPE UDIR(C) + SKIPG DG2(C) + JRST .+2 + JRST JDF3A ;JUST READ IN TAPE POS + TLNN B,100000 + HRRZM C,UTTM4 ;UNIT TO START FLAPPING + LDB D,[4100,,B] + TLNN B,100000 + JRST JDBRK6 + TLNN B,200000 ;ABORT FLAPPING + CAMG D,TIME + HRRZM C,UTTM5 ;UNIT TO STOP FLAPPING + JRST JDBRK6 + + +JDF3: MOVE C,D + MOVE A,UDIRO(C) + AOJE A,JDF3A1 + TLNE A,10000 + JRST JDF3A2 + HRRZ A,ULDCH(C) + LDB Q,[IOCH,,IOBFT(A)] + CAIE Q,NUTIC+NUTOC + JRST 4,. + LDB Q,[IOLO,,IOBFT(A)] + CAIE Q,(C) + JRST 4,. + PUSHJ P,IBRTN +JDF3A2: SETOM UDIRO(C) + SETZM UTASS(C) +JDF3A1: SETOM UDPWF(C) + SKIPGE DG2(C) + JRST JDF6 +JDF3A: SETOM DG2(C) + MOVE E,EUPOS(C) + IMULI E,50. + IDIVI E,33. + ADDI E,30. + ADD E,TIME + DPB E,[4100,,UFLAPF(C)] + MOVSI E,100000 + IORM E,UFLAPF(C) + SKIPE SUNIT + CAMN C,SUNIT + JRST JDF8 + MOVEM C,FLPUNT + JRST JDB7D + +JDF8: LSH C,3 + CONO UTC,235000+UTCCHN(C) + JRST JDF9 + +JDF6: SKIPE SUNIT + CAMN C,SUNIT + JRST .+2 + JRST JDB7D + SETOB B,UDIR(C) + MOVEM C,SUNIT + DPB C,[30300,,SUNITL] + JRST JDF6B + +JDF4: MOVE C,D + CLEARM UFLAPF(C) + CLEARM EUPOS(C) + JRST JDF5 + +JDB5: HRRZ C,UTTM1 +JDB7: EXCH C,SUNIT ;SELECT UNIT IN C + JUMPE C,JDB7A ;NO UNIT SELECTED + CAMN C,SUNIT + JRST JDB7A + PUSHJ P,URLS + JUMPGE E,JDB7E ;OK TO LEAVE IT ALONE, CLEAR SELECTION CYCLE + SKIPN UDIR(C) + JRST JDB7E +JDB4B: HRRZM C,SUNIT ;ENTER UNIT STOPPING CYCLE + DPB C,[30300,,SUNITL] +JDB4A: MOVE A,SUNITL + SKIPG UDIR(C) + TRO A,10000 + CONO UTC,205000+UTCCHN(A) ;CLEAR GO BIT + SKIPE DG2(C) + JRST JDB4A1 + MOVE B,TIME + SUB B,ULCTM(C) + IMUL B,UDIR(C) + ADDM B,EUPOS(C) +JDB4A1: CLEARM UDIR(C) + HRLOI B,177777 + MOVEM B,DRTM(C) + SETOM DG2(C) +JDF9: SETOM USTPF ;UNIT STOPPING CYCLE + JRST POPRET + +EBLK + +USTPF: 0 +STPUNT: 0 ;UNIT TO STOP DUE TO CONFLICT + +BBLK + +JDB7E: SKIPA A,C +JDB7D: MOVE A,SUNIT + JUMPE A,JDB7D1 + SKIPLE DG2(A) + CLEARM DG2(A) +JDB7D1: CLEARM SUNIT ;DESELECT CYCLE + CONI UTC,A + TRZ A,200070 + TRO A,5000 + CONO UTC,(A) + JRST POPRET + + +JDB7A: MOVE C,SUNIT + MOVE A,EUPOS(C) + SUB A,UDIR(C) + SUB A,UDIR(C) + MOVEI B,1 + CAML A,UGOAL(C) + MOVNI B,1 + DPB C,[30300,,SUNITL] + MOVE D,UDIR(C) + MOVEM B,UDIR(C) + CAME D,B + JRST JDS4 ;CHANGING DIR (OR STARTING), ALLOW RELAY DLYS +JDBK3A: MOVE E,DRTM(C) + SUB E,TIME +JDDT8: MOVE A,SUNITL +IFN IMXP,[ + SKIPL IMPXF + SUBI E,2 +] + SKIPGE E + MOVEI E,0 + SKIPL D,DG2(C) + CAIG E,2 + JRST JDB3B + CAIGE E,20 + JUMPE D,JDB3B ;GETTING CLOSE READ BLOCK NO +JDB3A: +DCGBL2: TRO A,JDENB +JDB8A: XCT UTST(B) + JRST POPRET + + + +JDB3B: +DCGBL1: XCT UTST(B) + MOVE C,[JSR TAPE] + MOVEM C,DCMLOC + MOVEM C,DCMLOC+1 + MOVE C,[JRST UTP1] + MOVEM C,UTP1 + CONO DC,4010+UTCCHN + JRST POPRET + + + + CONO UTC,330200+UTCCHN(A) +UTST: CONO UTC,5000+UTCCHN(A) + CONO UTC,320200+UTCCHN(A) + + +JDS4: JUMPN D,UTER3 + MOVE D,TIME + MOVEM D,ULCTM(C) +JDF6B: SETOM USTSW ;STARTING OUT +UTER3: MOVE A,SUNITL ;PICK UP UNIT SELECT FIELD OF CONO + TRO A,6000 ;SET FOR MAXIMUM DELAY + JRST JDB8A + +URLS: SKIPE E,UDIR(C) ;SKIPN ON UNIT NOT RUNNING + SKIPG E,DG2(C) ;RELEASE UNIT IN C E HAS PREV STATE OF DG2 + POPJ P, + JRST UTDC +};IFE NEWDTP diff --git a/src/system/whovar.5 b/src/system/whovar.5 new file mode 100755 index 00000000..0aa8b2d7 --- /dev/null +++ b/src/system/whovar.5 @@ -0,0 +1,158 @@ +;channel header pointer (location 40, read only) +; +; ADDRESS(channel header area) +; ADDRESS(pointer area) +; I/O version number +; source file version number +; 0 always 0 +; INITED non-zero indicates PDP-11 is running ok(can be cleared by PDP-10) +; 0 always 0 +; GDOWN used as flag by PDP-10 to acknowledge clear of INITED +; +;channel header area (aligned on PDP-10 word) +; +; KBD channel: +; KBDFLG cleared by 10/set by 11 (chain of activated KBD buffers) +; 0 allows PDP-10 to do SKIPN for activation test +; DPY channel: (1 per console) +; DPYCHN buffer assigned to channel, if zero then DPY channel is closed +; DPYKBD .BYTE KBD#, DPY# (377 for either implies not assigned) +; KBD flags: (1 per console) +; ECOFLG Set by PDP-10. Next time DPYBUF is empty clear ECOFLG +; and put flag on KBD ring to signal this condition +; CHNCLS if -1, log this guy out!!!! +; WHO flags: (1 per console) +; WHOLIN who line variables for this console +; WHOUSR -1=>do system line, 0=>user who line +; +;format of KBD buffer (aligned on PDP-10 word) +; +; KBDSTS negative=>-(data byte count), 0=>free +; 0 +; KBDRNG next KBD buffer associated with this KBD +; KBDLST next buffer on activated list (0=>end of chain) +; KBDCHN keyboard channel +; 0 not used +; KBDATA key board data area (1 PDP-11 word/character) +; +;format of DPY buffer (aligned on PDP-10 word) +; +; DPY10B word PDP-10 is hacking (used only for initailization) +; DPY11B word PDP-11 is hacking +; DPYPP page printer variables +; DPYLGL last legal address in this buffer +; DPYSIZ size of data area in bytes +; 0 not used +; DPYATA display data area (1 PDP-11 word/character) +; +;format of pointer area (aligned on PDP-10 word) +; +; ADDRESS(system who line variables) +; ADDRESS(PDP-10/PDP-11 communication area) +; TENWHO (SET TO -1 WHENEVER ANYONE TYPES WHO LINE COMMAND, RESET TO 0 WHEN 10 +; UPDATES WHO LINES +; TENWH1 PADDING +; +;Notes: +; +;1. All addresses and pointers are in PDP-11 address space. +; +;2. KBD buffers are ringed two per channel. While the PDP-10 is +; emptying one, the PDP-11 can fill the other. +; +;3. There is only one DPY buffer per channel. When the buffer is filled +; with negative numbers, it is free. When the PDP-10 writes a positive +; number in the current word: then the PDP-11 processes the data in that +; word, sets that word to a negative number, and advances to the next word. +; WHO LINE VARIABLES +; +;SYSTEM WHO LINE (one PDP-11 word/line unless otherwise indicated) +; ITSTCH # total # 10/11 dpy channels (read only for PDP-10) +; ITSCHN # 10/11 dpy channels in use (read only for PDP-10) +; ITSVER ITS version # +; ITSJOB total jobs +; ITSCOR total core +; ITSRU runnable users +; ITSWBJ # jobs swap blocked +; ITSJWP # jobs waiting for pages +; ITSTRC total runable core +; ITSCFU core available for users +; ITSDAT date [byte (7) year (4) month (5) day] +; ITSDBG system debug flag +; ITSTIM time of day (# half seconds since midnight) aligned on PDP-10 word +; ITSTI1 low order of time +; ITSUSR total number of users +; +;USER WHO LINE (One PDP-11 word per line unless otherwise noted) + WHJOB==0 ;job #, -1=>who line not in use +; WHJOB1 ;pads WHJOB + WHMODE==1 ;mode 0=>follow keyboard +; 1=>freeze +; 2=>next higher (when PDP-10 sees this state, it searches +; user variables for next higher job index number with same +; uname. When it finds it, it stores the number in job # +; and changes mode to 1 +; 3=>next lower +; WHMOD1 ;pads WHMODE + WHUNAM==2 ;uname in sixbit (left 18 bits in first two words, right in next two) +; WHUNM1 + WHUNM2==3 +; WHUNM3 + WHJNAM==4 ;jname in sixbit +; WHJNM1 + WHJNM2==5 +; WHJNM3 + WHSNAM==6 ;sname in sixbit +; WHSNM1 + WHSNM2==7 +; WHSNM3 + WHSTAT==10 ;status in sixbit, 0=>job does not exist +; WHSTA1 + WHSTA2==11 +; WHSTA3 + WHJ%RT==12 ;job % run time +; WHJTRT job total run time (one millisec units) +; WHRPAG job number of pages real mem assigned +; WHPAG job number of pages virtual mem assigned +; WHO1 user who line control word +; WHO1A +; WHO2 first user who line variable +; WHO2A +; WHO2B +; WHO2C +; WHO3 second user who line variable +; WHO3A +; WHO3B +; WHO3C +; +; +;NOTE: The PDP-11 will not update who lines until it sees that ITSTIM +; has changed. +; +;PDP-10/PDP-11 COMMAND CHANNEL +; +; CMDFLG aligned on PDP-10 +; 0=>buffer is free (PDP-10 can write CMDBUF) +; positive=>command # from PDP-10 (PDP-11 can write CMDBUF) +; negative=>affirmative reply from PDP-11 (0=>command failed) +; PDP-10 can read CMDBUF, then must zero CMDFLG +; CMDFL1 always 0 +; CMDBUF each arg takes 4 bytes (1 PDP-10 word) +; +; PDP-10/PDP-11 COMMANDS +; +; 1 video switch +; arg1: video switch input # (set by PDP-10) +; arg2: video switch output # ( " " " " ) +; +; 2 reserve DPY +; arg1: DPY reserved (set by PDP-11) +; +; 3 free DPY +; arg1: DPY to free (set by PDP-10) +; +;;other 10-11 commuincation issues .. +; +;;go down resetting video switch vs not +;;PDP-11 indicates it has reset video switch +; ;(PDP-10 then detaches all jobs with tv ttys) diff --git a/tools/itstar b/tools/itstar new file mode 160000 index 00000000..63ecbaa4 --- /dev/null +++ b/tools/itstar @@ -0,0 +1 @@ +Subproject commit 63ecbaa4989cf9abf0235c114bcb72575ae657f9 diff --git a/tools/tapeutils b/tools/tapeutils new file mode 160000 index 00000000..2d4559f2 --- /dev/null +++ b/tools/tapeutils @@ -0,0 +1 @@ +Subproject commit 2d4559f2da7838031b7d85100b923519b17cdcb7