; REMOVE_ROM.mac by John Monahan (S100Computers.com) ; ; Assembled with AsmPDP.exe (windows) assembler. ; Note code cannot contain BASIC names like "PRINT" (Because the compiler was written in basic). ; Best to use lower case labels. ; ; Remember most port I/O's are 8 bits wide. If you send a word to an odd port you will trigger a CPU error/exception. ; Use MOVB x,y and not MOV x,y ; ; >>> For this monitor ALL S100 bus ports range from E000H - FFFFH. (The "Normal" S100 bus address range + E000H) <<< ; ; V0.1 2/16/2018 ;Initial code ; ; This is a simple demo program which is loaded at 100H in RAM to demonstrate the removal of the PDP11 V2 CPU ; Board ROMS. It would be used for example as a module before running Digital sotware. Releasing all S100 bus ; RAM from 0000H to DFFFH ; ; ; Note the assembler strips off the (3F)xxxx from the I/O addresses xxxx below ; ; so they edffectively become E000-FFFFH and on the S100 bus Ports 0000-1F00H ; ODT_CONIN_STAT: equ &FF70 ; &o17777560 Will be converted to 1F70H by the CPU board ODT_CONIN_DATA: equ &FF72 ; &o17777562 ODT_CONOUT_STAT: equ &FF74 ; &o17777564 ODT_CONOUT_DATA: equ &FF76 ; &o17777566 DEBUG_CONIN_STAT: equ &FF10 ; Will be converted to 1F10H by the CPU board if SB ODT UART is active DEBUG_CONIN_DATA: equ &FF12 ; DEBUG_CONOUT_STAT: equ &FF14 ; DEBUG_CONOUT_DATA: equ &FF16 ; S100_CONIN_STAT: equ &E000 ; S100Computers Console IO Board In Status (translated to 0000H by CPU board) S100_CONIN_DATA: equ &E001 ; S100Computers Console IO Board In Data S100_CONOUT_STAT: equ &E000 ; S100Computers Console IO Board Out Status S100_CONOUT_DATA: equ &E001 ; S100Computers Console IO Board Out Data CPU_STACK: equ &BFF0 ; Will place stack below ROMs CONSOLE_IO_FLAG: equ &BFFE ; FFFF = ALL CONSOLE IO TO ODT UART. ANYTHING ELSE THEN SEND TO S100 CONSOLE ROM_OUT_PORT: equ &E0E1 ; Port to shadow out ROM ROM_IN_PORT: equ &E0E2 ; Port to shadow in ROM ; Ther are multiple ways the Master/Slave switch could have taken place (jumper dependent) BUSMASTER: equ &E0E3 ; This will return control to the Z80 Master SW86: EQU &E0EDH ; INPUT FROM THIS PORT SWITCHES THE PDP11 BACK to the Z80 in hardware SW86_TM: EQU &E0EEH ; Output 00H to this port to switch back to Z80 Hardware (on SMB V2 only). ROM_HIGH_PORT: equ &E0E4 ; Port to shadow in ROM High Page in the PDP address space via Port E4H ROM_LOW_PORT: equ &E0E5 ; Port to shadow in ROM Low Page in the PDP address space via Port E5H SW86: equ &E0ED ; Input from this port switches the PDP back to the Z80 in hardware SW86_TM: equ &E0EE ; Output 00H switch the PDP back to Z80 Hardware (on SMB V2,V3 boards) IOBYTE: equ &E0EF ; S100Computers SMB IOBYTE Port CR: equ &0D LF: equ &0A BELL: equ &07 ESC: equ &1B SPACE: equ &20 SCROLL: equ &01 ; Set scrool direction UP. BELL: equ &08 TAB: equ &09 ; TAB ACROSS (8 SPACES FOR SD-BOARD) FF: equ &0C DELETE_CHAR: equ &7F BACKS: equ &08 BIT7: equ &80 ; &o200 BIT4: equ &10 BIT2: equ &04 BIT1: equ &02 BIT0: equ &01 ;_______________________________________________________________________________________________________________________ ; ORG &100 ; Start at 100H Start: MOV #CPU_STACK,SP ; LOW ROM & HIGH PAGEs: Setup stack at BF00H (Below ROM ORG at C000H) ; MOV #&00E0,@#PSW ; Block ALL Interrupts (Clear bits 7-5) JSR PC,Set_CONSOLE_IO ; Set Flag for Console IO to ODT UART or S100 Bus MOV #Signon,R5 ; Point to Signon Message JSR PC,PrStr ; Print string JSR PC,Set_CONSOLE_IO ; Update Flag for Console IO to ODT UART or S100 Bus JSR PC,ConCRLF Loop: MOV #MainMenu,R5 ; Point to Main Menu JSR PC,PrStr ; Print string JSR PC,CONSOLE_IN ; Get a menu character (WITH ECHO) to R0 JSR PC,ToUpper ; Y OR N JSR PC,CONSOLE_OUT ; Echo CMP #&59,R0 ; 'Y' BEQ ROM_OUT CMP #&4E,R0 ; 'N' BEQ ROM_IN CMP #&1B,R0 ; 'ESC' BEQ ACTIVATE_BUSMASTER MOV #MenuError,R5 ; Point to Main Menu JSR PC,PrStr ; Print string JSR PC,ConCRLF ; Show CR,LF JMP Loop ; Just in case ROM_OUT: MOVB @#ROM_OUT_PORT,R0 ; Input from port E0E1H inactivates the ROM JMP MemMap ROM_IN: MOVB @#ROM_IN_PORT,R0 ; Input from port E0E2H activates the ROM JMP MemMap ACTIVATE_BUSMASTER: MOVB @#BUSMASTER,R0 ; First try input from port E0E6H on U25 CPLD to deactivate TMAx, so we go back to the Z80 Bus Master MOVB @#SW86,R0 ; Could be the old (V1,V2) SMB TMA control port switch MOVB #0,@#SW86_TM ; Could be the new (V3) SMB TMA control port switch JMP Loop ; Should never get to here! MemMap: MOV #MM_Text,R5 ; Point to MemMap Message JSR PC,PrStr ; Print string MOV #0,R5 ; Set up start address MOV #16,R4 ; Characters across count Map1: JSR PC,PutWord_R5 ; Print HEX word value in R5 Map2: MOV #SPACE,R0 JSR PC,CONSOLE_OUT ; Send a space NotEmpty: MOV (R5),R0 ; Bring in the data MOV R0,R1 ; Store it MOV R0,R2 ; Also store it here INC R2 INC (R5) ; Inc RAM WORD CMP R2,(R5) ; Did if increase BNE IsROM ; Must be ROM (or Empty) MOV R1,(R5) ; Put back the origional data MOV #&52,R0 JSR PC,CONSOLE_OUT ; Send a 'R' BR Map3 IsROM: CMP #&FFFF,(R5) ; Is it Empty BNE NEmpty CMP #&FFFF,2(R5) ; Check next higher word BNE NotEmpty CMP #&FFFF,4(R5) ; Check next higher word BNE NotEmpty MOV #&2E,R0 ; Probably not RAM or ROM JSR PC,CONSOLE_OUT ; Send a '.' BR Map3 NEmpty: CMP #&C000,R5 ; Are we in the PDP Monitor ROM area BEQ ROM_AREA CMP #&E000,R5 ; Are we in the PDP Monitor ROM area BEQ PORTS_AREA MOV #&70,R0 JSR PC,CONSOLE_OUT ; Send a 'p' Map3: ADD #&100,R5 ; Next 100H bytes DEC R4 ; Count characters across BNE Map2 JSR PC,ConCRLF ; Show CR,LF MOV #16,R4 ; Characters across count BR Map1 ROM_AREA: MOV #ROM_AREA_MSG,R5 ; Say "--- ROM MONITOR ---" JSR PC,PrStr ; Print string JMP Loop PORTS_AREA: MOV #PORTS_AREA_MSG,R5 ; Say --- I/O PORTS ---" JSR PC,PrStr ; Print string JMP Loop ;-------------------------------- SUPPORT ROUTINES ------------------------------------------- PutWord_R5: ; Print HEX Word value in R5 SWAB R5 ; Value in R5 is retained JSR PC,PutByte_R5 ; Print HEX byte value in R5 SWAB R5 JSR PC,PutByte_R5 RTS PC PutByte_R5: ; Print HEX Byte value in R5 CLR R0 ; Clear R0 MOVB R5,R0 ; Origional number to R0 ROR R0 ; Shift upper byte to lower 4 bits ROR R0 ROR R0 ROR R0 ; Upper nibble is now lower nibble JSR PC,HexOut MOV R5,R0 JSR PC,HexOut RTS PC HexOut: ; Print Hex Byte value in R0 BICB #&F0,R0 ; Clear upper nibble ADD #&30,R0 ; CONVERT TO ASCII CMPB #&39,R0 ; See if > 9 BGE HexOK ADD #&07,R0 ; Add to make 10=A, 11=B... HexOK: JSR PC,CONSOLE_OUT RTS PC ToUpper: ; >>> ;a-z to A-Z CMP #&61,R0 ; less than 'a' BGT SkipToU CMP #&7A,R0 ; Greater tha 'z' BLT SkipToU SUB #&20,R0 ; Adjust SkipToU: RTS PC PrStr: MOVB (R5)+,R0 ; >>> Print String Routine to ODT (or S100 Console) BEQ PrStr1 JSR PC,CONSOLE_OUT BR PrStr ; Next character PrStr1: RTS PC ; return S100_PrStr: MOVB (R5)+,R0 ; >>> Print String Routine direct to S100 Console BEQ PrStr2 JSR PC,S100_CONSOLE_OUT BR S100_PrStr PrStr2: RTS PC ; return ConSPACE2: ; >>> Send SPACE+SPACE to ODT or S100 console MOVB #SPACE,R0 JSR PC,CONSOLE_OUT ConSPACE1: MOVB #SPACE,R0 JSR PC,CONSOLE_OUT RTS PC ; Note R0 contains ASCII ctaracter (as a Byte) ConCRLF: ; >>> Send CR+LF to ODT or S100 console MOVB #CR,R0 JSR PC,CONSOLE_OUT ConLF: ; >>> Send LF to ODT or S100 console MOVB #LF,R0 JSR PC,CONSOLE_OUT RTS PC ; Note R0 contains ASCII character (as a Byte) ;----------------------------------------------------------------------------------------------------------- Set_CONSOLE_IO: ; Set FLAG in RAM to decide where Console IO is directed. CMPB #&FF,@#DEBUG_CONOUT_STAT ; See if Port FF14 is present. (Will be FF if no Support Board present) BEQ NO_SBoard BITB #BIT0,@#DEBUG_CONOUT_STAT ; See if input comes from the S100 Bus (Support Board present) BEQ SET_S100_CONSOLE SET_ODT_CONSOLE: MOV #&FFFF,@#CONSOLE_IO_FLAG ; FFFF = ALL CONSOLE IO TO ODT UART. ANYTHING ELSE THEN SEND TO S100 CONSOLE RTS PC ; Note R0 contains ASCII character (as a Byte) SET_S100_CONSOLE: MOV #&0000,@#CONSOLE_IO_FLAG ; FFFF = ALL CONSOLE IO TO ODT UART. ANYTHING ELSE THEN SEND TO S100 CONSOLE RTS PC ; Note R0 contains ASCII character (as a Byte) NO_SBoard: BITB #BIT0,@#ODT_CONOUT_STAT ; Input comes from from the CPU Board UART (No Support Board Present) BEQ SET_S100_CONSOLE BR SET_ODT_CONSOLE CONIN_STATUS: ; Check if Character at Console, Set Carry if true CMP #&FFFF,@#CONSOLE_IO_FLAG ; FFFF = ALL CONSOLE IO TO ODT UART. ANYTHING ELSE THEN SEND TO S100 CONSOLE BEQ ODT_CONIN_STATUS BR S100_CONIN_STATUS ; If not go to the default ODT routine in the CPU S100_CONIN_STATUS: BITB #BIT1,@#S100_CONIN_STAT ; Check bit-1/ready of Propeller board Console In port (0H) ODT_STAT1: BEQ S100_Nothing ; Nothing there while bit-1 is 0 SEC ; Set Carry Flag if ESC RTS PC ; Return with Carry Set if a character is available S100_Nothing: CLC ; Return with Carry flag cleared RTS PC ; Return ODT_CONIN_STATUS: BITB #BIT7,@#ODT_CONIN_STAT ; Check bit-7/ready of xmt status reg BR ODT_STAT1 ;----------------------------------------------------------------------------------------------------------- CONSOLE_OUT: ; >>> MAIN Console output routine. Data in R0, return unchanged <<<< CMPB #&FFFF,@#CONSOLE_IO_FLAG ; FFFF = ALL CONSOLE IO TO ODT UART. ANYTHING ELSE THEN SEND TO S100 CONSOLE BEQ ODT_CONSOLE_OUT BR S100_CONSOLE_OUT ; If not go to the default ODT routine in the CPU S100_CONSOLE_OUT: ; S100 Bus Console output routine <<<< BITB #BIT2,@#S100_CONOUT_STAT ; Check bit-2/ready of Propeller board Console Out port (0H) BEQ S100_CONSOLE_OUT ; busy-loop while bit-2 is 0 MOVB R0,@#S100_CONOUT_DATA ; Send ASCII to Propeller board Console Out port (01H) RTS PC ; Note R0 contains ASCII ctaracter (as a Byte) ODT_CONSOLE_OUT: ; ODT Console Out Routine BITB #BIT7,@#ODT_CONOUT_STAT ; Check bit-7/ready of xmt status reg BEQ ODT_CONSOLE_OUT ; busy-loop while bit-7 is 0 MOVB R0,@#ODT_CONOUT_DATA ; send ASCII to xmt data reg RTS PC ; Note R0 is still valid (as a Byte) ;----------------------------------------------------------------------------------------------------------- CONSOLE_IN: ; >>> MAIN Console input routine. Data in R0, return unchanged <<<< CMPB #&FFFF,@#CONSOLE_IO_FLAG ; FFFF = ALL CONSOLE IO TO ODT UART. ANYTHING ELSE THEN SEND TO S100 CONSOLE BEQ ODT_CONSOLE_IN BR S100_CONSOLE_IN ; If not go to the default ODT routine in the CPU S100_CONSOLE_IN: ; S100 Bus Console input routine <<<< BITB #BIT1,@#S100_CONIN_STAT ; Check bit-1/ready of Propeller board Console In port (0H) BEQ S100_CONSOLE_IN ; Nothing there while bit-1 is 0 MOVB @#S100_CONIN_DATA,R0 ; Get ASCII from Propeller board Console In port (01H) RTS PC ; Note R0 contains ASCII ctaracter (as a Byte) ODT_CONSOLE_IN: ; ODT Console In Routine BITB #BIT7,@#ODT_CONIN_STAT ; Check bit-7/ready of xmt status reg BEQ ODT_CONSOLE_IN ; Nothing there while bit-7 is 0 MOVB @#ODT_CONIN_DATA,R0 ; ASCII to R0 reg RTS PC ; Return ; ; ;-------------------------------------------------------------------------------------------------------- ; Align Signon: equs CR,LF,"PDP-11 Routine to shadow IN or OUT the V2 PDP11 CPU Board ROMs",0 MainMenu: equs CR,LF,"Remove ROMs. (Esc to Abort). (Y/N): ",0 MenuError: equs CR,LF,"Menu Error ",CR,LF,BELL,0 MM_Text: equs CR,LF,LF,"Memory Map (64K)",CR,LF,0 ROM_AREA_MSG: equs "--- ROM MONITOR ---" equs CR,LF,"D000 --- ROM MONITOR ---" equs CR,LF,"E000 " PORTS_AREA_MSG: equs "--- I/O PORTS ---" equs CR,LF,"F000 --- I/O PORTS ---",CR,LF,0 ;END