nam Kermit68K ttl Low-level protocol subroutines module * Kermit68K: source file K68PT2 * * Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet), * Bologna University, Physics Department, July 1987. * * All rights reserved to Bologna University, Italy. * * Permission is granted to any individual or institution * to use, copy, or redistribute this software so long as * it is not sold for profit, provided this copyright * notice is retained. * * Modification History: * * Version Date Who Comments * * 1.0.00 870701 Roberto Bagnara First official release use DefsFile Edition equ 0 psect K68ProtoFuncs2,0,0,Edition,0,0 ******************************* TrnsInit ******************************ok * * * Initialize a transaction. * * * * Entry conditions : none * * * * Exit conditions : none * * * *********************************************************************** TrnsInit: MOVE.B #1,BlChkUs(A6) Reset block check type to 1 SF Bit8Flag(A6) Reset 8th bit quoting stuff MOVE.B #1,NextPckN(A6) Reset packet counters MOVE.B #0,PackNum(A6) MOVE.B #-1,PrevPckN(A6) SF MStrFlag(A6) Reset memory string flag CLR.L MStrgPnt(A6) Reset memory string pointer SF CtlXSeen(A6) Reset interrupts flag SF CtlZSeen(A6) CLR.B SendBuf(A6) Clear send buffer CLR.B FilName(A6) Clear current file name MOVE.B RtryInit(A6),Retry(A6) Initialize the retry limit CLR.L ChrsSent(A6) Clear the statistic variables CLR.L ChrsRecd(A6) CLR.L DChsSent(A6) CLR.L DChsRecd(A6) CLR.L PcksSent(A6) CLR.L PcksRecd(A6) CLR.L NAKsSent(A6) CLR.L NAKsRecd(A6) RTS *********************************** SetGCmd ***************************ok * * * Setup for generic commands. * * * * Entry conditions : D0.B command type * * A0.L destroyed * * A1.L destroyed * * A2.L first argument address, if any * * A3.L second argument address, if any * * A4.L third argument address, if any * * * * Exit conditions : D0.L destroyed * * * *********************************************************************** SetGCmd: LEA CmdBuf(A6),A1 Load pointer to command buffer MOVE.B D0,(A1)+ Write command type CLR.B (A1) Terminate it MOVE.L A2,D0 First argument pointer null ? BEQ.S SetGCmd1 Yes, exit TST.B (A2) No, first argument null ? BEQ.S SetGCmd1 Yes, exit MOVEA.L A2,A0 Load pointer to first argument BSR CpStrLn Copy it to data buffer MOVE.L A3,D0 Second argument pointer null ? BEQ.S SetGCmd1 Yes, exit TST.B (A3) No, second argument null ? BEQ.S SetGCmd1 Yes, exit MOVEA.L A3,A0 Load pointer to second argument BSR CpStrLn Copy it to data buffer MOVE.L A4,D0 Third argument pointer null ? BEQ.S SetGCmd1 Yes, exit TST.B (A4) No, third argument null ? BEQ.S SetGCmd1 Yes, exit MOVEA.L A4,A0 Load pointer to third argument BSR CpStrLn Copy it to data buffer SetGCmd1 MOVE.B #'G',ServrCmd(A6) Generic command packet type BSR TrnsInit Initialize the transaction RTS ********************************* Decode ******************************ok * * * Kermit packet decoding procedure, decodes from DataBuf and call an * * output function at the given address. * * * * Entry conditions : A0.L address of the output function * * * * Exit conditions : D0.B completion code * * * *********************************************************************** Decode: MOVEM.L A1/D1-D3,-(A7) Save working registers LEA DataBuf(A6),A1 Pointer to data buffer Decode1 MOVEQ #1,D3 Setup the repeat counter MOVE.B (A1)+,D0 Get a character BEQ.S Decode9 Exit at end of buffer TST.B ReptFlag(A6) Repeat processing ? BEQ.S Decode2 No CMP.B ReptQuot(A6),D0 Yes, got a repeat prefix ? BNE.S Decode2 No MOVE.B (A1)+,D3 Yes, get the repeat count SUBI.B #32,D3 Convert it ... MOVE.B (A1)+,D0 ... and get the prefixed character Decode2 MOVEQ #$00,D1 Clear the 8th bit register TST.B Bit8Flag(A6) 8th bit prefixing ? BEQ.S Decode3 No CMP.B Bit8Quot(A6),D0 Yes, got an 8th bit prefix ? BNE.S Decode3 No MOVEQ #$80,D1 Yes, remember this ... MOVE.B (A1)+,D0 ... and get the prefixed character Decode3 CMP.B ICtlQuot(A6),D0 Got a control prefix ? BNE.S Decode6 No MOVE.B (A1)+,D0 Yes, get its operand MOVE.B D0,D2 Make a copy ANDI.B #$7F,D2 Only look at lower 7 bits CMPI.B #$40,D2 Above Null ? BLT.S Decode4 No, look for Delete CMPI.B #$5F,D2 Yes, between Null and US ? BLE.S Decode5 Yes, uncontrollify Decode4 CMPI.B #'?',D2 Delete ? BNE.S Decode6 No, character not in control range Decode5 EORI.B #64,D0 Uncontrollify Decode6 OR.B D1,D0 OR in the 8th bit TST.B Binary(A6) Are we in binary mode ? BNE.S Decode8 Yes, CRLF-nl mapping not needed CMPI.B #Asc_CR,D0 Carriage Return ? BEQ.S Decode1 Yes, discard it CMPI.B #Asc_LF,D0 No, Line Feed ? BNE.S Decode8 No MOVEQ #NewLinCh,D0 Yes, convert it into newline character BRA.S Decode8 Ok, ready for output Decode7 JSR (A0) Call the output function TST.B D1 Check completion code BNE.S Decode9 If failure return ADDQ.L #1,DChsRecd(A6) Increment data chars received this trans ADDQ.L #1,TDChRecd(A6) Increment total data characters received Decode8 DBF D3,Decode7 Output char repeat times (at least 1) BRA.S Decode1 Decode9 MOVEM.L (A7)+,A1/D1-D3 Restore working registers RTS ******************************** CmdBfOut *****************************ok * * * Output to command buffer, called by Decode. * * * * Entry conditions : D0.B character to output * * * * Exit conditions : D1.B AllOk completion code (0) * * * *********************************************************************** CmdBfOut: MOVE.L A0,-(A7) Save register LEA CmdBuf(A6),A0 Point to command buffer start address CLR.W D1 Clear the index register MOVE.B CmdBfPnt(A6),D1 Load relative pointer to command buffer MOVE.B D0,(A0,D1.W) Write the character ADDQ.B #1,D1 Increment the index register CLR.B (A0,D1.W) Make sure buffer is null-terminated MOVE.B D1,CmdBfPnt(A6) Save the index register MOVEQ #AllOk,D1 Return a positive competion code (0) MOVE.L (A7)+,A0 Restore register RTS ********************************* Encode ******************************ok * * * Kermit packet encoding procedure, encodes to DataBuf. * * * * Entry conditions : D0.B character to be encoded * * D2.W current size of output data packet * * * * Exit conditions : D2.W current size of output data packet * * D1.L destroyed * * D3.B destroyed * * A1.L destroyed * * * *********************************************************************** Encode: LEA DataBuf(A6),A1 Pointer to data buffer TST.B ReptFlag(A6) Repeat processing ? BEQ.S Encode5 No, do prefixing CMP.B Next(A6),D0 Current and next character are equal ? BNE.S Encode4 No TST.B First(A6) Input in progress BNE.S Encode4 No, first time called ADDQ.B #1,ReptCnt(A6) Increment the repeat counter CMPI.B #94,ReptCnt(A6) Below max ? BEQ.S Encode2 No, max reached, must dump RTS Yes, just count and return Encode1 ADDQ.B #1,ReptCnt(A6) More than 2 character to repeat Encode2 MOVE.B ReptQuot(A6),(A1,D2.W) Write the repeat quote ADDQ.W #1,D2 Increment the pointer register MOVE.B ReptCnt(A6),D1 Get the repeat count ADDI.B #32,D1 Convert it into a character MOVE.B D1,(A1,D2.W) Write the repeat count ADDQ.W #1,D2 Increment the pointer register Encode3 CLR.B ReptCnt(A6) Reset the repeat counter BRA.S Encode5 Done repeat processing, do prefixing Encode4 CMPI.B #1,ReptCnt(A6) Run broken, only 2 ? BLT.S Encode5 No, only 1, do it BGT.S Encode1 No, more than 2 MOVE.B D0,D3 Yes, do the character twice, save char BSR.S Encode5 Do it the first time MOVE.B D3,D0 Restore the character CMP.B OMPckSiz(A6),D2 Max packet size exceded ? BGT.S Encode3 Yes, do the character again MOVE.B D2,OldSize(A6) No, update OldSize BRA.S Encode3 Do the character again Encode5 MOVEQ #$7F,D1 Isolate ASCII part AND.B D0,D1 BTST #7,D0 Do 8th bit prefixing if necessary BEQ.S Encode6 TST.B Bit8Flag(A6) BEQ.S Encode6 MOVE.B Bit8Quot(A6),(A1,D2.W) Write the 8th bit quote ADDQ.W #1,D2 Increment the pointer register MOVE.B D1,D0 Encode6 CMPI.B #' ',D1 Do control prefixing if necessary BLT.S Encode7 CMPI.B #Asc_Del,D1 Delete ? BNE.S Encode8 No, character not in control range Encode7 EORI.B #64,D0 Uncotrollify BRA.S Encode10 Encode8 CMPI.B #MyCtlQot,D1 Prefix the control prefix BEQ.S Encode10 CMP.B ReptQuot(A6),D1 If it's the repeat prefix ... BNE.S Encode9 TST.B ReptFlag(A6) ... quote it if doing repeat counts BEQ.S Encode11 BRA.S Encode10 Encode9 CMP.B Bit8Quot(A6),D1 Prefix the 8th bit prefix ... BNE.S Encode11 TST.B Bit8Flag(A6) ... if doing 8th-bit prefixes BEQ.S Encode11 Encode10 MOVE.B #MyCtlQot,(A1,D2.W) Write the control quote ADDQ.W #1,D2 Increment the pointer register Encode11 MOVE.B D0,(A1,D2.W) Finally, insert the character ADDQ.W #1,D2 Increment the pointer register CLR.B (A1,D2.W) Mark the end RTS ********************************* SndParm *****************************ok * * * Fill the data buffer with my send-init parameters. * * * * Entry conditions : none * * * * Exit conditions : D0.L data length * * D1.L destroyed * * A0.L destroyed * * * *********************************************************************** SndParm: LEA DataBuf(A6),A0 Pointer to send buffer MOVEQ #32,D1 Load register for quick addition MOVE.B IMPckSiz(A6),D0 Biggest packet I can receive ADD.B D1,D0 Conversion into a printable character MOVE.B D0,(A0)+ Put it into data buffer MOVE.B OTimInt(A6),D0 When I want to be timed out ADD.B D1,D0 Conversion into a printable character MOVE.B D0,(A0)+ Put it into data buffer MOVE.B IPadNumb(A6),D0 How much padding I need ADD.B D1,D0 Conversion into a printable character MOVE.B D0,(A0)+ Put it into data buffer MOVE.B IPadChar(A6),D0 Padding character I want EORI.B #64,D0 Uncontrollify it MOVE.B D0,(A0)+ Put it into data buffer MOVE.B IEOL(A6),D0 End-Of-Line character I want ADD.B D1,D0 Conversion into a printable character MOVE.B D0,(A0)+ Put it into data buffer MOVE.B OCtlQuot(A6),(A0)+ Control-Quote character I send MOVE.B Parity(A6),D0 Parity is enabled or the ... OR.B Bit8Flag(A6),D0 ... 8th bit processing flag is on ? BEQ.S SndParm1 No, no need for 8th bit quoting MOVE.B #My8BQuot,(A0)+ Send my 8th bit quote character MOVE.B Bit8Quot(A6),D0 Get quote CMPI.B #'Y',D0 If other side say YES to do ... SEQ Bit8Flag(A6) ... 8th bit quoting BEQ.S SndParm2 BSR ChkQuot If other side specify a valid quote ... MOVE.B D0,Bit8Flag(A6) ... turn the 8th bit quoting flag on BRA.S SndParm2 SndParm1 MOVE.B #'Y',(A0)+ Normally just say we're willing SndParm2 MOVE.B BlChkRq(A6),D0 Block check type ADDI.B #'0',D0 Conversion into a printable character MOVE.B D0,(A0)+ Send it MOVE.B #MyRptQot,(A0)+ Do repeat counts CLR.B (A0) Terminator MOVEQ #9,D0 Return length RTS ******************************** RdParam ******************************ok * * * Get the other host's send-init parameters. * * * * Entry conditions : none * * * * Exit conditions : D0.B destroyed * * D1.B destroyed * * D2.L destroyed * * A0.L destroyed * * * *********************************************************************** RdParam: LEA DataBuf(A6),A0 Pointer to data buffer MOVEQ #32,D2 Load register for quick subtraction MOVE.B #DefMxPSz,OMPckSiz(A6) Maximum send packet size MOVE.B #DefTmOut,ITimInt(A6) When I should time out MOVE.B #DefPadNm,OPadNumb(A6) Number of pads to send MOVE.B #DefPadCr,OPadChar(A6) Padding character to send MOVE.B #DefEOL,OEOL(A6) EOL character I must send MOVE.B #DefCtlQt,ICtlQuot(A6) Incoming data quote character MOVE.B Bit8Flag(A6),D1 Save 8th bit processing flag SF Bit8Flag(A6) No 8th bit quoting by default MOVE.B #1,BlChkRq(A6) Block check type requested SF ReptFlag(A6) No repeat processing by default MOVE.B (A0)+,D0 Maximum send packet size BEQ RdParam9 SUB.B D2,D0 TST.B SndPSFlg(A6) Override privilege ? BEQ.S RdParam1 No, continue CMPI.B #10,D0 Yes, less than 10 ? BLT.S RdParam2 Yes, leave unchanged the default value RdParam1 MOVE.B D0,OMPckSiz(A6) No, update RdParam2 MOVE.B (A0)+,D0 When I should time out BEQ RdParam9 SUB.B D2,D0 TST.B TimInFlg(A6) Override privilege ? BEQ.S RdParam3 No, continue TST.B D0 Yes, less than 0 ? BLT.S RdParam4 Yes, leave unchanged the default value RdParam3 MOVE.B D0,ITimInt(A6) No, update RdParam4 MOVE.B (A0)+,D0 Number of pads to send BEQ RdParam9 SUB.B D2,D0 MOVE.B D0,OPadNumb(A6) MOVE.B (A0)+,D0 Padding character to send BEQ.S RdParam9 EORI.B #64,D0 MOVE.B D0,OPadChar(A6) MOVE.B (A0)+,D0 EOL character I must send BEQ.S RdParam9 SUB.B D2,D0 CMPI.B #Asc_STx,D0 Valid range EOL character ? BCS.S RdParam5 No, leave unchanged the default value CMPI.B #Asc_US,D0 Valid range EOL character ? BHI.S RdParam5 No, leave unchanged the default value MOVE.B D0,OEOL(A6) RdParam5 MOVE.B (A0)+,D0 Incoming data quote character BEQ.S RdParam9 MOVE.B D0,ICtlQuot(A6) MOVE.B (A0)+,D0 8th bit quote character BEQ.S RdParam9 MOVE.B D0,Bit8Quot(A6) CMPI.B #'Y',D0 If flag off, then turn it on ... BNE.S RdParam6 ... if other side has asked us to OR.B Parity(A6),D1 ... or if we need it on BEQ.S RdParam7 ST Bit8Flag(A6) MOVE.B #My8BQuot,Bit8Quot(A6) BRA.S RdParam7 RdParam6 BSR ChkQuot MOVE.B D0,Bit8Flag(A6) RdParam7 MOVE.B (A0)+,D0 Block check type BEQ.S RdParam9 SUBI.B #'0',D0 Range adjust CMPI.B #1,D0 Less than 1 ? BCS.S RdParam8 Yes, invalid CMPI.B #3,D0 Greater than 3 ? BHI.S RdParam8 Yes, invalid MOVE.B D0,BlChkRq(A6) Ok, store block check type requested RdParam8 MOVE.B (A0)+,D0 Repeat prefix BEQ.S RdParam9 MOVE.B D0,ReptQuot(A6) BSR ChkQuot MOVE.B D0,ReptFlag(A6) RdParam9 RTS ******************************** Check1 *******************************ok * * * Perform a type 1 block check. * * * * Entry conditions : A0.L pointer to string buffer * * * * Exit conditions : D0.B type 1 block check * * * *********************************************************************** Check1: MOVE.W D1,-(A7) Save working register BSR Check2 Compute numeric sum MOVE.W D0,D1 Compute a type 1 checksum ANDI.W #192,D1 LSR.W #6,D1 ADD.W D1,D0 ANDI.W #63,D0 MOVE.W (A7)+,D1 Restore working register RTS ******************************** Check2 *******************************ok * * * Perform a type 2 block check. * * * * Entry conditions : A0.L pointer to string buffer * * * * Exit conditions : D0.W type 2 block check (numeric sum). * * * *********************************************************************** Check2: MOVE.W D1,-(A7) Save working register CLR.W D1 Clear the sum register CLR.W D0 Check21 MOVE.B (A0)+,D0 Get a character BEQ.S Check22 Exit if EOL BSR HndlPar Handle parity ADD.W D0,D1 Sum BRA.S Check21 Repeat until EOL Check22 MOVE.W D1,D0 Return numeric sum MOVE.W (A7)+,D1 Restore working register RTS ******************************** Check3 *******************************ok * * * Perform a type 3 block check, calculates the 16-bit CRC using a * * byte oriented tableless algorithm invented by Andy Lowry from * * Columbia University. The magic number $1081 is derived from the * * CRC-CCITT polynomial x^16+x^12+x^5+1. * * * * Entry conditions : A0.L pointer to string buffer * * * * Exit conditions : D0.L type 3 block check (CRC-CCITT). * * * *********************************************************************** Check3: MOVEM.L D1-D3,-(A7) Save working registers CLR.L D1 Clear character register CLR.L D2 Clear CRC register Check31 MOVE.B (A0)+,D0 Get a character BEQ.S Check32 Null, end of string buffer BSR HndlPar Remove parity bit if necessary MOVE.B D0,D1 Load the character register MOVE.L D1,D3 Low order nibble EOR.L D2,D3 MOVEQ #$0F,D0 AND.L D0,D3 ASR.L #4,D2 MULU #$1081,D3 EOR.L D3,D2 MOVE.L D1,D3 High order nibble LSR.L #4,D3 EOR.L D2,D3 MOVEQ #$0F,D0 AND.L D0,D3 ASR.L #4,D2 MULU #$1081,D3 EOR.L D3,D2 BRA.S Check31 Repeat until end of string buffer Check32 MOVE.L D2,D0 Return CRC-CCITT MOVEM.L (A7)+,D1-D3 Restore working registers RTS ******************************** BumpPckN *****************************ok * * * Bump packet counters. * * * * Entry conditions : none * * * * Exit conditions : none * * * *********************************************************************** BumpPckN: MOVE.B PackNum(A6),PrevPckN(A6) Save previous packet number MOVE.B NextPckN(A6),PackNum(A6) Update current packet number ADDQ.B #1,NextPckN(A6) Increment next packet number ANDI.B #63,NextPckN(A6) Modulo 64 RTS *********************************** CpStrLn ***************************ok * * * Copy a null terminated string to a buffer adding a leading * * encoded character count. * * * * Entry conditions : A0.L source string buffer address * * A1.L target buffer address * * * * Exit conditions : A1.L target buffer next char address * * D0.L destroyed * * D1.B destroyed * * * *********************************************************************** CpStrLn: MOVEQ #0,D0 Preset the counter/index register CpStrLn1 MOVE.B (A0)+,1(A1,D0.W) Move a character BEQ.S CpStrLn2 Exit on end of string ADDQ.W #1,D0 Increment the counter/index register BRA.S CpStrLn1 Loop for all characters CpStrLn2 MOVE.B D0,D1 Get the length BEQ.S CpStrLn3 Return if source was null ADDI.B #32,D1 Encode length MOVE.B D1,(A1) Write it on the first target buffer byte LEA 1(A1,D0.W),A1 Address of next available buffer byte CpStrLn3 RTS ******************************** ChkQuot ******************************ok * * * Check if a character is a valid quote. * * * * Entry conditions : D0.B character to check * * * * Exit conditions : D0.B completion code * * * *********************************************************************** ChkQuot CMPI.B #'!',D0 BCS.S ChkQuot2 CMPI.B #'>',D0 BLS.S ChkQuot1 CMPI.B #'`',D0 BCS.S ChkQuot2 CMPI.B #$7E,D0 ChkQuot1 SLS D0 RTS ChkQuot2 SF D0 RTS ends END