-- 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..