-- Copyright (C) 1982  by Xerox Corporation. All rights reserved. 
-- File: EtherBoot.mesa,  Edit: HGM February 2, 1981  11:28 PM
-- Snitched from Taft's EtherBoot.asm with a bit of help from Teco


DIRECTORY
  DiskLessDefs USING [];

EtherBoot: PROGRAM EXPORTS DiskLessDefs =
  BEGIN

  GetPointerToBootLoader: PUBLIC PROCEDURE RETURNS [POINTER] =
    BEGIN RETURN[@bootLoaderProgram]; END;

  bootLoaderProgram: ARRAY [31B..426B] OF WORD ← [
    --                             1	
    --                             2	; EtherBoot.asm - Alto Ethernet boot loader
    --                             3	; Implemented (with much blood and sweat) by E. A. Taft / July 1976
    --                             4	
    --                             5	;	Last modified January 2, 1978  1:54 PM
    --                             6	
    --                             7	.ent bootLoaderPacket
    --                             8	.ent EtherBoot
    --                             9	
    --                            10	.srel
    --                            11	
    --     0        31B           12	bootLoaderPacket: .bootLoaderPacket
    --     1         0B           13	EtherBoot: .EtherBoot
    --                            14	
    --                            15	.nrel
    --                            16	
    --                            17	; Format of an Ethernet-encapsulated Pup
    --               0            18	etherAdr = 0		; Destination/source bytes
    --               1            19	etherType = 1		; Ethernet type word
    --               2            20	pupLength = 2		; Pup length
    --               3            21	pupType = 3		; Transport control and type
    --               4            22	pupID = 4		; Pup ID (2 words)
    --               6            23	pupDNetHost = 6		; Pup destination net/host
    --               7            24	pupDSocket = 7		; Pup destination socket (2 words)
    --              11            25	pupSNetHost = 11	; Pup source net/host
    --              12            26	pupSSocket = 12		; Pup source socket
    --              14            27	pupContents = 14	; Pup contents start here
    --                            28	
    --             602            29	typeBreathOfLife = 602	; Ethernet type for a boot loader packet
    --            1000            30	typePup = 1000		; Ethernet type for a Pup
    --             244            31	typeMayday = 244	; Pup type for boot file request
    --               4            32	socketMiscServices = 4	; Socket to which request should be sent
    --              20            33	socketEFTPReceiver = 20	; Our EFTP receiver socket
    --                            34	
    --               3            35	page0origin = 3		; Where page 0 portion of loader runs
    --             624            36	page1origin = 624	; Where page 1 portion of loader will run
    --                            37	
    --                            38	; Ethernet control word addresses
    --             600            39	ePLoc = 600
    --             601            40	eBLoc = 601
    --             602            41	eELoc = 602
    --             603            42	eLLoc = 603
    --             604            43	eICLoc = 604
    --             605            44	eIPLoc = 605
    --             606            45	eOCLoc = 606
    --             607            46	eOPLoc = 607
    --             610            47	eHLoc = 610
    --                            48	
    --                            49	; Convenient constant for accessing Ethernet control words by
    --                            50	; displacement addressing
    --             777            51	eBase = 777

    --                            52	
    --                            53	; EtherBoot(bfn, returnOnFail [false], host [0])
    --                            54	; BCPL-callable procedure that copies the boot loader into page 0
    --                            55	; and dives into it.  bfn is the desired boot file number and
    --                            56	; host, if specified, is host from which to request the boot file
    --                            57	; (the default is zero, meaning broadcast the request).
    --                            58	
    --                            59	; If no boot server responds to the request and returnOnFail is true,
    --                            60	; EtherBoot returns to its caller.  Pages 0 and 1 are clobbered and
    --                            61	; interrupts are disabled, so it is the caller's responsibility to
    --                            62	; save and restore these pages and reenable interrupts.
    --                            63	
    --                            64	.EtherBoot:
    --     0     61000            65		dir			; Interrupts off
    --     1     50543            66		sta 2 bcplStack		; Save stack pointer for possible return
    --     2     40472            67		sta 0 mayday+pupID+1	; Put bfn in mayday packet
    --     3     21400            68		lda 0 0 3		; Get number of args
    --     4    100400            69		neg 0 0
    --     5    101405            70		inc 0 0 snr		; Skip if more than one
    --     6       405            71		 jmp eb1
    --     7    175400            72		inc 3 3			; Where to return to
    --    10    125014            73		mov# 1 1 szr		; returnOnFail true?
    --    11     54534            74		 sta 3 GiveUp		; Yes, set up return pc
    --    12    101405            75		inc 0 0 snr		; Skip if more than two args
    --    13    102461            76	eb1:	 mkzero 0 0 skp		; No host supplied, use zero
    --    14     21003            77		 lda 0 3 2		; Host supplied, use it
    --    15     40460            78		sta 0 mayday+pupDNetHost  ; Set Pup destination host
    --    16    101300            79		movs 0 0		; Put dest in left half
    --    17     40450            80		sta 0 mayday+etherAdr	; Set Ether destination
    --    20     22406            81		lda 0 @lvBootLoaderPacket  ; Get pointer to loader
    --    21    101400            82		inc 0 0			; Compute page0image-1
    --    22     24405            83		lda 1 k400		; Last destination address
    --    23     34405            84		lda 3 lblt		; Negative of number of words
    --    24     61005            85		blt			; Move loader into page 0
    --    25         6            86		jmp boot0-page0image+page0origin  ; Dive into loader
    --                            87	
    --    26         0            88	lvBootLoaderPacket: bootLoaderPacket
    --    27       400            89	k400:	400
    --    30    177402            90	lblt:	-401+page0origin

    --                            91	
    --                            92	; The Ethernet Boot Loader.
    --                            93	; The first two words are reserved for the Ethernet header.
    --                            94	; The Alto jumps to the third word of the packet after receipt.
    --                            95	
    --                            96	.bootLoaderPacket:	; Absolute address = 1 at runtime
    --    31-- 0B,  --        97		0		; Destination/source (filled in at runtime)
    --    32-- 602B,  --        98		typeBreathOfLife
    --                            99	
    --                           100	; The following code runs only in page 0 and never migrates to page 1.
    --                           101	page0image:	; Absolute address = 3 at runtime
    --                           102	
    --                           103	; Set the parameter that determines the desired boot file
    --    33-- 22574B,  --       104		lda 0 @c177035		; Get keyboard bits
    --    34-- 100000B,  --       105		com 0 0			; Turn them right side up
    --    35-- 40437B,
    --       106		sta 0 mayday+pupID+1	; Use as low 16 bits of Pup ID
    --                           107	
    --                           108	; Correct all memory parity by reading and writing all words in memory
    --                           109	; (note that interrupts are off, so the parity errors won't cause trouble).
    --                           110	; EtherBoot procedure enters here.
    --    36-- 102000B,
    --       111	boot0:	mkminusone 0 0		; First source adr = 0 (-1)
    --    37-- 34431B,  --       112		lda 3 k1000		; Count = -177000
    --    40-- 164000B,  --       113		com 3 1			; Last dest adr = 176777
    --    41-- 61005B,  --       114		blt
    --                           115	
    --                           116	; Zero selected regions in page 1
    --    42-- 102460B,  --       117		mkzero 0 0
    --    43-- 24567B,  --       118		lda 1 c427		; Zero 401-427
    --    44-- 34572B,  --       119		lda 3 m27
    --    45-- 61006B,  --       120		blks
    --    46-- 24565B,  --       121		lda 1 c567		; Zero 431-567
    --    47-- 34570B,  --       122		lda 3 m137
    --    50-- 61006B,  --       123		blks
    --    51-- 24564B,  --       124		lda 1 c777		; Zero 600-777
    --    52-- 34566B,  --       125		lda 3 m200
    --    53-- 61006B,  --       126		blks
    --                           127	
    --                           128	; Copy top part of boot loader up to page 1 (note ac1 still contains 777)
    --    54-- 20565B,  --       129		lda 0 pPage1Code
    --    55-- 34565B,  --       130		lda 3 mPage1Count
    --    56-- 61005B,  --       131		blt
    --                           132	
    --                           133	; Set up a "Mayday" packet to broadcast
    --    57-- 125220B,  --       134		movzr 1 1		; Make mask = 377
    --    60-- 46573B,
    --       135		sta 1 @.errcnt		; Max allowable output errors = 377
    --    61-- 20576B,  --       136		lda 0 c3		; Reset Ethernet
    --    62-- 61004B,  --       137		sio
    --    63-- 123400B,  --       138		and 1 0			; Mask local ethernet address
    --    64-- 30551B,  --       139		lda 2 .eBase
    --    65-- 41211B,  --       140		sta 0 eHLoc-eBase 2	; Store for microcode
    --    66-- 4416B,  --       141		jsr boot1		; Make pointer to output packet
    --                           142	
    --                           143	; The "Mayday" packet that we broadcast
    --    67-- 0B,  --       144	mayday:	0		; Destination/source (filled in)
    --    70-- 1000B,  --       145	k1000:	1000		; Ethernet packet type = typePup
    --    71-- 26B,  --       146		22.		; Pup length
    --    72-- 244B,  --       147		typeMayday	; Transport control/type
    --    73-- 0B,  --       148	timeout: 0		; Pup ID
    --    74-- 0B,  --       149		0		; 
    --    75-- 0B,
    --       150		0		; Destination net/host (broadcast or filled in)
    --    76-- 0B,  --       151		0		; Destination socket
    --    77-- 4B,  --       152		socketMiscServices
    --   100-- 0B,  --       153		0		; Source net/host (filled in at runtime)
    --   101-- 0B,  --       154		0		; Source socket (EFTP receiver)
    --   102-- 20B,  --       155		socketEFTPReceiver
    --   103-- 177777B,  --       156		-1		; Nil checksum
    --                           157	
    --   104-- 55210B,
    --       158	boot1:	sta 3 eOPLoc-eBase 2	; Set pointer to packet
    --   105-- 25400B,  --       159		lda 1 etherAdr 3	; Get dest host from packet
    --   106-- 107000B,  --       160		add 0 1			; Set source = me
    --   107-- 45400B,  --       161		sta 1 etherAdr 3
    --   110-- 41411B,
    --       162		sta 0 pupSNetHost 3	; Set Pup source net = 0, host = me
    --   111-- 20547B,  --       163		lda 0 d13		; Size of packet
    --   112-- 41207B,  --       164		sta 0 eOCLoc-eBase 2

    --                           165	
    --                           166	; Page 0 portion of boot loader (cont'd)
    --                           167	
    --                           168	; Loop here for each retransmission of broadcast request
    --   113-- 20544B,  --       169	boot2:	lda 0 c3		; Reset Ethernet
    --   114-- 61004B,  --       170		sio
    --   115-- 6531B,  --       171		jsr @.DoEtherOutput	; Send packet off
    --                           172	
    --                           173	; Set up to receive reply
    --   116-- 34517B,
    --       174	boot3:	lda 3 .eBase		; For accessing Ethernet control words
    --   117-- 30544B,  --       175		lda 2 c1000		; Where to put reply (page 2)
    --   120-- 51606B,  --       176		sta 2 eIPLoc-eBase 3
    --   121-- 20510B,  --       177		lda 0 d269		; Max length
    --   122-- 41605B,  --       178		sta 0 eICLoc-eBase 3
    --   123-- 42526B,  --       179		sta 0 @.maxLength
    --   124-- 102460B,  --       180		mkzero 0 0		; Zero post location
    --   125-- 41601B,  --       181		sta 0 ePLoc-eBase 3
    --   126-- 20530B,  --       182		lda 0 c2		; etherInputCommand
    --   127-- 61004B,  --       183		sio			; Fire up receiver
    --                           184	
    --                           185	; Await reply
    --   130-- 21601B,
    --       186	boot4:	lda 0 ePLoc-eBase 3	; Anything happened?
    --   131-- 101014B,  --       187		sz 0 0
    --   132-- 414B,  --       188		 jmp boot6		; Yes
    --   133-- 61020B,  --       189		mul			; No, waste time
    --   134-- 14737B,  --       190		dsz timeout		; Timed out (about 1 second)?
    --   135-- 773B,  --       191		 jmp boot4		; No, keep waiting
    --   136-- 14517B,  --       192		dsz retries		; Yes, too many retries?
    --   137-- 754B,  --       193		 jmp boot2		; No, send another request
    --   140-- 20517B,  --       194		lda 0 c3		; Yes, reset interface and give up
    --   141-- 61004B,  --       195		sio
    --   142-- 30402B,  --       196		lda 2 bcplStack
    --   143-- 2402B,  --       197		jmp @GiveUp		; Return to caller or loop
    --                           198	
    --   144-- 0B,  --       199	bcplStack: 0
    --   145-- 732B,
    --       200	GiveUp:	Bomb-D			; Overwritten by EtherBoot if returnOnFail
    --                           201	
    --                           202	; Here when have possible reply
    --   146-- 34514B,  --       203	boot6:	lda 3 c377		; Good input done status?
    --   147-- 162414B,  --       204		se 3 0
    --   150-- 746B,  --       205		 jmp boot3		; No, ignore
    --   151-- 21001B,  --       206		lda 0 etherType 2	; Yes, is it a Pup?
    --   152-- 24511B,  --       207		lda 1 c1000
    --   153-- 106414B,  --       208		se 0 1
    --   154-- 742B,  --       209		 jmp boot3		; No, ignore
    --   155-- 21003B,  --       210		lda 0 pupType 2		; Yes, get Pup type
    --   156-- 163400B,  --       211		and 3 0
    --   157-- 35005B,  --       212		lda 3 pupID+1 2		; Get sequence number
    --   160-- 24501B,  --       213		lda 1 c30		; EFTP data?
    --   161-- 106415B,  --       214		sne 0 1
    --   162-- 175014B,  --       215		sz 3 3			; Sequence number zero?
    --   163-- 733B,  --       216		 jmp boot3		; No, ignore

    --                           217	
    --                           218	; Page 0 portion of boot loader (cont'd)
    --                           219	
    --                           220	; We got a good packet, set up for transfer.
    --   164-- 21000B,  --       221		lda 0 etherAdr 2	; Get dest/source word
    --   165-- 42465B,  --       222		sta 0 @.goodDestSource	; Save it
    --   166-- 34457B,
    --       223		lda 3 .ackPacket	; Where we will build the Ack
    --   167-- 56445B,
    --       224		sta 3 @.eOPLoc		; Set pointer (count already ok)
    --   170-- 55775B,
    --       225		sta 3 426-ackPacket+D 3	; Cursor coordinates = (531,531)
    --   171-- 55776B,  --       226		sta 3 427-ackPacket+D 3
    --   172-- 101300B,  --       227		movs 0 0		; Swap source and destination
    --   173-- 41400B,  --       228		sta 0 etherAdr 3	; Store in Ack
    --   174-- 20467B,  --       229		lda 0 c1000		; Type = Pup
    --   175-- 41401B,  --       230		sta 0 etherType 3
    --   176-- 20432B,  --       231		lda 0 d22		; Pup length = 22
    --   177-- 41402B,  --       232		sta 0 pupLength 3
    --   200-- 121400B,  --       233		inc 1 0			; Pup type = Ack = 31
    --   201-- 41403B,  --       234		sta 0 pupType 3
    --   202-- 21006B,
    --       235		lda 0 pupDNetHost 2	; Copy and exchange source and
    --   203-- 41411B,  --       236		sta 0 pupSNetHost 3	;  destination ports
    --   204-- 21007B,  --       237		lda 0 pupDSocket 2
    --   205-- 41412B,  --       238		sta 0 pupSSocket 3
    --   206-- 21010B,  --       239		lda 0 pupDSocket+1 2
    --   207-- 41413B,  --       240		sta 0 pupSSocket+1 3
    --   210-- 21011B,  --       241		lda 0 pupSNetHost 2
    --   211-- 41406B,  --       242		sta 0 pupDNetHost 3
    --   212-- 21012B,  --       243		lda 0 pupSSocket 2
    --   213-- 41407B,  --       244		sta 0 pupDSocket 3
    --   214-- 21013B,  --       245		lda 0 pupSSocket+1 2
    --   215-- 41410B,  --       246		sta 0 pupDSocket+1 3
    --   216-- 15414B,  --       247		dsz pupContents 3	; Pup checksum = nil (-1)
    --                           248	
    --                           249	; Now read and discard packet 0 (which has the disk boot loader)
    --                           250	; and read packet 1, which contains the data destined for page 0.
    --   217-- 6427B,
    --       251		jsr @.DoEtherOutput	; Ack the packet we just got
    --   220-- 12434B,  --       252		isz @.seqNum		; Advance to sequence number 1
    --   221-- 6426B,  --       253		jsr @.ReceiveEFTPPacket	; Read packet 1
    --                           254	
    --                           255	; Set up to transfer packet data into page 0 and jump to remaining
    --                           256	; boot code in page 1
    --   222-- 20421B,  --       257		lda 0 pPage2Data	; First source adr -1
    --   223-- 24437B,  --       258		lda 1 c377		; Last dest adr
    --   224-- 134000B,  --       259		com 1 3			; - number of words (400)
    --   225-- 30417B,
    --       260		lda 2 pPage2Packet	; Where to start reading packet 2
    --   226-- 2422B,  --       261		jmp @.ContinueBoot	; Jump to code in page 1
    --                           262	
    --                           263	
    --   227-- 177035B,  --       264	c177035: 177035
    --   230-- 26B,  --       265	d22:	22.
    --   231-- 415B,  --       266	d269:	269.
    --   232-- 427B,  --       267	c427:	427
    --   233-- 567B,  --       268	c567:	567
    --   234-- 607B,  --       269	.eOPLoc: eOPLoc
    --                           270	.eBase:
    --   235-- 777B,  --       271	c777:	777
    --   236-- 177751B,  --       272	m27:	-27
    --   237-- 177641B,  --       273	m137:	-137
    --   240-- 177600B,  --       274	m200:	-200
    --   241-- 225B,  --       275	pPage1Code: page1image-page0image+page0origin-1
    --   242-- 177624B,  --       276	mPage1Count: page1origin-1000
    --   243-- 1013B,
    --       277	pPage2Data: 1000+12.-1	; Where page 0 data sits when in page 2
    --   244-- 764B,
    --       278	pPage2Packet: 1000-12.	; Where to start reading packet 2
    --   245-- 431B,
    --       279	.ackPacket: ackPacket-D	; Where Ack packet is built
    --   246-- 712B,  --       280	.DoEtherOutput: DoEtherOutput-D
    --   247-- 634B,  --       281	.ReceiveEFTPPacket: ReceiveEFTPPacket-D
    --   250-- 735B,  --       282	.ContinueBoot: ContinueBoot-D
    --   251-- 611B,  --       283	.maxLength: maxLength-D
    --   252-- 567B,  --       284	.goodDestSource: goodDestSource-D
    --   253-- 564B,  --       285	.errcnt: errcnt-D
    --   254-- 566B,  --       286	.seqNum: seqNum-D
    --   255-- 36B,  --       287	retries: 30.		; Max number of broadcast retries

    --                           288	
    --                           289	; Page 1 portion of boot program
    --                           290	
    --                           291	page1image:
    --                           292	
    --                           293	
    --                           294	; Assemble variables and constants here so they can be reached
    --                           295	; from the page 0 code also.
    --                           296	
    --                           297	
    --                           298	; Constants
    --   256-- 2B,  --       299	c2:	2
    --   257-- 3B,  --       300	c3:	3
    --   260-- 15B,  --       301	d13:	13.
    --   261-- 30B,  --       302	c30:	30		; typeEFTPData
    --   262-- 377B,  --       303	c377:	377
    --   263-- 1000B,  --       304	c1000:	1000
    --   264-- 177764B,  --       305	md12:	-12.
    --                           306	
    --          177432           307	D = page1image-page1origin	; Load - runtime displacement
    --                           308	; Note -
    --                           309	; To generate a page 1 pc-relative address for absolute address "X"
    --                           310	;  write "X+D".
    --                           311	; To generate an absolute (runtime) page 1 address for label "X"
    --                           312	;  write "X-D".
    --                           313	
    --                           314	; Ethernet control words addresses, for referencing relative
    --                           315	; to the page 1 portion of the boot loader.
    --             232           316	rEPLoc = ePLoc+D
    --             233           317	rEBLoc = eBLoc+D
    --             234           318	rEELoc = eELoc+D
    --             235           319	rELLoc = eLLoc+D
    --             236           320	rEICLoc = eICLoc+D
    --             237           321	rEIPLoc = eIPLoc+D
    --             240           322	rEOCLoc = eOCLoc+D
    --             241           323	rEOPLoc = eOPLoc+D
    --             242           324	rEHLoc = eHLoc+D
    --                           325	
    --                           326	; Random page 1 words we use as temporaries.
    --                           327	; All are assumed to be initialized to zero.
    --                           328	
    --                           329	; 400-414 are used for scratch
    --                           330	
    --              63           331	ackPacket = 431+D	; 13. words in which Ack packet is built.
    --                           332				; This is the cursor bitmap!
    --             216           333	errcnt = 564+D		; Output error countdown
    --             217           334	recret = 565+D		; Return from ReceiveEFTPPacket
    --             220           335	seqNum = 566+D		; Current EFTP sequence number
    --             221           336	goodDestSource = 567+D	; Ethernet address of me/partner
    --             243           337	maxLength = 611+D	; Max input packet length (269 or 12)
    --             244           338	dallyTimeout = 612+D	; Timeout for end dally if nonzero
    --             245           339	endFlag = 613+D		; Zero if packet was Data, nonzero if End
    --                           340	
    --                           341	
    --   265-- 436B,
    --       342	.ackID1: ackPacket-D+pupID+1  ; Pointer to Ack's sequence number

    --                           343	
    --                           344	; Page 1 portion of boot loader (cont'd)
    --                           345	; Subroutines called from both page 0 and page 1
    --                           346	
    --                           347	; Receive EFTP packet
    --                           348	;	2/ where to put it in memory
    --                           349	; Ac2 is unchanged upon return.
    --                           350	; endFlag will be zero if a Data was received, nonzero if End.
    --                           351	; If dallyTimeout is nonzero, it will be counted down and the
    --                           352	; routine will return if it reaches zero.
    --                           353	
    --                           354	ReceiveEFTPPacket:
    --   266-- 54731B,  --       355		sta 3 recret		; Save return
    --   267-- 50750B,  --       356		sta 2 rEIPLoc		; Set input pointer
    --                           357	
    --                           358	; Await a new packet
    --   270-- 20753B,  --       359	rec1:	lda 0 maxLength		; Set count
    --   271-- 40745B,  --       360		sta 0 rEICLoc
    --   272-- 102460B,  --       361		mkzero 0 0		; Zero post location
    --   273-- 40737B,  --       362		sta 0 rEPLoc
    --   274-- 20762B,  --       363		lda 0 c2		; etherInputCommand = 2
    --   275-- 61004B,  --       364		sio			; Fire up receiver
    --   276-- 20734B,
    --       365	rec1a:	lda 0 rEPLoc		; Wait for something to happen
    --   277-- 105304B,  --       366		movs 0 1 szr
    --   300-- 406B,  --       367		 jmp rec1b		; Something happened, check it
    --   301-- 20743B,
    --       368		lda 0 dallyTimeout	; No activity yet, check timeout
    --   302-- 101014B,  --       369		sz 0 0
    --   303-- 14741B,
    --       370		 dsz dallyTimeout	; One is set, count it down
    --   304-- 772B,  --       371		  jmp rec1a		; Not set or not yet timed out
    --   305-- 2712B,  --       372		jmp @recret		; Timed out, return now
    --                           373	
    --                           374	; A packet has arrived.  Accept if good input or buffer overrun.
    --                           375	; This code is a bit mysterious because the way it works is to
    --                           376	; set ac1 = 1000 iff the status is acceptable.  This then gets
    --                           377	; compared with the incoming Ethernet type which should be 1000.
    --   306-- 34754B,  --       378	rec1b:	lda 3 c377
    --   307-- 167700B,  --       379		ands 3 1		; Ac1 ← 1000 iff post code = 2
    --   310-- 116415B,  --       380		sne 0 3			; Good normal input done status?
    --   311-- 24752B,
    --       381		 lda 1 c1000		; Yes, make it look like post 2
    --                           382	
    --                           383	; Ensure that it is an EFTP Data or End from the correct partner
    --   312-- 21001B,  --       384		lda 0 etherType 2	; Get ethernet type word
    --   313-- 106414B,  --       385		se 0 1			; Is it a Pup? (1000)
    --   314-- 754B,  --       386		 jmp rec1		; No, ignore
    --   315-- 21000B,
    --       387		lda 0 etherAdr 2	; Get destination/source word
    --   316-- 24703B,  --       388		lda 1 goodDestSource	; Correct partner?
    --   317-- 106414B,  --       389		se 0 1
    --   320-- 750B,  --       390		 jmp rec1		; No, ignore (should really abort)
    --   321-- 21003B,  --       391		lda 0 pupType 2		; Get Pup type
    --   322-- 163400B,  --       392		and 3 0
    --   323-- 24736B,  --       393		lda 1 c30		; Switch on it
    --   324-- 106405B,  --       394		sub 0 1 snr
    --   325-- 404B,  --       395		 jmp rec3		; Got Data packet
    --   326-- 121400B,  --       396		inc 1 0
    --   327-- 101404B,  --       397		inc 0 0 szr		; Skip if End
    --   330-- 740B,  --       398		 jmp rec1		; Neither Data nor End, ignore
    --   331-- 44714B,
    --       399	rec3:	sta 1 endFlag		; Set nonzero if this is an End
    --                           400	
    --                           401	; Got an EFTP Data or end packet.
    --                           402	; Now check sequence number and send Ack
    --   332-- 21005B,
    --       403		lda 0 pupID+1 2		; Get packet sequence number
    --   333-- 42732B,  --       404		sta 0 @.ackID1		; Set it for possible Ack
    --   334-- 24664B,  --       405		lda 1 seqNum		; Get expected sequence number
    --   335-- 122405B,  --       406		sub 1 0 snr		; Is it the right one?
    --   336-- 404B,  --       407		 jmp rec4		; Yes
    --   337-- 101405B,
    --       408		inc 0 0 snr		; No, retransmission of last one?
    --   340-- 4404B,  --       409		 jsr DoEtherOutput	; Yes, ack it
    --   341-- 727B,  --       410		jmp rec1		; Ignore it and look for next
    --                           411	
    --                           412	; Here when got a new packet
    --   342-- 10656B,  --       413	rec4:	isz seqNum		; Advance sequence number
    --   343-- 34654B,  --       414		lda 3 recret		; Restore return pc
    --                           415					; Fall into DoEtherOutput

    --                           416	
    --                           417	; Page 1 portion of boot loader (cont'd)
    --                           418	
    --                           419	; Do Ethernet output
    --                           420	; Assumes the packet and eOPLoc and eOCLoc are set up
    --                           421	; Does not clobber ac2
    --                           422	
    --                           423	DoEtherOutput:
    --   344-- 24403B,  --       424		lda 1 k777
    --   345-- 120500B,  --       425		negl 1 0		; Delay about 2 ms to ensure that
    --   346-- 101404B,  --       426		inc 0 0 szr		;  our ack is heard
    --   347-- 777B,  --       427	k777:	 777			; (Otherwise known as "jmp .-1")
    --   350-- 40662B,  --       428		sta 0 rEPLoc		; Zero post location
    --   351-- 40664B,  --       429		sta 0 rELLoc		; Zero load location
    --   352-- 40664B,  --       430		sta 0 rEICLoc		; Zero input count location
    --   353-- 102520B,  --       431		mkone 0 0		; etherOutputCommand = 1
    --   354-- 61004B,  --       432		sio			; Start output
    --   355-- 20655B,  --       433		lda 0 rEPLoc		; Wait for something to happen
    --   356-- 101015B,  --       434		snz 0 0
    --   357-- 776B,  --       435		 jmp .-2
    --   360-- 106415B,  --       436		sne 0 1			; Good output done? ( = 777)
    --   361-- 1400B,  --       437		 jmp 0 3		; Yes, done, return
    --   362-- 14634B,  --       438		dsz errcnt		; No, check error counter
    --   363-- 761B,  --       439		 jmp DoEtherOutput	; Retry
    --                           440	
    --                           441	; If we get too many errors, probably the Ethernet interface
    --                           442	; is broken, so we should reset and give up lest we pollute
    --                           443	; the Ethernet indefinitely
    --   364-- 20673B,  --       444	Bomb:	lda 0 c3		; etherResetCommand
    --   365-- 61004B,  --       445		sio
    --   366-- 400B,  --       446	c400:	400			; (Otherwise known as "jmp .")

    --                           447	
    --                           448	; ** Main page 1 program **
    --                           449	; Control resumes here when the page 0 code is finished.
    --                           450	; When we get here, the second data packet of the transfer has
    --                           451	; been received (the one destined for page 0) and now resides
    --                           452	; in page 2, and the ac's are set up such that blt will move
    --                           453	; the data to page 0.  This code's responsibility is to receive
    --                           454	; the remaining pages of the transfer and store them starting at
    --                           455	; page 2.  The following variables are already set up:
    --                           456	;	goodDestSource	expected Ethernet dest/source word
    --                           457	;	seqNum		the next expected EFTP sequence number (2)
    --                           458	;	ac2		points to place to store next packet
    --                           459	;			(1000 minus the offset pupContents)
    --                           460	; Also, an Ack packet has already been built at ackPacket.
    --                           461	
    --                           462	ContinueBoot:
    --   367-- 61005B,  --       463		blt			; Copy data to page 0
    --                           464	
    --                           465	; The main loop of the EFTP boot load sequence.
    --                           466	; First, save away the stuff at the end of the previous page
    --                           467	; that will get clobbered by the new Pup's header.
    --                           468	; Locations 400-413 are used for scratch.
    --   370-- 102000B,
    --       469	bootlp:	mkminusone 0 0		; Compute first source adr -1
    --   371-- 143000B,  --       470		add 2 0
    --   372-- 34672B,  --       471		lda 3 md12		; -12. (number of words)
    --   373-- 24667B,
    --       472		lda 1 c377		; Compute pointer to last word of
    --   374-- 166400B,  --       473		sub 3 1			;  save area
    --   375-- 61005B,  --       474		blt			; Save the data
    --                           475	
    --                           476	; Now receive the next Data (or End) packet
    --   376-- 4670B,  --       477		jsr ReceiveEFTPPacket
    --                           478	
    --                           479	; Now restore the clobbered region
    --   377-- 20663B,
    --       480		lda 0 c377		; Pointer to start of save area -1
    --   400-- 34664B,  --       481		lda 3 md12		; -12. (number of words)
    --   401-- 164000B,  --       482		com 3 1			; Compute pointer to last word of
    --   402-- 147000B,  --       483		add 2 1			;  clobbered region
    --   403-- 61005B,  --       484		blt			; Move the data back
    --                           485	
    --                           486	; Unless memory is now full, advance the pointer and repeat.
    --                           487	; If we just read into the last page of memory, set the pointer to
    --                           488	; a scratch region at 400 and set the count so that only a minimum-
    --                           489	; length Pup (e.g., the End that we are expecting) will be
    --                           490	; accepted.
    --   404-- 24762B,  --       491		lda 1 c400		; Amount to advance pointer by
    --   405-- 132414B,
    --       492		se 1 2			; Skip if already at scratch region
    --   406-- 133000B,  --       493		 add 1 2		; Normally, advance pointer
    --   407-- 20636B,  --       494		lda 0 endFlag
    --   410-- 34416B,  --       495		lda 3 memOverflow
    --   411-- 101015B,  --       496		snz 0 0			; Was an End received?
    --   412-- 156415B,  --       497		sne 2 3			; Or beyond end of memory?
    --   413-- 131001B,  --       498		 mov 1 2 skp		; Yes, set pointer to 400
    --   414-- 754B,  --       499		 jmp bootlp		; No, continue normally
    --   415-- 24643B,  --       500		lda 1 d13		; Limit packet length to minimum
    --   416-- 44625B,  --       501		sta 1 maxLength
    --   417-- 101015B,  --       502		snz 0 0			; Received End?
    --   420-- 750B,  --       503		 jmp bootlp		; No, continue
    --   421-- 14623B,
    --       504		dsz dallyTimeout	; Yes, enable timeout (set to -1)
    --   422-- 4644B,
    --       505		jsr ReceiveEFTPPacket	; Await second End or timeout
    --   423-- 20634B,  --       506		lda 0 c3		; Reset the Ethernet
    --   424-- 61004B,  --       507		sio
    --   425-- 2000B,  --       508		jmp @0			; Jump into the bootload!
    --                           509	
    --   426-- 176764B
    --       510	memOverflow: 177000-12.  ; Where ac2 will point when memory is full
    --                           511	
    --                           512	
    --                           513	; ** Warning **
    --                           514	; The last 12 words of page 1 get clobbered during the act of
    --                           515	; receiving page 2.  This is ok since those 12 words are saved
    --                           516	; and restored.  However, the stuff in those words must not be
    --                           517	; executed or referenced while in the clobbered state!
    --                           518	
    --                           519		.end
    ];


  END..