;===============================================================; ; ; ; MBOOT86.A86 Ver 1.00 ; ; (preliminary release 11/08/83) ; ; ; ; This program accepts a file that comes in over ; ; an IBM ASYNC adapter board, port-0. ; ; ; ; **** BEWARE **** ; ; This codes is a 2 hour attempt at converting MBOOT ; ; from CP/M-80,8080 code TO CP/M-86,8086 code. It is ; ; not an exact translation!! Like MBOOT, is does have ; ; a terminal mode and will receive a file used the ; ; MODEM/XMODEM protocol. ; ; ; ; CREDITS ; ; MODEM BOOT(MBOOT) - Keith Petersen W8SDZ ; ; Terminal routine - John Taylor ; ; Based on MODEM.ASM - Ward Christensen ; ; MBOOT86 for CP/M-86 - Daniel Deward ; ; ; ; FOR THE CP/M-86 OPERATING SYSTEM ; ; To generate a .CMD file, ; ; A>asm86 mboot86 ; ; A>gencmd mboot86 ; ; ; ;===============================================================; ; ; BDOS FUNCTION NUMBERS ; CONINP EQU 1 ;CONSOLE INPUT CONOUT EQU 2 ;CONSOLE OUTPUT CSTAT EQU 11 ;GET CONSOLE STATUS ; ; ASCII CONTROL CHARACTER EQUATES ; SOH EQU 01H ;START OF HEADER EOT EQU 04H ;END OF TRANSMISSION CR EQU 0DH ;CARRIAGE RETURN LF EQU 0AH ;LINE FEED ESC EQU 1BH ;ESCAPE ACK EQU 06H ;ACKNOWLEDGE NAK EQU 15H ;NEGATIVE ACK CAN EQU 18H ;CANCEL TRANSMISSION ; ERRLIM EQU 10 EXITKEY EQU 03H ;CONTROL-C ; ; I/O PORT ASSIGNMENTS ; MODDATP EQU 03F8H ;MODEM DATA PORT MODCTLP EQU 03FDH ;MODEM CONTROL PORT ; ; CSEG CLI ;DISABLE INTERRUPTS MOV DX,OFFSET MSG1 ;LOGON CALL PSTRING ; MOV AL,FCB+1 ;CHECK FOR FILE ON COMMAND LINE CMP AL,' ' JNZ TERMI ; MOV DX,OFFSET MSG2 ;NO FILE NAME SPECIFIED CALL PSTRING JMP EXIT ; TERMI: MOV DX,MODDATP IN AL,DX ;GOBBLE UP GARBAGE IN AL,DX ; MOV DX,OFFSET MSG3 ;TERMINAL MODE CALL PSTRING ; TMODE: CALL STAT ;GET KEYBOARD STATUS JZ TERML ;NO CHAR READY CALL KEYIN ;ESLE GET CHAR CMP AL,EXITKEY ;TEST FOR EXIT JNZ KEYOK JMP EXIT ; KEYOK: CMP AL,ESC ;START FILE XFER ? JZ RCVFIL ; MOV DX,MODDATP OUT DX,AL ; TERML: MOV DX,MODCTLP ;GET MODEM STATUS IN AL,DX TEST AL,01H JZ TMODE ;NO CHAR YET MOV DX,MODDATP ;GET MODEM DATA IN AL,DX CALL COUT JMP TMODE ; RCVFIL: CALL MAKEFIL MOV DX,OFFSET MSG4 ;FILE OPEN READY TO RECEIVE CALL PSTRING ; RCVLP: CALL RCVSECT ;GET SECTOR JC RCVEOT ;IF END OF TRANSFER CALL WRSECT ;WRITE SECTOR CALL INCRSNO ;ADVANCE SECTOR # CALL SENDACK ;ACK RECORD JMP RCVLP ;CONTINUE TILL EOT ; RCVEOT: CALL WRBLOCK ;WRITE OUT LAST BUFFER CALL SENDACK ;SEND ACK CALL CLOSEFIL ;CLOSE THE FILE ; MOV DX,OFFSET MSG5 ;TRANSFER COMPLETE CALL PSTRING JMP EXIT ; ; SUBROUTINE RCVSECT ; RCVSECT: XOR AL,AL MOV ERRCT,AL ;RESET ERROR COUNT ; RCVRPT: MOV CH,10 ;SET RETRY COUNT TO 10 CALL RECV JC RCVSERR CMP AL,SOH ;START OF HEADER JZ RCVSOH ;GET IT OR AL,AL JZ RCVRPT CMP AL,EOT ;END OF TRANSMISSION STC ;INDICATE EOT JNZ RCVSERR JMP DORET ;YES, END OF TRANSMISSION ; RCVSERR: MOV CH,1 CALL RECV JNC RCVSERR ; MOV AL,NAK ;NAK THE BAD FRAME CALL SEND MOV AL,ERRCT INC AL MOV ERRCT,AL ;SAVE IT BACK ; CMP AL,ERRLIM ;ERROR LIMIT REACHED ? JC RCVRPT ; ; ABORT THE RECEIVE ; RCVSABT: CALL CLOSEFIL ;SAVE WHATEVER WE GOT MOV DX,OFFSET MSG6 ;UNABLE TO RECEIVE BLOCK CALL PSTRING JMP EXIT ; RCVSOH: MOV CH,1 ;TIME OUT = 1 MSEC CALL RECV ;GET A CHAR JC RCVSERR ; MOV DL,AL MOV CH,1 CALL RECV JC RCVSERR ; NOT AL CMP AL,DL JZ RCVDATA JMP RCVSERR ; RCVDATA: MOV AL,DL MOV RCVSNO,AL MOV CL,0 MOV DI,80H ; RCVCHR: MOV CH,1 ;TIME OUT OF 1 MSEC CALL RECV JC RCVSERR ; MOV BYTE PTR[DI],AL ;SAVE THE CHARACTER INC DI ;ADVANCE POINTER CMP DI,0100H ;END OF BUFFER ? JNZ RCVCHR ;CONTINUE UNTIL BUFFER FULL ; MOV DL,CL ;SAVE CHECK SUM MOV CH,1 ;SET TIME OUT TO 1 MSEC CALL RECV JC RCVSERR CMP AL,DL JNZ RCVSERR ; MOV AL,RCVSNO MOV BL,AL MOV AL,SECTNO CMP BL,AL JZ RECVACK INC AL CMP BL,AL JZ RCV0 JMP EXIT ; RCV0: RET ; ; RECVACK: CALL SENDACK JMP RCVSECT ; SENDACK: MOV AL,ACK SEND: PUSH AX ;SAVE OUTPUT CHAR ADD AL,CL MOV CL,AL ; SENDW: MOV DX,MODCTLP IN AL,DX TEST AL,20H JZ SENDW POP AX ;RESTORE OUTPUT CHAR MOV DX,MODDATP OUT DX,AL RET ; INCRSNO: MOV AL,SECTNO INC AL MOV SECTNO,AL RET ; MAKEFIL: MOV DX,OFFSET FCB MOV CL,22 CALL BDOS INC AL JZ DIRFULL JMP DORET ; DIRFULL: MOV DX,OFFSET MSG8 CALL PSTRING ;DIRCETORY FULL JMP EXIT ; CLOSEFIL: MOV DX,OFFSET FCB MOV CL,16 CALL BDOS INC AL JZ NOCLOSE JMP DORET ; NOCLOSE: MOV DX,OFFSET MSG9 ;CAN'T CLOSE FILE CALL PSTRING JMP EXIT ; WRSECT: MOV DI,SECPTR MOV SI,80H CALL MOVE128 ;COPY TO DISK BUFFER MOV SECPTR,DI ;SAVE NEW POINTER ; MOV AL,SECINBF INC AL MOV SECINBF,AL CMP AL,16 JZ WRBLOCK JMP DORET ; ; OUTPUT BUFFER TO DISK ; WRBLOCK: MOV AL,SECINBF ;GET SECTOR COUNTER OR AL,AL JNZ WR0 JMP DORET ; WR0: MOV CL,AL ;CL = WRITE COUNTER MOV DX,OFFSET DBUF ; DKWRLP: PUSH DX PUSH BX PUSH CX ;SAVE REGISTERS ; MOV CL,26 CALL BDOS ; STI ;ENABLE INTERRUPTS MOV DX,OFFSET FCB MOV CL,21 CALL BDOS CLI ;DISABLE INTERRUPTS ; POP CX POP BX POP DX OR AL,AL ;TEST DISK WRITE STATUS JNZ WRERR ;DISK WRITE ERROR ; ADD DX,80H ;ADVANCE DMA POINTER DEC CL JNZ DKWRLP ;CONTINUE WRITTING ; MOV SECINBF,0 MOV DX,OFFSET DBUF MOV SECPTR,DX ; RSDMA: MOV DX,80H MOV CL,26 CALL BDOS RET ; WRERR: CALL RSDMA MOV DX,OFFSET MSG10 CALL PSTRING ;ERROR IN WRITTING FILE JMP EXIT ; ; RECV ; UPON ENTRY ; CH = # OF MSEC BEFORE TIME OUT ; ; UPON EXIT ; CL = UPDATED CHECKSUM ; RECV: PUSH DX PUSH BX MSEC: MOV BX,50000 MWTI: MOV DX,MODCTLP IN AL,DX TEST AL,01H JNZ MCHAR DEC BL JNZ MWTI DEC BH JNZ MWTI DEC CH JNZ MSEC POP BX POP DX STC RET ; MCHAR: MOV DX,MODDATP IN AL,DX ADD CL,AL ;UPDATE CHECKSUM OR AL,AL POP BX POP DX RET ; MOVE128: PUSH BX MOV BL,128 MOVE: MOV AL,BYTE PTR [SI] MOV BYTE PTR [DI],AL INC SI INC DI DEC BL JNZ MOVE POP BX RET ; EXIT: STI MOV CL,0 CALL BDOS ; PSTRING: MOV CL,9 CALL BDOS RET ; KEYIN: PUSH BX PUSH DX MOV CL,CONINP CALL BDOS POP DX POP BX RET ; COUT: PUSH BX PUSH DX MOV DL,AL MOV CL,CONOUT CALL BDOS POP DX POP BX RET ; STAT: PUSH BX PUSH DX MOV CL,CSTAT CALL BDOS OR AL,AL POP DX POP BX RET ; DORET: RET ; BDOS: INT 224 RET ; ; DATA AREA ; DSEG ORG 5CH FCB RB 35 ;FILE CONTROL BLOCK BUFF RB 128 ;DISK WRITE BUFFER ; DW 0 ;ALIGN TO WORD BOUNDARY ; RCVSNO DB 0 ;RECEIVED SECTOR NUMBER SECTNO DB 0 ;CURRENT SECTOR NUMBER ERRCT DB 0 ;ERROR COUNT SECPTR DW DBUF ;DISK BUFFER POINTER SECINBF DB 0 ;# OF SECTORS IN DISK BUFFER ; DBUF RS 4096 ;DISK BUFFER DW 0 ; ; MESSAGES ; MSG1 DB CR,LF,'MBOOT FOR THE IBM-PC',CR,LF DB 'Version 1.00',CR,LF,'$' MSG2 DB CR,LF,'No file name specified',CR,LF,'$' MSG3 DB CR,LF,'Terminal mode',CR,LF,LF,'$' MSG4 DB CR,LF,'File open, ready to receive',CR,LF,'$' MSG5 DB CR,LF,'Transfer complete',CR,LF,'$' MSG6 DB CR,LF,'Unable to receive block',CR,LF,'$' MSG8 DB CR,LF,'Directory full',CR,LF,'$' MSG9 DB CR,LF,'Cannot close file',CR,LF,'$' MSG10 DB CR,LF,'Error in writting file',CR,LF,'$' ; END