; Alto 1822 Interface microcode

; Larry Stewart
; Last modified April 19, 1978 9:41 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
$ISOVF $1377;
buffer overflow (input only)
$ISIBLZ$1777;
block length zero (input only)

; 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

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

;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 IPTMOD)
%4,4,0,IIACPT,IIDISC;

; 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,IIDPST;

IIDATA:MAR← L← 2+T;Start fetch
MTEMP← L,IPTMOD;save cb ptr,test mode
T← MD;get pointer [IIACPT,IIDISC]
IIACPT:
L← MD-T;past end of buffer?
MAR← T,SH=0;start data fetch
L← ONE+T,:IIDMOR;[IIDMOR,IIDFUL]

IIDMOR:
MD← IREAD;Read and branch on last word.
;
Except on the last word, this
;
clears the wakeup
IICLNU:
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
L← ISDON;
IIDPST:
SINK← IREAD;clear wakeup (again)
IIFINS:
T← 10,:IPOST;

IIDISC:
L← T, T← IREAD,:IICLNU;throwaway word,branch if last

IIDFUL:
SINK← IREAD;overflow status
L← ISOVF,:IIFINS;[IIFINS,IIDPST]

;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

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

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:
IWRITE← MD,SH=0;send data,last?
MAR← MTEMP,:IONLST;start update [IONLST,IOLST]
IOLST:
SINK← 2,ISETCS;set last word function
IONLST:
L← ONE+T,TASK,:IDCON;finish

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