;************************************************************************ ;* * ;* SD SYSTEMS SBC-200 Z80 BOOTSTRAP LOADEE F. COOK 10/6/88 * ;* THE CODE IS IN A 2716 EPROM AT ADDRESS F000H * ;* * ;* THE LOADEE IS ACCESSED BY SENDING AN 'E' FOR ENQUIRE. IT WILL * ;* RESPOND WITH 'A' FOR ACKNOWLEDGE OR 'N' FOR NOT * ;* ACKNOWLEDGE. * ;* * ;* COMMAND DESCRIPTION * ;* * ;* L LOADS AN INTEL HEX FILE FROM THE SERIAL PORT * ;* RETURNS L * ;* JHHHH JUMPS TO HEX ADDRESS HHHH * ;* RETURNS JHHHH * ;* TSSSSFFFF TESTS RAM FROM SSSS TO FFFF * ;* RETURNS TP FOR PASS OR * ;* TF AAAA WW RR FOR FAIL * ;* WHERE AAAA IS THE BAD ADDRESS, * ;* WW IS THE DATA WRITTEN, * ;* AND RR IS THE DATA READ. * ;* * ;* Watchdog Control Switches on MIO BOARD: * ;* --------------------------------------- * ;* Switch 1: Off: Watchdog Disable * ;* On: Watchdog Enable * ;* * ;* Switch 2: Off: WD Jump to Loader * ;* On: WD Jump to 0103h * ;* * ;* The SBC-200 uses a different USART clock and * ;* has different time constants. * ;* * ;************************************************************************ .Z80 CTCSET EQU 045H ; CTC SETUP CONSTANT B9600 EQU 00DH ; CTC CONSTANT FOR 9600 BAUD CTCDAT EQU 078H ; Z-80 CTC BAUD RATE PORT UMODE EQU 0AEH ; 8251 8Bit 1SB NoPar UCOMD1 EQU 040H ; 8251 Internal Reset UCOMD2 EQU 015H ; 8251 Turn on XMTR, RCVR USARTD EQU 07CH ; 8251 USART DATA REGISTER USARTC EQU 07DH ; 8251 USART CONTROL/STATUS REGISTER SBCCNT EQU 07FH ; SBC-200 CONTROL PORT WATDOG EQU 057H ; WATCHDOG PORT on MIO STATUS EQU 057H ; Status PORT on MIO SWTBIT EQU 001H ; MIO Switch 2 And Mask TXRBIT EQU 001H ; TX REG EMPTY MASK RXRBIT EQU 002H ; RX REG EMPTY MASK DATMSK EQU 07FH ; MASK OFF BIT 7 CONTC EQU 003H ; CONTROL C CHAR LINFD EQU 00AH ; LINE FEED CHAR RETRN EQU 00DH ; CARRIAGE RETURN CHAR CONTZ EQU 01AH ; CONT Z CHARACTER BLANK EQU 020H ; BLANK CHARACTER ACK EQU 041H ; ACKNOWLEDGE CHAR 'A' ENQ EQU 045H ; ENQUIRE CHAR 'E' NAK EQU 04EH ; NOT ACKNOWLEDGE CHAR 'N' TPAT1 EQU 0AAH ; MEMORY TEST PATTERN 1 TPAT2 EQU 055H ; MEMORY TEST PATTERN 2 TRUE EQU 0FFH ; TRUE CHAR FALSE EQU 000H ; FALSE CHAR NMIADD EQU 00066H ; WATCHDOG NMI JUMP ADDRESS JMPINS EQU 0C3H ; JUMP INSTRUCTION OPCODE LDRHI EQU 0F0H ; LOADEE ADDRESS FOOO FOR WATCHDOG LDRLO EQU 000H RAMPRG EQU 00103H ; beginning of Program in RAM STACKT EQU 0EFFFH ; TOP OF STACK ;ORG F000H ; START OF CODE ON SBC-200 BOARD ;********************************************************************** ; BOOTSTRAP LOADEE BEGINS HERE DLLD: JP BEGIN ; JUMP FOR POWER ON RESET BOOT OFFSET BEGIN: IN A, (SBCCNT) ; Reset ROM ADDR Offset Circuit on CPU DI ; TURN OFF INTERRUPTS FROM SIO CHIPS CALL INIT ; INIT THE SYSTEM LD SP, STACKT ; SET UP THE STACK POINTER IN A, (STATUS) ; If MIO switch is ON, Jump to 0103H AND SWTBIT JP NZ, RAMPRG EXTENT: ; Entry point from Ram Program LD SP, STACKT ; SET UP THE STACK POINTER CALL HSHAKE ; ESTABLISH HANDSHAKE WITH THE LOADER GETCMD: CALL CREAD ; GET COMMAND CHAR CP 'J' ; IS COMMAND JUMP? JR Z, BEGJP ; IF SO, GET ADDRESS AND JUMP TO IT. CP 'L' ; IS COMMAND LOAD MEMORY? JR Z, BEGLD ; IF SO, BEGIN LOADING CP 'T' ; IS COMMAND TEST? JR Z, BEGTST ; IF SO, BEGIN TESTING MEMORY LD C, '?' ; RETURN ? FOR UNDEFINED COMMAND CALL CWRITE CALL CRLF ; SEND OUT CR LF JR GETCMD ; GET ANOTHER COMMAND BEGJP: CALL JPADDR ; JUMP TO ADDRESS ROUTINE JR GETCMD ; GET NEXT COMMAND BEGLD: CALL LDDATA ; LOAD DATA ROUTINE JR GETCMD ; GET NEXT COMMAND BEGTST: CALL MTEST ; CALL MEMORY TEST ROUTINE JR GETCMD ; GET NEXT COMMAND ;---------------------------------------------------------------------- ; LOAD DATA INTO THE Z-80 LDDATA: LD C, 'L' ; SEND BACK L FOR LOAD CALL CWRITE CALL CRLF ; SEND OUT CR LF LDDAT1: CALL CREAD ; LOOP UNTIL : CHAR COMES IN CP ':' JR NZ, LDDAT1 CALL GETHEX ; GET 2 LENGTH DIGITS LD C, A CALL GETHEX ; GET 2 HI ADDR DIGITS LD H, A CALL GETHEX ; GET 2 LO ADDR DIGITS LD L, A CALL GETHEX ; GET 2 0 DIGITS AND IGNORE LD A, C ; IF LEN = 0, EXIT CP 0 JR Z, LDDATX LDDAT2: LD A, C ; WHILE C > 0, GET DATA & STORE IT CP 0 JR Z, LDDAT3 ; IF C = 0, GET CHECKSUM CALL GETHEX ; GET 2 DATA DIGITS LD (HL), A ; STORE IN MEMORY INC HL ; UPDATE MEMORY POINTER DEC C ; COUNT DOWN BYTES IN LINE JR LDDAT2 ; LOOP BACK FOR MORE LDDAT3: CALL GETHEX ; GET 2 CHECKSUM DIGITS, IGNORE JR LDDAT1 ; LOOP BACK FOR NEXT LINE LDDATX: CALL GETHEX ; GET LAST 2 CHECKSUM DIGITS, IGNORE RET ;---------------------------------------------------------------------- ; JUMP TO A Z-80 ADDRESS AND EXECUTE CODE JPADDR: LD C, 'J' ; SEND BACK J FOR JUMP CALL CWRITE CALL GETHEX ; GET 2 HEX DIGITS FROM VAX LD H, A CALL GETHEX ; GET 2 MORE LD L, A LD A, H CALL HXPAIR ; SEND 2 HEX DIGITS TO VAX LD A, L CALL HXPAIR ; SEND OUT 2 MORE CALL CRLF ; SEND OUT CR LF JP (HL) ; JUMP TO ADDR IN HL ;---------------------------------------------------------------------- ; TEST MEMORY HERE MTEST: LD C, 'T' ; SEND BACK T FOR TEST CALL CWRITE LD BC, 0 ; ZERO ERROR COUNT CALL GETHEX ; GET TEST START ADDESS LD H, A CALL GETHEX LD L, A CALL GETHEX ; GET TEST END ADDRESS LD D, A CALL GETHEX LD E, A INC DE ; INCREMENT END ADDR FOR TEST BELOW MTLOOP: IN A, (WATDOG) ; Tickle The Watchdog LD A, TPAT1 ; WRITE AND READ TEST PATTERN #1 LD (HL), A LD A, (HL) CP TPAT1 ; IF DIFFERENT, AN ERROR OCURRED JR NZ, MEMER1 LD A, TPAT2 ; WRITE AND READ TEST PATTERN #2 LD (HL), A LD A, (HL) CP TPAT2 ; IF DIFFERENT, AN ERROR OCURRED JR NZ, MEMERR MERRET: INC HL ; GO TO NEXT ADDRESS LD A, H ; LOOP UNTIL HL POINTS PAST END ADDRESS CP D JR NZ, MTLOOP LD A, L CP E JR NZ, MTLOOP LD A, B ; IF NO ERRORS OCURRED, RETURN 'P' OR C RET NZ ; RETURN WITH PREVIOUS ERRORS LD C, 'P' ; SEND BACK P FOR PASSED CALL CWRITE CALL CRLF ; SEND CR LF RET MEMER1: PUSH DE LD D, TPAT1 ; WRITE CHAR JR MEMERR MEMER2: PUSH DE LD D, TPAT2 ; WRITE CHAR MEMERR: PUSH BC ; SAVE ERROR COUNT LD E, A ; READ RESPONSE LD C, 'F' ; SEND BACK F FOR FAILED TEST CALL CWRITE LD C, ' ' ; SEND SPACE TO VAX CALL CWRITE LD A, H ; SEND DEFECTIVE ADDRESS TO VAX CALL HXPAIR LD A, L CALL HXPAIR LD C, ' ' ; SEND SPACE TO VAX CALL CWRITE LD A, D ; SEND WRITE BYTE TO VAX CALL HXPAIR LD C, ' ' ; SEND SPACE TO VAX CALL CWRITE LD A, E ; SEND READ BYTE TO VAX CALL HXPAIR CALL CRLF ; SEND CR LF POP BC ; UNSAVE ERROR COUNT INC BC ; UPDATE ERROR COUNT POP DE JR MERRET ; CONTINUE WITH TEST ;---------------------------------------------------------------------- ; SEND CR LF TO THE PORT CRLF: PUSH BC LD C, RETRN ; SEND CARRIAGE RETURN CALL CWRITE LD C, LINFD ; SEND LINE FEED CALL CWRITE POP BC RET ;---------------------------------------------------------------------- ; INIT THE SYSTEM INIT: LD A, CTCSET ; CTC SETUP OUT (CTCDAT), A LD A, B9600 ; SET CTC FOR 9600 BAUD OUT (CTCDAT), A LD A, UMODE ; SET UP THE 8251 USART OUT (USARTC), A LD A, UCOMD1 ; RESET 8251 OUT (USARTC), A LD A, UMODE ; SET UP THE 8251 USART AGAIN OUT (USARTC), A LD A, UCOMD2 ; TURN ON 8251 OUT (USARTC), A RET ;---------------------------------------------------------------------- ; ESTABLISH HANDSHAKE WITH THE VAX HSHAKE: CALL CREAD ; GET A CHAR CP ENQ ; IS VAX SENDING ENQUIRE? JR Z, HSHAK1 ; IF SO, SEND ACK, GO TO COMMAND LOOP LD C, NAK ; IF NOT, SEND BACK NAK CALL CWRITE CALL CRLF ; SEND CR LF JR HSHAKE HSHAK1: LD C, ACK ; IF SO, SEND BACK ACKNOWLEDGE CHAR CALL CWRITE ; WRITE IT BACK CALL CRLF ; SEND CR LF RET ;---------------------------------------------------------------------- ; CHECK VAX READ STATUS, RETURN A=TRUE OR A=FALSE CSTAT: IN A, (WATDOG) ; Tickle The Watchdog IN A, (USARTC) ; BIT2 = 1 SAYS RX DATA RDY AND RXRBIT JR NZ, CSTATT ; JUMP IF READY LD A, FALSE ; RETURN FALSE FOR NO CHAR JR CSTATX CSTATT: LD A, TRUE ; RETURN TRUE FOR CHAR CSTATX: OR A ; SET FLAGS RET ;---------------------------------------------------------------------- ; READ IN 1 CHAR FROM VAX AND RETURN IT IN A CREAD: IN A, (WATDOG) ; Tickle The Watchdog CALL CSTAT ; WAIT ON CHAR IN JR Z, CREAD IN A, (USARTD) ; GET CHAR AND MASK BIT 7 AND DATMSK RET ;---------------------------------------------------------------------- ; WRITE 1 CHAR IN C REG TO VAX SERIAL LINE CWRITE: IN A, (WATDOG) ; Tickle The Watchdog IN A, (USARTC) ; WAIT ON XMTR READY BIT AND TXRBIT JR Z, CWRITE LD A, C ; PUT CHAR OUT TO VAX OUT (USARTD), A ; OUTPUT DATA RET ;---------------------------------------------------------------------- ; GET 2 HEX DIGITS FROM VAX, PUT THEM IN THE ACC GETHEX: PUSH BC CALL GETHD RLC A ;1ST DIGIT * 16 RLC A RLC A RLC A LD B, A CALL GETHD ;2ND DIGIT + 1ST DIGIT ADD A, B POP BC RET ;---------------------------------------------------------------------- ; get one HEX digit FROM THE VAX GETHD: PUSH BC PUSH DE DIGIN: CALL CREAD ; GET A CHAR FROM THE VAX CP ' ' ; IGNORE SPACES JR Z, DIGIN LD D, A LD B, '0' ; NUMBERS CHECK SUB B CP 10 JR C, OKDIG ; Digit? LD A, D LD B, 'A' ; A thru F check SUB B CP 6 JR C, OKHEX LD A, D LD B, 'a' ; a thru f check SUB B CP 6 JR C, OKHEX JP BADDIG OKHEX: ADD A, 10 ; ADD OFFSET TO LETTER DIGITS OKDIG: POP DE POP BC RET BADDIG: LD C, '#' ; SEND ERROR MESSAGE TO VAX CALL CWRITE CALL CRLF ; SEND CR LF POP DE POP BC RET ;---------------------------------------------------------------------- ; THIS SUBROUTINE PRINTS THE ACC TO THE VAX IN HEX PAIRS HXPAIR: PUSH AF ;SAVE REGS PUSH BC PUSH DE PUSH HL PUSH AF ;SAVE CHAR LD HL,HEXTAB ;POINT TO HEX TABLE LD DE,00 ;SET OFFSET TO 0 SRL A ;SHIFT HIGH NIBBLE TO LOW NIBBLE SRL A SRL A SRL A LD E,A ;GET NIBBLE OFFSET ADD HL,DE ;ADD OFFSET TO TABLE PTR LD A,(HL) ;GET TABLE ENTRY LD C, A CALL CWRITE ;OUTPUT CHAR TO VAX LD HL,HEXTAB ;POINT TO HEX TABLE LD DE,00 ;ZERO OFFSET POP AF ;UNSAVE CHAR AND 0FH ;MASK FOR LOW NIBBLE LD E,A ;GET NIBBLE OFFSET ADD HL,DE ;ADD OFFSET TO TABLE PTR LD A,(HL) ;GET TABLE ENTRY LD C, A CALL CWRITE ;OUTPUT CHAR TO VAX POP HL POP DE POP BC POP AF ;UNSAVE REGS RET HEXTAB: DB '0123456789ABCDEF' ;---------------------------------------------------------------------- END