ORG 0100H ;------------------------------------------------------------ ; SCSTEST_MENU_Z80.ASM ; ; Standalone Z80 NCR5380 SCSI read/write sector test ; No CP/M BDOS calls required for console I/O. ; ; Console: ; CONSOLE_STATUS = 00H ; CONSOLE_DATA = 01H ; ; NCR5380: ; Base I/O address = 40H ; ; Menu driven: ; R = read selected CP/M 128-byte sector ; W = write test pattern to selected CP/M sector, then read back ; T = set track number, 4 hex digits ; S = set sector number, 2 hex digits, 01..40H normally ; D = dump last read sector buffer ; Q = quit / return ; ; Disk geometry: ; CP/M logical sector size = 128 bytes ; SCSI physical sector = 512 bytes ; CP/M sectors per track = 64 ; 4 CP/M sectors per SCSI sector ; ; LBA = TRACK * 16 + ((SECTOR - 1) / 4) ; ; WARNING: ; The W command writes a 128-byte test pattern into the selected ; CP/M sector using read/modify/write of the containing 512-byte ; SCSI physical sector. ;------------------------------------------------------------ CONSOLE_STATUS EQU 00H CONSOLE_DATA EQU 01H DEFAULT_TRK EQU 0000H DEFAULT_SEC EQU 0001H NCRBASE EQU 48H ;Base port for all ports on board U17_SEL EQU 48H ;U17 address selection port store for NCR5380 NCR_CS EQU 4AH ;Chip select for NRC5380 SCSI chip ODR EQU NCRBASE+0 CSD EQU NCRBASE+0 ICR EQU NCRBASE+1 MR2 EQU NCRBASE+2 TCR EQU NCRBASE+3 SER EQU NCRBASE+4 CSB EQU NCRBASE+4 BSR EQU NCRBASE+5 IDR EQU NCRBASE+6 RPI EQU NCRBASE+7 ICR_DBUS EQU 01H ICR_ATN EQU 02H ICR_SEL EQU 04H ICR_BSY EQU 08H ICR_ACK EQU 10H ICR_RST EQU 80H PH_DATAOUT EQU 00H PH_DATAIN EQU 01H PH_COMMAND EQU 02H PH_STATUS EQU 03H PH_MSGOUT EQU 06H PH_MSGIN EQU 07H CSB_REQ EQU 20H CSB_BSY EQU 40H OURID EQU 80H ;Controller SCSI ID (ID 7) TGTID EQU 01H ;Assumes SCSI drive ID is 0 START: LD SP,STACK ; CALL SCSI_INIT ;<--- This was suggested by Chat GTP (made no difference) LD HL,DEFAULT_TRK LD (CURTRK),HL LD HL,DEFAULT_SEC LD (CURSEC),HL CALL CRLF LD HL,MSG_TITLE CALL PSTRING MAIN_MENU: CALL SHOW_POSITION LD HL,MSG_MENU CALL PSTRING CALL CONSOLE_INPUT_UPPER CALL ECHO_CHAR CALL CRLF CP 'R' JP Z,DO_READ CP 'W' JP Z,DO_WRITE CP 'T' JP Z,SET_TRACK CP 'S' JP Z,SET_SECTOR CP 'D' JP Z,DO_DUMP CP 'Q' JP Z,EXIT_PROGRAM LD HL,MSG_BAD CALL PSTRING JP MAIN_MENU EXIT_PROGRAM: LD HL,MSG_EXIT CALL PSTRING RET DO_READ: CALL MAKE_LBA CALL SCSI_READ512 OR A JP NZ,SCSI_ERROR CALL COPY_FROM_SECBUF LD HL,MSG_READOK CALL PSTRING CALL DUMP_DMABUF JP MAIN_MENU DO_WRITE: LD HL,MSG_WARN1 CALL PSTRING CALL CONSOLE_INPUT_UPPER CALL ECHO_CHAR CALL CRLF CP 'Y' JP NZ,MAIN_MENU CALL MAKE_LBA CALL MAKE_PATTERN CALL COPY_TO_SECBUF_RMW OR A JP NZ,SCSI_ERROR CALL SCSI_WRITE512 OR A JP NZ,SCSI_ERROR LD HL,MSG_WRITEOK CALL PSTRING CALL SCSI_READ512 OR A JP NZ,SCSI_ERROR CALL COPY_FROM_SECBUF CALL DUMP_DMABUF JP MAIN_MENU SET_TRACK: LD HL,MSG_TRACK CALL PSTRING CALL READ_HEX4 LD (CURTRK),HL CALL CRLF JP MAIN_MENU SET_SECTOR: LD HL,MSG_SECTOR CALL PSTRING CALL READ_HEX2 LD L,A LD H,0 LD (CURSEC),HL CALL CRLF JP MAIN_MENU DO_DUMP: LD HL,MSG_DUMP CALL PSTRING CALL DUMP_DMABUF JP MAIN_MENU SCSI_ERROR: LD HL,MSG_SCSIERR CALL PSTRING JP MAIN_MENU MAKE_LBA: LD HL,(CURSEC) DEC HL LD A,L AND 03H CP 00H JR NZ,MO1 XOR A LD (SECOFFL),A LD (SECOFFH),A JR MOX MO1: CP 01H JR NZ,MO2 LD A,080H LD (SECOFFL),A XOR A LD (SECOFFH),A JR MOX MO2: CP 02H JR NZ,MO3 XOR A LD (SECOFFL),A LD A,01H LD (SECOFFH),A JR MOX MO3: LD A,080H LD (SECOFFL),A LD A,01H LD (SECOFFH),A MOX: LD A,L SRL A SRL A AND 0FH LD E,A LD D,0 LD HL,(CURTRK) ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,DE LD A,L LD (LBA0),A LD A,H LD (LBA1),A XOR A LD (LBA2),A RET COPY_FROM_SECBUF: LD HL,SECBUF LD A,(SECOFFL) LD E,A LD A,(SECOFFH) LD D,A ADD HL,DE LD DE,DMABUF LD BC,128 LDIR RET COPY_TO_SECBUF_RMW: CALL SCSI_READ512 OR A RET NZ LD HL,DMABUF LD DE,SECBUF LD A,(SECOFFL) LD C,A LD A,(SECOFFH) LD B,A EX DE,HL ADD HL,BC EX DE,HL LD BC,128 LDIR XOR A RET MAKE_PATTERN: LD HL,DMABUF LD B,128 LD A,00H MP1: LD (HL),A INC A INC HL DJNZ MP1 LD HL,DMABUF LD (HL),'S' INC HL LD (HL),'C' INC HL LD (HL),'S' INC HL LD (HL),'I' INC HL LD (HL),'-' INC HL LD (HL),'T' INC HL LD (HL),'E' INC HL LD (HL),'S' INC HL LD (HL),'T' RET SCSI_READ512: CALL BUILD_READ_CDB LD A,'@' ;;;;;;;;;;;;;;;; CALL ZCO CALL SCSI_SELECT RET NZ LD A,'#' ;;;;;;;;;;;;;;;; CALL ZCO LD HL,CDB LD B,6 CALL SCSI_SEND_CMD RET NZ LD A,'$' ;;;;;;;;;;;;;;;; CALL ZCO LD HL,SECBUF LD DE,512 CALL SCSI_RECV_DATA RET NZ LD A,'%' ;;;;;;;;;;;;;;;; CALL ZCO CALL SCSI_GET_STATUS RET SCSI_WRITE512: CALL BUILD_WRITE_CDB CALL SCSI_SELECT RET NZ LD HL,CDB LD B,6 CALL SCSI_SEND_CMD RET NZ LD HL,SECBUF LD DE,512 CALL SCSI_SEND_DATA RET NZ CALL SCSI_GET_STATUS RET BUILD_READ_CDB: LD HL,CDB LD (HL),08H INC HL LD A,(LBA2) AND 1FH LD (HL),A INC HL LD A,(LBA1) LD (HL),A INC HL LD A,(LBA0) LD (HL),A INC HL LD (HL),01H INC HL LD (HL),00H RET BUILD_WRITE_CDB: LD HL,CDB LD (HL),0AH INC HL LD A,(LBA2) AND 1FH LD (HL),A INC HL LD A,(LBA1) LD (HL),A INC HL LD A,(LBA0) LD (HL),A INC HL LD (HL),01H INC HL LD (HL),00H RET SCSI_SELECT: XOR A ;;;;;;; OUT (ICR),A ;<<<<<<<<<<<< PUSH AF ; LD A,ICR ;Store NRC port address select OUT (U17_SEL),A ; POP AF ; OUT (NCR_CS),A ; ;;;;;;; OUT (TCR),A ;<<<<<<<<<<<< PUSH AF ; LD A,TCR ;Store NRC port address select OUT (U17_SEL),A ; POP AF ; OUT (NCR_CS),A ; ;Store NRC port address select ;;;;;;; OUT (MR2),A ;<<<<<<<<<<<< PUSH AF ; LD A,MR2 ;Store NRC port address select OUT (U17_SEL),A ; POP AF ; OUT (NCR_CS),A ; SELWAIT: ;;;;;; IN A,(CSB) ;<<<<<<<<<<<<<< LD A,CSB ;Store NRC port address select OUT (U17_SEL),A IN A,(NCR_CS) AND CSB_BSY JR NZ,SELWAIT LD A,OURID+TGTID ;;;;;;; OUT (ODR),A ;<<<<<<<<<<<< PUSH AF ; LD A,ODR ;Store NRC port address select OUT (U17_SEL),A ; POP AF ; OUT (NCR_CS),A ; LD A,ICR_DBUS+ICR_SEL ;;;;;;; OUT (ICR),A ;<<<<<<<<<<<< PUSH AF ; LD A,ICR ;Store NRC port address select OUT (U17_SEL),A ; POP AF ; OUT (NCR_CS),A ; CALL DELAY SELBUSY: ;;;;;;; IN A,(CSB) LD A,CSB ;Store NRC port address select OUT (U17_SEL),A IN A,(NCR_CS) AND CSB_BSY JR Z,SELBUSY XOR A ;;;;;;; OUT (ICR),A ;<<<<<<<<<<<< PUSH AF ; LD A,ICR ;Store NRC port address select OUT (U17_SEL),A ; POP AF ; OUT (NCR_CS),A ; ;Store NRC port address select XOR A RET SCSI_SEND_CMD: LD A,PH_COMMAND ;;;;;;; OUT (TCR),A ;<<<<<<<<<<<< PUSH AF ; LD A,TCR ;Store NRC port address select OUT (U17_SEL),A ; POP AF ; OUT (NCR_CS),A ; SCMD1: LD A,(HL) CALL SCSI_SEND_BYTE RET NZ INC HL DJNZ SCMD1 XOR A RET SCSI_SEND_DATA: ;;;;;;; OUT (TCR),A ;<<<<<<<<<<<< LD A,PH_DATAOUT ;<---- Suggested by Chat GPT ------------- PUSH AF ; LD A,TCR ;Store NRC port address select OUT (U17_SEL),A ; POP AF ; OUT (NCR_CS),A ; SDO1: LD A,D OR E JR Z,SDO_DONE LD A,(HL) CALL SCSI_SEND_BYTE RET NZ INC HL DEC DE JP SDO1 SDO_DONE: XOR A RET SCSI_RECV_DATA: LD A,PH_DATAIN ;;;;;;; OUT (TCR),A ;<<<<<<<<<<<< PUSH AF ; LD A,TCR ;Store NRC port address select OUT (U17_SEL),A ; POP AF ; OUT (NCR_CS),A ; SDI1: LD A,D OR E JR Z,SDI_DONE CALL SCSI_RECV_BYTE LD (HL),A INC HL DEC DE JP SDI1 SDI_DONE: XOR A RET SCSI_SEND_BYTE: ;;;;;;; OUT (ODR),A ;<<<<<<<<<<<< PUSH AF ; LD A,ODR ;Store NRC port address select OUT (U17_SEL),A ; POP AF ; OUT (NCR_CS),A ; WSREQ1: ;;;;;;; IN A,(CSB) ;<<<<<<<<<<<< LD A,CSB ;Store NRC port address select OUT (U17_SEL),A IN A,(NCR_CS) AND CSB_REQ JR Z,WSREQ1 LD A,ICR_DBUS ;;;;;;; OUT (ICR),A ;<<<<<<<<<<<< PUSH AF ; LD A,ICR ;Store NRC port address select OUT (U17_SEL),A ; POP AF ; OUT (NCR_CS),A ; LD A,ICR_DBUS+ICR_ACK ;;;;;;; OUT (ICR),A ;<<<<<<<<<<<< PUSH AF ; LD A,ICR ;Store NRC port address select OUT (U17_SEL),A ; POP AF ; OUT (NCR_CS),A ; WSREQ0: ;;;;;;; IN A,(CSB) ;<<<<<<<<<<<< LD A,CSB ;Store NRC port address select OUT (U17_SEL),A IN A,(NCR_CS) AND CSB_REQ JR NZ,WSREQ0 XOR A ;;;;;;; OUT (ICR),A ;<<<<<<<<<<<< PUSH AF ; LD A,ICR ;Store NRC port address select OUT (U17_SEL),A ; POP AF ; OUT (NCR_CS),A ; XOR A RET SCSI_RECV_BYTE: WRREQ1: ;;;;;;; IN A,(CSB) ;<<<<<<<<<<<< LD A,CSB ;Store NRC port address select OUT (U17_SEL),A IN A,(NCR_CS) AND CSB_REQ JR Z,WRREQ1 ;;;;;;; IN A,(CSD) ;<<<<<<<<<<<< LD A,CSD ;Store NRC port address select OUT (U17_SEL),A IN A,(NCR_CS) PUSH AF LD A,ICR_ACK ;;;;;;; OUT (ICR),A ;<<<<<<<<<<<< PUSH AF ; LD A,ICR ;Store NRC port address select OUT (U17_SEL),A ; POP AF ; OUT (NCR_CS),A ; WRREQ0: ;;;;;;; IN A,(CSB) ;<<<<<<<<<<<< LD A,CSB ;Store NRC port address select OUT (U17_SEL),A IN A,(NCR_CS) AND CSB_REQ JR NZ,WRREQ0 XOR A ;;;;;;; OUT (ICR),A ;<<<<<<<<<<<< PUSH AF ; LD A,ICR ;Store NRC port address select OUT (U17_SEL),A ; POP AF ; OUT (NCR_CS),A ; POP AF RET SCSI_GET_STATUS: LD A,PH_STATUS ;;;;;;; OUT (TCR),A ;<<<<<<<<<<<< PUSH AF ; LD A,TCR ;Store NRC port address select OUT (U17_SEL),A ; POP AF ; OUT (NCR_CS),A ; CALL SCSI_RECV_BYTE LD (SCSISTAT),A LD A,PH_MSGIN ;;;;;;; OUT (TCR),A ;<<<<<<<<<<<< PUSH AF ; LD A,TCR ;Store NRC port address select OUT (U17_SEL),A ; POP AF ; OUT (NCR_CS),A ; CALL SCSI_RECV_BYTE LD (SCSIMSG),A LD A,(SCSISTAT) OR A JR Z,SGOK LD A,1 RET SGOK: XOR A RET SCSI_INIT: ;Chat GTP code additions XOR A CALL NCR_OUT_ICR CALL NCR_OUT_TCR CALL NCR_OUT_MR2 CALL NCR_OUT_SER LD A,ICR_RST CALL NCR_OUT_ICR CALL LONG_DELAY XOR A CALL NCR_OUT_ICR CALL LONG_DELAY CALL LONG_DELAY RET NCR_OUT_ICR: PUSH AF LD A,ICR OUT (U17_SEL),A POP AF OUT (NCR_CS),A RET NCR_OUT_TCR: PUSH AF LD A,TCR OUT (U17_SEL),A POP AF OUT (NCR_CS),A RET NCR_OUT_MR2: PUSH AF LD A,MR2 OUT (U17_SEL),A POP AF OUT (NCR_CS),A RET NCR_OUT_SER: PUSH AF LD A,SER OUT (U17_SEL),A POP AF OUT (NCR_CS),A RET LONG_DELAY: LD DE,0010H LDLY1: LD BC,0FFFFH LDLY2: DEC BC LD A,B OR C JR NZ,LDLY2 DEC DE LD A,D OR E JR NZ,LDLY1 RET ;----------------------------------- Support Routines ------------------------- ZCI: IN A,(CONSOLE_STATUS) AND 02H JR Z,ZCI IN A,(CONSOLE_DATA) AND 7FH RET ZCO: PUSH AF ;Note this is different from typical Monitor ZCO ZCO1: IN A,(CONSOLE_STATUS) ;where the character in in [C] AND 04H JR Z,ZCO1 POP AF OUT (CONSOLE_DATA),A ;<<<<<<<<<<<< ;Store NRC port address select RET ZCSTS: IN A,(CONSOLE_STATUS) AND 02H JP Z,NOCHAR GOT_CHAR: XOR A DEC A RET NOCHAR: XOR A RET CONSOLE_INPUT_UPPER: CALL ZCI CP 'a' RET C CP 'z'+1 RET NC SUB 20H RET ECHO_CHAR: CALL ZCO RET PSTRING: LD A,(HL) CP '$' RET Z CALL ZCO INC HL JR PSTRING CRLF: PUSH AF LD A,13 CALL ZCO LD A,10 CALL ZCO POP AF RET SPACE: LD A,' ' CALL ZCO RET READ_HEX4: LD HL,0 LD B,4 RH4_1: CALL READ_HEX_NIBBLE ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL LD E,A LD D,0 ADD HL,DE DJNZ RH4_1 RET READ_HEX2: CALL READ_HEX_NIBBLE RLCA RLCA RLCA RLCA LD B,A CALL READ_HEX_NIBBLE OR B RET READ_HEX_NIBBLE: CALL CONSOLE_INPUT_UPPER CALL ECHO_CHAR CP '0' JR C,READ_HEX_NIBBLE CP '9'+1 JR C,RHN_DIGIT CP 'A' JR C,READ_HEX_NIBBLE CP 'F'+1 JR NC,READ_HEX_NIBBLE SUB 'A'-10 RET RHN_DIGIT: SUB '0' RET HEXOUT: PUSH AF RRCA RRCA RRCA RRCA CALL HEXNIB POP AF CALL HEXNIB RET HEXNIB: AND 0FH CP 10 JR C,HEXDIG ADD A,7 HEXDIG: ADD A,'0' CALL ZCO RET PRINT_HL_HEX: LD A,H CALL HEXOUT LD A,L CALL HEXOUT RET PRINT_A_HEX: CALL HEXOUT RET SHOW_POSITION: CALL CRLF LD HL,MSG_POS1 CALL PSTRING LD HL,(CURTRK) CALL PRINT_HL_HEX LD HL,MSG_POS2 CALL PSTRING LD HL,(CURSEC) LD A,L CALL PRINT_A_HEX CALL CRLF RET DUMP_DMABUF: LD HL,DMABUF LD B,8 DUMPLINE: PUSH BC LD B,16 DUMPBYTE: LD A,(HL) CALL HEXOUT CALL SPACE INC HL DJNZ DUMPBYTE CALL CRLF POP BC DJNZ DUMPLINE RET DELAY: LD BC,0020H DLY1: DEC BC LD A,B OR C JR NZ,DLY1 RET MSG_TITLE: DB 'NCR5380 SCSI SECTOR TEST - DIRECT CONSOLE I/O (V0.1A) ',13,10,'$' MSG_MENU: DB 13,10 DB 'R = Read selected sector',13,10 DB 'W = Write test pattern to selected sector',13,10 DB 'T = Set track, 4 hex digits',13,10 DB 'S = Set sector, 2 hex digits',13,10 DB 'D = Dump last buffer',13,10 DB 'Q = Quit',13,10 DB 'Choice: $' MSG_POS1: DB 'Current Track=$' MSG_POS2: DB ' Sector=$' MSG_TRACK: DB 'Enter track as 4 hex digits: $' MSG_SECTOR: DB 'Enter sector as 2 hex digits, 01-40H: $' MSG_BAD: DB 'Unknown command',13,10,'$' MSG_WARN1: DB 'WRITE WILL MODIFY THE DISK. Type Y to continue: $' MSG_READOK: DB 'READ OK - 128 byte sector dump:',13,10,'$' MSG_WRITEOK: DB 'WRITE OK - readback follows:',13,10,'$' MSG_DUMP: DB 'Last 128 byte buffer:',13,10,'$' MSG_SCSIERR: DB 'SCSI ERROR',13,10,'$' MSG_EXIT: DB 'Exiting.',13,10,'$' CURTRK: DW 0 CURSEC: DW 1 LBA0: DB 0 LBA1: DB 0 LBA2: DB 0 SECOFFL: DB 0 SECOFFH: DB 0 CDB: DS 6 SCSISTAT: DB 0 SCSIMSG: DB 0 DMABUF: DS 128 SECBUF: DS 512 DS 256 STACK: END START