; Alto 1822 Interface microcode

; Larry Stewart
; Special version for scatter/gather
; Last modified July 18, 1978 4:03 PM

#AltoConsts23.mu;

; Address definition for Emulator main loop in ROM

$START $L004020,000000,000000 ; Start of emulator main loop

; Task Specific Function Definitions

$IREAD $L000000,070017,000100 ; F1-17
Input data
$IWRITE$L020016,000000,124000 ; F1-16
Output data
$IOCLR $L016015,000000,000000 ; F1-15
Clear hardware output wakeup
$IPOSTF$L016014,066014,000100 ; F1-14
Post (gate status to bus)
$ISWAKC$L024014,000000,000000 ; F2-14
Clear SIO generated wakeup
$IBRNCH$L024013,000000,000000 ; F2-13
4-way branch on wakeup
$IIENBL$L024012,000000,000000 ; F2-12
Start read (turn on RFNIB)
$ISETCS$L024011,000000,000000 ; F2-11
Set control functions from bus
$IPTMOD$L024010,000000,000000 ; F2-10
2-way branch on throwaway mode

;R (S) registers

$ICBPTR$R76;
Control Block Pointer
$MTEMP $R25;
Temporary storage
$AC1 $R2;
Emulator register
$NWW $R4;
Interrupt system reg

; Task constants

$ISDON $777;
done
$ISFUL $1377;
buffer full (input only)
$ISIBLZ$1777;
block length zero (input only)
$ISFDON$2377;
input full and end of packet

; Initialization for putting this code in the RAM, including
; ’silent boot’ code
!17,20,LOC0,,,,,IMLOOP,,,,,,,,,,;

;Silent Boot code, branches to ROM immediately
LOC0:
SWMODE;
:START;

;Main loop. Task waits here when not processing anything.

;IBRNCH gates two bits onto NEXT6 and NEXT7
; 00 - Start input 01 - Set Control
; 10 - Output data wakup 10 - Input data wakeup

; 4-way branch using NEXT6,NEXT7 (Caused by IBRNCH)
%14,14,0,IISTRT,ICTST,IODATA,IIDATA;

IMLOOP
:T← ICBPTR,IBRNCH;test wakeup conditions
L← ISDON,:IISTRT;[IISTRT,ICTST,IODATA,IIDATA]

;Common Post routine
; Expects offset of post location in T
;
and task status in M

;IPOSTF gates hardware status bits to the bus

; 2-way branch using NEXT9 (Caused by SH=0)
!1,2,IIBLOK,IPOST;

IPOST:MAR← ICBPTR+T;Start double reference
T← NWW;
;
;
MD← M,IPOSTF;Bus AND hardware status
L← MD OR T,TASK;NWW OR interrupt bits
INXT:
NWW← L,:IMLOOP;

;Read status and set control register

;ISWAKC clears a wakeup caused by an SIO instruction
;ISETCS loads hardware control flops from the bus

ICTST:MAR← L← AC1;Start fetch of args
ICBPTR← L;Save ctl block pointer
T← 6,ISWAKC;post location offset
SINK← MD,ISETCS;Control function
INEND:
L← ISDON,:IPOST;Set control flops

;Input initialization

;IIENBL enables the hardware to receive a 16 bit word (turns it on)

IISTRT:MAR← 2+T;
ISWAKC;clear wakeup
;
;
T← MD;read data pointer
L← MD-T;
L← ISIBLZ,SH=0;
T←10,:IIBLOK;[IIBLOK,IPOST]
IIBLOK:
L← NWW,IIENBL,TASK,:INXT;length ok,start reader

;Input Main loop

;IREAD gates the receiver shift register to the bus
; and the PAD flop to NEXT7
; If the branch is taken (which happens when the last word of
; a packet is read), the wakeup will not be cleared, otherwise
; the wakeup will be cleared

; 2-way branch using NEXT9 (Caused by SH=0)
!1,2,IIDMOR,IIDFUL;

; 2-way branch using NEXT7 (Caused by IREAD)
%4,4,0,IIDCON,IIDLST;

; another 2-way branch using NEXT7 (Caused by IREAD)
%4,4,0,IIFINS,IIBFDN;

IIDATA:MAR← L← 2+T;Start fetch
MTEMP← L;save cb ptr
T← MD;get pointer
L← MD-T-1;at end of buffer?
MAR← T;start data store
L← ONE+T,SH=0;
MD← IREAD,:IIDMOR;[IIDMOR,IIDFUL]
;
Read and branch on last word.
;
Except on the last word, this
;
clears the wakeup

IIDMOR:
MAR← MTEMP,:IIDCON;[IIDCON,IIDLST]

IIDCON:
IIENBL,TASK;enable receiver
IDCON:
MD← M,:IMLOOP;update ptr,restart

IIDLST:
TASK;this TASK only works
;
because the hardware doesn’t really clear the
;
wakeup until the next IREAD in this case

MD← M;update pointer
IIDPST:
L← ISDON;
IIWCLR:
SINK← IREAD;clear wakeup (again)
IIFINS:
T← 10,:IPOST;

IIDFUL:
L← ISFUL,:IIFINS;[IIFINS,IIBFDN]
IIBFDN: TASK;
NOP;
L← ISFDON,:IIWCLR;

;Main output loop

;IWRITE loads the output shift register from the bus,
; clears the (hardware generated) wakeup if there was one,
; and starts the output hardware

;IOCLR resets the output hardware. This is how you clear the
; wakeups without restarting the output hardware

;IPTMOD gates the state of the Throwaway mode flop to NEXT7
; The branch is taken if the flop was set (by an ISETCS)

; 2-way branches using NEXT9 (both caused by SH=0)
!1,2,IODMOR,IODEND;
!1,2,IONLST,IOLST;

; 2-way branch using NEXT7 (Caused by IPTMOD)
%4,4,0,IOBFUL,IOBEND;

IODATA:MAR← L← 4+T;start pointer fetch
MTEMP← L;save cb ptr
T← MD,IOCLR;get pointer,clear wakeup
L← MD-T;past end of buffer?
MAR← T,SH=0;start data fetch
L← M-1,:IODMOR;[IODMOR,IODEND]

IODMOR:
SH=0;Last word?
IWRITE← MD,:IONLST;send data [IONLST,IOLST]
IONLST:
MAR← MTEMP;clear wakeup
IOBFUL:
L← ONE+T,TASK,:IDCON;go around

IOLST:
MAR← MTEMP,IPTMOD;start update
L← ONE+T,:IOBFUL;[IOBFUL,IOBEND]

IOBEND:
SINK← 2,ISETCS;do last bit function,(if IPT)
MD← M,TASK;update pointer
NOP,:IMLOOP;restart

IODEND:
T← 11+1,:INEND;offset of post loc