; DiskBoot.asm -- Alto Type B Disk Boot Loader ; Copyright Xerox Corporation 1979 ; Last modified December 21, 1978 2:13 PM by Boggs ; This loader lands in Page 0 and does the following things: ; Corrects memory parity by BLTing all of core to itself ; Zeros selected locations in Page 1 ; Copies a loader into Page 1 starting at location X ; Loads the B-format boot file following the loader page ; Starts the program by JMP @0 ; ; The display shows three lines of debugging information: ; The Parity error locations, 614-621 ; The first KCB, locations X to X+21 ; The second KCB, locations X+22 to X+43 ; ; The format of the lines is: ; Parity: DCBR KNMAR DWA CBA PC SAD ; KCBs: LINK STATUS CMD HDR LBL DATA BLANK BLANK BLANK ; NEXTDA LASTDA BLANK NUMCHARS PN VN SN SN ERRCNT ; The bottom part of each line is made up of tick-marks which should ; aid in deciphering the bits, should you be so unlucky as to need to. ; ; Boot format file: ; BootLoader (this thing -- on the first data page of the file) ; Images of pages 0,2,3,4,5,.....375 (octal) ; Note that no image of page 1 is restored. ; For more on the format of boot files see the documentation for BuildBoot. ; ; When control enters this loader: ; The ACs are unmodified from before the boot ; The PC from before the boot is in location 0 ; The display is off (location 420 contains 0) ; The interrupt system is disabled ; This loader is in locations 1-400 ; The label for this page is in locations 402-411 ; The disk status for this page is in location 2 ; ; When control leaves this loader: ; The display is off (420 contains 0, controller may NOT have noticed) ; The interrupt system is disabled ; The KCBs are left at location X ; Memory parity is guaranteed good for BANK 0 ONLY ; ; As of December, 1978 the emulator state from before the boot is no ; longer saved. The 2 words starting at location 4 (file byte pos = 6) ; are reserved for holding the date on which the boot file was made. ; Boot servers use this information to propagate the most recent ; versions of boot files ; Older versions of this loader contain 402b in location 1. .titl DiskBoot .nrel 0 ; The sacrificial word for BLDR to eat Loc1: jmp Boot1 ; This is location 1 in memory Loc2: 0 ; disk status for this page Loc3: 0 ; spacer to get date in advertised position Loc4: .blk 2 ; date file was built ; Correct memory parity by BLTing all of memory to itself Boot1: mkminusone 0 0 lda 1 MemEnd com 1 3 blt ; Zero selected parts of Page 1 mkzero 0 0 sta 0 @pDIW ; display interrupt bit mask sta 0 @pIWW ; interrupts waiting sta 0 @pIACTW ; active interrupt channels sta 0 @pKBLK0 ; disk command chain head lda 1 C777 lda 3 CWCNT blks ; 600-777 ; Copy the KCBs, DCBs, and loader loop into Page 1. jsr .+1 XOff: lda 0 ImgOff add 3 0 ; AC0← Image-1 lda 1 pImgEnd lda 3 ImgLen neg 3 3 blt lda 0 MarkWrd ; Put display mark words in 530-551 lda 1 MarkEnd lda 3 MarkCnt blks lda 0 @p0KA sta 0 @pKCB0DA ; put DA for 1st page of boot file in KCB0 lda 0 pDCB0 sta 0 @pDISP ; Start the display lda 2 pKCB0 ; Active KCB lda 3 pKCB1 ; Inactive KCB lda 1 C1000 ; next data block address - 400 sta 2 @pKBLK0 ; Start the disk jmp @pReadIn ; Jump into the loader loop in page 1 C777: 777 ; -> last word in page 1 to be cleared CWCNT: -177 ; # of words to zero in page 1 MemEnd: 176777 ; -> last word of real memory pImgEnd: ImgEnd-D ; -> last word of page 1 image ImgLen: ImgEnd-Image+1 ; Length of page 1 image ImgOff: Image-XOff-1 ; Relocation offset MarkWrd: 111111 ; Mark word pattern MarkEnd: 551 ; -> last mark word MarkCnt: -22 ; Number of mark words = length of KCB+Label p0KA: 402 ; -> Label of the boot loader page pKCB0DA: KCB0DA-D ; -> Disk address in KCB0 pDCB0: DCB0-D ; -> DCB0 pKCB0: KCB0-D ; -> KCB0 pKCB1: KCB1-D ; -> KCB1 C1000: 1000 pDISP: 420 ; -> Display control block list head pDIW: 421 ; -> Display vertical interrupt pIWW: 452 ; -> Interrupts waiting pIACTW: 453 ; -> Active interrupt channels pKBLK0: 521 ; -> Disk command block list head - page 0 copy pReadIn: ReadIn-D ; -> Loader loop in page 1 ; The following code is copied into Page 1 starting a location X. X = 626 ; disk control blocks Image: KCB0: KCB1+X-Image ; Link to the other KCB D = Image-X 0 ; status 44000 ; command: Read Header, Label, Data KCB1DA-D ; Header address -> Disk address word in KCB1 KCB1DA-D ; Label address. Read in on top of Header 0 ; Data address. This moves through memory 0 ; OK interrupt bit mask. not used 0 ; Error interrupt bit mask. not used 0 ; blank KCB0DA: 0 ; Disk address for this KCB, label area for KCB1 0 ; previous disk address 0 ; blank 0 ; numChars 0 ; page number 0 ; version 0 ; serial number high 0 ; serial number low ErrCnt: 0 ; incremented for each disk error KCB1: KCB0-D ; Link to the other KCB 0 ; status 44000 ; command: Read Header, Label, Data KCB0DA-D ; Header address -> Disk address word in KCB0 KCB0DA-D ; Label address. Read in on top of Header 0 ; Data address. This moves through memory 0 ; OK interrupt bit mask. not used 0 ; Error interrupt bit mask. not used 0 ; blank KCB1DA: 0 ; Disk address for this KCB, label area for KCB0 0 ; previous disk address 0 ; blank 0 ; numChars 0 ; page number 0 ; version 0 ; serial number high 0 ; serial number low 0 ; Pad to an even number of words ; Display control blocks DCB0: DCB1-D ; Head of a chain of 9 DCBs 0 0 200 ; 200 blank lines to space to center of screen DCB1: DCB2-D 100006 ; low resolution, 6 words/scan line 614 ; Parity error locations 1 DCB2: DCB3-D 100006 ; low resolution, 6 words/scan line 530 ; mark words for parity error locations 1 DCB3: DCB4-D 0 0 10 ; skip 20 scan lines DCB4: DCB5-D 100022 ; low resolution, 22 words/scan line KCB0-D ; KCB0 1 DCB5: DCB6-D 100022 ; low resolution, 22 words/scan line 530 ; mark words for KCB1 1 DCB6: DCB7-D 0 0 10 ; skip 20 scan lines DCB7: DCB8-D 100022 ; low resolution, 22 words/scan line KCB1-D ; KCB1 1 DCB8: 0 100022 ; low resolution, 22 words/scan line 530 ; mark words for KCB2 1 ; Main loop of the loader. This code runs in Page 1. ; Enter with a transfer started to read in page 0. ; Note that the next page read will go into page 2. ; On entry the ACs contain: ; AC1/ 1000B ; AC2/ Pointer to KCB0 (active) ; AC3/ Pointer to KCB1 (inactive) ReadIn: mkzero 0 0 sta 0 1 3 ; clear the status in the inactive KCB lda 0 5 2 ; data block address of active KCB add 1 0 ; plus 400B (1000B initially) sta 0 5 3 ; yields data block address for inactive KCB KWait: lda 0 1 2 snz 0 0 ; wait for the command to complete jmp KWait lda 1 ErrorMask and 0 1 szr ; Error? jmp ReRead ; Yes. Retry the read lda 0 14 3 ; numChars lda 1 FullPage se 0 1 ; Is the page full? jmp Start ; No. That was the last one. mov 2 0 ; Exchange exchange current and inactive KCBs mov 3 2 mov 0 3 movzr 1 1 ; AC1← 400B jmp ReadIn ; Read next page pKBLK1: 521 ; disk command block list head -- page 1 copy pDISP1: 420 ; display command block list head -- page 1 copy ErrorMask: 367 FullPage: 1000 ; bytes ; Come here to start the program. Start: mkzero 0 0 sta 0 @pKBLK1 ; stop the disk sta 0 @pDISP1 jmp @0 ; the program begins in location 0 ; Come here on disk error. ReRead: mkzero 0 0 ; Clear the status sta 0 1 2 sta 2 @pKBLK1 ; Restart the disk isz ErrCnt nop jmp KWait ; Last word of boot loader image ImgEnd = .-1 .end