TITLE 'INITIAL PROGRAM LOADER AND GENERATOR V1.1' ; NAME ('IPLGEN') ; DATE 21-JUN-83 ; CONVERTED TO MAC/RMAC CODE 18 JULY 83 RHP ; MACLIB Z80 ; Z-80 CODING IS USED ; ; ASEG ; ; *** ASCII CONSTANTS *** ; CR EQU 0DH LF EQU 0AH BELL EQU 07H EOM EQU '$' RETRY EQU 10 BDOS EQU 0005H ; ; ; ; *** PORT ASSIGNMENTS *** ; SCSI$BASE EQU 0050H ; SCSI INTERFACE BOARD BASE QUAD$EIA EQU 0010H ; BASE PORT FOR QUAD. EIA BOARD CRTSTATUS EQU QUAD$EIA+4 ; STATUS PORT FOR CONSOLE CRTDATA EQU QUAD$EIA+5 ; DATA PORT FOR CONSOLE ; TXRDY EQU 0001H ; TX. READY BIT IN 8251 USART RXRDY EQU 0002H ; RX. READY BIT IN 8251 USART ; ; *** SCSI PORT ASSIGNMENTS *** ; ; * BIT,BYTE AND PORT ASSIGMENTS FOR * ; * SCSI HOST INTERFACE ADAPTOR * ; DATAI EQU SCSI$BASE ; DATA IN REGISTER DATAO EQU SCSI$BASE+2 ; DATA OUT REGISTER BSTAT EQU SCSI$BASE+1 ; BUS STATUS SELPORT EQU SCSI$BASE ; SELECT PORT ADR. CLRINT EQU SCSI$BASE+1 ; CLR. INTRRUPT PORT DMAPORT EQU SCSI$BASE+3 ; DMA ADDRESS PORT CPARITY EQU SCSI$BASE+4 ; CLEAR PARITY PORT BUSY EQU 80H ; CONTROLER BUSY BIT CD EQU 40H ; COMMAND/DATA BIT DIREC EQU 20H ; DIRECTON BIT REQ EQU 10H ; REQUEST BIT MSG EQU 08H ; END MESSAGE BIT PERR EQU 04H ; PERR ERROR BIT BDACK EQU 02H ; BOARD ACK. SIGNAL LINT EQU 01H ; INTERUPTE BIT ; ; CSEG ; START: LXI SP,STACK ; SET UP THE STACK POINTER CALL TXOUT DB CR,LF DB 'IPLGEN00 -- INITIAL PROGRAM BOOTER AND' DB ' SYSTEM GENERATOR V1.1' DB CR,LF,LF DB 'FOR 60K SYSTEMS',CR,LF,LF,LF DB 'L)OAD OR M)AKE SYSTEM TRACK --->',EOM CALL CI ; GET ANSWER CPI 'M' ; SEE IF MAKE SYSTEM JZ MAKE$SYSTEM ; BRIF SO CPI 'L' ; SEE IF LOAD SYSTEM JZ LOAD$SYSTEM ; BRIF SO CALL TXOUT DB CR,LF,LF DB 'ERROR: PLEASE TYPE "M" OR "L"' DB CR,LF,LF,EOM JMP START ;* ;** ;* ;+ TXOUT: ;- XTHL ; HL @ DATA MOV A,M ; A = DATA INX H ; PUT BACK POINTER XTHL ; CPI EOM ; END OF MESSAGE??? RZ ; RETURN IF SO MOV E,A ; ELSE E = CHARACTER MVI C,2 ; CONSOLE OUTPUT CODE CALL BDOS ; DO THE BDOS STUFF JMP TXOUT ; AND REPEAT ;* ;** ;* ;+ CI: ;- MVI C,1 CALL BDOS RET ;* ;** ;* ;+ MAKE$SYSTEM: ;- CALL TXOUT DB CR,LF,LF DB 'PLEASE ENTER NAME OF GEN''ED CP/M SYSTEM --->',EOM LXI H,LINE$BUFFER ; HL @ LINE BUFFER MVI M,80 ; MAX. LINE SIZE = 80 CHARACTERS XCHG ; DE @ LINE BUFFER MVI C,10 ; READ CONSOLE BUFFER CALL BDOS ; LXI H,FCB ; CLEAR OUT FCB LXI D,FCB+1 ; LXI B,33 ; MVI M,00 ; PRIME THE ROUTINE LDIR ; PERFORM THE OPERATION LXI D,FCB+1 ; DE @ FILENAME LXI H,LINE$BUFFER+1 ; HL @ FILENAME LINE MOV C,M ; C = SIZE OF LINE INX H ; POINT TO DATA PART OF LINE MVI B,8 ; B = SIZE OF FILENAME MS010: MOV A,M ; A = DATA FROM LINE CPI '.' ; IS IT A DOT?? JZ MS020 ; BRIF SO STAX D ; ELSE STUFF TO FCB INX H ; INX D ; INCREMENT POINTERS DJNZ MS010 ; MS030: MOV A,M ; SKIP PAST '.' CPI '.' ; JZ MS020 ; BRIF FOUND INX H ; JMP MS030 ; AND COUNTINE ;* MS020: INX H ; POINT PAST '.' MOV A,B ; SEE IF ALL FILENAME IS FILED ORA A ; JZ MS040 ; BRIF SO MS050: MVI A,' ' ; PAD WITH SPACES STAX D ; INX D ; DJNZ MS050 ; MS040: LXI B,3 ; LDIR ; TRNSFR REST OF FILE NAME LXI D,FCB ; TRY TO OPEN MVI C,15 ; CALL BDOS ; CPI 0FFH ; CHECK FOR ERROR JNZ MS060 ; BRIF OK CALL TXOUT ; DB CR,LF,LF DB 'ERROR: CANNOT OPEN FILE ',EOM LDED LINE$BUFFER+1 LXI H,LINE$BUFFER+2 MVI D,0 DAD D MVI M,'$' LXI D,LINE$BUFFER+2 MVI C,9 CALL BDOS JMP MAKE$SYSTEM ;* MS060: CALL TXOUT DB CR,LF DB 'LOADING FILE ...',EOM LXI H,BUFFER MS070: XCHG ; DE @ DMA BUFFER PUSH D ; SAVE MVI C,26 ; SET DMA CALL BDOS ; LXI D,FCB ; DE @ FCB MVI C,20 ; GO READ A RECORD CALL BDOS ; PERFORM THE READ ORA A ; CHECK FOR ERRORS JNZ MS080 ; BRIF DONE POP H ; INCREMENT DMA LXI D,128 ; DAD D ; JMP MS070 ; ;* MS080: CALL TXOUT ; DB CR,LF,'OK',CR,LF,EOM CALL GET$DRIVE ; GO GET THE PROPER DRIVE CODE LXI H,BUFFER+0880H ; START = BUFFER SHLD BEGIN ; POP H ; END = LAST DMA SHLD LAST ; MVI A,03 ; COMMAND IS WRITE STA COMMAND ; CALL DOIO ; AND DO THE I/O CALL TXOUT DB CR,LF,LF DB 'OPERATION COMPLETED',CR,LF,EOM JMP 0000 ;* ;** ;* ;+ GET$DRIVE: ;- CALL TXOUT DB CR,LF DB 'ENTER 0 (DRIVE #0) OR 1 (DRIVE #1) -->',EOM CALL CI CPI '0' JZ GD99 CPI '1' JNZ GD010 MVI A,20H STA DRIVE GD99: CALL TXOUT DB CR,LF DB 'OK',CR,LF,EOM RET ;* GD010: CALL TXOUT DB CR,LF DB 'ERROR: PLEASE ENTER EITHER 0 OR 1',CR,LF,EOM JMP GET$DRIVE ;* ;** ;* ;+ LOAD$SYSTEM: ;- CALL TXOUT DB CR,LF,LF DB 'LOAD SYSTEM FUNCTION SELECTED',CR,LF,EOM CALL GET$DRIVE LXI H,0D400H SHLD BEGIN LXI H,0F700H SHLD LAST MVI A,1 STA COMMAND CALL TXOUT DB CR,LF,LF DB 'LOADING SYSTEM ...',EOM CALL DOIO JMP 0EA00H ;* ;** ;* ;+ DOIO: ;- LXI H,COMMAND LDA DRIVE ORA M MOV M,A LDED BEGIN SDED DMA MVI A,1 STA COMMAND+2 STA COMMAND+4 DOIO10: LXI H,COMMAND CALL DOCMD JRZ DOIO20 CALL TXOUT DB CR,LF,LF DB 'ERROR: DISK I/O ERROR DETECTED, OPERATION ABORTED' DB CR,LF,EOM JMP 0000 ;* DOIO20: LXI H,COMMAND+2 INR M LXI H,DMA+1 INR M LHLD DMA LDED LAST ORA A DSBC DE JC DOIO10 RET ;* ;** ;* ; ;* START OF PROTOCAL HANDLING ROUTNES * ; ;+ DOCMD: ;-OP: ISSUE COMMAND TO SCSI HOST ADAPTOR ;-PP: HL @ COMMAND BYTES TO SEND ;- @ACTSEC & @RPNTR ARE VALID ;-RC: NO - ZERO : ERROR IN COMMAND (A = ERROR BITS) ;- ZERO : COMMAND WAS EXECUTED SUCCESSFULLY ;- SHLD LCMD@ ; SAVE COMMAND @ MVI A,RETRY ; GET RETRY COUNT STA TRYCNTR ; RESET COUNTER OUT CPARITY ; RESET PARITY ERROR DCMD1: PUSH B ; SAVE COUNTER CALL ?PUTDMA ; SET DMA ADDRESS CALL ?SELECT ; GO SELECT CONTROLER POP B ; RECOVER BC ; WAIT: ; ;* HERE WE MUST WAIT FOR EXECUTION * ; IN BSTAT ; A <--- BUSS STATUS ANI CD+REQ ; CHECK FOR DATA JRNZ WAIT ; BRIF STILL DATA IN DATAI ; A <-- COMPLETION STATUS PUSH PSW ; SAVE ENDING STATUS WAIT1: IN BSTAT ; WAIT FOR REQ. AND MSG. ANI REQ+MSG ; JRNZ WAIT1 ; IN DATAI ; GET BYTE OF ZERO POP PSW ; RECOVER STATUS ANI 00011111B ; MASK OUT ERRORS JRNZ WAIT4 ; BRIF NOT OK IN BSTAT ; CHECK FOR PARITY ANI PERR ; OUT CLRINT ; CLEAR INTERRUPT MVI A,0FFH ; JRNZ WAIT4 ; BRIF ERROR XRA A ; EXIT WITH ZERO RET ; AND EXIT ;* ;* WAIT7: POP PSW ; CLEAR OUT STACK WAIT4: BIT 2,A ; HARDWARE BUSY?? JRZ WAIT6 ; BRIF NOT CALL TXOUT DB CR DB 'PLEASE WAIT, DRIVE IS SPINING UP',EOM JR WAIT5 ; AND CONTINUE ;* WAIT6: LXI H,TRYCNTR ; SEE IF RETRY UP DCR M ; JRZ WAIT2 ; BRIF RETRY IS UP WAIT5: LHLD LCMD@ ; RECOVER LAST COMMAND JMP DCMD1 ; AND TRY AGAIN ;* WAIT2: OUT CLRINT ; CLEAR INTERRUPT ORA A ; EXIT WITH NON-ZERO RET ; AND EXIT ;* ;** ;* ;+ ?PUTDMA: ;-OP: SEND DMA ADDRESS TO HOST ADAPTER ;-PP: RPNTR HAS DMA ADDRESS ;- LDA HIDMA ; SET HI-BYTE OUT DMAPORT ; HIGH BYTE ALWAYS ZERO LDED DMA ; DE @ DMA ADDRESS MOV A,D OUT DMAPORT ; SEND BYTE 1 MOV A,E OUT DMAPORT ; SEND BYTE 2 RET ; AND EXIT ;* ;** ;* ;+ ?SELECT: ;-OP: SELECT CONTROLER ;- IN BSTAT ; IS CONTROLER BUSY?? ANI BUSY ; WAIT FOR NOT BUSY JRZ ?SELECT ; WAIT IF SO SEL2: MVI A,01H ; SELECT CONTROLER #1 OUT DATAO ; OUT SELPORT ; AND SELECT CONTROLER SEL1: IN BSTAT ; WAIT FOR REQ ANI REQ ; JRNZ SEL1 ; MOV D,A ; D=0, MARK FIRST COMMAND ; ;* NOW FALL ON THRU TO OUTPUT COMMAND BYTES * ; ;+ ?OUTCMD: ;-OP: ISSUE COMMAND BYTES TO HOST ADAPTOR ;-PP: HL @ COMMAND BYTES ;- IN BSTAT ; GRAB BUSS STATUS MOV C,A ; SAVE STATUS ANI CD ; SEE IF DATA RNZ ; EXIT IF DATA MOV A,C ; CHECK FOR DIREC ANI DIREC ; RZ ; EXIT IF INPUT MVI A,REQ+BDACK ; BIT 0,D ; SEE IF FIRST CMD. JRNZ ?OC5 ; BRIF NOT MVI A,REQ ; ELSE JUST CHECK FOR REQ. ?OC5: ANA C ; CHECK FOR READY JRNZ ?OUTCMD ; BRIF NOT (1.75/1.17) ?OC1: MOV A,M ; GET COMMAND BYTE (1.75/1.17) OUT DATAO ; SEND TO CONTROLER (2.75/1.83) INX H ; POINT NEXT (1.5/1.0) MVI D,1 ; MARK NOT FIRST COMMAND JR ?OUTCMD ; AND DO IT AGAIN! ;* ;** ;* ; ; DSEG LINE$BUFFER: DS 80+2 LAST: DW 00 BEGIN: DW 00 HIDMA: DW 00 DRIVE: DW 00 DMA: DW 00 LCMD@: DW 00 TRYCNTR: DW 00 COMMAND: DW 00,00,00,00 FCB: DS 36 DW 100 STACK: BUFFER: END